From fe3f0f26e43ed7e01e0207119f11d24d16cd5540 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sat, 29 Jan 2022 13:22:03 +0300 Subject: [PATCH] [UI] Image post-processing and full presentation/window rework [GPU] Add FXAA post-processing [UI] Add FidelityFX FSR and CAS post-processing [UI] Add blue noise dithering from 10bpc to 8bpc [GPU] Apply the DC PWL gamma ramp closer to the spec, supporting fully white color [UI] Allow the GPU CP thread to present on the host directly, bypassing the UI thread OS paint event [UI] Allow variable refresh rate (or tearing) [UI] Present the newest frame (restart) on DXGI [UI] Replace GraphicsContext with a far more advanced Presenter with more coherent surface connection and UI overlay state management [UI] Connect presentation to windows via the Surface class, not native window handles [Vulkan] Switch to simpler Vulkan setup with no instance/device separation due to interdependencies and to pass fewer objects around [Vulkan] Lower the minimum required Vulkan version to 1.0 [UI/GPU] Various cleanup, mainly ComPtr usage [UI] Support per-monitor DPI awareness v2 on Windows [UI] DPI-scale Dear ImGui [UI] Replace the remaining non-detachable window delegates with unified window event and input listeners [UI] Allow listeners to safely destroy or close the window, and to register/unregister listeners without use-after-free and the ABA problem [UI] Explicit Z ordering of input listeners and UI overlays, top-down for input, bottom-up for drawing [UI] Add explicit window lifecycle phases [UI] Replace Window virtual functions with explicit desired state, its application, actual state, its feedback [UI] GTK: Apply the initial size to the drawing area [UI] Limit internal UI frame rate to that of the monitor [UI] Hide the cursor using a timer instead of polling due to no repeated UI thread paints with GPU CP thread presentation, and only within the window --- .gitmodules | 6 + src/xenia/app/emulator_window.cc | 740 +- src/xenia/app/emulator_window.h | 107 +- src/xenia/app/xenia_main.cc | 68 +- src/xenia/base/cvar.h | 38 +- src/xenia/base/filesystem.h | 6 +- src/xenia/base/filesystem_posix.cc | 4 +- src/xenia/base/filesystem_win.cc | 4 +- src/xenia/base/main_win.cc | 80 +- src/xenia/base/math.h | 7 +- src/xenia/base/profiling.cc | 274 +- src/xenia/base/profiling.h | 69 +- src/xenia/config.cc | 4 + src/xenia/config.h | 1 + src/xenia/debug/ui/debug_window.cc | 76 +- src/xenia/debug/ui/debug_window.h | 26 +- src/xenia/emulator.cc | 100 +- src/xenia/emulator.h | 59 +- src/xenia/gpu/command_processor.cc | 86 +- src/xenia/gpu/command_processor.h | 82 +- .../gpu/d3d12/d3d12_command_processor.cc | 1026 +- src/xenia/gpu/d3d12/d3d12_command_processor.h | 111 +- src/xenia/gpu/d3d12/d3d12_graphics_system.cc | 265 +- src/xenia/gpu/d3d12/d3d12_graphics_system.h | 31 +- .../gpu/d3d12/d3d12_primitive_processor.cc | 4 +- .../gpu/d3d12/d3d12_render_target_cache.cc | 32 +- src/xenia/gpu/d3d12/d3d12_shared_memory.cc | 29 +- src/xenia/gpu/d3d12/pipeline_cache.cc | 15 +- src/xenia/gpu/d3d12/texture_cache.cc | 41 +- src/xenia/gpu/draw_util.cc | 159 +- src/xenia/gpu/draw_util.h | 9 - src/xenia/gpu/graphics_system.cc | 107 +- src/xenia/gpu/graphics_system.h | 26 +- src/xenia/gpu/null/null_command_processor.cc | 6 +- src/xenia/gpu/null/null_command_processor.h | 4 +- src/xenia/gpu/null/null_graphics_system.cc | 21 +- src/xenia/gpu/null/null_graphics_system.h | 6 +- src/xenia/gpu/premake5.lua | 1 + src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl | 2 + src/xenia/gpu/shaders/apply_gamma_pwl.hlsli | 41 + .../shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl | 5 + .../gpu/shaders/apply_gamma_table.cs.hlsl | 2 + src/xenia/gpu/shaders/apply_gamma_table.hlsli | 23 + .../apply_gamma_table_fxaa_luma.cs.hlsl | 5 + src/xenia/gpu/shaders/bytecode/.clang-format | 1 + .../bytecode/d3d12_5_1/adaptive_quad_hs.h | 10 +- .../bytecode/d3d12_5_1/adaptive_triangle_hs.h | 10 +- .../bytecode/d3d12_5_1/apply_gamma_pwl_cs.h | 409 + .../d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h | 413 + .../bytecode/d3d12_5_1/apply_gamma_table_cs.h | 281 + .../apply_gamma_table_fxaa_luma_cs.h | 284 + .../bytecode/d3d12_5_1/clear_uint2_ps.h | 10 +- .../bytecode/d3d12_5_1/continuous_quad_hs.h | 10 +- .../d3d12_5_1/continuous_triangle_hs.h | 10 +- .../bytecode/d3d12_5_1/discrete_quad_hs.h | 10 +- .../bytecode/d3d12_5_1/discrete_triangle_hs.h | 10 +- .../bytecode/d3d12_5_1/float24_round_ps.h | 10 +- .../bytecode/d3d12_5_1/float24_truncate_ps.h | 10 +- .../bytecode/d3d12_5_1/fullscreen_tc_vs.h | 166 - .../bytecode/d3d12_5_1/fullscreen_vs.h | 10 +- .../gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h | 1270 + .../bytecode/d3d12_5_1/fxaa_extreme_cs.h | 1956 ++ .../d3d12_5_1/host_depth_store_1xmsaa_cs.h | 10 +- .../d3d12_5_1/host_depth_store_2xmsaa_cs.h | 10 +- .../d3d12_5_1/host_depth_store_4xmsaa_cs.h | 10 +- .../d3d12_5_1/passthrough_position_xy_vs.h | 10 +- .../d3d12_5_1/primitive_point_list_gs.h | 10 +- .../d3d12_5_1/primitive_quad_list_gs.h | 10 +- .../d3d12_5_1/primitive_rectangle_list_gs.h | 10 +- .../d3d12_5_1/resolve_clear_32bpp_cs.h | 10 +- .../d3d12_5_1/resolve_clear_32bpp_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_clear_64bpp_cs.h | 10 +- .../d3d12_5_1/resolve_clear_64bpp_scaled_cs.h | 10 +- .../resolve_fast_32bpp_1x2xmsaa_cs.h | 10 +- .../resolve_fast_32bpp_1x2xmsaa_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h | 10 +- .../resolve_fast_32bpp_4xmsaa_scaled_cs.h | 10 +- .../resolve_fast_64bpp_1x2xmsaa_cs.h | 10 +- .../resolve_fast_64bpp_1x2xmsaa_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h | 10 +- .../resolve_fast_64bpp_4xmsaa_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_full_128bpp_cs.h | 10 +- .../d3d12_5_1/resolve_full_128bpp_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_full_16bpp_cs.h | 10 +- .../d3d12_5_1/resolve_full_16bpp_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_full_32bpp_cs.h | 10 +- .../d3d12_5_1/resolve_full_32bpp_scaled_cs.h | 10 +- .../d3d12_5_1/resolve_full_64bpp_cs.h | 10 +- .../d3d12_5_1/resolve_full_64bpp_scaled_cs.h | 10 +- .../bytecode/d3d12_5_1/resolve_full_8bpp_cs.h | 10 +- .../d3d12_5_1/resolve_full_8bpp_scaled_cs.h | 10 +- .../shaders/bytecode/d3d12_5_1/stretch_ps.h | 167 - .../d3d12_5_1/tessellation_adaptive_vs.h | 10 +- .../d3d12_5_1/tessellation_indexed_vs.h | 10 +- .../d3d12_5_1/texture_load_128bpb_cs.h | 10 +- .../d3d12_5_1/texture_load_128bpb_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_16bpb_cs.h | 10 +- .../d3d12_5_1/texture_load_16bpb_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_32bpb_cs.h | 10 +- .../d3d12_5_1/texture_load_32bpb_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_64bpb_cs.h | 10 +- .../d3d12_5_1/texture_load_64bpb_scaled_cs.h | 10 +- .../bytecode/d3d12_5_1/texture_load_8bpb_cs.h | 10 +- .../d3d12_5_1/texture_load_8bpb_scaled_cs.h | 10 +- .../bytecode/d3d12_5_1/texture_load_ctx1_cs.h | 10 +- .../d3d12_5_1/texture_load_depth_float_cs.h | 10 +- .../texture_load_depth_float_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_depth_unorm_cs.h | 10 +- .../texture_load_depth_unorm_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_dxn_rg8_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt1_rgba8_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt3_rgba8_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt3a_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt3aas1111_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt5_rgba8_cs.h | 10 +- .../d3d12_5_1/texture_load_dxt5a_r8_cs.h | 10 +- .../texture_load_r10g11b11_rgba16_cs.h | 10 +- .../texture_load_r10g11b11_rgba16_scaled_cs.h | 10 +- .../texture_load_r10g11b11_rgba16_snorm_cs.h | 10 +- ...re_load_r10g11b11_rgba16_snorm_scaled_cs.h | 10 +- .../texture_load_r11g11b10_rgba16_cs.h | 10 +- .../texture_load_r11g11b10_rgba16_scaled_cs.h | 10 +- .../texture_load_r11g11b10_rgba16_snorm_cs.h | 10 +- ...re_load_r11g11b10_rgba16_snorm_scaled_cs.h | 10 +- .../texture_load_r4g4b4a4_b4g4r4a4_cs.h | 10 +- ...texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h | 10 +- .../texture_load_r5g5b5a1_b5g5r5a1_cs.h | 10 +- ...texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h | 10 +- ...xture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h | 10 +- ...oad_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h | 10 +- .../d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h | 10 +- .../texture_load_r5g6b5_b5g6r5_scaled_cs.h | 10 +- src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl | 7 - src/xenia/gpu/shaders/fxaa.cs.hlsl | 5 + src/xenia/gpu/shaders/fxaa.hlsli | 48 + src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl | 5 + src/xenia/gpu/shaders/stretch.ps.hlsl | 8 - src/xenia/gpu/shaders/stretch_gamma.ps.hlsl | 20 - src/xenia/gpu/trace_dump.cc | 19 +- src/xenia/gpu/trace_player.cc | 22 +- src/xenia/gpu/trace_player.h | 11 +- src/xenia/gpu/trace_viewer.cc | 97 +- src/xenia/gpu/trace_viewer.h | 55 +- src/xenia/gpu/vulkan/buffer_cache.cc | 106 +- src/xenia/gpu/vulkan/buffer_cache.h | 10 +- src/xenia/gpu/vulkan/pipeline_cache.cc | 129 +- src/xenia/gpu/vulkan/pipeline_cache.h | 8 +- src/xenia/gpu/vulkan/render_cache.cc | 172 +- src/xenia/gpu/vulkan/render_cache.h | 14 +- .../gpu/vulkan/shaders/bytecode/.clang-format | 2 + .../vulkan_spirv}/dummy_frag.h | 2 +- .../bytecode/vulkan_spirv/dummy_frag.spv | Bin 0 -> 548 bytes .../vulkan_spirv}/dummy_frag.txt | 2 +- .../vulkan_spirv}/line_quad_list_geom.h | 2 +- .../vulkan_spirv/line_quad_list_geom.spv | Bin 0 -> 2144 bytes .../vulkan_spirv}/line_quad_list_geom.txt | 2 +- .../vulkan_spirv}/point_list_geom.h | 2 +- .../bytecode/vulkan_spirv/point_list_geom.spv | Bin 0 -> 2888 bytes .../vulkan_spirv}/point_list_geom.txt | 2 +- .../vulkan_spirv}/quad_list_geom.h | 2 +- .../bytecode/vulkan_spirv/quad_list_geom.spv | Bin 0 -> 1996 bytes .../vulkan_spirv}/quad_list_geom.txt | 2 +- .../vulkan_spirv}/rect_list_geom.h | 64 +- .../bytecode/vulkan_spirv/rect_list_geom.spv | Bin 0 -> 4440 bytes .../vulkan_spirv}/rect_list_geom.txt | 54 +- src/xenia/gpu/vulkan/texture_cache.cc | 141 +- src/xenia/gpu/vulkan/texture_cache.h | 11 +- src/xenia/gpu/vulkan/texture_config.h | 2 +- .../gpu/vulkan/vulkan_command_processor.cc | 692 +- .../gpu/vulkan/vulkan_command_processor.h | 40 +- .../gpu/vulkan/vulkan_graphics_system.cc | 318 +- src/xenia/gpu/vulkan/vulkan_graphics_system.h | 23 +- src/xenia/gpu/vulkan/vulkan_shader.cc | 32 +- src/xenia/gpu/vulkan/vulkan_shader.h | 10 +- .../gpu/vulkan/vulkan_trace_dump_main.cc | 27 +- .../gpu/vulkan/vulkan_trace_viewer_main.cc | 6 +- src/xenia/hid/hid_demo.cc | 220 +- src/xenia/hid/input_driver.cc | 20 - src/xenia/hid/input_driver.h | 16 +- src/xenia/hid/nop/nop_hid.cc | 5 +- src/xenia/hid/nop/nop_hid.h | 3 +- src/xenia/hid/nop/nop_input_driver.cc | 3 +- src/xenia/hid/nop/nop_input_driver.h | 4 +- src/xenia/hid/premake5.lua | 1 - src/xenia/hid/sdl/sdl_hid.cc | 5 +- src/xenia/hid/sdl/sdl_hid.h | 3 +- src/xenia/hid/sdl/sdl_input_driver.cc | 4 +- src/xenia/hid/sdl/sdl_input_driver.h | 8 +- src/xenia/hid/winkey/winkey_hid.cc | 5 +- src/xenia/hid/winkey/winkey_hid.h | 3 +- src/xenia/hid/winkey/winkey_input_driver.cc | 66 +- src/xenia/hid/winkey/winkey_input_driver.h | 28 +- src/xenia/hid/xinput/xinput_hid.cc | 5 +- src/xenia/hid/xinput/xinput_hid.h | 3 +- src/xenia/hid/xinput/xinput_input_driver.cc | 5 +- src/xenia/hid/xinput/xinput_input_driver.h | 6 +- src/xenia/kernel/util/shim_utils.h | 2 +- src/xenia/kernel/xam/xam_nui.cc | 27 +- src/xenia/kernel/xam/xam_ui.cc | 30 +- src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc | 2 +- src/xenia/ui/d3d12/d3d12_api.h | 5 +- src/xenia/ui/d3d12/d3d12_context.cc | 379 - src/xenia/ui/d3d12/d3d12_context.h | 112 - .../ui/d3d12/d3d12_descriptor_heap_pool.cc | 25 +- .../ui/d3d12/d3d12_descriptor_heap_pool.h | 7 +- src/xenia/ui/d3d12/d3d12_immediate_drawer.cc | 384 +- src/xenia/ui/d3d12/d3d12_immediate_drawer.h | 95 +- src/xenia/ui/d3d12/d3d12_presenter.cc | 1466 + src/xenia/ui/d3d12/d3d12_presenter.h | 332 + src/xenia/ui/d3d12/d3d12_provider.cc | 45 +- src/xenia/ui/d3d12/d3d12_provider.h | 28 +- .../ui/d3d12/d3d12_submission_tracker.cc | 126 + src/xenia/ui/d3d12/d3d12_submission_tracker.h | 93 + .../ui/d3d12/d3d12_upload_buffer_pool.cc | 20 +- src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h | 5 +- src/xenia/ui/file_picker.h | 4 +- src/xenia/ui/file_picker_gtk.cc | 10 +- src/xenia/ui/file_picker_win.cc | 9 +- src/xenia/ui/graphics_context.cc | 48 - src/xenia/ui/graphics_context.h | 90 - src/xenia/ui/graphics_provider.h | 16 +- src/xenia/ui/graphics_upload_buffer_pool.cc | 21 +- src/xenia/ui/graphics_upload_buffer_pool.h | 3 +- src/xenia/ui/graphics_util.cc | 63 + src/xenia/ui/graphics_util.h | 30 + src/xenia/ui/imgui_dialog.cc | 36 +- src/xenia/ui/imgui_dialog.h | 21 +- src/xenia/ui/imgui_drawer.cc | 342 +- src/xenia/ui/imgui_drawer.h | 90 +- src/xenia/ui/immediate_drawer.cc | 108 + src/xenia/ui/immediate_drawer.h | 59 +- src/xenia/ui/menu_item.cc | 6 +- src/xenia/ui/menu_item.h | 16 +- src/xenia/ui/microprofile_drawer.cc | 36 +- src/xenia/ui/microprofile_drawer.h | 21 +- src/xenia/ui/premake5.lua | 5 + src/xenia/ui/presenter.cc | 1446 + src/xenia/ui/presenter.h | 1034 + src/xenia/ui/renderdoc_api.cc | 76 + src/xenia/ui/renderdoc_api.h | 39 + src/xenia/ui/shaders/bytecode/.clang-format | 1 + .../guest_output_bilinear_dither_ps.h | 1226 + .../d3d12_5_1/guest_output_bilinear_ps.h} | 285 +- .../guest_output_ffx_cas_resample_dither_ps.h | 2227 ++ .../guest_output_ffx_cas_resample_ps.h | 1264 + .../guest_output_ffx_cas_sharpen_dither_ps.h | 1454 + .../guest_output_ffx_cas_sharpen_ps.h | 491 + .../d3d12_5_1/guest_output_ffx_fsr_easu_ps.h | 2098 ++ .../guest_output_ffx_fsr_rcas_dither_ps.h | 1457 + .../d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h | 498 + .../guest_output_triangle_strip_rect_vs.h | 220 + .../shaders/bytecode/d3d12_5_1/immediate_ps.h | 10 +- .../shaders/bytecode/d3d12_5_1/immediate_vs.h | 213 +- .../guest_output_bilinear_dither_frag.h | 592 + .../guest_output_bilinear_dither_frag.spv | Bin 0 -> 7056 bytes .../guest_output_bilinear_dither_frag.txt | 365 + .../vulkan_spirv/guest_output_bilinear_frag.h | 120 + .../guest_output_bilinear_frag.spv | Bin 0 -> 1392 bytes .../guest_output_bilinear_frag.txt | 81 + ...uest_output_ffx_cas_resample_dither_frag.h | 1216 + ...st_output_ffx_cas_resample_dither_frag.spv | Bin 0 -> 14540 bytes ...st_output_ffx_cas_resample_dither_frag.txt | 728 + .../guest_output_ffx_cas_resample_frag.h | 745 + .../guest_output_ffx_cas_resample_frag.spv | Bin 0 -> 8892 bytes .../guest_output_ffx_cas_resample_frag.txt | 445 + ...guest_output_ffx_cas_sharpen_dither_frag.h | 1212 + ...est_output_ffx_cas_sharpen_dither_frag.spv | Bin 0 -> 14492 bytes ...est_output_ffx_cas_sharpen_dither_frag.txt | 726 + .../guest_output_ffx_cas_sharpen_frag.h | 741 + .../guest_output_ffx_cas_sharpen_frag.spv | Bin 0 -> 8844 bytes .../guest_output_ffx_cas_sharpen_frag.txt | 443 + .../guest_output_ffx_fsr_easu_frag.h | 1332 + .../guest_output_ffx_fsr_easu_frag.spv | Bin 0 -> 15936 bytes .../guest_output_ffx_fsr_easu_frag.txt | 790 + .../guest_output_ffx_fsr_rcas_dither_frag.h | 817 + .../guest_output_ffx_fsr_rcas_dither_frag.spv | Bin 0 -> 9748 bytes .../guest_output_ffx_fsr_rcas_dither_frag.txt | 491 + .../guest_output_ffx_fsr_rcas_frag.h | 345 + .../guest_output_ffx_fsr_rcas_frag.spv | Bin 0 -> 4084 bytes .../guest_output_ffx_fsr_rcas_frag.txt | 207 + .../guest_output_triangle_strip_rect_vert.h | 109 + .../guest_output_triangle_strip_rect_vert.spv | Bin 0 -> 1252 bytes .../guest_output_triangle_strip_rect_vert.txt | 74 + .../bytecode/vulkan_spirv/immediate_frag.h | 71 + .../bytecode/vulkan_spirv/immediate_frag.spv | Bin 0 -> 804 bytes .../bytecode/vulkan_spirv/immediate_frag.txt | 54 + .../bytecode/vulkan_spirv/immediate_vert.h | 117 + .../bytecode/vulkan_spirv/immediate_vert.spv | Bin 0 -> 1352 bytes .../bytecode/vulkan_spirv/immediate_vert.txt | 82 + src/xenia/ui/shaders/dither_8bpc.xesli | 34 + .../ui/shaders/guest_output_bilinear.frag | 3 + .../ui/shaders/guest_output_bilinear.glsli | 38 + .../ui/shaders/guest_output_bilinear.hlsli | 31 + .../ui/shaders/guest_output_bilinear.ps.hlsl | 1 + .../shaders/guest_output_bilinear_dither.frag | 4 + .../guest_output_bilinear_dither.ps.hlsl | 2 + .../guest_output_ffx_cas_resample.frag | 3 + .../guest_output_ffx_cas_resample.glsli | 57 + .../guest_output_ffx_cas_resample.hlsli | 49 + .../guest_output_ffx_cas_resample.ps.hlsl | 1 + .../guest_output_ffx_cas_resample_dither.frag | 4 + ...est_output_ffx_cas_resample_dither.ps.hlsl | 2 + .../shaders/guest_output_ffx_cas_sharpen.frag | 3 + .../guest_output_ffx_cas_sharpen.glsli | 53 + .../guest_output_ffx_cas_sharpen.hlsli | 44 + .../guest_output_ffx_cas_sharpen.ps.hlsl | 1 + .../guest_output_ffx_cas_sharpen_dither.frag | 4 + ...uest_output_ffx_cas_sharpen_dither.ps.hlsl | 2 + .../ui/shaders/guest_output_ffx_fsr_easu.frag | 38 + .../shaders/guest_output_ffx_fsr_easu.ps.hlsl | 39 + .../ui/shaders/guest_output_ffx_fsr_rcas.frag | 3 + .../shaders/guest_output_ffx_fsr_rcas.glsli | 45 + .../shaders/guest_output_ffx_fsr_rcas.hlsli | 36 + .../shaders/guest_output_ffx_fsr_rcas.ps.hlsl | 1 + .../guest_output_ffx_fsr_rcas_dither.frag | 4 + .../guest_output_ffx_fsr_rcas_dither.ps.hlsl | 2 + .../guest_output_triangle_strip_rect.vert | 17 + .../guest_output_triangle_strip_rect.vs.hlsl | 14 + src/xenia/ui/shaders/immediate.frag | 14 + src/xenia/ui/shaders/immediate.vert | 20 + src/xenia/ui/shaders/immediate.vs.hlsl | 4 +- src/xenia/ui/shaders/noise.xesli | 47 + src/xenia/ui/shaders/xesl.xesli | 45 + src/xenia/ui/surface.h | 83 + src/xenia/ui/surface_android.cc | 34 + src/xenia/ui/surface_android.h | 37 + src/xenia/ui/surface_gnulinux.cc | 31 + src/xenia/ui/surface_gnulinux.h | 39 + src/xenia/ui/surface_win.cc | 35 + src/xenia/ui/surface_win.h | 45 + src/xenia/ui/ui_drawer.h | 38 + src/xenia/ui/ui_event.h | 65 +- src/xenia/ui/vulkan/blitter.cc | 122 +- src/xenia/ui/vulkan/blitter.h | 9 +- src/xenia/ui/vulkan/circular_buffer.cc | 86 +- src/xenia/ui/vulkan/circular_buffer.h | 7 +- src/xenia/ui/vulkan/fenced_pools.cc | 51 +- src/xenia/ui/vulkan/fenced_pools.h | 35 +- src/xenia/ui/vulkan/functions/device_1_0.inc | 15 +- .../functions/device_ext_debug_marker.inc | 5 - .../ui/vulkan/functions/instance_1_0.inc | 1 - .../functions/instance_ext_debug_report.inc | 3 - .../functions/instance_ext_debug_utils.inc | 4 + ...ce_khr_get_physical_device_properties2.inc | 4 + .../functions/instance_khr_win32_surface.inc | 1 + .../ui/vulkan/shaders/bin/blit_color_frag.spv | Bin 1000 -> 0 bytes .../ui/vulkan/shaders/bin/blit_depth_frag.spv | Bin 660 -> 0 bytes .../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 - .../ui/vulkan/shaders/bytecode/.clang-format | 2 + .../vulkan_spirv}/blit_color_frag.h | 2 +- .../bytecode/vulkan_spirv/blit_color_frag.spv | Bin 0 -> 1000 bytes .../vulkan_spirv}/blit_color_frag.txt | 2 +- .../vulkan_spirv}/blit_depth_frag.h | 2 +- .../bytecode/vulkan_spirv/blit_depth_frag.spv | Bin 0 -> 660 bytes .../vulkan_spirv}/blit_depth_frag.txt | 2 +- .../vulkan_spirv}/blit_vert.h | 2 +- .../vulkan_spirv}/blit_vert.spv | Bin 1732 -> 1732 bytes .../vulkan_spirv}/blit_vert.txt | 2 +- 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 | 43 - src/xenia/ui/vulkan/vulkan_context.cc | 206 - src/xenia/ui/vulkan/vulkan_context.h | 67 - src/xenia/ui/vulkan/vulkan_device.cc | 427 - src/xenia/ui/vulkan/vulkan_device.h | 145 - .../ui/vulkan/vulkan_immediate_drawer.cc | 1825 +- src/xenia/ui/vulkan/vulkan_immediate_drawer.h | 166 +- src/xenia/ui/vulkan/vulkan_instance.cc | 634 - src/xenia/ui/vulkan/vulkan_instance.h | 145 - src/xenia/ui/vulkan/vulkan_mem_alloc.h | 32 +- src/xenia/ui/vulkan/vulkan_presenter.cc | 2548 ++ src/xenia/ui/vulkan/vulkan_presenter.h | 518 + src/xenia/ui/vulkan/vulkan_provider.cc | 1153 +- src/xenia/ui/vulkan/vulkan_provider.h | 275 +- .../ui/vulkan/vulkan_submission_tracker.cc | 174 + .../ui/vulkan/vulkan_submission_tracker.h | 135 + src/xenia/ui/vulkan/vulkan_swap_chain.cc | 824 - src/xenia/ui/vulkan/vulkan_swap_chain.h | 106 - .../ui/vulkan/vulkan_upload_buffer_pool.cc | 199 + .../ui/vulkan/vulkan_upload_buffer_pool.h | 67 + src/xenia/ui/vulkan/vulkan_util.cc | 643 +- src/xenia/ui/vulkan/vulkan_util.h | 210 +- src/xenia/ui/vulkan/vulkan_window_demo.cc | 2 +- src/xenia/ui/window.cc | 894 +- src/xenia/ui/window.h | 804 +- src/xenia/ui/window_android.cc | 74 +- src/xenia/ui/window_android.h | 38 +- src/xenia/ui/window_demo.cc | 107 +- src/xenia/ui/window_demo.h | 37 +- src/xenia/ui/window_gtk.cc | 810 +- src/xenia/ui/window_gtk.h | 117 +- src/xenia/ui/window_listener.h | 49 +- src/xenia/ui/window_win.cc | 1650 +- src/xenia/ui/window_win.h | 170 +- src/xenia/ui/windowed_app_context_android.h | 3 +- src/xenia/ui/windowed_app_context_win.cc | 38 +- src/xenia/ui/windowed_app_context_win.h | 58 +- src/xenia/xbox.h | 3 +- third_party/.clang-format | 2 + third_party/FidelityFX-CAS | 1 + third_party/FidelityFX-FSR | 1 + third_party/fxaa/FXAA3_11.h | 2065 ++ third_party/vulkan/vk_mem_alloc.h | 22071 ++++++++++++---- third_party/vulkan/vk_platform.h | 18 +- third_party/vulkan/vulkan.h | 47 +- third_party/vulkan/vulkan_android.h | 45 +- third_party/vulkan/vulkan_beta.h | 833 + third_party/vulkan/vulkan_core.h | 8772 +++++- third_party/vulkan/vulkan_directfb.h | 54 + third_party/vulkan/vulkan_fuchsia.h | 258 + third_party/vulkan/vulkan_ggp.h | 58 + third_party/vulkan/vulkan_ios.h | 29 +- third_party/vulkan/vulkan_macos.h | 29 +- third_party/vulkan/vulkan_metal.h | 54 + third_party/vulkan/vulkan_mir.h | 65 - third_party/vulkan/vulkan_screen.h | 54 + third_party/vulkan/vulkan_vi.h | 27 +- third_party/vulkan/vulkan_wayland.h | 27 +- third_party/vulkan/vulkan_win32.h | 101 +- third_party/vulkan/vulkan_xcb.h | 27 +- third_party/vulkan/vulkan_xlib.h | 27 +- third_party/vulkan/vulkan_xlib_xrandr.h | 25 +- xenia-build | 17 +- 429 files changed, 75942 insertions(+), 18360 deletions(-) create mode 100644 src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl create mode 100644 src/xenia/gpu/shaders/apply_gamma_pwl.hlsli create mode 100644 src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl create mode 100644 src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl create mode 100644 src/xenia/gpu/shaders/apply_gamma_table.hlsli create mode 100644 src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h delete mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h create mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h delete mode 100644 src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h delete mode 100644 src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl create mode 100644 src/xenia/gpu/shaders/fxaa.cs.hlsl create mode 100644 src/xenia/gpu/shaders/fxaa.hlsli create mode 100644 src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl delete mode 100644 src/xenia/gpu/shaders/stretch.ps.hlsl delete mode 100644 src/xenia/gpu/shaders/stretch_gamma.ps.hlsl create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/.clang-format rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/dummy_frag.h (98%) create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.spv rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/dummy_frag.txt (96%) rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/line_quad_list_geom.h (99%) create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.spv rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/line_quad_list_geom.txt (99%) rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/point_list_geom.h (99%) create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/point_list_geom.spv rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/point_list_geom.txt (99%) rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/quad_list_geom.h (99%) create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.spv rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/quad_list_geom.txt (99%) rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/rect_list_geom.h (92%) create mode 100644 src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.spv rename src/xenia/gpu/vulkan/shaders/{bin => bytecode/vulkan_spirv}/rect_list_geom.txt (92%) delete mode 100644 src/xenia/hid/input_driver.cc delete mode 100644 src/xenia/ui/d3d12/d3d12_context.cc delete mode 100644 src/xenia/ui/d3d12/d3d12_context.h create mode 100644 src/xenia/ui/d3d12/d3d12_presenter.cc create mode 100644 src/xenia/ui/d3d12/d3d12_presenter.h create mode 100644 src/xenia/ui/d3d12/d3d12_submission_tracker.cc create mode 100644 src/xenia/ui/d3d12/d3d12_submission_tracker.h delete mode 100644 src/xenia/ui/graphics_context.cc delete mode 100644 src/xenia/ui/graphics_context.h create mode 100644 src/xenia/ui/graphics_util.cc create mode 100644 src/xenia/ui/graphics_util.h create mode 100644 src/xenia/ui/immediate_drawer.cc create mode 100644 src/xenia/ui/presenter.cc create mode 100644 src/xenia/ui/presenter.h create mode 100644 src/xenia/ui/renderdoc_api.cc create mode 100644 src/xenia/ui/renderdoc_api.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h rename src/xenia/{gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h => ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h} (53%) create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h create mode 100644 src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.txt create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv create mode 100644 src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt create mode 100644 src/xenia/ui/shaders/dither_8bpc.xesli create mode 100644 src/xenia/ui/shaders/guest_output_bilinear.frag create mode 100644 src/xenia/ui/shaders/guest_output_bilinear.glsli create mode 100644 src/xenia/ui/shaders/guest_output_bilinear.hlsli create mode 100644 src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_bilinear_dither.frag create mode 100644 src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag create mode 100644 src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl create mode 100644 src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert create mode 100644 src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl create mode 100644 src/xenia/ui/shaders/immediate.frag create mode 100644 src/xenia/ui/shaders/immediate.vert create mode 100644 src/xenia/ui/shaders/noise.xesli create mode 100644 src/xenia/ui/shaders/xesl.xesli create mode 100644 src/xenia/ui/surface.h create mode 100644 src/xenia/ui/surface_android.cc create mode 100644 src/xenia/ui/surface_android.h create mode 100644 src/xenia/ui/surface_gnulinux.cc create mode 100644 src/xenia/ui/surface_gnulinux.h create mode 100644 src/xenia/ui/surface_win.cc create mode 100644 src/xenia/ui/surface_win.h create mode 100644 src/xenia/ui/ui_drawer.h delete mode 100644 src/xenia/ui/vulkan/functions/device_ext_debug_marker.inc delete mode 100644 src/xenia/ui/vulkan/functions/instance_ext_debug_report.inc create mode 100644 src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc create mode 100644 src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_color_frag.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.spv 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 create mode 100644 src/xenia/ui/vulkan/shaders/bytecode/.clang-format rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_color_frag.h (99%) create mode 100644 src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_color_frag.spv rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_color_frag.txt (98%) rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_depth_frag.h (98%) create mode 100644 src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.spv rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_depth_frag.txt (97%) rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_vert.h (99%) rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_vert.spv (59%) rename src/xenia/ui/vulkan/shaders/{bin => bytecode/vulkan_spirv}/blit_vert.txt (98%) 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_context.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_context.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 create mode 100644 src/xenia/ui/vulkan/vulkan_presenter.cc create mode 100644 src/xenia/ui/vulkan/vulkan_presenter.h create mode 100644 src/xenia/ui/vulkan/vulkan_submission_tracker.cc create mode 100644 src/xenia/ui/vulkan/vulkan_submission_tracker.h delete mode 100644 src/xenia/ui/vulkan/vulkan_swap_chain.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_swap_chain.h create mode 100644 src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc create mode 100644 src/xenia/ui/vulkan/vulkan_upload_buffer_pool.h create mode 100644 third_party/.clang-format create mode 160000 third_party/FidelityFX-CAS create mode 160000 third_party/FidelityFX-FSR create mode 100644 third_party/fxaa/FXAA3_11.h create mode 100644 third_party/vulkan/vulkan_beta.h create mode 100644 third_party/vulkan/vulkan_directfb.h create mode 100644 third_party/vulkan/vulkan_fuchsia.h create mode 100644 third_party/vulkan/vulkan_ggp.h create mode 100644 third_party/vulkan/vulkan_metal.h delete mode 100644 third_party/vulkan/vulkan_mir.h create mode 100644 third_party/vulkan/vulkan_screen.h diff --git a/.gitmodules b/.gitmodules index 5809e562b..5f5ee82b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -76,3 +76,9 @@ [submodule "third_party/premake-androidndk"] path = third_party/premake-androidndk url = https://github.com/Triang3l/premake-androidndk.git +[submodule "third_party/FidelityFX-CAS"] + path = third_party/FidelityFX-CAS + url = https://github.com/GPUOpen-Effects/FidelityFX-CAS.git +[submodule "third_party/FidelityFX-FSR"] + path = third_party/FidelityFX-FSR + url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index a91574604..097d59dfb 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -2,13 +2,20 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/app/emulator_window.h" +#include +#include +#include +#include +#include +#include + #include "third_party/fmt/include/fmt/format.h" #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" @@ -20,11 +27,17 @@ #include "xenia/base/profiling.h" #include "xenia/base/system.h" #include "xenia/base/threading.h" +#include "xenia/cpu/processor.h" #include "xenia/emulator.h" +#include "xenia/gpu/command_processor.h" #include "xenia/gpu/graphics_system.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" // Autogenerated by `xb premake`. @@ -32,13 +45,91 @@ DECLARE_bool(debug); +DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.", + "Display"); + +DEFINE_string( + postprocess_antialiasing, "", + "Post-processing anti-aliasing effect to apply to the image output of the " + "game.\n" + "Using post-process anti-aliasing is heavily recommended when AMD " + "FidelityFX Contrast Adaptive Sharpening or Super Resolution 1.0 is " + "active.\n" + "Use: [none, fxaa, fxaa_extreme]\n" + " none (or any value not listed here):\n" + " Don't alter the original image.\n" + " fxaa:\n" + " NVIDIA Fast Approximate Anti-Aliasing 3.11, normal quality preset (12)." + "\n" + " fxaa_extreme:\n" + " NVIDIA Fast Approximate Anti-Aliasing 3.11, extreme quality preset " + "(39).", + "Display"); +DEFINE_string( + postprocess_scaling_and_sharpening, "", + "Post-processing effect to use for resampling and/or sharpening of the " + "final display output.\n" + "Use: [bilinear, cas, fsr]\n" + " bilinear (or any value not listed here):\n" + " Original image at 1:1, simple bilinear stretching for resampling.\n" + " cas:\n" + " Use AMD FidelityFX Contrast Adaptive Sharpening (CAS) for sharpening " + "at scaling factors of up to 2x2, with additional bilinear stretching for " + "larger factors.\n" + " fsr:\n" + " Use AMD FidelityFX Super Resolution 1.0 (FSR) for highest-quality " + "upscaling, or AMD FidelityFX Contrast Adaptive Sharpening for sharpening " + "while not scaling or downsampling.\n" + " For scaling by factors of more than 2x2, multiple FSR passes are done.", + "Display"); +DEFINE_double( + postprocess_ffx_cas_additional_sharpness, + xe::ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessDefault, + "Additional sharpness for AMD FidelityFX Contrast Adaptive Sharpening " + "(CAS), from 0 to 1.\n" + "Higher is sharper.", + "Display"); +DEFINE_uint32( + postprocess_ffx_fsr_max_upsampling_passes, + xe::ui::Presenter::GuestOutputPaintConfig::kFsrMaxUpscalingPassesMax, + "Maximum number of upsampling passes performed in AMD FidelityFX Super " + "Resolution 1.0 (FSR) before falling back to bilinear stretching after the " + "final pass.\n" + "Each pass upscales only to up to 2x2 the previous size. If the game " + "outputs a 1280x720 image, 1 pass will upscale it to up to 2560x1440 " + "(below 4K), after 2 passes it will be upscaled to a maximum of 5120x2880 " + "(including 3840x2160 for 4K), and so on.\n" + "This variable has no effect if the display resolution isn't very high, " + "but may be reduced on resolutions like 4K or 8K in case the performance " + "impact of multiple FSR upsampling passes is too high, or if softer edges " + "are desired.\n" + "The default value is the maximum internally supported by Xenia.", + "Display"); +DEFINE_double( + postprocess_ffx_fsr_sharpness_reduction, + xe::ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionDefault, + "Sharpness reduction for AMD FidelityFX Super Resolution 1.0 (FSR), in " + "stops.\n" + "Lower is sharper.", + "Display"); +// Dithering to 8bpc is enabled by default since the effect is minor, only +// effects what can't be shown normally by host displays, and nothing is changed +// by it for 8bpc source without resampling. +DEFINE_bool( + postprocess_dither, true, + "Dither the final image output from the internal precision to 8 bits per " + "channel so gradients are smoother.\n" + "On a 10bpc display, the lower 2 bits will still be kept, but noise will " + "be added to them - disabling may be recommended for 10bpc, but it " + "depends on the 10bpc displaying capabilities of the actual display used.", + "Display"); + namespace xe { namespace app { using xe::ui::FileDropEvent; using xe::ui::KeyEvent; using xe::ui::MenuItem; -using xe::ui::MouseEvent; using xe::ui::UIEvent; const std::string kBaseTitle = "Xenia"; @@ -47,7 +138,12 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator, ui::WindowedAppContext& app_context) : emulator_(emulator), app_context_(app_context), - window_(ui::Window::Create(app_context, kBaseTitle)) { + window_listener_(*this), + window_(ui::Window::Create(app_context, kBaseTitle, 1280, 720)), + imgui_drawer_( + std::make_unique(window_.get(), kZOrderImGui)), + display_config_game_config_load_callback_( + new DisplayConfigGameConfigLoadCallback(*emulator, *this)) { base_title_ = kBaseTitle + #ifdef DEBUG #if _NO_DEBUG_HEAP == 1 @@ -76,109 +172,327 @@ std::unique_ptr EmulatorWindow::Create( return emulator_window; } -bool EmulatorWindow::Initialize() { - if (!window_->Initialize()) { - XELOGE("Failed to initialize platform window"); - return false; +EmulatorWindow::~EmulatorWindow() { + // Notify the ImGui drawer that the immediate drawer is being destroyed. + ShutdownGraphicsSystemPresenterPainting(); +} + +ui::Presenter* EmulatorWindow::GetGraphicsSystemPresenter() const { + gpu::GraphicsSystem* graphics_system = emulator_->graphics_system(); + return graphics_system ? graphics_system->presenter() : nullptr; +} + +void EmulatorWindow::SetupGraphicsSystemPresenterPainting() { + ShutdownGraphicsSystemPresenterPainting(); + + if (!window_) { + return; } - UpdateTitle(); + ui::Presenter* presenter = GetGraphicsSystemPresenter(); + if (!presenter) { + return; + } - window_->on_closed.AddListener( - [this](UIEvent* e) { app_context_.QuitFromUIThread(); }); + ApplyDisplayConfigForCvars(); - window_->on_file_drop.AddListener( - [this](FileDropEvent* e) { FileDrop(e->filename()); }); + window_->SetPresenter(presenter); - window_->on_key_down.AddListener([this](KeyEvent* e) { - bool handled = true; - switch (e->virtual_key()) { - case ui::VirtualKey::kO: { - if (e->is_ctrl_pressed()) { - FileOpen(); - } - } break; - case ui::VirtualKey::kMultiply: { - CpuTimeScalarReset(); - } break; - case ui::VirtualKey::kSubtract: { - CpuTimeScalarSetHalf(); - } break; - case ui::VirtualKey::kAdd: { - CpuTimeScalarSetDouble(); - } break; + immediate_drawer_ = + emulator_->graphics_system()->provider()->CreateImmediateDrawer(); + if (immediate_drawer_) { + immediate_drawer_->SetPresenter(presenter); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter, + immediate_drawer_.get()); + Profiler::SetUserIO(kZOrderProfiler, window_.get(), presenter, + immediate_drawer_.get()); + } +} - case ui::VirtualKey::kF3: { - Profiler::ToggleDisplay(); - } break; +void EmulatorWindow::ShutdownGraphicsSystemPresenterPainting() { + Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr); + imgui_drawer_->SetPresenterAndImmediateDrawer(nullptr, nullptr); + immediate_drawer_.reset(); + if (window_) { + window_->SetPresenter(nullptr); + } +} - case ui::VirtualKey::kF4: { - GpuTraceFrame(); - } break; - case ui::VirtualKey::kF5: { - GpuClearCaches(); - } break; -#ifdef DEBUG - case ui::VirtualKey::kF7: { - // Save to file - // TODO: Choose path based on user input, or from options - // TODO: Spawn a new thread to do this. - emulator()->SaveToFile("test.sav"); - } break; - case ui::VirtualKey::kF8: { - // Restore from file - // TODO: Choose path from user - // TODO: Spawn a new thread to do this. - emulator()->RestoreFromFile("test.sav"); - } break; -#endif // #ifdef DEBUG - case ui::VirtualKey::kF11: { - ToggleFullscreen(); - } break; - case ui::VirtualKey::kEscape: { - // Allow users to escape fullscreen (but not enter it). - if (window_->is_fullscreen()) { - window_->ToggleFullscreen(false); - } else { - handled = false; - } - } break; +void EmulatorWindow::OnEmulatorInitialized() { + emulator_initialized_ = true; + window_->SetMainMenuEnabled(true); + // When the user can see that the emulator isn't initializing anymore (the + // menu isn't disabled), enter fullscreen if requested. + if (cvars::fullscreen) { + window_->SetFullscreen(true); + } +} - case ui::VirtualKey::kPause: { - CpuBreakIntoDebugger(); - } break; - case ui::VirtualKey::kCancel: { - CpuBreakIntoHostDebugger(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnClosing(ui::UIEvent& e) { + emulator_window_.app_context_.QuitFromUIThread(); +} - case ui::VirtualKey::kF1: { - ShowHelpWebsite(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnFileDrop(ui::FileDropEvent& e) { + emulator_window_.FileDrop(e.filename()); +} - case ui::VirtualKey::kF2: { - ShowCommitID(); - } break; +void EmulatorWindow::EmulatorWindowListener::OnKeyDown(ui::KeyEvent& e) { + emulator_window_.OnKeyDown(e); +} - default: { - handled = false; - } break; - } - e->set_handled(handled); - }); +void EmulatorWindow::DisplayConfigGameConfigLoadCallback::PostGameConfigLoad() { + emulator_window_.ApplyDisplayConfigForCvars(); +} - window_->on_mouse_move.AddListener([this](MouseEvent* e) { - if (window_->is_fullscreen() && (e->dx() > 2 || e->dy() > 2)) { - if (!window_->is_cursor_visible()) { - window_->set_cursor_visible(true); +void EmulatorWindow::DisplayConfigDialog::OnDraw(ImGuiIO& io) { + gpu::GraphicsSystem* graphics_system = + emulator_window_.emulator_->graphics_system(); + if (!graphics_system) { + return; + } + + // In the top-left corner so it's close to the menu bar from where it was + // opened. + // Origin Y coordinate 20 was taken from the Dear ImGui demo. + ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(20, 20), ImGuiCond_FirstUseEver); + // Alpha from Dear ImGui tooltips (0.35 from the overlay provides too low + // visibility). Translucent so some effect of the changes can still be seen + // through it. + ImGui::SetNextWindowBgAlpha(0.6f); + bool dialog_open = true; + if (!ImGui::Begin("Post-processing", &dialog_open, + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_HorizontalScrollbar)) { + ImGui::End(); + return; + } + // Even if the close button has been pressed, still paint everything not to + // have one frame with an empty window. + + gpu::CommandProcessor* command_processor = + graphics_system->command_processor(); + if (command_processor) { + if (ImGui::TreeNodeEx( + "Anti-aliasing", + ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) { + gpu::CommandProcessor::SwapPostEffect current_swap_post_effect = + command_processor->GetDesiredSwapPostEffect(); + int new_swap_post_effect_index = int(current_swap_post_effect); + ImGui::RadioButton("None", &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kNone)); + ImGui::RadioButton( + "NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), normal quality", + &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kFxaa)); + ImGui::RadioButton( + "NVIDIA Fast Approximate Anti-Aliasing 3.11 (FXAA), extreme quality", + &new_swap_post_effect_index, + int(gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme)); + gpu::CommandProcessor::SwapPostEffect new_swap_post_effect = + gpu::CommandProcessor::SwapPostEffect(new_swap_post_effect_index); + if (current_swap_post_effect != new_swap_post_effect) { + command_processor->SetDesiredSwapPostEffect(new_swap_post_effect); } - cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000; + // Override the values in the cvars to save them to the config at exit if + // the user has set them to anything new. + if (GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing) != + new_swap_post_effect) { + OVERRIDE_string(postprocess_antialiasing, + GetCvarValueForSwapPostEffect(new_swap_post_effect)); + } + + ImGui::TreePop(); + } + } + + ui::Presenter* presenter = graphics_system->presenter(); + if (presenter) { + const ui::Presenter::GuestOutputPaintConfig& current_presenter_config = + presenter->GetGuestOutputPaintConfigFromUIThread(); + ui::Presenter::GuestOutputPaintConfig new_presenter_config = + current_presenter_config; + + if (ImGui::TreeNodeEx( + "Resampling and sharpening", + ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_DefaultOpen)) { + // Filtering effect. + int new_effect_index = int(new_presenter_config.GetEffect()); + ImGui::RadioButton( + "None / bilinear", &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear)); + ImGui::RadioButton( + "AMD FidelityFX Contrast Adaptive Sharpening (CAS)", + &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kCas)); + ImGui::RadioButton( + "AMD FidelityFX Super Resolution 1.0 (FSR)", &new_effect_index, + int(ui::Presenter::GuestOutputPaintConfig::Effect::kFsr)); + new_presenter_config.SetEffect( + ui::Presenter::GuestOutputPaintConfig::Effect(new_effect_index)); + + // effect_description must be one complete, but short enough, sentence per + // line, as TextWrapped doesn't work correctly in auto-resizing windows + // (in the initial frames, the window becomes extremely tall, and widgets + // added after the wrapped text have no effect on the width of the text). + const char* effect_description = nullptr; + switch (new_presenter_config.GetEffect()) { + case ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear: + effect_description = + "Simple bilinear filtering is done if resampling is needed.\n" + "Otherwise, only anti-aliasing is done if enabled, or displaying " + "as is."; + break; + case ui::Presenter::GuestOutputPaintConfig::Effect::kCas: + effect_description = + "Sharpening and resampling to up to 2x2 to improve the fidelity " + "of details.\n" + "For scaling by more than 2x2, bilinear stretching is done " + "afterwards."; + break; + case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr: + effect_description = + "High-quality edge-preserving upscaling to arbitrary target " + "resolutions.\n" + "For scaling by more than 2x2, multiple upsampling passes are " + "done.\n" + "If not upscaling, Contrast Adaptive Sharpening (CAS) is used " + "instead."; + break; + } + if (effect_description) { + ImGui::TextUnformatted(effect_description); + } + + if (new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kCas || + new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) { + if (effect_description) { + ImGui::Spacing(); + } + + ImGui::TextUnformatted( + "FXAA is highly recommended when using CAS or FSR."); + + ImGui::Spacing(); + + // 2 decimal places is more or less enough precision for the sharpness + // given the minor visual effect of small changes, the width of the + // slider, and readability convenience (2 decimal places is like an + // integer percentage). However, because Dear ImGui parses the string + // representation of the number and snaps the value to it internally, + // 2 decimal places actually offer less precision than the slider itself + // does. This is especially prominent in the low range of the non-linear + // FSR sharpness reduction slider. 3 decimal places are optimal in this + // case. + + if (new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr) { + float fsr_sharpness_reduction = + new_presenter_config.GetFsrSharpnessReduction(); + ImGui::TextUnformatted( + "FSR sharpness reduction when upscaling (lower is sharper):"); + // Power 2.0 as the reduction is in stops, used in exp2. + ImGui::SliderFloat( + "##FSRSharpnessReduction", &fsr_sharpness_reduction, + ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMin, + ui::Presenter::GuestOutputPaintConfig::kFsrSharpnessReductionMax, + "%.3f stops", 2.0f); + ImGui::SameLine(); + if (ImGui::Button("Reset##ResetFSRSharpnessReduction")) { + fsr_sharpness_reduction = ui::Presenter::GuestOutputPaintConfig :: + kFsrSharpnessReductionDefault; + } + new_presenter_config.SetFsrSharpnessReduction( + fsr_sharpness_reduction); + } + + float cas_additional_sharpness = + new_presenter_config.GetCasAdditionalSharpness(); + ImGui::TextUnformatted( + new_presenter_config.GetEffect() == + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr + ? "CAS additional sharpness when not upscaling (higher is " + "sharper):" + : "CAS additional sharpness (higher is sharper):"); + ImGui::SliderFloat( + "##CASAdditionalSharpness", &cas_additional_sharpness, + ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMin, + ui::Presenter::GuestOutputPaintConfig::kCasAdditionalSharpnessMax, + "%.3f"); + ImGui::SameLine(); + if (ImGui::Button("Reset##ResetCASAdditionalSharpness")) { + cas_additional_sharpness = ui::Presenter::GuestOutputPaintConfig :: + kCasAdditionalSharpnessDefault; + } + new_presenter_config.SetCasAdditionalSharpness( + cas_additional_sharpness); + + // There's no need to expose the setting for the maximum number of FSR + // EASU passes as it's largely meaningless if the user doesn't have a + // very high-resolution monitor compared to the original image size as + // most of the values of the slider will have no effect, and that's just + // very fine-grained performance control for a fixed-overhead pass only + // for huge screen resolutions. + } + + ImGui::TreePop(); } - e->set_handled(false); - }); + if (ImGui::TreeNodeEx("Dithering", ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_DefaultOpen)) { + bool dither = current_presenter_config.GetDither(); + ImGui::Checkbox( + "Dither the final output to 8bpc to make gradients smoother", + &dither); + new_presenter_config.SetDither(dither); - window_->on_paint.AddListener([this](UIEvent* e) { CheckHideCursor(); }); + ImGui::TreePop(); + } + + presenter->SetGuestOutputPaintConfigFromUIThread(new_presenter_config); + + // Override the values in the cvars to save them to the config at exit if + // the user has set them to anything new. + ui::Presenter::GuestOutputPaintConfig cvars_presenter_config = + GetGuestOutputPaintConfigForCvars(); + if (cvars_presenter_config.GetEffect() != + new_presenter_config.GetEffect()) { + OVERRIDE_string(postprocess_scaling_and_sharpening, + GetCvarValueForGuestOutputPaintEffect( + new_presenter_config.GetEffect())); + } + if (cvars_presenter_config.GetCasAdditionalSharpness() != + new_presenter_config.GetCasAdditionalSharpness()) { + OVERRIDE_double(postprocess_ffx_cas_additional_sharpness, + new_presenter_config.GetCasAdditionalSharpness()); + } + if (cvars_presenter_config.GetFsrSharpnessReduction() != + new_presenter_config.GetFsrSharpnessReduction()) { + OVERRIDE_double(postprocess_ffx_fsr_sharpness_reduction, + new_presenter_config.GetFsrSharpnessReduction()); + } + if (cvars_presenter_config.GetDither() != + new_presenter_config.GetDither()) { + OVERRIDE_bool(postprocess_dither, new_presenter_config.GetDither()); + } + } + + ImGui::End(); + + if (!dialog_open) { + emulator_window_.ToggleDisplayConfigDialog(); + // `this` might have been destroyed by ToggleDisplayConfigDialog. + return; + } +} + +bool EmulatorWindow::Initialize() { + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput); // Main menu. // FIXME: This code is really messy. @@ -198,9 +512,9 @@ bool EmulatorWindow::Initialize() { MenuItem::Type::kString, "Show content directory...", std::bind(&EmulatorWindow::ShowContentDirectory, this))); file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "E&xit", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "E&xit", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); @@ -253,14 +567,20 @@ bool EmulatorWindow::Initialize() { } main_menu->AddChild(std::move(gpu_menu)); - // Window menu. - auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Window"); + // Display menu. + auto display_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Display"); { - window_menu->AddChild( + display_menu->AddChild(MenuItem::Create( + MenuItem::Type::kString, "&Post-processing settings", "F6", + std::bind(&EmulatorWindow::ToggleDisplayConfigDialog, this))); + } + display_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator)); + { + display_menu->AddChild( MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11", std::bind(&EmulatorWindow::ToggleFullscreen, this))); } - main_menu->AddChild(std::move(window_menu)); + main_menu->AddChild(std::move(display_menu)); // Help menu. auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Help"); @@ -284,16 +604,196 @@ bool EmulatorWindow::Initialize() { } main_menu->AddChild(std::move(help_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - window_->Resize(1280, 720); + window_->SetMainMenuEnabled(false); - window_->DisableMainMenu(); + UpdateTitle(); + + if (!window_->Open()) { + XELOGE("Failed to open the platform window"); + return false; + } + + Profiler::SetUserIO(kZOrderProfiler, window_.get(), nullptr, nullptr); return true; } +const char* EmulatorWindow::GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect effect) { + switch (effect) { + case gpu::CommandProcessor::SwapPostEffect::kFxaa: + return "fxaa"; + case gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme: + return "fxaa_extreme"; + default: + return ""; + } +} + +gpu::CommandProcessor::SwapPostEffect +EmulatorWindow::GetSwapPostEffectForCvarValue(const std::string& cvar_value) { + if (cvar_value == GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect::kFxaa)) { + return gpu::CommandProcessor::SwapPostEffect::kFxaa; + } + if (cvar_value == GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme)) { + return gpu::CommandProcessor::SwapPostEffect::kFxaaExtreme; + } + return gpu::CommandProcessor::SwapPostEffect::kNone; +} + +const char* EmulatorWindow::GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect effect) { + switch (effect) { + case ui::Presenter::GuestOutputPaintConfig::Effect::kCas: + return "cas"; + case ui::Presenter::GuestOutputPaintConfig::Effect::kFsr: + return "fsr"; + default: + return ""; + } +} + +ui::Presenter::GuestOutputPaintConfig::Effect +EmulatorWindow::GetGuestOutputPaintEffectForCvarValue( + const std::string& cvar_value) { + if (cvar_value == GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect::kCas)) { + return ui::Presenter::GuestOutputPaintConfig::Effect::kCas; + } + if (cvar_value == GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect::kFsr)) { + return ui::Presenter::GuestOutputPaintConfig::Effect::kFsr; + } + return ui::Presenter::GuestOutputPaintConfig::Effect::kBilinear; +} + +ui::Presenter::GuestOutputPaintConfig +EmulatorWindow::GetGuestOutputPaintConfigForCvars() { + ui::Presenter::GuestOutputPaintConfig paint_config; + paint_config.SetEffect(GetGuestOutputPaintEffectForCvarValue( + cvars::postprocess_scaling_and_sharpening)); + paint_config.SetCasAdditionalSharpness( + float(cvars::postprocess_ffx_cas_additional_sharpness)); + paint_config.SetFsrMaxUpsamplingPasses( + cvars::postprocess_ffx_fsr_max_upsampling_passes); + paint_config.SetFsrSharpnessReduction( + float(cvars::postprocess_ffx_fsr_sharpness_reduction)); + paint_config.SetDither(cvars::postprocess_dither); + return paint_config; +} + +void EmulatorWindow::ApplyDisplayConfigForCvars() { + gpu::GraphicsSystem* graphics_system = emulator_->graphics_system(); + if (!graphics_system) { + return; + } + + gpu::CommandProcessor* command_processor = + graphics_system->command_processor(); + if (command_processor) { + command_processor->SetDesiredSwapPostEffect( + GetSwapPostEffectForCvarValue(cvars::postprocess_antialiasing)); + } + + ui::Presenter* presenter = graphics_system->presenter(); + if (presenter) { + presenter->SetGuestOutputPaintConfigFromUIThread( + GetGuestOutputPaintConfigForCvars()); + } +} + +void EmulatorWindow::OnKeyDown(ui::KeyEvent& e) { + if (!emulator_initialized_) { + return; + } + + switch (e.virtual_key()) { + case ui::VirtualKey::kO: { + if (!e.is_ctrl_pressed()) { + return; + } + FileOpen(); + } break; + case ui::VirtualKey::kMultiply: { + CpuTimeScalarReset(); + } break; + case ui::VirtualKey::kSubtract: { + CpuTimeScalarSetHalf(); + } break; + case ui::VirtualKey::kAdd: { + CpuTimeScalarSetDouble(); + } break; + + case ui::VirtualKey::kF3: { + Profiler::ToggleDisplay(); + } break; + + case ui::VirtualKey::kF4: { + GpuTraceFrame(); + } break; + case ui::VirtualKey::kF5: { + GpuClearCaches(); + } break; + + case ui::VirtualKey::kF6: { + ToggleDisplayConfigDialog(); + } break; + case ui::VirtualKey::kF11: { + ToggleFullscreen(); + } break; + case ui::VirtualKey::kEscape: { + // Allow users to escape fullscreen (but not enter it). + if (!window_->IsFullscreen()) { + return; + } + SetFullscreen(false); + } break; + +#ifdef DEBUG + case ui::VirtualKey::kF7: { + // Save to file + // TODO: Choose path based on user input, or from options + // TODO: Spawn a new thread to do this. + emulator()->SaveToFile("test.sav"); + } break; + case ui::VirtualKey::kF8: { + // Restore from file + // TODO: Choose path from user + // TODO: Spawn a new thread to do this. + emulator()->RestoreFromFile("test.sav"); + } break; +#endif // #ifdef DEBUG + + case ui::VirtualKey::kPause: { + CpuBreakIntoDebugger(); + } break; + case ui::VirtualKey::kCancel: { + CpuBreakIntoHostDebugger(); + } break; + + case ui::VirtualKey::kF1: { + ShowHelpWebsite(); + } break; + + case ui::VirtualKey::kF2: { + ShowCommitID(); + } break; + + default: + return; + } + + e.set_handled(true); +} + void EmulatorWindow::FileDrop(const std::filesystem::path& filename) { + if (!emulator_initialized_) { + return; + } auto result = emulator_->LaunchPath(filename); if (XFAILED(result)) { // TODO: Display a message box. @@ -316,7 +816,7 @@ void EmulatorWindow::FileOpen() { //{"Content Package (*.xcp)", "*.xcp" }, {"All Files (*.*)", "*.*"}, }); - if (file_picker->Show(window_->native_handle())) { + if (file_picker->Show(window_.get())) { auto selected_files = file_picker->selected_files(); if (!selected_files.empty()) { path = selected_files[0]; @@ -361,17 +861,6 @@ void EmulatorWindow::ShowContentDirectory() { LaunchFileExplorer(target_path); } -void EmulatorWindow::CheckHideCursor() { - if (!window_->is_fullscreen()) { - // Only hide when fullscreen. - return; - } - - if (Clock::QueryHostSystemTime() > cursor_hide_time_) { - window_->set_cursor_visible(false); - } -} - void EmulatorWindow::CpuTimeScalarReset() { Clock::set_guest_time_scalar(1.0); UpdateTitle(); @@ -389,7 +878,7 @@ void EmulatorWindow::CpuTimeScalarSetDouble() { void EmulatorWindow::CpuBreakIntoDebugger() { if (!cvars::debug) { - xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger", + xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(), "Xenia Debugger", "Xenia must be launched with the " "--debug flag in order to enable " "debugging."); @@ -415,13 +904,26 @@ void EmulatorWindow::GpuClearCaches() { emulator()->graphics_system()->ClearCaches(); } -void EmulatorWindow::ToggleFullscreen() { - window_->ToggleFullscreen(!window_->is_fullscreen()); +void EmulatorWindow::SetFullscreen(bool fullscreen) { + if (window_->IsFullscreen() == fullscreen) { + return; + } + window_->SetFullscreen(fullscreen); + window_->SetCursorVisibility(fullscreen + ? ui::Window::CursorVisibility::kAutoHidden + : ui::Window::CursorVisibility::kVisible); +} - // Hide the cursor after a second if we're going fullscreen - cursor_hide_time_ = Clock::QueryHostSystemTime() + 30000000; - if (!window_->is_fullscreen()) { - window_->set_cursor_visible(true); +void EmulatorWindow::ToggleFullscreen() { + SetFullscreen(!window_->IsFullscreen()); +} + +void EmulatorWindow::ToggleDisplayConfigDialog() { + if (!display_config_dialog_) { + display_config_dialog_ = std::unique_ptr( + new DisplayConfigDialog(imgui_drawer_.get(), *this)); + } else { + display_config_dialog_.reset(); } } @@ -477,7 +979,7 @@ void EmulatorWindow::UpdateTitle() { sb.Append(u8" (Preloading shaders\u2026)"); } - window_->set_title(sb.to_string_view()); + window_->SetTitle(sb.to_string_view()); } void EmulatorWindow::SetInitializingShaderStorage(bool initializing) { diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 6dfb69080..ad6c4daee 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,42 +13,124 @@ #include #include +#include "xenia/emulator.h" +#include "xenia/gpu/command_processor.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" -namespace xe { -class Emulator; -} // namespace xe - namespace xe { namespace app { class EmulatorWindow { public: + enum : size_t { + // The UI is on top of the game and is open in special cases, so + // lowest-priority. + kZOrderHidInput, + kZOrderImGui, + kZOrderProfiler, + // Emulator window controls are expected to be always accessible by the + // user, so highest-priority. + kZOrderEmulatorWindowInput, + }; + + virtual ~EmulatorWindow(); + static std::unique_ptr Create( Emulator* emulator, ui::WindowedAppContext& app_context); Emulator* emulator() const { return emulator_; } ui::WindowedAppContext& app_context() const { return app_context_; } ui::Window* window() const { return window_.get(); } + ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); } + + ui::Presenter* GetGraphicsSystemPresenter() const; + void SetupGraphicsSystemPresenterPainting(); + void ShutdownGraphicsSystemPresenterPainting(); + + void OnEmulatorInitialized(); void UpdateTitle(); + void SetFullscreen(bool fullscreen); void ToggleFullscreen(); void SetInitializingShaderStorage(bool initializing); private: + class EmulatorWindowListener final : public ui::WindowListener, + public ui::WindowInputListener { + public: + explicit EmulatorWindowListener(EmulatorWindow& emulator_window) + : emulator_window_(emulator_window) {} + + void OnClosing(ui::UIEvent& e) override; + void OnFileDrop(ui::FileDropEvent& e) override; + + void OnKeyDown(ui::KeyEvent& e) override; + + private: + EmulatorWindow& emulator_window_; + }; + + class DisplayConfigGameConfigLoadCallback + : public Emulator::GameConfigLoadCallback { + public: + DisplayConfigGameConfigLoadCallback(Emulator& emulator, + EmulatorWindow& emulator_window) + : Emulator::GameConfigLoadCallback(emulator), + emulator_window_(emulator_window) {} + + void PostGameConfigLoad() override; + + private: + EmulatorWindow& emulator_window_; + }; + + class DisplayConfigDialog final : public ui::ImGuiDialog { + public: + DisplayConfigDialog(ui::ImGuiDrawer* imgui_drawer, + EmulatorWindow& emulator_window) + : ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + EmulatorWindow& emulator_window_; + }; + explicit EmulatorWindow(Emulator* emulator, ui::WindowedAppContext& app_context); bool Initialize(); + // For comparisons, use GetSwapPostEffectForCvarValue instead as the default + // fallback may be used for multiple values. + static const char* GetCvarValueForSwapPostEffect( + gpu::CommandProcessor::SwapPostEffect effect); + static gpu::CommandProcessor::SwapPostEffect GetSwapPostEffectForCvarValue( + const std::string& cvar_value); + // For comparisons, use GetGuestOutputPaintEffectForCvarValue instead as the + // default fallback may be used for multiple values. + static const char* GetCvarValueForGuestOutputPaintEffect( + ui::Presenter::GuestOutputPaintConfig::Effect effect); + static ui::Presenter::GuestOutputPaintConfig::Effect + GetGuestOutputPaintEffectForCvarValue(const std::string& cvar_value); + static ui::Presenter::GuestOutputPaintConfig + GetGuestOutputPaintConfigForCvars(); + void ApplyDisplayConfigForCvars(); + + void OnKeyDown(ui::KeyEvent& e); void FileDrop(const std::filesystem::path& filename); void FileOpen(); void FileClose(); void ShowContentDirectory(); - void CheckHideCursor(); void CpuTimeScalarReset(); void CpuTimeScalarSetHalf(); void CpuTimeScalarSetDouble(); @@ -56,15 +138,26 @@ class EmulatorWindow { void CpuBreakIntoHostDebugger(); void GpuTraceFrame(); void GpuClearCaches(); + void ToggleDisplayConfigDialog(); void ShowHelpWebsite(); void ShowCommitID(); Emulator* emulator_; ui::WindowedAppContext& app_context_; + EmulatorWindowListener window_listener_; std::unique_ptr window_; + std::unique_ptr imgui_drawer_; + std::unique_ptr + display_config_game_config_load_callback_; + // Creation may fail, in this case immediate drawer UI must not be drawn. + std::unique_ptr immediate_drawer_; + + bool emulator_initialized_ = false; + std::string base_title_; - uint64_t cursor_hide_time_ = 0; bool initializing_shader_storage_ = false; + + std::unique_ptr display_config_dialog_; }; } // namespace app diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 39a2a72b4..98ceb6578 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -28,6 +28,7 @@ #include "xenia/emulator.h" #include "xenia/ui/file_picker.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/vfs/devices/host_path_device.h" @@ -62,8 +63,6 @@ DEFINE_string(gpu, "any", "Graphics system. Use: [any, d3d12, vulkan, null]", DEFINE_string(hid, "any", "Input system. Use: [any, nop, sdl, winkey, xinput]", "HID"); -DEFINE_bool(fullscreen, false, "Toggles fullscreen", "GPU"); - DEFINE_path( storage_root, "", "Root path for persistent internal data storage (config, etc.), or empty " @@ -192,6 +191,17 @@ class EmulatorApp final : public xe::ui::WindowedApp { } }; + class DebugWindowClosedListener final : public xe::ui::WindowListener { + public: + explicit DebugWindowClosedListener(EmulatorApp& emulator_app) + : emulator_app_(emulator_app) {} + + void OnClosing(xe::ui::UIEvent& e) override; + + private: + EmulatorApp& emulator_app_; + }; + explicit EmulatorApp(xe::ui::WindowedAppContext& app_context); static std::unique_ptr CreateAudioSystem( @@ -203,6 +213,8 @@ class EmulatorApp final : public xe::ui::WindowedApp { void EmulatorThread(); void ShutdownEmulatorThreadFromUIThread(); + DebugWindowClosedListener debug_window_closed_listener_; + std::unique_ptr emulator_; std::unique_ptr emulator_window_; @@ -215,8 +227,15 @@ class EmulatorApp final : public xe::ui::WindowedApp { std::thread emulator_thread_; }; +void EmulatorApp::DebugWindowClosedListener::OnClosing(xe::ui::UIEvent& e) { + EmulatorApp* emulator_app = &emulator_app_; + emulator_app->emulator_->processor()->set_debug_listener(nullptr); + emulator_app->debug_window_.reset(); +} + EmulatorApp::EmulatorApp(xe::ui::WindowedAppContext& app_context) - : xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]") { + : xe::ui::WindowedApp(app_context, "xenia", "[Path to .iso/.xex]"), + debug_window_closed_listener_(*this) { AddPositionalOption("target"); } @@ -252,9 +271,10 @@ std::vector> EmulatorApp::CreateInputDrivers( ui::Window* window) { std::vector> drivers; if (cvars::hid.compare("nop") == 0) { - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back( + xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput)); } else { - Factory factory; + Factory factory; #if XE_PLATFORM_WIN32 factory.Add("xinput", xe::hid::xinput::Create); #endif // XE_PLATFORM_WIN32 @@ -263,14 +283,16 @@ std::vector> EmulatorApp::CreateInputDrivers( // WinKey input driver should always be the last input driver added! factory.Add("winkey", xe::hid::winkey::Create); #endif // XE_PLATFORM_WIN32 - for (auto& driver : factory.CreateAll(cvars::hid, window)) { + for (auto& driver : factory.CreateAll(cvars::hid, window, + EmulatorWindow::kZOrderHidInput)) { if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } } if (drivers.empty()) { // Fallback to nop if none created. - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back( + xe::hid::nop::Create(window, EmulatorWindow::kZOrderHidInput)); } } return drivers; @@ -365,6 +387,9 @@ void EmulatorApp::OnDestroy() { // The profiler needs to shut down before the graphics context. Profiler::Shutdown(); + // Write all cvar overrides to the config. + config::SaveConfig(); + // TODO(DrChat): Remove this code and do a proper exit. XELOGI("Cheap-skate exit!"); std::quick_exit(EXIT_SUCCESS); @@ -378,15 +403,18 @@ void EmulatorApp::EmulatorThread() { // Setup and initialize all subsystems. If we can't do something // (unsupported system, memory issues, etc) this will fail early. - X_STATUS result = - emulator_->Setup(emulator_window_->window(), CreateAudioSystem, - CreateGraphicsSystem, CreateInputDrivers); + X_STATUS result = emulator_->Setup( + emulator_window_->window(), emulator_window_->imgui_drawer(), + CreateAudioSystem, CreateGraphicsSystem, CreateInputDrivers); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); app_context().RequestDeferredQuit(); return; } + app_context().CallInUIThread( + [this]() { emulator_window_->SetupGraphicsSystemPresenterPainting(); }); + if (cvars::mount_scratch) { auto scratch_device = std::make_unique( "\\SCRATCH", "scratch", false); @@ -455,12 +483,8 @@ void EmulatorApp::EmulatorThread() { app_context().CallInUIThreadSynchronous([this]() { debug_window_ = xe::debug::ui::DebugWindow::Create(emulator_.get(), app_context()); - debug_window_->window()->on_closed.AddListener( - [this](xe::ui::UIEvent* e) { - emulator_->processor()->set_debug_listener(nullptr); - app_context().CallInUIThread( - [this]() { debug_window_.reset(); }); - }); + debug_window_->window()->AddListener( + &debug_window_closed_listener_); }); // If failed to enqueue the UI thread call, this will just be null. return debug_window_.get(); @@ -489,9 +513,9 @@ void EmulatorApp::EmulatorThread() { } }); - // Enable the main menu now that the emulator is properly loaded + // Enable emulator input now that the emulator is properly loaded. app_context().CallInUIThread( - [this]() { emulator_window_->window()->EnableMainMenu(); }); + [this]() { emulator_window_->OnEmulatorInitialized(); }); // Grab path from the flag or unnamed argument. std::filesystem::path path; @@ -499,12 +523,6 @@ void EmulatorApp::EmulatorThread() { path = cvars::target; } - // Toggles fullscreen - if (cvars::fullscreen) { - app_context().CallInUIThread( - [this]() { emulator_window_->ToggleFullscreen(); }); - } - if (!path.empty()) { // Normalize the path and make absolute. auto abs_path = std::filesystem::absolute(path); diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h index 1f92d0766..585039fd6 100644 --- a/src/xenia/base/cvar.h +++ b/src/xenia/base/cvar.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -86,6 +86,10 @@ class ConfigVar : public CommandVar, virtual public IConfigVar { void LoadGameConfigValue(std::shared_ptr result) override; void SetConfigValue(T val); void SetGameConfigValue(T val); + // Changes the actual value used to the one specified, and also makes it the + // one that will be stored when the global config is written next time. After + // overriding, however, the next game config loaded may still change it. + void OverrideConfigValue(T val); private: std::string category_; @@ -260,6 +264,16 @@ void ConfigVar::SetGameConfigValue(T val) { UpdateValue(); } template +void ConfigVar::OverrideConfigValue(T val) { + config_value_ = std::make_unique(val); + // The user explicitly changes the value at runtime and wants it to take + // effect immediately. Drop everything with a higher priority. The next game + // config load, however, may still change it. + game_config_value_.reset(); + this->commandline_value_.reset(); + UpdateValue(); +} +template void ConfigVar::ResetConfigValueToDefault() { SetConfigValue(this->default_value_); } @@ -373,6 +387,28 @@ ICommandVar* define_cmdvar(const char* name, T* default_value, extern type name; \ } +#define ACCESS_CVar(name) (*cv::cv_##name) + +// dynamic_cast is needed because of virtual inheritance. +#define OVERRIDE_CVar(name, type, value) \ + dynamic_cast*>(&ACCESS_CVar(name)) \ + ->OverrideConfigValue(value); + +#define OVERRIDE_bool(name, value) OVERRIDE_CVar(name, bool, value) + +#define OVERRIDE_int32(name, value) OVERRIDE_CVar(name, int32_t, value) + +#define OVERRIDE_uint32(name, value) OVERRIDE_CVar(name, uint32_t, value) + +#define OVERRIDE_uint64(name, value) OVERRIDE_CVar(name, uint64_t, value) + +#define OVERRIDE_double(name, value) OVERRIDE_CVar(name, double, value) + +#define OVERRIDE_string(name, value) OVERRIDE_CVar(name, std::string, value) + +#define OVERRIDE_path(name, value) \ + OVERRIDE_CVar(name, std::filesystem::path, value) + // Interface for changing the default value of a variable with auto-upgrading of // users' configs (to distinguish between a leftover old default and an explicit // override), without having to rename the variable. diff --git a/src/xenia/base/filesystem.h b/src/xenia/base/filesystem.h index 036a6a7a4..c8cff150f 100644 --- a/src/xenia/base/filesystem.h +++ b/src/xenia/base/filesystem.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -41,8 +41,8 @@ std::filesystem::path GetUserFolder(); // attempting to create it. bool CreateParentFolder(const std::filesystem::path& path); -// Creates an empty file at the given path. -bool CreateFile(const std::filesystem::path& path); +// Creates an empty file at the given path, overwriting if it exists. +bool CreateEmptyFile(const std::filesystem::path& path); // Opens the file at the given path with the specified mode. // This behaves like fopen and the returned handle can be used with stdio. diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 497c98bd3..2e9ddb2c5 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -122,7 +122,7 @@ static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { return filetime; } -bool CreateFile(const std::filesystem::path& path) { +bool CreateEmptyFile(const std::filesystem::path& path) { int file = creat(path.c_str(), 0774); if (file >= 0) { close(file); diff --git a/src/xenia/base/filesystem_win.cc b/src/xenia/base/filesystem_win.cc index 9daf15af5..f1f16c063 100644 --- a/src/xenia/base/filesystem_win.cc +++ b/src/xenia/base/filesystem_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -60,7 +60,7 @@ std::filesystem::path GetUserFolder() { return result; } -bool CreateFile(const std::filesystem::path& path) { +bool CreateEmptyFile(const std::filesystem::path& path) { auto handle = CreateFileW(path.c_str(), 0, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle == INVALID_HANDLE_VALUE) { diff --git a/src/xenia/base/main_win.cc b/src/xenia/base/main_win.cc index 33bd65e75..b6eaa4a7b 100644 --- a/src/xenia/base/main_win.cc +++ b/src/xenia/base/main_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,37 +19,64 @@ // Autogenerated by `xb premake`. #include "build/version.h" -// For RequestHighPerformance. +// For RequestWin32MMCSS. +#include +// For RequestWin32HighResolutionTimer. #include -DEFINE_bool(win32_high_freq, true, - "Requests high performance from the NT kernel", "Kernel"); +DEFINE_bool(win32_high_resolution_timer, true, + "Requests high-resolution timer from the NT kernel", "Win32"); +DEFINE_bool( + win32_mmcss, true, + "Opt in the Multimedia Class Scheduler Service (MMCSS) scheduling for " + "prioritized access to CPU resources", + "Win32"); namespace xe { -static void RequestHighPerformance() { -#if XE_PLATFORM_WIN32 - NTSTATUS(*NtQueryTimerResolution) - (OUT PULONG MinimumResolution, OUT PULONG MaximumResolution, - OUT PULONG CurrentResolution); +static void RequestWin32HighResolutionTimer() { + HMODULE ntdll_module = GetModuleHandleW(L"ntdll.dll"); + if (!ntdll_module) { + return; + } - NTSTATUS(*NtSetTimerResolution) - (IN ULONG DesiredResolution, IN BOOLEAN SetResolution, - OUT PULONG CurrentResolution); - - NtQueryTimerResolution = (decltype(NtQueryTimerResolution))GetProcAddress( - GetModuleHandleW(L"ntdll.dll"), "NtQueryTimerResolution"); - NtSetTimerResolution = (decltype(NtSetTimerResolution))GetProcAddress( - GetModuleHandleW(L"ntdll.dll"), "NtSetTimerResolution"); - if (!NtQueryTimerResolution || !NtSetTimerResolution) { + // clang-format off + NTSTATUS (NTAPI* nt_query_timer_resolution)(OUT PULONG MinimumResolution, + OUT PULONG MaximumResolution, + OUT PULONG CurrentResolution); + NTSTATUS (NTAPI* nt_set_timer_resolution)(IN ULONG DesiredResolution, + IN BOOLEAN SetResolution, + OUT PULONG CurrentResolution); + // clang-format on + nt_query_timer_resolution = + reinterpret_cast( + GetProcAddress(ntdll_module, "NtQueryTimerResolution")); + nt_set_timer_resolution = reinterpret_cast( + GetProcAddress(ntdll_module, "NtSetTimerResolution")); + if (!nt_query_timer_resolution || !nt_set_timer_resolution) { return; } ULONG minimum_resolution, maximum_resolution, current_resolution; - NtQueryTimerResolution(&minimum_resolution, &maximum_resolution, - ¤t_resolution); - NtSetTimerResolution(maximum_resolution, TRUE, ¤t_resolution); -#endif + nt_query_timer_resolution(&minimum_resolution, &maximum_resolution, + ¤t_resolution); + nt_set_timer_resolution(maximum_resolution, TRUE, ¤t_resolution); +} + +static void RequestWin32MMCSS() { + HMODULE dwmapi_module = LoadLibraryW(L"dwmapi.dll"); + if (!dwmapi_module) { + return; + } + // clang-format off + HRESULT (STDAPICALLTYPE* dwm_enable_mmcss)(BOOL fEnableMMCSS); + // clang-format on + dwm_enable_mmcss = reinterpret_cast( + GetProcAddress(dwmapi_module, "DwmEnableMMCSS")); + if (dwm_enable_mmcss) { + dwm_enable_mmcss(TRUE); + } + FreeLibrary(dwmapi_module); } bool ParseWin32LaunchArguments( @@ -103,9 +130,12 @@ int InitializeWin32App(const std::string_view app_name) { #endif XE_BUILD_BRANCH "@" XE_BUILD_COMMIT_SHORT " on " XE_BUILD_DATE); - // Request high performance timing. - if (cvars::win32_high_freq) { - RequestHighPerformance(); + // Request high-performance timing and scheduling. + if (cvars::win32_high_resolution_timer) { + RequestWin32HighResolutionTimer(); + } + if (cvars::win32_mmcss) { + RequestWin32MMCSS(); } return 0; diff --git a/src/xenia/base/math.h b/src/xenia/base/math.h index ac3ef8056..de92fbc7e 100644 --- a/src/xenia/base/math.h +++ b/src/xenia/base/math.h @@ -53,8 +53,11 @@ constexpr T align(T value, T alignment) { // Rounds the given number up to the next highest multiple. template -constexpr T round_up(T value, V multiple) { - return value ? (((value + multiple - 1) / multiple) * multiple) : multiple; +constexpr T round_up(T value, V multiple, bool force_non_zero = true) { + if (force_non_zero && !value) { + return multiple; + } + return (value + multiple - 1) / multiple * multiple; } // Using the same conventions as in shading languages, returning 0 for NaN. diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index 038c26058..800ab8680 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -2,11 +2,12 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ +#include #include // NOTE: this must be included before microprofile as macro expansion needs @@ -36,6 +37,7 @@ #include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/profiling.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" @@ -44,21 +46,27 @@ #endif // XE_OPTION_PROFILING #if XE_OPTION_PROFILING_UI -#undef DrawText #include "xenia/ui/microprofile_drawer.h" #endif // XE_OPTION_PROFILING_UI +DEFINE_bool(profiler_dpi_scaling, false, + "Apply window DPI scaling to the profiler.", "UI"); DEFINE_bool(show_profiler, false, "Show profiling UI by default.", "UI"); namespace xe { -#if XE_OPTION_PROFILING_UI -ui::Window* Profiler::window_ = nullptr; -std::unique_ptr Profiler::drawer_ = nullptr; -#endif // XE_OPTION_PROFILING_UI - #if XE_OPTION_PROFILING +Profiler::ProfilerWindowInputListener Profiler::input_listener_; +size_t Profiler::z_order_ = 0; +ui::Window* Profiler::window_ = nullptr; +#if XE_OPTION_PROFILING_UI +Profiler::ProfilerUIDrawer Profiler::ui_drawer_; +ui::Presenter* Profiler::presenter_ = nullptr; +std::unique_ptr Profiler::drawer_; +bool Profiler::dpi_scaling_ = false; +#endif // XE_OPTION_PROFILING_UI + bool Profiler::is_enabled() { return true; } bool Profiler::is_visible() { return is_enabled() && MicroProfileIsDrawing(); } @@ -79,6 +87,7 @@ void Profiler::Initialize() { g_MicroProfile.nActiveBars |= 0x1 | 0x2; #if XE_OPTION_PROFILING_UI + dpi_scaling_ = cvars::profiler_dpi_scaling; MicroProfileInitUI(); g_MicroProfileUI.bShowSpikes = true; g_MicroProfileUI.nOpacityBackground = 0x40u << 24; @@ -102,7 +111,7 @@ void Profiler::Dump() { } void Profiler::Shutdown() { - drawer_.reset(); + SetUserIO(0, nullptr, nullptr, nullptr); window_ = nullptr; MicroProfileShutdown(); } @@ -119,144 +128,208 @@ void Profiler::ThreadEnter(const char* name) { void Profiler::ThreadExit() { MicroProfileOnThreadExit(); } -bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { +void Profiler::ProfilerWindowInputListener::OnKeyDown(ui::KeyEvent& e) { // https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - switch (virtual_key) { + bool handled = true; + switch (e.virtual_key()) { case ui::VirtualKey::kOem3: // ` MicroProfileTogglePause(); - return true; + break; #if XE_OPTION_PROFILING_UI case ui::VirtualKey::kTab: - MicroProfileToggleDisplayMode(); - return true; + ToggleDisplay(); + break; case ui::VirtualKey::k1: MicroProfileModKey(1); - return true; + break; #endif // XE_OPTION_PROFILING_UI default: + handled = false; break; } - return false; + if (handled) { + e.set_handled(true); + } + PostInputEvent(); } -bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { - switch (virtual_key) { +void Profiler::ProfilerWindowInputListener::OnKeyUp(ui::KeyEvent& e) { + bool handled = true; + switch (e.virtual_key()) { #if XE_OPTION_PROFILING_UI case ui::VirtualKey::k1: MicroProfileModKey(0); - return true; + break; #endif // XE_OPTION_PROFILING_UI default: + handled = false; break; } - return false; + if (handled) { + e.set_handled(true); + } + PostInputEvent(); } #if XE_OPTION_PROFILING_UI -void Profiler::OnMouseDown(bool left_button, bool right_button) { - MicroProfileMouseButton(left_button, right_button); +void Profiler::ProfilerWindowInputListener::OnMouseDown(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + MicroProfileMouseButton(e.button() == ui::MouseEvent::Button::kLeft, + e.button() == ui::MouseEvent::Button::kRight); + e.set_handled(true); + PostInputEvent(); } -void Profiler::OnMouseUp() { MicroProfileMouseButton(0, 0); } - -void Profiler::OnMouseMove(int x, int y) { MicroProfileMousePosition(x, y, 0); } - -void Profiler::OnMouseWheel(int x, int y, int dy) { - MicroProfileMousePosition(x, y, dy); +void Profiler::ProfilerWindowInputListener::OnMouseUp(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + MicroProfileMouseButton(0, 0); + e.set_handled(true); + PostInputEvent(); } -void Profiler::ToggleDisplay() { MicroProfileToggleDisplayMode(); } +void Profiler::ProfilerWindowInputListener::OnMouseMove(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), 0); + e.set_handled(true); + PostInputEvent(); +} + +void Profiler::ProfilerWindowInputListener::OnMouseWheel(ui::MouseEvent& e) { + Profiler::SetMousePosition(e.x(), e.y(), e.scroll_y()); + e.set_handled(true); + PostInputEvent(); +} void Profiler::TogglePause() { MicroProfileTogglePause(); } #else -void Profiler::OnMouseDown(bool left_button, bool right_button) {} - -void Profiler::OnMouseUp() {} - -void Profiler::OnMouseMove(int x, int y) {} - -void Profiler::OnMouseWheel(int x, int y, int dy) {} - -void Profiler::ToggleDisplay() {} - void Profiler::TogglePause() {} #endif // XE_OPTION_PROFILING_UI -void Profiler::set_window(ui::Window* window) { - assert_null(window_); +void Profiler::ToggleDisplay() { + bool was_visible = is_visible(); + MicroProfileToggleDisplayMode(); + if (is_visible() != was_visible) { + if (window_) { + if (was_visible) { + window_->RemoveInputListener(&input_listener_); + } else { + window_->AddInputListener(&input_listener_, z_order_); + } + } +#if XE_OPTION_PROFILING_UI + if (presenter_) { + if (was_visible) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } else { + presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_); + } + } +#endif // XE_OPTION_PROFILING_UI + } +} + +void Profiler::SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer) { +#if XE_OPTION_PROFILING_UI + if (presenter_ && is_visible()) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } + drawer_.reset(); + presenter_ = nullptr; +#endif // XE_OPTION_PROFILING_UI + + if (window_) { + if (is_visible()) { + window_->RemoveInputListener(&input_listener_); + } + window_ = nullptr; + } + if (!window) { return; } + + z_order_ = z_order; window_ = window; - drawer_ = std::make_unique(window); - window_->on_painted.AddListener([](ui::UIEvent* e) { Profiler::Present(); }); +#if XE_OPTION_PROFILING_UI + if (presenter && immediate_drawer) { + presenter_ = presenter; + drawer_ = std::make_unique(immediate_drawer); + } +#endif // XE_OPTION_PROFILING_UI - // Pass through mouse events. - window_->on_mouse_down.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseDown(e->button() == ui::MouseEvent::Button::kLeft, - e->button() == ui::MouseEvent::Button::kRight); - e->set_handled(true); - window_->Invalidate(); + if (is_visible()) { + window_->AddInputListener(&input_listener_, z_order_); +#if XE_OPTION_PROFILING_UI + if (presenter_) { + presenter_->AddUIDrawerFromUIThread(&ui_drawer_, z_order_); } - }); - window_->on_mouse_up.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseUp(); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_mouse_move.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseMove(e->x(), e->y()); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_mouse_wheel.AddListener([](ui::MouseEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnMouseWheel(e->x(), e->y(), -e->dy()); - e->set_handled(true); - window_->Invalidate(); - } - }); - - // Watch for toggle/mode keys and such. - window_->on_key_down.AddListener([](ui::KeyEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnKeyDown(e->virtual_key()); - e->set_handled(true); - window_->Invalidate(); - } - }); - window_->on_key_up.AddListener([](ui::KeyEvent* e) { - if (Profiler::is_visible()) { - Profiler::OnKeyUp(e->virtual_key()); - e->set_handled(true); - window_->Invalidate(); - } - }); +#endif // XE_OPTION_PROFILING_UI + } +} + +void Profiler::Flip() { + MicroProfileFlip(); + // This can be called from non-UI threads, so not trying to access the drawer + // to trigger redraw here as it's owned and managed exclusively by the UI + // thread. Relying on continuous painting currently. } -void Profiler::Present() { - SCOPE_profile_cpu_f("internal"); #if XE_OPTION_PROFILING_UI - if (!window_ || !drawer_) { +void Profiler::ProfilerUIDrawer::Draw(ui::UIDrawContext& ui_draw_context) { + if (!window_ || !presenter_ || !drawer_) { return; } - drawer_->Begin(); - MicroProfileDraw(window_->scaled_width(), window_->scaled_height()); + SCOPE_profile_cpu_f("internal"); + uint32_t coordinate_space_width = dpi_scaling_ + ? window_->GetActualLogicalWidth() + : window_->GetActualPhysicalWidth(); + uint32_t coordinate_space_height = dpi_scaling_ + ? window_->GetActualLogicalHeight() + : window_->GetActualPhysicalHeight(); + drawer_->Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); + MicroProfileDraw(coordinate_space_width, coordinate_space_height); drawer_->End(); -#endif // XE_OPTION_PROFILING_UI + // Continuous repaint. + if (is_visible()) { + presenter_->RequestUIPaintFromUIThread(); + } } +#endif // XE_OPTION_PROFILING_UI -void Profiler::Flip() { MicroProfileFlip(); } +#if XE_OPTION_PROFILING_UI +void Profiler::SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta) { + if (!window_) { + return; + } + if (dpi_scaling_) { + x = window_->PositionToLogical(x); + y = window_->PositionToLogical(y); + } + MicroProfileMousePosition(uint32_t(std::max(int32_t(0), x)), + uint32_t(std::max(int32_t(0), y)), wheel_delta); +} +#endif // XE_OPTION_PROFILING_UI + +void Profiler::PostInputEvent() { + // The profiler can be hidden from within the profiler (Mode > Off). + if (!is_visible()) { + window_->RemoveInputListener(&input_listener_); +#if XE_OPTION_PROFILING_UI + if (presenter_) { + presenter_->RemoveUIDrawerFromUIThread(&ui_drawer_); + } +#endif // XE_OPTION_PROFILING_UI + return; + } + // Relying on continuous painting currently, no need to request drawing. +} #else @@ -268,16 +341,11 @@ void Profiler::Shutdown() {} uint32_t Profiler::GetColor(const char* str) { return 0; } void Profiler::ThreadEnter(const char* name) {} void Profiler::ThreadExit() {} -bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { return false; } -bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { return false; } -void Profiler::OnMouseDown(bool left_button, bool right_button) {} -void Profiler::OnMouseUp() {} -void Profiler::OnMouseMove(int x, int y) {} -void Profiler::OnMouseWheel(int x, int y, int dy) {} void Profiler::ToggleDisplay() {} void Profiler::TogglePause() {} -void Profiler::set_window(ui::Window* window) {} -void Profiler::Present() {} +void Profiler::SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer) {} void Profiler::Flip() {} #endif // XE_OPTION_PROFILING @@ -316,7 +384,7 @@ void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, if (!drawer) { return; } - drawer->DrawText(nX, nY, nColor, pText, nLen); + drawer->DrawTextString(nX, nY, nColor, pText, nLen); } #endif // XE_OPTION_PROFILING_UI diff --git a/src/xenia/base/profiling.h b/src/xenia/base/profiling.h index a55600d7e..24b875967 100644 --- a/src/xenia/base/profiling.h +++ b/src/xenia/base/profiling.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,10 +10,15 @@ #ifndef XENIA_BASE_PROFILING_H_ #define XENIA_BASE_PROFILING_H_ +#include +#include #include +#include "xenia/base/platform.h" #include "xenia/base/string.h" +#include "xenia/ui/ui_drawer.h" #include "xenia/ui/virtual_key.h" +#include "xenia/ui/window_listener.h" #if XE_PLATFORM_WIN32 #define XE_OPTION_PROFILING 1 @@ -30,7 +35,9 @@ namespace xe { namespace ui { +class ImmediateDrawer; class MicroprofileDrawer; +class Presenter; class Window; } // namespace ui } // namespace xe @@ -172,27 +179,65 @@ class Profiler { // Deactivates the calling thread for profiling. static void ThreadExit(); - static bool OnKeyDown(ui::VirtualKey virtual_key); - static bool OnKeyUp(ui::VirtualKey virtual_key); - static void OnMouseDown(bool left_button, bool right_button); - static void OnMouseUp(); - static void OnMouseMove(int x, int y); - static void OnMouseWheel(int x, int y, int dy); static void ToggleDisplay(); static void TogglePause(); - // Initializes input and drawing with the given display. - static void set_window(ui::Window* window); - // Gets the current display, if any. - static ui::MicroprofileDrawer* drawer() { return drawer_.get(); } + // Initializes input for the given window and drawing for the given presenter + // and immediate drawer. + static void SetUserIO(size_t z_order, ui::Window* window, + ui::Presenter* presenter, + ui::ImmediateDrawer* immediate_drawer); + // Gets the current drawer, if any. + static ui::MicroprofileDrawer* drawer() { +#if XE_OPTION_PROFILING_UI + return drawer_.get(); +#else + return nullptr; +#endif + } // Presents the profiler to the bound display, if any. - static void Present(); + static void Present(ui::UIDrawContext& ui_draw_context); // Starts a new frame on the profiler static void Flip(); private: +#if XE_OPTION_PROFILING + class ProfilerWindowInputListener final : public ui::WindowInputListener { + public: + void OnKeyDown(ui::KeyEvent& e) override; + void OnKeyUp(ui::KeyEvent& e) override; +#if XE_OPTION_PROFILING_UI + void OnMouseDown(ui::MouseEvent& e) override; + void OnMouseMove(ui::MouseEvent& e) override; + void OnMouseUp(ui::MouseEvent& e) override; + void OnMouseWheel(ui::MouseEvent& e) override; +#endif // XE_OPTION_PROFILING_UI + }; + // For now, no need for OnDpiChanged in a WindowListener because redrawing is + // done continuously. + +#if XE_OPTION_PROFILING_UI + class ProfilerUIDrawer final : public ui::UIDrawer { + public: + void Draw(ui::UIDrawContext& context) override; + }; +#endif // XE_OPTION_PROFILING_UI + +#if XE_OPTION_PROFILING_UI + static void SetMousePosition(int32_t x, int32_t y, int32_t wheel_delta); +#endif // XE_OPTION_PROFILING_UI + static void PostInputEvent(); + + static ProfilerWindowInputListener input_listener_; + static size_t z_order_; static ui::Window* window_; +#if XE_OPTION_PROFILING_UI + static ProfilerUIDrawer ui_drawer_; + static ui::Presenter* presenter_; static std::unique_ptr drawer_; + static bool dpi_scaling_; +#endif // XE_OPTION_PROFILING_UI +#endif // XE_OPTION_PROFILING }; } // namespace xe diff --git a/src/xenia/config.cc b/src/xenia/config.cc index be19bccda..dcdc5ac2b 100644 --- a/src/xenia/config.cc +++ b/src/xenia/config.cc @@ -105,6 +105,10 @@ void ReadGameConfig(const std::filesystem::path& file_path) { } void SaveConfig() { + if (config_path.empty()) { + return; + } + // All cvar defaults have been updated on loading - store the current date. auto defaults_date_cvar = dynamic_cast*>(cv::cv_defaults_date); diff --git a/src/xenia/config.h b/src/xenia/config.h index 63ef265d5..2271cea6c 100644 --- a/src/xenia/config.h +++ b/src/xenia/config.h @@ -15,6 +15,7 @@ namespace config { void SetupConfig(const std::filesystem::path& config_folder); void LoadGameConfig(const std::string_view title_id); +void SaveConfig(); } // namespace config #endif // XENIA_CONFIG_H_ diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index bb9ee8225..bcbf7e042 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -32,6 +32,8 @@ #include "xenia/kernel/xthread.h" #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/windowed_app_context.h" DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.", "UI"); @@ -49,14 +51,18 @@ using xe::ui::MenuItem; using xe::ui::MouseEvent; using xe::ui::UIEvent; -const std::string kBaseTitle = "Xenia Debugger"; +void DebugWindow::DebugDialog::OnDraw(ImGuiIO& io) { + debug_window_.DrawFrame(io); +} + +static const std::string kBaseTitle = "Xenia Debugger"; DebugWindow::DebugWindow(Emulator* emulator, xe::ui::WindowedAppContext& app_context) : emulator_(emulator), processor_(emulator->processor()), app_context_(app_context), - window_(xe::ui::Window::Create(app_context_, kBaseTitle)) { + window_(xe::ui::Window::Create(app_context_, kBaseTitle, 1500, 1000)) { if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) { assert_always("Failed to initialize capstone"); } @@ -86,44 +92,57 @@ std::unique_ptr DebugWindow::Create( } bool DebugWindow::Initialize() { - if (!window_->Initialize()) { - XELOGE("Failed to initialize platform window"); - return false; - } - // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "&Close", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - window_->Resize(1500, 1000); + // Open the window once it's configured. + if (!window_->Open()) { + XELOGE("Failed to open the platform window for the debugger"); + return false; + } - // Create the graphics context used for drawing. - auto provider = emulator_->display_window()->context()->provider(); - window_->set_context(provider->CreateContext(window_.get())); + // Setup drawing to the window. - // Enable imgui input. - window_->set_imgui_input_enabled(true); + xe::ui::GraphicsProvider& graphics_provider = + *emulator_->graphics_system()->provider(); - window_->on_painting.AddListener([this](UIEvent* e) { DrawFrame(); }); + presenter_ = graphics_provider.CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter for the debugger"); + return false; + } + immediate_drawer_ = graphics_provider.CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer for the debugger"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + + imgui_drawer_ = std::make_unique(window_.get(), 0); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + debug_dialog_ = + std::unique_ptr(new DebugDialog(imgui_drawer_.get(), *this)); + + // Update the cache before the first frame. UpdateCache(); - window_->Invalidate(); + + // Begin drawing. + window_->SetPresenter(presenter_.get()); return true; } -void DebugWindow::DrawFrame() { - xe::ui::GraphicsContextLock lock(window_->context()); - - auto& io = window_->imgui_drawer()->GetIO(); - +void DebugWindow::DrawFrame(ImGuiIO& io) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(-1, 0)); ImGui::Begin("main_window", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | @@ -242,9 +261,6 @@ void DebugWindow::DrawFrame() { ImGui::ShowDemoWindow(); ImGui::ShowMetricsWindow(); } - - // Continuous paint. - window_->Invalidate(); } void DebugWindow::DrawToolbar() { @@ -1443,7 +1459,7 @@ void DebugWindow::UpdateCache() { title += " (stepping)"; break; } - window_->set_title(title); + window_->SetTitle(title); }); cache_.is_running = @@ -1573,7 +1589,7 @@ void DebugWindow::OnBreakpointHit(Breakpoint* breakpoint, } void DebugWindow::Focus() const { - app_context_.CallInUIThread([this]() { window_->set_focus(true); }); + app_context_.CallInUIThread([this]() { window_->Focus(); }); } } // namespace ui diff --git a/src/xenia/debug/ui/debug_window.h b/src/xenia/debug/ui/debug_window.h index 7c9cfae4f..be7294940 100644 --- a/src/xenia/debug/ui/debug_window.h +++ b/src/xenia/debug/ui/debug_window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,7 +18,11 @@ #include "xenia/cpu/debug_listener.h" #include "xenia/cpu/processor.h" #include "xenia/emulator.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -48,11 +52,24 @@ class DebugWindow : public cpu::DebugListener { cpu::ThreadDebugInfo* thread_info) override; private: + class DebugDialog final : public xe::ui::ImGuiDialog { + public: + explicit DebugDialog(xe::ui::ImGuiDrawer* imgui_drawer, + DebugWindow& debug_window) + : xe::ui::ImGuiDialog(imgui_drawer), debug_window_(debug_window) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + DebugWindow& debug_window_; + }; + explicit DebugWindow(Emulator* emulator, xe::ui::WindowedAppContext& app_context); bool Initialize(); - void DrawFrame(); + void DrawFrame(ImGuiIO& io); void DrawToolbar(); void DrawFunctionsPane(); void DrawSourcePane(); @@ -93,7 +110,10 @@ class DebugWindow : public cpu::DebugListener { cpu::Processor* processor_ = nullptr; xe::ui::WindowedAppContext& app_context_; std::unique_ptr window_; - uint64_t last_draw_tick_count_ = 0; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr debug_dialog_; uintptr_t capstone_handle_ = 0; diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 0af32710c..0fbf74d18 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -9,6 +9,7 @@ #include "xenia/emulator.h" +#include #include #include "config.h" @@ -23,7 +24,6 @@ #include "xenia/base/literals.h" #include "xenia/base/logging.h" #include "xenia/base/mapped_memory.h" -#include "xenia/base/profiling.h" #include "xenia/base/string.h" #include "xenia/cpu/backend/code_cache.h" #include "xenia/cpu/backend/x64/x64_backend.h" @@ -41,6 +41,7 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/memory.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/vfs/devices/disc_image_device.h" @@ -63,6 +64,15 @@ namespace xe { using namespace xe::literals; +Emulator::GameConfigLoadCallback::GameConfigLoadCallback(Emulator& emulator) + : emulator_(emulator) { + emulator_.AddGameConfigLoadCallback(this); +} + +Emulator::GameConfigLoadCallback::~GameConfigLoadCallback() { + emulator_.RemoveGameConfigLoadCallback(this); +} + Emulator::Emulator(const std::filesystem::path& command_line, const std::filesystem::path& storage_root, const std::filesystem::path& content_root, @@ -116,7 +126,7 @@ Emulator::~Emulator() { } X_STATUS Emulator::Setup( - ui::Window* display_window, + ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, std::function(cpu::Processor*)> audio_system_factory, std::function()> @@ -126,6 +136,7 @@ X_STATUS Emulator::Setup( X_STATUS result = X_STATUS_UNSUCCESSFUL; display_window_ = display_window; + imgui_drawer_ = imgui_drawer; // Initialize clock. // 360 uses a 50MHz clock. @@ -212,8 +223,10 @@ X_STATUS Emulator::Setup( kernel_state_ = std::make_unique(this); // Setup the core components. - result = graphics_system_->Setup(processor_.get(), kernel_state_.get(), - display_window_); + result = graphics_system_->Setup( + processor_.get(), kernel_state_.get(), + display_window_ ? &display_window_->app_context() : nullptr, + display_window_ != nullptr); if (result) { return result; } @@ -236,14 +249,6 @@ X_STATUS Emulator::Setup( // Initialize emulator fallback exception handling last. ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this); - if (display_window_) { - // Finish initializing the display. - display_window_->app_context().CallInUIThreadSynchronous([this]() { - xe::ui::GraphicsContextLock context_lock(display_window_->context()); - Profiler::set_window(display_window_); - }); - } - return result; } @@ -417,7 +422,7 @@ void Emulator::Resume() { bool Emulator::SaveToFile(const std::filesystem::path& path) { Pause(); - filesystem::CreateFile(path); + filesystem::CreateEmptyFile(path); auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite, 0, 2_GiB); if (!map) { return false; @@ -587,14 +592,16 @@ bool Emulator::ExceptionCallback(Exception* ex) { } // Display a dialog telling the user the guest has crashed. - display_window()->app_context().CallInUIThreadSynchronous([this]() { - xe::ui::ImGuiDialog::ShowMessageBox( - display_window(), "Uh-oh!", - "The guest has crashed.\n\n" - "" - "Xenia has now paused itself.\n" - "A crash dump has been written into the log."); - }); + if (display_window_ && imgui_drawer_) { + display_window_->app_context().CallInUIThreadSynchronous([this]() { + xe::ui::ImGuiDialog::ShowMessageBox( + imgui_drawer_, "Uh-oh!", + "The guest has crashed.\n\n" + "" + "Xenia has now paused itself.\n" + "A crash dump has been written into the log."); + }); + } // Now suspend ourself (we should be a guest thread). current_thread->Suspend(nullptr); @@ -621,6 +628,41 @@ void Emulator::WaitUntilExit() { on_exit(); } +void Emulator::AddGameConfigLoadCallback(GameConfigLoadCallback* callback) { + assert_not_null(callback); + // Game config load callbacks handling is entirely in the UI thread. + assert_true(!display_window_ || + display_window_->app_context().IsInUIThread()); + // Check if already added. + if (std::find(game_config_load_callbacks_.cbegin(), + game_config_load_callbacks_.cend(), + callback) != game_config_load_callbacks_.cend()) { + return; + } + game_config_load_callbacks_.push_back(callback); +} + +void Emulator::RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback) { + assert_not_null(callback); + // Game config load callbacks handling is entirely in the UI thread. + assert_true(!display_window_ || + display_window_->app_context().IsInUIThread()); + auto it = std::find(game_config_load_callbacks_.cbegin(), + game_config_load_callbacks_.cend(), callback); + if (it == game_config_load_callbacks_.cend()) { + return; + } + if (game_config_load_callback_loop_next_index_ != SIZE_MAX) { + // Actualize the next callback index after the erasure from the vector. + size_t existing_index = + size_t(std::distance(game_config_load_callbacks_.cbegin(), it)); + if (game_config_load_callback_loop_next_index_ > existing_index) { + --game_config_load_callback_loop_next_index_; + } + } + game_config_load_callbacks_.erase(it); +} + std::string Emulator::FindLaunchModule() { std::string path("game:\\"); @@ -677,6 +719,10 @@ static std::string format_version(xex2_version version) { X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, const std::string_view module_path) { + // Making changes to the UI (setting the icon) and executing game config load + // callbacks which expect to be called from the UI thread. + assert_true(display_window_->app_context().IsInUIThread()); + // Setup NullDevices for raw HDD partition accesses // Cache/STFC code baked into games tries reading/writing to these // By using a NullDevice that just returns success to all IO requests it @@ -729,7 +775,19 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, // Try and load the resource database (xex only). if (module->title_id()) { auto title_id = fmt::format("{:08X}", module->title_id()); + + // Load the per-game configuration file and make sure updates are handled by + // the callbacks. config::LoadGameConfig(title_id); + assert_true(game_config_load_callback_loop_next_index_ == SIZE_MAX); + game_config_load_callback_loop_next_index_ = 0; + while (game_config_load_callback_loop_next_index_ < + game_config_load_callbacks_.size()) { + game_config_load_callbacks_[game_config_load_callback_loop_next_index_++] + ->PostGameConfigLoad(); + } + game_config_load_callback_loop_next_index_ = SIZE_MAX; + uint32_t resource_data = 0; uint32_t resource_size = 0; if (XSUCCEEDED(module->GetSection(title_id.c_str(), &resource_data, diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index cd86e1f81..96d81d00a 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -10,9 +10,12 @@ #ifndef XENIA_EMULATOR_H_ #define XENIA_EMULATOR_H_ +#include +#include #include #include #include +#include #include "xenia/base/delegate.h" #include "xenia/base/exception_handler.h" @@ -38,6 +41,7 @@ class InputDriver; class InputSystem; } // namespace hid namespace ui { +class ImGuiDrawer; class Window; } // namespace ui } // namespace xe @@ -50,6 +54,37 @@ constexpr fourcc_t kEmulatorSaveSignature = make_fourcc("XSAV"); // This is responsible for initializing and managing all the various subsystems. class Emulator { public: + // This is the class for the top-level callbacks. They may be called in an + // undefined order, so among them there must be no dependencies on each other, + // especially hierarchical ones. If hierarchical handling is needed, for + // instance, if a specific implementation of a subsystem needs to handle + // changes, but the entire implementation must be reloaded, the implementation + // in this example _must not_ register / unregister its own callback - rather, + // the proper ordering and hierarchy should be constructed in a single + // callback (in this example, for the whole subsystem). + // + // All callbacks must be created and destroyed in the UI thread only (or the + // thread that takes its place in the architecture of the specific app if + // there's no UI), as they are invoked in the UI thread. + class GameConfigLoadCallback { + public: + GameConfigLoadCallback(Emulator& emulator); + GameConfigLoadCallback(const GameConfigLoadCallback& callback) = delete; + GameConfigLoadCallback& operator=(const GameConfigLoadCallback& callback) = + delete; + virtual ~GameConfigLoadCallback(); + + // The callback is invoked in the UI thread (or the thread that takes its + // place in the architecture of the specific app if there's no UI). + virtual void PostGameConfigLoad() = 0; + + protected: + Emulator& emulator() const { return emulator_; } + + private: + Emulator& emulator_; + }; + explicit Emulator(const std::filesystem::path& command_line, const std::filesystem::path& storage_root, const std::filesystem::path& content_root, @@ -82,9 +117,13 @@ class Emulator { // Are we currently running a title? bool is_title_open() const { return title_id_.has_value(); } - // Window used for displaying graphical output. + // Window used for displaying graphical output. Can be null. ui::Window* display_window() const { return display_window_; } + // ImGui drawer for various kinds of dialogs requested by the guest. Can be + // null. + ui::ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; } + // Guest memory system modelling the RAM (both virtual and physical) of the // system. Memory* memory() const { return memory_.get(); } @@ -121,7 +160,7 @@ class Emulator { // Once this function returns a game can be launched using one of the Launch // functions. X_STATUS Setup( - ui::Window* display_window, + ui::Window* display_window, ui::ImGuiDrawer* imgui_drawer, std::function(cpu::Processor*)> audio_system_factory, std::function()> @@ -170,6 +209,9 @@ class Emulator { static bool ExceptionCallbackThunk(Exception* ex, void* data); bool ExceptionCallback(Exception* ex); + void AddGameConfigLoadCallback(GameConfigLoadCallback* callback); + void RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback); + std::string FindLaunchModule(); X_STATUS CompleteLaunch(const std::filesystem::path& path, @@ -183,7 +225,8 @@ class Emulator { std::string title_name_; std::string title_version_; - ui::Window* display_window_; + ui::Window* display_window_ = nullptr; + ui::ImGuiDrawer* imgui_drawer_ = nullptr; std::unique_ptr memory_; @@ -196,6 +239,16 @@ class Emulator { std::unique_ptr file_system_; std::unique_ptr kernel_state_; + + // Accessible only from the thread that invokes those callbacks (the UI thread + // if the UI is available). + std::vector game_config_load_callbacks_; + // Using an index, not an iterator, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + // SIZE_MAX if not currently in the game config load callback loop. + size_t game_config_load_callback_loop_next_index_ = SIZE_MAX; + kernel::object_ref main_thread_; std::optional title_id_; // Currently running title ID diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 2e1a43c36..07ff7f070 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -45,15 +45,12 @@ CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system, CommandProcessor::~CommandProcessor() = default; -bool CommandProcessor::Initialize( - std::unique_ptr context) { - context_ = std::move(context); - +bool CommandProcessor::Initialize() { // Initialize the gamma ramps to their default (linear) values - taken from // what games set when starting. for (uint32_t i = 0; i < 256; ++i) { uint32_t value = i * 1023 / 255; - gamma_ramp_.normal[i].value = value | (value << 10) | (value << 20); + gamma_ramp_.table[i].value = value | (value << 10) | (value << 20); } for (uint32_t i = 0; i < 128; ++i) { uint32_t value = (i * 65535 / 127) & ~63; @@ -64,7 +61,7 @@ bool CommandProcessor::Initialize( gamma_ramp_.pwl[i].values[j].value = value; } } - dirty_gamma_ramp_normal_ = true; + dirty_gamma_ramp_table_ = true; dirty_gamma_ramp_pwl_ = true; worker_running_ = true; @@ -140,8 +137,18 @@ void CommandProcessor::CallInThread(std::function fn) { void CommandProcessor::ClearCaches() {} +void CommandProcessor::SetDesiredSwapPostEffect( + SwapPostEffect swap_post_effect) { + if (swap_post_effect_desired_ == swap_post_effect) { + return; + } + swap_post_effect_desired_ = swap_post_effect; + CallInThread([this, swap_post_effect]() { + swap_post_effect_actual_ = swap_post_effect; + }); +} + void CommandProcessor::WorkerThreadMain() { - context_->MakeCurrent(); if (!SetupContext()) { xe::FatalError("Unable to setup command processor internal state"); return; @@ -212,9 +219,6 @@ void CommandProcessor::Pause() { threading::Thread::GetCurrentThread()->Suspend(); }); - // HACK - Prevents a hang in IssueSwap() - swap_state_.pending = false; - fence.Wait(); } @@ -255,7 +259,7 @@ bool CommandProcessor::Restore(ByteStream* stream) { bool CommandProcessor::SetupContext() { return true; } -void CommandProcessor::ShutdownContext() { context_.reset(); } +void CommandProcessor::ShutdownContext() {} void CommandProcessor::InitializeRingBuffer(uint32_t ptr, uint32_t size_log2) { read_ptr_index_ = 0; @@ -326,14 +330,17 @@ void CommandProcessor::UpdateGammaRampValue(GammaRampType type, if (mask_lo) { switch (type) { - case GammaRampType::kNormal: + case GammaRampType::kTable: assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 0); - gamma_ramp_.normal[index].value = value; - dirty_gamma_ramp_normal_ = true; + gamma_ramp_.table[index].value = value; + dirty_gamma_ramp_table_ = true; break; case GammaRampType::kPWL: assert_true(regs->values[XE_GPU_REG_DC_LUT_RW_MODE].u32 == 1); - gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value = value; + // The lower 6 bits are hardwired to 0. + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + gamma_ramp_.pwl[index].values[gamma_ramp_rw_subindex_].value = + value & ~(uint32_t(63) | (uint32_t(63) << 16)); gamma_ramp_rw_subindex_ = (gamma_ramp_rw_subindex_ + 1) % 3; dirty_gamma_ramp_pwl_ = true; break; @@ -385,51 +392,6 @@ void CommandProcessor::PrepareForWait() { trace_writer_.Flush(); } void CommandProcessor::ReturnFromWait() {} -void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { - SCOPE_profile_cpu_f("gpu"); - if (!swap_request_handler_) { - return; - } - - // If there was a swap pending we drop it on the floor. - // This prevents the display from pulling the backbuffer out from under us. - // If we skip a lot then we may need to buffer more, but as the display - // thread should be fairly idle that shouldn't happen. - if (!cvars::vsync) { - std::lock_guard lock(swap_state_.mutex); - if (swap_state_.pending) { - swap_state_.pending = false; - // TODO(benvanik): frame skip counter. - XELOGW("Skipped frame!"); - } - } else { - // Spin until no more pending swap. - while (worker_running_) { - { - std::lock_guard lock(swap_state_.mutex); - if (!swap_state_.pending) { - break; - } - } - xe::threading::MaybeYield(); - } - } - - PerformSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); - - { - // Set pending so that the display will swap the next time it can. - std::lock_guard lock(swap_state_.mutex); - swap_state_.pending = true; - } - - // Notify the display a swap is pending so that our changes are picked up. - // It does the actual front/back buffer swap. - swap_request_handler_(); -} - uint32_t CommandProcessor::ExecutePrimaryBuffer(uint32_t read_index, uint32_t write_index) { SCOPE_profile_cpu_f("gpu"); @@ -837,7 +799,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader, uint32_t frontbuffer_height = reader->ReadAndSwap(); reader->AdvanceRead((count - 4) * sizeof(uint32_t)); - if (swap_mode_ == SwapMode::kNormal) { + if (!ignore_swap_) { IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); } diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index d2ee29d8f..caa49e300 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -26,7 +26,7 @@ #include "xenia/gpu/xenos.h" #include "xenia/kernel/xthread.h" #include "xenia/memory.h" -#include "xenia/ui/graphics_context.h" +#include "xenia/ui/presenter.h" namespace xe { @@ -60,12 +60,20 @@ enum class SwapMode { enum class GammaRampType { kUnknown = 0, - kNormal, + kTable, kPWL, }; struct GammaRamp { - struct NormalEntry { + // A lot of gamma ramp (DC_LUT) documentation: + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + // The ramps entries are BGR, not RGB. + // For the 256-entry table (used by Direct3D 9 for a 8bpc front buffer), + // 535107D4 has in-game settings allowing separate configuration. + // The component order of the PWL table is untested, however, it's likely BGR + // too, since DC_LUTA/B registers have values for blue first, and for red + // last. + struct TableEntry { union { uint32_t value; struct { @@ -81,6 +89,15 @@ struct GammaRamp { union { uint32_t value; struct { + // The lower 6 bits are always zero (these are 10-bit in the upper bits + // thus, not fully 16-bit). + // See DC_LUTA/B_CONTROL for information about the way they should be + // interpreted (`output = base + (multiplier * delta) / 2^increment`, + // where the increment is the value specified in DC_LUTA/B_CONTROL for + // the specific color channel, the base is 7 bits of the front buffer + // value above `increment` bits, the multiplier is the lower `increment` + // bits of it; the increment is nonzero, otherwise the 256-entry table + // should be used instead). uint16_t base; uint16_t delta; }; @@ -91,19 +108,25 @@ struct GammaRamp { union { PWLValue values[3]; struct { - PWLValue r; - PWLValue g; PWLValue b; + PWLValue g; + PWLValue r; }; }; }; - NormalEntry normal[256]; + TableEntry table[256]; PWLEntry pwl[128]; }; class CommandProcessor { public: + enum class SwapPostEffect { + kNone, + kFxaa, + kFxaaExtreme, + }; + CommandProcessor(GraphicsSystem* graphics_system, kernel::KernelState* kernel_state); virtual ~CommandProcessor(); @@ -114,21 +137,26 @@ class CommandProcessor { Shader* active_vertex_shader() const { return active_vertex_shader_; } Shader* active_pixel_shader() const { return active_pixel_shader_; } - virtual bool Initialize(std::unique_ptr context); + virtual bool Initialize(); virtual void Shutdown(); void CallInThread(std::function fn); virtual void ClearCaches(); - SwapState& swap_state() { return swap_state_; } - void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; } - void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height); - - void set_swap_request_handler(std::function fn) { - swap_request_handler_ = fn; + void SetIgnoreSwap(bool ignore_swap) { ignore_swap_ = ignore_swap; } + // "Desired" is for the external thread managing the post-processing effect. + SwapPostEffect GetDesiredSwapPostEffect() const { + return swap_post_effect_desired_; } + void SetDesiredSwapPostEffect(SwapPostEffect swap_post_effect); + // Implementations must not make assumptions that the front buffer will + // necessarily be a resolve destination - it may be a texture generated by any + // means like written to by the CPU or loaded from a file (the disclaimer + // screen right in the beginning of 4D530AA4 is not a resolved render target, + // for instance). + virtual void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) = 0; // May be called not only from the command processor thread when the command // processor is paused, and the termination of this function may be explicitly @@ -179,9 +207,6 @@ class CommandProcessor { virtual void PrepareForWait(); virtual void ReturnFromWait(); - virtual void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) = 0; - uint32_t ExecutePrimaryBuffer(uint32_t start_index, uint32_t end_index); virtual void OnPrimaryBufferEnd() {} void ExecuteIndirectBuffer(uint32_t ptr, uint32_t length); @@ -254,6 +279,14 @@ class CommandProcessor { bool major_mode_explicit) = 0; virtual bool IssueCopy() = 0; + // "Actual" is for the command processor thread, to be read by the + // implementations. + SwapPostEffect GetActualSwapPostEffect() const { + return swap_post_effect_actual_; + } + + // TODO(Triang3l): Write the gamma ramp (including the display controller + // write pointers) in the common code. virtual void InitializeTrace() = 0; Memory* memory_ = nullptr; @@ -274,10 +307,8 @@ class CommandProcessor { std::atomic worker_running_; kernel::object_ref worker_thread_; - std::unique_ptr context_; - SwapMode swap_mode_ = SwapMode::kNormal; - SwapState swap_state_; - std::function swap_request_handler_; + bool ignore_swap_ = false; + std::queue> pending_fns_; // MicroEngine binary from PM4_ME_INIT @@ -305,8 +336,13 @@ class CommandProcessor { GammaRamp gamma_ramp_ = {}; int gamma_ramp_rw_subindex_ = 0; - bool dirty_gamma_ramp_normal_ = true; + bool dirty_gamma_ramp_table_ = true; bool dirty_gamma_ramp_pwl_ = true; + + // By default (such as for tools), post-processing is disabled. + // "Desired" is for the external thread managing the post-processing effect. + SwapPostEffect swap_post_effect_desired_ = SwapPostEffect::kNone; + SwapPostEffect swap_post_effect_actual_ = SwapPostEffect::kNone; }; } // namespace gpu diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 6a3f78bc0..ccab20972 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -23,6 +23,7 @@ #include "xenia/gpu/draw_util.h" #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/xenos.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" #include "xenia/ui/d3d12/d3d12_util.h" DEFINE_bool(d3d12_bindless, true, @@ -51,6 +52,16 @@ namespace xe { namespace gpu { namespace d3d12 { +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h" +} // namespace shaders + D3D12CommandProcessor::D3D12CommandProcessor( D3D12GraphicsSystem* graphics_system, kernel::KernelState* kernel_state) : CommandProcessor(graphics_system, kernel_state), @@ -71,7 +82,7 @@ void D3D12CommandProcessor::InitializeShaderStorage( void D3D12CommandProcessor::RequestFrameTrace( const std::filesystem::path& root_path) { // Capture with PIX if attached. - if (GetD3D12Context().GetD3D12Provider().GetGraphicsAnalysis() != nullptr) { + if (GetD3D12Provider().GetGraphicsAnalysis() != nullptr) { pix_capture_requested_.store(true, std::memory_order_relaxed); return; } @@ -86,7 +97,9 @@ void D3D12CommandProcessor::TracePlaybackWroteMemory(uint32_t base_ptr, void D3D12CommandProcessor::RestoreEdramSnapshot(const void* snapshot) { // Starting a new frame because descriptors may be needed. - BeginSubmission(true); + if (!BeginSubmission(true)) { + return; + } render_target_cache_->RestoreEdramSnapshot(snapshot); } @@ -364,8 +377,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature( ++desc.NumParameters; } - ID3D12RootSignature* root_signature = ui::d3d12::util::CreateRootSignature( - GetD3D12Context().GetD3D12Provider(), desc); + ID3D12RootSignature* root_signature = + ui::d3d12::util::CreateRootSignature(GetD3D12Provider(), desc); if (root_signature == nullptr) { XELOGE( "Failed to create a root signature with {} pixel textures, {} pixel " @@ -430,7 +443,7 @@ uint64_t D3D12CommandProcessor::RequestViewBindfulDescriptors( deferred_command_list_.SetDescriptorHeaps(view_bindful_heap_current_, sampler_bindful_heap_current_); } - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); cpu_handle_out = provider.OffsetViewDescriptor( view_bindful_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index); gpu_handle_out = provider.OffsetViewDescriptor( @@ -464,7 +477,7 @@ bool D3D12CommandProcessor::RequestOneUseSingleViewDescriptors( return true; } assert_not_null(handles_out); - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); if (bindless_resources_used_) { // Request separate bindless descriptors that will be freed when this // submission is completed by the GPU. @@ -511,7 +524,7 @@ ui::d3d12::util::DescriptorCpuGpuHandlePair D3D12CommandProcessor::GetSystemBindlessViewHandlePair( SystemBindlessView view) const { assert_true(bindless_resources_used_); - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); return std::make_pair(provider.OffsetViewDescriptor( view_bindless_heap_cpu_start_, uint32_t(view)), provider.OffsetViewDescriptor( @@ -623,7 +636,7 @@ uint64_t D3D12CommandProcessor::RequestSamplerBindfulDescriptors( deferred_command_list_.SetDescriptorHeaps(view_bindful_heap_current_, sampler_bindful_heap_current_); } - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); cpu_handle_out = provider.OffsetSamplerDescriptor( sampler_bindful_heap_pool_->GetLastRequestHeapCPUStart(), descriptor_index); @@ -650,8 +663,8 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( size = xe::align(size, kScratchBufferSizeIncrement); - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc( buffer_desc, size, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); @@ -664,8 +677,7 @@ ID3D12Resource* D3D12CommandProcessor::RequestScratchGPUBuffer( return nullptr; } if (scratch_buffer_ != nullptr) { - buffers_for_deletion_.push_back( - std::make_pair(scratch_buffer_, submission_current_)); + resources_for_deletion_.emplace_back(submission_current_, scratch_buffer_); } scratch_buffer_ = buffer; scratch_buffer_size_ = size; @@ -789,76 +801,15 @@ std::string D3D12CommandProcessor::GetWindowTitleText() const { return title.str(); } -std::unique_ptr D3D12CommandProcessor::Capture() { - ID3D12Resource* readback_buffer = - RequestReadbackBuffer(uint32_t(swap_texture_copy_size_)); - if (!readback_buffer) { - return nullptr; - } - BeginSubmission(false); - PushTransitionBarrier(swap_texture_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_COPY_SOURCE); - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = swap_texture_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_source.SubresourceIndex = 0; - location_dest.pResource = readback_buffer; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_dest.PlacedFootprint = swap_texture_copy_footprint_; - deferred_command_list_.CopyTexture(location_dest, location_source); - PushTransitionBarrier(swap_texture_, D3D12_RESOURCE_STATE_COPY_SOURCE, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - if (!AwaitAllQueueOperationsCompletion()) { - return nullptr; - } - D3D12_RANGE readback_range; - readback_range.Begin = swap_texture_copy_footprint_.Offset; - readback_range.End = swap_texture_copy_size_; - void* readback_mapping; - if (FAILED(readback_buffer->Map(0, &readback_range, &readback_mapping))) { - return nullptr; - } - std::unique_ptr raw_image(new xe::ui::RawImage()); - auto swap_texture_size = GetSwapTextureSize(); - raw_image->width = swap_texture_size.first; - raw_image->height = swap_texture_size.second; - raw_image->stride = swap_texture_size.first * 4; - raw_image->data.resize(raw_image->stride * swap_texture_size.second); - const uint8_t* readback_source_data = - reinterpret_cast(readback_mapping) + - swap_texture_copy_footprint_.Offset; - static_assert( - ui::d3d12::D3D12Context::kSwapChainFormat == DXGI_FORMAT_B8G8R8A8_UNORM, - "D3D12CommandProcessor::Capture assumes swap_texture_ to be in " - "DXGI_FORMAT_B8G8R8A8_UNORM because it swaps red and blue"); - for (uint32_t i = 0; i < swap_texture_size.second; ++i) { - uint8_t* pixel_dest = raw_image->data.data() + i * raw_image->stride; - const uint8_t* pixel_source = - readback_source_data + - i * swap_texture_copy_footprint_.Footprint.RowPitch; - for (uint32_t j = 0; j < swap_texture_size.first; ++j) { - pixel_dest[0] = pixel_source[2]; - pixel_dest[1] = pixel_source[1]; - pixel_dest[2] = pixel_source[0]; - pixel_dest[3] = pixel_source[3]; - pixel_dest += 4; - pixel_source += 4; - } - } - return raw_image; -} - bool D3D12CommandProcessor::SetupContext() { if (!CommandProcessor::SetupContext()) { XELOGE("Failed to initialize base command processor context"); return false; } - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); - auto direct_queue = provider.GetDirectQueue(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); fence_completion_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (fence_completion_event_ == nullptr) { @@ -1222,120 +1173,255 @@ bool D3D12CommandProcessor::SetupContext() { D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = provider.GetHeapFlagCreateNotZeroed(); - // Create gamma ramp resources. The PWL gamma ramp is 16-bit, but 6 bits are - // hardwired to zero, so DXGI_FORMAT_R10G10B10A2_UNORM can be used for it too. - // https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf - dirty_gamma_ramp_normal_ = true; + // Create gamma ramp resources. + dirty_gamma_ramp_table_ = true; dirty_gamma_ramp_pwl_ = true; - D3D12_RESOURCE_DESC gamma_ramp_desc; - gamma_ramp_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; - gamma_ramp_desc.Alignment = 0; - gamma_ramp_desc.Width = 256; - gamma_ramp_desc.Height = 1; - gamma_ramp_desc.DepthOrArraySize = 1; - // Normal gamma is 256x1, PWL gamma is 128x1. - gamma_ramp_desc.MipLevels = 2; - gamma_ramp_desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; - gamma_ramp_desc.SampleDesc.Count = 1; - gamma_ramp_desc.SampleDesc.Quality = 0; - gamma_ramp_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - gamma_ramp_desc.Flags = D3D12_RESOURCE_FLAG_NONE; + D3D12_RESOURCE_DESC gamma_ramp_buffer_desc; + ui::d3d12::util::FillBufferResourceDesc( + gamma_ramp_buffer_desc, (256 + 128 * 3) * 4, D3D12_RESOURCE_FLAG_NONE); // The first action will be uploading. - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; + gamma_ramp_buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, - &gamma_ramp_desc, gamma_ramp_texture_state_, nullptr, - IID_PPV_ARGS(&gamma_ramp_texture_)))) { - XELOGE("Failed to create the gamma ramp texture"); + &gamma_ramp_buffer_desc, gamma_ramp_buffer_state_, nullptr, + IID_PPV_ARGS(&gamma_ramp_buffer_)))) { + XELOGE("Failed to create the gamma ramp buffer"); return false; } - // Get the layout for the upload buffer. - gamma_ramp_desc.DepthOrArraySize = kQueueFrames; - UINT64 gamma_ramp_upload_size; - device->GetCopyableFootprints(&gamma_ramp_desc, 0, kQueueFrames * 2, 0, - gamma_ramp_footprints_, nullptr, nullptr, - &gamma_ramp_upload_size); - // Create the upload buffer for the gamma ramp. - ui::d3d12::util::FillBufferResourceDesc( - gamma_ramp_desc, gamma_ramp_upload_size, D3D12_RESOURCE_FLAG_NONE); + // The upload buffer is frame-buffered. + gamma_ramp_buffer_desc.Width *= kQueueFrames; if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, - &gamma_ramp_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&gamma_ramp_upload_)))) { + &gamma_ramp_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_PPV_ARGS(&gamma_ramp_upload_buffer_)))) { XELOGE("Failed to create the gamma ramp upload buffer"); return false; } - if (FAILED(gamma_ramp_upload_->Map( - 0, nullptr, reinterpret_cast(&gamma_ramp_upload_mapping_)))) { + if (FAILED(gamma_ramp_upload_buffer_->Map( + 0, nullptr, + reinterpret_cast(&gamma_ramp_upload_buffer_mapping_)))) { XELOGE("Failed to map the gamma ramp upload buffer"); - gamma_ramp_upload_mapping_ = nullptr; + gamma_ramp_upload_buffer_mapping_ = nullptr; return false; } - D3D12_RESOURCE_DESC swap_texture_desc; - swap_texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - swap_texture_desc.Alignment = 0; - auto swap_texture_size = GetSwapTextureSize(); - swap_texture_desc.Width = swap_texture_size.first; - swap_texture_desc.Height = swap_texture_size.second; - swap_texture_desc.DepthOrArraySize = 1; - swap_texture_desc.MipLevels = 1; - swap_texture_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_texture_desc.SampleDesc.Count = 1; - swap_texture_desc.SampleDesc.Quality = 0; - swap_texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - swap_texture_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - // Can be sampled at any time, switch to render target when needed, then back. - if (FAILED(device->CreateCommittedResource( - &ui::d3d12::util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, - &swap_texture_desc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - nullptr, IID_PPV_ARGS(&swap_texture_)))) { - XELOGE("Failed to create the command processor front buffer"); + // Initialize compute pipelines for output with gamma ramp. + D3D12_ROOT_PARAMETER + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kCount)]; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_constants = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kConstants)]; + apply_gamma_root_parameter_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + apply_gamma_root_parameter_constants.Constants.ShaderRegister = 0; + apply_gamma_root_parameter_constants.Constants.RegisterSpace = 0; + apply_gamma_root_parameter_constants.Constants.Num32BitValues = + sizeof(ApplyGammaConstants) / sizeof(uint32_t); + apply_gamma_root_parameter_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_dest; + apply_gamma_root_descriptor_range_dest.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + apply_gamma_root_descriptor_range_dest.NumDescriptors = 1; + apply_gamma_root_descriptor_range_dest.BaseShaderRegister = 0; + apply_gamma_root_descriptor_range_dest.RegisterSpace = 0; + apply_gamma_root_descriptor_range_dest.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_dest = + apply_gamma_root_parameters[UINT( + ApplyGammaRootParameter::kDestination)]; + apply_gamma_root_parameter_dest.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_dest.DescriptorTable.NumDescriptorRanges = 1; + apply_gamma_root_parameter_dest.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_dest; + apply_gamma_root_parameter_dest.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_source; + apply_gamma_root_descriptor_range_source.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + apply_gamma_root_descriptor_range_source.NumDescriptors = 1; + apply_gamma_root_descriptor_range_source.BaseShaderRegister = 0; + apply_gamma_root_descriptor_range_source.RegisterSpace = 0; + apply_gamma_root_descriptor_range_source.OffsetInDescriptorsFromTableStart = + 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_source = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kSource)]; + apply_gamma_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_source.DescriptorTable.NumDescriptorRanges = 1; + apply_gamma_root_parameter_source.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_source; + apply_gamma_root_parameter_source.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE apply_gamma_root_descriptor_range_ramp; + apply_gamma_root_descriptor_range_ramp.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + apply_gamma_root_descriptor_range_ramp.NumDescriptors = 1; + apply_gamma_root_descriptor_range_ramp.BaseShaderRegister = 1; + apply_gamma_root_descriptor_range_ramp.RegisterSpace = 0; + apply_gamma_root_descriptor_range_ramp.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& apply_gamma_root_parameter_gamma_ramp = + apply_gamma_root_parameters[UINT(ApplyGammaRootParameter::kRamp)]; + apply_gamma_root_parameter_gamma_ramp.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + apply_gamma_root_parameter_gamma_ramp.DescriptorTable.NumDescriptorRanges = + 1; + apply_gamma_root_parameter_gamma_ramp.DescriptorTable.pDescriptorRanges = + &apply_gamma_root_descriptor_range_ramp; + apply_gamma_root_parameter_gamma_ramp.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_ROOT_SIGNATURE_DESC apply_gamma_root_signature_desc; + apply_gamma_root_signature_desc.NumParameters = + UINT(ApplyGammaRootParameter::kCount); + apply_gamma_root_signature_desc.pParameters = apply_gamma_root_parameters; + apply_gamma_root_signature_desc.NumStaticSamplers = 0; + apply_gamma_root_signature_desc.pStaticSamplers = nullptr; + apply_gamma_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + *(apply_gamma_root_signature_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateRootSignature(provider, + apply_gamma_root_signature_desc); + if (!apply_gamma_root_signature_) { + XELOGE("Failed to create the gamma ramp application root signature"); return false; } - device->GetCopyableFootprints(&swap_texture_desc, 0, 1, 0, - &swap_texture_copy_footprint_, nullptr, nullptr, - &swap_texture_copy_size_); - D3D12_DESCRIPTOR_HEAP_DESC swap_descriptor_heap_desc; - swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - swap_descriptor_heap_desc.NumDescriptors = 1; - swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - swap_descriptor_heap_desc.NodeMask = 0; - if (FAILED(device->CreateDescriptorHeap( - &swap_descriptor_heap_desc, - IID_PPV_ARGS(&swap_texture_rtv_descriptor_heap_)))) { - XELOGE("Failed to create the command processor front buffer RTV heap"); + *(apply_gamma_table_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_table_cs, + sizeof(shaders::apply_gamma_table_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_table_pipeline_) { + XELOGE( + "Failed to create the 256-entry table gamma ramp application compute " + "pipeline"); return false; } - swap_texture_rtv_ = - swap_texture_rtv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart(); - D3D12_RENDER_TARGET_VIEW_DESC swap_rtv_desc; - swap_rtv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - swap_rtv_desc.Texture2D.MipSlice = 0; - swap_rtv_desc.Texture2D.PlaneSlice = 0; - device->CreateRenderTargetView(swap_texture_, &swap_rtv_desc, - swap_texture_rtv_); - swap_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - swap_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - if (FAILED(device->CreateDescriptorHeap( - &swap_descriptor_heap_desc, - IID_PPV_ARGS(&swap_texture_srv_descriptor_heap_)))) { - XELOGE("Failed to create the command processor front buffer SRV heap"); + *(apply_gamma_table_fxaa_luma_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_table_fxaa_luma_cs, + sizeof(shaders::apply_gamma_table_fxaa_luma_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_table_fxaa_luma_pipeline_) { + XELOGE( + "Failed to create the 256-entry table gamma ramp application compute " + "pipeline with perceptual luma output"); + return false; + } + *(apply_gamma_pwl_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_pwl_cs, + sizeof(shaders::apply_gamma_pwl_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_pwl_pipeline_) { + XELOGE("Failed to create the PWL gamma ramp application compute pipeline"); + return false; + } + *(apply_gamma_pwl_fxaa_luma_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline( + device, shaders::apply_gamma_pwl_fxaa_luma_cs, + sizeof(shaders::apply_gamma_pwl_fxaa_luma_cs), + apply_gamma_root_signature_.Get()); + if (!apply_gamma_pwl_fxaa_luma_pipeline_) { + XELOGE( + "Failed to create the PWL gamma ramp application compute pipeline with " + "perceptual luma output"); + return false; + } + + // Initialize compute pipelines for post-processing anti-aliasing. + D3D12_ROOT_PARAMETER fxaa_root_parameters[UINT(FxaaRootParameter::kCount)]; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_constants = + fxaa_root_parameters[UINT(ApplyGammaRootParameter::kConstants)]; + fxaa_root_parameter_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + fxaa_root_parameter_constants.Constants.ShaderRegister = 0; + fxaa_root_parameter_constants.Constants.RegisterSpace = 0; + fxaa_root_parameter_constants.Constants.Num32BitValues = + sizeof(FxaaConstants) / sizeof(uint32_t); + fxaa_root_parameter_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE fxaa_root_descriptor_range_dest; + fxaa_root_descriptor_range_dest.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + fxaa_root_descriptor_range_dest.NumDescriptors = 1; + fxaa_root_descriptor_range_dest.BaseShaderRegister = 0; + fxaa_root_descriptor_range_dest.RegisterSpace = 0; + fxaa_root_descriptor_range_dest.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_dest = + fxaa_root_parameters[UINT(FxaaRootParameter::kDestination)]; + fxaa_root_parameter_dest.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + fxaa_root_parameter_dest.DescriptorTable.NumDescriptorRanges = 1; + fxaa_root_parameter_dest.DescriptorTable.pDescriptorRanges = + &fxaa_root_descriptor_range_dest; + fxaa_root_parameter_dest.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_DESCRIPTOR_RANGE fxaa_root_descriptor_range_source; + fxaa_root_descriptor_range_source.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + fxaa_root_descriptor_range_source.NumDescriptors = 1; + fxaa_root_descriptor_range_source.BaseShaderRegister = 0; + fxaa_root_descriptor_range_source.RegisterSpace = 0; + fxaa_root_descriptor_range_source.OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& fxaa_root_parameter_source = + fxaa_root_parameters[UINT(FxaaRootParameter::kSource)]; + fxaa_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + fxaa_root_parameter_source.DescriptorTable.NumDescriptorRanges = 1; + fxaa_root_parameter_source.DescriptorTable.pDescriptorRanges = + &fxaa_root_descriptor_range_source; + fxaa_root_parameter_source.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + D3D12_STATIC_SAMPLER_DESC fxaa_root_sampler; + fxaa_root_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + fxaa_root_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + fxaa_root_sampler.MipLODBias = 0.0f; + fxaa_root_sampler.MaxAnisotropy = 1; + fxaa_root_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + fxaa_root_sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + fxaa_root_sampler.MinLOD = 0.0f; + fxaa_root_sampler.MaxLOD = 0.0f; + fxaa_root_sampler.ShaderRegister = 0; + fxaa_root_sampler.RegisterSpace = 0; + fxaa_root_sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + D3D12_ROOT_SIGNATURE_DESC fxaa_root_signature_desc; + fxaa_root_signature_desc.NumParameters = UINT(FxaaRootParameter::kCount); + fxaa_root_signature_desc.pParameters = fxaa_root_parameters; + fxaa_root_signature_desc.NumStaticSamplers = 1; + fxaa_root_signature_desc.pStaticSamplers = &fxaa_root_sampler; + fxaa_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + *(fxaa_root_signature_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateRootSignature(provider, fxaa_root_signature_desc); + if (!fxaa_root_signature_) { + XELOGE("Failed to create the FXAA root signature"); + return false; + } + *(fxaa_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline(device, shaders::fxaa_cs, + sizeof(shaders::fxaa_cs), + fxaa_root_signature_.Get()); + if (!fxaa_pipeline_) { + XELOGE("Failed to create the FXAA compute pipeline"); + return false; + } + *(fxaa_extreme_pipeline_.ReleaseAndGetAddressOf()) = + ui::d3d12::util::CreateComputePipeline(device, shaders::fxaa_extreme_cs, + sizeof(shaders::fxaa_extreme_cs), + fxaa_root_signature_.Get()); + if (!fxaa_pipeline_) { + XELOGE("Failed to create the extreme-quality FXAA compute pipeline"); return false; } - D3D12_SHADER_RESOURCE_VIEW_DESC swap_srv_desc; - swap_srv_desc.Format = ui::d3d12::D3D12Context::kSwapChainFormat; - swap_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - swap_srv_desc.Shader4ComponentMapping = - D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - swap_srv_desc.Texture2D.MostDetailedMip = 0; - swap_srv_desc.Texture2D.MipLevels = 1; - swap_srv_desc.Texture2D.PlaneSlice = 0; - swap_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; - device->CreateShaderResourceView( - swap_texture_, &swap_srv_desc, - swap_texture_srv_descriptor_heap_->GetCPUDescriptorHandleForHeapStart()); if (bindless_resources_used_) { // Create the system bindless descriptors once all resources are @@ -1471,11 +1557,11 @@ bool D3D12CommandProcessor::SetupContext() { view_bindless_heap_cpu_start_, uint32_t(SystemBindlessView::kEdramR32G32B32A32UintUAV)), 4); - // kGammaRampNormalSRV. + // kGammaRampTableSRV. WriteGammaRampSRV(false, provider.OffsetViewDescriptor( view_bindless_heap_cpu_start_, - uint32_t(SystemBindlessView::kGammaRampNormalSRV))); + uint32_t(SystemBindlessView::kGammaRampTableSRV))); // kGammaRampPWLSRV. WriteGammaRampSRV(true, provider.OffsetViewDescriptor( @@ -1501,35 +1587,29 @@ void D3D12CommandProcessor::ShutdownContext() { ui::d3d12::util::ReleaseAndNull(scratch_buffer_); scratch_buffer_size_ = 0; - for (auto& buffer_for_deletion : buffers_for_deletion_) { - buffer_for_deletion.first->Release(); + for (const std::pair& resource_for_deletion : + resources_for_deletion_) { + resource_for_deletion.second->Release(); } - buffers_for_deletion_.clear(); + resources_for_deletion_.clear(); - if (swap_texture_srv_descriptor_heap_ != nullptr) { - { - std::lock_guard lock(swap_state_.mutex); - swap_state_.pending = false; - swap_state_.front_buffer_texture = 0; - } - // TODO(Triang3l): Ensure this is synchronized. The display context may not - // exist at this point, so awaiting its fence doesn't always work. - swap_texture_srv_descriptor_heap_->Release(); - swap_texture_srv_descriptor_heap_ = nullptr; - } - ui::d3d12::util::ReleaseAndNull(swap_texture_rtv_descriptor_heap_); - ui::d3d12::util::ReleaseAndNull(swap_texture_); + fxaa_source_texture_submission_ = 0; + fxaa_source_texture_.Reset(); - // Don't need the data anymore, so zero range. - if (gamma_ramp_upload_mapping_ != nullptr) { - D3D12_RANGE gamma_ramp_written_range; - gamma_ramp_written_range.Begin = 0; - gamma_ramp_written_range.End = 0; - gamma_ramp_upload_->Unmap(0, &gamma_ramp_written_range); - gamma_ramp_upload_mapping_ = nullptr; - } - ui::d3d12::util::ReleaseAndNull(gamma_ramp_upload_); - ui::d3d12::util::ReleaseAndNull(gamma_ramp_texture_); + fxaa_extreme_pipeline_.Reset(); + fxaa_pipeline_.Reset(); + fxaa_root_signature_.Reset(); + + apply_gamma_pwl_fxaa_luma_pipeline_.Reset(); + apply_gamma_pwl_pipeline_.Reset(); + apply_gamma_table_fxaa_luma_pipeline_.Reset(); + apply_gamma_table_pipeline_.Reset(); + apply_gamma_root_signature_.Reset(); + + // Unmapping will be done implicitly by the destruction. + gamma_ramp_upload_buffer_mapping_ = nullptr; + gamma_ramp_upload_buffer_.Reset(); + gamma_ramp_buffer_.Reset(); pipeline_cache_.reset(); @@ -1596,6 +1676,8 @@ void D3D12CommandProcessor::ShutdownContext() { fence_completion_event_ = nullptr; } + device_removed_ = false; + CommandProcessor::ShutdownContext(); } @@ -1633,177 +1715,339 @@ void D3D12CommandProcessor::WriteRegister(uint32_t index, uint32_t value) { } 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); + UpdateGammaRampValue(GammaRampType::kTable, value); } else if (index == XE_GPU_REG_DC_LUT_RW_MODE) { gamma_ramp_rw_subindex_ = 0; } } -void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { +void D3D12CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) { // FIXME(Triang3l): frontbuffer_ptr is currently unreliable, in the trace // player it's set to 0, but it's not needed anyway since the fetch constant // contains the address. SCOPE_profile_cpu_f("gpu"); + ui::Presenter* presenter = graphics_system_->presenter(); + if (!presenter) { + return; + } + // In case the swap command is the only one in the frame. - BeginSubmission(true); - - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); - - // Upload the new gamma ramps, using the upload buffer for the current frame - // (will close the frame after this anyway, so can't write multiple times per - // frame). - uint32_t gamma_ramp_frame = uint32_t(frame_current_ % kQueueFrames); - if (dirty_gamma_ramp_normal_) { - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& gamma_ramp_footprint = - gamma_ramp_footprints_[gamma_ramp_frame * 2]; - volatile uint32_t* mapping = reinterpret_cast( - gamma_ramp_upload_mapping_ + gamma_ramp_footprint.Offset); - for (uint32_t i = 0; i < 256; ++i) { - uint32_t value = gamma_ramp_.normal[i].value; - // Swap red and blue (535107D4 has settings allowing separate - // configuration). - mapping[i] = ((value & 1023) << 20) | (value & (1023 << 10)) | - ((value >> 20) & 1023); - } - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_COPY_DEST); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = gamma_ramp_upload_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_source.PlacedFootprint = gamma_ramp_footprint; - location_dest.pResource = gamma_ramp_texture_; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_dest.SubresourceIndex = 0; - deferred_command_list_.CopyTexture(location_dest, location_source); - dirty_gamma_ramp_normal_ = false; - } - if (dirty_gamma_ramp_pwl_) { - const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& gamma_ramp_footprint = - gamma_ramp_footprints_[gamma_ramp_frame * 2 + 1]; - volatile uint32_t* mapping = reinterpret_cast( - gamma_ramp_upload_mapping_ + gamma_ramp_footprint.Offset); - for (uint32_t i = 0; i < 128; ++i) { - // TODO(Triang3l): Find a game to test if red and blue need to be swapped. - mapping[i] = (gamma_ramp_.pwl[i].values[0].base >> 6) | - (uint32_t(gamma_ramp_.pwl[i].values[1].base >> 6) << 10) | - (uint32_t(gamma_ramp_.pwl[i].values[2].base >> 6) << 20); - } - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_COPY_DEST); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_COPY_DEST; - SubmitBarriers(); - D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = gamma_ramp_upload_; - location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - location_source.PlacedFootprint = gamma_ramp_footprint; - location_dest.pResource = gamma_ramp_texture_; - location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - location_dest.SubresourceIndex = 1; - deferred_command_list_.CopyTexture(location_dest, location_source); - dirty_gamma_ramp_pwl_ = false; + if (!BeginSubmission(true)) { + return; } + // Obtain the actual front buffer size to pass to RefreshGuestOutput, + // resolution-scaled if it's a resolve destination, or not otherwise. D3D12_SHADER_RESOURCE_VIEW_DESC swap_texture_srv_desc; xenos::TextureFormat frontbuffer_format; ID3D12Resource* swap_texture_resource = texture_cache_->RequestSwapTexture( swap_texture_srv_desc, frontbuffer_format); - if (swap_texture_resource) { - // This is according to D3D::InitializePresentationParameters from a game - // executable, which initializes the normal gamma ramp for 8_8_8_8 output - // and the PWL gamma ramp for 2_10_10_10. - bool use_pwl_gamma_ramp = - frontbuffer_format == xenos::TextureFormat::k_2_10_10_10 || - frontbuffer_format == xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16; - - bool descriptors_obtained; - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_swap_texture; - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptor_gamma_ramp; - if (bindless_resources_used_) { - descriptors_obtained = - RequestOneUseSingleViewDescriptors(1, &descriptor_swap_texture); - descriptor_gamma_ramp = GetSystemBindlessViewHandlePair( - use_pwl_gamma_ramp ? SystemBindlessView::kGammaRampPWLSRV - : SystemBindlessView::kGammaRampNormalSRV); - } else { - ui::d3d12::util::DescriptorCpuGpuHandlePair descriptors[2]; - descriptors_obtained = RequestOneUseSingleViewDescriptors(2, descriptors); - if (descriptors_obtained) { - descriptor_swap_texture = descriptors[0]; - descriptor_gamma_ramp = descriptors[1]; - WriteGammaRampSRV(use_pwl_gamma_ramp, descriptor_gamma_ramp.first); - } - } - if (descriptors_obtained) { - // Must not call anything that can change the descriptor heap from now on! - - // Create the swap texture descriptor. - device->CreateShaderResourceView(swap_texture_resource, - &swap_texture_srv_desc, - descriptor_swap_texture.first); - - // The swap texture is kept as an SRV because the graphics system may draw - // with it at any time. It's switched to RTV and back when needed. - PushTransitionBarrier(swap_texture_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, - D3D12_RESOURCE_STATE_RENDER_TARGET); - PushTransitionBarrier(gamma_ramp_texture_, gamma_ramp_texture_state_, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - gamma_ramp_texture_state_ = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - SubmitBarriers(); - - auto swap_texture_size = GetSwapTextureSize(); - - // Draw the stretching rectangle. - render_target_cache_->InvalidateCommandListRenderTargets(); - deferred_command_list_.D3DOMSetRenderTargets(1, &swap_texture_rtv_, TRUE, - nullptr); - D3D12_VIEWPORT viewport; - viewport.TopLeftX = 0.0f; - viewport.TopLeftY = 0.0f; - viewport.Width = float(swap_texture_size.first); - viewport.Height = float(swap_texture_size.second); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 0.0f; - SetViewport(viewport); - D3D12_RECT scissor; - scissor.left = 0; - scissor.top = 0; - scissor.right = swap_texture_size.first; - scissor.bottom = swap_texture_size.second; - SetScissorRect(scissor); - D3D12GraphicsSystem* graphics_system = - static_cast(graphics_system_); - current_cached_pipeline_ = nullptr; - current_external_pipeline_ = nullptr; - current_graphics_root_signature_ = nullptr; - primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - graphics_system->StretchTextureToFrontBuffer( - descriptor_swap_texture.second, &descriptor_gamma_ramp.second, - use_pwl_gamma_ramp ? (1.0f / 128.0f) : (1.0f / 256.0f), - deferred_command_list_); - // Ending the current frame anyway, so no need to reset the current render - // targets when using ROV. - - PushTransitionBarrier(swap_texture_, D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - // Don't care about graphics state because the frame is ending anyway. - auto swap_screen_size = GetSwapScreenSize(); - { - std::lock_guard lock(swap_state_.mutex); - swap_state_.width = swap_screen_size.first; - swap_state_.height = swap_screen_size.second; - swap_state_.front_buffer_texture = - reinterpret_cast(swap_texture_srv_descriptor_heap_); - } - } + if (!swap_texture_resource) { + return; } + D3D12_RESOURCE_DESC swap_texture_desc = swap_texture_resource->GetDesc(); + uint32_t resolution_scale_max = + std::max(texture_cache_->GetDrawResolutionScaleX(), + texture_cache_->GetDrawResolutionScaleY()); + presenter->RefreshGuestOutput( + uint32_t(swap_texture_desc.Width), uint32_t(swap_texture_desc.Height), + 1280 * resolution_scale_max, 720 * resolution_scale_max, + [this, &swap_texture_srv_desc, frontbuffer_format, swap_texture_resource, + &swap_texture_desc]( + ui::Presenter::GuestOutputRefreshContext& context) -> bool { + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + + SwapPostEffect swap_post_effect = GetActualSwapPostEffect(); + bool use_fxaa = swap_post_effect == SwapPostEffect::kFxaa || + swap_post_effect == SwapPostEffect::kFxaaExtreme; + if (use_fxaa) { + // Make sure the texture of the correct size is available for FXAA. + if (fxaa_source_texture_) { + D3D12_RESOURCE_DESC fxaa_source_texture_desc = + fxaa_source_texture_->GetDesc(); + if (fxaa_source_texture_desc.Width != swap_texture_desc.Width || + fxaa_source_texture_desc.Height != swap_texture_desc.Height) { + if (submission_completed_ < fxaa_source_texture_submission_) { + fxaa_source_texture_->AddRef(); + resources_for_deletion_.emplace_back( + fxaa_source_texture_submission_, + fxaa_source_texture_.Get()); + } + fxaa_source_texture_.Reset(); + fxaa_source_texture_submission_ = 0; + } + } + if (!fxaa_source_texture_) { + D3D12_RESOURCE_DESC fxaa_source_texture_desc; + fxaa_source_texture_desc.Dimension = + D3D12_RESOURCE_DIMENSION_TEXTURE2D; + fxaa_source_texture_desc.Alignment = 0; + fxaa_source_texture_desc.Width = swap_texture_desc.Width; + fxaa_source_texture_desc.Height = swap_texture_desc.Height; + fxaa_source_texture_desc.DepthOrArraySize = 1; + fxaa_source_texture_desc.MipLevels = 1; + fxaa_source_texture_desc.Format = kFxaaSourceTextureFormat; + fxaa_source_texture_desc.SampleDesc.Count = 1; + fxaa_source_texture_desc.SampleDesc.Quality = 0; + fxaa_source_texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + fxaa_source_texture_desc.Flags = + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (FAILED(device->CreateCommittedResource( + &ui::d3d12::util::kHeapPropertiesDefault, + provider.GetHeapFlagCreateNotZeroed(), + &fxaa_source_texture_desc, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, nullptr, + IID_PPV_ARGS(&fxaa_source_texture_)))) { + XELOGE("Failed to create the FXAA input texture"); + swap_post_effect = SwapPostEffect::kNone; + use_fxaa = false; + } + } + } + + // This is according to D3D::InitializePresentationParameters from a + // game executable, which initializes the 256-entry table gamma ramp for + // 8_8_8_8 output and the PWL gamma ramp for 2_10_10_10. + bool use_pwl_gamma_ramp = + frontbuffer_format == xenos::TextureFormat::k_2_10_10_10 || + frontbuffer_format == + xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16; + + context.SetIs8bpc(!use_pwl_gamma_ramp && !use_fxaa); + + // Upload the new gamma ramp, using the upload buffer for the current + // frame (will close the frame after this anyway, so can't write + // multiple times per frame). + if (use_pwl_gamma_ramp ? dirty_gamma_ramp_pwl_ + : dirty_gamma_ramp_table_) { + uint32_t gamma_ramp_offset_bytes = use_pwl_gamma_ramp ? 256 * 4 : 0; + uint32_t gamma_ramp_upload_offset_bytes = + uint32_t(frame_current_ % kQueueFrames) * ((256 + 128 * 3) * 4) + + gamma_ramp_offset_bytes; + uint32_t gamma_ramp_size_bytes = + (use_pwl_gamma_ramp ? 128 * 3 : 256) * 4; + std::memcpy(gamma_ramp_upload_buffer_mapping_ + + gamma_ramp_upload_offset_bytes, + use_pwl_gamma_ramp + ? static_cast(gamma_ramp_.pwl) + : static_cast(gamma_ramp_.table), + gamma_ramp_size_bytes); + PushTransitionBarrier(gamma_ramp_buffer_.Get(), + gamma_ramp_buffer_state_, + D3D12_RESOURCE_STATE_COPY_DEST); + gamma_ramp_buffer_state_ = D3D12_RESOURCE_STATE_COPY_DEST; + SubmitBarriers(); + deferred_command_list_.D3DCopyBufferRegion( + gamma_ramp_buffer_.Get(), gamma_ramp_offset_bytes, + gamma_ramp_upload_buffer_.Get(), gamma_ramp_upload_offset_bytes, + gamma_ramp_size_bytes); + (use_pwl_gamma_ramp ? dirty_gamma_ramp_pwl_ + : dirty_gamma_ramp_table_) = false; + } + + // Destination, source, and if bindful, gamma ramp. + ui::d3d12::util::DescriptorCpuGpuHandlePair apply_gamma_descriptors[3]; + ui::d3d12::util::DescriptorCpuGpuHandlePair + apply_gamma_descriptor_gamma_ramp; + if (!RequestOneUseSingleViewDescriptors( + bindless_resources_used_ ? 2 : 3, apply_gamma_descriptors)) { + return false; + } + // Must not call anything that can change the descriptor heap from now + // on! + if (bindless_resources_used_) { + apply_gamma_descriptor_gamma_ramp = GetSystemBindlessViewHandlePair( + use_pwl_gamma_ramp ? SystemBindlessView::kGammaRampPWLSRV + : SystemBindlessView::kGammaRampTableSRV); + } else { + apply_gamma_descriptor_gamma_ramp = apply_gamma_descriptors[2]; + WriteGammaRampSRV(use_pwl_gamma_ramp, + apply_gamma_descriptor_gamma_ramp.first); + } + + ID3D12Resource* guest_output_resource = + static_cast< + ui::d3d12::D3D12Presenter::D3D12GuestOutputRefreshContext&>( + context) + .resource_uav_capable(); + + if (use_fxaa) { + fxaa_source_texture_submission_ = submission_current_; + } + + ID3D12Resource* apply_gamma_dest = + use_fxaa ? fxaa_source_texture_.Get() : guest_output_resource; + D3D12_RESOURCE_STATES apply_gamma_dest_initial_state = + use_fxaa ? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + : ui::d3d12::D3D12Presenter::kGuestOutputInternalState; + static_cast( + context) + .resource_uav_capable(); + PushTransitionBarrier(apply_gamma_dest, apply_gamma_dest_initial_state, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + // From now on, even in case of failure, apply_gamma_dest must be + // transitioned back to apply_gamma_dest_initial_state! + D3D12_UNORDERED_ACCESS_VIEW_DESC apply_gamma_dest_uav_desc; + apply_gamma_dest_uav_desc.Format = + use_fxaa ? kFxaaSourceTextureFormat + : ui::d3d12::D3D12Presenter::kGuestOutputFormat; + apply_gamma_dest_uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + apply_gamma_dest_uav_desc.Texture2D.MipSlice = 0; + apply_gamma_dest_uav_desc.Texture2D.PlaneSlice = 0; + device->CreateUnorderedAccessView(apply_gamma_dest, nullptr, + &apply_gamma_dest_uav_desc, + apply_gamma_descriptors[0].first); + + device->CreateShaderResourceView(swap_texture_resource, + &swap_texture_srv_desc, + apply_gamma_descriptors[1].first); + + PushTransitionBarrier(gamma_ramp_buffer_.Get(), + gamma_ramp_buffer_state_, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + gamma_ramp_buffer_state_ = + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + deferred_command_list_.D3DSetComputeRootSignature( + apply_gamma_root_signature_.Get()); + ApplyGammaConstants apply_gamma_constants; + apply_gamma_constants.size[0] = uint32_t(swap_texture_desc.Width); + apply_gamma_constants.size[1] = uint32_t(swap_texture_desc.Height); + deferred_command_list_.D3DSetComputeRoot32BitConstants( + UINT(ApplyGammaRootParameter::kConstants), + sizeof(apply_gamma_constants) / sizeof(uint32_t), + &apply_gamma_constants, 0); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kDestination), + apply_gamma_descriptors[0].second); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kSource), + apply_gamma_descriptors[1].second); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(ApplyGammaRootParameter::kRamp), + apply_gamma_descriptor_gamma_ramp.second); + ID3D12PipelineState* apply_gamma_pipeline; + if (use_pwl_gamma_ramp) { + apply_gamma_pipeline = use_fxaa + ? apply_gamma_pwl_fxaa_luma_pipeline_.Get() + : apply_gamma_pwl_pipeline_.Get(); + } else { + apply_gamma_pipeline = + use_fxaa ? apply_gamma_table_fxaa_luma_pipeline_.Get() + : apply_gamma_table_pipeline_.Get(); + } + SetExternalPipeline(apply_gamma_pipeline); + SubmitBarriers(); + uint32_t group_count_x = (uint32_t(swap_texture_desc.Width) + 7) / 8; + uint32_t group_count_y = (uint32_t(swap_texture_desc.Height) + 7) / 8; + deferred_command_list_.D3DDispatch(group_count_x, group_count_y, 1); + + // Apply FXAA. + if (use_fxaa) { + // Destination and source. + ui::d3d12::util::DescriptorCpuGpuHandlePair fxaa_descriptors[2]; + if (!RequestOneUseSingleViewDescriptors( + uint32_t(xe::countof(fxaa_descriptors)), fxaa_descriptors)) { + // Failed to obtain descriptors for FXAA - just copy after gamma + // ramp application without applying FXAA. + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_COPY_SOURCE); + PushTransitionBarrier( + guest_output_resource, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState, + D3D12_RESOURCE_STATE_COPY_DEST); + SubmitBarriers(); + deferred_command_list_.D3DCopyResource(guest_output_resource, + apply_gamma_dest); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_COPY_SOURCE, + apply_gamma_dest_initial_state); + PushTransitionBarrier( + guest_output_resource, D3D12_RESOURCE_STATE_COPY_DEST, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + return false; + } else { + assert_true(apply_gamma_dest_initial_state == + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + apply_gamma_dest_initial_state); + PushTransitionBarrier( + guest_output_resource, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + // From now on, even in case of failure, guest_output_resource must + // be transitioned back to kGuestOutputInternalState! + deferred_command_list_.D3DSetComputeRootSignature( + fxaa_root_signature_.Get()); + FxaaConstants fxaa_constants; + fxaa_constants.size[0] = uint32_t(swap_texture_desc.Width); + fxaa_constants.size[1] = uint32_t(swap_texture_desc.Height); + fxaa_constants.size_inv[0] = 1.0f / float(fxaa_constants.size[0]); + fxaa_constants.size_inv[1] = 1.0f / float(fxaa_constants.size[1]); + deferred_command_list_.D3DSetComputeRoot32BitConstants( + UINT(FxaaRootParameter::kConstants), + sizeof(fxaa_constants) / sizeof(uint32_t), &fxaa_constants, 0); + D3D12_UNORDERED_ACCESS_VIEW_DESC fxaa_dest_uav_desc; + fxaa_dest_uav_desc.Format = + ui::d3d12::D3D12Presenter::kGuestOutputFormat; + fxaa_dest_uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + fxaa_dest_uav_desc.Texture2D.MipSlice = 0; + fxaa_dest_uav_desc.Texture2D.PlaneSlice = 0; + device->CreateUnorderedAccessView(guest_output_resource, nullptr, + &fxaa_dest_uav_desc, + fxaa_descriptors[0].first); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(FxaaRootParameter::kDestination), + fxaa_descriptors[0].second); + D3D12_SHADER_RESOURCE_VIEW_DESC fxaa_source_srv_desc; + fxaa_source_srv_desc.Format = kFxaaSourceTextureFormat; + fxaa_source_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + fxaa_source_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + fxaa_source_srv_desc.Texture2D.MostDetailedMip = 0; + fxaa_source_srv_desc.Texture2D.MipLevels = 1; + fxaa_source_srv_desc.Texture2D.PlaneSlice = 0; + fxaa_source_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView(fxaa_source_texture_.Get(), + &fxaa_source_srv_desc, + fxaa_descriptors[1].first); + deferred_command_list_.D3DSetComputeRootDescriptorTable( + UINT(FxaaRootParameter::kSource), fxaa_descriptors[1].second); + SetExternalPipeline(swap_post_effect == SwapPostEffect::kFxaaExtreme + ? fxaa_extreme_pipeline_.Get() + : fxaa_pipeline_.Get()); + SubmitBarriers(); + deferred_command_list_.D3DDispatch(group_count_x, group_count_y, 1); + PushTransitionBarrier( + guest_output_resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + } + } else { + assert_true(apply_gamma_dest_initial_state == + ui::d3d12::D3D12Presenter::kGuestOutputInternalState); + PushTransitionBarrier(apply_gamma_dest, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + apply_gamma_dest_initial_state); + } + + // Need to submit all the commands before giving the image back to the + // presenter so it can submit its own commands for displaying it to the + // queue. + SubmitBarriers(); + EndSubmission(true); + return true; + }); + + // End the frame even if did not present for any reason (the image refresher + // was not called), to prevent leaking per-frame resources. EndSubmission(true); } @@ -1829,7 +2073,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES - ID3D12Device* device = GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = GetD3D12Provider().GetDevice(); const RegisterFile& regs = *register_file_; xenos::ModeControl edram_mode = regs.Get().edram_mode; @@ -1884,7 +2128,9 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, pixel_shader && pixel_shader->is_valid_memexport_used(); bool memexport_used = memexport_used_vertex || memexport_used_pixel; - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } // Process primitives. PrimitiveProcessor::ProcessingResult primitive_processing_result; @@ -2349,7 +2595,9 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, } void D3D12CommandProcessor::InitializeTrace() { - BeginSubmission(false); + if (!BeginSubmission(false)) { + return; + } bool render_target_cache_submitted = render_target_cache_->InitializeTraceSubmitDownloads(); bool shared_memory_submitted = @@ -2370,7 +2618,9 @@ bool D3D12CommandProcessor::IssueCopy() { #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES - BeginSubmission(true); + if (!BeginSubmission(true)) { + return false; + } uint32_t written_address, written_length; if (!render_target_cache_->Resolve(*memory_, *shared_memory_, *texture_cache_, written_address, written_length)) { @@ -2416,8 +2666,7 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { // outside of a submission, await explicitly. if (queue_operations_done_since_submission_signal_) { UINT64 fence_value = ++queue_operations_since_submission_fence_last_; - ID3D12CommandQueue* direct_queue = - GetD3D12Context().GetD3D12Provider().GetDirectQueue(); + ID3D12CommandQueue* direct_queue = GetD3D12Provider().GetDirectQueue(); if (SUCCEEDED( direct_queue->Signal(queue_operations_since_submission_fence_, fence_value) && @@ -2486,13 +2735,13 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { view_bindless_one_use_descriptors_.pop_front(); } - // Delete transient buffers marked for deletion. - while (!buffers_for_deletion_.empty()) { - if (buffers_for_deletion_.front().second > submission_completed_) { + // Delete transient resources marked for deletion. + while (!resources_for_deletion_.empty()) { + if (resources_for_deletion_.front().first > submission_completed_) { break; } - buffers_for_deletion_.front().first->Release(); - buffers_for_deletion_.pop_front(); + resources_for_deletion_.front().second->Release(); + resources_for_deletion_.pop_front(); } shared_memory_->CompletedSubmissionUpdated(); @@ -2502,14 +2751,28 @@ void D3D12CommandProcessor::CheckSubmissionFence(uint64_t await_submission) { render_target_cache_->CompletedSubmissionUpdated(); } -void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { +bool D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); #endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES + if (device_removed_) { + return false; + } + bool is_opening_frame = is_guest_command && !frame_open_; if (submission_open_ && !is_opening_frame) { - return; + return true; + } + + // Check if the device is still available. + ID3D12Device* device = GetD3D12Provider().GetDevice(); + HRESULT device_removed_reason = device->GetDeviceRemovedReason(); + if (FAILED(device_removed_reason)) { + device_removed_ = true; + graphics_system_->OnHostGpuLossFromAnyThread(device_removed_reason != + DXGI_ERROR_DEVICE_REMOVED); + return false; } // Check the fence - needed for all kinds of submissions (to reclaim transient @@ -2610,7 +2873,7 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { pix_capture_requested_.exchange(false, std::memory_order_relaxed); if (pix_capturing_) { IDXGraphicsAnalysis* graphics_analysis = - GetD3D12Context().GetD3D12Provider().GetGraphicsAnalysis(); + GetD3D12Provider().GetGraphicsAnalysis(); if (graphics_analysis != nullptr) { graphics_analysis->BeginCapture(); } @@ -2620,10 +2883,12 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) { texture_cache_->BeginFrame(); } + + return true; } bool D3D12CommandProcessor::EndSubmission(bool is_swap) { - auto& provider = GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); // Make sure there is a command allocator to write commands to. if (submission_open_ && !command_allocator_writable_first_) { @@ -2660,7 +2925,7 @@ bool D3D12CommandProcessor::EndSubmission(bool is_swap) { // destroyed between frames. SubmitBarriers(); - auto direct_queue = provider.GetDirectQueue(); + ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); // Submit the deferred command list. // Only one deferred command list must be executed in the same @@ -3347,9 +3612,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( bool D3D12CommandProcessor::UpdateBindings( const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader, ID3D12RootSignature* root_signature) { - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); - auto& regs = *register_file_; + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); + const RegisterFile& regs = *register_file_; #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES SCOPE_profile_cpu_f("gpu"); @@ -4178,8 +4443,8 @@ ID3D12Resource* D3D12CommandProcessor::RequestReadbackBuffer(uint32_t size) { } size = xe::align(size, kReadbackBufferSizeIncrement); if (size > readback_buffer_size_) { - auto& provider = GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; ui::d3d12::util::FillBufferResourceDesc(buffer_desc, size, D3D12_RESOURCE_FLAG_NONE); @@ -4201,16 +4466,23 @@ ID3D12Resource* D3D12CommandProcessor::RequestReadbackBuffer(uint32_t size) { void D3D12CommandProcessor::WriteGammaRampSRV( bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const { - auto device = GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = GetD3D12Provider().GetDevice(); D3D12_SHADER_RESOURCE_VIEW_DESC desc; desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - // 256-entry for normal, 128-entry for PWL. - desc.Texture1D.MostDetailedMip = is_pwl ? 1 : 0; - desc.Texture1D.MipLevels = 1; - desc.Texture1D.ResourceMinLODClamp = 0.0f; - device->CreateShaderResourceView(gamma_ramp_texture_, &desc, handle); + desc.Buffer.StructureByteStride = 0; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; + if (is_pwl) { + desc.Format = DXGI_FORMAT_R16G16_UINT; + desc.Buffer.FirstElement = 256 * 4 / 4; + desc.Buffer.NumElements = 128 * 3; + } else { + desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = 256; + } + device->CreateShaderResourceView(gamma_ramp_buffer_.Get(), &desc, handle); } } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.h b/src/xenia/gpu/d3d12/d3d12_command_processor.h index 3476a9ad8..abdd1fbda 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.h +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -32,8 +32,8 @@ #include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/xenos.h" #include "xenia/kernel/kernel_state.h" -#include "xenia/ui/d3d12/d3d12_context.h" #include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h" +#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h" #include "xenia/ui/d3d12/d3d12_util.h" @@ -58,8 +58,9 @@ class D3D12CommandProcessor : public CommandProcessor { void RestoreEdramSnapshot(const void* snapshot) override; - ui::d3d12::D3D12Context& GetD3D12Context() const { - return static_cast(*context_); + ui::d3d12::D3D12Provider& GetD3D12Provider() const { + return *static_cast( + graphics_system_->provider()); } // Returns the deferred drawing command list for the currently open @@ -153,7 +154,7 @@ class D3D12CommandProcessor : public CommandProcessor { kEdramR32G32UintUAV, kEdramR32G32B32A32UintUAV, - kGammaRampNormalSRV, + kGammaRampTableSRV, kGammaRampPWLSRV, // Beyond this point, SRVs are accessible to shaders through an unbounded @@ -210,16 +211,14 @@ class D3D12CommandProcessor : public CommandProcessor { // Returns the text to display in the GPU backend name in the window title. std::string GetWindowTitleText() const; - std::unique_ptr Capture(); - protected: bool SetupContext() override; void ShutdownContext() override; void WriteRegister(uint32_t index, uint32_t value) override; - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) override; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; void OnPrimaryBufferEnd() override; @@ -321,8 +320,9 @@ class D3D12CommandProcessor : public CommandProcessor { void CheckSubmissionFence(uint64_t await_submission); // If is_guest_command is true, a new full frame - with full cleanup of // resources and, if needed, starting capturing - is opened if pending (as - // opposed to simply resuming after mid-frame synchronization). - void BeginSubmission(bool is_guest_command); + // opposed to simply resuming after mid-frame synchronization). Returns + // whether a submission is open currently and the device is not removed. + bool BeginSubmission(bool is_guest_command); // If is_swap is true, a full frame is closed - with, if needed, cache // clearing and stopping capturing. Returns whether the submission was done // successfully, if it has failed, leaves it open. @@ -380,6 +380,8 @@ class D3D12CommandProcessor : public CommandProcessor { void WriteGammaRampSRV(bool is_pwl, D3D12_CPU_DESCRIPTOR_HANDLE handle) const; + bool device_removed_ = false; + bool cache_clear_requested_ = false; HANDLE fence_completion_event_ = nullptr; @@ -497,42 +499,73 @@ class D3D12CommandProcessor : public CommandProcessor { std::unique_ptr texture_cache_; - // Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL - // ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D. - ID3D12Resource* gamma_ramp_texture_ = nullptr; - D3D12_RESOURCE_STATES gamma_ramp_texture_state_; + // Bytes 0x0...0x3FF - 256-entry R10G10B10X2 gamma ramp (red and blue must be + // read as swapped - 535107D4 has settings allowing separate configuration). + // Bytes 0x400...0x9FF - 128-entry PWL R16G16 gamma ramp (R - base, G - delta, + // low 6 bits of each are zero, 3 elements per entry). + // https://www.x.org/docs/AMD/old/42590_m76_rrg_1.01o.pdf + Microsoft::WRL::ComPtr gamma_ramp_buffer_; + D3D12_RESOURCE_STATES gamma_ramp_buffer_state_; // Upload buffer for an image that is the same as gamma_ramp_, but with // kQueueFrames array layers. - ID3D12Resource* gamma_ramp_upload_ = nullptr; - uint8_t* gamma_ramp_upload_mapping_ = nullptr; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT gamma_ramp_footprints_[kQueueFrames * 2]; + Microsoft::WRL::ComPtr gamma_ramp_upload_buffer_; + uint8_t* gamma_ramp_upload_buffer_mapping_ = nullptr; - static constexpr uint32_t kSwapTextureWidth = 1280; - static constexpr uint32_t kSwapTextureHeight = 720; - std::pair GetSwapTextureSize() const { - return std::make_pair( - kSwapTextureWidth * texture_cache_->GetDrawResolutionScaleX(), - kSwapTextureHeight * texture_cache_->GetDrawResolutionScaleY()); - } - std::pair GetSwapScreenSize() const { - uint32_t resolution_scale = - std::max(texture_cache_->GetDrawResolutionScaleX(), - texture_cache_->GetDrawResolutionScaleY()); - return std::make_pair(kSwapTextureWidth * resolution_scale, - kSwapTextureHeight * resolution_scale); - } - ID3D12Resource* swap_texture_ = nullptr; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT swap_texture_copy_footprint_; - UINT64 swap_texture_copy_size_; - ID3D12DescriptorHeap* swap_texture_rtv_descriptor_heap_ = nullptr; - D3D12_CPU_DESCRIPTOR_HANDLE swap_texture_rtv_; - ID3D12DescriptorHeap* swap_texture_srv_descriptor_heap_ = nullptr; + struct ApplyGammaConstants { + uint32_t size[2]; + }; + enum class ApplyGammaRootParameter : UINT { + kConstants, + kDestination, + kSource, + kRamp, + + kCount, + }; + Microsoft::WRL::ComPtr apply_gamma_root_signature_; + Microsoft::WRL::ComPtr apply_gamma_table_pipeline_; + Microsoft::WRL::ComPtr + apply_gamma_table_fxaa_luma_pipeline_; + Microsoft::WRL::ComPtr apply_gamma_pwl_pipeline_; + Microsoft::WRL::ComPtr + apply_gamma_pwl_fxaa_luma_pipeline_; + + struct FxaaConstants { + uint32_t size[2]; + float size_inv[2]; + }; + enum class FxaaRootParameter : UINT { + kConstants, + kDestination, + kSource, + + kCount, + }; + Microsoft::WRL::ComPtr fxaa_root_signature_; + Microsoft::WRL::ComPtr fxaa_pipeline_; + Microsoft::WRL::ComPtr fxaa_extreme_pipeline_; + + // PWL gamma ramp can result in values with more precision than 10bpc. Though + // those sub-10bpc bits don't have any noticeable visual effect, so normally + // R10G10B10A2_UNORM is enough. But what's the most important is that for the + // original FXAA shader, the luma needs to be written to the alpha channel. + // For simplicity (to avoid modifying the FXAA shader and adding more texture + // fetches into it), and for the highest quality (preserving all 13 bits that + // may be generated by applying the PWL gamma ramp with an increment of 2^3, + // and also leaving some space for the result of applying fractional weights + // to calculate the luma), using R16G16B16A16_UNORM instead of + // R10G10B10X2_UNORM with a separate alpha texture. + static constexpr DXGI_FORMAT kFxaaSourceTextureFormat = + DXGI_FORMAT_R16G16B16A16_UNORM; + // Kept in NON_PIXEL_SHADER_RESOURCE state. + Microsoft::WRL::ComPtr fxaa_source_texture_; + uint64_t fxaa_source_texture_submission_ = 0; // Unsubmitted barrier batch. std::vector barriers_; // , sorted by the submission number. - std::deque> buffers_for_deletion_; + std::deque> resources_for_deletion_; static constexpr uint32_t kScratchBufferSizeIncrement = 16 * 1024 * 1024; ID3D12Resource* scratch_buffer_ = nullptr; diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc index 411e95ce5..b4e0d025d 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc @@ -22,13 +22,6 @@ namespace xe { namespace gpu { namespace d3d12 { -// Generated with `xb buildshaders`. -namespace shaders { -#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_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" -} // namespace shaders - D3D12GraphicsSystem::D3D12GraphicsSystem() {} D3D12GraphicsSystem::~D3D12GraphicsSystem() {} @@ -48,198 +41,11 @@ std::string D3D12GraphicsSystem::name() const { X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + bool is_surface_required) { provider_ = xe::ui::d3d12::D3D12Provider::Create(); - auto d3d12_provider = static_cast(provider()); - auto device = d3d12_provider->GetDevice(); - - auto result = GraphicsSystem::Setup(processor, kernel_state, target_window); - if (result != X_STATUS_SUCCESS) { - return result; - } - - if (target_window) { - display_context_ = reinterpret_cast( - target_window->context()); - } - - // Create the stretch pipeline root signature, with 1 parameter (source - // texture) for raw stretch and 3 parameters (source texture, gamma ramp LUT, - // inverse of the size of the gamma ramp LUT) for gamma-correcting stretch. - // Raw. - D3D12_ROOT_PARAMETER stretch_root_parameters[3]; - stretch_root_parameters[0].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - stretch_root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; - D3D12_DESCRIPTOR_RANGE stretch_root_texture_range; - stretch_root_texture_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - stretch_root_texture_range.NumDescriptors = 1; - stretch_root_texture_range.BaseShaderRegister = 0; - stretch_root_texture_range.RegisterSpace = 0; - stretch_root_texture_range.OffsetInDescriptorsFromTableStart = 0; - stretch_root_parameters[0].DescriptorTable.pDescriptorRanges = - &stretch_root_texture_range; - stretch_root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - D3D12_STATIC_SAMPLER_DESC stretch_sampler_desc; - stretch_sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - stretch_sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - stretch_sampler_desc.MipLODBias = 0.0f; - stretch_sampler_desc.MaxAnisotropy = 1; - stretch_sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; - stretch_sampler_desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; - stretch_sampler_desc.MinLOD = 0.0f; - stretch_sampler_desc.MaxLOD = 0.0f; - stretch_sampler_desc.ShaderRegister = 0; - stretch_sampler_desc.RegisterSpace = 0; - stretch_sampler_desc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - D3D12_ROOT_SIGNATURE_DESC stretch_root_desc; - stretch_root_desc.NumParameters = 1; - stretch_root_desc.pParameters = stretch_root_parameters; - stretch_root_desc.NumStaticSamplers = 1; - stretch_root_desc.pStaticSamplers = &stretch_sampler_desc; - stretch_root_desc.Flags = - D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS; - stretch_root_signature_ = - ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc); - if (stretch_root_signature_ == nullptr) { - XELOGE("Failed to create the front buffer stretch root signature"); - return X_STATUS_UNSUCCESSFUL; - } - // Gamma. - stretch_root_parameters[1].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - stretch_root_parameters[1].DescriptorTable.NumDescriptorRanges = 1; - D3D12_DESCRIPTOR_RANGE stretch_root_gamma_ramp_range; - stretch_root_gamma_ramp_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - stretch_root_gamma_ramp_range.NumDescriptors = 1; - stretch_root_gamma_ramp_range.BaseShaderRegister = 1; - stretch_root_gamma_ramp_range.RegisterSpace = 0; - stretch_root_gamma_ramp_range.OffsetInDescriptorsFromTableStart = 0; - stretch_root_parameters[1].DescriptorTable.pDescriptorRanges = - &stretch_root_gamma_ramp_range; - stretch_root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - stretch_root_parameters[2].ParameterType = - D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - stretch_root_parameters[2].Constants.ShaderRegister = 0; - stretch_root_parameters[2].Constants.RegisterSpace = 0; - stretch_root_parameters[2].Constants.Num32BitValues = 1; - stretch_root_parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - stretch_root_desc.NumParameters = 3; - stretch_root_desc.pParameters = stretch_root_parameters; - stretch_gamma_root_signature_ = - ui::d3d12::util::CreateRootSignature(*d3d12_provider, stretch_root_desc); - if (stretch_gamma_root_signature_ == nullptr) { - XELOGE( - "Failed to create the gamma-correcting front buffer stretch root " - "signature"); - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - - // Create the stretch pipelines. - D3D12_GRAPHICS_PIPELINE_STATE_DESC stretch_pipeline_desc = {}; - stretch_pipeline_desc.pRootSignature = stretch_root_signature_; - stretch_pipeline_desc.VS.pShaderBytecode = shaders::fullscreen_tc_vs; - stretch_pipeline_desc.VS.BytecodeLength = sizeof(shaders::fullscreen_tc_vs); - stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_ps; - stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_ps); - // The shader will set alpha to 1, don't use output-merger to preserve it. - stretch_pipeline_desc.BlendState.RenderTarget[0].RenderTargetWriteMask = - D3D12_COLOR_WRITE_ENABLE_ALL; - stretch_pipeline_desc.SampleMask = UINT_MAX; - stretch_pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; - stretch_pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; - stretch_pipeline_desc.RasterizerState.DepthClipEnable = TRUE; - stretch_pipeline_desc.PrimitiveTopologyType = - D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - stretch_pipeline_desc.NumRenderTargets = 1; - stretch_pipeline_desc.RTVFormats[0] = - ui::d3d12::D3D12Context::kSwapChainFormat; - stretch_pipeline_desc.SampleDesc.Count = 1; - if (FAILED(device->CreateGraphicsPipelineState( - &stretch_pipeline_desc, IID_PPV_ARGS(&stretch_pipeline_)))) { - XELOGE("Failed to create the front buffer stretch pipeline"); - stretch_gamma_root_signature_->Release(); - stretch_gamma_root_signature_ = nullptr; - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - stretch_pipeline_desc.pRootSignature = stretch_gamma_root_signature_; - stretch_pipeline_desc.PS.pShaderBytecode = shaders::stretch_gamma_ps; - stretch_pipeline_desc.PS.BytecodeLength = sizeof(shaders::stretch_gamma_ps); - if (FAILED(device->CreateGraphicsPipelineState( - &stretch_pipeline_desc, IID_PPV_ARGS(&stretch_gamma_pipeline_)))) { - XELOGE( - "Failed to create the gamma-correcting front buffer stretch pipeline"); - stretch_pipeline_->Release(); - stretch_pipeline_ = nullptr; - stretch_gamma_root_signature_->Release(); - stretch_gamma_root_signature_ = nullptr; - stretch_root_signature_->Release(); - stretch_root_signature_ = nullptr; - return X_STATUS_UNSUCCESSFUL; - } - - return X_STATUS_SUCCESS; -} - -void D3D12GraphicsSystem::Shutdown() { - ui::d3d12::util::ReleaseAndNull(stretch_gamma_pipeline_); - ui::d3d12::util::ReleaseAndNull(stretch_pipeline_); - ui::d3d12::util::ReleaseAndNull(stretch_gamma_root_signature_); - ui::d3d12::util::ReleaseAndNull(stretch_root_signature_); - - GraphicsSystem::Shutdown(); -} - -std::unique_ptr D3D12GraphicsSystem::Capture() { - auto d3d12_command_processor = - static_cast(command_processor()); - if (!d3d12_command_processor) { - return nullptr; - } - return d3d12_command_processor->Capture(); -} - -void D3D12GraphicsSystem::StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - ID3D12GraphicsCommandList* command_list) { - if (gamma_ramp_handle != nullptr) { - command_list->SetPipelineState(stretch_gamma_pipeline_); - command_list->SetGraphicsRootSignature(stretch_gamma_root_signature_); - command_list->SetGraphicsRootDescriptorTable(1, *gamma_ramp_handle); - command_list->SetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, 0); - } else { - command_list->SetPipelineState(stretch_pipeline_); - command_list->SetGraphicsRootSignature(stretch_root_signature_); - } - command_list->SetGraphicsRootDescriptorTable(0, handle); - command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - command_list->DrawInstanced(3, 1, 0, 0); -} - -void D3D12GraphicsSystem::StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - DeferredCommandList& command_list) { - if (gamma_ramp_handle != nullptr) { - command_list.D3DSetPipelineState(stretch_gamma_pipeline_); - command_list.D3DSetGraphicsRootSignature(stretch_gamma_root_signature_); - command_list.D3DSetGraphicsRootDescriptorTable(1, *gamma_ramp_handle); - command_list.D3DSetGraphicsRoot32BitConstants(2, 1, &gamma_ramp_inv_size, - 0); - } else { - command_list.D3DSetPipelineState(stretch_pipeline_); - command_list.D3DSetGraphicsRootSignature(stretch_root_signature_); - } - command_list.D3DSetGraphicsRootDescriptorTable(0, handle); - command_list.D3DIASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - command_list.D3DDrawInstanced(3, 1, 0, 0); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } std::unique_ptr @@ -248,69 +54,6 @@ D3D12GraphicsSystem::CreateCommandProcessor() { new D3D12CommandProcessor(this, kernel_state_)); } -void D3D12GraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (display_context_->WasLost()) { - // We're crashing. Cheese it. - return; - } - - if (!command_processor_) { - return; - } - - auto& swap_state = command_processor_->swap_state(); - ID3D12DescriptorHeap* swap_srv_heap; - { - std::lock_guard lock(swap_state.mutex); - swap_state.pending = false; - swap_srv_heap = reinterpret_cast( - swap_state.front_buffer_texture); - } - if (swap_srv_heap == nullptr) { - // Not ready yet. - return; - } - - uint32_t window_width, window_height; - display_context_->GetSwapChainSize(window_width, window_height); - - int32_t target_x, target_y; - uint32_t target_width, target_height; - draw_util::GetPresentArea(swap_state.width, swap_state.height, window_width, - window_height, target_x, target_y, target_width, - target_height); - // For safety. - target_x = clamp(target_x, int32_t(D3D12_VIEWPORT_BOUNDS_MIN), - int32_t(D3D12_VIEWPORT_BOUNDS_MAX)); - target_y = clamp(target_y, int32_t(D3D12_VIEWPORT_BOUNDS_MIN), - int32_t(D3D12_VIEWPORT_BOUNDS_MAX)); - target_width = std::min( - target_width, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_x)); - target_height = std::min( - target_height, uint32_t(int32_t(D3D12_VIEWPORT_BOUNDS_MAX) - target_y)); - - auto command_list = display_context_->GetSwapCommandList(); - // Assuming the window has already been cleared to the needed letterbox color. - D3D12_VIEWPORT viewport; - viewport.TopLeftX = float(target_x); - viewport.TopLeftY = float(target_y); - viewport.Width = float(target_width); - viewport.Height = float(target_height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 0.0f; - command_list->RSSetViewports(1, &viewport); - D3D12_RECT scissor; - scissor.left = 0; - scissor.top = 0; - scissor.right = window_width; - scissor.bottom = window_height; - command_list->RSSetScissorRects(1, &scissor); - command_list->SetDescriptorHeaps(1, &swap_srv_heap); - StretchTextureToFrontBuffer( - swap_srv_heap->GetGPUDescriptorHandleForHeapStart(), nullptr, 0.0f, - command_list); -} - } // namespace d3d12 } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.h b/src/xenia/gpu/d3d12/d3d12_graphics_system.h index 00faeb34f..249cc3ffa 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.h +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.h @@ -15,7 +15,6 @@ #include "xenia/gpu/command_processor.h" #include "xenia/gpu/d3d12/deferred_command_list.h" #include "xenia/gpu/graphics_system.h" -#include "xenia/ui/d3d12/d3d12_context.h" namespace xe { namespace gpu { @@ -31,37 +30,11 @@ class D3D12GraphicsSystem : public GraphicsSystem { std::string name() const override; X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; - - std::unique_ptr Capture() override; - - // Draws a texture covering the entire viewport to the render target currently - // bound on the specified command list (in D3D12Context::kSwapChainFormat). - // This changes the current pipeline, graphics root signature and primitive - // topology. The gamma ramp texture must be 1D if present at all, for linear - // space, pass nullptr as the gamma ramp. - void StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - ID3D12GraphicsCommandList* command_list); - void StretchTextureToFrontBuffer( - D3D12_GPU_DESCRIPTOR_HANDLE handle, - D3D12_GPU_DESCRIPTOR_HANDLE* gamma_ramp_handle, float gamma_ramp_inv_size, - DeferredCommandList& command_list); + ui::WindowedAppContext* app_context, + bool is_surface_required) override; protected: std::unique_ptr CreateCommandProcessor() override; - - void Swap(xe::ui::UIEvent* e) override; - - private: - ui::d3d12::D3D12Context* display_context_ = nullptr; - - ID3D12RootSignature* stretch_root_signature_ = nullptr; - ID3D12RootSignature* stretch_gamma_root_signature_ = nullptr; - ID3D12PipelineState* stretch_pipeline_ = nullptr; - ID3D12PipelineState* stretch_gamma_pipeline_ = nullptr; }; } // namespace d3d12 diff --git a/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc b/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc index ec1e576b0..a806546a1 100644 --- a/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_primitive_processor.cc @@ -33,7 +33,7 @@ bool D3D12PrimitiveProcessor::Initialize() { return false; } frame_index_buffer_pool_ = std::make_unique( - command_processor_.GetD3D12Context().GetD3D12Provider(), + command_processor_.GetD3D12Provider(), std::max(size_t(kMinRequiredConvertedIndexBufferSize), ui::GraphicsUploadBufferPool::kDefaultPageSize)); return true; @@ -90,7 +90,7 @@ bool D3D12PrimitiveProcessor::InitializeBuiltin16BitIndexBuffer( assert_null(builtin_index_buffer_upload_); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC resource_desc; diff --git a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc index d72e37428..61b8bb83f 100644 --- a/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc +++ b/src/xenia/gpu/d3d12/d3d12_render_target_cache.cc @@ -215,7 +215,7 @@ D3D12RenderTargetCache::~D3D12RenderTargetCache() { Shutdown(true); } bool D3D12RenderTargetCache::Initialize() { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); if (cvars::render_target_path_d3d12 == "rtv") { @@ -1298,7 +1298,7 @@ bool D3D12RenderTargetCache::Update(bool is_rasterization_done, void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1311,7 +1311,7 @@ void D3D12RenderTargetCache::WriteEdramRawSRVDescriptor( void D3D12RenderTargetCache::WriteEdramRawUAVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1339,7 +1339,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2SRVDescriptor( return; } const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1366,7 +1366,7 @@ void D3D12RenderTargetCache::WriteEdramUintPow2UAVDescriptor( return; } const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, @@ -1668,8 +1668,9 @@ bool D3D12RenderTargetCache::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc(edram_snapshot_download_buffer_desc, xenos::kEdramSizeBytes, D3D12_RESOURCE_FLAG_NONE); - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesReadback, provider.GetHeapFlagCreateNotZeroed(), @@ -1721,7 +1722,8 @@ void D3D12RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) { // Create the buffer - will be used for copying to either a 32-bit 1280x2048 // render target or the EDRAM buffer. - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (!edram_snapshot_restore_pool_) { edram_snapshot_restore_pool_ = std::make_unique( @@ -1966,8 +1968,7 @@ DXGI_FORMAT D3D12RenderTargetCache::GetDepthSRVStencilDXGIFormat( RenderTargetCache::RenderTarget* D3D12RenderTargetCache::CreateRenderTarget( RenderTargetKey key) { - ID3D12Device* device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); D3D12_RESOURCE_DESC resource_desc; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -4345,8 +4346,7 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) { // *************************************************************************** ID3D12PipelineState* const* pipelines; - ID3D12Device* device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); D3D12_INPUT_ELEMENT_DESC pipeline_input_element_desc; pipeline_input_element_desc.SemanticName = "POSITION"; pipeline_input_element_desc.SemanticIndex = 0; @@ -4516,7 +4516,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears( assert_true(GetPath() == Path::kHostRenderTargets); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); uint64_t current_submission = command_processor_.GetCurrentSubmission(); DeferredCommandList& command_list = @@ -6476,8 +6476,8 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline( // Pipeline // *************************************************************************** ID3D12PipelineState* pipeline = ui::d3d12::util::CreateComputePipeline( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - built_shader_.data(), built_shader_size_bytes, + command_processor_.GetD3D12Provider().GetDevice(), built_shader_.data(), + built_shader_size_bytes, key.is_depth ? dump_root_signature_depth_ : dump_root_signature_color_); const char* format_name = key.is_depth @@ -6561,7 +6561,7 @@ void D3D12RenderTargetCache::DumpRenderTargets(uint32_t dump_base, // 32bpp and 64bpp. size_t edram_uav_indices[2] = {SIZE_MAX, SIZE_MAX}; const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); if (!bindless_resources_used_) { if (any_sources_32bpp_64bpp[0]) { edram_uav_indices[0] = current_temporary_descriptors_cpu_.size(); diff --git a/src/xenia/gpu/d3d12/d3d12_shared_memory.cc b/src/xenia/gpu/d3d12/d3d12_shared_memory.cc index fd521da54..e946a3319 100644 --- a/src/xenia/gpu/d3d12/d3d12_shared_memory.cc +++ b/src/xenia/gpu/d3d12/d3d12_shared_memory.cc @@ -43,7 +43,7 @@ bool D3D12SharedMemory::Initialize() { InitializeCommon(); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); D3D12_RESOURCE_DESC buffer_desc; @@ -215,8 +215,9 @@ void D3D12SharedMemory::CommitUAVWritesAndTransitionBuffer( void D3D12SharedMemory::WriteRawSRVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -226,8 +227,9 @@ void D3D12SharedMemory::WriteRawSRVDescriptor( void D3D12SharedMemory::WriteRawUAVDescriptor( D3D12_CPU_DESCRIPTOR_HANDLE handle) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -252,8 +254,9 @@ void D3D12SharedMemory::WriteUintPow2SRVDescriptor( assert_unhandled_case(element_size_bytes_pow2); return; } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -278,8 +281,9 @@ void D3D12SharedMemory::WriteUintPow2UAVDescriptor( assert_unhandled_case(element_size_bytes_pow2); return; } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); device->CopyDescriptorsSimple( 1, handle, provider.OffsetViewDescriptor(buffer_descriptor_heap_start_, @@ -298,8 +302,9 @@ bool D3D12SharedMemory::InitializeTraceSubmitDownloads() { ui::d3d12::util::FillBufferResourceDesc( download_buffer_desc, download_page_count << page_size_log2(), D3D12_RESOURCE_FLAG_NONE); - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (FAILED(device->CreateCommittedResource( &ui::d3d12::util::kHeapPropertiesReadback, provider.GetHeapFlagCreateNotZeroed(), &download_buffer_desc, @@ -365,7 +370,7 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange( << host_gpu_memory_sparse_granularity_log2(); const ui::d3d12::D3D12Provider& provider = - command_processor_.GetD3D12Context().GetD3D12Provider(); + command_processor_.GetD3D12Provider(); ID3D12Device* device = provider.GetDevice(); ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 3eb63f172..f8617355a 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -87,7 +87,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor, register_file_(register_file), render_target_cache_(render_target_cache), bindless_resources_used_(bindless_resources_used) { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); bool edram_rov_used = render_target_cache.GetPath() == RenderTargetCache::Path::kPixelShaderInterlock; @@ -109,7 +110,8 @@ PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor, PipelineCache::~PipelineCache() { Shutdown(); } bool PipelineCache::Initialize() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); // Initialize the command processor thread DXIL objects. dxbc_converter_ = nullptr; @@ -414,7 +416,8 @@ void PipelineCache::InitializeShaderStorage( std::mutex shaders_failed_to_translate_mutex; std::vector shaders_failed_to_translate; auto shader_translation_thread_function = [&]() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); StringBuffer ucode_disasm_buffer; DxbcShaderTranslator translator( provider.GetAdapterVendorID(), bindless_resources_used_, @@ -1241,7 +1244,8 @@ bool PipelineCache::TranslateAnalyzedShader( } // Disassemble the shader for dumping. - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (cvars::d3d12_dxbc_disasm_dxilconv) { translation.DisassembleDxbcAndDxil(provider, cvars::d3d12_dxbc_disasm, dxbc_converter, dxc_utils, dxc_compiler); @@ -2052,8 +2056,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline( } // Create the D3D12 pipeline state object. - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); ID3D12PipelineState* state; if (FAILED(device->CreateGraphicsPipelineState(&state_desc, IID_PPV_ARGS(&state)))) { diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index f2098c9df..3c03131e3 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -869,8 +869,9 @@ TextureCache::TextureCache(D3D12CommandProcessor& command_processor, TextureCache::~TextureCache() { Shutdown(); } bool TextureCache::Initialize() { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); if (IsDrawResolutionScaled()) { // Buffers not used yet - no need aliasing barriers to change ownership of @@ -1444,7 +1445,8 @@ void TextureCache::WriteActiveTextureBindfulSRV( } } } - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); D3D12_CPU_DESCRIPTOR_HANDLE source_handle; if (descriptor_index != UINT32_MAX) { assert_not_null(texture); @@ -1622,8 +1624,7 @@ void TextureCache::WriteSampler(SamplerParameters parameters, desc.MinLOD = float(parameters.mip_min_level); // Maximum mip level is in the texture resource itself. desc.MaxLOD = FLT_MAX; - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); device->CreateSampler(&desc, handle); } @@ -1712,8 +1713,9 @@ bool TextureCache::EnsureScaledResolveMemoryCommitted( uint64_t last_scaled = uint64_t(start_unscaled + (length_unscaled - 1)) * draw_resolution_scale_area; - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); // Ensure GPU virtual memory for buffers that may be used to access the range // is allocated - buffers are created. Always creating both buffers for all @@ -1943,8 +1945,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2SRV( scaled_resolve_2gb_buffers_[buffer_index]; assert_not_null(buffer); ui::d3d12::util::CreateBufferTypedSRV( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - handle, buffer->resource(), + command_processor_.GetD3D12Provider().GetDevice(), handle, + buffer->resource(), ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2), uint32_t(scaled_resolve_current_range_length_scaled_ >> element_size_bytes_pow2), @@ -1961,8 +1963,8 @@ void TextureCache::CreateCurrentScaledResolveRangeUintPow2UAV( scaled_resolve_2gb_buffers_[buffer_index]; assert_not_null(buffer); ui::d3d12::util::CreateBufferTypedUAV( - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(), - handle, buffer->resource(), + command_processor_.GetD3D12Provider().GetDevice(), handle, + buffer->resource(), ui::d3d12::util::GetUintPow2DXGIFormat(element_size_bytes_pow2), uint32_t(scaled_resolve_current_range_length_scaled_ >> element_size_bytes_pow2), @@ -2254,8 +2256,9 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { // Untiling through a buffer instead of using unordered access because copying // is not done that often. desc.Flags = D3D12_RESOURCE_FLAG_NONE; - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); - auto device = provider.GetDevice(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); + ID3D12Device* device = provider.GetDevice(); // Assuming untiling will be the next operation. D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST; ID3D12Resource* resource; @@ -2317,9 +2320,9 @@ bool TextureCache::LoadTextureData(Texture* texture) { return true; } - auto& command_list = command_processor_.GetDeferredCommandList(); - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + DeferredCommandList& command_list = + command_processor_.GetDeferredCommandList(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); // Get the pipeline. LoadMode load_mode = GetLoadMode(texture->key); @@ -2875,8 +2878,7 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture, host_swizzle | D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES; - auto device = - command_processor_.GetD3D12Context().GetD3D12Provider().GetDevice(); + ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice(); uint32_t descriptor_index; if (bindless_resources_used_) { descriptor_index = @@ -2928,7 +2930,8 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture, D3D12_CPU_DESCRIPTOR_HANDLE TextureCache::GetTextureDescriptorCPUHandle( uint32_t descriptor_index) const { - auto& provider = command_processor_.GetD3D12Context().GetD3D12Provider(); + const ui::d3d12::D3D12Provider& provider = + command_processor_.GetD3D12Provider(); if (bindless_resources_used_) { return provider.OffsetViewDescriptor( command_processor_.GetViewBindlessHeapCPUStart(), descriptor_index); diff --git a/src/xenia/gpu/draw_util.cc b/src/xenia/gpu/draw_util.cc index 6cb28c9a4..83ea6601d 100644 --- a/src/xenia/gpu/draw_util.cc +++ b/src/xenia/gpu/draw_util.cc @@ -23,6 +23,7 @@ #include "xenia/gpu/texture_info.h" #include "xenia/gpu/texture_util.h" #include "xenia/gpu/xenos.h" +#include "xenia/ui/graphics_util.h" // Very prominent in 545407F2. DEFINE_bool( @@ -33,85 +34,10 @@ DEFINE_bool( "for certain games to display the scene graphics).", "GPU"); -DEFINE_bool( - present_rescale, true, - "Whether to rescale the image, instead of maintaining the original pixel " - "size, when presenting to the window. When this is disabled, other " - "positioning options are ignored.", - "GPU"); -DEFINE_bool( - present_letterbox, true, - "Maintain aspect ratio when stretching by displaying bars around the image " - "when there's no more overscan area to crop out.", - "GPU"); -// https://github.com/MonoGame/MonoGame/issues/4697#issuecomment-217779403 -// Using the value from DirectXTK (5% cropped out from each side, thus 90%), -// which is not exactly the Xbox One title-safe area, but close, and within the -// action-safe area: -// https://github.com/microsoft/DirectXTK/blob/1e80a465c6960b457ef9ab6716672c1443a45024/Src/SimpleMath.cpp#L144 -// XNA TitleSafeArea is 80%, but it's very conservative, designed for CRT, and -// is the title-safe area rather than the action-safe area. -// 90% is also exactly the fraction of 16:9 height in 16:10. -DEFINE_int32( - present_safe_area_x, 90, - "Percentage of the image width that can be kept when presenting to " - "maintain aspect ratio without letterboxing or stretching.", - "GPU"); -DEFINE_int32( - present_safe_area_y, 90, - "Percentage of the image height that can be kept when presenting to " - "maintain aspect ratio without letterboxing or stretching.", - "GPU"); - namespace xe { namespace gpu { namespace draw_util { -int32_t FloatToD3D11Fixed16p8(float f32) { - // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#3.2.4.1%20FLOAT%20-%3E%20Fixed%20Point%20Integer - // Early exit tests. - // n == NaN || n.unbiasedExponent < -f-1 -> 0 . 0 - if (!(std::abs(f32) >= 1.0f / 512.0f)) { - return 0; - } - // n >= (2^(i-1)-2^-f) -> 2^(i-1)-1 . 2^f-1 - if (f32 >= 32768.0f - 1.0f / 256.0f) { - return (1 << 23) - 1; - } - // n <= -2^(i-1) -> -2^(i-1) . 0 - if (f32 <= -32768.0f) { - return -32768 * 256; - } - uint32_t f32_bits = *reinterpret_cast(&f32); - // Copy float32 mantissa bits [22:0] into corresponding bits [22:0] of a - // result buffer that has at least 24 bits total storage (before reaching - // rounding step further below). This includes one bit for the hidden 1. - // Set bit [23] (float32 hidden bit). - // Clear bits [31:24]. - union { - int32_t s; - uint32_t u; - } result; - result.u = (f32_bits & ((1 << 23) - 1)) | (1 << 23); - // If the sign bit is set in the float32 number (negative), then take the 2's - // component of the entire set of bits. - if ((f32_bits >> 31) != 0) { - result.s = -result.s; - } - // Final calculation: extraBits = (mantissa - f) - n.unbiasedExponent - // (guaranteed to be >= 0). - int32_t exponent = int32_t((f32_bits >> 23) & 255) - 127; - uint32_t extra_bits = uint32_t(15 - exponent); - if (extra_bits) { - // Round the 32-bit value to a decimal that is extraBits to the left of - // the LSB end, using nearest-even. - result.u += (1 << (extra_bits - 1)) - 1 + ((result.u >> extra_bits) & 1); - // Shift right by extraBits (sign extending). - result.s >>= extra_bits; - } - return result.s; -} - bool IsRasterizationPotentiallyDone(const RegisterFile& regs, bool primitive_polygonal) { // TODO(Triang3l): Investigate ModeControl::kIgnore better, with respect to @@ -746,7 +672,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory, regs.Get().pix_center ? 0.0f : 0.5f; int32_t vertices_fixed[6]; for (size_t i = 0; i < xe::countof(vertices_fixed); ++i) { - vertices_fixed[i] = FloatToD3D11Fixed16p8( + vertices_fixed[i] = ui::FloatToD3D11Fixed16p8( xenos::GpuSwap(vertices_guest[i], fetch.endian) + half_pixel_offset); } // Inclusive. @@ -1151,87 +1077,6 @@ ResolveCopyShaderIndex ResolveInfo::GetCopyShader( return shader; } -void GetPresentArea(uint32_t source_width, uint32_t source_height, - uint32_t window_width, uint32_t window_height, - int32_t& target_x_out, int32_t& target_y_out, - uint32_t& target_width_out, uint32_t& target_height_out) { - if (!cvars::present_rescale) { - target_x_out = (int32_t(window_width) - int32_t(source_width)) / 2; - target_y_out = (int32_t(window_height) - int32_t(source_height)) / 2; - target_width_out = source_width; - target_height_out = source_height; - return; - } - // Prevent division by zero. - if (!source_width || !source_height) { - target_x_out = 0; - target_y_out = 0; - target_width_out = 0; - target_height_out = 0; - return; - } - if (uint64_t(window_width) * source_height > - uint64_t(source_width) * window_height) { - // The window is wider that the source - crop along Y, then letterbox or - // stretch along X. - uint32_t present_safe_area; - if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) { - present_safe_area = uint32_t(cvars::present_safe_area_y); - } else { - present_safe_area = 100; - } - uint32_t target_height = - uint32_t(uint64_t(window_width) * source_height / source_width); - bool letterbox = false; - if (target_height * present_safe_area > window_height * 100) { - // Don't crop out more than the safe area margin - letterbox or stretch. - target_height = window_height * 100 / present_safe_area; - letterbox = true; - } - if (letterbox && cvars::present_letterbox) { - uint32_t target_width = - uint32_t(uint64_t(source_width) * window_height * 100 / - (source_height * present_safe_area)); - target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2; - target_width_out = target_width; - } else { - target_x_out = 0; - target_width_out = window_width; - } - target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2; - target_height_out = target_height; - } else { - // The window is taller than the source - crop along X, then letterbox or - // stretch along Y. - uint32_t present_safe_area; - if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) { - present_safe_area = uint32_t(cvars::present_safe_area_x); - } else { - present_safe_area = 100; - } - uint32_t target_width = - uint32_t(uint64_t(window_height) * source_width / source_height); - bool letterbox = false; - if (target_width * present_safe_area > window_width * 100) { - // Don't crop out more than the safe area margin - letterbox or stretch. - target_width = window_width * 100 / present_safe_area; - letterbox = true; - } - if (letterbox && cvars::present_letterbox) { - uint32_t target_height = - uint32_t(uint64_t(source_height) * window_width * 100 / - (source_width * present_safe_area)); - target_y_out = (int32_t(window_height) - int32_t(target_height)) / 2; - target_height_out = target_height; - } else { - target_y_out = 0; - target_height_out = window_height; - } - target_x_out = (int32_t(window_width) - int32_t(target_width)) / 2; - target_width_out = target_width; - } -} - } // namespace draw_util } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/draw_util.h b/src/xenia/gpu/draw_util.h index 24f58b23a..39d430676 100644 --- a/src/xenia/gpu/draw_util.h +++ b/src/xenia/gpu/draw_util.h @@ -25,15 +25,6 @@ namespace xe { namespace gpu { namespace draw_util { -// For estimating coverage extents from vertices. This may give results that are -// different than what the host GPU will actually draw (this is the reference -// conversion with 1/2 ULP accuracy, but Direct3D 11 permits 0.6 ULP tolerance -// in floating point to fixed point conversion), but is enough to tie-break -// vertices at pixel centers (due to the half-pixel offset applied to integer -// coordinates incorrectly, for instance) with some error tolerance near 0.5, -// for use with the top-left rasterization rule later. -int32_t FloatToD3D11Fixed16p8(float f32); - // Polygonal primitive types (not including points and lines) are rasterized as // triangles, have front and back faces, and also support face culling and fill // modes (polymode_front_ptype, polymode_back_ptype). Other primitive types are diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index 6ffab9150..b5470fd0a 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -2,13 +2,19 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/gpu/graphics_system.h" +#include +#include +#include +#include +#include + #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" @@ -48,70 +54,40 @@ GraphicsSystem::~GraphicsSystem() = default; X_STATUS GraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + [[maybe_unused]] bool is_surface_required) { memory_ = processor->memory(); processor_ = processor; kernel_state_ = kernel_state; - target_window_ = target_window; + app_context_ = app_context; - // Initialize display and rendering context. - // This must happen on the UI thread. - std::unique_ptr processor_context = nullptr; if (provider_) { - // Setup the context the command processor will do all its drawing in. - bool contexts_initialized = true; - processor_context = provider()->CreateOffscreenContext(); - if (processor_context) { - if (target_window_) { - if (!target_window_->app_context().CallInUIThreadSynchronous([&]() { - // Create the context used for presentation. - assert_null(target_window->context()); - target_window_->set_context( - provider_->CreateContext(target_window_)); - })) { - contexts_initialized = false; - } - } + // Safe if either the UI thread call or the presenter creation fails. + if (app_context_) { + app_context_->CallInUIThreadSynchronous([this]() { + presenter_ = provider_->CreatePresenter( + [this](bool is_responsible, bool statically_from_ui_thread) { + OnHostGpuLossFromAnyThread(is_responsible); + }); + }); } else { - contexts_initialized = false; - } - if (!contexts_initialized) { - xe::FatalError( - "Unable to initialize graphics context. Xenia requires Vulkan " - "support.\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."); - return X_STATUS_UNSUCCESSFUL; + // May be needed for offscreen use, such as capturing the guest output + // image. + presenter_ = provider_->CreatePresenter( + [this](bool is_responsible, bool statically_from_ui_thread) { + OnHostGpuLossFromAnyThread(is_responsible); + }); } } // Create command processor. This will spin up a thread to process all // incoming ringbuffer packets. command_processor_ = CreateCommandProcessor(); - if (!command_processor_->Initialize(std::move(processor_context))) { + if (!command_processor_->Initialize()) { XELOGE("Unable to initialize command processor"); return X_STATUS_UNSUCCESSFUL; } - if (target_window) { - command_processor_->set_swap_request_handler( - [this]() { target_window_->Invalidate(); }); - - // Watch for paint requests to do our swap. - target_window->on_painting.AddListener( - [this](xe::ui::UIEvent* e) { Swap(e); }); - - // Watch for context lost events. - target_window->on_context_lost.AddListener( - [this](xe::ui::UIEvent* e) { Reset(); }); - } else { - command_processor_->set_swap_request_handler([]() {}); - } - // Let the processor know we want register access callbacks. memory_->AddVirtualMappedRange( 0x7FC80000, 0xFFFF0000, 0x0000FFFF, this, @@ -152,6 +128,7 @@ void GraphicsSystem::Shutdown() { if (command_processor_) { EndTracing(); command_processor_->Shutdown(); + command_processor_.reset(); } if (vsync_worker_thread_) { @@ -159,13 +136,35 @@ void GraphicsSystem::Shutdown() { vsync_worker_thread_->Wait(0, 0, 0, nullptr); vsync_worker_thread_.reset(); } + + if (presenter_) { + if (app_context_) { + app_context_->CallInUIThreadSynchronous([this]() { presenter_.reset(); }); + } + // If there's no app context (thus the presenter is owned by the thread that + // initialized the GraphicsSystem) or can't be queueing UI thread calls + // anymore, shutdown anyway. + presenter_.reset(); + } + + provider_.reset(); } -void GraphicsSystem::Reset() { - // TODO(DrChat): Reset the system. - XELOGI("Context lost; Reset invoked"); - Shutdown(); - +void GraphicsSystem::OnHostGpuLossFromAnyThread( + [[maybe_unused]] bool is_responsible) { + // TODO(Triang3l): Somehow gain exclusive ownership of the Provider (may be + // used by the command processor, the presenter, and possibly anything else, + // it's considered free-threaded, except for lifetime management which will be + // involved in this case) and reset it so a new host GPU API device is + // created. Then ask the command processor to reset itself in its thread, and + // ask the UI thread to reset the Presenter (the UI thread manages its + // lifetime - but if there's no WindowedAppContext, either don't reset it as + // in this case there's no user who needs uninterrupted gameplay, or somehow + // protect it with a mutex so any thread can be considered a UI thread and + // reset). + if (host_gpu_loss_reported_.test_and_set(std::memory_order_relaxed)) { + return; + } xe::FatalError("Graphics device lost (probably due to an internal error)"); } diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index 3fd7132e1..0434a5619 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,7 +11,10 @@ #define XENIA_GPU_GRAPHICS_SYSTEM_H_ #include +#include +#include #include +#include #include #include @@ -19,7 +22,9 @@ #include "xenia/gpu/register_file.h" #include "xenia/kernel/xthread.h" #include "xenia/memory.h" -#include "xenia/ui/window.h" +#include "xenia/ui/graphics_provider.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" namespace xe { @@ -41,14 +46,17 @@ class GraphicsSystem { cpu::Processor* processor() const { return processor_; } kernel::KernelState* kernel_state() const { return kernel_state_; } ui::GraphicsProvider* provider() const { return provider_.get(); } + ui::Presenter* presenter() const { return presenter_.get(); } virtual X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window); + ui::WindowedAppContext* app_context, + bool is_surface_required); virtual void Shutdown(); - virtual void Reset(); - virtual std::unique_ptr Capture() { return nullptr; } + // May be called from any thread any number of times, even during recovery + // from a device loss. + void OnHostGpuLossFromAnyThread(bool is_responsible); RegisterFile* register_file() { return ®ister_file_; } CommandProcessor* command_processor() const { @@ -91,12 +99,11 @@ class GraphicsSystem { void WriteRegister(uint32_t addr, uint32_t value); void MarkVblank(); - virtual void Swap(xe::ui::UIEvent* e) = 0; Memory* memory_ = nullptr; cpu::Processor* processor_ = nullptr; kernel::KernelState* kernel_state_ = nullptr; - ui::Window* target_window_ = nullptr; + ui::WindowedAppContext* app_context_ = nullptr; std::unique_ptr provider_; uint32_t interrupt_callback_ = 0; @@ -109,6 +116,11 @@ class GraphicsSystem { std::unique_ptr command_processor_; bool paused_ = false; + + private: + std::unique_ptr presenter_; + + std::atomic_flag host_gpu_loss_reported_; }; } // namespace gpu diff --git a/src/xenia/gpu/null/null_command_processor.cc b/src/xenia/gpu/null/null_command_processor.cc index 5d1e7a9b0..e706d5bbf 100644 --- a/src/xenia/gpu/null/null_command_processor.cc +++ b/src/xenia/gpu/null/null_command_processor.cc @@ -31,9 +31,9 @@ void NullCommandProcessor::ShutdownContext() { return CommandProcessor::ShutdownContext(); } -void NullCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) {} +void NullCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) {} Shader* NullCommandProcessor::LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, diff --git a/src/xenia/gpu/null/null_command_processor.h b/src/xenia/gpu/null/null_command_processor.h index 0285b1ed2..11c829018 100644 --- a/src/xenia/gpu/null/null_command_processor.h +++ b/src/xenia/gpu/null/null_command_processor.h @@ -33,8 +33,8 @@ class NullCommandProcessor : public CommandProcessor { bool SetupContext() override; void ShutdownContext() override; - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) override; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, diff --git a/src/xenia/gpu/null/null_graphics_system.cc b/src/xenia/gpu/null/null_graphics_system.cc index c6df3ff09..57d5e958f 100644 --- a/src/xenia/gpu/null/null_graphics_system.cc +++ b/src/xenia/gpu/null/null_graphics_system.cc @@ -23,31 +23,20 @@ NullGraphicsSystem::~NullGraphicsSystem() {} X_STATUS NullGraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) { + ui::WindowedAppContext* app_context, + bool is_surface_required) { // This is a null graphics system, but we still setup vulkan because UI needs // it through us :| - provider_ = xe::ui::vulkan::VulkanProvider::Create(); - - return GraphicsSystem::Setup(processor, kernel_state, target_window); + provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } -void NullGraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); } - std::unique_ptr NullGraphicsSystem::CreateCommandProcessor() { return std::unique_ptr( new NullCommandProcessor(this, kernel_state_)); } -void NullGraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (!command_processor_) { - return; - } - - auto& swap_state = command_processor_->swap_state(); - std::lock_guard lock(swap_state.mutex); - swap_state.pending = false; -} - } // namespace null } // namespace gpu } // namespace xe \ No newline at end of file diff --git a/src/xenia/gpu/null/null_graphics_system.h b/src/xenia/gpu/null/null_graphics_system.h index 640a0424f..d5b8d32b9 100644 --- a/src/xenia/gpu/null/null_graphics_system.h +++ b/src/xenia/gpu/null/null_graphics_system.h @@ -29,13 +29,11 @@ class NullGraphicsSystem : public GraphicsSystem { std::string name() const override { return "null"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; + ui::WindowedAppContext* app_context, + bool is_surface_required) override; private: std::unique_ptr CreateCommandProcessor() override; - - void Swap(xe::ui::UIEvent* e) override; }; } // namespace null diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 27e817f44..bfdb70789 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -39,6 +39,7 @@ project("xenia-gpu-shader-compiler") "spirv-tools", "xenia-base", "xenia-gpu", + "xenia-ui", "xenia-ui-spirv", }) defines({ diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl new file mode 100644 index 000000000..8ba176f73 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl.cs.hlsl @@ -0,0 +1,2 @@ +float XeApplyGammaGetAlpha(float3 color) { return 1.0f; } +#include "apply_gamma_pwl.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli b/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli new file mode 100644 index 000000000..a77c85460 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl.hlsli @@ -0,0 +1,41 @@ +// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally. + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_apply_gamma_size; +}; +RWTexture2D xe_apply_gamma_dest : register(u0); +Texture2D xe_apply_gamma_source : register(t0); +Buffer xe_apply_gamma_ramp : register(t1); + +float XeApplyPWLGamma(uint input, uint component) { + // TODO(Triang3l): If this is ever used for gamma other than 128 entries for a + // 10bpc front buffer, handle the increment from DC_LUTA/B_CONTROL. Currently + // assuming it's 2^3 = 8, or 1024 / 128. + // output = base + (multiplier * delta) / increment + // https://developer.amd.com/wordpress/media/2012/10/RRG-216M56-03oOEM.pdf + // The lower 6 bits of the base and the delta are 0 (though enforcing that in + // the shader is not necessary). + // The `(multiplier * delta) / increment` part may result in a nonzero value + // in the lower 6 bits of the result, however, so doing `* (1.0f / 64.0f)` + // instead of `>> 6` to preserve them (if the render target is 16bpc rather + // than 10bpc, for instance). + uint2 ramp_value = xe_apply_gamma_ramp[(input >> 3u) * 3u + component]; + return saturate((float(ramp_value.x) + + float((input & 7u) * ramp_value.y) * (1.0f / 8.0f)) * + (1.0f / (64.0f * 1023.0f))); +} + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) { + return; + } + // UNORM conversion according to the Direct3D 10+ rules. + uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 1023.0f + 0.5f); + // The ramp is BGR, not RGB. + float3 output = float3(XeApplyPWLGamma(input.r, 2u), + XeApplyPWLGamma(input.g, 1u), + XeApplyPWLGamma(input.b, 0u)); + xe_apply_gamma_dest[xe_thread_id.xy] = + float4(output, XeApplyGammaGetAlpha(output)); +} diff --git a/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl new file mode 100644 index 000000000..3a6bb4f9b --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_pwl_fxaa_luma.cs.hlsl @@ -0,0 +1,5 @@ +// Perceptual luminance for FXAA. +float XeApplyGammaGetAlpha(float3 color) { + return dot(color, float3(0.299, 0.587, 0.114)); +} +#include "apply_gamma_pwl.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl new file mode 100644 index 000000000..94b43ddd8 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table.cs.hlsl @@ -0,0 +1,2 @@ +float XeApplyGammaGetAlpha(float3 color) { return 1.0f; } +#include "apply_gamma_table.hlsli" diff --git a/src/xenia/gpu/shaders/apply_gamma_table.hlsli b/src/xenia/gpu/shaders/apply_gamma_table.hlsli new file mode 100644 index 000000000..7f43a9567 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table.hlsli @@ -0,0 +1,23 @@ +// float XeApplyGammaGetAlpha(float3 color) needs to be specified externally. + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_apply_gamma_size; +}; +RWTexture2D xe_apply_gamma_dest : register(u0); +Texture2D xe_apply_gamma_source : register(t0); +Buffer xe_apply_gamma_ramp : register(t1); + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_apply_gamma_size)) { + return; + } + // UNORM conversion according to the Direct3D 10+ rules. + uint3 input = uint3(xe_apply_gamma_source[xe_thread_id.xy] * 255.0f + 0.5f); + // The ramp is BGR, not RGB. + float3 output = float3(xe_apply_gamma_ramp[input.r].b, + xe_apply_gamma_ramp[input.g].g, + xe_apply_gamma_ramp[input.b].r); + xe_apply_gamma_dest[xe_thread_id.xy] = + float4(output, XeApplyGammaGetAlpha(output)); +} diff --git a/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl b/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl new file mode 100644 index 000000000..16b2593f2 --- /dev/null +++ b/src/xenia/gpu/shaders/apply_gamma_table_fxaa_luma.cs.hlsl @@ -0,0 +1,5 @@ +// Perceptual luminance for FXAA. +float XeApplyGammaGetAlpha(float3 color) { + return dot(color, float3(0.299, 0.587, 0.114)); +} +#include "apply_gamma_table.hlsli" diff --git a/src/xenia/gpu/shaders/bytecode/.clang-format b/src/xenia/gpu/shaders/bytecode/.clang-format index e3845288a..9d159247d 100644 --- a/src/xenia/gpu/shaders/bytecode/.clang-format +++ b/src/xenia/gpu/shaders/bytecode/.clang-format @@ -1 +1,2 @@ DisableFormat: true +SortIncludes: false diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h index ecae25810..1ff1d3d38 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h @@ -84,10 +84,10 @@ ret const BYTE adaptive_quad_hs[] = { - 68, 88, 66, 67, 94, 229, - 104, 122, 195, 92, 144, 36, - 252, 149, 235, 210, 131, 205, - 139, 42, 1, 0, 0, 0, + 68, 88, 66, 67, 91, 114, + 196, 93, 35, 195, 210, 49, + 154, 70, 168, 244, 8, 132, + 25, 246, 1, 0, 0, 0, 176, 4, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 164, 0, 0, 0, 220, 0, @@ -98,7 +98,7 @@ const BYTE adaptive_quad_hs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 60, 0, + 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h index 682d79b83..4d9950a38 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h @@ -73,10 +73,10 @@ ret const BYTE adaptive_triangle_hs[] = { - 68, 88, 66, 67, 86, 168, - 189, 119, 111, 17, 238, 147, - 225, 129, 174, 39, 170, 24, - 24, 225, 1, 0, 0, 0, + 68, 88, 66, 67, 10, 165, + 117, 176, 19, 12, 130, 108, + 171, 104, 195, 161, 52, 251, + 99, 193, 1, 0, 0, 0, 224, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 164, 0, 0, 0, 220, 0, @@ -87,7 +87,7 @@ const BYTE adaptive_triangle_hs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 60, 0, + 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h new file mode 100644 index 000000000..727d15384 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_cs.h @@ -0,0 +1,409 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture uint2 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 3 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0) +imul null, r0.w, r1.z, l(3) +imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0) +ld r1.xz, r1.xxxx, T1[1].xzyw +utof r1.x, r1.x +and r0.xyz, r0.xyzx, l(7, 7, 7, 0) +imul null, r0.x, r1.z, r0.x +utof r0.x, r0.x +mad r0.x, r0.x, l(0.125000), r1.x +mul r0.x, r0.x, l(0.000015) +min r2.x, r0.x, l(1.000000) +ld r1.xy, r1.yyyy, T1[1].xyzw +utof r0.x, r1.x +imul null, r0.y, r0.y, r1.y +utof r0.y, r0.y +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.y, r0.x, l(1.000000) +ld r0.xy, r0.wwww, T1[1].xyzw +imul null, r0.y, r0.y, r0.z +utof r0.xy, r0.xyxx +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.z, r0.x, l(1.000000) +mov r2.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw +ret +// Approximately 37 instruction slots used +#endif + +const BYTE apply_gamma_pwl_cs[] = +{ + 68, 88, 66, 67, 180, 180, + 222, 28, 4, 138, 188, 113, + 52, 97, 214, 88, 116, 106, + 105, 240, 1, 0, 0, 0, + 128, 7, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 228, 6, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 164, 4, 0, 0, + 81, 0, 5, 0, 41, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 192, + 127, 68, 0, 192, 127, 68, + 0, 192, 127, 68, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 35, 0, 0, 15, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 82, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 134, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 45, 0, 0, 8, + 50, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 32, + 128, 55, 51, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 45, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 54, 0, 0, 5, + 130, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 37, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h new file mode 100644 index 000000000..ed86b4d4a --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_pwl_fxaa_luma_cs.h @@ -0,0 +1,413 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture uint2 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (uint,uint,uint,uint) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 3 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(1023.000000, 1023.000000, 1023.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ushr r1.xyz, r0.xyzx, l(3, 3, 3, 0) +imul null, r0.w, r1.z, l(3) +imad r1.xy, r1.xyxx, l(3, 3, 0, 0), l(2, 1, 0, 0) +ld r1.xz, r1.xxxx, T1[1].xzyw +utof r1.x, r1.x +and r0.xyz, r0.xyzx, l(7, 7, 7, 0) +imul null, r0.x, r1.z, r0.x +utof r0.x, r0.x +mad r0.x, r0.x, l(0.125000), r1.x +mul r0.x, r0.x, l(0.000015) +min r2.x, r0.x, l(1.000000) +ld r1.xy, r1.yyyy, T1[1].xyzw +utof r0.x, r1.x +imul null, r0.y, r0.y, r1.y +utof r0.y, r0.y +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.y, r0.x, l(1.000000) +ld r0.xy, r0.wwww, T1[1].xyzw +imul null, r0.y, r0.y, r0.z +utof r0.xy, r0.xyxx +mad r0.x, r0.y, l(0.125000), r0.x +mul r0.x, r0.x, l(0.000015) +min r2.z, r0.x, l(1.000000) +dp3 r2.w, r2.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r2.xyzw +ret +// Approximately 37 instruction slots used +#endif + +const BYTE apply_gamma_pwl_fxaa_luma_cs[] = +{ + 68, 88, 66, 67, 165, 122, + 242, 36, 160, 218, 193, 67, + 37, 43, 138, 45, 109, 219, + 226, 109, 1, 0, 0, 0, + 148, 7, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 248, 6, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 184, 4, 0, 0, + 81, 0, 5, 0, 46, 1, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 68, 68, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 192, + 127, 68, 0, 192, 127, 68, + 0, 192, 127, 68, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 10, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 38, 0, + 0, 8, 0, 208, 0, 0, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 3, 0, 0, 0, + 35, 0, 0, 15, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 3, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 82, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 134, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 1, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 7, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 45, 0, 0, 8, + 50, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 86, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 38, 0, 0, 8, 0, 208, + 0, 0, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 62, 10, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 8, 32, + 128, 55, 51, 0, 0, 7, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 45, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 38, 0, 0, 8, + 0, 208, 0, 0, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 62, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 8, 32, 128, 55, 51, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 16, 0, 0, 10, + 130, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 135, 22, 153, 62, + 162, 69, 22, 63, 213, 120, + 233, 61, 0, 0, 0, 0, + 164, 0, 0, 7, 242, 224, + 33, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 5, + 2, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 37, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 11, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h new file mode 100644 index 000000000..a890e8f48 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_cs.h @@ -0,0 +1,281 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture float3 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (float,float,float,float) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 2 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ld r1.x, r0.xxxx, T1[1].zxyw +ld r1.y, r0.yyyy, T1[1].xyzw +ld r1.z, r0.zzzz, T1[1].yzxw +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 16 instruction slots used +#endif + +const BYTE apply_gamma_table_cs[] = +{ + 68, 88, 66, 67, 20, 63, + 31, 100, 63, 232, 227, 64, + 21, 8, 34, 27, 205, 36, + 202, 71, 1, 0, 0, 0, + 252, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 96, 4, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 32, 2, 0, 0, + 81, 0, 5, 0, 136, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 2, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 127, 67, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 38, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 45, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 45, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 150, 124, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 164, 0, 0, 7, + 242, 224, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 5, 2, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h new file mode 100644 index 000000000..4373d8498 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/apply_gamma_table_fxaa_luma_cs.h @@ -0,0 +1,284 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_apply_gamma_size; // Offset: 0 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_apply_gamma_source texture float3 2d T0 t0 1 +// xe_apply_gamma_ramp texture float3 buf T1 t1 1 +// xe_apply_gamma_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_resource_buffer (float,float,float,float) T1[1:1], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 2 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +mov r0.xy, vThreadID.xyxx +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mad r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000), l(0.500000, 0.500000, 0.500000, 0.000000) +ftou r0.xyz, r0.xyzx +ld r1.x, r0.xxxx, T1[1].zxyw +ld r1.y, r0.yyyy, T1[1].xyzw +ld r1.z, r0.zzzz, T1[1].yzxw +dp3 r1.w, r1.xyzx, l(0.299000, 0.587000, 0.114000, 0.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 16 instruction slots used +#endif + +const BYTE apply_gamma_table_fxaa_luma_cs[] = +{ + 68, 88, 66, 67, 148, 92, + 39, 196, 202, 33, 41, 82, + 77, 137, 192, 188, 150, 218, + 30, 64, 1, 0, 0, 0, + 16, 5, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 24, 2, 0, 0, 40, 2, + 0, 0, 56, 2, 0, 0, + 116, 4, 0, 0, 82, 68, + 69, 70, 220, 1, 0, 0, + 1, 0, 0, 0, 52, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 180, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 6, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 115, 111, 117, 114, 99, + 101, 0, 120, 101, 95, 97, + 112, 112, 108, 121, 95, 103, + 97, 109, 109, 97, 95, 114, + 97, 109, 112, 0, 120, 101, + 95, 97, 112, 112, 108, 121, + 95, 103, 97, 109, 109, 97, + 95, 100, 101, 115, 116, 0, + 88, 101, 65, 112, 112, 108, + 121, 71, 97, 109, 109, 97, + 82, 97, 109, 112, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 26, 1, 0, 0, + 1, 0, 0, 0, 76, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 144, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 97, 112, 112, + 108, 121, 95, 103, 97, 109, + 109, 97, 95, 115, 105, 122, + 101, 0, 117, 105, 110, 116, + 50, 0, 171, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 52, 2, 0, 0, + 81, 0, 5, 0, 141, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 88, 8, 0, 7, + 70, 126, 48, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 156, 24, 0, 7, 70, 238, + 49, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 95, 0, + 0, 2, 50, 0, 2, 0, + 104, 0, 0, 2, 2, 0, + 0, 0, 155, 0, 0, 4, + 8, 0, 0, 0, 8, 0, + 0, 0, 1, 0, 0, 0, + 80, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 2, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 60, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 21, 0, + 0, 1, 54, 0, 0, 4, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 127, 67, 0, 0, 127, 67, + 0, 0, 127, 67, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 28, 0, + 0, 5, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 18, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 38, 125, 32, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 45, 0, 0, 8, + 34, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 45, 0, + 0, 8, 66, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 150, 124, 32, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 16, 0, 0, 10, 130, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 135, 22, 153, 62, 162, 69, + 22, 63, 213, 120, 233, 61, + 0, 0, 0, 0, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h index 12d936ccf..8bf1a7d63 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/clear_uint2_ps.h @@ -44,10 +44,10 @@ ret const BYTE clear_uint2_ps[] = { - 68, 88, 66, 67, 37, 23, - 17, 1, 102, 148, 181, 42, - 241, 102, 112, 167, 142, 147, - 73, 7, 1, 0, 0, 0, + 68, 88, 66, 67, 90, 79, + 67, 15, 17, 175, 210, 170, + 189, 222, 209, 228, 62, 31, + 153, 246, 1, 0, 0, 0, 148, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 88, 1, 0, 0, 104, 1, @@ -57,7 +57,7 @@ const BYTE clear_uint2_ps[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 244, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h index cba1c29ab..9969afd5f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h @@ -121,10 +121,10 @@ ret const BYTE continuous_quad_hs[] = { - 68, 88, 66, 67, 109, 174, - 137, 67, 82, 213, 246, 48, - 97, 232, 232, 104, 109, 96, - 97, 35, 1, 0, 0, 0, + 68, 88, 66, 67, 38, 148, + 187, 235, 226, 45, 172, 116, + 78, 244, 151, 91, 91, 131, + 203, 9, 1, 0, 0, 0, 240, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -135,7 +135,7 @@ const BYTE continuous_quad_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h index afd8a3347..7ebd3f557 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h @@ -112,10 +112,10 @@ ret const BYTE continuous_triangle_hs[] = { - 68, 88, 66, 67, 150, 55, - 56, 98, 126, 111, 114, 179, - 197, 7, 10, 15, 70, 32, - 249, 93, 1, 0, 0, 0, + 68, 88, 66, 67, 73, 225, + 250, 199, 94, 238, 81, 135, + 38, 37, 240, 107, 243, 39, + 228, 138, 1, 0, 0, 0, 96, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -126,7 +126,7 @@ const BYTE continuous_triangle_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h index 53a0af447..3fb7e283f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h @@ -121,10 +121,10 @@ ret const BYTE discrete_quad_hs[] = { - 68, 88, 66, 67, 174, 141, - 75, 94, 70, 108, 133, 212, - 18, 161, 84, 115, 238, 199, - 1, 25, 1, 0, 0, 0, + 68, 88, 66, 67, 30, 187, + 71, 171, 142, 3, 72, 194, + 131, 236, 131, 25, 126, 147, + 165, 207, 1, 0, 0, 0, 240, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -135,7 +135,7 @@ const BYTE discrete_quad_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h index d5855480a..4d4118deb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h @@ -112,10 +112,10 @@ ret const BYTE discrete_triangle_hs[] = { - 68, 88, 66, 67, 100, 231, - 203, 227, 24, 0, 204, 209, - 145, 54, 166, 75, 102, 255, - 190, 98, 1, 0, 0, 0, + 68, 88, 66, 67, 59, 166, + 23, 194, 170, 244, 84, 16, + 156, 139, 156, 141, 147, 143, + 102, 19, 1, 0, 0, 0, 96, 13, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 188, 10, 0, 0, 240, 10, @@ -126,7 +126,7 @@ const BYTE discrete_triangle_hs[] = 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, 83, 72, - 0, 5, 4, 0, 82, 10, + 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h index ca93f0d29..8a82eb0e7 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_round_ps.h @@ -76,10 +76,10 @@ ret const BYTE float24_round_ps[] = { - 68, 88, 66, 67, 23, 65, - 158, 4, 125, 87, 131, 240, - 183, 241, 233, 246, 170, 100, - 46, 3, 1, 0, 0, 0, + 68, 88, 66, 67, 229, 54, + 46, 1, 194, 31, 164, 202, + 193, 71, 175, 129, 44, 52, + 218, 154, 1, 0, 0, 0, 8, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 120, 2, @@ -89,7 +89,7 @@ const BYTE float24_round_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h index 1111cd47f..91eb48136 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/float24_truncate_ps.h @@ -58,10 +58,10 @@ ret const BYTE float24_truncate_ps[] = { - 68, 88, 66, 67, 73, 81, - 190, 30, 130, 230, 10, 4, - 35, 6, 194, 2, 204, 207, - 200, 64, 1, 0, 0, 0, + 68, 88, 66, 67, 234, 72, + 187, 196, 185, 155, 10, 179, + 119, 204, 17, 88, 131, 142, + 107, 205, 1, 0, 0, 0, 140, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 120, 2, @@ -71,7 +71,7 @@ const BYTE float24_truncate_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h deleted file mode 100644 index c14aebabf..000000000 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_tc_vs.h +++ /dev/null @@ -1,166 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 10.1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_VertexID 0 x 0 VERTID uint x -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy -// SV_Position 0 xyzw 1 POS float xyzw -// -vs_5_1 -dcl_globalFlags refactoringAllowed -dcl_input_sgv v0.x, vertex_id -dcl_output o0.xy -dcl_output_siv o1.xyzw, position -dcl_temps 1 -ishl r0.y, v0.x, l(1) -mov r0.x, v0.x -and r0.xy, r0.xyxx, l(2, 2, 0, 0) -utof r0.xy, r0.xyxx -mad o1.xy, r0.xyxx, l(2.000000, -2.000000, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000) -mov o1.zw, l(0,0,0,1.000000) -mov o0.xy, r0.xyxx -ret -// Approximately 8 instruction slots used -#endif - -const BYTE fullscreen_tc_vs[] = -{ - 68, 88, 66, 67, 194, 19, - 91, 0, 93, 21, 209, 27, - 252, 153, 187, 171, 84, 80, - 251, 138, 1, 0, 0, 0, - 240, 2, 0, 0, 5, 0, - 0, 0, 52, 0, 0, 0, - 160, 0, 0, 0, 212, 0, - 0, 0, 44, 1, 0, 0, - 84, 2, 0, 0, 82, 68, - 69, 70, 100, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, - 60, 0, 0, 0, 19, 19, - 68, 37, 60, 0, 0, 0, - 24, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 0, 0, - 36, 0, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, - 77, 105, 99, 114, 111, 115, - 111, 102, 116, 32, 40, 82, - 41, 32, 72, 76, 83, 76, - 32, 83, 104, 97, 100, 101, - 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 49, - 48, 46, 49, 0, 73, 83, - 71, 78, 44, 0, 0, 0, - 1, 0, 0, 0, 8, 0, - 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 1, - 0, 0, 83, 86, 95, 86, - 101, 114, 116, 101, 120, 73, - 68, 0, 79, 83, 71, 78, - 80, 0, 0, 0, 2, 0, - 0, 0, 8, 0, 0, 0, - 56, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 3, 12, 0, 0, - 65, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 15, 0, 0, 0, - 84, 69, 88, 67, 79, 79, - 82, 68, 0, 83, 86, 95, - 80, 111, 115, 105, 116, 105, - 111, 110, 0, 171, 171, 171, - 83, 72, 69, 88, 32, 1, - 0, 0, 81, 0, 1, 0, - 72, 0, 0, 0, 106, 8, - 0, 1, 96, 0, 0, 4, - 18, 16, 16, 0, 0, 0, - 0, 0, 6, 0, 0, 0, - 101, 0, 0, 3, 50, 32, - 16, 0, 0, 0, 0, 0, - 103, 0, 0, 4, 242, 32, - 16, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 104, 0, - 0, 2, 1, 0, 0, 0, - 41, 0, 0, 7, 34, 0, - 16, 0, 0, 0, 0, 0, - 10, 16, 16, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 1, 0, 0, 0, 54, 0, - 0, 5, 18, 0, 16, 0, - 0, 0, 0, 0, 10, 16, - 16, 0, 0, 0, 0, 0, - 1, 0, 0, 10, 50, 0, - 16, 0, 0, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 2, 64, 0, 0, - 2, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 86, 0, - 0, 5, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 0, - 16, 0, 0, 0, 0, 0, - 50, 0, 0, 15, 50, 32, - 16, 0, 1, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 2, 64, 0, 0, - 0, 0, 0, 64, 0, 0, - 0, 192, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 64, - 0, 0, 0, 0, 128, 191, - 0, 0, 128, 63, 0, 0, - 0, 0, 0, 0, 0, 0, - 54, 0, 0, 8, 194, 32, - 16, 0, 1, 0, 0, 0, - 2, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 128, 63, 54, 0, 0, 5, - 50, 32, 16, 0, 0, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 8, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0 -}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h index f12247ce4..5a388c0a8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h @@ -34,10 +34,10 @@ ret const BYTE fullscreen_vs[] = { - 68, 88, 66, 67, 11, 43, - 171, 43, 233, 188, 20, 107, - 115, 148, 0, 215, 116, 165, - 194, 26, 1, 0, 0, 0, + 68, 88, 66, 67, 111, 71, + 234, 43, 238, 70, 168, 114, + 17, 145, 139, 145, 152, 124, + 190, 180, 1, 0, 0, 0, 172, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 212, 0, @@ -47,7 +47,7 @@ const BYTE fullscreen_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h new file mode 100644 index 000000000..8ca505c28 --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_cs.h @@ -0,0 +1,1270 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_fxaa_size; // Offset: 0 Size: 8 +// float2 xe_fxaa_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_fxaa_source texture float4 2d T0 t0 1 +// xe_fxaa_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 7 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +utof r0.xy, vThreadID.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.zw, r0.xxxy, CB0[0][0].zzzw +sample_l r1.xyzw, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +gather4 r2.xyz, r0.zwzz, T0[0].xyzw, S0[0].w +gather4_aoffimmi(-1,-1,0) r3.xyz, r0.zwzz, T0[0].zxwy, S0[0].w +max r2.w, r1.w, r2.x +min r3.w, r1.w, r2.x +max r2.w, r2.w, r2.z +min r3.w, r2.z, r3.w +max r4.x, r3.y, r3.x +min r4.y, r3.y, r3.x +max r2.w, r2.w, r4.x +min r3.w, r3.w, r4.y +mul r4.x, r2.w, l(0.166000) +add r2.w, r2.w, -r3.w +max r3.w, r4.x, l(0.083300) +lt r3.w, r2.w, r3.w +if_z r3.w +endif +if_z r3.w + sample_l_aoffimmi(1,-1,0) r3.w, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) + sample_l_aoffimmi(-1,1,0) r4.x, r0.zwzz, T0[0].wxyz, S0[0], l(0.000000) + add r4.yz, r2.xxzx, r3.xxyx + div r2.w, l(1.000000, 1.000000, 1.000000, 1.000000), r2.w + add r4.w, r4.z, r4.y + mad r4.yz, r1.wwww, l(0.000000, -2.000000, -2.000000, 0.000000), r4.yyzy + add r5.x, r2.y, r3.w + add r3.w, r3.w, r3.z + mad r5.y, r2.z, l(-2.000000), r5.x + mad r3.w, r3.x, l(-2.000000), r3.w + add r3.z, r3.z, r4.x + add r2.y, r2.y, r4.x + mad r4.x, |r4.y|, l(2.000000), |r5.y| + mad r3.w, |r4.z|, l(2.000000), |r3.w| + mad r4.y, r3.y, l(-2.000000), r3.z + mad r2.y, r2.x, l(-2.000000), r2.y + add r4.x, r4.x, |r4.y| + add r2.y, r3.w, |r2.y| + add r3.z, r5.x, r3.z + ge r2.y, r4.x, r2.y + mad r3.z, r4.w, l(2.000000), r3.z + if_z r2.y + mov r3.x, r3.y + mov r2.x, r2.z + endif + if_nz r2.y + mov r2.z, CB0[0][0].w + else + mov r2.z, CB0[0][0].z + endif + mad r3.y, r3.z, l(0.083333), -r1.w + add r3.z, -r1.w, r3.x + add r3.w, -r1.w, r2.x + ge r4.x, |r3.z|, |r3.w| + max r3.z, |r3.w|, |r3.z| + if_nz r4.x + mov r2.z, -r2.z + endif + mul_sat r2.w, r2.w, |r3.y| + and r3.y, r2.y, CB0[0][0].z + movc r3.w, r2.y, l(0), CB0[0][0].w + if_z r2.y + mad r4.y, r2.z, l(0.500000), r0.z + else + mov r4.y, r0.z + endif + if_nz r2.y + mad r4.z, r2.z, l(0.500000), r0.w + else + mov r4.z, r0.w + endif + add r5.xy, -r3.ywyy, r4.yzyy + add r4.yw, r3.yyyw, r4.yyyz + mad r4.z, r2.w, l(-2.000000), l(3.000000) + sample_l r5.z, r5.xyxx, T0[0].xywz, S0[0], l(0.000000) + mul r2.w, r2.w, r2.w + sample_l r5.w, r4.ywyy, T0[0].xyzw, S0[0], l(0.000000) + if_z r4.x + add r3.x, r1.w, r2.x + else + add r3.x, r1.w, r3.x + endif + mul r2.x, r3.z, l(0.250000) + mad r3.z, -r3.x, l(0.500000), r1.w + mul r2.w, r2.w, r4.z + lt r3.z, r3.z, l(0.000000) + mad r6.x, -r3.x, l(0.500000), r5.z + mad r6.y, -r3.x, l(0.500000), r5.w + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(1.500000), r5.x + mad r5.y, -r3.w, l(1.500000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(1.500000), r4.y + mad r4.w, r3.w, l(1.500000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(4.000000), r5.x + mad r5.y, -r3.w, l(4.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(4.000000), r4.y + mad r4.w, r3.w, l(4.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(12.000000), r5.x + mad r5.y, -r3.w, l(12.000000), r5.y + endif + if_nz r4.z + mad r4.y, r3.y, l(12.000000), r4.y + mad r4.w, r3.w, l(12.000000), r4.w + endif + endif + endif + endif + if_z r2.y + mad r2.x, r0.y, CB0[0][0].w, -r5.y + mad r0.x, -r0.y, CB0[0][0].w, r4.w + else + mad r2.x, r0.x, CB0[0][0].z, -r5.x + mad r0.x, -r0.x, CB0[0][0].z, r4.y + endif + lt r3.xy, r6.xyxx, l(0.000000, 0.000000, 0.000000, 0.000000) + add r0.y, r2.x, r0.x + ine r3.xy, r3.zzzz, r3.xyxx + div r0.y, l(1.000000, 1.000000, 1.000000, 1.000000), r0.y + lt r3.z, r2.x, r0.x + min r0.x, r0.x, r2.x + movc r2.x, r3.z, r3.x, r3.y + mul r2.w, r2.w, r2.w + mad r0.x, r0.x, -r0.y, l(0.500000) + mul r0.y, r2.w, l(0.750000) + and r0.x, r0.x, r2.x + max r0.x, r0.y, r0.x + if_z r2.y + mad r0.z, r0.x, r2.z, r0.z + endif + if_nz r2.y + mad r0.w, r0.x, r2.z, r0.w + endif + sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +endif +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 205 instruction slots used +#endif + +const BYTE fxaa_cs[] = +{ + 68, 88, 66, 67, 146, 66, + 17, 144, 231, 237, 183, 236, + 231, 78, 100, 194, 80, 51, + 78, 217, 1, 0, 0, 0, + 184, 23, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 108, 2, 0, 0, 124, 2, + 0, 0, 140, 2, 0, 0, + 28, 23, 0, 0, 82, 68, + 69, 70, 48, 2, 0, 0, + 1, 0, 0, 0, 44, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 8, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 115, 97, 109, 112, 108, + 101, 114, 95, 108, 105, 110, + 101, 97, 114, 95, 99, 108, + 97, 109, 112, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 111, 117, 114, 99, 101, + 0, 120, 101, 95, 102, 120, + 97, 97, 95, 100, 101, 115, + 116, 0, 88, 101, 65, 112, + 112, 108, 121, 71, 97, 109, + 109, 97, 82, 97, 109, 112, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 171, 171, + 16, 1, 0, 0, 2, 0, + 0, 0, 68, 1, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 102, + 120, 97, 97, 95, 115, 105, + 122, 101, 0, 117, 105, 110, + 116, 50, 0, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 1, 0, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 102, 108, 111, + 97, 116, 50, 0, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 136, 20, 0, 0, + 81, 0, 5, 0, 34, 5, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 156, 24, 0, 7, + 70, 238, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, + 0, 0, 0, 0, 0, 0, + 95, 0, 0, 2, 50, 0, + 2, 0, 104, 0, 0, 2, + 7, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 80, 0, 0, 8, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 70, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 21, 0, 0, 1, 86, 0, + 0, 4, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 2, 0, 0, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 9, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 72, 0, 0, 13, 242, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 140, 1, 254, + 1, 0, 114, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 38, 119, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 231, 251, 41, 62, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 49, 153, 170, 61, + 49, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 0, 3, + 58, 0, 16, 0, 3, 0, + 0, 0, 72, 0, 0, 142, + 1, 226, 1, 0, 130, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 142, 1, 62, 0, 0, + 18, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 98, 0, + 16, 0, 4, 0, 0, 0, + 6, 2, 16, 0, 2, 0, + 0, 0, 6, 1, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 130, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 12, 98, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 192, 0, 0, 0, 192, + 0, 0, 0, 0, 86, 6, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 10, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 128, 129, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 11, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 128, + 129, 0, 0, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 26, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 29, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 42, 0, 16, 0, 3, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 50, 0, 0, 10, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 171, 170, 170, 61, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 29, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 52, 0, + 0, 9, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 56, 32, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 11, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 42, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 9, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 1, 64, 0, 0, 0, 0, + 64, 64, 72, 0, 0, 13, + 66, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 70, 123, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 72, 0, + 0, 13, 130, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 0, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 56, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 62, 50, 0, + 0, 10, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 42, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 58, 0, + 16, 0, 5, 0, 0, 0, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 192, 63, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 64, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 64, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 64, 65, 10, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 65, 26, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 64, 65, + 26, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 64, 65, + 58, 0, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 58, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 18, 0, 0, 1, 50, 0, + 0, 12, 18, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 5, 0, 0, 0, 50, 0, + 0, 12, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 49, 0, 0, 10, + 50, 0, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 39, 0, + 0, 7, 50, 0, 16, 0, + 3, 0, 0, 0, 166, 10, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 3, 0, + 0, 0, 14, 0, 0, 10, + 34, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 26, 0, + 16, 0, 0, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 51, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 55, 0, 0, 9, + 18, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 56, 0, + 0, 7, 34, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 63, 1, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 31, 0, + 0, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 72, 0, 0, 13, 114, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 164, 0, + 0, 7, 242, 224, 33, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 5, 2, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 205, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 94, 0, 0, 0, 1, 0, + 0, 0, 7, 0, 0, 0, + 7, 0, 0, 0, 35, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h new file mode 100644 index 000000000..026ac19fc --- /dev/null +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fxaa_extreme_cs.h @@ -0,0 +1,1956 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeApplyGammaRampConstants +// { +// +// uint2 xe_fxaa_size; // Offset: 0 Size: 8 +// float2 xe_fxaa_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_fxaa_source texture float4 2d T0 t0 1 +// xe_fxaa_dest UAV unorm4 2d U0 u0 1 +// XeApplyGammaRampConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Input +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// no Output +cs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_uav_typed_texture2d (unorm,unorm,unorm,unorm) U0[0:0], space=0 +dcl_input vThreadID.xy +dcl_temps 7 +dcl_thread_group 8, 8, 1 +uge r0.xy, vThreadID.xyxx, CB0[0][0].xyxx +or r0.x, r0.y, r0.x +if_nz r0.x + ret +endif +utof r0.xy, vThreadID.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.zw, r0.xxxy, CB0[0][0].zzzw +sample_l r1.xyzw, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +gather4 r2.xyz, r0.zwzz, T0[0].xyzw, S0[0].w +gather4_aoffimmi(-1,-1,0) r3.xyz, r0.zwzz, T0[0].zxwy, S0[0].w +max r2.w, r1.w, r2.x +min r3.w, r1.w, r2.x +max r2.w, r2.w, r2.z +min r3.w, r2.z, r3.w +max r4.x, r3.y, r3.x +min r4.y, r3.y, r3.x +max r2.w, r2.w, r4.x +min r3.w, r3.w, r4.y +mul r4.x, r2.w, l(0.063000) +add r2.w, r2.w, -r3.w +max r3.w, r4.x, l(0.031200) +lt r3.w, r2.w, r3.w +if_z r3.w +endif +if_z r3.w + sample_l_aoffimmi(1,-1,0) r3.w, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) + sample_l_aoffimmi(-1,1,0) r4.x, r0.zwzz, T0[0].wxyz, S0[0], l(0.000000) + add r4.yz, r2.xxzx, r3.xxyx + div r2.w, l(1.000000, 1.000000, 1.000000, 1.000000), r2.w + add r4.w, r4.z, r4.y + mad r4.yz, r1.wwww, l(0.000000, -2.000000, -2.000000, 0.000000), r4.yyzy + add r5.x, r2.y, r3.w + add r3.w, r3.w, r3.z + mad r5.y, r2.z, l(-2.000000), r5.x + mad r3.w, r3.x, l(-2.000000), r3.w + add r3.z, r3.z, r4.x + add r2.y, r2.y, r4.x + mad r4.x, |r4.y|, l(2.000000), |r5.y| + mad r3.w, |r4.z|, l(2.000000), |r3.w| + mad r4.y, r3.y, l(-2.000000), r3.z + mad r2.y, r2.x, l(-2.000000), r2.y + add r4.x, r4.x, |r4.y| + add r2.y, r3.w, |r2.y| + add r3.z, r5.x, r3.z + ge r2.y, r4.x, r2.y + mad r3.z, r4.w, l(2.000000), r3.z + if_z r2.y + mov r3.x, r3.y + mov r2.x, r2.z + endif + if_nz r2.y + mov r2.z, CB0[0][0].w + else + mov r2.z, CB0[0][0].z + endif + mad r3.y, r3.z, l(0.083333), -r1.w + add r3.z, -r1.w, r3.x + add r3.w, -r1.w, r2.x + ge r4.x, |r3.z|, |r3.w| + max r3.z, |r3.w|, |r3.z| + if_nz r4.x + mov r2.z, -r2.z + endif + mul_sat r2.w, r2.w, |r3.y| + and r3.y, r2.y, CB0[0][0].z + movc r3.w, r2.y, l(0), CB0[0][0].w + if_z r2.y + mad r4.y, r2.z, l(0.500000), r0.z + else + mov r4.y, r0.z + endif + if_nz r2.y + mad r4.z, r2.z, l(0.500000), r0.w + else + mov r4.z, r0.w + endif + add r5.xy, -r3.ywyy, r4.yzyy + add r4.yw, r3.yyyw, r4.yyyz + mad r4.z, r2.w, l(-2.000000), l(3.000000) + sample_l r5.z, r5.xyxx, T0[0].xywz, S0[0], l(0.000000) + mul r2.w, r2.w, r2.w + sample_l r5.w, r4.ywyy, T0[0].xyzw, S0[0], l(0.000000) + if_z r4.x + add r3.x, r1.w, r2.x + else + add r3.x, r1.w, r3.x + endif + mul r2.x, r3.z, l(0.250000) + mad r3.z, -r3.x, l(0.500000), r1.w + mul r2.w, r2.w, r4.z + lt r3.z, r3.z, l(0.000000) + mad r6.x, -r3.x, l(0.500000), r5.z + mad r6.y, -r3.x, l(0.500000), r5.w + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + add r5.xy, -r3.ywyy, r5.xyxx + endif + or r5.z, r4.z, r4.x + if_nz r4.z + add r4.yw, r3.yyyw, r4.yyyw + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(1.500000), r5.x + mad r5.y, -r3.w, l(1.500000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(1.500000), r4.y + mad r4.w, r3.w, l(1.500000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(2.000000), r5.x + mad r5.y, -r3.w, l(2.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(2.000000), r4.y + mad r4.w, r3.w, l(2.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(4.000000), r5.x + mad r5.y, -r3.w, l(4.000000), r5.y + endif + or r5.z, r4.z, r4.x + if_nz r4.z + mad r4.y, r3.y, l(4.000000), r4.y + mad r4.w, r3.w, l(4.000000), r4.w + endif + if_nz r5.z + if_nz r4.x + sample_l r6.x, r5.xyxx, T0[0].wxyz, S0[0], l(0.000000) + endif + if_nz r4.z + sample_l r6.y, r4.ywyy, T0[0].xwyz, S0[0], l(0.000000) + endif + if_nz r4.x + mad r6.x, -r3.x, l(0.500000), r6.x + endif + if_nz r4.z + mad r6.y, -r3.x, l(0.500000), r6.y + endif + lt r4.xz, |r6.xxyx|, r2.xxxx + if_nz r4.x + mad r5.x, -r3.y, l(8.000000), r5.x + mad r5.y, -r3.w, l(8.000000), r5.y + endif + if_nz r4.z + mad r4.y, r3.y, l(8.000000), r4.y + mad r4.w, r3.w, l(8.000000), r4.w + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + endif + if_z r2.y + mad r2.x, r0.y, CB0[0][0].w, -r5.y + mad r0.x, -r0.y, CB0[0][0].w, r4.w + else + mad r2.x, r0.x, CB0[0][0].z, -r5.x + mad r0.x, -r0.x, CB0[0][0].z, r4.y + endif + lt r3.xy, r6.xyxx, l(0.000000, 0.000000, 0.000000, 0.000000) + add r0.y, r2.x, r0.x + ine r3.xy, r3.zzzz, r3.xyxx + div r0.y, l(1.000000, 1.000000, 1.000000, 1.000000), r0.y + lt r3.z, r2.x, r0.x + min r0.x, r0.x, r2.x + movc r2.x, r3.z, r3.x, r3.y + mul r2.w, r2.w, r2.w + mad r0.x, r0.x, -r0.y, l(0.500000) + and r0.x, r0.x, r2.x + max r0.x, r2.w, r0.x + if_z r2.y + mad r0.z, r0.x, r2.z, r0.z + endif + if_nz r2.y + mad r0.w, r0.x, r2.z, r0.w + endif + sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +endif +mov r1.w, l(1.000000) +store_uav_typed U0[0].xyzw, vThreadID.xyyy, r1.xyzw +ret +// Approximately 364 instruction slots used +#endif + +const BYTE fxaa_extreme_cs[] = +{ + 68, 88, 66, 67, 37, 138, + 209, 45, 7, 149, 158, 200, + 128, 20, 212, 142, 87, 247, + 202, 95, 1, 0, 0, 0, + 16, 36, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 108, 2, 0, 0, 124, 2, + 0, 0, 140, 2, 0, 0, + 116, 35, 0, 0, 82, 68, + 69, 70, 48, 2, 0, 0, + 1, 0, 0, 0, 44, 1, + 0, 0, 4, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 83, 67, 0, 5, 0, 0, + 8, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 220, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 1, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 120, 101, + 95, 115, 97, 109, 112, 108, + 101, 114, 95, 108, 105, 110, + 101, 97, 114, 95, 99, 108, + 97, 109, 112, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 111, 117, 114, 99, 101, + 0, 120, 101, 95, 102, 120, + 97, 97, 95, 100, 101, 115, + 116, 0, 88, 101, 65, 112, + 112, 108, 121, 71, 97, 109, + 109, 97, 82, 97, 109, 112, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 171, 171, + 16, 1, 0, 0, 2, 0, + 0, 0, 68, 1, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 1, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 102, + 120, 97, 97, 95, 115, 105, + 122, 101, 0, 117, 105, 110, + 116, 50, 0, 171, 1, 0, + 19, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 1, 0, 0, 120, 101, + 95, 102, 120, 97, 97, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 102, 108, 111, + 97, 116, 50, 0, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 8, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 79, 83, 71, 78, 8, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 83, 72, + 69, 88, 224, 32, 0, 0, + 81, 0, 5, 0, 56, 8, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 156, 24, 0, 7, + 70, 238, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 17, + 0, 0, 0, 0, 0, 0, + 95, 0, 0, 2, 50, 0, + 2, 0, 104, 0, 0, 2, + 7, 0, 0, 0, 155, 0, + 0, 4, 8, 0, 0, 0, + 8, 0, 0, 0, 1, 0, + 0, 0, 80, 0, 0, 8, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 2, 0, + 70, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 21, 0, 0, 1, 86, 0, + 0, 4, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 2, 0, 0, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 9, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 72, 0, 0, 13, 242, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 114, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 140, 1, 254, + 1, 0, 114, 0, 16, 0, + 3, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 38, 119, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 37, 6, 129, 61, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 36, 151, 255, 60, + 49, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 31, 0, + 0, 3, 58, 0, 16, 0, + 3, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 0, 3, + 58, 0, 16, 0, 3, 0, + 0, 0, 72, 0, 0, 142, + 1, 226, 1, 0, 130, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 142, 1, 62, 0, 0, + 18, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 98, 0, + 16, 0, 4, 0, 0, 0, + 6, 2, 16, 0, 2, 0, + 0, 0, 6, 1, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 130, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 12, 98, 0, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 192, 0, 0, 0, 192, + 0, 0, 0, 0, 86, 6, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 10, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 34, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 11, 18, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 128, 129, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 11, 130, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 128, + 129, 0, 0, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 42, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 34, 0, 16, 0, 2, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 26, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 29, 0, + 0, 7, 34, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 42, 0, 16, 0, 3, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 54, 0, + 0, 7, 66, 0, 16, 0, + 2, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 54, 0, 0, 7, 66, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 50, 0, 0, 10, + 34, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 171, 170, 170, 61, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 8, 66, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 29, 0, + 0, 9, 18, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 52, 0, + 0, 9, 66, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 6, 66, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 21, 0, + 0, 1, 56, 32, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 55, 0, + 0, 11, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 42, 0, + 16, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 26, 0, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 5, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 9, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 192, + 1, 64, 0, 0, 0, 0, + 64, 64, 72, 0, 0, 13, + 66, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 70, 123, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 72, 0, + 0, 13, 130, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 2, 0, 0, 0, + 18, 0, 0, 1, 0, 0, + 0, 7, 18, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 21, 0, 0, 1, + 56, 0, 0, 7, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 62, 50, 0, + 0, 10, 66, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 49, 0, 0, 7, 66, 0, + 16, 0, 3, 0, 0, 0, + 42, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 42, 0, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 58, 0, + 16, 0, 5, 0, 0, 0, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 13, 16, 0, 3, 0, + 0, 0, 86, 13, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 5, 0, 0, 0, + 214, 5, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 7, 162, 0, 16, 0, + 4, 0, 0, 0, 86, 13, + 16, 0, 3, 0, 0, 0, + 86, 13, 16, 0, 4, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 5, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 18, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 54, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 34, 0, 16, 0, 6, 0, + 0, 0, 214, 5, 16, 0, + 4, 0, 0, 0, 198, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 18, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 10, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 34, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 26, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 49, 0, 0, 8, + 82, 0, 16, 0, 4, 0, + 0, 0, 6, 1, 16, 128, + 129, 0, 0, 0, 6, 0, + 0, 0, 6, 0, 16, 0, + 2, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 5, 0, 0, 0, 214, 5, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 60, 0, + 0, 7, 66, 0, 16, 0, + 5, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 10, 0, 16, 0, 4, 0, + 0, 0, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 162, 0, 16, 0, 4, 0, + 0, 0, 86, 13, 16, 0, + 3, 0, 0, 0, 86, 13, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 5, 0, 0, 0, 31, 0, + 4, 3, 10, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 18, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 54, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 72, 0, 0, 13, 34, 0, + 16, 0, 6, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 198, 121, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 10, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 26, 0, 16, 0, 6, 0, + 0, 0, 21, 0, 0, 1, + 49, 0, 0, 8, 82, 0, + 16, 0, 4, 0, 0, 0, + 6, 1, 16, 128, 129, 0, + 0, 0, 6, 0, 0, 0, + 6, 0, 16, 0, 2, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 8, + 50, 0, 16, 0, 5, 0, + 0, 0, 214, 5, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 21, 0, + 0, 1, 60, 0, 0, 7, + 66, 0, 16, 0, 5, 0, + 0, 0, 42, 0, 16, 0, + 4, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 7, 162, 0, + 16, 0, 4, 0, 0, 0, + 86, 13, 16, 0, 3, 0, + 0, 0, 86, 13, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 192, 63, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 192, 63, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 60, 0, 0, 7, 66, 0, + 16, 0, 5, 0, 0, 0, + 42, 0, 16, 0, 4, 0, + 0, 0, 10, 0, 16, 0, + 4, 0, 0, 0, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 26, 0, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 58, 0, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 5, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 4, 0, + 0, 0, 72, 0, 0, 13, + 18, 0, 16, 0, 6, 0, + 0, 0, 70, 0, 16, 0, + 5, 0, 0, 0, 54, 121, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 4, 0, 0, 0, 72, 0, + 0, 13, 34, 0, 16, 0, + 6, 0, 0, 0, 214, 5, + 16, 0, 4, 0, 0, 0, + 198, 121, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 10, 0, 16, 0, + 6, 0, 0, 0, 21, 0, + 0, 1, 31, 0, 4, 3, + 42, 0, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 6, 0, + 0, 0, 10, 0, 16, 128, + 65, 0, 0, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 63, 26, 0, + 16, 0, 6, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 8, 82, 0, 16, 0, + 4, 0, 0, 0, 6, 1, + 16, 128, 129, 0, 0, 0, + 6, 0, 0, 0, 6, 0, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 10, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 65, 10, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 65, + 26, 0, 16, 0, 5, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 42, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 65, 26, 0, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 65, 58, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 21, 0, + 0, 1, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 12, + 18, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 5, 0, + 0, 0, 50, 0, 0, 12, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 18, 0, 0, 1, + 50, 0, 0, 12, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 42, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 12, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 42, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 49, 0, + 0, 10, 50, 0, 16, 0, + 3, 0, 0, 0, 70, 0, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 39, 0, 0, 7, 50, 0, + 16, 0, 3, 0, 0, 0, + 166, 10, 16, 0, 3, 0, + 0, 0, 70, 0, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 10, 34, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 26, 0, 16, 0, 0, 0, + 0, 0, 49, 0, 0, 7, + 66, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 10, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 1, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 21, 0, 0, 1, 72, 0, + 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 21, 0, 0, 1, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 164, 0, 0, 7, + 242, 224, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 70, 5, 2, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 108, 1, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 134, 0, + 0, 0, 1, 0, 0, 0, + 14, 0, 0, 0, 7, 0, + 0, 0, 84, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h index b4022a12a..3e43288af 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_1xmsaa_cs.h @@ -100,10 +100,10 @@ ret const BYTE host_depth_store_1xmsaa_cs[] = { - 68, 88, 66, 67, 40, 219, - 237, 83, 207, 54, 217, 154, - 183, 72, 124, 224, 242, 47, - 153, 1, 1, 0, 0, 0, + 68, 88, 66, 67, 240, 197, + 52, 115, 102, 12, 206, 220, + 26, 47, 204, 31, 163, 187, + 103, 82, 1, 0, 0, 0, 196, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -113,7 +113,7 @@ const BYTE host_depth_store_1xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h index 21f6ce603..16d7d51b2 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_2xmsaa_cs.h @@ -113,10 +113,10 @@ ret const BYTE host_depth_store_2xmsaa_cs[] = { - 68, 88, 66, 67, 238, 111, - 30, 240, 147, 73, 122, 32, - 177, 28, 116, 35, 239, 195, - 44, 205, 1, 0, 0, 0, + 68, 88, 66, 67, 220, 153, + 96, 168, 160, 176, 100, 61, + 221, 246, 187, 57, 87, 53, + 74, 27, 1, 0, 0, 0, 104, 11, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -126,7 +126,7 @@ const BYTE host_depth_store_2xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h index 5ba206a86..0ff471cc5 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/host_depth_store_4xmsaa_cs.h @@ -102,10 +102,10 @@ ret const BYTE host_depth_store_4xmsaa_cs[] = { - 68, 88, 66, 67, 2, 59, - 173, 180, 27, 122, 26, 189, - 176, 122, 66, 167, 148, 57, - 133, 176, 1, 0, 0, 0, + 68, 88, 66, 67, 255, 93, + 213, 231, 110, 151, 46, 65, + 140, 74, 54, 254, 196, 135, + 241, 89, 1, 0, 0, 0, 72, 10, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 2, 0, 0, 188, 2, @@ -115,7 +115,7 @@ const BYTE host_depth_store_4xmsaa_cs[] = 2, 0, 0, 0, 92, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 70, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h index 6e58bc909..a5f7f58b8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/passthrough_position_xy_vs.h @@ -29,10 +29,10 @@ ret const BYTE passthrough_position_xy_vs[] = { - 68, 88, 66, 67, 228, 252, - 150, 103, 204, 200, 35, 231, - 157, 180, 182, 79, 123, 204, - 157, 78, 1, 0, 0, 0, + 68, 88, 66, 67, 92, 220, + 0, 199, 190, 67, 183, 153, + 171, 192, 4, 39, 67, 55, + 215, 255, 1, 0, 0, 0, 12, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 212, 0, @@ -42,7 +42,7 @@ const BYTE passthrough_position_xy_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h index 05adda89b..a8a356706 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h @@ -273,10 +273,10 @@ ret const BYTE primitive_point_list_gs[] = { - 68, 88, 66, 67, 22, 253, - 167, 182, 60, 53, 75, 37, - 178, 38, 230, 182, 97, 141, - 160, 120, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 119, + 40, 99, 120, 121, 153, 224, + 111, 77, 187, 15, 15, 245, + 37, 128, 1, 0, 0, 0, 136, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 248, 12, @@ -286,7 +286,7 @@ const BYTE primitive_point_list_gs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h index ac77eae81..e349a4f47 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h @@ -194,10 +194,10 @@ ret const BYTE primitive_quad_list_gs[] = { - 68, 88, 66, 67, 60, 29, - 113, 120, 166, 105, 127, 75, - 174, 160, 2, 184, 182, 91, - 66, 12, 1, 0, 0, 0, + 68, 88, 66, 67, 26, 143, + 179, 72, 238, 147, 43, 130, + 37, 11, 116, 191, 138, 68, + 255, 76, 1, 0, 0, 0, 36, 16, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 224, 2, @@ -207,7 +207,7 @@ const BYTE primitive_quad_list_gs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h index 6ce8c711d..4c078e6ed 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h @@ -424,10 +424,10 @@ ret const BYTE primitive_rectangle_list_gs[] = { - 68, 88, 66, 67, 8, 81, - 101, 117, 123, 39, 249, 189, - 184, 94, 218, 115, 216, 148, - 125, 96, 1, 0, 0, 0, + 68, 88, 66, 67, 84, 207, + 1, 11, 213, 109, 28, 213, + 94, 110, 135, 167, 112, 243, + 154, 30, 1, 0, 0, 0, 68, 40, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 160, 0, 0, 0, 224, 2, @@ -437,7 +437,7 @@ const BYTE primitive_rectangle_list_gs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 71, 0, 5, 4, 0, + 83, 71, 0, 5, 0, 0, 60, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h index 960fc26a4..cc4b6ddd1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h @@ -80,10 +80,10 @@ ret const BYTE resolve_clear_32bpp_cs[] = { - 68, 88, 66, 67, 212, 33, - 57, 169, 71, 99, 28, 75, - 202, 138, 254, 170, 245, 39, - 113, 44, 1, 0, 0, 0, + 68, 88, 66, 67, 226, 247, + 125, 160, 57, 195, 118, 226, + 52, 138, 250, 148, 103, 90, + 91, 213, 1, 0, 0, 0, 120, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 64, 2, 0, 0, 80, 2, @@ -93,7 +93,7 @@ const BYTE resolve_clear_32bpp_cs[] = 1, 0, 0, 0, 176, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 220, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h index 03fdb042d..2afb65467 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_scaled_cs.h @@ -100,10 +100,10 @@ ret const BYTE resolve_clear_32bpp_scaled_cs[] = { - 68, 88, 66, 67, 151, 173, - 156, 244, 183, 241, 226, 31, - 214, 214, 54, 114, 10, 217, - 153, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 205, 174, + 123, 5, 98, 198, 38, 143, + 98, 109, 190, 150, 214, 170, + 216, 92, 1, 0, 0, 0, 104, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 228, 2, 0, 0, 244, 2, @@ -113,7 +113,7 @@ const BYTE resolve_clear_32bpp_scaled_cs[] = 2, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 128, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h index 25c2c75c5..c50250e97 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h @@ -79,10 +79,10 @@ ret const BYTE resolve_clear_64bpp_cs[] = { - 68, 88, 66, 67, 11, 134, - 106, 112, 85, 206, 144, 113, - 121, 69, 237, 199, 49, 129, - 4, 62, 1, 0, 0, 0, + 68, 88, 66, 67, 16, 5, + 27, 66, 247, 175, 170, 221, + 90, 253, 80, 46, 104, 119, + 87, 139, 1, 0, 0, 0, 148, 7, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 64, 2, 0, 0, 80, 2, @@ -92,7 +92,7 @@ const BYTE resolve_clear_64bpp_cs[] = 1, 0, 0, 0, 176, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 220, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h index af43268c5..8db3ee557 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_scaled_cs.h @@ -98,10 +98,10 @@ ret const BYTE resolve_clear_64bpp_scaled_cs[] = { - 68, 88, 66, 67, 226, 249, - 231, 177, 11, 141, 42, 153, - 99, 45, 131, 104, 152, 194, - 26, 176, 1, 0, 0, 0, + 68, 88, 66, 67, 246, 14, + 132, 223, 204, 44, 6, 28, + 86, 181, 216, 251, 242, 62, + 34, 31, 1, 0, 0, 0, 112, 9, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 228, 2, 0, 0, 244, 2, @@ -111,7 +111,7 @@ const BYTE resolve_clear_64bpp_scaled_cs[] = 2, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 128, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h index c188bb822..4205ee54f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h @@ -214,10 +214,10 @@ ret const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] = { - 68, 88, 66, 67, 155, 144, - 108, 102, 32, 219, 74, 112, - 191, 128, 193, 179, 111, 166, - 110, 225, 1, 0, 0, 0, + 68, 88, 66, 67, 239, 168, + 103, 4, 189, 160, 141, 83, + 16, 65, 33, 184, 201, 9, + 185, 83, 1, 0, 0, 0, 156, 24, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -227,7 +227,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h index 146f231b0..227c58ca3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_scaled_cs.h @@ -278,10 +278,10 @@ ret const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 145, 228, - 65, 128, 86, 250, 142, 70, - 190, 88, 12, 69, 154, 111, - 98, 110, 1, 0, 0, 0, + 68, 88, 66, 67, 33, 171, + 235, 222, 88, 49, 17, 196, + 69, 254, 64, 92, 43, 122, + 25, 15, 1, 0, 0, 0, 40, 31, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -291,7 +291,7 @@ const BYTE resolve_fast_32bpp_1x2xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h index b78967304..1de49b65a 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h @@ -225,10 +225,10 @@ ret const BYTE resolve_fast_32bpp_4xmsaa_cs[] = { - 68, 88, 66, 67, 83, 123, - 16, 172, 13, 23, 165, 181, - 111, 176, 230, 199, 227, 113, - 202, 160, 1, 0, 0, 0, + 68, 88, 66, 67, 170, 85, + 205, 145, 228, 207, 40, 6, + 92, 178, 101, 253, 108, 144, + 148, 218, 1, 0, 0, 0, 196, 25, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -238,7 +238,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h index dd885ae7a..48e3dda10 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_scaled_cs.h @@ -290,10 +290,10 @@ ret const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 31, 111, - 219, 218, 202, 212, 228, 164, - 35, 4, 215, 208, 98, 172, - 195, 246, 1, 0, 0, 0, + 68, 88, 66, 67, 228, 200, + 92, 46, 175, 37, 210, 169, + 116, 188, 100, 167, 120, 186, + 226, 184, 1, 0, 0, 0, 100, 32, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -303,7 +303,7 @@ const BYTE resolve_fast_32bpp_4xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h index 06bd84852..827dbd661 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h @@ -203,10 +203,10 @@ ret const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] = { - 68, 88, 66, 67, 148, 119, - 138, 27, 157, 3, 164, 49, - 44, 31, 102, 96, 70, 236, - 100, 146, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 88, + 245, 144, 16, 3, 175, 59, + 111, 160, 2, 183, 105, 216, + 39, 35, 1, 0, 0, 0, 16, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -216,7 +216,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h index dca0ec999..d957d07a4 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_scaled_cs.h @@ -265,10 +265,10 @@ ret const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 146, 74, - 159, 181, 129, 209, 232, 153, - 8, 178, 69, 215, 5, 127, - 187, 119, 1, 0, 0, 0, + 68, 88, 66, 67, 217, 58, + 225, 5, 83, 76, 76, 76, + 41, 4, 184, 58, 64, 138, + 164, 215, 1, 0, 0, 0, 24, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -278,7 +278,7 @@ const BYTE resolve_fast_64bpp_1x2xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h index 8d109abf3..6d0167148 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h @@ -204,10 +204,10 @@ ret const BYTE resolve_fast_64bpp_4xmsaa_cs[] = { - 68, 88, 66, 67, 103, 127, - 24, 191, 130, 242, 189, 20, - 38, 18, 213, 75, 35, 175, - 132, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 219, 212, + 228, 165, 45, 17, 135, 148, + 112, 245, 209, 7, 35, 133, + 189, 71, 1, 0, 0, 0, 40, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -217,7 +217,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h index 8da74d9b4..c3155881e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_scaled_cs.h @@ -263,10 +263,10 @@ ret const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] = { - 68, 88, 66, 67, 175, 243, - 135, 222, 141, 148, 29, 126, - 11, 2, 155, 131, 194, 117, - 96, 179, 1, 0, 0, 0, + 68, 88, 66, 67, 128, 163, + 164, 187, 116, 154, 133, 40, + 143, 38, 115, 1, 152, 118, + 125, 200, 1, 0, 0, 0, 36, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -276,7 +276,7 @@ const BYTE resolve_fast_64bpp_4xmsaa_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h index 8c891d214..3dcc2a0fc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h @@ -797,10 +797,10 @@ ret const BYTE resolve_full_128bpp_cs[] = { - 68, 88, 66, 67, 138, 187, - 29, 190, 119, 248, 103, 130, - 145, 38, 138, 150, 199, 99, - 88, 186, 1, 0, 0, 0, + 68, 88, 66, 67, 21, 9, + 61, 18, 132, 97, 176, 57, + 19, 100, 60, 248, 43, 42, + 194, 237, 1, 0, 0, 0, 156, 86, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -810,7 +810,7 @@ const BYTE resolve_full_128bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h index 55de6d907..33a40c184 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_scaled_cs.h @@ -858,10 +858,10 @@ ret const BYTE resolve_full_128bpp_scaled_cs[] = { - 68, 88, 66, 67, 252, 54, - 64, 236, 181, 3, 56, 102, - 51, 248, 62, 205, 28, 164, - 215, 11, 1, 0, 0, 0, + 68, 88, 66, 67, 0, 197, + 108, 112, 31, 221, 155, 150, + 192, 148, 203, 210, 205, 214, + 112, 66, 1, 0, 0, 0, 220, 91, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -871,7 +871,7 @@ const BYTE resolve_full_128bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h index 6d6a4feb6..cfeca33cb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h @@ -1350,10 +1350,10 @@ ret const BYTE resolve_full_16bpp_cs[] = { - 68, 88, 66, 67, 85, 89, - 112, 166, 132, 95, 159, 158, - 148, 255, 182, 126, 49, 65, - 238, 68, 1, 0, 0, 0, + 68, 88, 66, 67, 122, 248, + 161, 239, 38, 34, 59, 122, + 64, 201, 159, 30, 45, 236, + 145, 6, 1, 0, 0, 0, 112, 158, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1363,7 +1363,7 @@ const BYTE resolve_full_16bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h index e1252bd02..189c65905 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_scaled_cs.h @@ -1382,10 +1382,10 @@ ret const BYTE resolve_full_16bpp_scaled_cs[] = { - 68, 88, 66, 67, 24, 35, - 27, 103, 137, 85, 99, 31, - 248, 119, 100, 82, 1, 5, - 211, 65, 1, 0, 0, 0, + 68, 88, 66, 67, 17, 196, + 248, 162, 148, 187, 123, 170, + 150, 149, 87, 23, 157, 34, + 89, 51, 1, 0, 0, 0, 188, 160, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1395,7 +1395,7 @@ const BYTE resolve_full_16bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h index e5857d3e0..3c923d804 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h @@ -1354,10 +1354,10 @@ ret const BYTE resolve_full_32bpp_cs[] = { - 68, 88, 66, 67, 191, 202, - 187, 105, 122, 172, 254, 124, - 230, 42, 42, 152, 112, 61, - 118, 194, 1, 0, 0, 0, + 68, 88, 66, 67, 6, 223, + 221, 81, 201, 228, 242, 38, + 30, 228, 108, 198, 29, 216, + 108, 219, 1, 0, 0, 0, 220, 157, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1367,7 +1367,7 @@ const BYTE resolve_full_32bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h index 1d0a0d2fe..89ca2467e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_scaled_cs.h @@ -1397,10 +1397,10 @@ ret const BYTE resolve_full_32bpp_scaled_cs[] = { - 68, 88, 66, 67, 159, 80, - 95, 78, 198, 213, 86, 238, - 93, 9, 250, 90, 57, 206, - 56, 203, 1, 0, 0, 0, + 68, 88, 66, 67, 19, 170, + 1, 90, 249, 15, 80, 164, + 255, 208, 31, 117, 114, 147, + 62, 94, 1, 0, 0, 0, 4, 162, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1410,7 +1410,7 @@ const BYTE resolve_full_32bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h index b8e43bbe1..eb712a645 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h @@ -1275,10 +1275,10 @@ ret const BYTE resolve_full_64bpp_cs[] = { - 68, 88, 66, 67, 123, 61, - 63, 178, 155, 115, 88, 68, - 202, 19, 87, 198, 58, 252, - 174, 110, 1, 0, 0, 0, + 68, 88, 66, 67, 87, 220, + 183, 187, 206, 232, 244, 147, + 255, 195, 21, 134, 69, 222, + 224, 255, 1, 0, 0, 0, 232, 147, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -1288,7 +1288,7 @@ const BYTE resolve_full_64bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h index 085b4df2e..3bd227749 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_scaled_cs.h @@ -1338,10 +1338,10 @@ ret const BYTE resolve_full_64bpp_scaled_cs[] = { - 68, 88, 66, 67, 192, 10, - 30, 169, 238, 27, 64, 245, - 27, 79, 191, 206, 88, 74, - 18, 223, 1, 0, 0, 0, + 68, 88, 66, 67, 60, 118, + 161, 100, 5, 152, 135, 130, + 31, 41, 169, 237, 170, 21, + 198, 182, 1, 0, 0, 0, 216, 153, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -1351,7 +1351,7 @@ const BYTE resolve_full_64bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h index d1b5e34c1..b1a8c9c74 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h @@ -678,10 +678,10 @@ ret const BYTE resolve_full_8bpp_cs[] = { - 68, 88, 66, 67, 253, 28, - 166, 242, 173, 99, 18, 102, - 240, 221, 130, 124, 127, 224, - 31, 30, 1, 0, 0, 0, + 68, 88, 66, 67, 160, 163, + 233, 191, 143, 128, 203, 231, + 48, 167, 197, 167, 225, 27, + 77, 108, 1, 0, 0, 0, 196, 76, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 2, 0, 0, 224, 2, @@ -691,7 +691,7 @@ const BYTE resolve_full_8bpp_cs[] = 1, 0, 0, 0, 236, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 108, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h index 0cc4578ad..5801deccd 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h @@ -720,10 +720,10 @@ ret const BYTE resolve_full_8bpp_scaled_cs[] = { - 68, 88, 66, 67, 162, 175, - 232, 246, 251, 37, 158, 3, - 20, 94, 73, 161, 62, 53, - 31, 163, 1, 0, 0, 0, + 68, 88, 66, 67, 143, 238, + 173, 2, 246, 240, 28, 191, + 52, 72, 53, 243, 190, 87, + 239, 146, 1, 0, 0, 0, 200, 80, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 56, 3, 0, 0, 72, 3, @@ -733,7 +733,7 @@ const BYTE resolve_full_8bpp_scaled_cs[] = 2, 0, 0, 0, 52, 1, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 212, 2, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h deleted file mode 100644 index 34b882a0d..000000000 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h +++ /dev/null @@ -1,167 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 10.1 -// -// -// Resource Bindings: -// -// Name Type Format Dim ID HLSL Bind Count -// ------------------------------ ---------- ------- ----------- ------- -------------- ------ -// xe_sampler_linear_clamp sampler NA NA S0 s0 1 -// xe_texture texture float3 2d T0 t0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// -ps_5_1 -dcl_globalFlags refactoringAllowed -dcl_sampler S0[0:0], mode_default, space=0 -dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 -dcl_input_ps linear v0.xy -dcl_output o0.xyzw -dcl_temps 1 -sample_l r0.xyz, v0.xyxx, T0[0].xyzw, S0[0], l(0.000000) -mov o0.xyz, r0.xyzx -mov o0.w, l(1.000000) -ret -// Approximately 4 instruction slots used -#endif - -const BYTE stretch_ps[] = -{ - 68, 88, 66, 67, 42, 105, - 40, 75, 32, 223, 178, 162, - 221, 190, 237, 193, 82, 219, - 83, 57, 1, 0, 0, 0, - 224, 2, 0, 0, 5, 0, - 0, 0, 52, 0, 0, 0, - 20, 1, 0, 0, 72, 1, - 0, 0, 124, 1, 0, 0, - 68, 2, 0, 0, 82, 68, - 69, 70, 216, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, - 175, 0, 0, 0, 19, 19, - 68, 37, 60, 0, 0, 0, - 24, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 0, 0, - 36, 0, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, - 140, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 164, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 120, 101, 95, 115, - 97, 109, 112, 108, 101, 114, - 95, 108, 105, 110, 101, 97, - 114, 95, 99, 108, 97, 109, - 112, 0, 120, 101, 95, 116, - 101, 120, 116, 117, 114, 101, - 0, 77, 105, 99, 114, 111, - 115, 111, 102, 116, 32, 40, - 82, 41, 32, 72, 76, 83, - 76, 32, 83, 104, 97, 100, - 101, 114, 32, 67, 111, 109, - 112, 105, 108, 101, 114, 32, - 49, 48, 46, 49, 0, 171, - 73, 83, 71, 78, 44, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171, 171, 171, 79, 83, - 71, 78, 44, 0, 0, 0, - 1, 0, 0, 0, 8, 0, - 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 83, 86, 95, 84, - 97, 114, 103, 101, 116, 0, - 171, 171, 83, 72, 69, 88, - 192, 0, 0, 0, 81, 0, - 0, 0, 48, 0, 0, 0, - 106, 8, 0, 1, 90, 0, - 0, 6, 70, 110, 48, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 88, 24, - 0, 7, 70, 126, 48, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 85, 85, 0, 0, 0, 0, - 0, 0, 98, 16, 0, 3, - 50, 16, 16, 0, 0, 0, - 0, 0, 101, 0, 0, 3, - 242, 32, 16, 0, 0, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 72, 0, - 0, 13, 114, 0, 16, 0, - 0, 0, 0, 0, 70, 16, - 16, 0, 0, 0, 0, 0, - 70, 126, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 96, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 0, 0, - 0, 0, 54, 0, 0, 5, - 114, 32, 16, 0, 0, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 54, 0, - 0, 5, 130, 32, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 128, 63, - 62, 0, 0, 1, 83, 84, - 65, 84, 148, 0, 0, 0, - 4, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 -}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h index 4c69634b8..a80df6cfc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_adaptive_vs.h @@ -94,10 +94,10 @@ ret const BYTE tessellation_adaptive_vs[] = { - 68, 88, 66, 67, 223, 69, - 21, 252, 96, 81, 180, 155, - 11, 146, 181, 238, 118, 211, - 188, 154, 1, 0, 0, 0, + 68, 88, 66, 67, 75, 49, + 78, 76, 10, 94, 91, 100, + 187, 17, 145, 80, 196, 255, + 224, 35, 1, 0, 0, 0, 196, 13, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 236, 10, @@ -107,7 +107,7 @@ const BYTE tessellation_adaptive_vs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h index d5126c625..5362ad6fe 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_indexed_vs.h @@ -96,10 +96,10 @@ ret const BYTE tessellation_indexed_vs[] = { - 68, 88, 66, 67, 6, 210, - 5, 58, 145, 186, 106, 71, - 191, 85, 65, 89, 187, 76, - 25, 50, 1, 0, 0, 0, + 68, 88, 66, 67, 126, 143, + 61, 16, 42, 166, 147, 123, + 54, 196, 251, 250, 225, 235, + 160, 249, 1, 0, 0, 0, 248, 13, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 184, 10, 0, 0, 236, 10, @@ -109,7 +109,7 @@ const BYTE tessellation_indexed_vs[] = 1, 0, 0, 0, 120, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, + 254, 255, 0, 5, 0, 0, 82, 10, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h index 73b94fb24..4d3c417b7 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_128bpb_cs[] = { - 68, 88, 66, 67, 69, 109, - 54, 62, 246, 252, 13, 179, - 61, 140, 108, 218, 151, 23, - 217, 10, 1, 0, 0, 0, + 68, 88, 66, 67, 202, 63, + 252, 201, 70, 118, 107, 252, + 56, 217, 121, 32, 214, 118, + 48, 42, 1, 0, 0, 0, 92, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_128bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h index 9b102e5b3..ab9c0540c 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_scaled_cs.h @@ -175,10 +175,10 @@ ret const BYTE texture_load_128bpb_scaled_cs[] = { - 68, 88, 66, 67, 152, 21, - 0, 244, 101, 90, 251, 167, - 33, 145, 108, 252, 235, 186, - 133, 5, 1, 0, 0, 0, + 68, 88, 66, 67, 0, 151, + 15, 173, 246, 165, 135, 120, + 79, 233, 110, 0, 24, 192, + 65, 142, 1, 0, 0, 0, 160, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -188,7 +188,7 @@ const BYTE texture_load_128bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h index e9e64685f..880b2d954 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h @@ -150,10 +150,10 @@ ret const BYTE texture_load_16bpb_cs[] = { - 68, 88, 66, 67, 174, 93, - 70, 99, 109, 104, 7, 76, - 197, 223, 164, 98, 22, 191, - 35, 145, 1, 0, 0, 0, + 68, 88, 66, 67, 241, 108, + 80, 210, 39, 187, 91, 178, + 204, 21, 81, 58, 61, 11, + 55, 221, 1, 0, 0, 0, 28, 17, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -163,7 +163,7 @@ const BYTE texture_load_16bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h index 488d317d3..b7e86471d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_scaled_cs.h @@ -163,10 +163,10 @@ ret const BYTE texture_load_16bpb_scaled_cs[] = { - 68, 88, 66, 67, 81, 210, - 211, 210, 188, 152, 146, 59, - 242, 122, 231, 17, 215, 172, - 246, 100, 1, 0, 0, 0, + 68, 88, 66, 67, 194, 117, + 247, 194, 178, 87, 120, 28, + 79, 25, 94, 189, 238, 128, + 139, 128, 1, 0, 0, 0, 0, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -176,7 +176,7 @@ const BYTE texture_load_16bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h index c5a0d2816..db483628e 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h @@ -161,10 +161,10 @@ ret const BYTE texture_load_32bpb_cs[] = { - 68, 88, 66, 67, 127, 41, - 115, 152, 37, 92, 49, 26, - 80, 31, 185, 102, 249, 41, - 197, 36, 1, 0, 0, 0, + 68, 88, 66, 67, 147, 100, + 112, 89, 242, 160, 225, 236, + 154, 215, 131, 75, 212, 235, + 15, 182, 1, 0, 0, 0, 204, 18, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -174,7 +174,7 @@ const BYTE texture_load_32bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h index 2619fa2f4..c4be248cc 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_scaled_cs.h @@ -180,10 +180,10 @@ ret const BYTE texture_load_32bpb_scaled_cs[] = { - 68, 88, 66, 67, 213, 122, - 184, 211, 188, 144, 40, 184, - 157, 227, 165, 48, 220, 115, - 140, 200, 1, 0, 0, 0, + 68, 88, 66, 67, 218, 190, + 24, 130, 153, 203, 104, 119, + 33, 181, 7, 206, 254, 211, + 212, 77, 1, 0, 0, 0, 108, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -193,7 +193,7 @@ const BYTE texture_load_32bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h index 8f5da5ce0..7a37abea3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_64bpb_cs[] = { - 68, 88, 66, 67, 58, 78, - 250, 228, 232, 27, 64, 158, - 177, 203, 109, 154, 100, 33, - 245, 49, 1, 0, 0, 0, + 68, 88, 66, 67, 92, 16, + 243, 45, 89, 227, 7, 187, + 59, 197, 251, 47, 47, 108, + 92, 190, 1, 0, 0, 0, 104, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_64bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h index 39c9a6d0a..61aad6d3f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_scaled_cs.h @@ -180,10 +180,10 @@ ret const BYTE texture_load_64bpb_scaled_cs[] = { - 68, 88, 66, 67, 146, 51, - 188, 210, 64, 194, 16, 242, - 150, 245, 136, 237, 175, 242, - 242, 204, 1, 0, 0, 0, + 68, 88, 66, 67, 129, 207, + 119, 119, 100, 163, 90, 188, + 114, 227, 54, 159, 242, 90, + 188, 99, 1, 0, 0, 0, 108, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -193,7 +193,7 @@ const BYTE texture_load_64bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h index 5dfaf8bb6..7d294832c 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h @@ -139,10 +139,10 @@ ret const BYTE texture_load_8bpb_cs[] = { - 68, 88, 66, 67, 94, 187, - 134, 253, 107, 160, 196, 222, - 117, 123, 98, 19, 188, 66, - 171, 48, 1, 0, 0, 0, + 68, 88, 66, 67, 78, 119, + 192, 2, 178, 124, 184, 10, + 189, 127, 69, 194, 97, 210, + 18, 48, 1, 0, 0, 0, 36, 16, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -152,7 +152,7 @@ const BYTE texture_load_8bpb_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h index 855c58e75..4a3f556f9 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_scaled_cs.h @@ -151,10 +151,10 @@ ret const BYTE texture_load_8bpb_scaled_cs[] = { - 68, 88, 66, 67, 240, 96, - 141, 60, 254, 240, 162, 218, - 255, 165, 237, 94, 178, 76, - 40, 219, 1, 0, 0, 0, + 68, 88, 66, 67, 104, 142, + 181, 219, 239, 205, 13, 249, + 232, 59, 4, 117, 104, 185, + 138, 244, 1, 0, 0, 0, 252, 17, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -164,7 +164,7 @@ const BYTE texture_load_8bpb_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h index a275eadb2..706bee507 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h @@ -498,10 +498,10 @@ ret const BYTE texture_load_ctx1_cs[] = { - 68, 88, 66, 67, 218, 197, - 112, 160, 14, 201, 105, 66, - 53, 47, 83, 103, 144, 212, - 96, 106, 1, 0, 0, 0, + 68, 88, 66, 67, 224, 177, + 169, 46, 201, 156, 106, 177, + 123, 25, 97, 64, 20, 172, + 37, 106, 1, 0, 0, 0, 116, 65, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -511,7 +511,7 @@ const BYTE texture_load_ctx1_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h index 8dced34cb..143b2359f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h @@ -193,10 +193,10 @@ ret const BYTE texture_load_depth_float_cs[] = { - 68, 88, 66, 67, 204, 91, - 20, 67, 68, 27, 100, 159, - 55, 40, 24, 32, 240, 93, - 21, 161, 1, 0, 0, 0, + 68, 88, 66, 67, 118, 118, + 229, 207, 223, 43, 191, 129, + 46, 182, 152, 168, 144, 51, + 219, 93, 1, 0, 0, 0, 180, 23, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -206,7 +206,7 @@ const BYTE texture_load_depth_float_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h index d73996e19..31ec2d1af 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_scaled_cs.h @@ -212,10 +212,10 @@ ret const BYTE texture_load_depth_float_scaled_cs[] = { - 68, 88, 66, 67, 97, 66, - 8, 141, 64, 232, 246, 129, - 214, 180, 240, 206, 10, 93, - 136, 7, 1, 0, 0, 0, + 68, 88, 66, 67, 88, 225, + 211, 33, 229, 40, 36, 2, + 174, 238, 58, 147, 100, 14, + 137, 242, 1, 0, 0, 0, 84, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -225,7 +225,7 @@ const BYTE texture_load_depth_float_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h index 1824bb5c2..2aa17af24 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h @@ -171,10 +171,10 @@ ret const BYTE texture_load_depth_unorm_cs[] = { - 68, 88, 66, 67, 69, 6, - 138, 33, 133, 185, 5, 144, - 97, 147, 106, 215, 106, 118, - 65, 58, 1, 0, 0, 0, + 68, 88, 66, 67, 164, 201, + 22, 59, 241, 134, 166, 121, + 89, 49, 109, 127, 19, 134, + 179, 77, 1, 0, 0, 0, 28, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -184,7 +184,7 @@ const BYTE texture_load_depth_unorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h index d877269d3..60e54685b 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_scaled_cs.h @@ -190,10 +190,10 @@ ret const BYTE texture_load_depth_unorm_scaled_cs[] = { - 68, 88, 66, 67, 171, 5, - 112, 51, 93, 95, 86, 30, - 36, 93, 246, 161, 8, 191, - 36, 204, 1, 0, 0, 0, + 68, 88, 66, 67, 46, 48, + 136, 105, 27, 59, 153, 68, + 207, 149, 101, 215, 91, 14, + 213, 200, 1, 0, 0, 0, 188, 22, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -203,7 +203,7 @@ const BYTE texture_load_depth_unorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h index 0c1582b51..e2f833cab 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h @@ -756,10 +756,10 @@ ret const BYTE texture_load_dxn_rg8_cs[] = { - 68, 88, 66, 67, 211, 36, - 163, 209, 153, 81, 143, 128, - 61, 32, 177, 173, 61, 97, - 58, 73, 1, 0, 0, 0, + 68, 88, 66, 67, 58, 123, + 85, 153, 121, 158, 245, 188, + 30, 31, 213, 99, 33, 63, + 238, 113, 1, 0, 0, 0, 152, 107, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -769,7 +769,7 @@ const BYTE texture_load_dxn_rg8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h index f19eb9d29..d929471f2 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h @@ -964,10 +964,10 @@ ret const BYTE texture_load_dxt1_rgba8_cs[] = { - 68, 88, 66, 67, 171, 63, - 106, 29, 93, 176, 47, 157, - 131, 34, 243, 102, 115, 232, - 70, 144, 1, 0, 0, 0, + 68, 88, 66, 67, 162, 2, + 233, 77, 119, 170, 48, 9, + 89, 123, 33, 178, 116, 19, + 98, 50, 1, 0, 0, 0, 72, 139, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -977,7 +977,7 @@ const BYTE texture_load_dxt1_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h index e28a1380c..153919e73 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h @@ -402,10 +402,10 @@ ret const BYTE texture_load_dxt3_rgba8_cs[] = { - 68, 88, 66, 67, 202, 139, - 131, 58, 228, 184, 167, 198, - 214, 82, 38, 18, 195, 26, - 166, 103, 1, 0, 0, 0, + 68, 88, 66, 67, 12, 204, + 97, 23, 183, 245, 147, 165, + 41, 149, 238, 95, 107, 29, + 121, 103, 1, 0, 0, 0, 200, 53, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -415,7 +415,7 @@ const BYTE texture_load_dxt3_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h index d9525a0e3..a5cb13f4d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h @@ -223,10 +223,10 @@ ret const BYTE texture_load_dxt3a_cs[] = { - 68, 88, 66, 67, 161, 154, - 167, 17, 42, 20, 207, 220, - 166, 224, 185, 142, 22, 195, - 81, 32, 1, 0, 0, 0, + 68, 88, 66, 67, 104, 192, + 139, 183, 85, 14, 81, 232, + 35, 168, 116, 5, 160, 169, + 85, 249, 1, 0, 0, 0, 208, 28, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -236,7 +236,7 @@ const BYTE texture_load_dxt3a_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h index 70f0637e5..0b2a5e780 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h @@ -388,10 +388,10 @@ ret const BYTE texture_load_dxt3aas1111_cs[] = { - 68, 88, 66, 67, 90, 5, - 35, 3, 92, 51, 204, 73, - 141, 97, 178, 144, 202, 117, - 220, 55, 1, 0, 0, 0, + 68, 88, 66, 67, 22, 23, + 173, 181, 12, 133, 91, 227, + 193, 248, 70, 118, 201, 133, + 160, 27, 1, 0, 0, 0, 116, 60, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -401,7 +401,7 @@ const BYTE texture_load_dxt3aas1111_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h index 4b7c67107..4ed638286 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h @@ -904,10 +904,10 @@ ret const BYTE texture_load_dxt5_rgba8_cs[] = { - 68, 88, 66, 67, 180, 185, - 178, 42, 202, 99, 164, 29, - 112, 142, 14, 240, 160, 77, - 17, 147, 1, 0, 0, 0, + 68, 88, 66, 67, 174, 151, + 189, 10, 239, 215, 42, 88, + 164, 121, 146, 214, 247, 6, + 218, 92, 1, 0, 0, 0, 136, 117, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -917,7 +917,7 @@ const BYTE texture_load_dxt5_rgba8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h index df0266f2c..6f24b0572 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h @@ -820,10 +820,10 @@ ret const BYTE texture_load_dxt5a_r8_cs[] = { - 68, 88, 66, 67, 26, 197, - 196, 184, 97, 248, 148, 119, - 98, 119, 209, 241, 44, 179, - 197, 227, 1, 0, 0, 0, + 68, 88, 66, 67, 254, 188, + 43, 237, 174, 91, 14, 57, + 46, 249, 95, 48, 189, 201, + 171, 161, 1, 0, 0, 0, 36, 112, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -833,7 +833,7 @@ const BYTE texture_load_dxt5a_r8_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h index d4719dafd..67c0cbdb1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h @@ -206,10 +206,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_cs[] = { - 68, 88, 66, 67, 131, 13, - 20, 178, 131, 231, 128, 185, - 113, 12, 55, 205, 96, 44, - 175, 81, 1, 0, 0, 0, + 68, 88, 66, 67, 47, 2, + 160, 5, 228, 91, 168, 34, + 190, 254, 217, 6, 7, 78, + 252, 141, 1, 0, 0, 0, 44, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -219,7 +219,7 @@ const BYTE texture_load_r10g11b11_rgba16_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h index 867dace24..ff438bf21 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_scaled_cs.h @@ -224,10 +224,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_scaled_cs[] = { - 68, 88, 66, 67, 155, 144, - 74, 111, 245, 166, 226, 11, - 144, 219, 119, 58, 140, 196, - 87, 164, 1, 0, 0, 0, + 68, 88, 66, 67, 20, 16, + 81, 114, 70, 228, 22, 196, + 107, 196, 190, 30, 167, 28, + 162, 144, 1, 0, 0, 0, 176, 28, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -237,7 +237,7 @@ const BYTE texture_load_r10g11b11_rgba16_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h index d0f2a724a..a64921485 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h @@ -316,10 +316,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_snorm_cs[] = { - 68, 88, 66, 67, 132, 107, - 13, 78, 171, 0, 197, 83, - 243, 104, 225, 235, 102, 35, - 191, 255, 1, 0, 0, 0, + 68, 88, 66, 67, 126, 137, + 222, 85, 154, 50, 59, 65, + 64, 122, 77, 236, 149, 56, + 130, 232, 1, 0, 0, 0, 228, 41, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -329,7 +329,7 @@ const BYTE texture_load_r10g11b11_rgba16_snorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h index b5fa9cff7..980a7d8bb 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_scaled_cs.h @@ -334,10 +334,10 @@ ret const BYTE texture_load_r10g11b11_rgba16_snorm_scaled_cs[] = { - 68, 88, 66, 67, 162, 29, - 212, 129, 112, 166, 188, 86, - 123, 71, 28, 10, 208, 33, - 149, 252, 1, 0, 0, 0, + 68, 88, 66, 67, 143, 241, + 241, 106, 117, 162, 243, 107, + 211, 190, 66, 35, 157, 41, + 39, 22, 1, 0, 0, 0, 104, 44, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -347,7 +347,7 @@ const BYTE texture_load_r10g11b11_rgba16_snorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h index a9c2bfa67..571407a24 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h @@ -210,10 +210,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_cs[] = { - 68, 88, 66, 67, 140, 202, - 56, 216, 12, 60, 186, 15, - 110, 177, 222, 251, 148, 130, - 188, 179, 1, 0, 0, 0, + 68, 88, 66, 67, 128, 35, + 108, 79, 134, 63, 204, 101, + 37, 250, 141, 229, 110, 97, + 86, 185, 1, 0, 0, 0, 124, 26, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -223,7 +223,7 @@ const BYTE texture_load_r11g11b10_rgba16_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h index dcd872964..dc090002d 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_scaled_cs.h @@ -228,10 +228,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_scaled_cs[] = { - 68, 88, 66, 67, 137, 198, - 120, 58, 180, 179, 225, 37, - 185, 213, 74, 210, 172, 40, - 217, 34, 1, 0, 0, 0, + 68, 88, 66, 67, 71, 13, + 151, 213, 246, 156, 242, 12, + 33, 146, 244, 98, 204, 37, + 211, 102, 1, 0, 0, 0, 0, 29, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -241,7 +241,7 @@ const BYTE texture_load_r11g11b10_rgba16_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h index 655fc1cc3..41980c994 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h @@ -316,10 +316,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_snorm_cs[] = { - 68, 88, 66, 67, 213, 22, - 164, 196, 90, 153, 244, 222, - 212, 71, 213, 96, 207, 65, - 216, 237, 1, 0, 0, 0, + 68, 88, 66, 67, 148, 131, + 162, 115, 4, 155, 42, 57, + 217, 241, 77, 237, 50, 228, + 133, 33, 1, 0, 0, 0, 228, 41, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -329,7 +329,7 @@ const BYTE texture_load_r11g11b10_rgba16_snorm_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h index 0e333a659..500db9f89 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_scaled_cs.h @@ -334,10 +334,10 @@ ret const BYTE texture_load_r11g11b10_rgba16_snorm_scaled_cs[] = { - 68, 88, 66, 67, 161, 142, - 120, 161, 78, 207, 43, 55, - 216, 104, 110, 214, 21, 94, - 233, 199, 1, 0, 0, 0, + 68, 88, 66, 67, 75, 177, + 94, 135, 174, 139, 119, 66, + 179, 219, 255, 123, 200, 30, + 105, 239, 1, 0, 0, 0, 104, 44, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -347,7 +347,7 @@ const BYTE texture_load_r11g11b10_rgba16_snorm_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h index 351327ab6..bbdade597 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r4g4b4a4_b4g4r4a4_cs[] = { - 68, 88, 66, 67, 123, 178, - 4, 149, 160, 65, 196, 92, - 197, 33, 231, 200, 130, 56, - 69, 71, 1, 0, 0, 0, + 68, 88, 66, 67, 49, 31, + 131, 53, 100, 96, 178, 5, + 2, 82, 81, 83, 23, 105, + 45, 74, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r4g4b4a4_b4g4r4a4_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h index c96fe8c51..7e639b240 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r4g4b4a4_b4g4r4a4_scaled_cs[] = { - 68, 88, 66, 67, 217, 199, - 168, 29, 226, 179, 202, 87, - 196, 221, 10, 176, 71, 209, - 93, 59, 1, 0, 0, 0, + 68, 88, 66, 67, 77, 180, + 20, 47, 174, 216, 74, 169, + 81, 35, 81, 193, 58, 15, + 131, 7, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r4g4b4a4_b4g4r4a4_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h index ba3b52739..fcd9812cd 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r5g5b5a1_b5g5r5a1_cs[] = { - 68, 88, 66, 67, 135, 143, - 167, 233, 77, 208, 99, 166, - 216, 43, 121, 223, 203, 20, - 55, 249, 1, 0, 0, 0, + 68, 88, 66, 67, 142, 91, + 118, 66, 49, 193, 130, 167, + 134, 65, 2, 182, 229, 160, + 140, 89, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r5g5b5a1_b5g5r5a1_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h index 35ef6c89b..12cc39ab1 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r5g5b5a1_b5g5r5a1_scaled_cs[] = { - 68, 88, 66, 67, 82, 18, - 33, 217, 174, 124, 154, 217, - 180, 135, 1, 110, 160, 231, - 43, 26, 1, 0, 0, 0, + 68, 88, 66, 67, 118, 127, + 179, 72, 186, 4, 108, 94, + 144, 13, 145, 177, 14, 255, + 152, 175, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r5g5b5a1_b5g5r5a1_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/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 index a6d581bb4..71dfe6ea8 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/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 @@ -160,10 +160,10 @@ ret const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs[] = { - 68, 88, 66, 67, 53, 93, - 80, 84, 203, 45, 115, 170, - 188, 117, 87, 176, 190, 115, - 70, 191, 1, 0, 0, 0, + 68, 88, 66, 67, 242, 245, + 114, 197, 70, 66, 49, 31, + 114, 195, 63, 33, 103, 191, + 133, 52, 1, 0, 0, 0, 148, 18, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -173,7 +173,7 @@ const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h index b7ed1f186..30c8a1951 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs.h @@ -173,10 +173,10 @@ ret const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs[] = { - 68, 88, 66, 67, 4, 135, - 9, 244, 156, 123, 41, 147, - 145, 234, 137, 185, 2, 70, - 230, 241, 1, 0, 0, 0, + 68, 88, 66, 67, 224, 225, + 230, 21, 25, 203, 114, 212, + 208, 192, 99, 236, 28, 219, + 255, 255, 1, 0, 0, 0, 120, 20, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -186,7 +186,7 @@ const BYTE texture_load_r5g5b6_b5g6r5_swizzle_rbga_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h index fa0ac7235..279724d2f 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h @@ -164,10 +164,10 @@ ret const BYTE texture_load_r5g6b5_b5g6r5_cs[] = { - 68, 88, 66, 67, 27, 115, - 39, 235, 56, 147, 179, 61, - 11, 80, 115, 207, 237, 93, - 153, 217, 1, 0, 0, 0, + 68, 88, 66, 67, 127, 73, + 53, 241, 142, 177, 61, 101, + 28, 212, 103, 166, 115, 116, + 219, 222, 1, 0, 0, 0, 28, 19, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -177,7 +177,7 @@ const BYTE texture_load_r5g6b5_b5g6r5_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h index 8c6ef5b3e..d9849b0c3 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h +++ b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_scaled_cs.h @@ -177,10 +177,10 @@ ret const BYTE texture_load_r5g6b5_b5g6r5_scaled_cs[] = { - 68, 88, 66, 67, 188, 32, - 89, 167, 62, 193, 205, 149, - 127, 86, 15, 49, 116, 163, - 146, 187, 1, 0, 0, 0, + 68, 88, 66, 67, 80, 139, + 235, 77, 41, 132, 249, 150, + 54, 120, 97, 180, 209, 107, + 181, 68, 1, 0, 0, 0, 0, 21, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 4, 0, 0, 44, 4, @@ -190,7 +190,7 @@ const BYTE texture_load_r5g6b5_b5g6r5_scaled_cs[] = 1, 0, 0, 0, 248, 0, 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 83, 67, 0, 5, 4, 0, + 83, 67, 0, 5, 0, 0, 181, 3, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl b/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl deleted file mode 100644 index e862f0b7c..000000000 --- a/src/xenia/gpu/shaders/fullscreen_tc.vs.hlsl +++ /dev/null @@ -1,7 +0,0 @@ -// A triangle covering the whole viewport. -void main(uint xe_vertex_id : SV_VertexID, out float2 xe_texcoord : TEXCOORD, - out float4 xe_position : SV_Position) { - xe_texcoord = float2(uint2(xe_vertex_id, xe_vertex_id << 1u) & 2u); - xe_position = - float4(xe_texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); -} diff --git a/src/xenia/gpu/shaders/fxaa.cs.hlsl b/src/xenia/gpu/shaders/fxaa.cs.hlsl new file mode 100644 index 000000000..74a9032bb --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa.cs.hlsl @@ -0,0 +1,5 @@ +#define FXAA_QUALITY__PRESET 12 +#define FXAA_QUALITY__SUBPIX 0.75 +#define FXAA_QUALITY__EDGE_THRESHOLD 0.166 +#define FXAA_QUALITY__EDGE_THRESHOLD_MIN 0.0833 +#include "fxaa.hlsli" diff --git a/src/xenia/gpu/shaders/fxaa.hlsli b/src/xenia/gpu/shaders/fxaa.hlsli new file mode 100644 index 000000000..f20fdd4a5 --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa.hlsli @@ -0,0 +1,48 @@ +// Inputs: +// - FXAA_QUALITY__PRESET +// - FXAA_QUALITY__SUBPIX +// - FXAA_QUALITY__EDGE_THRESHOLD +// - FXAA_QUALITY__EDGE_THRESHOLD_MIN + +// "use of potentially uninitialized variable" in FxaaPixelShader due to the +// early exit with a `return` in the beginning of the function, caused by a bug +// in FXC (the warning is common for early exiting in HLSL in general). +#pragma warning(disable: 4000) + +cbuffer XeApplyGammaRampConstants : register(b0) { + uint2 xe_fxaa_size; + float2 xe_fxaa_size_inv; +}; + +RWTexture2D xe_fxaa_dest : register(u0); +Texture2D xe_fxaa_source : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +#define FXAA_PC 1 +#define FXAA_HLSL_5 1 +#include "../../../../third_party/fxaa/FXAA3_11.h" + +[numthreads(8, 8, 1)] +void main(uint3 xe_thread_id : SV_DispatchThreadID) { + [branch] if (any(xe_thread_id.xy >= xe_fxaa_size)) { + return; + } + FxaaTex fxaa_texture; + fxaa_texture.smpl = xe_sampler_linear_clamp; + fxaa_texture.tex = xe_fxaa_source; + // Force alpha to 1 to simplify calculations, won't need it anymore anyway. + xe_fxaa_dest[xe_thread_id.xy] = + float4( + FxaaPixelShader( + (float2(xe_thread_id.xy) + 0.5) * xe_fxaa_size_inv, + (float2(xe_thread_id.xy).xyxy + float2(0.0, 1.0).xxyy) * + xe_fxaa_size_inv.xyxy, + fxaa_texture, fxaa_texture, fxaa_texture, xe_fxaa_size_inv, + float2(-0.5, 0.5).xxyy * xe_fxaa_size_inv.xyxy, + float2(-2.0, 2.0).xxyy * xe_fxaa_size_inv.xyxy, + float2(8.0, -4.0).xxyy * xe_fxaa_size_inv.xyxy, + FXAA_QUALITY__SUBPIX, FXAA_QUALITY__EDGE_THRESHOLD, + FXAA_QUALITY__EDGE_THRESHOLD_MIN, 8.0, 0.125, 0.05, + float4(1.0, -1.0, 0.25, -0.25)).rgb, + 1.0); +} diff --git a/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl b/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl new file mode 100644 index 000000000..68eb85b96 --- /dev/null +++ b/src/xenia/gpu/shaders/fxaa_extreme.cs.hlsl @@ -0,0 +1,5 @@ +#define FXAA_QUALITY__PRESET 39 +#define FXAA_QUALITY__SUBPIX 1.0 +#define FXAA_QUALITY__EDGE_THRESHOLD 0.063 +#define FXAA_QUALITY__EDGE_THRESHOLD_MIN 0.0312 +#include "fxaa.hlsli" diff --git a/src/xenia/gpu/shaders/stretch.ps.hlsl b/src/xenia/gpu/shaders/stretch.ps.hlsl deleted file mode 100644 index c7a568434..000000000 --- a/src/xenia/gpu/shaders/stretch.ps.hlsl +++ /dev/null @@ -1,8 +0,0 @@ -Texture2D xe_texture : register(t0); -SamplerState xe_sampler_linear_clamp : register(s0); - -float4 main(float2 xe_texcoord : TEXCOORD) : SV_Target { - // Force alpha to 1 to make sure the surface won't be translucent. - return float4( - xe_texture.SampleLevel(xe_sampler_linear_clamp, xe_texcoord, 0.0f), 1.0f); -} diff --git a/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl b/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl deleted file mode 100644 index a13e333a8..000000000 --- a/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl +++ /dev/null @@ -1,20 +0,0 @@ -Texture2D xe_texture : register(t0); -Texture1D xe_gamma_ramp : register(t1); -SamplerState xe_sampler_linear_clamp : register(s0); -cbuffer XeStretchGammaRootConstants : register(b0) { - float xe_gamma_ramp_inv_size; -}; - -float4 main(float2 xe_texcoord : TEXCOORD) : SV_Target { - float3 color = - xe_texture.SampleLevel(xe_sampler_linear_clamp, xe_texcoord, 0.0f); - // The center of the first texel of the LUT contains the value for 0, and the - // center of the last texel contains the value for 1. - color = - color * (1.0f - xe_gamma_ramp_inv_size) + (0.5 * xe_gamma_ramp_inv_size); - color.r = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.r, 0.0f).r; - color.g = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.g, 0.0f).g; - color.b = xe_gamma_ramp.SampleLevel(xe_sampler_linear_clamp, color.b, 0.0f).b; - // Force alpha to 1 to make sure the surface won't be translucent. - return float4(color, 1.0f); -} diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc index a78964d14..2932a4110 100644 --- a/src/xenia/gpu/trace_dump.cc +++ b/src/xenia/gpu/trace_dump.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,6 +18,7 @@ #include "xenia/gpu/graphics_system.h" #include "xenia/memory.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" #include "xenia/xbox.h" @@ -94,7 +95,8 @@ bool TraceDump::Setup() { // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); + nullptr, nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, + nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); return false; @@ -125,18 +127,19 @@ int TraceDump::Run() { // Capture. int result = 0; - auto raw_image = graphics_system_->Capture(); - if (raw_image) { + ui::Presenter* presenter = graphics_system_->presenter(); + ui::RawImage raw_image; + if (presenter && presenter->CaptureGuestOutput(raw_image)) { // Save framebuffer png. auto png_path = base_output_path_.replace_extension(".png"); auto handle = filesystem::OpenFile(png_path, "wb"); auto callback = [](void* context, void* data, int size) { fwrite(data, 1, size, (FILE*)context); }; - stbi_write_png_to_func(callback, handle, static_cast(raw_image->width), - static_cast(raw_image->height), 4, - raw_image->data.data(), - static_cast(raw_image->stride)); + stbi_write_png_to_func(callback, handle, static_cast(raw_image.width), + static_cast(raw_image.height), 4, + raw_image.data.data(), + static_cast(raw_image.stride)); fclose(handle); } else { result = 1; diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 8f2c98b8a..54db1156c 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -87,15 +87,19 @@ void TracePlayer::PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches) { playing_trace_ = true; + // Pass a copy of present_last_copy_ to the thread so it's not accessible by + // multiple threads at once. + bool present_last_copy = present_last_copy_; graphics_system_->command_processor()->CallInThread([=]() { - PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches); + PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches, + present_last_copy); }); } void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, - bool clear_caches) { + bool clear_caches, bool present_last_copy) { auto memory = graphics_system_->memory(); auto command_processor = graphics_system_->command_processor(); @@ -103,7 +107,10 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, command_processor->ClearCaches(); } - command_processor->set_swap_mode(SwapMode::kIgnored); + if (present_last_copy) { + command_processor->SetIgnoreSwap(true); + } + playback_percent_ = 0; auto trace_end = trace_data + trace_size; @@ -215,8 +222,11 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, } playing_trace_ = false; - command_processor->set_swap_mode(SwapMode::kNormal); - command_processor->IssueSwap(0, 1280, 720); + + if (present_last_copy) { + command_processor->SetIgnoreSwap(false); + command_processor->IssueSwap(0, 1280, 720); + } playback_event_->Set(); } diff --git a/src/xenia/gpu/trace_player.h b/src/xenia/gpu/trace_player.h index d56205d59..cfc2702a1 100644 --- a/src/xenia/gpu/trace_player.h +++ b/src/xenia/gpu/trace_player.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -33,6 +33,9 @@ class TracePlayer : public TraceReader { ~TracePlayer() override; GraphicsSystem* graphics_system() const { return graphics_system_; } + void SetPresentLastCopy(bool present_last_copy) { + present_last_copy_ = present_last_copy; + } int current_frame_index() const { return current_frame_index_; } int current_command_index() const { return current_command_index_; } bool is_playing_trace() const { return playing_trace_; } @@ -51,9 +54,13 @@ class TracePlayer : public TraceReader { void PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches); void PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, - TracePlaybackMode playback_mode, bool clear_caches); + TracePlaybackMode playback_mode, bool clear_caches, + bool present_last_copy); GraphicsSystem* graphics_system_; + // Whether to present the results of the latest resolve instead of displaying + // the front buffer from the trace. + bool present_last_copy_ = false; int current_frame_index_; int current_command_index_; bool playing_trace_ = false; diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index d5f389276..660f24805 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,6 +30,9 @@ #include "xenia/memory.h" #include "xenia/ui/file_picker.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" @@ -51,7 +54,8 @@ static const ImVec4 kColorIgnored = TraceViewer::TraceViewer(xe::ui::WindowedAppContext& app_context, const std::string_view name) - : xe::ui::WindowedApp(app_context, name, "some.trace") { + : xe::ui::WindowedApp(app_context, name, "some.trace"), + window_listener_(*this) { AddPositionalOption("target_trace_file"); } @@ -102,22 +106,27 @@ bool TraceViewer::OnInitialize() { } bool TraceViewer::Setup() { + enum : size_t { + kZOrderImGui, + kZOrderTraceViewerInput, + }; + // Main display window. assert_true(app_context().IsInUIThread()); - window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer"); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); + window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer", + 1920, 1200); + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderTraceViewerInput); + if (!window_->Open()) { + XELOGE("Failed to open the main window"); return false; } - window_->on_closed.AddListener( - [this](xe::ui::UIEvent* e) { app_context().QuitFromUIThread(); }); - window_->Resize(1920, 1200); // Create the emulator but don't initialize so we can setup the window. emulator_ = std::make_unique("", "", "", ""); X_STATUS result = emulator_->Setup( - window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); }, - nullptr); + window_.get(), nullptr, nullptr, + [this]() { return CreateGraphicsSystem(); }, nullptr); if (XFAILED(result)) { XELOGE("Failed to setup emulator: {:08X}", result); return false; @@ -125,31 +134,55 @@ bool TraceViewer::Setup() { memory_ = emulator_->memory(); graphics_system_ = emulator_->graphics_system(); - window_->set_imgui_input_enabled(true); - - window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) { - if (e->virtual_key() == xe::ui::VirtualKey::kF5) { - graphics_system_->ClearCaches(); - e->set_handled(true); - } - }); - player_ = std::make_unique(graphics_system_); + player_->SetPresentLastCopy(true); - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - DrawUI(); - - // Continuous paint. - window_->Invalidate(); - }); - window_->Invalidate(); + // Setup drawing to the window. + xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider(); + presenter_ = graphics_provider.CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } + immediate_drawer_ = graphics_provider.CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + imgui_drawer_ = + std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + trace_viewer_dialog_ = std::unique_ptr( + new TraceViewerDialog(imgui_drawer_.get(), *this)); + window_->SetPresenter(presenter_.get()); return true; } +void TraceViewer::TraceViewerWindowListener::OnClosing(xe::ui::UIEvent& e) { + trace_viewer_.app_context().QuitFromUIThread(); +} + +void TraceViewer::TraceViewerWindowListener::OnKeyDown(xe::ui::KeyEvent& e) { + switch (e.virtual_key()) { + case xe::ui::VirtualKey::kF5: + trace_viewer_.graphics_system_->ClearCaches(); + break; + default: + return; + } + e.set_handled(true); +} + +void TraceViewer::TraceViewerDialog::OnDraw(ImGuiIO& io) { + trace_viewer_.DrawUI(); +} + bool TraceViewer::Load(const std::filesystem::path& trace_file_path) { auto file_name = trace_file_path.filename(); - window_->set_title("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name)); + window_->SetTitle("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name)); if (!player_->Open(trace_file_path)) { XELOGE("Could not load trace file"); @@ -233,8 +266,9 @@ void TraceViewer::DrawControllerUI() { void TraceViewer::DrawPacketDisassemblerUI() { ImGui::SetNextWindowCollapsed(true, ImGuiCond_FirstUseEver); - ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 5), - ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos( + ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 5), + ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(500, 300)); if (!ImGui::Begin("Packet Disassembler", nullptr)) { ImGui::End(); @@ -1052,8 +1086,9 @@ void TraceViewer::DrawStateUI() { auto command_processor = graphics_system_->command_processor(); auto& regs = *graphics_system_->register_file(); - ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 30), - ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos( + ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 30), + ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(500, 680)); if (!ImGui::Begin("State", nullptr)) { ImGui::End(); diff --git a/src/xenia/gpu/trace_viewer.h b/src/xenia/gpu/trace_viewer.h index 1e22439fb..ecca12792 100644 --- a/src/xenia/gpu/trace_viewer.h +++ b/src/xenia/gpu/trace_viewer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,7 +18,12 @@ #include "xenia/gpu/trace_protocol.h" #include "xenia/gpu/xenos.h" #include "xenia/memory.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" namespace xe { @@ -38,6 +43,7 @@ class TraceViewer : public xe::ui::WindowedApp { const std::string_view name); virtual std::unique_ptr CreateGraphicsSystem() = 0; + GraphicsSystem* graphics_system() const { return graphics_system_; } void DrawMultilineString(const std::string_view str); @@ -56,13 +62,34 @@ class TraceViewer : public xe::ui::WindowedApp { virtual bool Setup(); - std::unique_ptr window_; - std::unique_ptr emulator_; - Memory* memory_ = nullptr; - GraphicsSystem* graphics_system_ = nullptr; - std::unique_ptr player_; - private: + class TraceViewerWindowListener final : public xe::ui::WindowListener, + public xe::ui::WindowInputListener { + public: + explicit TraceViewerWindowListener(TraceViewer& trace_viewer) + : trace_viewer_(trace_viewer) {} + + void OnClosing(xe::ui::UIEvent& e) override; + + void OnKeyDown(xe::ui::KeyEvent& e) override; + + private: + TraceViewer& trace_viewer_; + }; + + class TraceViewerDialog final : public ui::ImGuiDialog { + public: + explicit TraceViewerDialog(xe::ui::ImGuiDrawer* imgui_drawer, + TraceViewer& trace_viewer) + : xe::ui::ImGuiDialog(imgui_drawer), trace_viewer_(trace_viewer) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + TraceViewer& trace_viewer_; + }; + enum class ShaderDisplayType : int { kUcode, kTranslated, @@ -92,6 +119,20 @@ class TraceViewer : public xe::ui::WindowedApp { void DrawVertexFetcher(Shader* shader, const Shader::VertexBinding& vertex_binding, const xenos::xe_gpu_vertex_fetch_t* fetch); + + TraceViewerWindowListener window_listener_; + + std::unique_ptr window_; + + std::unique_ptr emulator_; + Memory* memory_ = nullptr; + GraphicsSystem* graphics_system_ = nullptr; + std::unique_ptr player_; + + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr trace_viewer_dialog_; }; } // namespace gpu diff --git a/src/xenia/gpu/vulkan/buffer_cache.cc b/src/xenia/gpu/vulkan/buffer_cache.cc index 0e4b73163..6ef89b289 100644 --- a/src/xenia/gpu/vulkan/buffer_cache.cc +++ b/src/xenia/gpu/vulkan/buffer_cache.cc @@ -16,6 +16,7 @@ #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h" #include "xenia/ui/vulkan/vulkan_mem_alloc.h" +#include "xenia/ui/vulkan/vulkan_util.h" using namespace xe::gpu::xenos; @@ -91,16 +92,17 @@ void copy_cmp_swap_32_unaligned(void* dest_ptr, const void* src_ptr, } #endif -using xe::ui::vulkan::CheckResult; +using xe::ui::vulkan::util::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) { + const ui::vulkan::VulkanProvider& provider, + size_t capacity) + : register_file_(register_file), memory_(memory), provider_(provider) { transient_buffer_ = std::make_unique( - device_, + provider_, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, capacity, 256); @@ -109,23 +111,41 @@ BufferCache::BufferCache(RegisterFile* register_file, Memory* memory, BufferCache::~BufferCache() { Shutdown(); } VkResult BufferCache::Initialize() { + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + VkResult status = VK_SUCCESS; + VkMemoryRequirements pool_reqs; transient_buffer_->GetBufferMemoryRequirements(&pool_reqs); - gpu_memory_pool_ = device_->AllocateMemory(pool_reqs); + VkMemoryAllocateInfo pool_allocate_info; + pool_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + pool_allocate_info.pNext = nullptr; + pool_allocate_info.allocationSize = pool_reqs.size; + pool_allocate_info.memoryTypeIndex = ui::vulkan::util::ChooseHostMemoryType( + provider_, pool_reqs.memoryTypeBits, false); + if (pool_allocate_info.memoryTypeIndex == UINT32_MAX) { + return VK_ERROR_INITIALIZATION_FAILED; + } + status = dfn.vkAllocateMemory(device, &pool_allocate_info, nullptr, + &gpu_memory_pool_); + if (status != VK_SUCCESS) { + return status; + } - VkResult status = transient_buffer_->Initialize(gpu_memory_pool_, 0); + 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, *device_); - - VmaAllocatorCreateInfo alloc_info = { - 0, *device_, *device_, 0, 0, nullptr, nullptr, 0, nullptr, &vulkan_funcs, - }; + ui::vulkan::FillVMAVulkanFunctions(&vulkan_funcs, provider_); + VmaAllocatorCreateInfo alloc_info = {}; + alloc_info.physicalDevice = provider_.physical_device(); + alloc_info.device = device; + alloc_info.pVulkanFunctions = &vulkan_funcs; + alloc_info.instance = provider_.instance(); status = vmaCreateAllocator(&alloc_info, &mem_allocator_); if (status != VK_SUCCESS) { return status; @@ -145,7 +165,8 @@ VkResult BufferCache::Initialize() { } VkResult BufferCache::CreateVertexDescriptorPool() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status; std::vector pool_sizes; @@ -154,7 +175,7 @@ VkResult BufferCache::CreateVertexDescriptorPool() { 32 * 16384, }); vertex_descriptor_pool_ = std::make_unique( - *device_, 32 * 16384, pool_sizes); + provider_, 32 * 16384, pool_sizes); // 32 storage buffers available to vertex shader. // TODO(DrChat): In the future, this could hold memexport staging data. @@ -171,7 +192,7 @@ VkResult BufferCache::CreateVertexDescriptorPool() { 1, &binding, }; - status = dfn.vkCreateDescriptorSetLayout(*device_, &layout_info, nullptr, + status = dfn.vkCreateDescriptorSetLayout(device, &layout_info, nullptr, &vertex_descriptor_set_layout_); if (status != VK_SUCCESS) { return status; @@ -183,13 +204,15 @@ VkResult BufferCache::CreateVertexDescriptorPool() { void BufferCache::FreeVertexDescriptorPool() { vertex_descriptor_pool_.reset(); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, *device_, - vertex_descriptor_set_layout_); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, + device, vertex_descriptor_set_layout_); } VkResult BufferCache::CreateConstantDescriptorSet() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Descriptor pool used for all of our cached descriptors. @@ -207,7 +230,7 @@ VkResult BufferCache::CreateConstantDescriptorSet() { pool_sizes[0].descriptorCount = 2; transient_descriptor_pool_info.poolSizeCount = 1; transient_descriptor_pool_info.pPoolSizes = pool_sizes; - status = dfn.vkCreateDescriptorPool(*device_, &transient_descriptor_pool_info, + status = dfn.vkCreateDescriptorPool(device, &transient_descriptor_pool_info, nullptr, &constant_descriptor_pool_); if (status != VK_SUCCESS) { return status; @@ -240,8 +263,8 @@ VkResult BufferCache::CreateConstantDescriptorSet() { descriptor_set_layout_info.bindingCount = static_cast(xe::countof(bindings)); descriptor_set_layout_info.pBindings = bindings; - status = dfn.vkCreateDescriptorSetLayout(*device_, - &descriptor_set_layout_info, nullptr, + status = dfn.vkCreateDescriptorSetLayout(device, &descriptor_set_layout_info, + nullptr, &constant_descriptor_set_layout_); if (status != VK_SUCCESS) { return status; @@ -256,7 +279,7 @@ VkResult BufferCache::CreateConstantDescriptorSet() { set_alloc_info.descriptorPool = constant_descriptor_pool_; set_alloc_info.descriptorSetCount = 1; set_alloc_info.pSetLayouts = &constant_descriptor_set_layout_; - status = dfn.vkAllocateDescriptorSets(*device_, &set_alloc_info, + status = dfn.vkAllocateDescriptorSets(device, &set_alloc_info, &constant_descriptor_set_); if (status != VK_SUCCESS) { return status; @@ -289,24 +312,26 @@ VkResult BufferCache::CreateConstantDescriptorSet() { fragment_uniform_binding_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; fragment_uniform_binding_write.pBufferInfo = &buffer_info; - dfn.vkUpdateDescriptorSets(*device_, 2, descriptor_writes, 0, nullptr); + dfn.vkUpdateDescriptorSets(device, 2, descriptor_writes, 0, nullptr); return VK_SUCCESS; } void BufferCache::FreeConstantDescriptorSet() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); if (constant_descriptor_set_) { - dfn.vkFreeDescriptorSets(*device_, constant_descriptor_pool_, 1, + dfn.vkFreeDescriptorSets(device, constant_descriptor_pool_, 1, &constant_descriptor_set_); constant_descriptor_set_ = nullptr; } - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, *device_, - constant_descriptor_set_layout_); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyDescriptorPool, *device_, - constant_descriptor_pool_); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, + device, + constant_descriptor_set_layout_); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyDescriptorPool, device, + constant_descriptor_pool_); } void BufferCache::Shutdown() { @@ -319,9 +344,10 @@ void BufferCache::Shutdown() { FreeVertexDescriptorPool(); transient_buffer_->Shutdown(); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - ui::vulkan::DestroyAndNullHandle(dfn.vkFreeMemory, *device_, - gpu_memory_pool_); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkFreeMemory, device, + gpu_memory_pool_); } std::pair BufferCache::UploadConstantRegisters( @@ -368,7 +394,7 @@ std::pair BufferCache::UploadConstantRegisters( offset, kConstantRegisterUniformRange, }; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); @@ -484,7 +510,7 @@ std::pair BufferCache::UploadIndexBuffer( offset, source_length, }; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); @@ -552,7 +578,7 @@ std::pair BufferCache::UploadVertexBuffer( offset, upload_size, }; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); @@ -697,8 +723,9 @@ VkDescriptorSet BufferCache::PrepareVertexSet( }; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, nullptr); vertex_sets_[hash] = set; return set; } @@ -771,7 +798,8 @@ void BufferCache::CacheTransientData(uint32_t guest_address, } void BufferCache::Flush(VkCommandBuffer command_buffer) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // 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 @@ -790,7 +818,7 @@ void BufferCache::Flush(VkCommandBuffer command_buffer) { dirty_range.memory = transient_buffer_->gpu_memory(); dirty_range.offset = 0; dirty_range.size = transient_buffer_->capacity(); - dfn.vkFlushMappedMemoryRanges(*device_, 1, &dirty_range); + dfn.vkFlushMappedMemoryRanges(device, 1, &dirty_range); } void BufferCache::InvalidateCache() { diff --git a/src/xenia/gpu/vulkan/buffer_cache.h b/src/xenia/gpu/vulkan/buffer_cache.h index 4080b1803..449e23558 100644 --- a/src/xenia/gpu/vulkan/buffer_cache.h +++ b/src/xenia/gpu/vulkan/buffer_cache.h @@ -17,10 +17,8 @@ #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 "xenia/ui/vulkan/vulkan_mem_alloc.h" +#include "xenia/ui/vulkan/vulkan_provider.h" #include #include @@ -35,7 +33,7 @@ namespace vulkan { class BufferCache { public: BufferCache(RegisterFile* register_file, Memory* memory, - ui::vulkan::VulkanDevice* device, size_t capacity); + const ui::vulkan::VulkanProvider& provider, size_t capacity); ~BufferCache(); VkResult Initialize(); @@ -147,7 +145,7 @@ class BufferCache { RegisterFile* register_file_ = nullptr; Memory* memory_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; + const ui::vulkan::VulkanProvider& provider_; VkDeviceMemory gpu_memory_pool_ = nullptr; VmaAllocator mem_allocator_ = nullptr; diff --git a/src/xenia/gpu/vulkan/pipeline_cache.cc b/src/xenia/gpu/vulkan/pipeline_cache.cc index 128c5b133..2581dc9f2 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/pipeline_cache.cc @@ -16,6 +16,7 @@ #include "xenia/base/xxhash.h" #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h" +#include "xenia/ui/vulkan/vulkan_util.h" #include #include @@ -24,18 +25,18 @@ namespace xe { namespace gpu { namespace vulkan { -using xe::ui::vulkan::CheckResult; +using xe::ui::vulkan::util::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" +#include "xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.h" +#include "xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.h" +#include "xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/point_list_geom.h" +#include "xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.h" +#include "xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.h" PipelineCache::PipelineCache(RegisterFile* register_file, - ui::vulkan::VulkanDevice* device) - : register_file_(register_file), device_(device) { + const ui::vulkan::VulkanProvider& provider) + : register_file_(register_file), provider_(provider) { shader_translator_.reset(new SpirvShaderTranslator()); } @@ -45,7 +46,8 @@ VkResult PipelineCache::Initialize( VkDescriptorSetLayout uniform_descriptor_set_layout, VkDescriptorSetLayout texture_descriptor_set_layout, VkDescriptorSetLayout vertex_descriptor_set_layout) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status; // Initialize the shared driver pipeline cache. @@ -58,7 +60,7 @@ VkResult PipelineCache::Initialize( pipeline_cache_info.flags = 0; pipeline_cache_info.initialDataSize = 0; pipeline_cache_info.pInitialData = nullptr; - status = dfn.vkCreatePipelineCache(*device_, &pipeline_cache_info, nullptr, + status = dfn.vkCreatePipelineCache(device, &pipeline_cache_info, nullptr, &pipeline_cache_); if (status != VK_SUCCESS) { return status; @@ -96,7 +98,7 @@ VkResult PipelineCache::Initialize( pipeline_layout_info.pushConstantRangeCount = static_cast(xe::countof(push_constant_ranges)); pipeline_layout_info.pPushConstantRanges = push_constant_ranges; - status = dfn.vkCreatePipelineLayout(*device_, &pipeline_layout_info, nullptr, + status = dfn.vkCreatePipelineLayout(device, &pipeline_layout_info, nullptr, &pipeline_layout_); if (status != VK_SUCCESS) { return status; @@ -113,58 +115,57 @@ VkResult PipelineCache::Initialize( static_cast(sizeof(line_quad_list_geom)); shader_module_info.pCode = reinterpret_cast(line_quad_list_geom); - status = dfn.vkCreateShaderModule(*device_, &shader_module_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(geometry_shaders_.line_quad_list), + "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 = dfn.vkCreateShaderModule(*device_, &shader_module_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(geometry_shaders_.point_list), + "S(g): Point List"); shader_module_info.codeSize = static_cast(sizeof(quad_list_geom)); shader_module_info.pCode = reinterpret_cast(quad_list_geom); - status = dfn.vkCreateShaderModule(*device_, &shader_module_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(geometry_shaders_.quad_list), + "S(g): Quad List"); shader_module_info.codeSize = static_cast(sizeof(rect_list_geom)); shader_module_info.pCode = reinterpret_cast(rect_list_geom); - status = dfn.vkCreateShaderModule(*device_, &shader_module_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(geometry_shaders_.rect_list), + "S(g): Rect List"); shader_module_info.codeSize = static_cast(sizeof(dummy_frag)); shader_module_info.pCode = reinterpret_cast(dummy_frag); - status = dfn.vkCreateShaderModule(*device_, &shader_module_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(dummy_pixel_shader_), "S(g): Dummy"); return VK_SUCCESS; } @@ -172,37 +173,38 @@ VkResult PipelineCache::Initialize( void PipelineCache::Shutdown() { ClearCache(); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Destroy geometry shaders. if (geometry_shaders_.line_quad_list) { - dfn.vkDestroyShaderModule(*device_, geometry_shaders_.line_quad_list, + dfn.vkDestroyShaderModule(device, geometry_shaders_.line_quad_list, nullptr); geometry_shaders_.line_quad_list = nullptr; } if (geometry_shaders_.point_list) { - dfn.vkDestroyShaderModule(*device_, geometry_shaders_.point_list, nullptr); + dfn.vkDestroyShaderModule(device, geometry_shaders_.point_list, nullptr); geometry_shaders_.point_list = nullptr; } if (geometry_shaders_.quad_list) { - dfn.vkDestroyShaderModule(*device_, geometry_shaders_.quad_list, nullptr); + dfn.vkDestroyShaderModule(device, geometry_shaders_.quad_list, nullptr); geometry_shaders_.quad_list = nullptr; } if (geometry_shaders_.rect_list) { - dfn.vkDestroyShaderModule(*device_, geometry_shaders_.rect_list, nullptr); + dfn.vkDestroyShaderModule(device, geometry_shaders_.rect_list, nullptr); geometry_shaders_.rect_list = nullptr; } if (dummy_pixel_shader_) { - dfn.vkDestroyShaderModule(*device_, dummy_pixel_shader_, nullptr); + dfn.vkDestroyShaderModule(device, dummy_pixel_shader_, nullptr); dummy_pixel_shader_ = nullptr; } if (pipeline_layout_) { - dfn.vkDestroyPipelineLayout(*device_, pipeline_layout_, nullptr); + dfn.vkDestroyPipelineLayout(device, pipeline_layout_, nullptr); pipeline_layout_ = nullptr; } if (pipeline_cache_) { - dfn.vkDestroyPipelineCache(*device_, pipeline_cache_, nullptr); + dfn.vkDestroyPipelineCache(device, pipeline_cache_, nullptr); pipeline_cache_ = nullptr; } } @@ -223,7 +225,7 @@ VulkanShader* PipelineCache::LoadShader(xenos::ShaderType shader_type, // 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, + VulkanShader* shader = new VulkanShader(provider_, shader_type, data_hash, host_address, dword_count); shader_map_.insert({data_hash, shader}); @@ -278,10 +280,11 @@ PipelineCache::UpdateStatus PipelineCache::ConfigurePipeline( } void PipelineCache::ClearCache() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Destroy all pipelines. for (auto it : cached_pipelines_) { - dfn.vkDestroyPipeline(*device_, it.second, nullptr); + dfn.vkDestroyPipeline(device, it.second, nullptr); } cached_pipelines_.clear(); COUNT_profile_set("gpu/pipeline_cache/pipelines", 0); @@ -343,9 +346,10 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state, pipeline_info.basePipelineHandle = nullptr; pipeline_info.basePipelineIndex = -1; VkPipeline pipeline = nullptr; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); auto result = dfn.vkCreateGraphicsPipelines( - *device_, pipeline_cache_, 1, &pipeline_info, nullptr, &pipeline); + device, pipeline_cache_, 1, &pipeline_info, nullptr, &pipeline); if (result != VK_SUCCESS) { XELOGE("vkCreateGraphicsPipelines failed with code {}", result); assert_always(); @@ -354,9 +358,10 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state, // Dump shader disassembly. if (cvars::vulkan_dump_disasm) { - if (device_->HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) { + if (provider_.device_extensions().amd_shader_info) { DumpShaderDisasmAMD(pipeline); - } else if (device_->device_info().properties.vendorID == 0x10DE) { + } else if (provider_.device_properties().vendorID == + uint32_t(ui::GraphicsProvider::GpuVendorID::kNvidia)) { // NVIDIA cards DumpShaderDisasmNV(pipeline_info); } @@ -421,7 +426,8 @@ static void DumpShaderStatisticsAMD(const VkShaderStatisticsInfoAMD& stats) { } void PipelineCache::DumpShaderDisasmAMD(VkPipeline pipeline) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; size_t data_size = 0; @@ -429,9 +435,9 @@ void PipelineCache::DumpShaderDisasmAMD(VkPipeline pipeline) { data_size = sizeof(stats); // Vertex shader - status = dfn.vkGetShaderInfoAMD( - *device_, pipeline, VK_SHADER_STAGE_VERTEX_BIT, - VK_SHADER_INFO_TYPE_STATISTICS_AMD, &data_size, &stats); + status = dfn.vkGetShaderInfoAMD(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); @@ -439,7 +445,7 @@ void PipelineCache::DumpShaderDisasmAMD(VkPipeline pipeline) { // Fragment shader status = dfn.vkGetShaderInfoAMD( - *device_, pipeline, VK_SHADER_STAGE_FRAGMENT_BIT, + 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:"); @@ -455,7 +461,8 @@ void PipelineCache::DumpShaderDisasmNV( // This code is super ugly. Update this when NVidia includes an official // way to dump shader disassembly. - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkPipelineCacheCreateInfo pipeline_cache_info; VkPipelineCache dummy_pipeline_cache; @@ -464,23 +471,23 @@ void PipelineCache::DumpShaderDisasmNV( pipeline_cache_info.flags = 0; pipeline_cache_info.initialDataSize = 0; pipeline_cache_info.pInitialData = nullptr; - auto status = dfn.vkCreatePipelineCache(*device_, &pipeline_cache_info, - nullptr, &dummy_pipeline_cache); + auto status = dfn.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 = - dfn.vkCreateGraphicsPipelines(*device_, dummy_pipeline_cache, 1, + dfn.vkCreateGraphicsPipelines(device, dummy_pipeline_cache, 1, &pipeline_info, nullptr, &dummy_pipeline); std::vector pipeline_data; size_t data_size = 0; - status = dfn.vkGetPipelineCacheData(*device_, dummy_pipeline_cache, - &data_size, nullptr); + status = dfn.vkGetPipelineCacheData(device, dummy_pipeline_cache, &data_size, + nullptr); if (status == VK_SUCCESS) { pipeline_data.resize(data_size); - dfn.vkGetPipelineCacheData(*device_, dummy_pipeline_cache, &data_size, + dfn.vkGetPipelineCacheData(device, dummy_pipeline_cache, &data_size, pipeline_data.data()); // Scan the data for the disassembly. @@ -537,8 +544,8 @@ void PipelineCache::DumpShaderDisasmNV( disasm_fp); } - dfn.vkDestroyPipeline(*device_, dummy_pipeline, nullptr); - dfn.vkDestroyPipelineCache(*device_, dummy_pipeline_cache, nullptr); + dfn.vkDestroyPipeline(device, dummy_pipeline, nullptr); + dfn.vkDestroyPipelineCache(device, dummy_pipeline_cache, nullptr); } VkShaderModule PipelineCache::GetGeometryShader( @@ -582,7 +589,7 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer, SCOPE_profile_cpu_f("gpu"); #endif // FINE_GRAINED_DRAW_SCOPES - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); auto& regs = set_dynamic_state_registers_; bool window_offset_dirty = SetShadowRegister(®s.pa_sc_window_offset, diff --git a/src/xenia/gpu/vulkan/pipeline_cache.h b/src/xenia/gpu/vulkan/pipeline_cache.h index 64d319165..b85a52c86 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.h +++ b/src/xenia/gpu/vulkan/pipeline_cache.h @@ -20,8 +20,7 @@ #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" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace gpu { @@ -38,7 +37,8 @@ class PipelineCache { kError, }; - PipelineCache(RegisterFile* register_file, ui::vulkan::VulkanDevice* device); + PipelineCache(RegisterFile* register_file, + const ui::vulkan::VulkanProvider& provider); ~PipelineCache(); VkResult Initialize(VkDescriptorSetLayout uniform_descriptor_set_layout, @@ -90,7 +90,7 @@ class PipelineCache { bool is_line_mode); RegisterFile* register_file_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; + const ui::vulkan::VulkanProvider& provider_; // Temporary storage for AnalyzeUcode calls. StringBuffer ucode_disasm_buffer_; diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index b3dc4d389..5b15a304b 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -19,13 +19,14 @@ #include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/registers.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h" +#include "xenia/ui/vulkan/vulkan_util.h" namespace xe { namespace gpu { namespace vulkan { using namespace xe::gpu::xenos; -using xe::ui::vulkan::CheckResult; +using xe::ui::vulkan::util::CheckResult; constexpr uint32_t kEdramBufferCapacity = 10 * 1024 * 1024; @@ -105,7 +106,7 @@ class CachedFramebuffer { // Associated render pass VkRenderPass render_pass = nullptr; - CachedFramebuffer(const ui::vulkan::VulkanDevice& device, + CachedFramebuffer(const ui::vulkan::VulkanProvider& provider, VkRenderPass render_pass, uint32_t surface_width, uint32_t surface_height, CachedTileView* target_color_attachments[4], @@ -117,7 +118,7 @@ class CachedFramebuffer { bool IsCompatible(const RenderConfiguration& desired_config) const; private: - const ui::vulkan::VulkanDevice& device_; + const ui::vulkan::VulkanProvider& provider_; }; // Cached render passes based on register states. @@ -134,7 +135,7 @@ class CachedRenderPass { // Cache of framebuffers for the various tile attachments. std::vector cached_framebuffers; - CachedRenderPass(const ui::vulkan::VulkanDevice& device, + CachedRenderPass(const ui::vulkan::VulkanProvider& provider, const RenderConfiguration& desired_config); ~CachedRenderPass(); @@ -143,28 +144,30 @@ class CachedRenderPass { bool IsCompatible(const RenderConfiguration& desired_config) const; private: - const ui::vulkan::VulkanDevice& device_; + const ui::vulkan::VulkanProvider& provider_; }; -CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, +CachedTileView::CachedTileView(const ui::vulkan::VulkanProvider& provider, VkDeviceMemory edram_memory, TileViewKey view_key) - : device_(device), key(std::move(view_key)) {} + : provider_(provider), key(std::move(view_key)) {} CachedTileView::~CachedTileView() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyImageView, *device_, - image_view); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyImageView, *device_, - image_view_depth); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyImageView, *device_, - image_view_stencil); - ui::vulkan::DestroyAndNullHandle(dfn.vkDestroyImage, *device_, image); - ui::vulkan::DestroyAndNullHandle(dfn.vkFreeMemory, *device_, memory); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyImageView, device, + image_view); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyImageView, device, + image_view_depth); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyImageView, device, + image_view_stencil); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyImage, device, image); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkFreeMemory, device, memory); } VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Map format to Vulkan. @@ -237,26 +240,40 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { image_info.queueFamilyIndexCount = 0; image_info.pQueueFamilyIndices = nullptr; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - status = dfn.vkCreateImage(*device_, &image_info, nullptr, &image); + status = dfn.vkCreateImage(device, &image_info, nullptr, &image); if (status != VK_SUCCESS) { return status; } - device_->DbgSetObjectName( - reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + provider_.SetDeviceObjectName( + VK_OBJECT_TYPE_IMAGE, uint64_t(image), 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))); + uint32_t(key.msaa_samples), uint32_t(key.edram_format)) + .c_str()); VkMemoryRequirements memory_requirements; - dfn.vkGetImageMemoryRequirements(*device_, image, &memory_requirements); + dfn.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 = dfn.vkBindImageMemory(*device_, image, memory, 0); + VkMemoryAllocateInfo memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = memory_requirements.size; + if (!xe::bit_scan_forward(memory_requirements.memoryTypeBits & + provider_.memory_types_device_local(), + &memory_allocate_info.memoryTypeIndex)) { + return VK_ERROR_INITIALIZATION_FAILED; + } + status = + dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory); + if (status != VK_SUCCESS) { + return status; + } + status = dfn.vkBindImageMemory(device, image, memory, 0); if (status != VK_SUCCESS) { return status; } @@ -284,7 +301,7 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; } status = - dfn.vkCreateImageView(*device_, &image_view_info, nullptr, &image_view); + dfn.vkCreateImageView(device, &image_view_info, nullptr, &image_view); if (status != VK_SUCCESS) { return status; } @@ -292,14 +309,14 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { // Create separate depth/stencil views. if (key.color_or_depth == 0) { image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - status = dfn.vkCreateImageView(*device_, &image_view_info, nullptr, + status = dfn.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 = dfn.vkCreateImageView(*device_, &image_view_info, nullptr, + status = dfn.vkCreateImageView(device, &image_view_info, nullptr, &image_view_stencil); if (status != VK_SUCCESS) { return status; @@ -338,11 +355,11 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { } CachedFramebuffer::CachedFramebuffer( - const ui::vulkan::VulkanDevice& device, VkRenderPass render_pass, + const ui::vulkan::VulkanProvider& provider, VkRenderPass render_pass, uint32_t surface_width, uint32_t surface_height, CachedTileView* target_color_attachments[4], CachedTileView* target_depth_stencil_attachment) - : device_(device), + : provider_(provider), width(surface_width), height(surface_height), depth_stencil_attachment(target_depth_stencil_attachment), @@ -354,8 +371,9 @@ CachedFramebuffer::CachedFramebuffer( CachedFramebuffer::~CachedFramebuffer() { if (handle != VK_NULL_HANDLE) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkDestroyFramebuffer(device_, handle, nullptr); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyFramebuffer(device, handle, nullptr); } } @@ -381,8 +399,9 @@ VkResult CachedFramebuffer::Initialize() { framebuffer_info.width = width; framebuffer_info.height = height; framebuffer_info.layers = 1; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - return dfn.vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &handle); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + return dfn.vkCreateFramebuffer(device, &framebuffer_info, nullptr, &handle); } bool CachedFramebuffer::IsCompatible( @@ -427,9 +446,9 @@ bool CachedFramebuffer::IsCompatible( return true; } -CachedRenderPass::CachedRenderPass(const ui::vulkan::VulkanDevice& device, +CachedRenderPass::CachedRenderPass(const ui::vulkan::VulkanProvider& provider, const RenderConfiguration& desired_config) - : device_(device) { + : provider_(provider) { std::memcpy(&config, &desired_config, sizeof(config)); } @@ -440,8 +459,9 @@ CachedRenderPass::~CachedRenderPass() { cached_framebuffers.clear(); if (handle != VK_NULL_HANDLE) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkDestroyRenderPass(device_, handle, nullptr); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyRenderPass(device, handle, nullptr); } } @@ -553,8 +573,9 @@ VkResult CachedRenderPass::Initialize() { render_pass_info.dependencyCount = 1; render_pass_info.pDependencies = dependencies; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - return dfn.vkCreateRenderPass(device_, &render_pass_info, nullptr, &handle); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + return dfn.vkCreateRenderPass(device, &render_pass_info, nullptr, &handle); } bool CachedRenderPass::IsCompatible( @@ -577,13 +598,14 @@ bool CachedRenderPass::IsCompatible( } RenderCache::RenderCache(RegisterFile* register_file, - ui::vulkan::VulkanDevice* device) - : register_file_(register_file), device_(device) {} + const ui::vulkan::VulkanProvider& provider) + : register_file_(register_file), provider_(provider) {} RenderCache::~RenderCache() { Shutdown(); } VkResult RenderCache::Initialize() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Create the buffer we'll bind to our memory. @@ -597,7 +619,7 @@ VkResult RenderCache::Initialize() { buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; buffer_info.queueFamilyIndexCount = 0; buffer_info.pQueueFamilyIndices = nullptr; - status = dfn.vkCreateBuffer(*device_, &buffer_info, nullptr, &edram_buffer_); + status = dfn.vkCreateBuffer(device, &buffer_info, nullptr, &edram_buffer_); CheckResult(status, "vkCreateBuffer"); if (status != VK_SUCCESS) { return status; @@ -606,20 +628,29 @@ VkResult RenderCache::Initialize() { // Query requirements for the buffer. // It should be 1:1. VkMemoryRequirements buffer_requirements; - dfn.vkGetBufferMemoryRequirements(*device_, edram_buffer_, + dfn.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_) { + VkMemoryAllocateInfo buffer_allocate_info; + buffer_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + buffer_allocate_info.pNext = nullptr; + buffer_allocate_info.allocationSize = buffer_requirements.size; + buffer_allocate_info.memoryTypeIndex = ui::vulkan::util::ChooseHostMemoryType( + provider_, buffer_requirements.memoryTypeBits, false); + if (buffer_allocate_info.memoryTypeIndex == UINT32_MAX) { return VK_ERROR_INITIALIZATION_FAILED; } + status = dfn.vkAllocateMemory(device, &buffer_allocate_info, nullptr, + &edram_memory_); + if (status != VK_SUCCESS) { + return status; + } // Bind buffer to map our entire memory. - status = dfn.vkBindBufferMemory(*device_, edram_buffer_, edram_memory_, 0); + status = dfn.vkBindBufferMemory(device, edram_buffer_, edram_memory_, 0); CheckResult(status, "vkBindBufferMemory"); if (status != VK_SUCCESS) { return status; @@ -628,16 +659,15 @@ VkResult RenderCache::Initialize() { if (status == VK_SUCCESS) { // For debugging, upload a grid into the EDRAM buffer. uint32_t* gpu_data = nullptr; - status = - dfn.vkMapMemory(*device_, edram_memory_, 0, buffer_requirements.size, 0, - reinterpret_cast(&gpu_data)); + status = dfn.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; } - dfn.vkUnmapMemory(*device_, edram_memory_); + dfn.vkUnmapMemory(device, edram_memory_); } } @@ -647,7 +677,8 @@ VkResult RenderCache::Initialize() { void RenderCache::Shutdown() { // TODO(benvanik): wait for idle. - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Dispose all render passes (and their framebuffers). for (auto render_pass : cached_render_passes_) { @@ -663,11 +694,11 @@ void RenderCache::Shutdown() { // Release underlying EDRAM memory. if (edram_buffer_) { - dfn.vkDestroyBuffer(*device_, edram_buffer_, nullptr); + dfn.vkDestroyBuffer(device, edram_buffer_, nullptr); edram_buffer_ = nullptr; } if (edram_memory_) { - dfn.vkFreeMemory(*device_, edram_memory_, nullptr); + dfn.vkFreeMemory(device, edram_memory_, nullptr); edram_memory_ = nullptr; } } @@ -803,7 +834,7 @@ const RenderState* RenderCache::BeginRenderPass(VkCommandBuffer command_buffer, render_pass_begin_info.pClearValues = nullptr; // Begin the render pass. - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); @@ -891,11 +922,10 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, // If no render pass was found in the cache create a new one. if (!render_pass) { - render_pass = new CachedRenderPass(*device_, *config); + render_pass = new CachedRenderPass(provider_, *config); VkResult status = render_pass->Initialize(); if (status != VK_SUCCESS) { - XELOGE("{}: Failed to create render pass, status {}", __func__, - ui::vulkan::to_string(status)); + XELOGE("{}: Failed to create render pass", __func__); delete render_pass; return false; } @@ -971,12 +1001,11 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, 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, + provider_, 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)); + XELOGE("{}: Failed to create framebuffer", __func__); delete framebuffer; return false; } @@ -1025,11 +1054,10 @@ CachedTileView* RenderCache::FindOrCreateTileView( } // Create a new tile and add to the cache. - tile_view = new CachedTileView(device_, edram_memory_, view_key); + tile_view = new CachedTileView(provider_, 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)); + XELOGE("{}: Failed to create tile view", __func__); delete tile_view; return nullptr; @@ -1042,7 +1070,7 @@ CachedTileView* RenderCache::FindOrCreateTileView( void RenderCache::UpdateTileView(VkCommandBuffer command_buffer, CachedTileView* view, bool load, bool insert_barrier) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); uint32_t tile_width = view->key.msaa_samples == uint16_t(xenos::MsaaSamples::k4X) ? 40 : 80; @@ -1111,7 +1139,7 @@ void RenderCache::EndRenderPass() { assert_not_null(current_command_buffer_); // End the render pass. - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdEndRenderPass(current_command_buffer_); // Copy all render targets back into our EDRAM buffer. @@ -1165,7 +1193,7 @@ void RenderCache::RawCopyToImage(VkCommandBuffer command_buffer, VkImageLayout image_layout, bool color_or_depth, VkOffset3D offset, VkExtent3D extents) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); // Transition the texture into a transfer destination layout. VkImageMemoryBarrier image_barrier; @@ -1239,7 +1267,7 @@ void RenderCache::BlitToImage(VkCommandBuffer command_buffer, bool color_or_depth, uint32_t format, VkFilter filter, VkOffset3D offset, VkExtent3D extents) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); if (color_or_depth) { // Adjust similar formats for easier matching. @@ -1372,7 +1400,7 @@ void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer, std::memcpy(clear_value.float32, color, sizeof(float) * 4); // Issue a clear command - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdClearColorImage(command_buffer, tile_view->image, VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &range); @@ -1412,7 +1440,7 @@ void RenderCache::ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, clear_value.stencil = stencil; // Issue a clear command - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdClearDepthStencilImage(command_buffer, tile_view->image, VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &range); @@ -1422,7 +1450,7 @@ void RenderCache::ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, } void RenderCache::FillEDRAM(VkCommandBuffer command_buffer, uint32_t value) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); dfn.vkCmdFillBuffer(command_buffer, edram_buffer_, 0, kEdramBufferCapacity, value); } diff --git a/src/xenia/gpu/vulkan/render_cache.h b/src/xenia/gpu/vulkan/render_cache.h index 9dfbf648d..f73fa39e5 100644 --- a/src/xenia/gpu/vulkan/render_cache.h +++ b/src/xenia/gpu/vulkan/render_cache.h @@ -16,8 +16,7 @@ #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" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace gpu { @@ -68,8 +67,8 @@ class CachedTileView { // (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(const ui::vulkan::VulkanProvider& provider, + VkDeviceMemory edram_memory, TileViewKey view_key); ~CachedTileView(); VkResult Initialize(VkCommandBuffer command_buffer); @@ -89,7 +88,7 @@ class CachedTileView { } private: - ui::vulkan::VulkanDevice* device_ = nullptr; + const ui::vulkan::VulkanProvider& provider_; }; // Parsed render configuration from the current render state. @@ -274,7 +273,8 @@ struct RenderState { // 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(RegisterFile* register_file, + const ui::vulkan::VulkanProvider& provider); ~RenderCache(); VkResult Initialize(); @@ -358,7 +358,7 @@ class RenderCache { CachedFramebuffer** out_framebuffer); RegisterFile* register_file_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; + const ui::vulkan::VulkanProvider& provider_; // Entire 10MiB of EDRAM. VkDeviceMemory edram_memory_ = nullptr; diff --git a/src/xenia/gpu/vulkan/shaders/bytecode/.clang-format b/src/xenia/gpu/vulkan/shaders/bytecode/.clang-format new file mode 100644 index 000000000..9d159247d --- /dev/null +++ b/src/xenia/gpu/vulkan/shaders/bytecode/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false diff --git a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.h similarity index 98% rename from src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.h index 7bcf6bc90..035b6b881 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.h @@ -1,7 +1,7 @@ // generated from `xb genspirv` // source: dummy.frag const uint8_t dummy_frag[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 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, diff --git a/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.spv b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d34b4e9802b3d6eab7dee3295660d5b09ef0088b GIT binary patch literal 548 zcmY*WO-sW-6nr*~Z56a4>O~~t&1!8+6~U8w$R#KJ0n0XB;%eN4WCeepzsif?Oj4mP zyv&=~_n8ekXFZV(*^<7@q&<7mfg(a20k>td;c@bujBCFf&#xzp+>wCL-0ezFy6|c5 z+B)i&uqkYaIO=EwFF;k1FEr@NK;lH*KRqb(S>`siUTN)daCY zGk5VQ5+jRoC%nKR=T3ioAKP%B(`GYi{6qNMHG&->z7Hg4{{wsnzzD`OTJdxEL)bAm z|2cE0Mc@}e{H{j7TXD|RYHhtSIO{Y23dnqF%;#hArKmHXoI6mv!M2>AxjfXqp@hI6 Ibhw560w5wh-~a#s literal 0 HcmV?d00001 diff --git a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.txt similarity index 96% rename from src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.txt index 33d1d9990..944db921e 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/dummy_frag.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 50 ; Schema: 0 OpCapability Shader diff --git a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.h similarity index 99% rename from src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.h index 28935cc4a..3524cbc22 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.h @@ -1,7 +1,7 @@ // 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, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 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, diff --git a/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.spv b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/line_quad_list_geom.spv new file mode 100644 index 0000000000000000000000000000000000000000..16668f787d2e22ab642eec22e593760630441557 GIT binary patch literal 2144 zcmZvcTTc{05QQ7qh2T?@J8}6p;|BH5Io7LM$K9|poZCA%Iauvy z?bY>-H8LmN5Q~pZxe1Rd!e7F;3qK~iENjT_$PQ&kvSZn_vdNwEe#QH8eJzVEmSWfC zS7k%`hqiALRB@xy6f}=t1<`r06Sv|l2(v7WPlHa<3bQ!rmUH@1FHFNM3i_YIc9aIm z>F21G^{JcpH{Dg8x27H+JHb(ueu&a6Iu{h1^Z3M)e(ZY;yAhwyj65HAvy=F1L|#>T znFAknFKNA~ET0rTk*41z8`i~8klo(mWjxsw3l?kEJ<}d^&Ro^kGubc6s!4r zQ6%Uk+8MNxBy9(0-LrnwW^c{k+243yC;Jojaqcsq@dX9;eTEYBjpvIqj&s4W?rBcU zoVz7%^C<7JS(Nv{v1d9}z=H(BI ztIHNtUq2j=dB;n_=r^t|JSxmD1b(Z)yal*9Va`#PasHJ8Psrz^9%r+9M|`&M=>eYCiZ-z6;rDO(*9t$MK}9|De6Z=U`Jv~Q zcxu5>zpj<~@aO?IWN_r))=JFuFUud0!IKZ>PT{C`xA56xde`K0Z-!sUr#|=fS}R(K z)9;N|IO}&HpW5*B1M_C!$bYMq{g(f(h{2N&J}Nl$y_ZjKdJqTm#^9dmjiZCRVKV$ha@w1h%bg=E>hoVohapXA3gk6*)Vq1SW?%+!=p6tq%7|9nNv1h*5{T zyeXp&In)7@L!4RPlQDnO!rbo{Jo$|Rf7it93=hQ7o0_(dGdz?LGreHbyCUEAl=VIm zPt3G|P1~w`v{^pd9?RfO8@R0Pi7&Mwkd-*ZQ!!Dm%{Yn{g$rJH)IyWj5V>F$|1nVeXfHfD#}ZFZUmruhz-3H=$f z$4tp%%-Z_R_2sG_ET1~PLd0G(iEzGsX2w|^*;`SX!S53mg$sfe`od7Cg#C&pcGl?~ zr%QFYg6~Mn_l$JnC-p~7KdPXP*`=E7>Wzyw*)B$DoYpp~>oV=zQ65KinrH2pDk-8e zsuNpnMuViZdH-G#*D9u!2UnU6?I_BI<7k-JQzuu7D86sHifZ@P)l7D)j^W5|B<1a- ztdnh-VjCVEUtXoI4%Radac($WGi{!dU5u+u8|PV7SGNALNLV-JedrI+>+RUD1H zuj|%v9uMkmdv~jLdy<7x73J#IL-rZzYyYB1J`SDoCO>YD8z9NaBm6h7tV4`cV`VG7Hr-DT-f_r=^^)F?;{tz^(5Il^mbG_we3#6z#O6H`e@644kn9M2?ESl#t|YO{i{DS? z6YSL6tGZ3Rjah;B#G3)B9s zD1<$xq#yJA_lh|o{RPi4pWoEYOOkwlswR9d3UKs@zM*yO`>H@L@P~XM2KkGxP5;td zeawb<)`#AfrPEuejs9N~;6raKo`YxR%=%lu|4HfOCx-n`OHw0}{W;^YKz?c}gfqf- zzVA1si1NVV+>SA7j`_OaDZ$qE#yCj!4$%#OaWiN_yH4urmdpT2mDi2zSL?;9JPyWgJ4J=t*WncSBRKjZJsmUMdJ k{^8^Ol4~f5?V!Z literal 0 HcmV?d00001 diff --git a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/point_list_geom.txt similarity index 99% rename from src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/point_list_geom.txt index 0eec50c66..42ddf5846 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/point_list_geom.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 118 ; Schema: 0 OpCapability Geometry diff --git a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.h similarity index 99% rename from src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.h index fd5741897..a8e19a833 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.h @@ -1,7 +1,7 @@ // 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, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 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, diff --git a/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.spv b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.spv new file mode 100644 index 0000000000000000000000000000000000000000..a330c444385061afb1ef2aa473dbd7a8c6a738fe GIT binary patch literal 1996 zcmZvc+fEcg5QZD}#3>5ONrN~Gc!(fD1Vjm#MR8HNFp_vX8FnY@=sL5R9TMV|ujDKE z82TI96*p!uFO#R^S zV7Z$#m)F);$UJ8XC>uL(Myywq|IQ0S@CC_D$);pWvM1S>Jd=zno7@R&7p*PRa^z{PmK_f_9FG=Fy$ZbarFA1WsH>c}&yx2>8xBJ>_ z`mq}wz404K_a7cYLD+KJUf4SJTE4rsy3+9)Z%s)|y?ZMOp}!z(`X}B|+m~I^In7D8 z+U^TKe&xrBe~W$WG#5cr5y<$dHB2`@@DjZQW{RMoM%cl>*oHnY+i2eUy@DFOX`Sv-Wt77 zM=o)Co{^?+awf&#NF!5vsnEAtmJjC}4R&u1Uk<%6*g>TgK* zNx-Sc=eGrn_^r&YX8vty*2{fB*Z!EZ{iz~CeHU$K5=|-c(HfX1#2>!HSw@EZw?HuZPl^vRS9@a z9y75hVNSs5hrFuvl7tvs%*wKac_fFm@X3LP*|{Uhd3YD_IMS;UV(>6iYZ7?Kfd`)) t;@tU;ggKxeIJp0Z5^(aFDg4j6sSm1QPn;ingtPa&IiD}e`z6_w{098iv@rkx literal 0 HcmV?d00001 diff --git a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.txt similarity index 99% rename from src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.txt index a7767342d..e64e521bf 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/quad_list_geom.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 76 ; Schema: 0 OpCapability Geometry diff --git a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.h similarity index 92% rename from src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.h index d613de39c..b545ff142 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.h @@ -1,8 +1,8 @@ // 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, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2A, 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, @@ -124,7 +124,7 @@ const uint8_t rect_list_geom[] = { 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, + 0x07, 0x00, 0x00, 0x00, 0x27, 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, @@ -143,14 +143,14 @@ const uint8_t rect_list_geom[] = { 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, + 0x17, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0xBC, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x9B, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x1B, 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, + 0x1C, 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, @@ -163,16 +163,16 @@ const uint8_t rect_list_geom[] = { 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, + 0x21, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, + 0xBC, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, + 0x22, 0x01, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x9B, 0x00, 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x25, 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, + 0x47, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x26, 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, @@ -244,32 +244,32 @@ const uint8_t rect_list_geom[] = { 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, + 0x29, 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, + 0x0A, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x29, 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, + 0x24, 0x00, 0x00, 0x00, 0x29, 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, + 0x29, 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, + 0x29, 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, + 0xAE, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x29, 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, + 0x29, 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, @@ -341,32 +341,32 @@ const uint8_t rect_list_geom[] = { 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, + 0x23, 0x00, 0x00, 0x00, 0x28, 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, + 0x28, 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, + 0x5B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x28, 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, + 0x28, 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, + 0x25, 0x00, 0x00, 0x00, 0x28, 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, + 0x28, 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, + 0x09, 0x01, 0x00, 0x00, 0x28, 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, diff --git a/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.spv b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.spv new file mode 100644 index 0000000000000000000000000000000000000000..b898570a94cc7f45c015a09e74f016c8f7122276 GIT binary patch literal 4440 zcmZveS#On96o$V}6beFd0HTNmWJa9OAPA=36qJMlinE8(9^qi=X-*Fb@kWtoq8Cng z$^|59#5hC}=P8KM=wHwaG0_XBD@Daf^m)GSr90@?uI}}|YuIbAJ)~`|^E->8rRXXq z7E4=-@|#|?@>3L!vlu5A6YwaCzKvTqt{7_$typ>0WjanR+8j#Tv|>t$+QEAUY9sRV zkd4T#$Q{TOl1xLUBi(rGI|J!PQ}=V8uw7W{lUWw<^#(5%%*a-Xs4=s;tjS*?ui8W^fJD)k+^tAow4qUcETN8KIF zN&-J}cCTdn2qxIo|X1&4kN}K(!jr_-iZDP4ESSq7+A}fRS zdSj@vcVzEab;#I><(~a(A7f?zm`l6+S#je3Nw6Ldd+9fMd?&NX?5lq6t@h|e z9us}YW8{qKqtC8?4&oIb=2O-15YY&oKktGuVU7BtI9Y z#QL3!cUR(PGOEk#H=EHo&-fhvy3XLv13PCA;n-6=Q6gGdQq%N zcwXYnH$U0*F`xKi#4qpybnA=x7HZ@({~|_XtvURcCNBJ!WmvyUk^0#ORvUkLvbjdr z>mJ2=wciMKZSvMH_MMQ^zA5R(h_@yj_1LeQ5%Z!*|edGm=qdveZy7K&>L|Eb9)ufN!{ z$#3EO-6+=X9NNX6Rk`Kd75PPA_dvNC&b^H{Rlnb1Iv9KLc7GQmo*B=9XJa9>l)2K06B!}k(&?ft2a73jvx_ma)Ca0Oz#v5K+o?UjhOP1NKXRwho~k0lic zQr?*W?dG3CUj1jm>C=vAe;;4(-UaB|?8!l_U2wC}<&Px1DsjKj#ntG3e_)fp29dL8 z>d}Wa=y@OVo?VMgd-$$RzR};jXX~(OkDgtJZoGV~cP_QMUTv}7d2sxe>(w6XU4X7F zU++S&{3+HDYjHeD=j=xxVoy91`npbgv4PRgUg)zPIf~c|^*Eb>N(Z@VueYAV;?n1naac;bWcPCzd@3r^~Iuqxu0?zj- z&f9i)ZBef{>fM1JF?qd%@YHgVLp z8$DuTF7N5Rh_IZ-4r}wDGWn=YY;9j6`Mi0)GkwEvd&=W}*^}^#_1@2% zo$wDLp5wUV520^Q!cd;){p_{A4g{4YjA%c^_$xg-$f(`VJ9wB;EN@=*IOorzyT|4>N1UbSz}nmc*YG?d7jZA3 z8@Ck6*q6|aU4Z1VFN3v3>?`QT%lDGcH{(^r`)Zth6YKW?cKc*+ zv{_f)OV=LfRDJ{4UidCW?$^=t_eh+-M{j_=L-xx2_R90}CZf$ezDI8%`FkYRN4xLQ z+eq|0?$tYqk2@gF@BF)9=XPG_k9~R%U7K;%D~>z=0eZyb^?nGi%@}JFM{UQ@tu6e$ z^B*C{kf=?Z*LEE2Jnm;++s9ySQJXkw`vg5=VlI36DWWZE6Gv^IpoLhwzOahoAL@pYw)aR=jwph7O@l1jhF8wpYKs8y6=&3 e_D!r`yhrv%n|0>BbnS6Y^Y>^2{Amhah5QY`PoISV literal 0 HcmV?d00001 diff --git a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.txt similarity index 92% rename from src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt rename to src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.txt index ff580ea8d..c77ff157e 100644 --- a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt +++ b/src/xenia/gpu/vulkan/shaders/bytecode/vulkan_spirv/rect_list_geom.txt @@ -1,7 +1,7 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 296 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 298 ; Schema: 0 OpCapability Geometry OpCapability GeometryPointSize @@ -84,7 +84,7 @@ %_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 + %295 = 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 @@ -95,11 +95,11 @@ %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 + %279 = OpFSub %v2float %52 %46 + %280 = OpExtInst %v2float %1 FAbs %279 + %283 = OpFOrdLessThanEqual %v2bool %280 %295 + %284 = OpAll %bool %283 + %56 = OpLogicalNot %bool %284 OpSelectionMerge %58 None OpBranchConditional %56 %57 %58 %57 = OpLabel @@ -108,13 +108,13 @@ %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 + %289 = OpFSub %v2float %52 %63 + %290 = OpExtInst %v2float %1 FAbs %289 + %293 = OpFOrdLessThanEqual %v2bool %290 %295 + %294 = OpAll %bool %293 OpBranch %58 %58 = OpLabel - %71 = OpPhi %bool %283 %5 %292 %57 + %71 = OpPhi %bool %284 %5 %294 %57 OpSelectionMerge %73 None OpBranchConditional %71 %72 %177 %72 = OpLabel @@ -171,23 +171,23 @@ OpStore %84 %107 OpBranch %153 %153 = OpLabel - %295 = OpPhi %int %int_0 %72 %176 %154 - %160 = OpSLessThan %bool %295 %int_16 + %297 = OpPhi %int %int_0 %72 %176 %154 + %160 = OpSLessThan %bool %297 %int_16 OpLoopMerge %155 %154 None OpBranchConditional %160 %154 %155 %154 = OpLabel - %163 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %295 + %163 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %297 %164 = OpLoad %v4float %163 %165 = OpFNegate %v4float %164 - %167 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %295 + %167 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %297 %168 = OpLoad %v4float %167 %169 = OpFAdd %v4float %165 %168 - %171 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %295 + %171 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %297 %172 = OpLoad %v4float %171 %173 = OpFAdd %v4float %169 %172 - %174 = OpAccessChain %_ptr_Output_v4float %out_interpolators %295 + %174 = OpAccessChain %_ptr_Output_v4float %out_interpolators %297 OpStore %174 %173 - %176 = OpIAdd %int %295 %int_1 + %176 = OpIAdd %int %297 %int_1 OpBranch %153 %155 = OpLabel OpEmitVertex @@ -247,23 +247,23 @@ OpStore %183 %198 OpBranch %243 %243 = OpLabel - %294 = OpPhi %int %int_0 %177 %265 %244 - %249 = OpSLessThan %bool %294 %int_16 + %296 = OpPhi %int %int_0 %177 %265 %244 + %249 = OpSLessThan %bool %296 %int_16 OpLoopMerge %245 %244 None OpBranchConditional %249 %244 %245 %244 = OpLabel - %252 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %294 + %252 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %296 %253 = OpLoad %v4float %252 - %255 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %294 + %255 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %296 %256 = OpLoad %v4float %255 %257 = OpFNegate %v4float %256 %258 = OpFAdd %v4float %253 %257 - %260 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %294 + %260 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %296 %261 = OpLoad %v4float %260 %262 = OpFAdd %v4float %258 %261 - %263 = OpAccessChain %_ptr_Output_v4float %out_interpolators %294 + %263 = OpAccessChain %_ptr_Output_v4float %out_interpolators %296 OpStore %263 %262 - %265 = OpIAdd %int %294 %int_1 + %265 = OpIAdd %int %296 %int_1 OpBranch %243 %245 = OpLabel OpEmitVertex diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc index 866c51bd2..262819d46 100644 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ b/src/xenia/gpu/vulkan/texture_cache.cc @@ -23,8 +23,8 @@ #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_instance.h" #include "xenia/ui/vulkan/vulkan_mem_alloc.h" +#include "xenia/ui/vulkan/vulkan_util.h" DECLARE_bool(texture_dump); @@ -35,7 +35,7 @@ void TextureDump(const TextureInfo& src, void* buffer, size_t length); namespace vulkan { -using xe::ui::vulkan::CheckResult; +using xe::ui::vulkan::util::CheckResult; using namespace xe::literals; @@ -58,20 +58,21 @@ const char* get_dimension_name(xenos::DataDimension dimension) { TextureCache::TextureCache(Memory* memory, RegisterFile* register_file, TraceWriter* trace_writer, - ui::vulkan::VulkanDevice* device) + ui::vulkan::VulkanProvider& provider) : memory_(memory), register_file_(register_file), trace_writer_(trace_writer), - device_(device), - staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + provider_(provider), + staging_buffer_(provider, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, kStagingBufferSize), - wb_staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_DST_BIT, + wb_staging_buffer_(provider, VK_BUFFER_USAGE_TRANSFER_DST_BIT, kStagingBufferSize) {} TextureCache::~TextureCache() { Shutdown(); } VkResult TextureCache::Initialize() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Descriptor pool used for all of our cached descriptors. @@ -79,16 +80,16 @@ VkResult TextureCache::Initialize() { pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; pool_sizes[0].descriptorCount = 32768; descriptor_pool_ = std::make_unique( - *device_, 32768, + provider_, 32768, std::vector(pool_sizes, std::end(pool_sizes))); wb_command_pool_ = std::make_unique( - *device_, device_->queue_family_index()); + provider_, provider_.queue_family_graphics_compute()); // 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; + auto& limits = provider_.device_properties().limits; if (limits.maxPerStageDescriptorSamplers < kMaxTextureSamplers || limits.maxPerStageDescriptorSampledImages < kMaxTextureSamplers) { XELOGE( @@ -120,7 +121,7 @@ VkResult TextureCache::Initialize() { static_cast(xe::countof(bindings)); descriptor_set_layout_info.pBindings = bindings; status = - dfn.vkCreateDescriptorSetLayout(*device_, &descriptor_set_layout_info, + dfn.vkCreateDescriptorSetLayout(device, &descriptor_set_layout_info, nullptr, &texture_descriptor_set_layout_); if (status != VK_SUCCESS) { return status; @@ -138,14 +139,16 @@ VkResult TextureCache::Initialize() { // Create a memory allocator for textures. VmaVulkanFunctions vulkan_funcs = {}; - ui::vulkan::FillVMAVulkanFunctions(&vulkan_funcs, *device_); + ui::vulkan::FillVMAVulkanFunctions(&vulkan_funcs, provider_); - VmaAllocatorCreateInfo alloc_info = { - 0, *device_, *device_, 0, 0, nullptr, nullptr, 0, nullptr, &vulkan_funcs, - }; + VmaAllocatorCreateInfo alloc_info = {}; + alloc_info.physicalDevice = provider_.physical_device(); + alloc_info.device = device; + alloc_info.pVulkanFunctions = &vulkan_funcs; + alloc_info.instance = provider_.instance(); status = vmaCreateAllocator(&alloc_info, &mem_allocator_); if (status != VK_SUCCESS) { - dfn.vkDestroyDescriptorSetLayout(*device_, texture_descriptor_set_layout_, + dfn.vkDestroyDescriptorSetLayout(device, texture_descriptor_set_layout_, nullptr); return status; } @@ -154,8 +157,6 @@ VkResult TextureCache::Initialize() { 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); @@ -170,10 +171,6 @@ void TextureCache::Shutdown() { memory_invalidation_callback_handle_ = nullptr; } - if (device_queue_) { - device_->ReleaseQueue(device_queue_, device_->queue_family_index()); - } - // Free all textures allocated. ClearCache(); Scavenge(); @@ -182,8 +179,9 @@ void TextureCache::Shutdown() { vmaDestroyAllocator(mem_allocator_); mem_allocator_ = nullptr; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkDestroyDescriptorSetLayout(*device_, texture_descriptor_set_layout_, + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyDescriptorSetLayout(device, texture_descriptor_set_layout_, nullptr); } @@ -235,20 +233,19 @@ TextureCache::Texture* TextureCache::AllocateTexture( image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - const ui::vulkan::VulkanInstance* instance = device_->instance(); - const ui::vulkan::VulkanInstance::InstanceFunctions& ifn = instance->ifn(); + const ui::vulkan::VulkanProvider::InstanceFunctions& ifn = provider_.ifn(); // Check the device limits for the format before we create it. VkFormatProperties props; - ifn.vkGetPhysicalDeviceFormatProperties(*device_, format, &props); + ifn.vkGetPhysicalDeviceFormatProperties(provider_.physical_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))); + "Texture Cache: Invalid usage flag specified on format {} (0x{:X})\n\t" + "(requested: 0x{:X})", + texture_info.format_info()->name, uint32_t(format), + uint32_t(required_flags & ~props.optimalTilingFeatures)); } if (texture_info.dimension != xenos::DataDimension::kCube && @@ -267,8 +264,8 @@ TextureCache::Texture* TextureCache::AllocateTexture( VkImageFormatProperties image_props; ifn.vkGetPhysicalDeviceImageFormatProperties( - *device_, format, image_info.imageType, image_info.tiling, - image_info.usage, image_info.flags, &image_props); + provider_.physical_device(), format, image_info.imageType, + image_info.tiling, image_info.usage, image_info.flags, &image_props); // TODO(DrChat): Actually check the image properties. @@ -317,10 +314,11 @@ TextureCache::Texture* TextureCache::AllocateTexture( } bool TextureCache::FreeTexture(Texture* texture) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); if (texture->in_flight_fence) { - VkResult status = dfn.vkGetFenceStatus(*device_, texture->in_flight_fence); + VkResult status = dfn.vkGetFenceStatus(device, texture->in_flight_fence); if (status != VK_SUCCESS && status != VK_ERROR_DEVICE_LOST) { // Texture still in flight. return false; @@ -328,11 +326,11 @@ bool TextureCache::FreeTexture(Texture* texture) { } if (texture->framebuffer) { - dfn.vkDestroyFramebuffer(*device_, texture->framebuffer, nullptr); + dfn.vkDestroyFramebuffer(device, texture->framebuffer, nullptr); } for (auto it = texture->views.begin(); it != texture->views.end();) { - dfn.vkDestroyImageView(*device_, (*it)->view, nullptr); + dfn.vkDestroyImageView(device, (*it)->view, nullptr); it = texture->views.erase(it); } @@ -529,14 +527,14 @@ TextureCache::Texture* TextureCache::DemandResolveTexture( } // Setup a debug name for the texture. - device_->DbgSetObjectName( - reinterpret_cast(texture->image), - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + provider_.SetDeviceObjectName( + VK_OBJECT_TYPE_IMAGE, uint64_t(texture->image), 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))); + get_dimension_name(texture_info.dimension)) + .c_str()); // Setup an access watch. If this texture is touched, it is destroyed. WatchTexture(texture); @@ -612,14 +610,14 @@ TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info, } // Setup a debug name for the texture. - device_->DbgSetObjectName( - reinterpret_cast(texture->image), - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + provider_.SetDeviceObjectName( + VK_OBJECT_TYPE_IMAGE, uint64_t(texture->image), 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))); + get_dimension_name(texture_info.dimension)) + .c_str()); textures_[texture_hash] = texture; COUNT_profile_set("gpu/texture_cache/textures", textures_.size()); @@ -703,8 +701,9 @@ TextureCache::TextureView* TextureCache::DemandView(Texture* texture, !is_cube ? 1 : 1 + texture->texture_info.depth; VkImageView view; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - auto status = dfn.vkCreateImageView(*device_, &view_info, nullptr, &view); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + auto status = dfn.vkCreateImageView(device, &view_info, nullptr, &view); CheckResult(status, "vkCreateImageView"); if (status == VK_SUCCESS) { auto texture_view = new TextureView(); @@ -844,9 +843,10 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) { sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; sampler_create_info.unnormalizedCoordinates = VK_FALSE; VkSampler vk_sampler; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); status = - dfn.vkCreateSampler(*device_, &sampler_create_info, nullptr, &vk_sampler); + dfn.vkCreateSampler(device, &sampler_create_info, nullptr, &vk_sampler); CheckResult(status, "vkCreateSampler"); if (status != VK_SUCCESS) { return nullptr; @@ -960,7 +960,8 @@ TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address, void TextureCache::FlushPendingCommands(VkCommandBuffer command_buffer, VkFence completion_fence) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); auto status = dfn.vkEndCommandBuffer(command_buffer); CheckResult(status, "vkEndCommandBuffer"); @@ -970,21 +971,17 @@ void TextureCache::FlushPendingCommands(VkCommandBuffer command_buffer, submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = &command_buffer; - if (device_queue_) { - auto status = - dfn.vkQueueSubmit(device_queue_, 1, &submit_info, completion_fence); - CheckResult(status, "vkQueueSubmit"); - } else { - std::lock_guard lock(device_->primary_queue_mutex()); - - auto status = dfn.vkQueueSubmit(device_->primary_queue(), 1, &submit_info, + { + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); + auto status = dfn.vkQueueSubmit(queue_acquisition.queue, 1, &submit_info, completion_fence); CheckResult(status, "vkQueueSubmit"); } - dfn.vkWaitForFences(*device_, 1, &completion_fence, VK_TRUE, -1); + dfn.vkWaitForFences(device, 1, &completion_fence, VK_TRUE, -1); staging_buffer_.Scavenge(); - dfn.vkResetFences(*device_, 1, &completion_fence); + dfn.vkResetFences(device, 1, &completion_fence); // Reset the command buffer and put it back into the recording state. dfn.vkResetCommandBuffer(command_buffer, 0); @@ -1169,7 +1166,7 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer, TextureDump(src, unpack_buffer, unpack_length); } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); // Transition the texture into a transfer destination layout. VkImageMemoryBarrier barrier; @@ -1313,7 +1310,7 @@ uint32_t TextureCache::ComputeTextureStorage(const TextureInfo& src) { } void TextureCache::WritebackTexture(Texture* texture) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); VkResult status = VK_SUCCESS; VkFence fence = wb_command_pool_->BeginBatch(); auto alloc = wb_staging_buffer_.Acquire(texture->alloc_info.size, fence); @@ -1361,7 +1358,8 @@ void TextureCache::WritebackTexture(Texture* texture) { // Submit the command buffer. // Submit commands and wait. { - std::lock_guard lock(device_->primary_queue_mutex()); + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, @@ -1373,12 +1371,11 @@ void TextureCache::WritebackTexture(Texture* texture) { 0, nullptr, }; - status = - dfn.vkQueueSubmit(device_->primary_queue(), 1, &submit_info, fence); + status = dfn.vkQueueSubmit(queue_acquisition.queue, 1, &submit_info, fence); CheckResult(status, "vkQueueSubmit"); if (status == VK_SUCCESS) { - status = dfn.vkQueueWaitIdle(device_->primary_queue()); + status = dfn.vkQueueWaitIdle(queue_acquisition.queue); CheckResult(status, "vkQueueWaitIdle"); } } @@ -1471,8 +1468,9 @@ VkDescriptorSet TextureCache::PrepareTextureSet( // Update the descriptor set. if (update_set_info->image_write_count > 0) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkUpdateDescriptorSets(*device_, update_set_info->image_write_count, + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkUpdateDescriptorSets(device, update_set_info->image_write_count, update_set_info->image_writes, 0, nullptr); } @@ -1632,9 +1630,10 @@ void TextureCache::ClearCache() { textures_.clear(); COUNT_profile_set("gpu/texture_cache/textures", 0); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); for (auto it = samplers_.begin(); it != samplers_.end(); ++it) { - dfn.vkDestroySampler(*device_, it->second->sampler, nullptr); + dfn.vkDestroySampler(device, it->second->sampler, nullptr); delete it->second; } samplers_.clear(); diff --git a/src/xenia/gpu/vulkan/texture_cache.h b/src/xenia/gpu/vulkan/texture_cache.h index dd1adbb91..a26f87fe2 100644 --- a/src/xenia/gpu/vulkan/texture_cache.h +++ b/src/xenia/gpu/vulkan/texture_cache.h @@ -26,10 +26,8 @@ #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" +#include "xenia/ui/vulkan/vulkan_mem_alloc.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace gpu { @@ -78,7 +76,7 @@ class TextureCache { }; TextureCache(Memory* memory, RegisterFile* register_file, - TraceWriter* trace_writer, ui::vulkan::VulkanDevice* device); + TraceWriter* trace_writer, ui::vulkan::VulkanProvider& provider); ~TextureCache(); VkResult Initialize(); @@ -203,8 +201,7 @@ class TextureCache { RegisterFile* register_file_ = nullptr; TraceWriter* trace_writer_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; - VkQueue device_queue_ = nullptr; + ui::vulkan::VulkanProvider& provider_; std::unique_ptr wb_command_pool_ = nullptr; std::unique_ptr descriptor_pool_ = nullptr; diff --git a/src/xenia/gpu/vulkan/texture_config.h b/src/xenia/gpu/vulkan/texture_config.h index 6587b68cc..dad6f1aec 100644 --- a/src/xenia/gpu/vulkan/texture_config.h +++ b/src/xenia/gpu/vulkan/texture_config.h @@ -12,7 +12,7 @@ #include "xenia/gpu/texture_info.h" #include "xenia/gpu/xenos.h" -#include "xenia/ui/vulkan/vulkan.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace gpu { diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index d9da7d9bd..be7268329 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -21,6 +21,7 @@ #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_presenter.h" #include "xenia/ui/vulkan/vulkan_util.h" namespace xe { @@ -29,21 +30,22 @@ namespace vulkan { using namespace xe::literals; using namespace xe::gpu::xenos; - -using xe::ui::vulkan::CheckResult; +using xe::ui::vulkan::util::CheckResult; constexpr size_t kDefaultBufferCacheCapacity = 256_MiB; VulkanCommandProcessor::VulkanCommandProcessor( VulkanGraphicsSystem* graphics_system, kernel::KernelState* kernel_state) - : CommandProcessor(graphics_system, kernel_state) {} + : CommandProcessor(graphics_system, kernel_state), + swap_submission_tracker_(GetVulkanProvider()) {} VulkanCommandProcessor::~VulkanCommandProcessor() = default; void VulkanCommandProcessor::RequestFrameTrace( const std::filesystem::path& root_path) { // Override traces if renderdoc is attached. - if (device_->is_renderdoc_attached()) { + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + if (provider.renderdoc_api().api_1_0_0()) { trace_requested_ = true; return; } @@ -67,21 +69,12 @@ bool VulkanCommandProcessor::SetupContext() { 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(); - } - + ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); VkResult status = VK_SUCCESS; // Setup a blitter. - blitter_ = std::make_unique(); - status = blitter_->Initialize(device_); + blitter_ = std::make_unique(provider); + status = blitter_->Initialize(); if (status != VK_SUCCESS) { XELOGE("Unable to initialize blitter"); blitter_->Shutdown(); @@ -90,11 +83,11 @@ bool VulkanCommandProcessor::SetupContext() { // Setup fenced pools used for all our per-frame/per-draw resources. command_buffer_pool_ = std::make_unique( - *device_, device_->queue_family_index()); + provider, provider.queue_family_graphics_compute()); // Initialize the state machine caches. buffer_cache_ = std::make_unique( - register_file_, memory_, device_, kDefaultBufferCacheCapacity); + register_file_, memory_, provider, kDefaultBufferCacheCapacity); status = buffer_cache_->Initialize(); if (status != VK_SUCCESS) { XELOGE("Unable to initialize buffer cache"); @@ -103,7 +96,7 @@ bool VulkanCommandProcessor::SetupContext() { } texture_cache_ = std::make_unique(memory_, register_file_, - &trace_writer_, device_); + &trace_writer_, provider); status = texture_cache_->Initialize(); if (status != VK_SUCCESS) { XELOGE("Unable to initialize texture cache"); @@ -111,7 +104,7 @@ bool VulkanCommandProcessor::SetupContext() { return false; } - pipeline_cache_ = std::make_unique(register_file_, device_); + pipeline_cache_ = std::make_unique(register_file_, provider); status = pipeline_cache_->Initialize( buffer_cache_->constant_descriptor_set_layout(), texture_cache_->texture_descriptor_set_layout(), @@ -122,7 +115,7 @@ bool VulkanCommandProcessor::SetupContext() { return false; } - render_cache_ = std::make_unique(register_file_, device_); + render_cache_ = std::make_unique(register_file_, provider); status = render_cache_->Initialize(); if (status != VK_SUCCESS) { XELOGE("Unable to initialize render cache"); @@ -136,10 +129,14 @@ bool VulkanCommandProcessor::SetupContext() { void VulkanCommandProcessor::ShutdownContext() { // TODO(benvanik): wait until idle. - if (swap_state_.front_buffer_texture) { - // Free swap chain image. - DestroySwapImage(); - } + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + swap_submission_tracker_.Shutdown(); + ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyFramebuffer, device, + swap_framebuffer_); + swap_framebuffer_version_ = UINT64_MAX; buffer_cache_.reset(); pipeline_cache_.reset(); @@ -151,12 +148,6 @@ void VulkanCommandProcessor::ShutdownContext() { // 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(); } @@ -178,26 +169,6 @@ void VulkanCommandProcessor::MakeCoherent() { } } -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); @@ -223,7 +194,7 @@ void VulkanCommandProcessor::WriteRegister(uint32_t index, uint32_t value) { } 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); + UpdateGammaRampValue(GammaRampType::kTable, 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; @@ -237,109 +208,6 @@ void VulkanCommandProcessor::WriteRegister(uint32_t index, uint32_t value) { } } -void VulkanCommandProcessor::CreateSwapImage(VkCommandBuffer setup_buffer, - VkExtent2D extents) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - 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 = dfn.vkCreateImage(*device_, &image_info, nullptr, &image_fb); - CheckResult(status, "vkCreateImage"); - - // Bind memory to image. - VkMemoryRequirements mem_requirements; - dfn.vkGetImageMemoryRequirements(*device_, image_fb, &mem_requirements); - fb_memory_ = device_->AllocateMemory(mem_requirements, 0); - assert_not_null(fb_memory_); - - status = dfn.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 = dfn.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 = dfn.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}; - - dfn.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() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - dfn.vkDestroyFramebuffer(*device_, fb_framebuffer_, nullptr); - dfn.vkDestroyImageView(*device_, fb_image_view_, nullptr); - - std::lock_guard lock(swap_state_.mutex); - dfn.vkDestroyImage( - *device_, reinterpret_cast(swap_state_.front_buffer_texture), - nullptr); - dfn.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_); @@ -351,7 +219,8 @@ void VulkanCommandProcessor::BeginFrame() { current_command_buffer_ = command_buffer_pool_->AcquireEntry(); current_setup_buffer_ = command_buffer_pool_->AcquireEntry(); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkCommandBufferBeginInfo command_buffer_begin_info; command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -368,19 +237,14 @@ void VulkanCommandProcessor::BeginFrame() { // 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(); + if ((cvars::vulkan_renderdoc_capture_all || trace_requested_) && + !capturing_) { + const RENDERDOC_API_1_0_0* renderdoc_api = + provider.renderdoc_api().api_1_0_0(); + if (renderdoc_api && !renderdoc_api->IsFrameCapturing()) { + capturing_ = true; + trace_requested_ = false; + renderdoc_api->StartFrameCapture(nullptr, nullptr); } } @@ -393,7 +257,8 @@ void VulkanCommandProcessor::EndFrame() { current_render_state_ = nullptr; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); VkResult status = VK_SUCCESS; status = dfn.vkEndCommandBuffer(current_setup_buffer_); CheckResult(status, "vkEndCommandBuffer"); @@ -407,170 +272,348 @@ void VulkanCommandProcessor::EndFrame() { frame_open_ = false; } -void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, - uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { +void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, + uint32_t frontbuffer_width, + uint32_t frontbuffer_height) { SCOPE_profile_cpu_f("gpu"); - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - // 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; + ui::Presenter* presenter = graphics_system_->presenter(); + if (!presenter) { + return; } - 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 = dfn.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}; - - dfn.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; - dfn.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; - dfn.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 = dfn.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(); + } + bool submitted = false; + + auto& regs = *register_file_; + int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0; + auto group = + reinterpret_cast(®s.values[r]); + TextureInfo texture_info; + if (!TextureInfo::Prepare(group->texture_fetch, &texture_info)) { + assert_always(); + } + auto texture = texture_cache_->Lookup(texture_info); + if (texture) { + presenter->RefreshGuestOutput( + frontbuffer_width, frontbuffer_height, 1280, 720, + [this, frontbuffer_width, frontbuffer_height, texture, &submit_buffers, + &submitted]( + ui::Presenter::GuestOutputRefreshContext& context) -> bool { + auto& vulkan_context = static_cast< + ui::vulkan::VulkanPresenter::VulkanGuestOutputRefreshContext&>( + context); + + ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = + provider.dfn(); + VkDevice device = provider.device(); + + // Make sure the framebuffer is for the current guest output image. + if (swap_framebuffer_ != VK_NULL_HANDLE && + swap_framebuffer_version_ != vulkan_context.image_version()) { + swap_submission_tracker_.AwaitAllSubmissionsCompletion(); + dfn.vkDestroyFramebuffer(device, swap_framebuffer_, nullptr); + swap_framebuffer_ = VK_NULL_HANDLE; + } + if (swap_framebuffer_ == VK_NULL_HANDLE) { + VkRenderPass render_pass = blitter_->GetRenderPass( + ui::vulkan::VulkanPresenter::kGuestOutputFormat, true); + if (render_pass == VK_NULL_HANDLE) { + return false; + } + VkImageView guest_output_image_view = vulkan_context.image_view(); + VkFramebufferCreateInfo swap_framebuffer_create_info; + swap_framebuffer_create_info.sType = + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + swap_framebuffer_create_info.pNext = nullptr; + swap_framebuffer_create_info.flags = 0; + swap_framebuffer_create_info.renderPass = render_pass; + swap_framebuffer_create_info.attachmentCount = 1; + swap_framebuffer_create_info.pAttachments = + &guest_output_image_view; + swap_framebuffer_create_info.width = frontbuffer_width; + swap_framebuffer_create_info.height = frontbuffer_height; + swap_framebuffer_create_info.layers = 1; + if (dfn.vkCreateFramebuffer(device, &swap_framebuffer_create_info, + nullptr, + &swap_framebuffer_) != VK_SUCCESS) { + XELOGE( + "Failed to create the Vulkan framebuffer for presentation"); + return false; + } + swap_framebuffer_version_ = vulkan_context.image_version(); + } + + // Build a final command buffer that copies the game's frontbuffer + // texture into our backbuffer texture. + VkCommandBuffer copy_commands = nullptr; + bool opened_batch = !command_buffer_pool_->has_open_batch(); + if (!command_buffer_pool_->has_open_batch()) { + current_batch_fence_ = command_buffer_pool_->BeginBatch(); + } + copy_commands = 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; + dfn.vkBeginCommandBuffer(copy_commands, &command_buffer_begin_info); + + texture->in_flight_fence = current_batch_fence_; + + // Insert a barrier so the GPU finishes writing to the image, and a + // barrier after the last presenter's usage of the guest output image. + VkPipelineStageFlags acquire_barrier_src_stages = 0; + VkPipelineStageFlags acquire_barrier_dst_stages = 0; + VkImageMemoryBarrier acquire_image_memory_barriers[2]; + uint32_t acquire_image_memory_barrier_count = 0; + { + acquire_barrier_src_stages |= + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_TRANSFER_BIT; + acquire_barrier_dst_stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + VkImageMemoryBarrier& acquire_image_memory_barrier = + acquire_image_memory_barriers + [acquire_image_memory_barrier_count++]; + acquire_image_memory_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + acquire_image_memory_barrier.pNext = nullptr; + acquire_image_memory_barrier.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT; + acquire_image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + acquire_image_memory_barrier.oldLayout = texture->image_layout; + acquire_image_memory_barrier.newLayout = texture->image_layout; + acquire_image_memory_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + acquire_image_memory_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + acquire_image_memory_barrier.image = texture->image; + ui::vulkan::util::InitializeSubresourceRange( + acquire_image_memory_barrier.subresourceRange); + } + { + acquire_barrier_dst_stages |= + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkImageMemoryBarrier& acquire_image_memory_barrier = + acquire_image_memory_barriers + [acquire_image_memory_barrier_count++]; + acquire_image_memory_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + acquire_image_memory_barrier.pNext = nullptr; + acquire_image_memory_barrier.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + // Will be overwriting all the contents. + acquire_image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + acquire_image_memory_barrier.newLayout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + acquire_image_memory_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + acquire_image_memory_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + acquire_image_memory_barrier.image = vulkan_context.image(); + ui::vulkan::util::InitializeSubresourceRange( + acquire_image_memory_barrier.subresourceRange); + if (vulkan_context.image_ever_written_previously()) { + acquire_barrier_src_stages |= + ui::vulkan::VulkanPresenter::kGuestOutputInternalStageMask; + acquire_image_memory_barrier.srcAccessMask = + ui::vulkan::VulkanPresenter::kGuestOutputInternalAccessMask; + } else { + acquire_image_memory_barrier.srcAccessMask = 0; + } + } + assert_not_zero(acquire_barrier_src_stages); + assert_not_zero(acquire_barrier_dst_stages); + assert_not_zero(acquire_image_memory_barrier_count); + dfn.vkCmdPipelineBarrier(copy_commands, acquire_barrier_src_stages, + acquire_barrier_dst_stages, 0, 0, nullptr, 0, + nullptr, acquire_image_memory_barrier_count, + acquire_image_memory_barriers); + + // 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}, + ui::vulkan::VulkanPresenter::kGuestOutputFormat, dst_rect, + {frontbuffer_width, frontbuffer_height}, swap_framebuffer_, + viewport, scissor, VK_FILTER_LINEAR, true, true); + + VkPipelineStageFlags release_barrier_src_stages = 0; + VkPipelineStageFlags release_barrier_dst_stages = 0; + VkImageMemoryBarrier release_image_memory_barriers[2]; + uint32_t release_image_memory_barrier_count = 0; + { + release_barrier_src_stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + release_barrier_dst_stages |= + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_TRANSFER_BIT; + VkImageMemoryBarrier& release_image_memory_barrier = + release_image_memory_barriers + [release_image_memory_barrier_count++]; + release_image_memory_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + release_image_memory_barrier.pNext = nullptr; + release_image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + release_image_memory_barrier.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_TRANSFER_WRITE_BIT; + release_image_memory_barrier.oldLayout = texture->image_layout; + release_image_memory_barrier.newLayout = texture->image_layout; + release_image_memory_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + release_image_memory_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + release_image_memory_barrier.image = texture->image; + ui::vulkan::util::InitializeSubresourceRange( + release_image_memory_barrier.subresourceRange); + } + { + release_barrier_src_stages |= + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + release_barrier_dst_stages |= + ui::vulkan::VulkanPresenter::kGuestOutputInternalStageMask; + VkImageMemoryBarrier& release_image_memory_barrier = + release_image_memory_barriers + [release_image_memory_barrier_count++]; + release_image_memory_barrier.sType = + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + release_image_memory_barrier.pNext = nullptr; + release_image_memory_barrier.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + release_image_memory_barrier.dstAccessMask = + ui::vulkan::VulkanPresenter::kGuestOutputInternalAccessMask; + release_image_memory_barrier.oldLayout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + release_image_memory_barrier.newLayout = + ui::vulkan::VulkanPresenter::kGuestOutputInternalLayout; + release_image_memory_barrier.srcQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + release_image_memory_barrier.dstQueueFamilyIndex = + VK_QUEUE_FAMILY_IGNORED; + release_image_memory_barrier.image = vulkan_context.image(); + ui::vulkan::util::InitializeSubresourceRange( + release_image_memory_barrier.subresourceRange); + } + assert_not_zero(release_barrier_src_stages); + assert_not_zero(release_barrier_dst_stages); + assert_not_zero(release_image_memory_barrier_count); + dfn.vkCmdPipelineBarrier(copy_commands, release_barrier_src_stages, + release_barrier_dst_stages, 0, 0, nullptr, 0, + nullptr, release_image_memory_barrier_count, + release_image_memory_barriers); + + dfn.vkEndCommandBuffer(copy_commands); + + // Need to submit all the commands before giving the image back to the + // presenter so it can submit its own commands for displaying it to + // the queue. + + if (frame_open_) { + EndFrame(); + } + + if (opened_batch) { + command_buffer_pool_->EndBatch(); + } + + submit_buffers.push_back(copy_commands); + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = uint32_t(submit_buffers.size()); + submit_info.pCommandBuffers = submit_buffers.data(); + VkResult submit_result; + { + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider.AcquireQueue(provider.queue_family_graphics_compute(), + 0)); + submit_result = dfn.vkQueueSubmit( + queue_acquisition.queue, 1, &submit_info, current_batch_fence_); + } + if (submit_result != VK_SUCCESS) { + return false; + } + submitted = true; + + // Signal the fence for destroying objects depending on the guest + // output image. + { + ui::vulkan::VulkanSubmissionTracker::FenceAcquisition + fence_acqusition = + swap_submission_tracker_.AcquireFenceToAdvanceSubmission(); + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider.AcquireQueue(provider.queue_family_graphics_compute(), + 0)); + if (dfn.vkQueueSubmit(queue_acquisition.queue, 0, nullptr, + fence_acqusition.fence()) != VK_SUCCESS) { + fence_acqusition.SubmissionSucceededSignalFailed(); + } + } + + return true; + }); } - if (opened_batch) { - command_buffer_pool_->EndBatch(); - } + ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); - 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(); + if (!submitted) { + // End the frame even if failed to refresh the guest output. + if (frame_open_) { + EndFrame(); } - - 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 = dfn.vkQueueSubmit(queue_, 1, &submit_info, current_batch_fence_); - if (device_->is_renderdoc_attached() && capturing_) { - device_->EndRenderDocFrameCapture(); - capturing_ = false; - } - if (queue_mutex_) { - queue_mutex_->unlock(); + if (!submit_buffers.empty() || current_batch_fence_ != VK_NULL_HANDLE) { + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = uint32_t(submit_buffers.size()); + submit_info.pCommandBuffers = submit_buffers.data(); + VkResult submit_result; + { + ui::vulkan::VulkanProvider::QueueAcquisition queue_acquisition( + provider.AcquireQueue(provider.queue_family_graphics_compute(), 0)); + submit_result = dfn.vkQueueSubmit(queue_acquisition.queue, 1, + &submit_info, current_batch_fence_); + } + CheckResult(submit_result, "vkQueueSubmit"); } } - dfn.vkWaitForFences(*device_, 1, ¤t_batch_fence_, VK_TRUE, -1); + if (current_batch_fence_ != VK_NULL_HANDLE) { + dfn.vkWaitForFences(device, 1, ¤t_batch_fence_, VK_TRUE, -1); + } if (cache_clear_requested_) { cache_clear_requested_ = false; @@ -675,7 +718,8 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, } } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); // Configure the pipeline for drawing. // This encodes all render state (blend, depth, etc), our shader stages, @@ -767,7 +811,8 @@ bool VulkanCommandProcessor::PopulateConstants(VkCommandBuffer command_buffer, uint32_t set_constant_offsets[2] = { static_cast(constant_offsets.first), static_cast(constant_offsets.second)}; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); dfn.vkCmdBindDescriptorSets( command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &constant_descriptor_set, @@ -820,7 +865,8 @@ bool VulkanCommandProcessor::PopulateIndexBuffer( VkIndexType index_type = info.format == xenos::IndexFormat::kInt32 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); dfn.vkCmdBindIndexBuffer(command_buffer, buffer_ref.first, buffer_ref.second, index_type); @@ -850,7 +896,8 @@ bool VulkanCommandProcessor::PopulateVertexBuffers( return false; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); dfn.vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_cache_->pipeline_layout(), 2, 1, &descriptor_set, 0, nullptr); @@ -875,7 +922,8 @@ bool VulkanCommandProcessor::PopulateSamplers(VkCommandBuffer command_buffer, return false; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); dfn.vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_cache_->pipeline_layout(), 1, 1, &descriptor_set, 0, nullptr); @@ -1083,7 +1131,9 @@ bool VulkanCommandProcessor::IssueCopy() { render_cache_->EndRenderPass(); current_render_state_ = nullptr; } - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const ui::vulkan::VulkanProvider& provider = GetVulkanProvider(); + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); auto command_buffer = current_command_buffer_; if (texture->image_layout == VK_IMAGE_LAYOUT_UNDEFINED) { @@ -1219,8 +1269,8 @@ bool VulkanCommandProcessor::IssueCopy() { 1, }; - VkResult res = dfn.vkCreateFramebuffer(*device_, &fb_create_info, - nullptr, &texture->framebuffer); + VkResult res = dfn.vkCreateFramebuffer(device, &fb_create_info, nullptr, + &texture->framebuffer); CheckResult(res, "vkCreateFramebuffer"); } diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.h b/src/xenia/gpu/vulkan/vulkan_command_processor.h index c1fb1735e..2c2738440 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.h +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.h @@ -11,6 +11,7 @@ #define XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_ #include +#include #include #include #include @@ -27,21 +28,21 @@ #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_graphics_system.h" #include "xenia/gpu/vulkan/vulkan_shader.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_provider.h" +#include "xenia/ui/vulkan/vulkan_submission_tracker.h" #include "xenia/ui/vulkan/vulkan_util.h" namespace xe { namespace gpu { namespace vulkan { -class VulkanGraphicsSystem; class TextureCache; class VulkanCommandProcessor : public CommandProcessor { @@ -55,6 +56,11 @@ class VulkanCommandProcessor : public CommandProcessor { void RestoreEdramSnapshot(const void* snapshot) override; void ClearCaches() override; + ui::vulkan::VulkanProvider& GetVulkanProvider() const { + return *static_cast( + graphics_system_->provider()); + } + RenderCache* render_cache() { return render_cache_.get(); } private: @@ -62,19 +68,14 @@ class VulkanCommandProcessor : public CommandProcessor { 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; + void IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, + uint32_t frontbuffer_height) override; Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, @@ -99,13 +100,6 @@ class VulkanCommandProcessor : public CommandProcessor { void InitializeTrace() 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; @@ -114,14 +108,6 @@ class VulkanCommandProcessor : public CommandProcessor { 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; @@ -142,6 +128,10 @@ class VulkanCommandProcessor : public CommandProcessor { VkCommandBuffer current_command_buffer_ = nullptr; VkCommandBuffer current_setup_buffer_ = nullptr; VkFence current_batch_fence_; + + ui::vulkan::VulkanSubmissionTracker swap_submission_tracker_; + VkFramebuffer swap_framebuffer_ = VK_NULL_HANDLE; + uint64_t swap_framebuffer_version_ = UINT64_MAX; }; } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc index 9c852c706..c42510050 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc @@ -2,267 +2,32 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2022 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(); - device_ = provider->device(); - provider_ = std::move(provider); - - 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(), - }; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - auto status = - dfn.vkCreateCommandPool(*device_, &create_info, nullptr, &command_pool_); - CheckResult(status, "vkCreateCommandPool"); - - return X_STATUS_SUCCESS; -} - -void VulkanGraphicsSystem::Shutdown() { - GraphicsSystem::Shutdown(); - - if (command_pool_ != VK_NULL_HANDLE) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkDestroyCommandPool(*device_, command_pool_, nullptr); - command_pool_ = VK_NULL_HANDLE; - } -} - -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; - } - - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = dfn.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, - }; - dfn.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) { - dfn.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}; - dfn.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}, - }; - - dfn.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, - }; - dfn.vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, - 1, &memory_barrier, 0, nullptr); - - status = dfn.vkEndCommandBuffer(cmd); - - // Submit commands and wait. - if (status == VK_SUCCESS) { - std::lock_guard lock(device_->primary_queue_mutex()); - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, - nullptr, - 0, - nullptr, - nullptr, - 1, - &cmd, - 0, - nullptr, - }; - status = - dfn.vkQueueSubmit(device_->primary_queue(), 1, &submit_info, nullptr); - CheckResult(status, "vkQueueSubmit"); - - if (status == VK_SUCCESS) { - status = dfn.vkQueueWaitIdle(device_->primary_queue()); - CheckResult(status, "vkQueueWaitIdle"); - } - } - - dfn.vkFreeCommandBuffers(*device_, command_pool_, 1, &cmd); - - void* data; - if (status == VK_SUCCESS) { - status = dfn.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); - - dfn.vkUnmapMemory(*device_, capture_buffer_memory_); - DestroyCaptureBuffer(); - return raw_image; - } - - DestroyCaptureBuffer(); - return nullptr; -} - -VkResult VulkanGraphicsSystem::CreateCaptureBuffer(VkCommandBuffer cmd, - VkExtent2D extents) { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = - dfn.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; - dfn.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 = dfn.vkBindBufferMemory(*device_, capture_buffer_, - capture_buffer_memory_, 0); - CheckResult(status, "vkBindImageMemory"); - if (status != VK_SUCCESS) { - dfn.vkDestroyBuffer(*device_, capture_buffer_, nullptr); - return status; - } - - return status; -} - -void VulkanGraphicsSystem::DestroyCaptureBuffer() { - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkDestroyBuffer(*device_, capture_buffer_, nullptr); - dfn.vkFreeMemory(*device_, capture_buffer_memory_, nullptr); - capture_buffer_ = nullptr; - capture_buffer_memory_ = nullptr; - capture_buffer_size_ = 0; + ui::WindowedAppContext* app_context, + bool is_surface_required) { + provider_ = xe::ui::vulkan::VulkanProvider::Create(is_surface_required); + return GraphicsSystem::Setup(processor, kernel_state, app_context, + is_surface_required); } std::unique_ptr @@ -270,71 +35,6 @@ VulkanGraphicsSystem::CreateCommandProcessor() { return std::make_unique(this, kernel_state_); } -void VulkanGraphicsSystem::Swap(xe::ui::UIEvent* e) { - if (!command_processor_ || !display_context_) { - 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; - } - - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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}; - dfn.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}; - dfn.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); -} - } // namespace vulkan } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.h b/src/xenia/gpu/vulkan/vulkan_graphics_system.h index 74a17aa78..2433703f2 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.h +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -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 { @@ -29,26 +29,11 @@ class VulkanGraphicsSystem : public GraphicsSystem { std::string name() const override { return "Vulkan - obsolete"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, - ui::Window* target_window) override; - void Shutdown() override; - - std::unique_ptr Capture() override; + ui::WindowedAppContext* app_context, + bool is_surface_required) 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 index f70be58eb..e23de068e 100644 --- a/src/xenia/gpu/vulkan/vulkan_shader.cc +++ b/src/xenia/gpu/vulkan/vulkan_shader.cc @@ -13,26 +13,27 @@ #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; +using xe::ui::vulkan::util::CheckResult; -VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device, +VulkanShader::VulkanShader(const ui::vulkan::VulkanProvider& provider, 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) {} + : Shader(shader_type, data_hash, dword_ptr, dword_count), + provider_(provider) {} VulkanShader::VulkanTranslation::~VulkanTranslation() { if (shader_module_) { - const VulkanShader& vulkan_shader = static_cast(shader()); - const ui::vulkan::VulkanDevice* device = vulkan_shader.device_; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device->dfn(); - dfn.vkDestroyShaderModule(*device, shader_module_, nullptr); + const ui::vulkan::VulkanProvider& provider = + static_cast(shader()).provider_; + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + dfn.vkDestroyShaderModule(device, shader_module_, nullptr); shader_module_ = nullptr; } } @@ -42,8 +43,9 @@ bool VulkanShader::VulkanTranslation::Prepare() { assert_true(is_valid()); const VulkanShader& vulkan_shader = static_cast(shader()); - const ui::vulkan::VulkanDevice* device = vulkan_shader.device_; - const ui::vulkan::VulkanDevice::DeviceFunctions& dfn = device->dfn(); + const ui::vulkan::VulkanProvider& provider = vulkan_shader.provider_; + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); // Create the shader module. VkShaderModuleCreateInfo shader_info; @@ -54,7 +56,7 @@ bool VulkanShader::VulkanTranslation::Prepare() { shader_info.pCode = reinterpret_cast(translated_binary().data()); auto status = - dfn.vkCreateShaderModule(*device, &shader_info, nullptr, &shader_module_); + dfn.vkCreateShaderModule(device, &shader_info, nullptr, &shader_module_); CheckResult(status, "vkCreateShaderModule"); char type_char; @@ -68,10 +70,10 @@ bool VulkanShader::VulkanTranslation::Prepare() { default: type_char = 'u'; } - device->DbgSetObjectName(uint64_t(shader_module_), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - fmt::format("S({}): {:016X}", type_char, - vulkan_shader.ucode_data_hash())); + provider.SetDeviceObjectName( + VK_OBJECT_TYPE_SHADER_MODULE, uint64_t(shader_module_), + fmt::format("S({}): {:016X}", type_char, vulkan_shader.ucode_data_hash()) + .c_str()); return status == VK_SUCCESS; } diff --git a/src/xenia/gpu/vulkan/vulkan_shader.h b/src/xenia/gpu/vulkan/vulkan_shader.h index 76a196bff..00e913923 100644 --- a/src/xenia/gpu/vulkan/vulkan_shader.h +++ b/src/xenia/gpu/vulkan/vulkan_shader.h @@ -13,7 +13,7 @@ #include #include "xenia/gpu/shader.h" -#include "xenia/ui/vulkan/vulkan_context.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace gpu { @@ -36,15 +36,15 @@ class VulkanShader : public Shader { VkShaderModule shader_module_ = nullptr; }; - VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type, - uint64_t data_hash, const uint32_t* dword_ptr, - uint32_t dword_count); + VulkanShader(const ui::vulkan::VulkanProvider& provider, + xenos::ShaderType shader_type, uint64_t data_hash, + const uint32_t* dword_ptr, uint32_t dword_count); protected: Translation* CreateTranslationInstance(uint64_t modification) override; private: - ui::vulkan::VulkanDevice* device_ = nullptr; + const ui::vulkan::VulkanProvider& provider_; }; } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc index d1d78047c..4483129b8 100644 --- a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc +++ b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -12,7 +12,6 @@ #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 { @@ -28,20 +27,24 @@ class VulkanTraceDump : public TraceDump { } void BeginHostCapture() override { - auto device = static_cast( - graphics_system_->provider()) - ->device(); - if (device->is_renderdoc_attached()) { - device->BeginRenderDocFrameCapture(); + const RENDERDOC_API_1_0_0* renderdoc_api = + static_cast( + graphics_system_->provider()) + ->renderdoc_api() + .api_1_0_0(); + if (renderdoc_api && !renderdoc_api->IsFrameCapturing()) { + renderdoc_api->StartFrameCapture(nullptr, nullptr); } } void EndHostCapture() override { - auto device = static_cast( - graphics_system_->provider()) - ->device(); - if (device->is_renderdoc_attached()) { - device->EndRenderDocFrameCapture(); + const RENDERDOC_API_1_0_0* renderdoc_api = + static_cast( + graphics_system_->provider()) + ->renderdoc_api() + .api_1_0_0(); + if (renderdoc_api && renderdoc_api->IsFrameCapturing()) { + renderdoc_api->EndFrameCapture(nullptr, nullptr); } } }; diff --git a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc index ed296d4e0..e50abb41f 100644 --- a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc +++ b/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc @@ -36,7 +36,7 @@ class VulkanTraceViewer final : public TraceViewer { uint32_t pitch, xenos::MsaaSamples samples, uint32_t base, xenos::ColorRenderTargetFormat format) override { auto command_processor = static_cast( - graphics_system_->command_processor()); + graphics_system()->command_processor()); // return command_processor->GetColorRenderTarget(pitch, samples, base, // format); return 0; @@ -46,7 +46,7 @@ class VulkanTraceViewer final : public TraceViewer { uint32_t pitch, xenos::MsaaSamples samples, uint32_t base, xenos::DepthRenderTargetFormat format) override { auto command_processor = static_cast( - graphics_system_->command_processor()); + graphics_system()->command_processor()); // return command_processor->GetDepthRenderTarget(pitch, samples, base, // format); return 0; @@ -55,7 +55,7 @@ class VulkanTraceViewer final : public TraceViewer { uintptr_t GetTextureEntry(const TextureInfo& texture_info, const SamplerInfo& sampler_info) override { auto command_processor = static_cast( - graphics_system_->command_processor()); + graphics_system()->command_processor()); // auto entry_view = // command_processor->texture_cache()->Demand(texture_info, diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index d02735a42..f4d616f9e 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -24,10 +24,14 @@ #include "xenia/base/threading.h" #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" +#include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" // Available input drivers: @@ -59,12 +63,41 @@ class HidDemoApp final : public ui::WindowedApp { bool OnInitialize() override; private: + enum : size_t { + kZOrderHidInput, + kZOrderImGui, + }; + + class HidDemoWindowListener final : public ui::WindowListener { + public: + explicit HidDemoWindowListener(ui::WindowedAppContext& app_context) + : app_context_(app_context) {} + void OnClosing(ui::UIEvent& e) override { app_context_.QuitFromUIThread(); } + + private: + ui::WindowedAppContext& app_context_; + }; + + class HidDemoDialog final : public ui::ImGuiDialog { + public: + explicit HidDemoDialog(ui::ImGuiDrawer* imgui_drawer, HidDemoApp& app) + : ui::ImGuiDialog(imgui_drawer), app_(app) {} + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + HidDemoApp& app_; + }; + explicit HidDemoApp(ui::WindowedAppContext& app_context) - : ui::WindowedApp(app_context, "xenia-hid-demo") {} + : ui::WindowedApp(app_context, "xenia-hid-demo"), + window_listener_(app_context) {} static std::vector> CreateInputDrivers( ui::Window* window); + void Draw(ImGuiIO& io); void DrawUserInputGetState(uint32_t user_index) const; void DrawInputGetState() const; void DrawUserInputGetKeystroke(uint32_t user_index, bool poll, @@ -72,9 +105,15 @@ class HidDemoApp final : public ui::WindowedApp { void DrawInputGetKeystroke(bool poll, bool hide_repeats, bool clear_log) const; + HidDemoWindowListener window_listener_; std::unique_ptr graphics_provider_; std::unique_ptr window_; std::unique_ptr input_system_; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr demo_dialog_; + bool is_active_ = true; }; @@ -82,71 +121,64 @@ std::vector> HidDemoApp::CreateInputDrivers( ui::Window* window) { std::vector> drivers; if (cvars::hid.compare("nop") == 0) { - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput)); } else if (cvars::hid.compare("sdl") == 0) { - auto driver = xe::hid::sdl::Create(window); + auto driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } #if XE_PLATFORM_WIN32 } else if (cvars::hid.compare("winkey") == 0) { - auto driver = xe::hid::winkey::Create(window); + auto driver = xe::hid::winkey::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } } else if (cvars::hid.compare("xinput") == 0) { - auto driver = xe::hid::xinput::Create(window); + auto driver = xe::hid::xinput::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } #endif // XE_PLATFORM_WIN32 } else { - auto sdl_driver = xe::hid::sdl::Create(window); + auto sdl_driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (sdl_driver && XSUCCEEDED(sdl_driver->Setup())) { drivers.emplace_back(std::move(sdl_driver)); } #if XE_PLATFORM_WIN32 - auto xinput_driver = xe::hid::xinput::Create(window); + auto xinput_driver = xe::hid::xinput::Create(window, kZOrderHidInput); if (xinput_driver && XSUCCEEDED(xinput_driver->Setup())) { drivers.emplace_back(std::move(xinput_driver)); } - auto winkey_driver = xe::hid::winkey::Create(window); + auto winkey_driver = xe::hid::winkey::Create(window, kZOrderHidInput); if (winkey_driver && XSUCCEEDED(winkey_driver->Setup())) { drivers.emplace_back(std::move(winkey_driver)); } #endif // XE_PLATFORM_WIN32 if (drivers.empty()) { // Fallback to nop if none created. - drivers.emplace_back(xe::hid::nop::Create(window)); + drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput)); } } return drivers; } bool HidDemoApp::OnInitialize() { - // Create graphics provider that provides the context for the window. - graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create(); + // Create the graphics provider that provides the presenter for the window. + graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create(true); if (!graphics_provider_) { + XELOGE("Failed to initialize the graphics provider"); return false; } - // Create the window. - window_ = xe::ui::Window::Create(app_context(), GetName()); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); + // Create and configure the window. + window_ = xe::ui::Window::Create(app_context(), GetName(), + COL_WIDTH_STATE + COL_WIDTH_STROKE, + ROW_HEIGHT_GENERAL + 500); + window_->AddListener(&window_listener_); + if (!window_->Open()) { + XELOGE("Failed to open the main window"); return false; } - window_->on_closed.AddListener([this](xe::ui::UIEvent* e) { - XELOGI("User-initiated death!"); - app_context().QuitFromUIThread(); - }); - - // Initial size setting, done here so that it knows the menu exists. - window_->Resize(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL + 500); - - // Create the graphics context for the window. The window will finish - // initialization with the context (loading resources, etc). - window_->set_context(graphics_provider_->CreateContext(window_.get())); // Initialize input system and all drivers. input_system_ = std::make_unique(window_.get()); @@ -157,71 +189,83 @@ bool HidDemoApp::OnInitialize() { input_system_->AddDriver(std::move(driver)); } - window_->Invalidate(); - - window_->set_imgui_input_enabled(true); - - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - auto& io = window_->imgui_drawer()->GetIO(); - - const ImGuiWindowFlags wflags = - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_NoScrollbar; - - ImGui::Begin("General", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(0, 0)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL)); - - ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str()); - ImGui::Checkbox("is_active", &is_active_); - } - ImGui::End(); - - ImGui::Begin("GetState()", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); - - static bool enable_GetState = false; - ImGui::Checkbox("Active", &enable_GetState); - ImGui::SameLine(); - ImGui::Checkbox("Guide Button", &cvars::guide_button); - if (enable_GetState) { - ImGui::Spacing(); - DrawInputGetState(); - } - } - ImGui::End(); - - ImGui::Begin("GetKeystroke()", nullptr, wflags); - { - ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL)); - ImGui::SetWindowSize( - ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); - - static bool enable_GetKeystroke = false; - static bool hide_repeats = false; - ImGui::Checkbox("Active", &enable_GetKeystroke); - ImGui::SameLine(); - ImGui::Checkbox("Hide repeats", &hide_repeats); - ImGui::SameLine(); - const bool clear_log = ImGui::Button("Clear"); - ImGui::Spacing(); - DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log); - } - ImGui::End(); - - // Continuous paint. - window_->Invalidate(); - }); + // Setup drawing to the window. + presenter_ = graphics_provider_->CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } + immediate_drawer_ = graphics_provider_->CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); + imgui_drawer_ = + std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + demo_dialog_ = std::make_unique(imgui_drawer_.get(), *this); + window_->SetPresenter(presenter_.get()); return true; } +void HidDemoApp::HidDemoDialog::OnDraw(ImGuiIO& io) { app_.Draw(io); } + +void HidDemoApp::Draw(ImGuiIO& io) { + const ImGuiWindowFlags wflags = + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoScrollbar; + + ImGui::Begin("General", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(0, 0)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL)); + + ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str()); + ImGui::Checkbox("is_active", &is_active_); + } + ImGui::End(); + + ImGui::Begin("GetState()", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); + + static bool enable_GetState = false; + ImGui::Checkbox("Active", &enable_GetState); + ImGui::SameLine(); + ImGui::Checkbox("Guide Button", &cvars::guide_button); + if (enable_GetState) { + ImGui::Spacing(); + DrawInputGetState(); + } + } + ImGui::End(); + + ImGui::Begin("GetKeystroke()", nullptr, wflags); + { + ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL)); + ImGui::SetWindowSize( + ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL)); + + static bool enable_GetKeystroke = false; + static bool hide_repeats = false; + ImGui::Checkbox("Active", &enable_GetKeystroke); + ImGui::SameLine(); + ImGui::Checkbox("Hide repeats", &hide_repeats); + ImGui::SameLine(); + const bool clear_log = ImGui::Button("Clear"); + ImGui::Spacing(); + DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log); + } + ImGui::End(); +} + void HidDemoApp::DrawUserInputGetState(uint32_t user_index) const { ImGui::Text("User %u:", user_index); diff --git a/src/xenia/hid/input_driver.cc b/src/xenia/hid/input_driver.cc deleted file mode 100644 index 1627d5dc4..000000000 --- a/src/xenia/hid/input_driver.cc +++ /dev/null @@ -1,20 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/hid/input_driver.h" - -namespace xe { -namespace hid { - -InputDriver::InputDriver(xe::ui::Window* window) : window_(window) {} - -InputDriver::~InputDriver() = default; - -} // namespace hid -} // namespace xe diff --git a/src/xenia/hid/input_driver.h b/src/xenia/hid/input_driver.h index aef8cffeb..6b0ff3472 100644 --- a/src/xenia/hid/input_driver.h +++ b/src/xenia/hid/input_driver.h @@ -10,6 +10,7 @@ #ifndef XENIA_HID_INPUT_DRIVER_H_ #define XENIA_HID_INPUT_DRIVER_H_ +#include #include #include "xenia/hid/input.h" @@ -29,7 +30,7 @@ class InputSystem; class InputDriver { public: - virtual ~InputDriver(); + virtual ~InputDriver() = default; virtual X_STATUS Setup() = 0; @@ -45,18 +46,21 @@ class InputDriver { is_active_callback_ = is_active_callback; } - private: - xe::ui::Window* window_ = nullptr; - std::function is_active_callback_ = nullptr; - protected: - explicit InputDriver(xe::ui::Window* window); + explicit InputDriver(xe::ui::Window* window, size_t window_z_order) + : window_(window), window_z_order_(window_z_order) {} xe::ui::Window* window() const { return window_; } + size_t window_z_order() const { return window_z_order_; } bool is_active() const { return !is_active_callback_ || is_active_callback_(); } + + private: + xe::ui::Window* window_; + size_t window_z_order_; + std::function is_active_callback_ = nullptr; }; } // namespace hid diff --git a/src/xenia/hid/nop/nop_hid.cc b/src/xenia/hid/nop/nop_hid.cc index 54765df5f..4d198b278 100644 --- a/src/xenia/hid/nop/nop_hid.cc +++ b/src/xenia/hid/nop/nop_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace nop { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace nop diff --git a/src/xenia/hid/nop/nop_hid.h b/src/xenia/hid/nop/nop_hid.h index c2ea0a037..6d8f36016 100644 --- a/src/xenia/hid/nop/nop_hid.h +++ b/src/xenia/hid/nop/nop_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace nop { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace nop } // namespace hid diff --git a/src/xenia/hid/nop/nop_input_driver.cc b/src/xenia/hid/nop/nop_input_driver.cc index bd22d65e2..da6897459 100644 --- a/src/xenia/hid/nop/nop_input_driver.cc +++ b/src/xenia/hid/nop/nop_input_driver.cc @@ -15,7 +15,8 @@ namespace xe { namespace hid { namespace nop { -NopInputDriver::NopInputDriver(xe::ui::Window* window) : InputDriver(window) {} +NopInputDriver::NopInputDriver(xe::ui::Window* window, size_t window_z_order) + : InputDriver(window, window_z_order) {} NopInputDriver::~NopInputDriver() = default; diff --git a/src/xenia/hid/nop/nop_input_driver.h b/src/xenia/hid/nop/nop_input_driver.h index be949f016..361b63a7f 100644 --- a/src/xenia/hid/nop/nop_input_driver.h +++ b/src/xenia/hid/nop/nop_input_driver.h @@ -16,9 +16,9 @@ namespace xe { namespace hid { namespace nop { -class NopInputDriver : public InputDriver { +class NopInputDriver final : public InputDriver { public: - explicit NopInputDriver(xe::ui::Window* window); + explicit NopInputDriver(xe::ui::Window* window, size_t window_z_order); ~NopInputDriver() override; X_STATUS Setup() override; diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index 1aeef5657..eaaa792e4 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -41,7 +41,6 @@ project("xenia-hid-demo") filter("platforms:Linux") links({ "SDL2", - "vulkan", "X11", "xcb", "X11-xcb", diff --git a/src/xenia/hid/sdl/sdl_hid.cc b/src/xenia/hid/sdl/sdl_hid.cc index 336423ae2..cc20274b9 100644 --- a/src/xenia/hid/sdl/sdl_hid.cc +++ b/src/xenia/hid/sdl/sdl_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace sdl { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace sdl diff --git a/src/xenia/hid/sdl/sdl_hid.h b/src/xenia/hid/sdl/sdl_hid.h index ba02f0d6c..7bedd8c03 100644 --- a/src/xenia/hid/sdl/sdl_hid.h +++ b/src/xenia/hid/sdl/sdl_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace sdl { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace sdl } // namespace hid diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index 6b348f285..044c7dcd0 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -33,8 +33,8 @@ namespace xe { namespace hid { namespace sdl { -SDLInputDriver::SDLInputDriver(xe::ui::Window* window) - : InputDriver(window), +SDLInputDriver::SDLInputDriver(xe::ui::Window* window, size_t window_z_order) + : InputDriver(window, window_z_order), sdl_events_initialized_(false), sdl_gamecontroller_initialized_(false), sdl_events_unflushed_(0), diff --git a/src/xenia/hid/sdl/sdl_input_driver.h b/src/xenia/hid/sdl/sdl_input_driver.h index 367206cdb..de5c48e7c 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.h +++ b/src/xenia/hid/sdl/sdl_input_driver.h @@ -28,9 +28,9 @@ namespace xe { namespace hid { namespace sdl { -class SDLInputDriver : public InputDriver { +class SDLInputDriver final : public InputDriver { public: - explicit SDLInputDriver(xe::ui::Window* window); + explicit SDLInputDriver(xe::ui::Window* window, size_t window_z_order); ~SDLInputDriver() override; X_STATUS Setup() override; @@ -42,7 +42,7 @@ class SDLInputDriver : public InputDriver { X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags, X_INPUT_KEYSTROKE* out_keystroke) override; - protected: + private: struct ControllerState { SDL_GameController* sdl; X_INPUT_CAPABILITIES caps; @@ -65,7 +65,6 @@ class SDLInputDriver : public InputDriver { uint32_t repeat_time; }; - protected: void HandleEvent(const SDL_Event& event); void OnControllerDeviceAdded(const SDL_Event& event); void OnControllerDeviceRemoved(const SDL_Event& event); @@ -80,7 +79,6 @@ class SDLInputDriver : public InputDriver { void UpdateXCapabilities(ControllerState& state); void QueueControllerUpdate(); - protected: bool sdl_events_initialized_; bool sdl_gamecontroller_initialized_; int sdl_events_unflushed_; diff --git a/src/xenia/hid/winkey/winkey_hid.cc b/src/xenia/hid/winkey/winkey_hid.cc index 7244f4c53..2f75ef5c4 100644 --- a/src/xenia/hid/winkey/winkey_hid.cc +++ b/src/xenia/hid/winkey/winkey_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace winkey { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace winkey diff --git a/src/xenia/hid/winkey/winkey_hid.h b/src/xenia/hid/winkey/winkey_hid.h index a17e5ba98..6061c6a06 100644 --- a/src/xenia/hid/winkey/winkey_hid.h +++ b/src/xenia/hid/winkey/winkey_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace winkey { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace winkey } // namespace hid diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index c038e69db..53c5ef359 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -80,47 +80,22 @@ void WinKeyInputDriver::ParseKeyBinding(ui::VirtualKey output_key, } } -WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) - : InputDriver(window), packet_number_(1) { - // Register a key listener. - window->on_key_down.AddListener([this](ui::KeyEvent* evt) { - if (!is_active()) { - return; - } - - auto global_lock = global_critical_region_.Acquire(); - - KeyEvent key; - key.virtual_key = evt->virtual_key(); - key.transition = true; - key.prev_state = evt->prev_state(); - key.repeat_count = evt->repeat_count(); - key_events_.push(key); - }); - window->on_key_up.AddListener([this](ui::KeyEvent* evt) { - if (!is_active()) { - return; - } - - auto global_lock = global_critical_region_.Acquire(); - - KeyEvent key; - key.virtual_key = evt->virtual_key(); - key.transition = false; - key.prev_state = evt->prev_state(); - key.repeat_count = evt->repeat_count(); - key_events_.push(key); - }); - +WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window, + size_t window_z_order) + : InputDriver(window, window_z_order), window_input_listener_(*this) { #define XE_HID_WINKEY_BINDING(button, description, cvar_name, \ cvar_default_value) \ ParseKeyBinding(xe::ui::VirtualKey::kXInputPad##button, description, \ cvars::cvar_name); #include "winkey_binding_table.inc" #undef XE_HID_WINKEY_BINDING + + window->AddInputListener(&window_input_listener_, window_z_order); } -WinKeyInputDriver::~WinKeyInputDriver() = default; +WinKeyInputDriver::~WinKeyInputDriver() { + window()->RemoveInputListener(&window_input_listener_); +} X_STATUS WinKeyInputDriver::Setup() { return X_STATUS_SUCCESS; } @@ -162,7 +137,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, int16_t thumb_rx = 0; int16_t thumb_ry = 0; - if (window()->has_focus() && is_active()) { + if (window()->HasFocus() && is_active()) { bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT); for (const KeyBinding& b : key_bindings_) { if (((b.lowercase == b.uppercase) || (b.lowercase && !capital) || @@ -331,6 +306,29 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, return result; } +void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyDown(ui::KeyEvent& e) { + driver_.OnKey(e, true); +} + +void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) { + driver_.OnKey(e, false); +} + +void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) { + if (!is_active()) { + return; + } + + KeyEvent key; + key.virtual_key = e.virtual_key(); + key.transition = is_down; + key.prev_state = e.prev_state(); + key.repeat_count = e.repeat_count(); + + auto global_lock = global_critical_region_.Acquire(); + key_events_.push(key); +} + } // namespace winkey } // namespace hid } // namespace xe diff --git a/src/xenia/hid/winkey/winkey_input_driver.h b/src/xenia/hid/winkey/winkey_input_driver.h index 8b45c1457..e11788acf 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.h +++ b/src/xenia/hid/winkey/winkey_input_driver.h @@ -20,9 +20,9 @@ namespace xe { namespace hid { namespace winkey { -class WinKeyInputDriver : public InputDriver { +class WinKeyInputDriver final : public InputDriver { public: - explicit WinKeyInputDriver(xe::ui::Window* window); + explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order); ~WinKeyInputDriver() override; X_STATUS Setup() override; @@ -49,15 +49,31 @@ class WinKeyInputDriver : public InputDriver { bool lowercase = false; }; - xe::global_critical_region global_critical_region_; - std::queue key_events_; - std::vector key_bindings_; + class WinKeyWindowInputListener final : public ui::WindowInputListener { + public: + explicit WinKeyWindowInputListener(WinKeyInputDriver& driver) + : driver_(driver) {} - uint32_t packet_number_; + void OnKeyDown(ui::KeyEvent& e) override; + void OnKeyUp(ui::KeyEvent& e) override; + + private: + WinKeyInputDriver& driver_; + }; void ParseKeyBinding(ui::VirtualKey virtual_key, const std::string_view description, const std::string_view binding); + + void OnKey(ui::KeyEvent& e, bool is_down); + + WinKeyWindowInputListener window_input_listener_; + + xe::global_critical_region global_critical_region_; + std::queue key_events_; + std::vector key_bindings_; + + uint32_t packet_number_ = 1; }; } // namespace winkey diff --git a/src/xenia/hid/xinput/xinput_hid.cc b/src/xenia/hid/xinput/xinput_hid.cc index 093d266f0..21f4304f1 100644 --- a/src/xenia/hid/xinput/xinput_hid.cc +++ b/src/xenia/hid/xinput/xinput_hid.cc @@ -15,8 +15,9 @@ namespace xe { namespace hid { namespace xinput { -std::unique_ptr Create(xe::ui::Window* window) { - return std::make_unique(window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order) { + return std::make_unique(window, window_z_order); } } // namespace xinput diff --git a/src/xenia/hid/xinput/xinput_hid.h b/src/xenia/hid/xinput/xinput_hid.h index c295cb434..2c6cb231b 100644 --- a/src/xenia/hid/xinput/xinput_hid.h +++ b/src/xenia/hid/xinput/xinput_hid.h @@ -18,7 +18,8 @@ namespace xe { namespace hid { namespace xinput { -std::unique_ptr Create(xe::ui::Window* window); +std::unique_ptr Create(xe::ui::Window* window, + size_t window_z_order); } // namespace xinput } // namespace hid diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc index 830daa0e4..497d80089 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.cc +++ b/src/xenia/hid/xinput/xinput_input_driver.cc @@ -21,8 +21,9 @@ namespace xe { namespace hid { namespace xinput { -XInputInputDriver::XInputInputDriver(xe::ui::Window* window) - : InputDriver(window), +XInputInputDriver::XInputInputDriver(xe::ui::Window* window, + size_t window_z_order) + : InputDriver(window, window_z_order), module_(nullptr), XInputGetCapabilities_(nullptr), XInputGetState_(nullptr), diff --git a/src/xenia/hid/xinput/xinput_input_driver.h b/src/xenia/hid/xinput/xinput_input_driver.h index dcde26197..b14113963 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.h +++ b/src/xenia/hid/xinput/xinput_input_driver.h @@ -16,9 +16,9 @@ namespace xe { namespace hid { namespace xinput { -class XInputInputDriver : public InputDriver { +class XInputInputDriver final : public InputDriver { public: - explicit XInputInputDriver(xe::ui::Window* window); + explicit XInputInputDriver(xe::ui::Window* window, size_t window_z_order); ~XInputInputDriver() override; X_STATUS Setup() override; @@ -30,7 +30,7 @@ class XInputInputDriver : public InputDriver { X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags, X_INPUT_KEYSTROKE* out_keystroke) override; - protected: + private: void* module_; void* XInputGetCapabilities_; void* XInputGetState_; diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 3233ec67e..0b6551615 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -458,7 +458,7 @@ inline void AppendParam(StringBuffer* string_buffer, inline void AppendParam(StringBuffer* string_buffer, pointer_t record) { string_buffer->AppendFormat("{:08X}({:08X})", record.guest_address(), - uint32_t(record->exception_code)); + uint32_t(record->code)); } template void AppendParam(StringBuffer* string_buffer, pointer_t param) { diff --git a/src/xenia/kernel/xam/xam_nui.cc b/src/xenia/kernel/xam/xam_nui.cc index 48ab0d946..53fe06e6f 100644 --- a/src/xenia/kernel/xam/xam_nui.cc +++ b/src/xenia/kernel/xam/xam_nui.cc @@ -14,6 +14,7 @@ #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -49,17 +50,21 @@ dword_result_t XamShowNuiTroubleshooterUI_entry(unknown_t unk1, unknown_t unk2, return 0; } - auto display_window = kernel_state()->emulator()->display_window(); - xe::threading::Fence fence; - if (display_window->app_context().CallInUIThreadSynchronous([&]() { - xe::ui::ImGuiDialog::ShowMessageBox( - display_window, "NUI Troubleshooter", - "The game has indicated there is a problem with NUI (Kinect).") - ->Then(&fence); - })) { - ++xam_dialogs_shown_; - fence.Wait(); - --xam_dialogs_shown_; + const Emulator* emulator = kernel_state()->emulator(); + ui::Window* display_window = emulator->display_window(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); + if (display_window && imgui_drawer) { + xe::threading::Fence fence; + if (display_window->app_context().CallInUIThreadSynchronous([&]() { + xe::ui::ImGuiDialog::ShowMessageBox( + imgui_drawer, "NUI Troubleshooter", + "The game has indicated there is a problem with NUI (Kinect).") + ->Then(&fence); + })) { + ++xam_dialogs_shown_; + fence.Wait(); + --xam_dialogs_shown_; + } } return 0; diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 2762facf3..be8e2c892 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -16,6 +16,7 @@ #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" #include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/window.h" #include "xenia/ui/windowed_app_context.h" #include "xenia/xbox.h" @@ -51,7 +52,8 @@ class XamDialog : public xe::ui::ImGuiDialog { } protected: - XamDialog(xe::ui::Window* window) : xe::ui::ImGuiDialog(window) {} + XamDialog(xe::ui::ImGuiDrawer* imgui_drawer) + : xe::ui::ImGuiDialog(imgui_drawer) {} void OnClose() override { if (close_callback_) { @@ -206,10 +208,10 @@ DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency); class MessageBoxDialog : public XamDialog { public: - MessageBoxDialog(xe::ui::Window* window, std::string title, + MessageBoxDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title, std::string description, std::vector buttons, uint32_t default_button) - : XamDialog(window), + : XamDialog(imgui_drawer), title_(title), description_(description), buttons_(std::move(buttons)), @@ -310,11 +312,11 @@ dword_result_t XamShowMessageBoxUI_entry( *result_ptr = dialog->chosen_button(); return X_ERROR_SUCCESS; }; - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); result = xeXamDispatchDialog( - new MessageBoxDialog(display_window, title, - xe::to_utf8(text_ptr.value()), buttons, - active_button), + new MessageBoxDialog(imgui_drawer, title, xe::to_utf8(text_ptr.value()), + buttons, active_button), close, overlapped); } return result; @@ -323,10 +325,10 @@ DECLARE_XAM_EXPORT1(XamShowMessageBoxUI, kUI, kImplemented); class KeyboardInputDialog : public XamDialog { public: - KeyboardInputDialog(xe::ui::Window* window, std::string title, + KeyboardInputDialog(xe::ui::ImGuiDrawer* imgui_drawer, std::string title, std::string description, std::string default_text, size_t max_length) - : XamDialog(window), + : XamDialog(imgui_drawer), title_(title), description_(description), default_text_(default_text), @@ -446,10 +448,11 @@ dword_result_t XamShowKeyboardUI_entry( return X_ERROR_SUCCESS; } }; - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); result = xeXamDispatchDialogEx( new KeyboardInputDialog( - display_window, title ? xe::to_utf8(title.value()) : "", + imgui_drawer, title ? xe::to_utf8(title.value()) : "", description ? xe::to_utf8(description.value()) : "", default_text ? xe::to_utf8(default_text.value()) : "", buffer_length), @@ -479,10 +482,11 @@ void XamShowDirtyDiscErrorUI_entry(dword_t user_index) { exit(1); return; } - auto display_window = kernel_state()->emulator()->display_window(); + const Emulator* emulator = kernel_state()->emulator(); + ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer(); xeXamDispatchDialog( new MessageBoxDialog( - display_window, "Disc Read Error", + imgui_drawer, "Disc Read Error", "There's been an issue reading content from the game disc.\nThis is " "likely caused by bad or unimplemented file IO calls.", {"OK"}, 0), diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc index 4470cd36e..0bc8a8f8d 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc @@ -124,7 +124,7 @@ void HandleCppException(pointer_t record) { } void RtlRaiseException_entry(pointer_t record) { - switch (record->exception_code) { + switch (record->code) { case 0x406D1388: { HandleSetThreadName(record); return; diff --git a/src/xenia/ui/d3d12/d3d12_api.h b/src/xenia/ui/d3d12/d3d12_api.h index e474d9391..82bc44bff 100644 --- a/src/xenia/ui/d3d12/d3d12_api.h +++ b/src/xenia/ui/d3d12/d3d12_api.h @@ -10,15 +10,14 @@ #ifndef XENIA_UI_D3D12_D3D12_API_H_ #define XENIA_UI_D3D12_D3D12_API_H_ -// This must be included before D3D and DXGI for things like NOMINMAX. +// Must be included before D3D and DXGI for things like NOMINMAX. #include "xenia/base/platform_win.h" #include #include #include #include -#include -#include +#include #include // For Microsoft::WRL::ComPtr. #include diff --git a/src/xenia/ui/d3d12/d3d12_context.cc b/src/xenia/ui/d3d12/d3d12_context.cc deleted file mode 100644 index a37c61b72..000000000 --- a/src/xenia/ui/d3d12/d3d12_context.cc +++ /dev/null @@ -1,379 +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. * - ****************************************************************************** - */ - -#include "xenia/ui/d3d12/d3d12_context.h" - -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" -#include "xenia/ui/d3d12/d3d12_provider.h" -#include "xenia/ui/d3d12/d3d12_util.h" -#include "xenia/ui/window.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -D3D12Context::D3D12Context(D3D12Provider* provider, Window* target_window) - : GraphicsContext(provider, target_window) {} - -D3D12Context::~D3D12Context() { Shutdown(); } - -bool D3D12Context::Initialize() { - context_lost_ = false; - - if (!target_window_) { - return true; - } - - const D3D12Provider& provider = GetD3D12Provider(); - IDXGIFactory2* dxgi_factory = provider.GetDXGIFactory(); - ID3D12Device* device = provider.GetDevice(); - ID3D12CommandQueue* direct_queue = provider.GetDirectQueue(); - - swap_fence_current_value_ = 1; - swap_fence_completed_value_ = 0; - swap_fence_completion_event_ = CreateEvent(nullptr, false, false, nullptr); - if (swap_fence_completion_event_ == nullptr) { - XELOGE("Failed to create the composition fence completion event"); - Shutdown(); - return false; - } - // Create a fence for transient resources of compositing. - if (FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, - IID_PPV_ARGS(&swap_fence_)))) { - XELOGE("Failed to create the composition fence"); - Shutdown(); - return false; - } - - // Create the swap chain. - swap_chain_width_ = target_window_->scaled_width(); - swap_chain_height_ = target_window_->scaled_height(); - DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; - swap_chain_desc.Width = swap_chain_width_; - swap_chain_desc.Height = swap_chain_height_; - swap_chain_desc.Format = kSwapChainFormat; - swap_chain_desc.Stereo = FALSE; - swap_chain_desc.SampleDesc.Count = 1; - swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.BufferCount = kSwapChainBufferCount; - swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; - swap_chain_desc.Flags = 0; - IDXGISwapChain1* swap_chain_1; - if (FAILED(dxgi_factory->CreateSwapChainForComposition( - provider.GetDirectQueue(), &swap_chain_desc, nullptr, - &swap_chain_1))) { - XELOGE("Failed to create a DXGI swap chain for composition"); - Shutdown(); - return false; - } - if (FAILED(swap_chain_1->QueryInterface(IID_PPV_ARGS(&swap_chain_)))) { - XELOGE("Failed to get version 3 of the DXGI swap chain interface"); - swap_chain_1->Release(); - Shutdown(); - return false; - } - swap_chain_1->Release(); - - // Create a heap for RTV descriptors of swap chain buffers. - D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc; - rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtv_heap_desc.NumDescriptors = kSwapChainBufferCount; - rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - rtv_heap_desc.NodeMask = 0; - if (FAILED(device->CreateDescriptorHeap( - &rtv_heap_desc, IID_PPV_ARGS(&swap_chain_rtv_heap_)))) { - XELOGE("Failed to create swap chain RTV descriptor heap"); - Shutdown(); - return false; - } - swap_chain_rtv_heap_start_ = - swap_chain_rtv_heap_->GetCPUDescriptorHandleForHeapStart(); - - // Get the buffers and create their RTV descriptors. - if (!InitializeSwapChainBuffers()) { - Shutdown(); - return false; - } - - // Create the command list for compositing. - for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { - if (FAILED(device->CreateCommandAllocator( - D3D12_COMMAND_LIST_TYPE_DIRECT, - IID_PPV_ARGS(&swap_command_allocators_[i])))) { - XELOGE("Failed to create a composition command allocator"); - Shutdown(); - return false; - } - } - if (FAILED(device->CreateCommandList( - 0, D3D12_COMMAND_LIST_TYPE_DIRECT, swap_command_allocators_[0].Get(), - nullptr, IID_PPV_ARGS(&swap_command_list_)))) { - XELOGE("Failed to create the composition graphics command list"); - Shutdown(); - return false; - } - // Initially in open state, wait until BeginSwap. - swap_command_list_->Close(); - - // Associate the swap chain with the window via DirectComposition. - if (FAILED(provider.CreateDCompositionDevice(nullptr, - IID_PPV_ARGS(&dcomp_device_)))) { - XELOGE("Failed to create a DirectComposition device"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->CreateTargetForHwnd( - reinterpret_cast(target_window_->native_handle()), TRUE, - &dcomp_target_))) { - XELOGE("Failed to create a DirectComposition target for the window"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->CreateVisual(&dcomp_visual_))) { - XELOGE("Failed to create a DirectComposition visual"); - Shutdown(); - return false; - } - if (FAILED(dcomp_visual_->SetContent(swap_chain_.Get()))) { - XELOGE( - "Failed to set the content of the DirectComposition visual to the swap " - "chain"); - Shutdown(); - return false; - } - if (FAILED(dcomp_target_->SetRoot(dcomp_visual_.Get()))) { - XELOGE( - "Failed to set the root of the DirectComposition target to the swap " - "chain visual"); - Shutdown(); - return false; - } - if (FAILED(dcomp_device_->Commit())) { - XELOGE("Failed to commit DirectComposition commands"); - Shutdown(); - return false; - } - - // Initialize the immediate mode drawer if not offscreen. - immediate_drawer_ = std::make_unique(*this); - if (!immediate_drawer_->Initialize()) { - Shutdown(); - return false; - } - - return true; -} - -bool D3D12Context::InitializeSwapChainBuffers() { - // Get references to the buffers. - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - if (FAILED( - swap_chain_->GetBuffer(i, IID_PPV_ARGS(&swap_chain_buffers_[i])))) { - XELOGE("Failed to get buffer {} of the swap chain", i); - return false; - } - } - - // Get the back buffer index for the first draw. - swap_chain_back_buffer_index_ = swap_chain_->GetCurrentBackBufferIndex(); - - // Create RTV descriptors for the swap chain buffers. - ID3D12Device* device = GetD3D12Provider().GetDevice(); - D3D12_RENDER_TARGET_VIEW_DESC rtv_desc; - rtv_desc.Format = kSwapChainFormat; - rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - rtv_desc.Texture2D.MipSlice = 0; - rtv_desc.Texture2D.PlaneSlice = 0; - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - device->CreateRenderTargetView(swap_chain_buffers_[i].Get(), &rtv_desc, - GetSwapChainBufferRTV(i)); - } - - return true; -} - -void D3D12Context::Shutdown() { - if (!target_window_) { - return; - } - - if (!context_lost_ && swap_fence_ && - swap_fence_->GetCompletedValue() + 1 < swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion(swap_fence_current_value_ - 1, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - } - - immediate_drawer_.reset(); - - dcomp_visual_.Reset(); - dcomp_target_.Reset(); - dcomp_device_.Reset(); - - swap_command_list_.Reset(); - for (uint32_t i = 0; i < kSwapCommandAllocatorCount; ++i) { - swap_command_allocators_[i].Reset(); - } - - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - swap_chain_buffers_[i].Reset(); - } - swap_chain_rtv_heap_.Reset(); - swap_chain_.Reset(); - - // First release the fence since it may reference the event. - swap_fence_.Reset(); - if (swap_fence_completion_event_) { - CloseHandle(swap_fence_completion_event_); - swap_fence_completion_event_ = nullptr; - } - swap_fence_current_value_ = 1; - swap_fence_completed_value_ = 0; -} - -ImmediateDrawer* D3D12Context::immediate_drawer() { - return immediate_drawer_.get(); -} - -bool D3D12Context::WasLost() { return context_lost_; } - -bool D3D12Context::BeginSwap() { - if (!target_window_ || context_lost_) { - return false; - } - - // Resize the swap chain if the window is resized. - uint32_t target_window_width = target_window_->scaled_width(); - uint32_t target_window_height = target_window_->scaled_height(); - if (swap_chain_width_ != target_window_width || - swap_chain_height_ != target_window_height) { - // Await the completion of swap chain use. - // Context loss is also faked if resizing fails. In this case, before the - // context is shut down to be recreated, frame completion must be awaited - // (this isn't done if the context is truly lost). - if (swap_fence_completed_value_ + 1 < swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion(swap_fence_current_value_ - 1, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - swap_fence_completed_value_ = swap_fence_current_value_ - 1; - } - // All buffer references must be released before resizing. - for (uint32_t i = 0; i < kSwapChainBufferCount; ++i) { - swap_chain_buffers_[i].Reset(); - } - if (FAILED(swap_chain_->ResizeBuffers( - kSwapChainBufferCount, target_window_width, target_window_height, - kSwapChainFormat, 0))) { - context_lost_ = true; - return false; - } - swap_chain_width_ = target_window_width; - swap_chain_height_ = target_window_height; - if (!InitializeSwapChainBuffers()) { - context_lost_ = true; - return false; - } - } - - // Wait for a swap command allocator to become free. - // Command allocator 0 is used when swap_fence_current_value_ is 1, 4, 7... - swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); - if (swap_fence_completed_value_ + kSwapCommandAllocatorCount < - swap_fence_current_value_) { - swap_fence_->SetEventOnCompletion( - swap_fence_current_value_ - kSwapCommandAllocatorCount, - swap_fence_completion_event_); - WaitForSingleObject(swap_fence_completion_event_, INFINITE); - swap_fence_completed_value_ = swap_fence_->GetCompletedValue(); - } - - // Start the command list. - uint32_t command_allocator_index = - uint32_t((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1)) % - kSwapCommandAllocatorCount); - ID3D12CommandAllocator* command_allocator = - swap_command_allocators_[command_allocator_index].Get(); - command_allocator->Reset(); - swap_command_list_->Reset(command_allocator, nullptr); - - // Bind the back buffer as a render target and clear it. - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = - swap_chain_buffers_[swap_chain_back_buffer_index_].Get(); - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - swap_command_list_->ResourceBarrier(1, &barrier); - D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = GetSwapChainBackBufferRTV(); - swap_command_list_->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); - float clear_color[4]; - GetClearColor(clear_color); - swap_command_list_->ClearRenderTargetView(back_buffer_rtv, clear_color, 0, - nullptr); - - return true; -} - -void D3D12Context::EndSwap() { - if (!target_window_ || context_lost_) { - return; - } - - ID3D12CommandQueue* direct_queue = GetD3D12Provider().GetDirectQueue(); - - // Switch the back buffer to presentation state. - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = - swap_chain_buffers_[swap_chain_back_buffer_index_].Get(); - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - swap_command_list_->ResourceBarrier(1, &barrier); - - // Submit the command list. - swap_command_list_->Close(); - ID3D12CommandList* execute_command_lists[] = {swap_command_list_.Get()}; - direct_queue->ExecuteCommandLists(1, execute_command_lists); - - // Present and check if the context was lost. - if (FAILED(swap_chain_->Present(0, 0))) { - context_lost_ = true; - return; - } - - // Signal the fence to wait for frame resources to become free again. - direct_queue->Signal(swap_fence_.Get(), swap_fence_current_value_++); - - // Get the back buffer index for the next frame. - swap_chain_back_buffer_index_ = swap_chain_->GetCurrentBackBufferIndex(); -} - -std::unique_ptr D3D12Context::Capture() { - // TODO(Triang3l): Read back swap chain front buffer. - return nullptr; -} - -D3D12_CPU_DESCRIPTOR_HANDLE D3D12Context::GetSwapChainBufferRTV( - uint32_t buffer_index) const { - return GetD3D12Provider().OffsetRTVDescriptor(swap_chain_rtv_heap_start_, - buffer_index); -} - -} // namespace d3d12 -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_context.h b/src/xenia/ui/d3d12/d3d12_context.h deleted file mode 100644 index 308d3aa6f..000000000 --- a/src/xenia/ui/d3d12/d3d12_context.h +++ /dev/null @@ -1,112 +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_D3D12_D3D12_CONTEXT_H_ -#define XENIA_UI_D3D12_D3D12_CONTEXT_H_ - -#include - -#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" -#include "xenia/ui/d3d12/d3d12_provider.h" -#include "xenia/ui/graphics_context.h" - -namespace xe { -namespace ui { -namespace d3d12 { - -class D3D12Context : public GraphicsContext { - public: - ~D3D12Context() override; - - ImmediateDrawer* immediate_drawer() override; - - bool WasLost() override; - - bool BeginSwap() override; - void EndSwap() override; - - std::unique_ptr Capture() override; - - D3D12Provider& GetD3D12Provider() const { - return static_cast(*provider_); - } - - // The format used by DWM. - static constexpr DXGI_FORMAT kSwapChainFormat = DXGI_FORMAT_B8G8R8A8_UNORM; - ID3D12Resource* GetSwapChainBuffer(uint32_t buffer_index) const { - return swap_chain_buffers_[buffer_index].Get(); - } - uint32_t GetSwapChainBackBufferIndex() const { - return swap_chain_back_buffer_index_; - } - D3D12_CPU_DESCRIPTOR_HANDLE GetSwapChainBufferRTV( - uint32_t buffer_index) const; - D3D12_CPU_DESCRIPTOR_HANDLE GetSwapChainBackBufferRTV() const { - return GetSwapChainBufferRTV(GetSwapChainBackBufferIndex()); - } - void GetSwapChainSize(uint32_t& width, uint32_t& height) const { - width = swap_chain_width_; - height = swap_chain_height_; - } - // Inside the current BeginSwap/EndSwap pair. - uint64_t GetSwapCurrentFenceValue() const { - return swap_fence_current_value_; - } - uint64_t GetSwapCompletedFenceValue() const { - return swap_fence_completed_value_; - } - ID3D12GraphicsCommandList* GetSwapCommandList() const { - return swap_command_list_.Get(); - } - - private: - friend class D3D12Provider; - explicit D3D12Context(D3D12Provider* provider, Window* target_window); - bool Initialize(); - - private: - bool InitializeSwapChainBuffers(); - void Shutdown(); - - bool context_lost_ = false; - - static constexpr uint32_t kSwapChainBufferCount = 3; - Microsoft::WRL::ComPtr swap_chain_; - uint32_t swap_chain_width_ = 0, swap_chain_height_ = 0; - Microsoft::WRL::ComPtr - swap_chain_buffers_[kSwapChainBufferCount]; - uint32_t swap_chain_back_buffer_index_ = 0; - Microsoft::WRL::ComPtr swap_chain_rtv_heap_; - D3D12_CPU_DESCRIPTOR_HANDLE swap_chain_rtv_heap_start_; - - uint64_t swap_fence_current_value_ = 1; - uint64_t swap_fence_completed_value_ = 0; - HANDLE swap_fence_completion_event_ = nullptr; - Microsoft::WRL::ComPtr swap_fence_; - - static constexpr uint32_t kSwapCommandAllocatorCount = 3; - Microsoft::WRL::ComPtr - swap_command_allocators_[kSwapCommandAllocatorCount]; - // Current command allocator is: - // ((swap_fence_current_value_ + (kSwapCommandAllocatorCount - 1))) % - // kSwapCommandAllocatorCount. - Microsoft::WRL::ComPtr swap_command_list_; - - Microsoft::WRL::ComPtr dcomp_device_; - Microsoft::WRL::ComPtr dcomp_target_; - Microsoft::WRL::ComPtr dcomp_visual_; - - std::unique_ptr immediate_drawer_; -}; - -} // namespace d3d12 -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_D3D12_D3D12_CONTEXT_H_ diff --git a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc index 5d3dac99d..906a8a1d9 100644 --- a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc +++ b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -41,6 +41,25 @@ void D3D12DescriptorHeapPool::Reclaim(uint64_t completed_submission_index) { } } +void D3D12DescriptorHeapPool::ChangeSubmissionTimeline() { + // Reclaim all submitted pages. + if (writable_last_) { + writable_last_->next = submitted_first_; + } else { + writable_first_ = submitted_first_; + } + writable_last_ = submitted_last_; + submitted_first_ = nullptr; + submitted_last_ = nullptr; + + // Mark all pages as never used yet in the new timeline. + Page* page = writable_first_; + while (page) { + page->last_submission_index = 0; + page = page->next; + } +} + void D3D12DescriptorHeapPool::ClearCache() { // Not checking current_page_used_ != 0 because asking for 0 descriptors // returns a valid heap also - but actually the new heap will be different now @@ -49,14 +68,12 @@ void D3D12DescriptorHeapPool::ClearCache() { current_page_used_ = 0; while (submitted_first_) { auto next = submitted_first_->next; - submitted_first_->heap->Release(); delete submitted_first_; submitted_first_ = next; } submitted_last_ = nullptr; while (writable_first_) { auto next = writable_first_->next; - writable_first_->heap->Release(); delete writable_first_; writable_first_ = next; } @@ -110,7 +127,7 @@ uint64_t D3D12DescriptorHeapPool::Request(uint64_t submission_index, new_heap_desc.NumDescriptors = page_size_; new_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; new_heap_desc.NodeMask = 0; - ID3D12DescriptorHeap* new_heap; + Microsoft::WRL::ComPtr new_heap; if (FAILED(device_->CreateDescriptorHeap(&new_heap_desc, IID_PPV_ARGS(&new_heap)))) { XELOGE("Failed to create a heap for {} shader-visible descriptors", diff --git a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h index fbc77aeef..9eb1c5b31 100644 --- a/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h +++ b/src/xenia/ui/d3d12/d3d12_descriptor_heap_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -30,6 +30,7 @@ class D3D12DescriptorHeapPool { ~D3D12DescriptorHeapPool(); void Reclaim(uint64_t completed_submission_index); + void ChangeSubmissionTimeline(); void ClearCache(); // Because all descriptors for a single draw call must be in the same heap, @@ -65,7 +66,7 @@ class D3D12DescriptorHeapPool { // after a successful request because before a request, the heap may not exist // yet. ID3D12DescriptorHeap* GetLastRequestHeap() const { - return writable_first_->heap; + return writable_first_->heap.Get(); } D3D12_CPU_DESCRIPTOR_HANDLE GetLastRequestHeapCPUStart() const { return writable_first_->cpu_start; @@ -80,7 +81,7 @@ class D3D12DescriptorHeapPool { uint32_t page_size_; struct Page { - ID3D12DescriptorHeap* heap; + Microsoft::WRL::ComPtr heap; D3D12_CPU_DESCRIPTOR_HANDLE cpu_start; D3D12_GPU_DESCRIPTOR_HANDLE gpu_start; uint64_t last_submission_index; diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc index 5cd6b551c..76bdcb5c0 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,7 +17,7 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_context.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" #include "xenia/ui/d3d12/d3d12_util.h" namespace xe { @@ -38,35 +38,40 @@ D3D12ImmediateDrawer::D3D12ImmediateTexture::D3D12ImmediateTexture( resource_(resource), sampler_index_(sampler_index), immediate_drawer_(immediate_drawer), - immediate_drawer_index_(immediate_drawer_index) { - if (resource_) { - resource_->AddRef(); - } -} + immediate_drawer_index_(immediate_drawer_index) {} D3D12ImmediateDrawer::D3D12ImmediateTexture::~D3D12ImmediateTexture() { if (immediate_drawer_) { immediate_drawer_->OnImmediateTextureDestroyed(*this); } - if (resource_) { - resource_->Release(); - } } -void D3D12ImmediateDrawer::D3D12ImmediateTexture::OnImmediateDrawerShutdown() { +void D3D12ImmediateDrawer::D3D12ImmediateTexture::OnImmediateDrawerDestroyed() { immediate_drawer_ = nullptr; // Lifetime is not managed anymore, so don't keep the resource either. - util::ReleaseAndNull(resource_); + resource_.Reset(); } -D3D12ImmediateDrawer::D3D12ImmediateDrawer(D3D12Context& graphics_context) - : ImmediateDrawer(&graphics_context), context_(graphics_context) {} +D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { + // Await GPU usage completion of all draws and texture uploads (which happen + // before draws). + auto d3d12_presenter = static_cast(presenter()); + if (d3d12_presenter) { + d3d12_presenter->AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + } -D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { Shutdown(); } + // Texture resources and descriptors are owned and tracked by the immediate + // drawer. Zombie texture objects are supported, but are meaningless. + assert_true(textures_.empty()); + for (D3D12ImmediateTexture* texture : textures_) { + texture->OnImmediateDrawerDestroyed(); + } + textures_.clear(); +} bool D3D12ImmediateDrawer::Initialize() { - const D3D12Provider& provider = context_.GetD3D12Provider(); - ID3D12Device* device = provider.GetDevice(); + ID3D12Device* device = provider_.GetDevice(); // Create the root signature. D3D12_ROOT_PARAMETER root_parameters[size_t(RootParameter::kCount)]; @@ -99,7 +104,7 @@ bool D3D12ImmediateDrawer::Initialize() { } { auto& root_parameter = - root_parameters[size_t(RootParameter::kViewportSizeInv)]; + root_parameters[size_t(RootParameter::kCoordinateSpaceSizeInv)]; root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; root_parameter.Constants.ShaderRegister = 0; root_parameter.Constants.RegisterSpace = 0; @@ -113,16 +118,16 @@ bool D3D12ImmediateDrawer::Initialize() { root_signature_desc.pStaticSamplers = nullptr; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - root_signature_ = util::CreateRootSignature(provider, root_signature_desc); - if (root_signature_ == nullptr) { - XELOGE("Failed to create the Direct3D 12 immediate drawer root signature"); - Shutdown(); + *(root_signature_.ReleaseAndGetAddressOf()) = + util::CreateRootSignature(provider_, root_signature_desc); + if (!root_signature_) { + XELOGE("D3D12ImmediateDrawer: Failed to create the root signature"); return false; } // Create the pipelines. D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_desc = {}; - pipeline_desc.pRootSignature = root_signature_; + pipeline_desc.pRootSignature = root_signature_.Get(); pipeline_desc.VS.pShaderBytecode = shaders::immediate_vs; pipeline_desc.VS.BytecodeLength = sizeof(shaders::immediate_vs); pipeline_desc.PS.pShaderBytecode = shaders::immediate_ps; @@ -133,13 +138,10 @@ bool D3D12ImmediateDrawer::Initialize() { pipeline_blend_desc.SrcBlend = D3D12_BLEND_SRC_ALPHA; pipeline_blend_desc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA; pipeline_blend_desc.BlendOp = D3D12_BLEND_OP_ADD; - // Don't change alpha (always 1). - pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_ZERO; + pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_ONE; pipeline_blend_desc.DestBlendAlpha = D3D12_BLEND_ONE; pipeline_blend_desc.BlendOpAlpha = D3D12_BLEND_OP_ADD; - pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_RED | - D3D12_COLOR_WRITE_ENABLE_GREEN | - D3D12_COLOR_WRITE_ENABLE_BLUE; + pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; pipeline_desc.SampleMask = UINT_MAX; pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; @@ -161,23 +163,17 @@ bool D3D12ImmediateDrawer::Initialize() { UINT(xe::countof(pipeline_input_elements)); pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; pipeline_desc.NumRenderTargets = 1; - pipeline_desc.RTVFormats[0] = D3D12Context::kSwapChainFormat; + pipeline_desc.RTVFormats[0] = D3D12Presenter::kSwapChainFormat; pipeline_desc.SampleDesc.Count = 1; if (FAILED(device->CreateGraphicsPipelineState( &pipeline_desc, IID_PPV_ARGS(&pipeline_triangle_)))) { - XELOGE( - "Failed to create the Direct3D 12 immediate drawer triangle pipeline " - "state"); - Shutdown(); + XELOGE("D3D12ImmediateDrawer: Failed to create the triangle pipeline"); return false; } pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; if (FAILED(device->CreateGraphicsPipelineState( &pipeline_desc, IID_PPV_ARGS(&pipeline_line_)))) { - XELOGE( - "Failed to create the Direct3D 12 immediate drawer line pipeline " - "state"); - Shutdown(); + XELOGE("D3D12ImmediateDrawer: Failed to create the line pipeline"); return false; } @@ -190,14 +186,12 @@ bool D3D12ImmediateDrawer::Initialize() { if (FAILED(device->CreateDescriptorHeap(&sampler_heap_desc, IID_PPV_ARGS(&sampler_heap_)))) { XELOGE( - "Failed to create the Direct3D 12 immediate drawer sampler descriptor " - "heap"); - Shutdown(); + "D3D12ImmediateDrawer: Failed to create the sampler descriptor heap"); return false; } sampler_heap_cpu_start_ = sampler_heap_->GetCPUDescriptorHandleForHeapStart(); sampler_heap_gpu_start_ = sampler_heap_->GetGPUDescriptorHandleForHeapStart(); - uint32_t sampler_size = provider.GetSamplerDescriptorSize(); + uint32_t sampler_size = provider_.GetSamplerDescriptorSize(); // Nearest neighbor, clamp. D3D12_SAMPLER_DESC sampler_desc = {}; sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; @@ -228,58 +222,22 @@ bool D3D12ImmediateDrawer::Initialize() { device->CreateSampler(&sampler_desc, sampler_handle); // Create pools for draws. - vertex_buffer_pool_ = std::make_unique(provider); + vertex_buffer_pool_ = std::make_unique(provider_); texture_descriptor_pool_ = std::make_unique( device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048); // Reset the current state. - current_command_list_ = nullptr; batch_open_ = false; return true; } -void D3D12ImmediateDrawer::Shutdown() { - for (auto& deleted_texture : textures_deleted_) { - deleted_texture.first->Release(); - } - textures_deleted_.clear(); - - for (auto& texture_upload : texture_uploads_submitted_) { - texture_upload.buffer->Release(); - texture_upload.texture->Release(); - } - texture_uploads_submitted_.clear(); - - for (auto& texture_upload : texture_uploads_pending_) { - texture_upload.buffer->Release(); - texture_upload.texture->Release(); - } - texture_uploads_pending_.clear(); - - for (D3D12ImmediateTexture* texture : textures_) { - texture->OnImmediateDrawerShutdown(); - } - textures_.clear(); - - texture_descriptor_pool_.reset(); - vertex_buffer_pool_.reset(); - - util::ReleaseAndNull(sampler_heap_); - - util::ReleaseAndNull(pipeline_line_); - util::ReleaseAndNull(pipeline_triangle_); - - util::ReleaseAndNull(root_signature_); -} - std::unique_ptr D3D12ImmediateDrawer::CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool is_repeated, const uint8_t* data) { - const D3D12Provider& provider = context_.GetD3D12Provider(); - ID3D12Device* device = provider.GetDevice(); + ID3D12Device* device = provider_.GetDevice(); D3D12_HEAP_FLAGS heap_flag_create_not_zeroed = - provider.GetHeapFlagCreateNotZeroed(); + provider_.GetHeapFlagCreateNotZeroed(); D3D12_RESOURCE_DESC resource_desc; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -293,8 +251,8 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; - ID3D12Resource* resource; - if (SUCCEEDED(provider.GetDevice()->CreateCommittedResource( + Microsoft::WRL::ComPtr resource; + if (SUCCEEDED(device->CreateCommittedResource( &util::kHeapPropertiesDefault, heap_flag_create_not_zeroed, &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&resource)))) { @@ -306,7 +264,7 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( D3D12_RESOURCE_DESC upload_buffer_desc; util::FillBufferResourceDesc(upload_buffer_desc, upload_size, D3D12_RESOURCE_FLAG_NONE); - ID3D12Resource* upload_buffer; + Microsoft::WRL::ComPtr upload_buffer; if (SUCCEEDED(device->CreateCommittedResource( &util::kHeapPropertiesUpload, heap_flag_create_not_zeroed, &upload_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, @@ -333,35 +291,30 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( } upload_buffer->Unmap(0, nullptr); // Defer uploading and transition to the next draw. - PendingTextureUpload& pending_upload = - texture_uploads_pending_.emplace_back(); // While the upload has not been yet completed, keep a reference to the // resource because its lifetime is not tied to that of the // ImmediateTexture (and thus to context's submissions) now. - resource->AddRef(); - pending_upload.texture = resource; - pending_upload.buffer = upload_buffer; + PendingTextureUpload& pending_upload = + texture_uploads_pending_.emplace_back(resource.Get(), + upload_buffer.Get()); } else { XELOGE( - "Failed to map a Direct3D 12 upload buffer for a {}x{} texture for " - "immediate drawing", + "D3D12ImmediateDrawer: Failed to map an upload buffer for a {}x{} " + "texture", width, height); - upload_buffer->Release(); - resource->Release(); - resource = nullptr; + upload_buffer.Reset(); + resource.Reset(); } } else { XELOGE( - "Failed to create a Direct3D 12 upload buffer for a {}x{} texture " - "for immediate drawing", + "D3D12ImmediateDrawer: Failed to create an upload buffer for a {}x{} " + "texture", width, height); - resource->Release(); - resource = nullptr; + resource.Reset(); } } else { - XELOGE("Failed to create a {}x{} Direct3D 12 texture for immediate drawing", - width, height); - resource = nullptr; + XELOGE("D3D12ImmediateDrawer: Failed to create a {}x{} texture", width, + height); } SamplerIndex sampler_index; @@ -376,35 +329,38 @@ std::unique_ptr D3D12ImmediateDrawer::CreateTexture( // Manage by this immediate drawer if successfully created a resource. std::unique_ptr texture = std::make_unique( - width, height, resource, sampler_index, resource ? this : nullptr, - textures_.size()); + width, height, resource.Get(), sampler_index, + resource ? this : nullptr, textures_.size()); if (resource) { textures_.push_back(texture.get()); - // D3D12ImmediateTexture now holds a reference. - resource->Release(); } return std::move(texture); } -void D3D12ImmediateDrawer::Begin(int render_target_width, - int render_target_height) { - assert_null(current_command_list_); +void D3D12ImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + ImmediateDrawer::Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); + assert_false(batch_open_); - ID3D12Device* device = context_.GetD3D12Provider().GetDevice(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + static_cast(ui_draw_context); - // Use the compositing command list. - current_command_list_ = context_.GetSwapCommandList(); - - uint64_t completed_fence_value = context_.GetSwapCompletedFenceValue(); + // Update the submission index to be used throughout the current immediate + // drawer paint. + last_paint_submission_index_ = + d3d12_ui_draw_context.submission_index_current(); + last_completed_submission_index_ = + d3d12_ui_draw_context.submission_index_completed(); // Release deleted textures. for (auto it = textures_deleted_.begin(); it != textures_deleted_.end();) { - if (it->second > completed_fence_value) { + if (it->second > last_completed_submission_index_) { ++it; continue; } - it->first->Release(); if (std::next(it) != textures_deleted_.end()) { *it = textures_deleted_.back(); } @@ -414,37 +370,45 @@ void D3D12ImmediateDrawer::Begin(int render_target_width, // Release upload buffers for completed texture uploads. auto erase_uploads_end = texture_uploads_submitted_.begin(); while (erase_uploads_end != texture_uploads_submitted_.end()) { - if (erase_uploads_end->fence_value > completed_fence_value) { + if (erase_uploads_end->submission_index > + last_completed_submission_index_) { break; } - erase_uploads_end->buffer->Release(); - // Release the texture reference held for uploading. - erase_uploads_end->texture->Release(); ++erase_uploads_end; } texture_uploads_submitted_.erase(texture_uploads_submitted_.begin(), erase_uploads_end); - vertex_buffer_pool_->Reclaim(completed_fence_value); - texture_descriptor_pool_->Reclaim(completed_fence_value); + // Make sure textures created before the current frame are uploaded, even if + // nothing was drawn in the previous frames or nothing will be drawn in the + // current or subsequent ones, as that would result in upload buffers kept + // forever. + UploadTextures(); + + texture_descriptor_pool_->Reclaim(last_completed_submission_index_); + vertex_buffer_pool_->Reclaim(last_completed_submission_index_); + + // Begin drawing. + + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); - current_render_target_width_ = render_target_width; - current_render_target_height_ = render_target_height; D3D12_VIEWPORT viewport; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; - viewport.Width = float(render_target_width); - viewport.Height = float(render_target_height); + viewport.Width = float(d3d12_ui_draw_context.render_target_width()); + viewport.Height = float(d3d12_ui_draw_context.render_target_height()); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; - current_command_list_->RSSetViewports(1, &viewport); + command_list->RSSetViewports(1, &viewport); - current_command_list_->SetGraphicsRootSignature(root_signature_); - float viewport_inv_size[2]; - viewport_inv_size[0] = 1.0f / viewport.Width; - viewport_inv_size[1] = 1.0f / viewport.Height; - current_command_list_->SetGraphicsRoot32BitConstants( - UINT(RootParameter::kViewportSizeInv), 2, viewport_inv_size, 0); + command_list->SetGraphicsRootSignature(root_signature_.Get()); + float coordinate_space_size_inv[2]; + coordinate_space_size_inv[0] = 1.0f / coordinate_space_width; + coordinate_space_size_inv[1] = 1.0f / coordinate_space_height; + command_list->SetGraphicsRoot32BitConstants( + UINT(RootParameter::kCoordinateSpaceSizeInv), 2, + coordinate_space_size_inv, 0); current_scissor_.left = 0; current_scissor_.top = 0; @@ -460,9 +424,12 @@ void D3D12ImmediateDrawer::Begin(int render_target_width, void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { assert_false(batch_open_); - assert_not_null(current_command_list_); - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); // Bind the vertices. D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view; @@ -470,16 +437,16 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { vertex_buffer_view.SizeInBytes = UINT(sizeof(ImmediateVertex)) * batch.vertex_count; void* vertex_buffer_mapping = vertex_buffer_pool_->Request( - current_fence_value, vertex_buffer_view.SizeInBytes, sizeof(float), - nullptr, nullptr, &vertex_buffer_view.BufferLocation); + last_paint_submission_index_, vertex_buffer_view.SizeInBytes, + sizeof(float), nullptr, nullptr, &vertex_buffer_view.BufferLocation); if (vertex_buffer_mapping == nullptr) { - XELOGE("Failed to get a buffer for {} vertices in the immediate drawer", + XELOGE("D3D12ImmediateDrawer: Failed to get a buffer for {} vertices", batch.vertex_count); return; } std::memcpy(vertex_buffer_mapping, batch.vertices, vertex_buffer_view.SizeInBytes); - current_command_list_->IASetVertexBuffers(0, 1, &vertex_buffer_view); + command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); // Bind the indices. batch_has_index_buffer_ = batch.indices != nullptr; @@ -488,16 +455,16 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { index_buffer_view.SizeInBytes = UINT(sizeof(uint16_t)) * batch.index_count; index_buffer_view.Format = DXGI_FORMAT_R16_UINT; void* index_buffer_mapping = vertex_buffer_pool_->Request( - current_fence_value, index_buffer_view.SizeInBytes, sizeof(uint16_t), - nullptr, nullptr, &index_buffer_view.BufferLocation); + last_paint_submission_index_, index_buffer_view.SizeInBytes, + sizeof(uint16_t), nullptr, nullptr, &index_buffer_view.BufferLocation); if (index_buffer_mapping == nullptr) { - XELOGE("Failed to get a buffer for {} indices in the immediate drawer", + XELOGE("D3D12ImmediateDrawer: Failed to get a buffer for {} indices", batch.index_count); return; } std::memcpy(index_buffer_mapping, batch.indices, index_buffer_view.SizeInBytes); - current_command_list_->IASetIndexBuffer(&index_buffer_view); + command_list->IASetIndexBuffer(&index_buffer_view); } batch_open_ = true; @@ -509,30 +476,30 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { return; } - // Set the scissor rectangle if enabled. - D3D12_RECT scissor; - if (draw.scissor) { - scissor.left = draw.scissor_rect[0]; - scissor.top = current_render_target_height_ - - (draw.scissor_rect[1] + draw.scissor_rect[3]); - scissor.right = scissor.left + draw.scissor_rect[2]; - scissor.bottom = scissor.top + draw.scissor_rect[3]; - } else { - scissor.left = 0; - scissor.top = 0; - scissor.right = current_render_target_width_; - scissor.bottom = current_render_target_height_; - } - if (scissor.right <= scissor.left || scissor.bottom <= scissor.top) { - // Nothing is visible (used as the default current_scissor_ value also). + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); + + // Set the scissor rectangle. + uint32_t scissor_left, scissor_top, scissor_width, scissor_height; + if (!ScissorToRenderTarget(draw, scissor_left, scissor_top, scissor_width, + scissor_height)) { + // Nothing is visible (zero area is used as the default current_scissor_ + // value also). return; } + D3D12_RECT scissor; + scissor.left = LONG(scissor_left); + scissor.top = LONG(scissor_top); + scissor.right = LONG(scissor_left + scissor_width); + scissor.bottom = LONG(scissor_top + scissor_height); if (current_scissor_.left != scissor.left || current_scissor_.top != scissor.top || current_scissor_.right != scissor.right || current_scissor_.bottom != scissor.bottom) { current_scissor_ = scissor; - current_command_list_->RSSetScissorRects(1, &scissor); + command_list->RSSetScissorRects(1, &scissor); } // Ensure texture data is available if any texture is loaded, upload all in a @@ -542,30 +509,27 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { // Bind the texture. If this is the first draw in a frame, the descriptor heap // index will be invalid initially, and the texture will be bound regardless // of what's in current_texture_. - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); auto texture = static_cast(draw.texture); ID3D12Resource* texture_resource = texture ? texture->resource() : nullptr; bool bind_texture = current_texture_ != texture_resource; uint32_t texture_descriptor_index; uint64_t texture_heap_index = texture_descriptor_pool_->Request( - current_fence_value, current_texture_descriptor_heap_index_, + last_paint_submission_index_, current_texture_descriptor_heap_index_, bind_texture ? 1 : 0, 1, texture_descriptor_index); if (texture_heap_index == D3D12DescriptorHeapPool::kHeapIndexInvalid) { return; } if (texture_resource) { - texture->SetLastUsageFenceValue(current_fence_value); + texture->SetLastUsageSubmissionIndex(last_paint_submission_index_); } if (current_texture_descriptor_heap_index_ != texture_heap_index) { current_texture_descriptor_heap_index_ = texture_heap_index; bind_texture = true; ID3D12DescriptorHeap* descriptor_heaps[] = { - texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_}; - current_command_list_->SetDescriptorHeaps(2, descriptor_heaps); + texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_.Get()}; + command_list->SetDescriptorHeaps(2, descriptor_heaps); } - const D3D12Provider& provider = context_.GetD3D12Provider(); - if (bind_texture) { current_texture_ = texture_resource; D3D12_SHADER_RESOURCE_VIEW_DESC texture_view_desc; @@ -587,14 +551,14 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { texture_view_desc.Texture2D.MipLevels = 1; texture_view_desc.Texture2D.PlaneSlice = 0; texture_view_desc.Texture2D.ResourceMinLODClamp = 0.0f; - provider.GetDevice()->CreateShaderResourceView( + provider_.GetDevice()->CreateShaderResourceView( texture_resource, &texture_view_desc, - provider.OffsetViewDescriptor( + provider_.OffsetViewDescriptor( texture_descriptor_pool_->GetLastRequestHeapCPUStart(), texture_descriptor_index)); - current_command_list_->SetGraphicsRootDescriptorTable( + command_list->SetGraphicsRootDescriptorTable( UINT(RootParameter::kTexture), - provider.OffsetViewDescriptor( + provider_.OffsetViewDescriptor( texture_descriptor_pool_->GetLastRequestHeapGPUStart(), texture_descriptor_index)); } @@ -605,10 +569,10 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { texture_resource ? texture->sampler_index() : SamplerIndex::kNearestClamp; if (current_sampler_index_ != sampler_index) { current_sampler_index_ = sampler_index; - current_command_list_->SetGraphicsRootDescriptorTable( + command_list->SetGraphicsRootDescriptorTable( UINT(RootParameter::kSampler), - provider.OffsetSamplerDescriptor(sampler_heap_gpu_start_, - uint32_t(sampler_index))); + provider_.OffsetSamplerDescriptor(sampler_heap_gpu_start_, + uint32_t(sampler_index))); } // Set the primitive type and the pipeline for it. @@ -617,11 +581,11 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { switch (draw.primitive_type) { case ImmediatePrimitiveType::kLines: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; - pipeline = pipeline_line_; + pipeline = pipeline_line_.Get(); break; case ImmediatePrimitiveType::kTriangles: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - pipeline = pipeline_triangle_; + pipeline = pipeline_triangle_.Get(); break; default: assert_unhandled_case(draw.primitive_type); @@ -629,16 +593,16 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) { } if (current_primitive_topology_ != primitive_topology) { current_primitive_topology_ = primitive_topology; - current_command_list_->IASetPrimitiveTopology(primitive_topology); - current_command_list_->SetPipelineState(pipeline); + command_list->IASetPrimitiveTopology(primitive_topology); + command_list->SetPipelineState(pipeline); } // Draw. if (batch_has_index_buffer_) { - current_command_list_->DrawIndexedInstanced( - draw.count, 1, draw.index_offset, draw.base_vertex, 0); + command_list->DrawIndexedInstanced(draw.count, 1, draw.index_offset, + draw.base_vertex, 0); } else { - current_command_list_->DrawInstanced(draw.count, 1, draw.base_vertex, 0); + command_list->DrawInstanced(draw.count, 1, draw.base_vertex, 0); } } @@ -646,11 +610,29 @@ void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; } void D3D12ImmediateDrawer::End() { assert_false(batch_open_); - if (current_command_list_) { - // Don't keep upload buffers forever if nothing was drawn in this frame. - UploadTextures(); - current_command_list_ = nullptr; + + ImmediateDrawer::End(); +} + +void D3D12ImmediateDrawer::OnLeavePresenter() { + // Leaving the presenter's submission timeline - await GPU usage completion of + // all draws and texture uploads (which happen before draws) and reset + // submission indices. + D3D12Presenter& d3d12_presenter = *static_cast(presenter()); + d3d12_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + + for (D3D12ImmediateTexture* texture : textures_) { + texture->SetLastUsageSubmissionIndex(0); } + + texture_uploads_submitted_.clear(); + + vertex_buffer_pool_->ChangeSubmissionTimeline(); + texture_descriptor_pool_->ChangeSubmissionTimeline(); + + last_paint_submission_index_ = 0; + last_completed_submission_index_ = 0; } void D3D12ImmediateDrawer::OnImmediateTextureDestroyed( @@ -665,35 +647,35 @@ void D3D12ImmediateDrawer::OnImmediateTextureDestroyed( // Queue for delayed release. ID3D12Resource* resource = texture.resource(); - uint64_t last_usage_fence_value = texture.last_usage_fence_value(); + UINT64 last_usage_submission_index = texture.last_usage_submission_index(); if (resource && - last_usage_fence_value > context_.GetSwapCompletedFenceValue()) { - resource->AddRef(); - textures_deleted_.push_back( - std::make_pair(resource, last_usage_fence_value)); + last_usage_submission_index > last_completed_submission_index_) { + textures_deleted_.emplace_back(resource, last_usage_submission_index); } } void D3D12ImmediateDrawer::UploadTextures() { - assert_not_null(current_command_list_); if (texture_uploads_pending_.empty()) { // Called often - don't initialize anything. return; } - ID3D12Device* device = context_.GetD3D12Provider().GetDevice(); - uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); + ID3D12Device* device = provider_.GetDevice(); + const D3D12UIDrawContext& d3d12_ui_draw_context = + *static_cast(ui_draw_context()); + ID3D12GraphicsCommandList* command_list = + d3d12_ui_draw_context.command_list(); // Copy all at once, then transition all at once (not interleaving copying and // pipeline barriers). std::vector barriers; barriers.reserve(texture_uploads_pending_.size()); for (const PendingTextureUpload& pending_upload : texture_uploads_pending_) { - ID3D12Resource* texture = pending_upload.texture; + ID3D12Resource* texture = pending_upload.texture.Get(); D3D12_RESOURCE_DESC texture_desc = texture->GetDesc(); D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; - location_source.pResource = pending_upload.buffer; + location_source.pResource = pending_upload.buffer.Get(); location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; device->GetCopyableFootprints(&texture_desc, 0, 1, 0, &location_source.PlacedFootprint, nullptr, @@ -701,8 +683,8 @@ void D3D12ImmediateDrawer::UploadTextures() { location_dest.pResource = texture; location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; location_dest.SubresourceIndex = 0; - current_command_list_->CopyTextureRegion(&location_dest, 0, 0, 0, - &location_source, nullptr); + command_list->CopyTextureRegion(&location_dest, 0, 0, 0, &location_source, + nullptr); D3D12_RESOURCE_BARRIER& barrier = barriers.emplace_back(); barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; @@ -712,18 +694,12 @@ void D3D12ImmediateDrawer::UploadTextures() { barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - SubmittedTextureUpload& submitted_upload = - texture_uploads_submitted_.emplace_back(); - // Transfer the reference to the texture - need to keep it until the upload - // is completed. - submitted_upload.texture = texture; - submitted_upload.buffer = pending_upload.buffer; - submitted_upload.fence_value = current_fence_value; + texture_uploads_submitted_.emplace_back( + texture, pending_upload.buffer.Get(), last_paint_submission_index_); } texture_uploads_pending_.clear(); assert_false(barriers.empty()); - current_command_list_->ResourceBarrier(UINT(barriers.size()), - barriers.data()); + command_list->ResourceBarrier(UINT(barriers.size()), barriers.data()); } } // namespace d3d12 diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.h b/src/xenia/ui/d3d12/d3d12_immediate_drawer.h index fbc362f59..2c3691e1f 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.h +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,6 +17,7 @@ #include "xenia/ui/d3d12/d3d12_api.h" #include "xenia/ui/d3d12/d3d12_descriptor_heap_pool.h" +#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_upload_buffer_pool.h" #include "xenia/ui/immediate_drawer.h" @@ -24,15 +25,19 @@ namespace xe { namespace ui { namespace d3d12 { -class D3D12Context; - -class D3D12ImmediateDrawer : public ImmediateDrawer { +class D3D12ImmediateDrawer final : public ImmediateDrawer { public: - D3D12ImmediateDrawer(D3D12Context& graphics_context); - ~D3D12ImmediateDrawer() override; + static std::unique_ptr Create( + const D3D12Provider& provider) { + auto immediate_drawer = std::unique_ptr( + new D3D12ImmediateDrawer(provider)); + if (!immediate_drawer->Initialize()) { + return nullptr; + } + return std::move(immediate_drawer); + } - bool Initialize(); - void Shutdown(); + ~D3D12ImmediateDrawer(); std::unique_ptr CreateTexture(uint32_t width, uint32_t height, @@ -40,12 +45,16 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { bool is_repeated, const uint8_t* data) override; - void Begin(int render_target_width, int render_target_height) override; + void Begin(UIDrawContext& ui_draw_context, float coordinate_space_width, + float coordinate_space_height) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void Draw(const ImmediateDraw& draw) override; void EndDrawBatch() override; void End() override; + protected: + void OnLeavePresenter() override; + private: enum class SamplerIndex { kNearestClamp, @@ -57,7 +66,7 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { kInvalid = kCount }; - class D3D12ImmediateTexture : public ImmediateTexture { + class D3D12ImmediateTexture final : public ImmediateTexture { public: static constexpr DXGI_FORMAT kFormat = DXGI_FORMAT_R8G8B8A8_UNORM; D3D12ImmediateTexture(uint32_t width, uint32_t height, @@ -66,75 +75,93 @@ class D3D12ImmediateDrawer : public ImmediateDrawer { size_t immediate_drawer_index); ~D3D12ImmediateTexture() override; - ID3D12Resource* resource() const { return resource_; } + ID3D12Resource* resource() const { return resource_.Get(); } SamplerIndex sampler_index() const { return sampler_index_; } size_t immediate_drawer_index() const { return immediate_drawer_index_; } void SetImmediateDrawerIndex(size_t index) { immediate_drawer_index_ = index; } - void OnImmediateDrawerShutdown(); + void OnImmediateDrawerDestroyed(); - uint64_t last_usage_fence_value() const { return last_usage_fence_value_; } - void SetLastUsageFenceValue(uint64_t fence_value) { - last_usage_fence_value_ = fence_value; + UINT64 last_usage_submission_index() const { + return last_usage_submission_index_; + } + void SetLastUsageSubmissionIndex(UINT64 submission_index) { + last_usage_submission_index_ = submission_index; } private: - ID3D12Resource* resource_; + Microsoft::WRL::ComPtr resource_; SamplerIndex sampler_index_; D3D12ImmediateDrawer* immediate_drawer_; size_t immediate_drawer_index_; - uint64_t last_usage_fence_value_ = 0; + UINT64 last_usage_submission_index_ = 0; }; + D3D12ImmediateDrawer(const D3D12Provider& provider) : provider_(provider) {} + bool Initialize(); + void OnImmediateTextureDestroyed(D3D12ImmediateTexture& texture); void UploadTextures(); - D3D12Context& context_; + const D3D12Provider& provider_; - ID3D12RootSignature* root_signature_ = nullptr; + Microsoft::WRL::ComPtr root_signature_; enum class RootParameter { kTexture, kSampler, - kViewportSizeInv, + kCoordinateSpaceSizeInv, kCount }; - ID3D12PipelineState* pipeline_triangle_ = nullptr; - ID3D12PipelineState* pipeline_line_ = nullptr; + Microsoft::WRL::ComPtr pipeline_triangle_; + Microsoft::WRL::ComPtr pipeline_line_; - ID3D12DescriptorHeap* sampler_heap_ = nullptr; + Microsoft::WRL::ComPtr sampler_heap_; D3D12_CPU_DESCRIPTOR_HANDLE sampler_heap_cpu_start_; D3D12_GPU_DESCRIPTOR_HANDLE sampler_heap_gpu_start_; - std::unique_ptr vertex_buffer_pool_; - std::unique_ptr texture_descriptor_pool_; - // Only with non-null resources. std::vector textures_; struct PendingTextureUpload { - ID3D12Resource* texture; - ID3D12Resource* buffer; + PendingTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer) + : texture(texture), buffer(buffer) {} + Microsoft::WRL::ComPtr texture; + Microsoft::WRL::ComPtr buffer; }; std::vector texture_uploads_pending_; struct SubmittedTextureUpload { - ID3D12Resource* texture; - ID3D12Resource* buffer; - uint64_t fence_value; + SubmittedTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer, + UINT64 submission_index) + : texture(texture), + buffer(buffer), + submission_index(submission_index) {} + Microsoft::WRL::ComPtr texture; + Microsoft::WRL::ComPtr buffer; + UINT64 submission_index; }; std::deque texture_uploads_submitted_; - std::vector> textures_deleted_; + std::deque, UINT64>> + textures_deleted_; + + std::unique_ptr vertex_buffer_pool_; + std::unique_ptr texture_descriptor_pool_; + + // The submission index within the current Begin (or the last, if outside + // one). + UINT64 last_paint_submission_index_ = 0; + // Completed submission index as of the latest Begin, to coarsely skip delayed + // texture deletion. + UINT64 last_completed_submission_index_ = 0; - ID3D12GraphicsCommandList* current_command_list_ = nullptr; - int current_render_target_width_, current_render_target_height_; bool batch_open_ = false; bool batch_has_index_buffer_; D3D12_RECT current_scissor_; diff --git a/src/xenia/ui/d3d12/d3d12_presenter.cc b/src/xenia/ui/d3d12/d3d12_presenter.cc new file mode 100644 index 000000000..574b66d0d --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_presenter.cc @@ -0,0 +1,1466 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/d3d12/d3d12_presenter.h" + +#include +#include +#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/d3d12/d3d12_provider.h" +#include "xenia/ui/d3d12/d3d12_util.h" +#include "xenia/ui/surface_win.h" + +DEFINE_bool( + d3d12_allow_variable_refresh_rate_and_tearing, true, + "In fullscreen, allow using variable refresh rate on displays supporting " + "it. On displays not supporting VRR, screen tearing may occur in certain " + "cases.", + "D3D12"); + +namespace xe { +namespace ui { +namespace d3d12 { + +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h" +} // namespace shaders + +D3D12Presenter::~D3D12Presenter() { + // Await completion of the usage of everything before destroying anything. + // From most likely the latest to most likely the earliest to be signaled, so + // just one sleep will likely be needed. + paint_context_.AwaitSwapChainUsageCompletion(); + guest_output_resource_refresher_submission_tracker_.Shutdown(); + ui_submission_tracker_.Shutdown(); +} + +Surface::TypeFlags D3D12Presenter::GetSupportedSurfaceTypes() const { + Surface::TypeFlags types = 0; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) + types |= Surface::kTypeFlag_Win32Hwnd; +#endif + return types; +} + +bool D3D12Presenter::CaptureGuestOutput(RawImage& image_out) { + Microsoft::WRL::ComPtr guest_output_resource; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, nullptr, nullptr)); + if (guest_output_mailbox_index != UINT32_MAX) { + guest_output_resource = + guest_output_resources_[guest_output_mailbox_index].second; + } + // Incremented the reference count of the guest output resource - safe to + // leave the consumer critical section now. + } + if (!guest_output_resource) { + return false; + } + + ID3D12Device* device = provider_.GetDevice(); + + D3D12_RESOURCE_DESC texture_desc = guest_output_resource->GetDesc(); + D3D12_TEXTURE_COPY_LOCATION copy_dest; + UINT64 copy_dest_size; + device->GetCopyableFootprints(&texture_desc, 0, 1, 0, + ©_dest.PlacedFootprint, nullptr, nullptr, + ©_dest_size); + + D3D12_RESOURCE_DESC buffer_desc; + util::FillBufferResourceDesc(buffer_desc, copy_dest_size, + D3D12_RESOURCE_FLAG_NONE); + Microsoft::WRL::ComPtr buffer; + // Create zeroed not to leak data in the row padding. + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesReadback, D3D12_HEAP_FLAG_NONE, &buffer_desc, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&buffer)))) { + XELOGE("D3D12Presenter: Failed to create the guest output capture buffer"); + return false; + } + + { + Microsoft::WRL::ComPtr command_allocator; + if (FAILED( + device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&command_allocator)))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output capturing command " + "allocator"); + return false; + } + Microsoft::WRL::ComPtr command_list; + if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + command_allocator.Get(), nullptr, + IID_PPV_ARGS(&command_list)))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output capturing command " + "list"); + return false; + } + + D3D12_RESOURCE_BARRIER barrier; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = guest_output_resource.Get(); + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = kGuestOutputInternalState; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + if constexpr (kGuestOutputInternalState != + D3D12_RESOURCE_STATE_COPY_SOURCE) { + command_list->ResourceBarrier(1, &barrier); + } + copy_dest.pResource = buffer.Get(); + copy_dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + D3D12_TEXTURE_COPY_LOCATION copy_source; + copy_source.pResource = guest_output_resource.Get(); + copy_source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + copy_source.SubresourceIndex = 0; + command_list->CopyTextureRegion(©_dest, 0, 0, 0, ©_source, nullptr); + if constexpr (kGuestOutputInternalState != + D3D12_RESOURCE_STATE_COPY_SOURCE) { + std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter); + command_list->ResourceBarrier(1, &barrier); + } + if (FAILED(command_list->Close())) { + XELOGE( + "D3D12Presenter: Failed to close the guest output capturing command " + "list"); + return false; + } + + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + + // Make sure that if any work is submitted, any `return` will cause an await + // before releasing the command allocator / list and the resource the RAII + // way in the destruction of the submission tracker - so create after the + // objects referenced in the submission - but don't submit anything if + // failed to initialize the fence. + D3D12SubmissionTracker submission_tracker; + if (!submission_tracker.Initialize(device, direct_queue)) { + return false; + } + ID3D12CommandList* execute_command_list = command_list.Get(); + direct_queue->ExecuteCommandLists(1, &execute_command_list); + if (!submission_tracker.NextSubmission()) { + XELOGE( + "D3D12Presenter: Failed to signal the guest output capturing fence"); + return false; + } + if (!submission_tracker.AwaitAllSubmissionsCompletion()) { + XELOGE( + "D3D12Presenter: Failed to await the guest output capturing fence"); + return false; + } + } + + D3D12_RANGE read_range; + read_range.Begin = copy_dest.PlacedFootprint.Offset; + read_range.End = copy_dest_size; + void* mapping; + if (FAILED(buffer->Map(0, &read_range, &mapping))) { + XELOGE("D3D12Presenter: Failed to map the guest output capture buffer"); + return false; + } + image_out.width = uint32_t(texture_desc.Width); + image_out.height = uint32_t(texture_desc.Height); + image_out.stride = sizeof(uint32_t) * image_out.width; + image_out.data.resize(image_out.stride * image_out.height); + uint32_t* image_out_pixels = + reinterpret_cast(image_out.data.data()); + for (uint32_t y = 0; y < image_out.height; ++y) { + uint32_t* dest_row = &image_out_pixels[size_t(image_out.width) * y]; + const uint32_t* source_row = reinterpret_cast( + reinterpret_cast(mapping) + + copy_dest.PlacedFootprint.Offset + + size_t(copy_dest.PlacedFootprint.Footprint.RowPitch) * y); + for (uint32_t x = 0; x < image_out.width; ++x) { + dest_row[x] = Packed10bpcRGBTo8bpcBytes(source_row[x]); + } + } + // Unmapping will be done implicitly when the resource goes out of scope and + // gets destroyed. + return true; +} + +Presenter::SurfacePaintConnectResult +D3D12Presenter::ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) { + uint32_t new_swap_chain_width = std::min( + new_surface_width, uint32_t(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION)); + uint32_t new_swap_chain_height = std::min( + new_surface_height, uint32_t(D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION)); + + // ConnectOrReconnectPaintingToSurfaceFromUIThread may be called only for the + // surface of the current swap chain or when the old swap chain has already + // been destroyed, if the surface is the same, try resizing. + if (paint_context_.swap_chain) { + if (was_paintable && + paint_context_.swap_chain_width == new_swap_chain_width && + paint_context_.swap_chain_height == new_swap_chain_height) { + is_vsync_implicit_out = false; + return SurfacePaintConnectResult::kSuccessUnchanged; + } + paint_context_.AwaitSwapChainUsageCompletion(); + // Using the current swap_chain_allows_tearing_ value that's consistent with + // the creation of the swap chain because ResizeBuffers can't toggle the + // tearing flag. + for (Microsoft::WRL::ComPtr& swap_chain_buffer_ref : + paint_context_.swap_chain_buffers) { + swap_chain_buffer_ref.Reset(); + } + bool swap_chain_resized = + SUCCEEDED(paint_context_.swap_chain->ResizeBuffers( + 0, UINT(new_swap_chain_width), UINT(new_swap_chain_height), + DXGI_FORMAT_UNKNOWN, + paint_context_.swap_chain_allows_tearing + ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING + : 0)); + if (swap_chain_resized) { + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + if (FAILED(paint_context_.swap_chain->GetBuffer( + i, IID_PPV_ARGS(&paint_context_.swap_chain_buffers[i])))) { + swap_chain_resized = false; + break; + } + } + if (swap_chain_resized) { + paint_context_.swap_chain_width = new_swap_chain_width; + paint_context_.swap_chain_height = new_swap_chain_height; + } + } + if (!swap_chain_resized) { + XELOGE("D3D12Presenter: Failed to resize a swap chain"); + // Failed to resize, retry creating from scratch. + paint_context_.DestroySwapChain(); + } + } + + if (!paint_context_.swap_chain) { + // Create a new swap chain. + Surface::TypeIndex surface_type = new_surface.GetType(); + DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; + swap_chain_desc.Width = UINT(new_swap_chain_width); + swap_chain_desc.Height = UINT(new_swap_chain_height); + swap_chain_desc.Format = kSwapChainFormat; + swap_chain_desc.Stereo = FALSE; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.SampleDesc.Quality = 0; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.BufferCount = UINT(PaintContext::kSwapChainBufferCount); + // DXGI_SCALING_STRETCH may cause the content to "shake" while resizing, + // with relayout done for the guest output twice visually rather than once, + // and the UI becoming stretched and then jumping to normal. If it's + // possible to cover the entire surface without stretching, don't stretch. + // After resizing, the presenter repaints as soon as possible anyway, so + swap_chain_desc.Scaling = (new_swap_chain_width == new_surface_width && + new_swap_chain_height == new_surface_height) + ? DXGI_SCALING_NONE + : DXGI_SCALING_STRETCH; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swap_chain_desc.Flags = 0; + if (cvars::d3d12_allow_variable_refresh_rate_and_tearing && + dxgi_supports_tearing_) { + // Allow tearing in borderless fullscreen to support variable refresh + // rate. + swap_chain_desc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } + IDXGIFactory2* dxgi_factory = provider_.GetDXGIFactory(); + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + Microsoft::WRL::ComPtr swap_chain_1; + switch (surface_type) { +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) + case Surface::kTypeIndex_Win32Hwnd: { + HWND surface_hwnd = + static_cast(new_surface).hwnd(); + if (FAILED(dxgi_factory->CreateSwapChainForHwnd( + direct_queue, surface_hwnd, &swap_chain_desc, nullptr, nullptr, + &swap_chain_1))) { + XELOGE("D3D12Presenter: Failed to create a swap chain for the HWND"); + return SurfacePaintConnectResult::kFailure; + } + // Disable automatic Alt+Enter handling - DXGI fullscreen doesn't + // support ALLOW_TEARING, and using custom fullscreen in ui::Win32Window + // anyway as with Alt+Enter the menu is kept, state changes are tracked + // better, and nothing is presented for some reason. + dxgi_factory->MakeWindowAssociation(surface_hwnd, + DXGI_MWA_NO_ALT_ENTER); + } break; +#endif + default: + assert_unhandled_case(surface_type); + XELOGE( + "D3D12Presenter: Tried to create a swap chain for an unsupported " + "Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + if (FAILED(swap_chain_1->QueryInterface( + IID_PPV_ARGS(&paint_context_.swap_chain)))) { + XELOGE( + "D3D12Presenter: Failed to get version 3 of the swap chain " + "interface"); + return SurfacePaintConnectResult::kFailure; + } + // From now on, in case of any failure, DestroySwapChain must be called + // before returning. + paint_context_.swap_chain_width = new_swap_chain_width; + paint_context_.swap_chain_height = new_swap_chain_height; + paint_context_.swap_chain_allows_tearing = + (swap_chain_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) != 0; + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + if (FAILED(paint_context_.swap_chain->GetBuffer( + i, IID_PPV_ARGS(&paint_context_.swap_chain_buffers[i])))) { + XELOGE( + "D3D12Presenter: Failed to get buffer {} of a {}-buffer swap chain", + i, PaintContext::kSwapChainBufferCount); + paint_context_.DestroySwapChain(); + return SurfacePaintConnectResult::kFailure; + } + } + } + + ID3D12Device* device = provider_.GetDevice(); + + // Create the RTV descriptors. + D3D12_CPU_DESCRIPTOR_HANDLE rtv_heap_start = + paint_context_.rtv_heap->GetCPUDescriptorHandleForHeapStart(); + D3D12_RENDER_TARGET_VIEW_DESC rtv_desc; + rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + rtv_desc.Texture2D.MipSlice = 0; + rtv_desc.Texture2D.PlaneSlice = 0; + for (uint32_t i = 0; i < PaintContext::kSwapChainBufferCount; ++i) { + ID3D12Resource* swap_chain_buffer = + paint_context_.swap_chain_buffers[i].Get(); + rtv_desc.Format = kSwapChainFormat; + device->CreateRenderTargetView( + swap_chain_buffer, &rtv_desc, + provider_.OffsetRTVDescriptor( + rtv_heap_start, PaintContext::kRTVIndexSwapChainBuffer0 + i)); + } + + is_vsync_implicit_out = false; + return SurfacePaintConnectResult::kSuccess; +} + +void D3D12Presenter::DisconnectPaintingFromSurfaceFromUIThreadImpl() { + paint_context_.DestroySwapChain(); +} + +bool D3D12Presenter::RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) { + assert_not_zero(frontbuffer_width); + assert_not_zero(frontbuffer_height); + std::pair>& + guest_output_resource_ref = guest_output_resources_[mailbox_index]; + if (guest_output_resource_ref.second) { + D3D12_RESOURCE_DESC guest_output_resource_current_desc = + guest_output_resource_ref.second->GetDesc(); + if (guest_output_resource_current_desc.Width != frontbuffer_width || + guest_output_resource_current_desc.Height != frontbuffer_height) { + // Main target painting has its own reference to the textures for reading + // in its own submission tracker timeline, safe to release here. + guest_output_resource_refresher_submission_tracker_ + .AwaitSubmissionCompletion(guest_output_resource_ref.first); + guest_output_resource_ref.second.Reset(); + } + } + if (!guest_output_resource_ref.second) { + ID3D12Device* device = provider_.GetDevice(); + D3D12_RESOURCE_DESC guest_output_resource_new_desc; + guest_output_resource_new_desc.Dimension = + D3D12_RESOURCE_DIMENSION_TEXTURE2D; + guest_output_resource_new_desc.Alignment = 0; + guest_output_resource_new_desc.Width = frontbuffer_width; + guest_output_resource_new_desc.Height = frontbuffer_height; + guest_output_resource_new_desc.DepthOrArraySize = 1; + guest_output_resource_new_desc.MipLevels = 1; + guest_output_resource_new_desc.Format = kGuestOutputFormat; + guest_output_resource_new_desc.SampleDesc.Count = 1; + guest_output_resource_new_desc.SampleDesc.Quality = 0; + guest_output_resource_new_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + guest_output_resource_new_desc.Flags = + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesDefault, + provider_.GetHeapFlagCreateNotZeroed(), + &guest_output_resource_new_desc, kGuestOutputInternalState, nullptr, + IID_PPV_ARGS(&guest_output_resource_ref.second)))) { + XELOGE("D3D12Presenter: Failed to create the guest output {}x{} texture", + frontbuffer_width, frontbuffer_height); + return false; + } + } + D3D12GuestOutputRefreshContext context( + is_8bpc_out_ref, guest_output_resource_ref.second.Get()); + bool refresher_succeeded = refresher(context); + // Even if the refresher has returned false, it still might have submitted + // some commands referencing the resource. It's better to put an excessive + // signal and wait slightly longer, for nothing important, while shutting down + // than to destroy the resource while it's still in use. + guest_output_resource_ref.first = + guest_output_resource_refresher_submission_tracker_ + .GetCurrentSubmission(); + guest_output_resource_refresher_submission_tracker_.NextSubmission(); + return refresher_succeeded; +} + +void D3D12Presenter::PaintContext::DestroySwapChain() { + if (!swap_chain) { + return; + } + AwaitSwapChainUsageCompletion(); + for (Microsoft::WRL::ComPtr& swap_chain_buffer_ref : + swap_chain_buffers) { + swap_chain_buffer_ref.Reset(); + } + swap_chain.Reset(); + swap_chain_allows_tearing = false; + swap_chain_height = 0; + swap_chain_width = 0; +} + +Presenter::PaintResult D3D12Presenter::PaintAndPresentImpl( + bool execute_ui_drawers) { + // Begin the command list with the command allocator not currently potentially + // used on the GPU. + UINT64 current_paint_submission = + paint_context_.paint_submission_tracker.GetCurrentSubmission(); + UINT64 command_allocator_count = + UINT64(paint_context_.command_allocators.size()); + if (current_paint_submission >= command_allocator_count) { + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + current_paint_submission - command_allocator_count); + } + ID3D12CommandAllocator* command_allocator = + paint_context_ + .command_allocators[current_paint_submission % + command_allocator_count] + .Get(); + command_allocator->Reset(); + ID3D12GraphicsCommandList* command_list = paint_context_.command_list.Get(); + command_list->Reset(command_allocator, nullptr); + + ID3D12Device* device = provider_.GetDevice(); + + // Obtain the RTV heap and the back buffer. + D3D12_CPU_DESCRIPTOR_HANDLE rtv_heap_start = + paint_context_.rtv_heap->GetCPUDescriptorHandleForHeapStart(); + UINT back_buffer_index = + paint_context_.swap_chain->GetCurrentBackBufferIndex(); + D3D12_CPU_DESCRIPTOR_HANDLE back_buffer_rtv = provider_.OffsetRTVDescriptor( + rtv_heap_start, + PaintContext::kRTVIndexSwapChainBuffer0 + back_buffer_index); + ID3D12Resource* back_buffer = + paint_context_.swap_chain_buffers[back_buffer_index].Get(); + bool back_buffer_acquired = false; + bool back_buffer_bound = false; + bool back_buffer_clear_needed = true; + const float kBackBufferClearColor[] = {0.0f, 0.0f, 0.0f, 1.0f}; + + // Draw the guest output. + + GuestOutputProperties guest_output_properties; + GuestOutputPaintConfig guest_output_paint_config; + Microsoft::WRL::ComPtr guest_output_resource; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, &guest_output_properties, + &guest_output_paint_config)); + if (guest_output_mailbox_index != UINT32_MAX) { + guest_output_resource = + guest_output_resources_[guest_output_mailbox_index].second; + } + // Incremented the reference count of the guest output resource - safe to + // leave the consumer critical section now as everything here either will be + // using the new reference or is exclusively owned by main target painting + // (and multiple threads can't paint the main target at the same time). + } + + if (guest_output_resource) { + GuestOutputPaintFlow guest_output_flow = GetGuestOutputPaintFlow( + guest_output_properties, paint_context_.swap_chain_width, + paint_context_.swap_chain_height, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, + D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, guest_output_paint_config); + + // Check if all guest output paint effects are supported by the + // implementation. + if (guest_output_flow.effect_count) { + if (!guest_output_paint_final_pipelines_[size_t( + guest_output_flow.effects[guest_output_flow.effect_count - 1])]) { + guest_output_flow.effect_count = 0; + } + for (size_t i = 0; i + 1 < guest_output_flow.effect_count; ++i) { + if (!guest_output_paint_intermediate_pipelines_[size_t( + guest_output_flow.effects[i])]) { + guest_output_flow.effect_count = 0; + break; + } + } + } + + if (guest_output_flow.effect_count) { + ID3D12DescriptorHeap* view_heap = paint_context_.view_heap.Get(); + D3D12_CPU_DESCRIPTOR_HANDLE view_heap_cpu_start = + view_heap->GetCPUDescriptorHandleForHeapStart(); + + // Store the main target reference to the guest output texture so it's not + // destroyed while it's still potentially in use by main target painting + // queued on the GPU. + size_t guest_output_resource_paint_ref_index = SIZE_MAX; + size_t guest_output_resource_paint_ref_new_index = SIZE_MAX; + // Try to find the existing reference to the same texture, or an already + // released (or a taken, but never actually used) slot. + for (size_t i = 0; + i < paint_context_.guest_output_resource_paint_refs.size(); ++i) { + const std::pair>& + guest_output_resource_paint_ref = + paint_context_.guest_output_resource_paint_refs[i]; + if (guest_output_resource_paint_ref.second == guest_output_resource) { + guest_output_resource_paint_ref_index = i; + break; + } + if (guest_output_resource_paint_ref_new_index == SIZE_MAX && + (!guest_output_resource_paint_ref.second || + !guest_output_resource_paint_ref.first)) { + guest_output_resource_paint_ref_new_index = i; + } + } + if (guest_output_resource_paint_ref_index == SIZE_MAX) { + // New texture - store the reference and create the descriptors. + if (guest_output_resource_paint_ref_new_index == SIZE_MAX) { + // Replace the earliest used reference. + guest_output_resource_paint_ref_new_index = 0; + for (size_t i = 1; + i < paint_context_.guest_output_resource_paint_refs.size(); + ++i) { + if (paint_context_.guest_output_resource_paint_refs[i].first < + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_new_index] + .first) { + guest_output_resource_paint_ref_new_index = i; + } + } + // Await the completion of the usage of the old guest output + // resource and its SRV descriptors. + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_new_index] + .first); + } + guest_output_resource_paint_ref_index = + guest_output_resource_paint_ref_new_index; + // The actual submission index will be set if the texture is actually + // used, not dropped due to some error. + paint_context_.guest_output_resource_paint_refs + [guest_output_resource_paint_ref_index] = + std::make_pair(UINT64(0), guest_output_resource); + // Create the SRV descriptor of the new texture. + D3D12_SHADER_RESOURCE_VIEW_DESC guest_output_resource_srv_desc; + guest_output_resource_srv_desc.Format = kGuestOutputFormat; + guest_output_resource_srv_desc.ViewDimension = + D3D12_SRV_DIMENSION_TEXTURE2D; + guest_output_resource_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + guest_output_resource_srv_desc.Texture2D.MostDetailedMip = 0; + guest_output_resource_srv_desc.Texture2D.MipLevels = 1; + guest_output_resource_srv_desc.Texture2D.PlaneSlice = 0; + guest_output_resource_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView( + guest_output_resource.Get(), &guest_output_resource_srv_desc, + provider_.OffsetViewDescriptor( + view_heap_cpu_start, + PaintContext::kViewIndexGuestOutput0Srv + + uint32_t(guest_output_resource_paint_ref_index))); + } + + // Make sure intermediate textures of the needed size are available, and + // unneeded intermediate textures are destroyed. + for (size_t i = 0; i < kMaxGuestOutputPaintEffects - 1; ++i) { + std::pair intermediate_needed_size(0, 0); + if (i + 1 < guest_output_flow.effect_count) { + intermediate_needed_size = guest_output_flow.effect_output_sizes[i]; + } + Microsoft::WRL::ComPtr& intermediate_texture_ptr_ref = + paint_context_.guest_output_intermediate_textures[i]; + std::pair intermediate_current_size(0, 0); + if (intermediate_texture_ptr_ref) { + D3D12_RESOURCE_DESC intermediate_current_desc = + intermediate_texture_ptr_ref->GetDesc(); + intermediate_current_size.first = + uint32_t(intermediate_current_desc.Width); + intermediate_current_size.second = intermediate_current_desc.Height; + } + if (intermediate_current_size != intermediate_needed_size) { + if (intermediate_needed_size.first && + intermediate_needed_size.second) { + // Need to replace immediately as a new texture with the requested + // size is needed. + if (intermediate_texture_ptr_ref) { + paint_context_.paint_submission_tracker.AwaitSubmissionCompletion( + paint_context_.guest_output_intermediate_texture_last_usage); + intermediate_texture_ptr_ref.Reset(); + } + // Resource. + D3D12_RESOURCE_DESC intermediate_desc; + intermediate_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + intermediate_desc.Alignment = 0; + intermediate_desc.Width = intermediate_needed_size.first; + intermediate_desc.Height = intermediate_needed_size.second; + intermediate_desc.DepthOrArraySize = 1; + intermediate_desc.MipLevels = 1; + intermediate_desc.Format = kGuestOutputIntermediateFormat; + intermediate_desc.SampleDesc.Count = 1; + intermediate_desc.SampleDesc.Quality = 0; + intermediate_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + intermediate_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + if (FAILED(device->CreateCommittedResource( + &util::kHeapPropertiesDefault, + provider_.GetHeapFlagCreateNotZeroed(), &intermediate_desc, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, + IID_PPV_ARGS(&intermediate_texture_ptr_ref)))) { + XELOGE( + "D3D12Presenter: Failed to create a guest output " + "presentation intermediate texture"); + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + ID3D12Resource* intermediate_texture = + intermediate_texture_ptr_ref.Get(); + // SRV. + D3D12_SHADER_RESOURCE_VIEW_DESC intermediate_srv_desc; + intermediate_srv_desc.Format = kGuestOutputIntermediateFormat; + intermediate_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + intermediate_srv_desc.Shader4ComponentMapping = + D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + intermediate_srv_desc.Texture2D.MostDetailedMip = 0; + intermediate_srv_desc.Texture2D.MipLevels = 1; + intermediate_srv_desc.Texture2D.PlaneSlice = 0; + intermediate_srv_desc.Texture2D.ResourceMinLODClamp = 0.0f; + device->CreateShaderResourceView( + intermediate_texture, &intermediate_srv_desc, + provider_.OffsetViewDescriptor( + view_heap_cpu_start, + uint32_t( + PaintContext::kViewIndexGuestOutputIntermediate0Srv + + i))); + // RTV. + D3D12_RENDER_TARGET_VIEW_DESC intermediate_rtv_desc; + intermediate_rtv_desc.Format = kGuestOutputIntermediateFormat; + intermediate_rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + intermediate_rtv_desc.Texture2D.MipSlice = 0; + intermediate_rtv_desc.Texture2D.PlaneSlice = 0; + device->CreateRenderTargetView( + intermediate_texture, &intermediate_rtv_desc, + provider_.OffsetRTVDescriptor( + rtv_heap_start, + uint32_t(PaintContext::kRTVIndexGuestOutputIntermediate0 + + i))); + } else { + // Was previously needed, but not anymore - destroy when possible. + if (intermediate_texture_ptr_ref && + paint_context_.paint_submission_tracker + .GetCompletedSubmission() >= + paint_context_ + .guest_output_intermediate_texture_last_usage) { + intermediate_texture_ptr_ref.Reset(); + } + } + } + } + + if (guest_output_flow.effect_count) { + paint_context_ + .guest_output_resource_paint_refs + [guest_output_resource_paint_ref_index] + .first = current_paint_submission; + if (guest_output_flow.effect_count > 1) { + paint_context_.guest_output_intermediate_texture_last_usage = + current_paint_submission; + } + + command_list->SetDescriptorHeaps(1, &view_heap); + } + + // This effect loop must not be aborted so the states of the resources + // involved are consistent. + D3D12_GPU_DESCRIPTOR_HANDLE view_heap_gpu_start = + view_heap->GetGPUDescriptorHandleForHeapStart(); + for (size_t i = 0; i < guest_output_flow.effect_count; ++i) { + bool is_final_effect = i + 1 >= guest_output_flow.effect_count; + + GuestOutputPaintEffect effect = guest_output_flow.effects[i]; + + ID3D12Resource* effect_dest_resource; + int32_t effect_rect_x, effect_rect_y; + if (is_final_effect) { + effect_dest_resource = back_buffer; + if (!back_buffer_acquired) { + D3D12_RESOURCE_BARRIER barrier_present_to_rtv; + barrier_present_to_rtv.Type = + D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_present_to_rtv); + back_buffer_acquired = true; + } + effect_rect_x = guest_output_flow.output_x; + effect_rect_y = guest_output_flow.output_y; + } else { + effect_dest_resource = + paint_context_.guest_output_intermediate_textures[i].Get(); + if (!i) { + // If this is not the first effect, the transition has been done at + // the end of the previous effect in a single command. + D3D12_RESOURCE_BARRIER barrier_srv_to_rtv; + barrier_srv_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_srv_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_srv_to_rtv.Transition.pResource = effect_dest_resource; + barrier_srv_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_srv_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrier_srv_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_srv_to_rtv); + } + command_list->DiscardResource(effect_dest_resource, nullptr); + effect_rect_x = 0; + effect_rect_y = 0; + } + + if (is_final_effect) { + if (!back_buffer_bound) { + command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, + nullptr); + back_buffer_bound = true; + } + } else { + D3D12_CPU_DESCRIPTOR_HANDLE intermediate_rtv = + provider_.OffsetRTVDescriptor( + rtv_heap_start, + uint32_t(PaintContext::kRTVIndexGuestOutputIntermediate0 + + i)); + command_list->OMSetRenderTargets(1, &intermediate_rtv, TRUE, nullptr); + back_buffer_bound = false; + } + if (is_final_effect) { + back_buffer_bound = true; + } + D3D12_RESOURCE_DESC effect_dest_resource_desc = + effect_dest_resource->GetDesc(); + D3D12_VIEWPORT viewport; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + viewport.Width = float(effect_dest_resource_desc.Width); + viewport.Height = float(effect_dest_resource_desc.Height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + command_list->RSSetViewports(1, &viewport); + D3D12_RECT scissor; + scissor.left = 0; + scissor.top = 0; + scissor.right = LONG(effect_dest_resource_desc.Width); + scissor.bottom = LONG(effect_dest_resource_desc.Height); + command_list->RSSetScissorRects(1, &scissor); + + command_list->SetPipelineState( + is_final_effect + ? guest_output_paint_final_pipelines_[size_t(effect)].Get() + : guest_output_paint_intermediate_pipelines_[size_t(effect)] + .Get()); + GuestOutputPaintRootSignatureIndex + guest_output_paint_root_signature_index = + GetGuestOutputPaintRootSignatureIndex(effect); + command_list->SetGraphicsRootSignature( + guest_output_paint_root_signatures_ + [size_t(guest_output_paint_root_signature_index)] + .Get()); + + UINT effect_src_view_index = UINT( + i ? (PaintContext::kViewIndexGuestOutputIntermediate0Srv + (i - 1)) + : (PaintContext::kViewIndexGuestOutput0Srv + + guest_output_resource_paint_ref_index)); + command_list->SetGraphicsRootDescriptorTable( + UINT(GuestOutputPaintRootParameter::kSource), + provider_.OffsetViewDescriptor(view_heap_gpu_start, + effect_src_view_index)); + + GuestOutputPaintRectangleConstants effect_rect_constants; + float effect_x_to_ndc = 2.0f / viewport.Width; + float effect_y_to_ndc = 2.0f / viewport.Height; + effect_rect_constants.x = + -1.0f + float(effect_rect_x) * effect_x_to_ndc; + // +Y is -V. + effect_rect_constants.y = 1.0f - float(effect_rect_y) * effect_y_to_ndc; + effect_rect_constants.width = + float(guest_output_flow.effect_output_sizes[i].first) * + effect_x_to_ndc; + effect_rect_constants.height = + -float(guest_output_flow.effect_output_sizes[i].second) * + effect_y_to_ndc; + command_list->SetGraphicsRoot32BitConstants( + UINT(GuestOutputPaintRootParameter::kRectangle), + sizeof(effect_rect_constants) / sizeof(uint32_t), + &effect_rect_constants, 0); + + UINT effect_constants_size = 0; + union { + BilinearConstants bilinear; + CasSharpenConstants cas_sharpen; + CasResampleConstants cas_resample; + FsrEasuConstants fsr_easu; + FsrRcasConstants fsr_rcas; + } effect_constants; + switch (guest_output_paint_root_signature_index) { + case kGuestOutputPaintRootSignatureIndexBilinear: { + effect_constants_size = sizeof(effect_constants.bilinear); + effect_constants.bilinear.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintRootSignatureIndexCasSharpen: { + effect_constants_size = sizeof(effect_constants.cas_sharpen); + effect_constants.cas_sharpen.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + case kGuestOutputPaintRootSignatureIndexCasResample: { + effect_constants_size = sizeof(effect_constants.cas_resample); + effect_constants.cas_resample.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + case kGuestOutputPaintRootSignatureIndexFsrEasu: { + effect_constants_size = sizeof(effect_constants.fsr_easu); + effect_constants.fsr_easu.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintRootSignatureIndexFsrRcas: { + effect_constants_size = sizeof(effect_constants.fsr_rcas); + effect_constants.fsr_rcas.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + default: + break; + } + if (effect_constants_size) { + command_list->SetGraphicsRoot32BitConstants( + UINT(GuestOutputPaintRootParameter::kEffectConstants), + effect_constants_size / sizeof(uint32_t), &effect_constants, 0); + } + + command_list->IASetPrimitiveTopology( + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + command_list->DrawInstanced(4, 1, 0, 0); + + if (is_final_effect) { + // Clear the letterbox around the guest output if the guest output + // doesn't cover the entire back buffer. + if (guest_output_flow.letterbox_clear_rectangle_count) { + D3D12_RECT letterbox_clear_d3d12_rectangles + [GuestOutputPaintFlow::kMaxClearRectangles]; + for (size_t i = 0; + i < guest_output_flow.letterbox_clear_rectangle_count; ++i) { + D3D12_RECT& letterbox_clear_d3d12_rectangle = + letterbox_clear_d3d12_rectangles[i]; + const GuestOutputPaintFlow::ClearRectangle& + letterbox_clear_rectangle = + guest_output_flow.letterbox_clear_rectangles[i]; + letterbox_clear_d3d12_rectangle.left = + LONG(letterbox_clear_rectangle.x); + letterbox_clear_d3d12_rectangle.top = + LONG(letterbox_clear_rectangle.y); + letterbox_clear_d3d12_rectangle.right = + LONG(letterbox_clear_rectangle.x + + letterbox_clear_rectangle.width); + letterbox_clear_d3d12_rectangle.bottom = + LONG(letterbox_clear_rectangle.y + + letterbox_clear_rectangle.height); + } + command_list->ClearRenderTargetView( + back_buffer_rtv, kBackBufferClearColor, + UINT(guest_output_flow.letterbox_clear_rectangle_count), + letterbox_clear_d3d12_rectangles); + } + back_buffer_clear_needed = false; + } else { + D3D12_RESOURCE_BARRIER barriers[2]; + UINT barrier_count = 0; + // Transition the newly written intermediate image to SRV for use as + // the source in the next effect. + { + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_rtv_to_srv = + barriers[barrier_count++]; + barrier_rtv_to_srv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_rtv_to_srv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_rtv_to_srv.Transition.pResource = effect_dest_resource; + barrier_rtv_to_srv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_rtv_to_srv.Transition.StateBefore = + D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier_rtv_to_srv.Transition.StateAfter = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + } + // Merge the current destination > next source transition with the + // acquisition of the destination for the next effect. + if (i + 2 < guest_output_flow.effect_count) { + // The next effect won't be the last - transition the next + // intermediate destination to RTV. + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_srv_to_rtv = + barriers[barrier_count++]; + barrier_srv_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_srv_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_srv_to_rtv.Transition.pResource = + paint_context_.guest_output_intermediate_textures[i + 1].Get(); + barrier_srv_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_srv_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrier_srv_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + } else { + // The next effect draws to the back buffer - merge into one + // ResourceBarrier command. + if (!back_buffer_acquired) { + assert_true(barrier_count < xe::countof(barriers)); + D3D12_RESOURCE_BARRIER& barrier_present_to_rtv = + barriers[barrier_count++]; + barrier_present_to_rtv.Type = + D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + back_buffer_acquired = true; + } + } + if (barrier_count) { + command_list->ResourceBarrier(barrier_count, barriers); + } + } + } + } + } + + // Release main target guest output texture references that aren't needed + // anymore (this is done after various potential guest-output-related main + // target submission tracker waits so the completed submission value is the + // most actual). + UINT64 completed_paint_submission = + paint_context_.paint_submission_tracker.GetCompletedSubmission(); + for (std::pair>& + guest_output_resource_paint_ref : + paint_context_.guest_output_resource_paint_refs) { + if (!guest_output_resource_paint_ref.second || + guest_output_resource_paint_ref.second == guest_output_resource) { + continue; + } + if (completed_paint_submission >= guest_output_resource_paint_ref.first) { + guest_output_resource_paint_ref.second.Reset(); + } + } + + // If no guest output has been drawn, the transitioned of the back buffer to + // RTV hasn't been done yet, and it's needed to clear it, and optionally to + // draw the UI. + if (!back_buffer_acquired) { + D3D12_RESOURCE_BARRIER barrier_present_to_rtv; + barrier_present_to_rtv.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_present_to_rtv.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_present_to_rtv.Transition.pResource = back_buffer; + barrier_present_to_rtv.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_present_to_rtv.Transition.StateBefore = + D3D12_RESOURCE_STATE_PRESENT; + barrier_present_to_rtv.Transition.StateAfter = + D3D12_RESOURCE_STATE_RENDER_TARGET; + command_list->ResourceBarrier(1, &barrier_present_to_rtv); + back_buffer_acquired = true; + } + + if (back_buffer_clear_needed) { + command_list->ClearRenderTargetView(back_buffer_rtv, kBackBufferClearColor, + 0, nullptr); + back_buffer_clear_needed = false; + } + + if (execute_ui_drawers) { + // Draw the UI. + if (!back_buffer_bound) { + command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); + back_buffer_bound = true; + } + D3D12UIDrawContext ui_draw_context( + *this, paint_context_.swap_chain_width, + paint_context_.swap_chain_height, command_list, + ui_submission_tracker_.GetCurrentSubmission(), + ui_submission_tracker_.GetCompletedSubmission()); + ExecuteUIDrawersFromUIThread(ui_draw_context); + } + + // End drawing to the back buffer. + D3D12_RESOURCE_BARRIER barrier_rtv_to_present; + barrier_rtv_to_present.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier_rtv_to_present.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier_rtv_to_present.Transition.pResource = back_buffer; + barrier_rtv_to_present.Transition.Subresource = + D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier_rtv_to_present.Transition.StateBefore = + D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier_rtv_to_present.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + command_list->ResourceBarrier(1, &barrier_rtv_to_present); + + // Execute and present. + command_list->Close(); + ID3D12CommandList* execute_command_list = command_list; + provider_.GetDirectQueue()->ExecuteCommandLists(1, &execute_command_list); + if (execute_ui_drawers) { + ui_submission_tracker_.NextSubmission(); + } + paint_context_.paint_submission_tracker.NextSubmission(); + // Present as soon as possible, without waiting for vsync (the host refresh + // rate may be something like 144 Hz, which is not a multiple of the common + // 30 Hz or 60 Hz guest refresh rate), and allowing dropping outdated queued + // frames for lower latency. Also, if possible, allowing tearing to use + // variable refresh rate in borderless fullscreen (note that if DXGI + // fullscreen is ever used in, the allow tearing flag must not be passed in + // fullscreen, but DXGI fullscreen is largely unneeded with the flip + // presentation model used in Direct3D 12). + HRESULT present_result = paint_context_.swap_chain->Present( + 0, DXGI_PRESENT_RESTART | (paint_context_.swap_chain_allows_tearing + ? DXGI_PRESENT_ALLOW_TEARING + : 0)); + // Even if presentation has failed, work might have been enqueued anyway + // internally before the failure according to Jesse Natalie from the DirectX + // Discord server. + paint_context_.present_submission_tracker.NextSubmission(); + switch (present_result) { + case DXGI_ERROR_DEVICE_REMOVED: + return PaintResult::kGpuLostExternally; + case DXGI_ERROR_DEVICE_RESET: + return PaintResult::kGpuLostResponsible; + default: + return SUCCEEDED(present_result) ? PaintResult::kPresented + : PaintResult::kNotPresented; + } +} + +bool D3D12Presenter::InitializeSurfaceIndependent() { + // Check if DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING is supported. + { + Microsoft::WRL::ComPtr dxgi_factory_5; + if (SUCCEEDED(provider_.GetDXGIFactory()->QueryInterface( + IID_PPV_ARGS(&dxgi_factory_5)))) { + BOOL tearing_feature_data; + dxgi_supports_tearing_ = + SUCCEEDED(dxgi_factory_5->CheckFeatureSupport( + DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearing_feature_data, + sizeof(tearing_feature_data))) && + tearing_feature_data; + } + } + + ID3D12Device* device = provider_.GetDevice(); + + // Initialize static guest output painting objects. + + // Guest output painting root signatures. + // One (texture) for bilinear, two (texture and constants) for AMD FidelityFX + // CAS and FSR. + D3D12_ROOT_PARAMETER guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kCount)]; + // Source texture. + D3D12_DESCRIPTOR_RANGE guest_output_paint_root_descriptor_range_source; + guest_output_paint_root_descriptor_range_source.RangeType = + D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + guest_output_paint_root_descriptor_range_source.NumDescriptors = 1; + guest_output_paint_root_descriptor_range_source.BaseShaderRegister = 0; + guest_output_paint_root_descriptor_range_source.RegisterSpace = 0; + guest_output_paint_root_descriptor_range_source + .OffsetInDescriptorsFromTableStart = 0; + { + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_source = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kSource)]; + guest_output_paint_root_parameter_source.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + guest_output_paint_root_parameter_source.DescriptorTable + .NumDescriptorRanges = 1; + guest_output_paint_root_parameter_source.DescriptorTable.pDescriptorRanges = + &guest_output_paint_root_descriptor_range_source; + guest_output_paint_root_parameter_source.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + } + // Rectangle. + { + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_rect = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kRectangle)]; + guest_output_paint_root_parameter_rect.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + guest_output_paint_root_parameter_rect.Constants.ShaderRegister = 0; + guest_output_paint_root_parameter_rect.Constants.RegisterSpace = 0; + guest_output_paint_root_parameter_rect.Constants.Num32BitValues = + sizeof(GuestOutputPaintRectangleConstants) / sizeof(uint32_t); + guest_output_paint_root_parameter_rect.ShaderVisibility = + D3D12_SHADER_VISIBILITY_VERTEX; + } + // Pixel shader constants. + D3D12_ROOT_PARAMETER& guest_output_paint_root_parameter_effect_constants = + guest_output_paint_root_parameters[UINT( + GuestOutputPaintRootParameter::kEffectConstants)]; + guest_output_paint_root_parameter_effect_constants.ParameterType = + D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + guest_output_paint_root_parameter_effect_constants.Constants.ShaderRegister = + 0; + guest_output_paint_root_parameter_effect_constants.Constants.RegisterSpace = + 0; + guest_output_paint_root_parameter_effect_constants.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + // Bilinear sampler. + D3D12_STATIC_SAMPLER_DESC guest_output_paint_root_sampler; + guest_output_paint_root_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + guest_output_paint_root_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + guest_output_paint_root_sampler.MipLODBias = 0.0f; + guest_output_paint_root_sampler.MaxAnisotropy = 1; + guest_output_paint_root_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + guest_output_paint_root_sampler.BorderColor = + D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + guest_output_paint_root_sampler.MinLOD = 0.0f; + guest_output_paint_root_sampler.MaxLOD = 0.0f; + guest_output_paint_root_sampler.ShaderRegister = 0; + guest_output_paint_root_sampler.RegisterSpace = 0; + guest_output_paint_root_sampler.ShaderVisibility = + D3D12_SHADER_VISIBILITY_PIXEL; + D3D12_ROOT_SIGNATURE_DESC guest_output_paint_root_signature_desc; + guest_output_paint_root_signature_desc.NumParameters = + UINT(GuestOutputPaintRootParameter::kCount); + guest_output_paint_root_signature_desc.pParameters = + guest_output_paint_root_parameters; + guest_output_paint_root_signature_desc.NumStaticSamplers = 1; + guest_output_paint_root_signature_desc.pStaticSamplers = + &guest_output_paint_root_sampler; + guest_output_paint_root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + // Bilinear filtering (needs the sampler). + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(BilinearConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output bilinear " + "filtering presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexBilinear] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // EASU (needs the sampler). + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(FsrEasuConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "FSR EASU presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexFsrEasu] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // RCAS and CAS don't need the sampler. + guest_output_paint_root_signature_desc.NumStaticSamplers = 0; + // RCAS. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(FsrRcasConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "FSR RCAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexFsrRcas] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // CAS, sharpening only. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(CasSharpenConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output AMD FidelityFX " + "CAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexCasSharpen] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + // CAS, resampling. + guest_output_paint_root_parameter_effect_constants.Constants.Num32BitValues = + sizeof(CasResampleConstants) / sizeof(uint32_t); + { + ID3D12RootSignature* guest_output_paint_root_signature = + util::CreateRootSignature(provider_, + guest_output_paint_root_signature_desc); + if (!guest_output_paint_root_signature) { + XELOGE( + "D3D12Presenter: Failed to create the guest output resampling AMD " + "FidelityFX CAS presentation root signature"); + return false; + } + *(guest_output_paint_root_signatures_ + [kGuestOutputPaintRootSignatureIndexCasResample] + .ReleaseAndGetAddressOf()) = guest_output_paint_root_signature; + } + + // Guest output painting pipelines. + D3D12_GRAPHICS_PIPELINE_STATE_DESC guest_output_paint_pipeline_desc = {}; + guest_output_paint_pipeline_desc.VS.pShaderBytecode = + shaders::guest_output_triangle_strip_rect_vs; + guest_output_paint_pipeline_desc.VS.BytecodeLength = + sizeof(shaders::guest_output_triangle_strip_rect_vs); + guest_output_paint_pipeline_desc.BlendState.RenderTarget[0] + .RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + guest_output_paint_pipeline_desc.SampleMask = UINT_MAX; + guest_output_paint_pipeline_desc.RasterizerState.FillMode = + D3D12_FILL_MODE_SOLID; + guest_output_paint_pipeline_desc.RasterizerState.CullMode = + D3D12_CULL_MODE_NONE; + guest_output_paint_pipeline_desc.RasterizerState.DepthClipEnable = TRUE; + guest_output_paint_pipeline_desc.PrimitiveTopologyType = + D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + guest_output_paint_pipeline_desc.NumRenderTargets = 1; + guest_output_paint_pipeline_desc.SampleDesc.Count = 1; + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + GuestOutputPaintEffect guest_output_paint_effect = + GuestOutputPaintEffect(i); + switch (guest_output_paint_effect) { + case GuestOutputPaintEffect::kBilinear: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_bilinear_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_bilinear_ps); + break; + case GuestOutputPaintEffect::kBilinearDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_bilinear_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_bilinear_dither_ps); + break; + case GuestOutputPaintEffect::kCasSharpen: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_sharpen_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_sharpen_ps); + break; + case GuestOutputPaintEffect::kCasSharpenDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_sharpen_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_sharpen_dither_ps); + break; + case GuestOutputPaintEffect::kCasResample: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_resample_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_resample_ps); + break; + case GuestOutputPaintEffect::kCasResampleDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_cas_resample_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_cas_resample_dither_ps); + break; + case GuestOutputPaintEffect::kFsrEasu: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_easu_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_easu_ps); + break; + case GuestOutputPaintEffect::kFsrRcas: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_rcas_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_rcas_ps); + break; + case GuestOutputPaintEffect::kFsrRcasDither: + guest_output_paint_pipeline_desc.PS.pShaderBytecode = + shaders::guest_output_ffx_fsr_rcas_dither_ps; + guest_output_paint_pipeline_desc.PS.BytecodeLength = + sizeof(shaders::guest_output_ffx_fsr_rcas_dither_ps); + break; + default: + // Not supported by this implementation. + continue; + } + guest_output_paint_pipeline_desc.pRootSignature = + guest_output_paint_root_signatures_ + [GetGuestOutputPaintRootSignatureIndex(guest_output_paint_effect)] + .Get(); + if (CanGuestOutputPaintEffectBeIntermediate(guest_output_paint_effect)) { + guest_output_paint_pipeline_desc.RTVFormats[0] = + kGuestOutputIntermediateFormat; + if (FAILED(device->CreateGraphicsPipelineState( + &guest_output_paint_pipeline_desc, + IID_PPV_ARGS(&guest_output_paint_intermediate_pipelines_[i])))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output painting " + "pipeline for effect {} writing to an intermediate texture", + i); + return false; + } + } + if (CanGuestOutputPaintEffectBeFinal(guest_output_paint_effect)) { + guest_output_paint_pipeline_desc.RTVFormats[0] = kSwapChainFormat; + if (FAILED(device->CreateGraphicsPipelineState( + &guest_output_paint_pipeline_desc, + IID_PPV_ARGS(&guest_output_paint_final_pipelines_[i])))) { + XELOGE( + "D3D12Presenter: Failed to create the guest output painting " + "pipeline for effect {} writing to a swap chain buffer", + i); + return false; + } + } + } + + // Initialize connection-independent parts of the painting context. + + ID3D12CommandQueue* direct_queue = provider_.GetDirectQueue(); + + // Paint submission trackers. + if (!paint_context_.paint_submission_tracker.Initialize(device, + direct_queue) || + !paint_context_.present_submission_tracker.Initialize(device, + direct_queue)) { + return false; + } + + // Paint command allocators and command list. + for (Microsoft::WRL::ComPtr& + paint_command_allocator_ref : paint_context_.command_allocators) { + if (FAILED(device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&paint_command_allocator_ref)))) { + XELOGE( + "D3D12Presenter: Failed to create a command allocator for drawing to " + "a swap chain"); + return false; + } + } + if (FAILED(device->CreateCommandList( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, + paint_context_.command_allocators[0].Get(), nullptr, + IID_PPV_ARGS(&paint_context_.command_list)))) { + XELOGE( + "D3D12Presenter: Failed to create the command list for drawing to a " + "swap chain"); + return false; + } + // Command lists are created in an open state. + paint_context_.command_list->Close(); + + // RTV descriptor heap. + D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc; + rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtv_heap_desc.NumDescriptors = PaintContext::kRTVCount; + rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + rtv_heap_desc.NodeMask = 0; + if (FAILED(device->CreateDescriptorHeap( + &rtv_heap_desc, IID_PPV_ARGS(&paint_context_.rtv_heap)))) { + XELOGE( + "D3D12Presenter: Failed to create an RTV descriptor heap with {} " + "descriptors", + rtv_heap_desc.NumDescriptors); + return false; + } + + // CBV/SRV/UAV descriptor heap. + D3D12_DESCRIPTOR_HEAP_DESC view_heap_desc; + view_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + view_heap_desc.NumDescriptors = PaintContext::kViewCount; + view_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + view_heap_desc.NodeMask = 0; + if (FAILED(device->CreateDescriptorHeap( + &view_heap_desc, IID_PPV_ARGS(&paint_context_.view_heap)))) { + XELOGE( + "D3D12Presenter: Failed to create a shader-visible CBV/SRV/UAV " + "descriptor heap with {} descriptors", + view_heap_desc.NumDescriptors); + return false; + } + + if (!guest_output_resource_refresher_submission_tracker_.Initialize( + device, direct_queue)) { + return false; + } + + if (!ui_submission_tracker_.Initialize(device, direct_queue)) { + return false; + } + + return InitializeCommonSurfaceIndependent(); +} + +} // namespace d3d12 +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_presenter.h b/src/xenia/ui/d3d12/d3d12_presenter.h new file mode 100644 index 000000000..81d9c4ff5 --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_presenter.h @@ -0,0 +1,332 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_D3D12_D3D12_PRESENTER_H_ +#define XENIA_UI_D3D12_D3D12_PRESENTER_H_ + +#include +#include +#include + +#include "xenia/base/math.h" +#include "xenia/ui/d3d12/d3d12_provider.h" +#include "xenia/ui/d3d12/d3d12_submission_tracker.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +class D3D12UIDrawContext final : public UIDrawContext { + public: + D3D12UIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height, + ID3D12GraphicsCommandList* command_list, + UINT64 submission_index_current, + UINT64 submission_index_completed) + : UIDrawContext(presenter, render_target_width, render_target_height), + command_list_(command_list), + submission_index_current_(submission_index_current), + submission_index_completed_(submission_index_completed) {} + + ID3D12GraphicsCommandList* command_list() const { + return command_list_.Get(); + } + UINT64 submission_index_current() const { return submission_index_current_; } + UINT64 submission_index_completed() const { + return submission_index_completed_; + } + + private: + Microsoft::WRL::ComPtr command_list_; + UINT64 submission_index_current_; + UINT64 submission_index_completed_; +}; + +class D3D12Presenter final : public Presenter { + public: + static constexpr DXGI_FORMAT kGuestOutputFormat = + DXGI_FORMAT_R10G10B10A2_UNORM; + static constexpr D3D12_RESOURCE_STATES kGuestOutputInternalState = + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + + static constexpr DXGI_FORMAT kGuestOutputIntermediateFormat = + DXGI_FORMAT_R10G10B10A2_UNORM; + + // The format used internally by Windows composition. + static constexpr DXGI_FORMAT kSwapChainFormat = DXGI_FORMAT_B8G8R8A8_UNORM; + + // The callback must use the main direct queue of the provider. + class D3D12GuestOutputRefreshContext final + : public GuestOutputRefreshContext { + public: + D3D12GuestOutputRefreshContext(bool& is_8bpc_out_ref, + ID3D12Resource* resource) + : GuestOutputRefreshContext(is_8bpc_out_ref), resource_(resource) {} + + // kGuestOutputFormat, supports UAV. The initial state in the callback is + // kGuestOutputInternalState, and the callback must also transition it back + // to kGuestOutputInternalState before finishing. + ID3D12Resource* resource_uav_capable() const { return resource_.Get(); } + + private: + Microsoft::WRL::ComPtr resource_; + }; + + static std::unique_ptr Create( + HostGpuLossCallback host_gpu_loss_callback, + const D3D12Provider& provider) { + auto presenter = std::unique_ptr( + new D3D12Presenter(host_gpu_loss_callback, provider)); + if (!presenter->InitializeSurfaceIndependent()) { + return nullptr; + } + return presenter; + } + + ~D3D12Presenter(); + + const D3D12Provider& provider() const { return provider_; } + + Surface::TypeFlags GetSupportedSurfaceTypes() const override; + + bool CaptureGuestOutput(RawImage& image_out) override; + + void AwaitUISubmissionCompletionFromUIThread(UINT64 submission_index) { + ui_submission_tracker_.AwaitSubmissionCompletion(submission_index); + } + + protected: + SurfacePaintConnectResult ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) override; + void DisconnectPaintingFromSurfaceFromUIThreadImpl() override; + + bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out) override; + + PaintResult PaintAndPresentImpl(bool execute_ui_drawers) override; + + private: + struct GuestOutputPaintRectangleConstants { + union { + struct { + float x; + float y; + }; + float offset[2]; + }; + union { + struct { + float width; + float height; + }; + float size[2]; + }; + }; + + enum class GuestOutputPaintRootParameter : UINT { + kSource, + kRectangle, + kEffectConstants, + + kCount, + }; + + enum GuestOutputPaintRootSignatureIndex : size_t { + kGuestOutputPaintRootSignatureIndexBilinear, + kGuestOutputPaintRootSignatureIndexCasSharpen, + kGuestOutputPaintRootSignatureIndexCasResample, + kGuestOutputPaintRootSignatureIndexFsrEasu, + kGuestOutputPaintRootSignatureIndexFsrRcas, + + kGuestOutputPaintRootSignatureCount, + }; + + static constexpr GuestOutputPaintRootSignatureIndex + GetGuestOutputPaintRootSignatureIndex(GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + case GuestOutputPaintEffect::kBilinearDither: + return kGuestOutputPaintRootSignatureIndexBilinear; + case GuestOutputPaintEffect::kCasSharpen: + case GuestOutputPaintEffect::kCasSharpenDither: + return kGuestOutputPaintRootSignatureIndexCasSharpen; + case GuestOutputPaintEffect::kCasResample: + case GuestOutputPaintEffect::kCasResampleDither: + return kGuestOutputPaintRootSignatureIndexCasResample; + case GuestOutputPaintEffect::kFsrEasu: + return kGuestOutputPaintRootSignatureIndexFsrEasu; + case GuestOutputPaintEffect::kFsrRcas: + case GuestOutputPaintEffect::kFsrRcasDither: + return kGuestOutputPaintRootSignatureIndexFsrRcas; + default: + assert_unhandled_case(effect); + return kGuestOutputPaintRootSignatureCount; + } + } + + struct PaintContext { + explicit PaintContext() = default; + PaintContext(const PaintContext& paint_context) = delete; + PaintContext& operator=(const PaintContext& paint_context) = delete; + + static constexpr uint32_t kSwapChainBufferCount = 3; + + enum RTVIndex : UINT { + // Swap chain buffers - updated when creating the swap chain + // (connection-specific). + kRTVIndexSwapChainBuffer0, + + // Intermediate textures - the last usage is + // guest_output_intermediate_texture_paint_last_usage_. + kRTVIndexGuestOutputIntermediate0 = + kRTVIndexSwapChainBuffer0 + kSwapChainBufferCount, + + kRTVCount = + kRTVIndexGuestOutputIntermediate0 + kGuestOutputMailboxSize - 1, + }; + + enum ViewIndex : UINT { + // Guest output textures - indices are the same as in + // guest_output_resource_paint_refs, and the last usage is tied to them. + kViewIndexGuestOutput0Srv, + + // Intermediate textures - the last usage is + // guest_output_intermediate_texture_paint_last_usage_. + kViewIndexGuestOutputIntermediate0Srv = + kViewIndexGuestOutput0Srv + kGuestOutputMailboxSize, + + kViewCount = kViewIndexGuestOutputIntermediate0Srv + + kMaxGuestOutputPaintEffects - 1, + }; + + void AwaitSwapChainUsageCompletion() { + // Presentation engine usage. + present_submission_tracker.AwaitAllSubmissionsCompletion(); + // Paint (render target) usage. While the presentation fence is signaled + // on the same queue, and presentation happens after painting, awaiting + // anyway for safety just to make less assumptions in the architecture. + paint_submission_tracker.AwaitAllSubmissionsCompletion(); + } + + void DestroySwapChain(); + + // Connection-independent. + + // Signaled before presenting. + D3D12SubmissionTracker paint_submission_tracker; + // Signaled after presenting. + D3D12SubmissionTracker present_submission_tracker; + + std::array, + kSwapChainBufferCount> + command_allocators; + Microsoft::WRL::ComPtr command_list; + + // Descriptor heaps for views of the current resources related to the guest + // output and to painting, updated either during painting or during + // connection lifetime management if outdated after awaiting usage + // completion. + // RTV heap. + Microsoft::WRL::ComPtr rtv_heap; + // Shader-visible CBV/SRV/UAV heap. + Microsoft::WRL::ComPtr view_heap; + + // Refreshed and cleaned up during guest output painting. The first is the + // paint submission index in which the guest output texture (and its + // descriptors) was last used, the second is the reference to the texture, + // which may be null. The indices are not mailbox indices here, rather, if + // the reference is not in this array yet, the most outdated reference, if + // needed, is replaced with the new one, awaiting the completion of the last + // paint usage. + std::array>, + kGuestOutputMailboxSize> + guest_output_resource_paint_refs; + + // Current intermediate textures for guest output painting, refreshed when + // painting guest output. While not in use, they are in + // D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE. + std::array, + kMaxGuestOutputPaintEffects - 1> + guest_output_intermediate_textures; + UINT64 guest_output_intermediate_texture_last_usage = 0; + + // Connection-specific. + + uint32_t swap_chain_width = 0; + uint32_t swap_chain_height = 0; + bool swap_chain_allows_tearing = false; + Microsoft::WRL::ComPtr swap_chain; + std::array, kSwapChainBufferCount> + swap_chain_buffers; + }; + + explicit D3D12Presenter(HostGpuLossCallback host_gpu_loss_callback, + const D3D12Provider& provider) + : Presenter(host_gpu_loss_callback), provider_(provider) {} + + bool dxgi_supports_tearing() const { return dxgi_supports_tearing_; } + + bool InitializeSurfaceIndependent(); + + const D3D12Provider& provider_; + + // Whether DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING is supported by DXGI (depends in + // particular on the Windows 10 version and hardware support), primarily for + // variable refresh rate support. + bool dxgi_supports_tearing_ = false; + + // Static objects for guest output presentation, used only when painting the + // main target (can be destroyed only after awaiting main target usage + // completion). + std::array, + kGuestOutputPaintRootSignatureCount> + guest_output_paint_root_signatures_; + std::array, + size_t(GuestOutputPaintEffect::kCount)> + guest_output_paint_intermediate_pipelines_; + std::array, + size_t(GuestOutputPaintEffect::kCount)> + guest_output_paint_final_pipelines_; + + // The first is the refresher submission tracker fence value at which the + // guest output texture was last refreshed, the second is the reference to the + // texture, which may be null. The indices are the mailbox indices. + std::array>, + kGuestOutputMailboxSize> + guest_output_resources_; + // The guest output resources are protected by two submission trackers - the + // refresher ones (for writing to them via the guest_output_resources_ + // references) and the paint one (for presenting it via the + // paint_context_.guest_output_resource_paint_refs references taken from + // guest_output_resources_). + D3D12SubmissionTracker guest_output_resource_refresher_submission_tracker_; + + // UI submission tracker with the submission index that can be given to UI + // drawers (accessible from the UI thread only, at any time). + D3D12SubmissionTracker ui_submission_tracker_; + + // Accessible only by painting and by surface connection lifetime management + // (ConnectOrReconnectPaintingToSurfaceFromUIThread, + // DisconnectPaintingFromSurfaceFromUIThreadImpl) by the thread doing it, as + // well as by presenter initialization and shutdown. + PaintContext paint_context_; +}; + +} // namespace d3d12 +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_PRESENTER_H_ diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index 57345824d..3c3825091 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -15,7 +15,8 @@ #include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/ui/d3d12/d3d12_context.h" +#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" +#include "xenia/ui/d3d12/d3d12_presenter.h" DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.", "D3D12"); @@ -77,6 +78,14 @@ D3D12Provider::~D3D12Provider() { dxgi_factory_->Release(); } + if (cvars::d3d12_debug && pfn_dxgi_get_debug_interface1_) { + Microsoft::WRL::ComPtr dxgi_debug; + if (SUCCEEDED( + pfn_dxgi_get_debug_interface1_(0, IID_PPV_ARGS(&dxgi_debug)))) { + dxgi_debug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL); + } + } + if (library_dxcompiler_ != nullptr) { FreeLibrary(library_dxcompiler_); } @@ -86,9 +95,6 @@ D3D12Provider::~D3D12Provider() { if (library_d3dcompiler_ != nullptr) { FreeLibrary(library_d3dcompiler_); } - if (library_dcomp_ != nullptr) { - FreeLibrary(library_dcomp_); - } if (library_d3d12_ != nullptr) { FreeLibrary(library_d3d12_); } @@ -120,9 +126,8 @@ bool D3D12Provider::Initialize() { // Load the core libraries. library_dxgi_ = LoadLibraryW(L"dxgi.dll"); library_d3d12_ = LoadLibraryW(L"D3D12.dll"); - library_dcomp_ = LoadLibraryW(L"dcomp.dll"); - if (!library_dxgi_ || !library_d3d12_ || !library_dcomp_) { - XELOGE("Failed to load dxgi.dll, D3D12.dll or dcomp.dll"); + if (!library_dxgi_ || !library_d3d12_) { + XELOGE("Failed to load dxgi.dll or D3D12.dll"); return false; } bool libraries_loaded = true; @@ -143,12 +148,8 @@ bool D3D12Provider::Initialize() { (pfn_d3d12_serialize_root_signature_ = PFN_D3D12_SERIALIZE_ROOT_SIGNATURE( GetProcAddress(library_d3d12_, "D3D12SerializeRootSignature"))) != nullptr; - libraries_loaded &= - (pfn_dcomposition_create_device_ = PFNDCompositionCreateDevice( - GetProcAddress(library_dcomp_, "DCompositionCreateDevice"))) != - nullptr; if (!libraries_loaded) { - XELOGE("Failed to get DXGI, Direct3D 12 or DirectComposition functions"); + XELOGE("Failed to get DXGI or Direct3D 12 functions"); return false; } @@ -470,23 +471,13 @@ bool D3D12Provider::Initialize() { return true; } -std::unique_ptr D3D12Provider::CreateContext( - Window* target_window) { - auto new_context = - std::unique_ptr(new D3D12Context(this, target_window)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr D3D12Provider::CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback) { + return D3D12Presenter::Create(host_gpu_loss_callback, *this); } -std::unique_ptr D3D12Provider::CreateOffscreenContext() { - auto new_context = - std::unique_ptr(new D3D12Context(this, nullptr)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr D3D12Provider::CreateImmediateDrawer() { + return D3D12ImmediateDrawer::Create(*this); } } // namespace d3d12 diff --git a/src/xenia/ui/d3d12/d3d12_provider.h b/src/xenia/ui/d3d12/d3d12_provider.h index 3ddaf507d..937acaae9 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.h +++ b/src/xenia/ui/d3d12/d3d12_provider.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -23,15 +23,17 @@ namespace d3d12 { class D3D12Provider : public GraphicsProvider { public: - ~D3D12Provider() override; + ~D3D12Provider(); static bool IsD3D12APIAvailable(); static std::unique_ptr Create(); - std::unique_ptr CreateContext( - Window* target_window) override; - std::unique_ptr CreateOffscreenContext() override; + std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) override; + + std::unique_ptr CreateImmediateDrawer() override; IDXGIFactory2* GetDXGIFactory() const { return dxgi_factory_; } // nullptr if PIX not attached. @@ -118,11 +120,6 @@ class D3D12Provider : public GraphicsProvider { return pfn_d3d12_serialize_root_signature_(desc, version, blob_out, error_blob_out); } - HRESULT CreateDCompositionDevice(IDXGIDevice* dxgi_device, const IID& iid, - void** dcomposition_device_out) const { - return pfn_dcomposition_create_device_(dxgi_device, iid, - dcomposition_device_out); - } HRESULT Disassemble(const void* src_data, size_t src_data_size, UINT flags, const char* comments, ID3DBlob** disassembly_out) const { if (!pfn_d3d_disassemble_) { @@ -156,22 +153,17 @@ class D3D12Provider : public GraphicsProvider { _COM_Outptr_ void** ppFactory); typedef HRESULT(WINAPI* PFNDXGIGetDebugInterface1)( UINT Flags, REFIID riid, _COM_Outptr_ void** pDebug); - typedef HRESULT(WINAPI* PFNDCompositionCreateDevice)( - _In_opt_ IDXGIDevice* dxgiDevice, _In_ REFIID iid, - _Outptr_ void** dcompositionDevice); HMODULE library_dxgi_ = nullptr; PFNCreateDXGIFactory2 pfn_create_dxgi_factory2_; - PFNDXGIGetDebugInterface1 pfn_dxgi_get_debug_interface1_; + // Needed during shutdown as well to report live objects, so may be nullptr. + PFNDXGIGetDebugInterface1 pfn_dxgi_get_debug_interface1_ = nullptr; HMODULE library_d3d12_ = nullptr; PFN_D3D12_GET_DEBUG_INTERFACE pfn_d3d12_get_debug_interface_; PFN_D3D12_CREATE_DEVICE pfn_d3d12_create_device_; PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfn_d3d12_serialize_root_signature_; - HMODULE library_dcomp_ = nullptr; - PFNDCompositionCreateDevice pfn_dcomposition_create_device_; - HMODULE library_d3dcompiler_ = nullptr; pD3DDisassemble pfn_d3d_disassemble_ = nullptr; @@ -182,9 +174,9 @@ class D3D12Provider : public GraphicsProvider { DxcCreateInstanceProc pfn_dxcompiler_dxc_create_instance_ = nullptr; IDXGIFactory2* dxgi_factory_ = nullptr; - IDXGraphicsAnalysis* graphics_analysis_ = nullptr; ID3D12Device* device_ = nullptr; ID3D12CommandQueue* direct_queue_ = nullptr; + IDXGraphicsAnalysis* graphics_analysis_ = nullptr; uint32_t descriptor_sizes_[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; diff --git a/src/xenia/ui/d3d12/d3d12_submission_tracker.cc b/src/xenia/ui/d3d12/d3d12_submission_tracker.cc new file mode 100644 index 000000000..d8f604f7f --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_submission_tracker.cc @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/d3d12/d3d12_submission_tracker.h" + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +bool D3D12SubmissionTracker::Initialize(ID3D12Device* device, + ID3D12CommandQueue* queue) { + Shutdown(); + fence_completion_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (!fence_completion_event_) { + XELOGE( + "D3D12SubmissionTracker: Failed to create the fence completion event"); + Shutdown(); + return false; + } + // Continue where the tracker was left at the last shutdown. + if (FAILED(device->CreateFence(submission_current_ - 1, D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&fence_)))) { + XELOGE("D3D12SubmissionTracker: Failed to create the fence"); + Shutdown(); + return false; + } + queue_ = queue; + submission_signal_queued_ = submission_current_ - 1; + return true; +} + +void D3D12SubmissionTracker::Shutdown() { + AwaitAllSubmissionsCompletion(); + queue_.Reset(); + fence_.Reset(); + if (fence_completion_event_) { + CloseHandle(fence_completion_event_); + fence_completion_event_ = nullptr; + } +} + +bool D3D12SubmissionTracker::AwaitSubmissionCompletion( + UINT64 submission_index) { + if (!fence_ || !fence_completion_event_) { + // Not fully initialized yet or already shut down. + return false; + } + // The tracker itself can't give a submission index for a submission that + // hasn't even started being recorded yet, the client has provided a + // completely invalid value or has done overly optimistic math if such an + // index has been obtained somehow. + assert_true(submission_index <= submission_current_); + // Waiting for the current submission is fine if there was a refusal to + // submit, and the submission index wasn't incremented, but still need to + // release objects referenced in the dropped submission (while shutting down, + // for instance - in this case, waiting for the last successful submission, + // which could have also referenced the objects from the new submission - we + // can't know since the client has already overwritten its last usage index, + // would correctly ensure that GPU usage of the objects is not pending). + // Waiting for successful submissions, but failed signals, will result in a + // true race condition, however, but waiting for the closest successful signal + // is the best approximation - also retrying to signal in this case. + UINT64 fence_value = submission_index; + if (submission_index > submission_signal_queued_) { + TrySignalEnqueueing(); + fence_value = submission_signal_queued_; + } + if (fence_->GetCompletedValue() < fence_value) { + if (FAILED(fence_->SetEventOnCompletion(fence_value, + fence_completion_event_))) { + return false; + } + if (WaitForSingleObject(fence_completion_event_, INFINITE) != + WAIT_OBJECT_0) { + return false; + } + } + return fence_value == submission_index; +} + +void D3D12SubmissionTracker::SetQueue(ID3D12CommandQueue* new_queue) { + if (queue_.Get() == new_queue) { + return; + } + if (queue_) { + // Make sure the first signal on the new queue won't happen before the last + // signal, if pending, on the old one, as that would result first in too + // early submission completion indication, and then in rewinding. + AwaitAllSubmissionsCompletion(); + } + queue_ = new_queue; +} + +bool D3D12SubmissionTracker::NextSubmission() { + ++submission_current_; + assert_not_null(queue_); + assert_not_null(fence_); + return TrySignalEnqueueing(); +} + +bool D3D12SubmissionTracker::TrySignalEnqueueing() { + if (submission_signal_queued_ + 1 >= submission_current_) { + return true; + } + if (!queue_ || !fence_) { + return false; + } + if (FAILED(queue_->Signal(fence_.Get(), submission_current_ - 1))) { + return false; + } + submission_signal_queued_ = submission_current_ - 1; + return true; +} + +} // namespace d3d12 +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_submission_tracker.h b/src/xenia/ui/d3d12/d3d12_submission_tracker.h new file mode 100644 index 000000000..cf4e92836 --- /dev/null +++ b/src/xenia/ui/d3d12/d3d12_submission_tracker.h @@ -0,0 +1,93 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ +#define XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ + +#include "xenia/ui/d3d12/d3d12_api.h" + +namespace xe { +namespace ui { +namespace d3d12 { + +// GPU > CPU fence wrapper, safely handling cases when the fence has not been +// initialized yet or has already been shut down, dropped submissions, and also +// transfers between queues so signals stay ordered. +// +// The current submission index can be associated with the usage of objects to +// release them when the GPU isn't potentially referencing them anymore, and +// should be incremented only +// +// 0 can be used as a "never referenced" submission index. +// +// The submission index timeline survives Shutdown / Initialize, so submission +// indices can be given to clients that are not aware of the lifetime of the +// tracker. +class D3D12SubmissionTracker { + public: + D3D12SubmissionTracker() = default; + D3D12SubmissionTracker(const D3D12SubmissionTracker& submission_tracker) = + delete; + D3D12SubmissionTracker& operator=( + const D3D12SubmissionTracker& submission_tracker) = delete; + ~D3D12SubmissionTracker() { Shutdown(); } + + // The queue may be null if it's going to be set dynamically. Will also take a + // reference to the queue. + bool Initialize(ID3D12Device* device, ID3D12CommandQueue* queue); + void Shutdown(); + + // Will perform an ownership transfer if the queue is different than the + // current one, and take a reference to the queue. + void SetQueue(ID3D12CommandQueue* new_queue); + + UINT64 GetCurrentSubmission() const { return submission_current_; } + // May be lower than a value awaited by AwaitSubmissionCompletion if it + // returned false. + UINT64 GetCompletedSubmission() const { + // If shut down already or haven't fully initialized yet, don't care, for + // simplicity of external code, as any downloads are unlikely in this case, + // but destruction can be simplified. + return fence_ ? fence_->GetCompletedValue() : (GetCurrentSubmission() - 1); + } + + // Returns whether the expected GPU signal has actually been reached (rather + // than some fallback condition) for cases when stronger completeness + // guarantees as needed (when downloading, as opposed to just destroying). + // If false is returned, it's also not guaranteed that GetCompletedSubmission + // will return a value >= submission_index. + bool AwaitSubmissionCompletion(UINT64 submission_index); + bool AwaitAllSubmissionsCompletion() { + return AwaitSubmissionCompletion(GetCurrentSubmission() - 1); + } + + // Call after a successful ExecuteCommandList. Unconditionally increments the + // current submission index, and tries to enqueue the fence signal. Returns + // true if enqueued successfully, but even if not, waiting for submissions + // without a successfully enqueued signal is handled in the tracker in a way + // that it won't be infinite, so there's no need for clients to revert updates + // to submission indices associated with GPU usage of objects. + bool NextSubmission(); + // If NextSubmission has failed, but it's important that the signal is + // enqueued, can be used to retry enqueueing the signal. + bool TrySignalEnqueueing(); + + private: + UINT64 submission_current_ = 1; + UINT64 submission_signal_queued_ = 0; + HANDLE fence_completion_event_ = nullptr; + Microsoft::WRL::ComPtr fence_; + Microsoft::WRL::ComPtr queue_; +}; + +} // namespace d3d12 +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_SUBMISSION_TRACKER_H_ diff --git a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc index 0d6cf8b72..b50edfd6e 100644 --- a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc +++ b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,7 +38,7 @@ uint8_t* D3D12UploadBufferPool::Request( return nullptr; } if (buffer_out) { - *buffer_out = page->buffer_; + *buffer_out = page->buffer_.Get(); } if (offset_out) { *offset_out = offset; @@ -61,7 +61,7 @@ uint8_t* D3D12UploadBufferPool::RequestPartial( return nullptr; } if (buffer_out) { - *buffer_out = page->buffer_; + *buffer_out = page->buffer_.Get(); } if (offset_out) { *offset_out = offset; @@ -80,7 +80,7 @@ D3D12UploadBufferPool::CreatePageImplementation() { D3D12_RESOURCE_DESC buffer_desc; util::FillBufferResourceDesc(buffer_desc, page_size_, D3D12_RESOURCE_FLAG_NONE); - ID3D12Resource* buffer; + Microsoft::WRL::ComPtr buffer; if (FAILED(provider_.GetDevice()->CreateCommittedResource( &util::kHeapPropertiesUpload, provider_.GetHeapFlagCreateNotZeroed(), &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, @@ -97,24 +97,16 @@ D3D12UploadBufferPool::CreatePageImplementation() { buffer->Release(); return nullptr; } - D3D12Page* page = new D3D12Page(buffer, mapping); - // Owned by the page now. - buffer->Release(); - return page; + // Unmapping will be done implicitly when the resource is destroyed. + return new D3D12Page(buffer.Get(), mapping); } D3D12UploadBufferPool::D3D12Page::D3D12Page(ID3D12Resource* buffer, void* mapping) : buffer_(buffer), mapping_(mapping) { - buffer_->AddRef(); gpu_address_ = buffer_->GetGPUVirtualAddress(); } -D3D12UploadBufferPool::D3D12Page::~D3D12Page() { - // Unmapping is done implicitly when the buffer is destroyed. - buffer_->Release(); -} - } // namespace d3d12 } // namespace ui } // namespace xe diff --git a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h index 2a8d2ac0a..c35443c5e 100644 --- a/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h +++ b/src/xenia/ui/d3d12/d3d12_upload_buffer_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,8 +38,7 @@ class D3D12UploadBufferPool : public GraphicsUploadBufferPool { // Creates a reference to the buffer. It must not be unmapped until this // D3D12Page is deleted. D3D12Page(ID3D12Resource* buffer, void* mapping); - ~D3D12Page() override; - ID3D12Resource* buffer_; + Microsoft::WRL::ComPtr buffer_; void* mapping_; D3D12_GPU_VIRTUAL_ADDRESS gpu_address_; }; diff --git a/src/xenia/ui/file_picker.h b/src/xenia/ui/file_picker.h index 6a2259007..c2e6e1174 100644 --- a/src/xenia/ui/file_picker.h +++ b/src/xenia/ui/file_picker.h @@ -16,6 +16,8 @@ #include #include +#include "xenia/ui/window.h" + namespace xe { namespace ui { @@ -68,7 +70,7 @@ class FilePicker { selected_files_ = std::move(selected_files); } - virtual bool Show(void* parent_window_handle = nullptr) = 0; + virtual bool Show(Window* parent_window = nullptr) = 0; private: Mode mode_; diff --git a/src/xenia/ui/file_picker_gtk.cc b/src/xenia/ui/file_picker_gtk.cc index 456582906..0b6ed5044 100644 --- a/src/xenia/ui/file_picker_gtk.cc +++ b/src/xenia/ui/file_picker_gtk.cc @@ -19,6 +19,7 @@ #include "xenia/base/filesystem.h" #include "xenia/base/platform_linux.h" #include "xenia/base/string.h" +#include "xenia/ui/window_gtk.h" namespace xe { namespace ui { @@ -28,7 +29,7 @@ class GtkFilePicker : public FilePicker { GtkFilePicker(); ~GtkFilePicker() override; - bool Show(void* parent_window_handle) override; + bool Show(Window* parent_window) override; private: }; @@ -41,7 +42,7 @@ GtkFilePicker::GtkFilePicker() = default; GtkFilePicker::~GtkFilePicker() = default; -bool GtkFilePicker::Show(void* parent_window_handle) { +bool GtkFilePicker::Show(Window* parent_window) { // TODO(benvanik): FileSaveDialog. assert_true(mode() == Mode::kOpen); // TODO(benvanik): folder dialogs. @@ -50,7 +51,10 @@ bool GtkFilePicker::Show(void* parent_window_handle) { gint res; dialog = gtk_file_chooser_dialog_new( - "Open File", (GtkWindow*)parent_window_handle, + "Open File", + parent_window + ? GTK_WINDOW(static_cast(parent_window)->window()) + : nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL, "_Open", GTK_RESPONSE_ACCEPT, NULL); diff --git a/src/xenia/ui/file_picker_win.cc b/src/xenia/ui/file_picker_win.cc index d2d7bf33d..88ce056bc 100644 --- a/src/xenia/ui/file_picker_win.cc +++ b/src/xenia/ui/file_picker_win.cc @@ -11,6 +11,7 @@ #include "xenia/base/platform_win.h" #include "xenia/base/string.h" #include "xenia/ui/file_picker.h" +#include "xenia/ui/window_win.h" // Microsoft headers after platform_win.h. #include @@ -23,7 +24,7 @@ class Win32FilePicker : public FilePicker { Win32FilePicker(); ~Win32FilePicker() override; - bool Show(void* parent_window_handle) override; + bool Show(Window* parent_window) override; private: }; @@ -109,7 +110,7 @@ Win32FilePicker::Win32FilePicker() = default; Win32FilePicker::~Win32FilePicker() = default; -bool Win32FilePicker::Show(void* parent_window_handle) { +bool Win32FilePicker::Show(Window* parent_window) { // TODO(benvanik): FileSaveDialog. assert_true(mode() == Mode::kOpen); // TODO(benvanik): folder dialogs. @@ -179,7 +180,9 @@ bool Win32FilePicker::Show(void* parent_window_handle) { } // Show the dialog modally. - hr = file_dialog->Show(static_cast(parent_window_handle)); + hr = file_dialog->Show( + parent_window ? static_cast(parent_window)->hwnd() + : nullptr); file_dialog->Unadvise(cookie); if (!SUCCEEDED(hr)) { return false; diff --git a/src/xenia/ui/graphics_context.cc b/src/xenia/ui/graphics_context.cc deleted file mode 100644 index 7f5ab07b6..000000000 --- a/src/xenia/ui/graphics_context.cc +++ /dev/null @@ -1,48 +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/graphics_context.h" - -#include - -#include "xenia/base/cvar.h" -#include "xenia/ui/graphics_provider.h" - -DEFINE_bool(random_clear_color, false, "Randomize window clear color.", "UI"); - -namespace xe { -namespace ui { - -GraphicsContext::GraphicsContext(GraphicsProvider* provider, - Window* target_window) - : provider_(provider), target_window_(target_window) {} - -GraphicsContext::~GraphicsContext() = default; - -bool GraphicsContext::is_current() { return true; } - -bool GraphicsContext::MakeCurrent() { return true; } - -void GraphicsContext::ClearCurrent() {} - -void GraphicsContext::GetClearColor(float* rgba) { - if (cvars::random_clear_color) { - rgba[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn) - rgba[1] = 1.0f; - rgba[2] = 0.0f; - } else { - rgba[0] = 0.0f; - rgba[1] = 0.0f; - rgba[2] = 0.0f; - } - rgba[3] = 1.0f; -} - -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/graphics_context.h b/src/xenia/ui/graphics_context.h deleted file mode 100644 index 0ed5bd881..000000000 --- a/src/xenia/ui/graphics_context.h +++ /dev/null @@ -1,90 +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_GRAPHICS_CONTEXT_H_ -#define XENIA_UI_GRAPHICS_CONTEXT_H_ - -#include -#include - -namespace xe { -namespace ui { - -class GraphicsProvider; -class ImmediateDrawer; -class Window; - -class RawImage { - public: - RawImage() = default; - ~RawImage() = default; - - size_t width = 0; - size_t height = 0; - size_t stride = 0; - std::vector data; -}; - -class GraphicsContext { - public: - virtual ~GraphicsContext(); - - GraphicsProvider* provider() const { return provider_; } - Window* target_window() const { return target_window_; } - bool is_offscreen() { return immediate_drawer() == nullptr; } - - virtual ImmediateDrawer* immediate_drawer() = 0; - - virtual bool is_current(); - virtual bool MakeCurrent(); - virtual void ClearCurrent(); - - // 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. - virtual bool WasLost() = 0; - - // Returns true if able to draw now (the target surface is available). - virtual bool BeginSwap() = 0; - virtual void EndSwap() = 0; - - virtual std::unique_ptr Capture() = 0; - - protected: - explicit GraphicsContext(GraphicsProvider* provider, Window* target_window); - - static void GetClearColor(float* rgba); - - GraphicsProvider* provider_ = nullptr; - Window* target_window_ = nullptr; -}; - -struct GraphicsContextLock { - explicit GraphicsContextLock(GraphicsContext* context) : context_(context) { - was_current_ = context_->is_current(); - if (!was_current_) { - context_->MakeCurrent(); - } - } - ~GraphicsContextLock() { - if (!was_current_) { - context_->ClearCurrent(); - } - } - - private: - bool was_current_ = false; - GraphicsContext* context_ = nullptr; -}; - -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_GRAPHICS_CONTEXT_H_ diff --git a/src/xenia/ui/graphics_provider.h b/src/xenia/ui/graphics_provider.h index 8bbfe90d0..08c78cd1f 100644 --- a/src/xenia/ui/graphics_provider.h +++ b/src/xenia/ui/graphics_provider.h @@ -12,10 +12,12 @@ #include +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" + namespace xe { namespace ui { -class GraphicsContext; class Window; // Factory for graphics contexts. @@ -36,13 +38,13 @@ class GraphicsProvider { virtual ~GraphicsProvider() = default; - // Creates a new graphics context and swapchain for presenting to a window. - virtual std::unique_ptr CreateContext( - Window* target_window) = 0; + // It's safe to reinitialize the presenter in the host GPU loss callback if it + // was called from the UI thread as specified in the arguments. + virtual std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) = 0; - // Creates a new offscreen graphics context without a swapchain or immediate - // drawer. - virtual std::unique_ptr CreateOffscreenContext() = 0; + virtual std::unique_ptr CreateImmediateDrawer() = 0; protected: GraphicsProvider() = default; diff --git a/src/xenia/ui/graphics_upload_buffer_pool.cc b/src/xenia/ui/graphics_upload_buffer_pool.cc index 5eb04fba3..d68085b8d 100644 --- a/src/xenia/ui/graphics_upload_buffer_pool.cc +++ b/src/xenia/ui/graphics_upload_buffer_pool.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -38,6 +38,25 @@ void GraphicsUploadBufferPool::Reclaim(uint64_t completed_submission_index) { } } +void GraphicsUploadBufferPool::ChangeSubmissionTimeline() { + // Reclaim all submitted pages. + if (writable_last_) { + writable_last_->next_ = submitted_first_; + } else { + writable_first_ = submitted_first_; + } + writable_last_ = submitted_last_; + submitted_first_ = nullptr; + submitted_last_ = nullptr; + + // Mark all pages as never used yet in the new timeline. + Page* page = writable_first_; + while (page) { + page->last_submission_index_ = 0; + page = page->next_; + } +} + void GraphicsUploadBufferPool::ClearCache() { // Called from the destructor - must not call virtual functions here. current_page_flushed_ = 0; diff --git a/src/xenia/ui/graphics_upload_buffer_pool.h b/src/xenia/ui/graphics_upload_buffer_pool.h index 250eda70b..00f628af6 100644 --- a/src/xenia/ui/graphics_upload_buffer_pool.h +++ b/src/xenia/ui/graphics_upload_buffer_pool.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -32,6 +32,7 @@ class GraphicsUploadBufferPool { virtual ~GraphicsUploadBufferPool(); void Reclaim(uint64_t completed_submission_index); + void ChangeSubmissionTimeline(); void ClearCache(); // Should be called before submitting anything using this pool, unless the diff --git a/src/xenia/ui/graphics_util.cc b/src/xenia/ui/graphics_util.cc new file mode 100644 index 000000000..b69bc44b3 --- /dev/null +++ b/src/xenia/ui/graphics_util.cc @@ -0,0 +1,63 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/graphics_util.h" + +#include + +namespace xe { +namespace ui { + +int32_t FloatToD3D11Fixed16p8(float f32) { + // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#3.2.4.1%20FLOAT%20-%3E%20Fixed%20Point%20Integer + // Early exit tests. + // n == NaN || n.unbiasedExponent < -f-1 -> 0 . 0 + if (!(std::abs(f32) >= 1.0f / 512.0f)) { + return 0; + } + // n >= (2^(i-1)-2^-f) -> 2^(i-1)-1 . 2^f-1 + if (f32 >= 32768.0f - 1.0f / 256.0f) { + return (1 << 23) - 1; + } + // n <= -2^(i-1) -> -2^(i-1) . 0 + if (f32 <= -32768.0f) { + return -32768 * 256; + } + uint32_t f32_bits = *reinterpret_cast(&f32); + // Copy float32 mantissa bits [22:0] into corresponding bits [22:0] of a + // result buffer that has at least 24 bits total storage (before reaching + // rounding step further below). This includes one bit for the hidden 1. + // Set bit [23] (float32 hidden bit). + // Clear bits [31:24]. + union { + int32_t s; + uint32_t u; + } result; + result.u = (f32_bits & ((1 << 23) - 1)) | (1 << 23); + // If the sign bit is set in the float32 number (negative), then take the 2's + // component of the entire set of bits. + if ((f32_bits >> 31) != 0) { + result.s = -result.s; + } + // Final calculation: extraBits = (mantissa - f) - n.unbiasedExponent + // (guaranteed to be >= 0). + int32_t exponent = int32_t((f32_bits >> 23) & 255) - 127; + uint32_t extra_bits = uint32_t(15 - exponent); + if (extra_bits) { + // Round the 32-bit value to a decimal that is extraBits to the left of + // the LSB end, using nearest-even. + result.u += (1 << (extra_bits - 1)) - 1 + ((result.u >> extra_bits) & 1); + // Shift right by extraBits (sign extending). + result.s >>= extra_bits; + } + return result.s; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/graphics_util.h b/src/xenia/ui/graphics_util.h new file mode 100644 index 000000000..b3aa19a33 --- /dev/null +++ b/src/xenia/ui/graphics_util.h @@ -0,0 +1,30 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_GRAPHICS_UTIL_H_ +#define XENIA_UI_GRAPHICS_UTIL_H_ + +#include + +namespace xe { +namespace ui { + +// For estimating coverage extents from vertices. This may give results that are +// different than what the GPU will actually draw (this is the reference +// conversion with 1/2 ULP accuracy, but Direct3D 11 permits 0.6 ULP tolerance +// in floating point to fixed point conversion), but is enough to tie-break +// vertices at pixel centers (due to the half-pixel offset applied to integer +// coordinates incorrectly, for instance) with some error tolerance near 0.5, +// for use with the top-left rasterization rule later. +int32_t FloatToD3D11Fixed16p8(float f32); + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_GRAPHICS_UTIL_H_ diff --git a/src/xenia/ui/imgui_dialog.cc b/src/xenia/ui/imgui_dialog.cc index 2e2370bd9..4e940e798 100644 --- a/src/xenia/ui/imgui_dialog.cc +++ b/src/xenia/ui/imgui_dialog.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,20 +11,18 @@ #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" -#include "xenia/ui/window.h" +#include "xenia/ui/imgui_drawer.h" namespace xe { namespace ui { -ImGuiDialog::ImGuiDialog(Window* window) : window_(window) { - window_->AttachListener(this); - had_imgui_active_ = window_->is_imgui_input_enabled(); - window_->set_imgui_input_enabled(true); +ImGuiDialog::ImGuiDialog(ImGuiDrawer* imgui_drawer) + : imgui_drawer_(imgui_drawer) { + imgui_drawer_->AddDialog(this); } ImGuiDialog::~ImGuiDialog() { - window_->set_imgui_input_enabled(had_imgui_active_); - window_->DetachListener(this); + imgui_drawer_->RemoveDialog(this); for (auto fence : waiting_fences_) { fence->Signal(); } @@ -36,12 +34,9 @@ void ImGuiDialog::Then(xe::threading::Fence* fence) { void ImGuiDialog::Close() { has_close_pending_ = true; } -ImGuiIO& ImGuiDialog::GetIO() { return window_->imgui_drawer()->GetIO(); } - -void ImGuiDialog::OnPaint(UIEvent* e) { - // Keep imgui rendering every frame. - window_->Invalidate(); +ImGuiIO& ImGuiDialog::GetIO() { return imgui_drawer()->GetIO(); } +void ImGuiDialog::Draw() { // Draw UI. OnDraw(GetIO()); @@ -52,10 +47,13 @@ void ImGuiDialog::OnPaint(UIEvent* e) { } } -class MessageBoxDialog : public ImGuiDialog { +class MessageBoxDialog final : public ImGuiDialog { public: - MessageBoxDialog(Window* window, std::string title, std::string body) - : ImGuiDialog(window), title_(std::move(title)), body_(std::move(body)) {} + MessageBoxDialog(ImGuiDrawer* imgui_drawer, std::string title, + std::string body) + : ImGuiDialog(imgui_drawer), + title_(std::move(title)), + body_(std::move(body)) {} void OnDraw(ImGuiIO& io) override { if (!has_opened_) { @@ -84,9 +82,9 @@ class MessageBoxDialog : public ImGuiDialog { std::string body_; }; -ImGuiDialog* ImGuiDialog::ShowMessageBox(Window* window, std::string title, - std::string body) { - return new MessageBoxDialog(window, std::move(title), std::move(body)); +ImGuiDialog* ImGuiDialog::ShowMessageBox(ImGuiDrawer* imgui_drawer, + std::string title, std::string body) { + return new MessageBoxDialog(imgui_drawer, std::move(title), std::move(body)); } } // namespace ui diff --git a/src/xenia/ui/imgui_dialog.h b/src/xenia/ui/imgui_dialog.h index 3c9632c07..454659bea 100644 --- a/src/xenia/ui/imgui_dialog.h +++ b/src/xenia/ui/imgui_dialog.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -19,23 +19,25 @@ namespace xe { namespace ui { -class ImGuiDialog : private WindowListener { +class ImGuiDialog { public: ~ImGuiDialog(); // Shows a simple message box containing a text message. // Callers can want for the dialog to close with Wait(). // Dialogs retain themselves and will delete themselves when closed. - static ImGuiDialog* ShowMessageBox(Window* window, std::string title, - std::string body); + static ImGuiDialog* ShowMessageBox(ImGuiDrawer* imgui_drawer, + std::string title, std::string body); // A fence to signal when the dialog is closed. void Then(xe::threading::Fence* fence); - protected: - ImGuiDialog(Window* window); + void Draw(); - Window* window() const { return window_; } + protected: + ImGuiDialog(ImGuiDrawer* imgui_drawer); + + ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; } ImGuiIO& GetIO(); // Closes the dialog and returns to any waiters. @@ -46,10 +48,7 @@ class ImGuiDialog : private WindowListener { virtual void OnDraw(ImGuiIO& io) {} private: - void OnPaint(UIEvent* e) override; - - Window* window_ = nullptr; - bool had_imgui_active_ = false; + ImGuiDrawer* imgui_drawer_ = nullptr; bool has_close_pending_ = false; std::vector waiting_fences_; }; diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 276cea114..c3ab41906 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -2,17 +2,23 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/imgui_drawer.h" +#include +#include + #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" +#include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/window.h" namespace xe { @@ -26,18 +32,75 @@ const char kProggyTinyCompressedDataBase85[10950 + 1] = static_assert(sizeof(ImmediateVertex) == sizeof(ImDrawVert), "Vertex types must match"); -ImGuiDrawer::ImGuiDrawer(xe::ui::Window* window) - : window_(window), graphics_context_(window->context()) { +ImGuiDrawer::ImGuiDrawer(xe::ui::Window* window, size_t z_order) + : window_(window), z_order_(z_order) { Initialize(); } ImGuiDrawer::~ImGuiDrawer() { + SetPresenter(nullptr); + if (!dialogs_.empty()) { + window_->RemoveInputListener(this); + if (internal_state_) { + ImGui::SetCurrentContext(internal_state_); + if (ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } + } + } if (internal_state_) { ImGui::DestroyContext(internal_state_); internal_state_ = nullptr; } } +void ImGuiDrawer::AddDialog(ImGuiDialog* dialog) { + assert_not_null(dialog); + // Check if already added. + if (std::find(dialogs_.cbegin(), dialogs_.cend(), dialog) != + dialogs_.cend()) { + return; + } + if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) { + // First dialog added. dialog_loop_next_index_ == SIZE_MAX is also checked + // because in a situation of removing the only dialog, then adding a dialog, + // from within a dialog's Draw function, the removal would not cause the + // listener and the drawer to be removed (it's deferred in this case). + window_->AddInputListener(this, z_order_); + if (presenter_) { + presenter_->AddUIDrawerFromUIThread(this, z_order_); + } + } + dialogs_.push_back(dialog); +} + +void ImGuiDrawer::RemoveDialog(ImGuiDialog* dialog) { + assert_not_null(dialog); + auto it = std::find(dialogs_.cbegin(), dialogs_.cend(), dialog); + if (it == dialogs_.cend()) { + return; + } + if (dialog_loop_next_index_ != SIZE_MAX) { + // Actualize the next dialog index after the erasure from the vector. + size_t existing_index = size_t(std::distance(dialogs_.cbegin(), it)); + if (dialog_loop_next_index_ > existing_index) { + --dialog_loop_next_index_; + } + } + dialogs_.erase(it); + if (dialog_loop_next_index_ == SIZE_MAX && dialogs_.empty()) { + if (presenter_) { + presenter_->RemoveUIDrawerFromUIThread(this); + } + window_->RemoveInputListener(this); + // Clear all input since no input will be received anymore, and when the + // drawer becomes active again, it'd have an outdated input state otherwise + // which will be persistent until new events actualize individual input + // properties. + ClearInput(); + } +} + void ImGuiDrawer::Initialize() { // Setup ImGui internal state. // This will give us state we can swap to the ImGui globals when in use. @@ -51,9 +114,31 @@ void ImGuiDrawer::Initialize() { // Windows. io.IniFilename = nullptr; - SetupFont(); - - io.DeltaTime = 1.0f / 60.0f; + // Setup the font glyphs. + ImFontConfig font_config; + font_config.OversampleH = font_config.OversampleV = 1; + font_config.PixelSnapH = true; + static const ImWchar font_glyph_ranges[] = { + 0x0020, + 0x00FF, // Basic Latin + Latin Supplement + 0, + }; + io.Fonts->AddFontFromMemoryCompressedBase85TTF( + kProggyTinyCompressedDataBase85, 10.0f, &font_config, font_glyph_ranges); + // TODO(benvanik): jp font on other platforms? + // https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB. + const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc"; + if (std::filesystem::exists(jp_font_path)) { + ImFontConfig jp_font_config; + jp_font_config.MergeMode = true; + jp_font_config.OversampleH = jp_font_config.OversampleV = 1; + jp_font_config.PixelSnapH = true; + jp_font_config.FontNo = 0; + io.Fonts->AddFontFromFileTTF(jp_font_path, 12.0f, &jp_font_config, + io.Fonts->GetGlyphRangesJapanese()); + } else { + XELOGW("Unable to load Japanese font; JP characters will be boxes"); + } auto& style = ImGui::GetStyle(); style.ScrollbarRounding = 0; @@ -125,60 +210,121 @@ void ImGuiDrawer::Initialize() { io.KeyMap[ImGuiKey_X] = int(ui::VirtualKey::kX); io.KeyMap[ImGuiKey_Y] = int(ui::VirtualKey::kY); io.KeyMap[ImGuiKey_Z] = int(ui::VirtualKey::kZ); + + frame_time_tick_frequency_ = double(Clock::QueryHostTickFrequency()); + last_frame_time_ticks_ = Clock::QueryHostTickCount(); } -void ImGuiDrawer::SetupFont() { - auto& io = GetIO(); - - ImFontConfig font_config; - font_config.OversampleH = font_config.OversampleV = 1; - font_config.PixelSnapH = true; - static const ImWchar font_glyph_ranges[] = { - 0x0020, - 0x00FF, // Basic Latin + Latin Supplement - 0, - }; - io.Fonts->AddFontFromMemoryCompressedBase85TTF( - kProggyTinyCompressedDataBase85, 10.0f, &font_config, font_glyph_ranges); - - // TODO(benvanik): jp font on other platforms? - // https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB. - const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc"; - if (std::filesystem::exists(jp_font_path)) { - ImFontConfig jp_font_config; - jp_font_config.MergeMode = true; - jp_font_config.OversampleH = jp_font_config.OversampleV = 1; - jp_font_config.PixelSnapH = true; - jp_font_config.FontNo = 0; - io.Fonts->AddFontFromFileTTF(jp_font_path, 12.0f, &jp_font_config, - io.Fonts->GetGlyphRangesJapanese()); - } else { - XELOGW("Unable to load japanese font; jp characters will be boxes"); +void ImGuiDrawer::SetupFontTexture() { + if (font_texture_ || !immediate_drawer_) { + return; } - + ImGuiIO& io = GetIO(); unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - font_texture_ = graphics_context_->immediate_drawer()->CreateTexture( + font_texture_ = immediate_drawer_->CreateTexture( width, height, ImmediateTextureFilter::kLinear, true, reinterpret_cast(pixels)); - io.Fonts->TexID = reinterpret_cast(font_texture_.get()); } -void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { - auto drawer = graphics_context_->immediate_drawer(); +void ImGuiDrawer::SetPresenter(Presenter* new_presenter) { + if (presenter_) { + if (presenter_ == new_presenter) { + return; + } + if (!dialogs_.empty()) { + presenter_->RemoveUIDrawerFromUIThread(this); + } + ImGuiIO& io = GetIO(); + } + presenter_ = new_presenter; + if (presenter_) { + if (!dialogs_.empty()) { + presenter_->AddUIDrawerFromUIThread(this, z_order_); + } + } +} + +void ImGuiDrawer::SetImmediateDrawer(ImmediateDrawer* new_immediate_drawer) { + if (immediate_drawer_ == new_immediate_drawer) { + return; + } + if (immediate_drawer_) { + GetIO().Fonts->TexID = static_cast(nullptr); + font_texture_.reset(); + } + immediate_drawer_ = new_immediate_drawer; + if (immediate_drawer_) { + SetupFontTexture(); + } +} + +void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) { + // Drawing of anything is initiated by the presenter. + assert_not_null(presenter_); + if (!immediate_drawer_) { + // A presenter has been attached, but an immediate drawer hasn't been + // attached yet. + return; + } + + if (dialogs_.empty()) { + return; + } + + ImGui::SetCurrentContext(internal_state_); - // Handle cases of screen coordinates != from framebuffer coordinates (e.g. - // retina displays). ImGuiIO& io = ImGui::GetIO(); - float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y; - data->ScaleClipRects(io.DisplayFramebufferScale); - const float width = io.DisplaySize.x; - const float height = io.DisplaySize.y; - drawer->Begin(static_cast(width), static_cast(height)); + uint64_t current_frame_time_ticks = Clock::QueryHostTickCount(); + io.DeltaTime = + float(double(current_frame_time_ticks - last_frame_time_ticks_) / + frame_time_tick_frequency_); + if (!(io.DeltaTime > 0.0f) || + current_frame_time_ticks < last_frame_time_ticks_) { + // For safety as Dear ImGui doesn't allow non-positive DeltaTime. Using the + // same default value as in the official samples. + io.DeltaTime = 1.0f / 60.0f; + } + last_frame_time_ticks_ = current_frame_time_ticks; + + float physical_to_logical = + float(window_->GetMediumDpi()) / float(window_->GetDpi()); + io.DisplaySize.x = window_->GetActualPhysicalWidth() * physical_to_logical; + io.DisplaySize.y = window_->GetActualPhysicalHeight() * physical_to_logical; + + ImGui::NewFrame(); + + assert_true(dialog_loop_next_index_ == SIZE_MAX); + dialog_loop_next_index_ = 0; + while (dialog_loop_next_index_ < dialogs_.size()) { + dialogs_[dialog_loop_next_index_++]->Draw(); + } + dialog_loop_next_index_ = SIZE_MAX; + + ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); + if (draw_data) { + RenderDrawLists(draw_data, ui_draw_context); + } + + if (dialogs_.empty()) { + // All dialogs have removed themselves during the draw, detach. + presenter_->RemoveUIDrawerFromUIThread(this); + window_->RemoveInputListener(this); + } else { + // Repaint (and handle input) continuously if still active. + presenter_->RequestUIPaintFromUIThread(); + } +} + +void ImGuiDrawer::RenderDrawLists(ImDrawData* data, + UIDrawContext& ui_draw_context) { + ImGuiIO& io = ImGui::GetIO(); + + immediate_drawer_->Begin(ui_draw_context, io.DisplaySize.x, io.DisplaySize.y); for (int i = 0; i < data->CmdListsCount; ++i) { const auto cmd_list = data->CmdLists[i]; @@ -189,7 +335,7 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { batch.vertex_count = cmd_list->VtxBuffer.size(); batch.indices = cmd_list->IdxBuffer.Data; batch.index_count = cmd_list->IdxBuffer.size(); - drawer->BeginDrawBatch(batch); + immediate_drawer_->BeginDrawBatch(batch); int index_offset = 0; for (int j = 0; j < cmd_list->CmdBuffer.size(); ++j) { @@ -201,19 +347,19 @@ void ImGuiDrawer::RenderDrawLists(ImDrawData* data) { draw.index_offset = index_offset; draw.texture = reinterpret_cast(cmd.TextureId); draw.scissor = true; - draw.scissor_rect[0] = static_cast(cmd.ClipRect.x); - draw.scissor_rect[1] = static_cast(height - cmd.ClipRect.w); - draw.scissor_rect[2] = static_cast(cmd.ClipRect.z - cmd.ClipRect.x); - draw.scissor_rect[3] = static_cast(cmd.ClipRect.w - cmd.ClipRect.y); - drawer->Draw(draw); + draw.scissor_left = cmd.ClipRect.x; + draw.scissor_top = cmd.ClipRect.y; + draw.scissor_right = cmd.ClipRect.z; + draw.scissor_bottom = cmd.ClipRect.w; + immediate_drawer_->Draw(draw); index_offset += cmd.ElemCount; } - drawer->EndDrawBatch(); + immediate_drawer_->EndDrawBatch(); } - drawer->End(); + immediate_drawer_->End(); } ImGuiIO& ImGuiDrawer::GetIO() { @@ -221,33 +367,25 @@ ImGuiIO& ImGuiDrawer::GetIO() { return ImGui::GetIO(); } -void ImGuiDrawer::RenderDrawLists() { - ImGui::SetCurrentContext(internal_state_); - auto draw_data = ImGui::GetDrawData(); - if (draw_data) { - RenderDrawLists(draw_data); - } -} +void ImGuiDrawer::OnKeyDown(KeyEvent& e) { OnKey(e, true); } -void ImGuiDrawer::OnKeyDown(KeyEvent* e) { OnKey(e, true); } +void ImGuiDrawer::OnKeyUp(KeyEvent& e) { OnKey(e, false); } -void ImGuiDrawer::OnKeyUp(KeyEvent* e) { OnKey(e, false); } - -void ImGuiDrawer::OnKeyChar(KeyEvent* e) { +void ImGuiDrawer::OnKeyChar(KeyEvent& e) { auto& io = GetIO(); // TODO(Triang3l): Accept the Unicode character. - unsigned int character = static_cast(e->virtual_key()); + unsigned int character = static_cast(e.virtual_key()); if (character > 0 && character < 0x10000) { io.AddInputCharacter(character); - e->set_handled(true); + e.set_handled(true); } } -void ImGuiDrawer::OnMouseDown(MouseEvent* e) { +void ImGuiDrawer::OnMouseDown(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); int button = -1; - switch (e->button()) { + switch (e.button()) { case xe::ui::MouseEvent::Button::kLeft: { button = 0; break; @@ -261,25 +399,23 @@ void ImGuiDrawer::OnMouseDown(MouseEvent* e) { break; } } - if (button >= 0 && button < std::size(io.MouseDown)) { - if (!ImGui::IsAnyMouseDown()) { - window_->CaptureMouse(); + if (!io.MouseDown[button]) { + if (!ImGui::IsAnyMouseDown()) { + window_->CaptureMouse(); + } + io.MouseDown[button] = true; } - io.MouseDown[button] = true; } } -void ImGuiDrawer::OnMouseMove(MouseEvent* e) { - auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); -} +void ImGuiDrawer::OnMouseMove(MouseEvent& e) { UpdateMousePosition(e); } -void ImGuiDrawer::OnMouseUp(MouseEvent* e) { +void ImGuiDrawer::OnMouseUp(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); int button = -1; - switch (e->button()) { + switch (e.button()) { case xe::ui::MouseEvent::Button::kLeft: { button = 0; break; @@ -293,24 +429,42 @@ void ImGuiDrawer::OnMouseUp(MouseEvent* e) { break; } } - if (button >= 0 && button < std::size(io.MouseDown)) { - io.MouseDown[button] = false; - if (!ImGui::IsAnyMouseDown()) { - window_->ReleaseMouse(); + if (io.MouseDown[button]) { + io.MouseDown[button] = false; + if (!ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } } } } -void ImGuiDrawer::OnMouseWheel(MouseEvent* e) { +void ImGuiDrawer::OnMouseWheel(MouseEvent& e) { + UpdateMousePosition(e); auto& io = GetIO(); - io.MousePos = ImVec2(float(e->x()), float(e->y())); - io.MouseWheel += float(e->dy() / 120.0f); + io.MouseWheel += float(e.scroll_y()) / float(MouseEvent::kScrollPerDetent); } -void ImGuiDrawer::OnKey(KeyEvent* e, bool is_down) { +void ImGuiDrawer::ClearInput() { auto& io = GetIO(); - VirtualKey virtual_key = e->virtual_key(); + if (ImGui::IsAnyMouseDown()) { + window_->ReleaseMouse(); + } + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + std::memset(io.MouseDown, 0, sizeof(io.MouseDown)); + io.MouseWheel = 0.0f; + io.MouseWheelH = 0.0f; + io.KeyCtrl = false; + io.KeyShift = false; + io.KeyAlt = false; + io.KeySuper = false; + std::memset(io.KeysDown, 0, sizeof(io.KeysDown)); + io.ClearInputCharacters(); +} + +void ImGuiDrawer::OnKey(KeyEvent& e, bool is_down) { + auto& io = GetIO(); + VirtualKey virtual_key = e.virtual_key(); if (size_t(virtual_key) < xe::countof(io.KeysDown)) { io.KeysDown[size_t(virtual_key)] = is_down; } @@ -333,5 +487,13 @@ void ImGuiDrawer::OnKey(KeyEvent* e, bool is_down) { } } +void ImGuiDrawer::UpdateMousePosition(const MouseEvent& e) { + auto& io = GetIO(); + float physical_to_logical = + float(window_->GetMediumDpi()) / float(window_->GetDpi()); + io.MousePos.x = e.x() * physical_to_logical; + io.MousePos.y = e.y() * physical_to_logical; +} + } // namespace ui } // namespace xe diff --git a/src/xenia/ui/imgui_drawer.h b/src/xenia/ui/imgui_drawer.h index 2c370b2aa..fee5c4242 100644 --- a/src/xenia/ui/imgui_drawer.h +++ b/src/xenia/ui/imgui_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,10 +10,14 @@ #ifndef XENIA_UI_IMGUI_DRAWER_H_ #define XENIA_UI_IMGUI_DRAWER_H_ +#include +#include #include #include #include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/window.h" #include "xenia/ui/window_listener.h" struct ImDrawData; @@ -23,43 +27,73 @@ struct ImGuiIO; namespace xe { namespace ui { -class GraphicsContext; +class ImGuiDialog; class Window; -class ImGuiDrawer : public WindowListener { +class ImGuiDrawer : public WindowInputListener, public UIDrawer { public: - ImGuiDrawer(Window* window); + ImGuiDrawer(Window* window, size_t z_order); ~ImGuiDrawer(); - void SetupDefaultInput() {} - ImGuiIO& GetIO(); - void RenderDrawLists(); + + void AddDialog(ImGuiDialog* dialog); + void RemoveDialog(ImGuiDialog* dialog); + + // SetPresenter may be called from the destructor. + void SetPresenter(Presenter* new_presenter); + void SetImmediateDrawer(ImmediateDrawer* new_immediate_drawer); + void SetPresenterAndImmediateDrawer(Presenter* new_presenter, + ImmediateDrawer* new_immediate_drawer) { + SetPresenter(new_presenter); + SetImmediateDrawer(new_immediate_drawer); + } + + void Draw(UIDrawContext& ui_draw_context) override; protected: - void Initialize(); - void SetupFont(); - - void RenderDrawLists(ImDrawData* data); - - void OnKeyDown(KeyEvent* e) override; - void OnKeyUp(KeyEvent* e) override; - void OnKeyChar(KeyEvent* e) override; - void OnMouseDown(MouseEvent* e) override; - void OnMouseMove(MouseEvent* e) override; - void OnMouseUp(MouseEvent* e) override; - void OnMouseWheel(MouseEvent* e) override; - - static ImGuiDrawer* current_drawer_; - - Window* window_ = nullptr; - GraphicsContext* graphics_context_ = nullptr; - - ImGuiContext* internal_state_ = nullptr; - std::unique_ptr font_texture_; + void OnKeyDown(KeyEvent& e) override; + void OnKeyUp(KeyEvent& e) override; + void OnKeyChar(KeyEvent& e) override; + void OnMouseDown(MouseEvent& e) override; + void OnMouseMove(MouseEvent& e) override; + void OnMouseUp(MouseEvent& e) override; + void OnMouseWheel(MouseEvent& e) override; + // For now, no need for OnDpiChanged because redrawing is done continuously. private: - void OnKey(KeyEvent* e, bool is_down); + void Initialize(); + + void SetupFontTexture(); + + void RenderDrawLists(ImDrawData* data, UIDrawContext& ui_draw_context); + + void ClearInput(); + void OnKey(KeyEvent& e, bool is_down); + void UpdateMousePosition(const MouseEvent& e); + + Window* window_; + size_t z_order_; + + ImGuiContext* internal_state_ = nullptr; + + // All currently-attached dialogs that get drawn. + std::vector dialogs_; + // Using an index, not an iterator, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + // SIZE_MAX if not currently in the dialog loop. + size_t dialog_loop_next_index_ = SIZE_MAX; + + Presenter* presenter_ = nullptr; + + ImmediateDrawer* immediate_drawer_ = nullptr; + // Resources specific to an immediate drawer - must be destroyed before + // detaching the presenter. + std::unique_ptr font_texture_; + + double frame_time_tick_frequency_; + uint64_t last_frame_time_ticks_; }; } // namespace ui diff --git a/src/xenia/ui/immediate_drawer.cc b/src/xenia/ui/immediate_drawer.cc new file mode 100644 index 000000000..fb00be77f --- /dev/null +++ b/src/xenia/ui/immediate_drawer.cc @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/immediate_drawer.h" + +#include + +#include "xenia/base/assert.h" +#include "xenia/ui/graphics_util.h" +#include "xenia/ui/presenter.h" + +namespace xe { +namespace ui { + +void ImmediateDrawer::SetPresenter(Presenter* new_presenter) { + if (presenter_ == new_presenter) { + return; + } + // Changing the presenter while drawing would make the state inconsistent. + assert_null(ui_draw_context_); + if (presenter_) { + OnLeavePresenter(); + } + presenter_ = new_presenter; + if (presenter_) { + OnEnterPresenter(); + } +} + +void ImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + assert_true(&ui_draw_context.presenter() == presenter_); + ui_draw_context_ = &ui_draw_context; + // In case of non-positive values (or NaNs) - use render target coordinates + // according to the contract of the function, and also for safety because + // there will be division by the coordinate space size in several places. + if (!(coordinate_space_width > 0.0f) || !(coordinate_space_height > 0.0f)) { + coordinate_space_width = float(ui_draw_context.render_target_width()); + coordinate_space_height = float(ui_draw_context.render_target_height()); + } + coordinate_space_width_ = coordinate_space_width; + coordinate_space_height_ = coordinate_space_height; +} + +void ImmediateDrawer::End() { ui_draw_context_ = nullptr; } + +bool ImmediateDrawer::ScissorToRenderTarget(const ImmediateDraw& immediate_draw, + uint32_t& out_left, + uint32_t& out_top, + uint32_t& out_width, + uint32_t& out_height) { + uint32_t render_target_width = ui_draw_context()->render_target_width(); + uint32_t render_target_height = ui_draw_context()->render_target_height(); + if (!immediate_draw.scissor) { + out_left = 0; + out_top = 0; + out_width = render_target_width; + out_height = render_target_height; + return render_target_width && render_target_height; + } + float render_target_width_float = float(render_target_width); + float render_target_height_float = float(render_target_height); + // Scale to render target coordinates, drop NaNs (by doing + // std::max(0.0f, variable) in this argument order), and clamp to the render + // target size, below which the values are representable as 16p8 fixed-point. + float scale_x = render_target_width / coordinate_space_width(); + float scale_y = render_target_height / coordinate_space_height(); + float x0_float = + std::min(render_target_width_float, + std::max(0.0f, immediate_draw.scissor_left * scale_x)); + float y0_float = + std::min(render_target_height_float, + std::max(0.0f, immediate_draw.scissor_top * scale_y)); + // Also make sure the size is non-negative. + float x1_float = + std::min(render_target_width_float, + std::max(x0_float, immediate_draw.scissor_right * scale_x)); + float y1_float = + std::min(render_target_height_float, + std::max(y0_float, immediate_draw.scissor_bottom * scale_y)); + // Top-left - include .5 (0.128 treated as 0 covered, 0.129 as 0 not covered). + int32_t x0 = (FloatToD3D11Fixed16p8(x0_float) + 127) >> 8; + int32_t y0 = (FloatToD3D11Fixed16p8(y0_float) + 127) >> 8; + // Bottom-right - exclude .5. + int32_t x1 = (FloatToD3D11Fixed16p8(x1_float) + 127) >> 8; + int32_t y1 = (FloatToD3D11Fixed16p8(y1_float) + 127) >> 8; + assert_true(x0 >= 0); + assert_true(y0 >= 0); + assert_true(x1 >= x0); + assert_true(y1 >= y0); + assert_true(x1 <= int32_t(render_target_width)); + assert_true(y1 <= int32_t(render_target_height)); + out_left = uint32_t(x0); + out_top = uint32_t(y0); + out_width = uint32_t(x1 - x0); + out_height = uint32_t(y1 - y0); + return x1 > x0 && y1 > y0; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/immediate_drawer.h b/src/xenia/ui/immediate_drawer.h index 544f16aa1..48bca319c 100644 --- a/src/xenia/ui/immediate_drawer.h +++ b/src/xenia/ui/immediate_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -12,11 +12,11 @@ #include +#include "xenia/ui/presenter.h" + namespace xe { namespace ui { -class GraphicsContext; - // Describes the filter applied when sampling textures. enum class ImmediateTextureFilter { kNearest, @@ -80,21 +80,38 @@ struct ImmediateDraw { // True to enable scissoring using the region defined by scissor_rect. bool scissor = false; - // Scissoring region in framebuffer pixels as (x, y, w, h). - int scissor_rect[4] = {0}; + // Scissoring region in the coordinate space (if right < left or bottom < top, + // not drawing). + float scissor_left = 0.0f; + float scissor_top = 0.0f; + float scissor_right = 0.0f; + float scissor_bottom = 0.0f; }; class ImmediateDrawer { public: + ImmediateDrawer(const ImmediateDrawer& immediate_drawer) = delete; + ImmediateDrawer& operator=(const ImmediateDrawer& immediate_drawer) = delete; + virtual ~ImmediateDrawer() = default; + void SetPresenter(Presenter* new_presenter); + // Creates a new texture with the given attributes and R8G8B8A8 data. virtual std::unique_ptr CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool is_repeated, const uint8_t* data) = 0; - // Begins drawing in immediate mode using the given projection matrix. - virtual void Begin(int render_target_width, int render_target_height) = 0; + // Begins drawing in immediate mode using the given projection matrix. The + // presenter that is currently attached to the immediate drawer, as the + // implementation may hold presenter-specific information such as UI + // submission indices. Pass 0 or a negative value as the coordinate space + // width or height to use raw render target pixel coordinates (or this will + // just be used as a safe fallback when with a non-zero-sized surface the + // coordinate space size becomes zero somehow). + virtual void Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height); // Starts a draw batch. virtual void BeginDrawBatch(const ImmediateDrawBatch& batch) = 0; // Draws one set of a batch. @@ -102,13 +119,33 @@ class ImmediateDrawer { // Ends a draw batch. virtual void EndDrawBatch() = 0; // Ends drawing in immediate mode and flushes contents. - virtual void End() = 0; + virtual void End(); protected: - ImmediateDrawer(GraphicsContext* graphics_context) - : graphics_context_(graphics_context) {} + ImmediateDrawer() = default; - GraphicsContext* graphics_context_ = nullptr; + Presenter* presenter() const { return presenter_; } + virtual void OnLeavePresenter() {} + virtual void OnEnterPresenter() {} + + // Available between Begin and End. + UIDrawContext* ui_draw_context() const { return ui_draw_context_; } + float coordinate_space_width() const { return coordinate_space_width_; } + float coordinate_space_height() const { return coordinate_space_height_; } + + // Converts and clamps the scissor in the immediate draw to render target + // coordinates. Returns whether the scissor contains any render target pixels + // (but a valid scissor is written even if false is returned). + bool ScissorToRenderTarget(const ImmediateDraw& immediate_draw, + uint32_t& out_left, uint32_t& out_top, + uint32_t& out_width, uint32_t& out_height); + + private: + Presenter* presenter_ = nullptr; + + UIDrawContext* ui_draw_context_ = nullptr; + float coordinate_space_width_; + float coordinate_space_height_; }; } // namespace ui diff --git a/src/xenia/ui/menu_item.cc b/src/xenia/ui/menu_item.cc index 5563b8760..225ca6444 100644 --- a/src/xenia/ui/menu_item.cc +++ b/src/xenia/ui/menu_item.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -62,9 +62,11 @@ void MenuItem::RemoveChild(MenuItem* child_item) { MenuItem* MenuItem::child(size_t index) { return children_[index].get(); } -void MenuItem::OnSelected(UIEvent* e) { +void MenuItem::OnSelected() { if (callback_) { callback_(); + // Note that this MenuItem might have been destroyed by the callback. + // Must not do anything with *this in this function from now on. } } diff --git a/src/xenia/ui/menu_item.h b/src/xenia/ui/menu_item.h index 8b61f040a..01bcbe5c5 100644 --- a/src/xenia/ui/menu_item.h +++ b/src/xenia/ui/menu_item.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -48,14 +48,18 @@ class MenuItem { const std::string& text() { return text_; } const std::string& hotkey() { return hotkey_; } + // If the menu is currently attached to a Window, changes to it (such as the + // elements and the enabled / disabled state) may be not reflected + // immediately - call Window::CompleteMainMenuItemsUpdate when the + // modifications are done. + void AddChild(MenuItem* child_item); void AddChild(std::unique_ptr child_item); void AddChild(MenuItemPtr child_item); void RemoveChild(MenuItem* child_item); MenuItem* child(size_t index); - virtual void EnableMenuItem(Window& window) = 0; - virtual void DisableMenuItem(Window& window) = 0; + virtual void SetEnabled(bool enabled) {} protected: MenuItem(Type type, const std::string& text, const std::string& hotkey, @@ -64,13 +68,17 @@ class MenuItem { virtual void OnChildAdded(MenuItem* child_item) {} virtual void OnChildRemoved(MenuItem* child_item) {} - virtual void OnSelected(UIEvent* e); + // This MenuItem may be destroyed as a result of the callback, don't do + // anything with it after the call. + void OnSelected(); Type type_; MenuItem* parent_item_; std::vector children_; std::string text_; std::string hotkey_; + + private: std::function callback_; }; diff --git a/src/xenia/ui/microprofile_drawer.cc b/src/xenia/ui/microprofile_drawer.cc index fb6588348..9680a492c 100644 --- a/src/xenia/ui/microprofile_drawer.cc +++ b/src/xenia/ui/microprofile_drawer.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,9 +10,10 @@ #include "xenia/ui/microprofile_drawer.h" #include +#include #include "xenia/base/math.h" -#include "xenia/ui/window.h" +#include "xenia/base/profiling.h" namespace xe { namespace ui { @@ -124,10 +125,8 @@ const uint8_t kFontData[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; -MicroprofileDrawer::MicroprofileDrawer(xe::ui::Window* window) - : window_(window), - graphics_context_(window->context()), - vertices_(kMaxVertices) { +MicroprofileDrawer::MicroprofileDrawer(ImmediateDrawer* immediate_drawer) + : immediate_drawer_(immediate_drawer), vertices_(kMaxVertices) { SetupFont(); } @@ -171,21 +170,21 @@ void MicroprofileDrawer::SetupFont() { } } - font_texture_ = graphics_context_->immediate_drawer()->CreateTexture( + font_texture_ = immediate_drawer_->CreateTexture( kFontTextureWidth, kFontTextureHeight, ImmediateTextureFilter::kNearest, false, reinterpret_cast(unpacked)); } -MicroprofileDrawer::~MicroprofileDrawer() = default; - -void MicroprofileDrawer::Begin() { - graphics_context_->immediate_drawer()->Begin(window_->scaled_width(), - window_->scaled_height()); +void MicroprofileDrawer::Begin(UIDrawContext& ui_draw_context, + uint32_t coordinate_space_width, + uint32_t coordinate_space_height) { + immediate_drawer_->Begin(ui_draw_context, float(coordinate_space_width), + float(coordinate_space_height)); } void MicroprofileDrawer::End() { Flush(); - graphics_context_->immediate_drawer()->End(); + immediate_drawer_->End(); } ImmediateVertex* MicroprofileDrawer::BeginVertices( @@ -203,7 +202,6 @@ ImmediateVertex* MicroprofileDrawer::BeginVertices( void MicroprofileDrawer::EndVertices() {} void MicroprofileDrawer::Flush() { - auto drawer = graphics_context_->immediate_drawer(); if (!vertex_count_) { return; } @@ -211,15 +209,15 @@ void MicroprofileDrawer::Flush() { ImmediateDrawBatch batch; batch.vertices = vertices_.data(); batch.vertex_count = vertex_count_; - drawer->BeginDrawBatch(batch); + immediate_drawer_->BeginDrawBatch(batch); ImmediateDraw draw; draw.primitive_type = current_primitive_type_; draw.count = vertex_count_; draw.texture = font_texture_.get(); - drawer->Draw(draw); + immediate_drawer_->Draw(draw); - drawer->EndDrawBatch(); + immediate_drawer_->EndDrawBatch(); vertex_count_ = 0; } @@ -323,8 +321,8 @@ void MicroprofileDrawer::DrawLine2D(uint32_t count, float* vertices, EndVertices(); } -void MicroprofileDrawer::DrawText(int x, int y, uint32_t color, - const char* text, int text_length) { +void MicroprofileDrawer::DrawTextString(int x, int y, uint32_t color, + const char* text, int text_length) { if (!text_length) { return; } diff --git a/src/xenia/ui/microprofile_drawer.h b/src/xenia/ui/microprofile_drawer.h index 1f285e1bc..5313935dd 100644 --- a/src/xenia/ui/microprofile_drawer.h +++ b/src/xenia/ui/microprofile_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,6 +10,7 @@ #ifndef XENIA_UI_MICROPROFILE_DRAWER_H_ #define XENIA_UI_MICROPROFILE_DRAWER_H_ +#include #include #include @@ -18,9 +19,6 @@ namespace xe { namespace ui { -class GraphicsContext; -class Window; - class MicroprofileDrawer { public: enum class BoxType { @@ -28,15 +26,17 @@ class MicroprofileDrawer { kFlat = 1, // MicroProfileBoxTypeFlat }; - MicroprofileDrawer(Window* window); - ~MicroprofileDrawer(); + // Initially hidden. + MicroprofileDrawer(ImmediateDrawer* immediate_drawer); - void Begin(); + void Begin(UIDrawContext& ui_draw_context, uint32_t coordinate_space_width, + uint32_t coordinate_space_height); void End(); void DrawBox(int x0, int y0, int x1, int y1, uint32_t color, BoxType type); void DrawLine2D(uint32_t count, float* vertices, uint32_t color); - void DrawText(int x, int y, uint32_t color, const char* text, - int text_length); + // The name DrawTextString collides with DrawText in Windows. + void DrawTextString(int x, int y, uint32_t color, const char* text, + int text_length); protected: void SetupFont(); @@ -46,8 +46,7 @@ class MicroprofileDrawer { void EndVertices(); void Flush(); - Window* window_ = nullptr; - GraphicsContext* graphics_context_ = nullptr; + ImmediateDrawer* immediate_drawer_; std::vector vertices_; int vertex_count_ = 0; diff --git a/src/xenia/ui/premake5.lua b/src/xenia/ui/premake5.lua index 540c27154..3b9e482c4 100644 --- a/src/xenia/ui/premake5.lua +++ b/src/xenia/ui/premake5.lua @@ -18,3 +18,8 @@ project("xenia-ui") filter("platforms:Android-*") -- Exports JNI functions. wholelib("On") + + filter("platforms:Windows") + links({ + "DXGI", + }) diff --git a/src/xenia/ui/presenter.cc b/src/xenia/ui/presenter.cc new file mode 100644 index 000000000..aef8f7309 --- /dev/null +++ b/src/xenia/ui/presenter.cc @@ -0,0 +1,1446 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/presenter.h" + +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" +#include "xenia/ui/window.h" + +#if XE_PLATFORM_WIN32 +#include "xenia/ui/window_win.h" +#endif + +// On Windows, InvalidateRect causes WM_PAINT to be sent quite quickly, so +// presenting from the thread refreshing the guest output is not absolutely +// necessary, but still may be nice for bypassing the scheduling and the +// message queue. +// On GTK, the frame rate of draw signals is limited to the display refresh rate +// internally, so for the lowest latency especially in case the refresh rates +// differ significantly on the guest and the host (like 30/60 Hz presented to +// 144 Hz), drawing from the guest output refreshing thread is highly desirable. +// Presenting directly from the GPU emulation thread also makes debugging GPU +// emulation easier with external tools, as presenting in most cases happens +// exactly between emulation frames. +DEFINE_bool( + host_present_from_non_ui_thread, true, + "Allow the GPU emulation thread to present the guest output to the host " + "surface directly instead of requesting the UI thread to do so through the " + "host window system.", + "Display"); + +DEFINE_bool( + present_render_pass_clear, true, + "On graphics backends where this is supported, use the clear render pass " + "load operation in presentation instead of clear commands clearing only " + "the letterbox area.", + "Display"); + +DEFINE_bool( + present_letterbox, true, + "Maintain aspect ratio when stretching by displaying bars around the image " + "when there's no more overscan area to crop out.", + "Display"); +// https://github.com/MonoGame/MonoGame/issues/4697#issuecomment-217779403 +// Using the value from DirectXTK (5% cropped out from each side, thus 90%), +// which is not exactly the Xbox One title-safe area, but close, and within the +// action-safe area: +// https://github.com/microsoft/DirectXTK/blob/1e80a465c6960b457ef9ab6716672c1443a45024/Src/SimpleMath.cpp#L144 +// XNA TitleSafeArea is 80%, but it's very conservative, designed for CRT, and +// is the title-safe area rather than the action-safe area. +// 90% is also exactly the fraction of 16:9 height in 16:10. +DEFINE_int32( + present_safe_area_x, 90, + "Percentage of the image width that can be kept when presenting to " + "maintain aspect ratio without letterboxing or stretching.", + "Display"); +DEFINE_int32( + present_safe_area_y, 90, + "Percentage of the image height that can be kept when presenting to " + "maintain aspect ratio without letterboxing or stretching.", + "Display"); + +namespace xe { +namespace ui { + +void Presenter::FatalErrorHostGpuLossCallback( + [[maybe_unused]] bool is_responsible, + [[maybe_unused]] bool statically_from_ui_thread) { + xe::FatalError("Graphics device lost (probably due to an internal error)"); +} + +Presenter::~Presenter() { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + +#if XE_PLATFORM_WIN32 + if (dxgi_ui_tick_thread_.joinable()) { + { + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_tick_thread_shutdown_ = true; + } + dxgi_ui_tick_control_condition_.notify_all(); + dxgi_ui_tick_thread_.join(); + } +#endif // XE_PLATFORM + + if (window_) { + Window* old_window = window_; + // Null the pointer to prevent an infinite loop between SetPresenter and + // SetWindowSurfaceFromUIThread calling each other. + window_ = nullptr; + old_window->SetPresenter(nullptr); + } +} + +void Presenter::SetWindowSurfaceFromUIThread(Window* new_window, + Surface* new_surface) { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + // There can't be a valid surface pointer without a window, as a surface is + // created and owned by the window. + assert_false(new_surface && !new_window); + + if (window_ == new_window && (!window_ || surface_ == new_surface)) { + // Nothing has changed (or a recursive SetWindowSurfaceFromUIThread > + // SetPresenter > SetWindowSurfaceFromUIThread call). + return; + } + + // Disconnect from the current surface. + if (surface_) { + // Take ownership of painting, and also stop accepting paint requests from + // the guest output thread - the window (which is required for making them) + // may be going away, and there will be a forced paint when the connection + // becomes available. + SetPaintModeFromUIThread(PaintMode::kNone); + DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + surface_ = nullptr; + UpdateSurfaceMonitorFromUIThread(true); + } + + if (window_ != new_window) { + // The window pointer may be accessed by the guest output thread if painting + // is possible (or was possible, but the paint attempt has resulted in the + // implementation reporting that the connection has become outdated). + // However, a painting connection is currently not established at all, so + // it's safe to modify the window pointer here. + + // Detach from the old window if attaching to a different one or just + // detaching. SetPresenter for the new window might have been called without + // it having been called with nullptr for the old window. + if (window_) { + Window* old_window = window_; + // Null the pointer to prevent an infinite loop between SetPresenter and + // SetWindowSurfaceFromUIThread calling each other. + window_ = nullptr; + old_window->SetPresenter(nullptr); + } + + // Attach to the new one. + // This function is called from SetPresenter - don't need to notify the + // window of this, as it itself has triggered this. + window_ = new_window; + } + + if (new_surface) { + assert_true(paint_mode_ == PaintMode::kNone); + surface_ = new_surface; + UpdateSurfaceMonitorFromUIThread(true); + assert_true(surface_paint_connection_state_ == + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + bool request_repaint; + UpdateSurfacePaintConnectionFromUIThread(&request_repaint, true); + // Request to paint as soon as possible in the UI thread if connected + // successfully. + if (request_repaint) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } +} + +void Presenter::OnSurfaceMonitorUpdateFromUIThread( + bool old_monitor_potentially_disconnected) { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + if (!surface_) { + return; + } + + UpdateSurfaceMonitorFromUIThread(old_monitor_potentially_disconnected); +} + +void Presenter::OnSurfaceResizeFromUIThread() { + // No intrusive lifetime management must be performed from UI drawers - defer + // it if needed. + assert_false(is_executing_ui_drawers_); + + if (!surface_) { + return; + } + + // Let the UI thread take ownership of painting (so the connection can be + // updated) in a smooth way - downgrade to kUIThreadOnRequest rather than + // kNone, because a forced repaint may not be necessary if, for example, the + // size internally turns out to be the same after the update, and in this case + // the current image may be kept - but the new one must not be missed either + // if it becomes available during the resize. + if (paint_mode_ == PaintMode::kGuestOutputThreadImmediately) { + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + } + + bool request_repaint; + UpdateSurfacePaintConnectionFromUIThread(&request_repaint, true); + + // Request to repaint as soon as possible in the UI thread if needed. + if (request_repaint) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } +} + +void Presenter::PaintFromUIThread(bool force_paint) { + // If there is no surface, this will be a no-op, nothing outdated, nothing to + // paint. However, an explicit monitor check is needed because UI framerate + // limiting may be tied to signals from the OS for the monitor - but painting + // may still occur, for instance, if drawing to a composition surface in the + // OS (which will still be live even if the window goes outside any monitor). + // But a surface check still won't cause harm, for simplicity. + if (!InSurfaceOnMonitorFromUIThread()) { + return; + } + + // Defer changes to the paint mode as well as window paint requests, and do + // them in this function so they're consistent with the assumptions made here. + assert_false(is_in_ui_thread_paint_); + is_in_ui_thread_paint_ = true; + request_guest_output_paint_after_current_ui_thread_paint_ = false; + request_ui_paint_after_current_ui_thread_paint_ = false; + + // Actualize the connection if the UI needs to be drawn if there was some + // explicit paint request (the guest output has been refreshed, and the guest + // output thread was asked not to present directly due as the UI needs to be + // drawn, or some surface state change has happened so the guest output needs + // to be displayed as soon as possible without waiting for the guest to + // refresh it, or the guest output thread has been notified that the + // connection has become outdated and has requested the UI thread to + // reconnect). + bool draw_ui = !ui_drawers_.empty(); + bool do_paint = force_paint || draw_ui; + // Reset ui_thread_paint_requested_ unconditionally also, regardless of + // whether the UI needs to be drawn - the flag may be set to try reconnecting, + // for example. + if (ui_thread_paint_requested_.exchange(false, std::memory_order_relaxed)) { + do_paint = true; + } + PaintResult paint_result = PaintResult::kNotPresented; + bool request_repaint_at_tick = false; + bool request_repaint_immediately = false; + if (do_paint) { + // Take ownership of painting if it's currently owned by the guest output + // thread (downgrade from kGuestOutputThreadImmediately to + // kUIThreadOnRequest - not to kNone so if during this paint a new guest + // output frame is generated, the notification will still be sent to the UI + // thread rather than dropped, so the frame won't be skipped). This is + // needed to be able not only to paint, but also to try to recover from an + // outdated surface. + if (paint_mode_ == PaintMode::kGuestOutputThreadImmediately) { + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + } + // Try to recover from the connection becoming outdated in the previous + // paint. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + UpdateSurfacePaintConnectionFromUIThread(nullptr, false); + } + // If still paintable or recovered successfully, paint. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable) { + // The paint mode might have been set to kNone when the connection was + // marked as outdated last time. Or, if wasn't reconnecting, there was + // some other incorrect situation that caused the paint mode to be set to + // kNone for an active connection. Make sure that the current paint mode + // is consistent with painting from the UI thread. + SetPaintModeFromUIThread(PaintMode::kUIThreadOnRequest); + + // Limit the frame rate of the UI, usually to the monitor refresh rate, + // in a way so that the UI won't be stealing all the remaining GPU + // resources if it's repainted continuously, and the window system itself + // doesn't limit the frame rate. + WaitForUITickFromUIThread(); + + paint_result = PaintAndPresent(draw_ui); + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + // Request another PaintFromUIThread which will try to recover from the + // outdated connection in the next frame (not immediately, so the + // windowing system has some time to prepare what may be required to + // recover from it, such as to send a resize event). + request_repaint_immediately = true; + } + } + // If can't paint anymore, notify the paint mode refresh below (which is not + // guaranteed to have access to have ownership of painting as it's taken + // here only conditionally, thus can't know whether the connection is + // actually in a paintable state). + if (surface_paint_connection_state_ != + SurfacePaintConnectionState::kConnectedPaintable) { + SetPaintModeFromUIThread(PaintMode::kNone); + } + } + + // Transfer the ownership of painting back to the guest output thread if it + // was taken or if needed for any reason (however, it's taken conditionally - + // no guarantees that the actual connection state is accessible here, so only + // checking whether the mode is not kNone currently, not the connection + // state), and overall synchronize the state taking into account both what has + // been done in this function and what could have been done by the UI drawer + // callbacks. + if (paint_mode_ != PaintMode::kNone) { + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread(true)); + } + is_in_ui_thread_paint_ = false; + + // Check if the device has been lost. There's no point in requesting repaint + // if it has happened anyway, it won't be possible to satisfy such request + // with the current Presenter. + if (paint_result == PaintResult::kGpuLostExternally || + paint_result == PaintResult::kGpuLostResponsible) { + if (host_gpu_loss_callback_) { + host_gpu_loss_callback_(paint_result == PaintResult::kGpuLostResponsible, + true); + } + // The loss callback might have destroyed the presenter, must not do + // anything with `this` anymore. + return; + } + + // Request refresh if needed. + // Can't check the exact paintability as the connection state may currently + // be owned by the guest output thread, so check conservatively via + // paint_mode_. + if (paint_mode_ != PaintMode::kNone) { + // Immediately paint the guest output if requested explicitly or if the UI + // has hidden itself. + if (request_guest_output_paint_after_current_ui_thread_paint_ || + (draw_ui && ui_drawers_.empty())) { + request_repaint_immediately = true; + } + if (request_ui_paint_after_current_ui_thread_paint_ && + !ui_drawers_.empty()) { + request_repaint_at_tick = true; + } + } + if (request_repaint_at_tick || request_repaint_immediately) { + RequestPaintOrConnectionRecoveryViaWindow(request_repaint_immediately); + } +} + +bool Presenter::RefreshGuestOutput( + uint32_t frontbuffer_width, uint32_t frontbuffer_height, + uint32_t screen_width, uint32_t screen_height, + std::function refresher) { + GuestOutputProperties& writable_properties = + guest_output_properties_[guest_output_mailbox_writable_]; + writable_properties.frontbuffer_width = frontbuffer_width; + writable_properties.frontbuffer_height = frontbuffer_height; + writable_properties.screen_width = screen_width; + writable_properties.screen_height = screen_height; + writable_properties.is_8bpc = false; + bool is_active = writable_properties.IsActive(); + if (is_active) { + if (!RefreshGuestOutputImpl(guest_output_mailbox_writable_, + frontbuffer_width, frontbuffer_height, + refresher, writable_properties.is_8bpc)) { + // If failed to refresh, don't send the currently writable image to the + // mailbox as it may be in an undefined state. Don't disable the guest + // output either though because the failure may be something transient. + return false; + } + guest_output_active_last_refresh_ = true; + } else { + // Request presenting a blank image if there was a true image previously, + // but not now. + if (!guest_output_active_last_refresh_) { + return false; + } + guest_output_active_last_refresh_ = false; + } + + // Make the new image the next to present on the host (the "ready" one), + // replacing the one already specified as the next (dropping it instead of + // enqueueing the new image after it) to achieve the lowest latency (also, + // after switching from UI thread painting to doing it in the guest output + // thread, will immediately recover to having the latest frame always sent to + // the host present call on the CPU and all frames reaching a present call). + uint32_t last_acquired_and_ready = + guest_output_mailbox_acquired_and_ready_.load(std::memory_order_relaxed); + // Desired acquired = current acquired (changed only by the consumers). + // Desired ready = current writable. + // memory_order_acq_rel to acquire the new writable image and to release the + // current one (to let the consumers take it, from ready to acquired). + while (!guest_output_mailbox_acquired_and_ready_.compare_exchange_weak( + last_acquired_and_ready, + (last_acquired_and_ready & 3) | (guest_output_mailbox_writable_ << 2), + std::memory_order_acq_rel, std::memory_order_relaxed)) { + } + // Now, it's known that `ready == writable` on the host presentation side. + // Take the next `writable` with this assumption about its current value in + // mind. + uint32_t last_acquired = last_acquired_and_ready & 3; + if (last_acquired == guest_output_mailbox_writable_) { + // The new image has already been acquired by the time the compare-exchange + // loop has finished (acquired == ready == currently writable). + // It's a valid situation from the ownership perspective, and the semantics + // of the weak compare-exchange explicitly permit spurious `false` results. + // (3 - a - b) % 3 cannot be used here, as (3 - a - a) % 3 results in `a` - + // the same index. + // Take any free image. Preferably using + 1, not ^ 1, so if the guest needs + // to await any GPU work referencing the image, it will wait for the frame 3 + // frames ago, not 2, if this happens repeatedly. + guest_output_mailbox_writable_ = (guest_output_mailbox_writable_ + 1) % 3; + } else { + // Take the image other than the last acquired one and the new one, + // currently not accessible to the host presentation. + guest_output_mailbox_writable_ = + (3 - last_acquired - guest_output_mailbox_writable_) % 3; + } + + // Trigger the presentation on the host. + PaintResult paint_result = PaintResult::kNotPresented; + { + std::lock_guard paint_mode_mutex_lock(paint_mode_mutex_); + switch (paint_mode_) { + case PaintMode::kNone: + // Neither painting nor window paint requesting is accessible. + break; + case PaintMode::kUIThreadOnRequest: + // Only window paint requesting is accessible. + RequestPaintOrConnectionRecoveryViaWindow(true); + break; + case PaintMode::kGuestOutputThreadImmediately: + // Both painting and window paint requesting are accessible. + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable) { + paint_result = PaintAndPresent(false); + if (surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedOutdated) { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } + break; + } + } + // Handle GPU loss when not in the middle of the function anymore, and + // lifecycle management from the GPU loss callback is fine on the UI thread. + if (host_gpu_loss_callback_) { + if (paint_result == PaintResult::kGpuLostResponsible) { + host_gpu_loss_callback_(true, false); + } else if (paint_result == PaintResult::kGpuLostExternally) { + host_gpu_loss_callback_(false, false); + } + } + + return is_active; +} + +void Presenter::SetGuestOutputPaintConfigFromUIThread( + const GuestOutputPaintConfig& new_config) { + // For simplicity, this may be called externally repeatedly. + // Lock the mutex only when something has been modified, and also don't + // request UI thread guest output redraws when not needed. + bool modified = false; + bool request_repaint = false; + if (guest_output_paint_config_.GetEffect() != new_config.GetEffect()) { + modified = true; + request_repaint = true; + } + if (guest_output_paint_config_.GetFsrSharpnessReduction() != + new_config.GetFsrSharpnessReduction()) { + modified = true; + if (new_config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + request_repaint = true; + } + } + if (guest_output_paint_config_.GetCasAdditionalSharpness() != + new_config.GetCasAdditionalSharpness()) { + modified = true; + if (new_config.GetEffect() == GuestOutputPaintConfig::Effect::kCas || + new_config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + request_repaint = true; + } + } + if (guest_output_paint_config_.GetDither() != new_config.GetDither()) { + modified = true; + request_repaint = true; + } + if (modified) { + { + std::unique_lock config_lock( + guest_output_paint_config_mutex_); + guest_output_paint_config_ = new_config; + } + // Coarsely check the availability of painting and of the window (for + // calling RequestPaint) via paint_mode_ because the actual painting + // connection state may currently be owned not by the UI thread. + if (request_repaint && paint_mode_ != PaintMode::kNone) { + if (is_in_ui_thread_paint_) { + // Defer until the end of the current paint if called from, for + // instance, a UI drawer. + request_guest_output_paint_after_current_ui_thread_paint_ = true; + } else { + RequestPaintOrConnectionRecoveryViaWindow(true); + } + } + } +} + +void Presenter::AddUIDrawerFromUIThread(UIDrawer* drawer, size_t z_order) { + assert_not_null(drawer); + // Obtain whether the iterator list was empty before erasing in case of + // replacing with a new entry with a different Z order happens. + bool drawers_were_empty = ui_drawers_.empty(); + uint64_t drawer_last_draw = UINT64_MAX; + // Check if already added. + for (auto it_existing = ui_drawers_.begin(); it_existing != ui_drawers_.end(); + ++it_existing) { + if (it_existing->second.drawer != drawer) { + continue; + } + if (it_existing->first == z_order) { + return; + } + // Keep the same last draw index to prevent the drawer from being executed + // twice if increasing its Z order during the drawer loop. + drawer_last_draw = it_existing->second.last_draw; + // If removing the drawer that is the next in the current drawer loop, skip + // it (in a multimap, only one element iterator is invalidated). + if (is_executing_ui_drawers_ && ui_draw_next_iterator_ == it_existing) { + ++ui_draw_next_iterator_; + } + ui_drawers_.erase(it_existing); + break; + } + auto it_new = + ui_drawers_.emplace(z_order, UIDrawerReference(drawer, drawer_last_draw)); + // If adding to the Z layer currently being processed (for drawing, from the + // lowest to the highest), or to layers in between the current and the + // previously next, make sure the new drawer is executed too. + if (is_executing_ui_drawers_ && z_order >= ui_draw_current_z_order_ && + (ui_draw_next_iterator_ == ui_drawers_.end() || + z_order < ui_draw_next_iterator_->first)) { + ui_draw_next_iterator_ = it_new; + } + HandleUIDrawersChangeFromUIThread(drawers_were_empty); +} + +void Presenter::RemoveUIDrawerFromUIThread(UIDrawer* drawer) { + assert_not_null(drawer); + for (auto it_existing = ui_drawers_.begin(); it_existing != ui_drawers_.end(); + ++it_existing) { + if (it_existing->second.drawer != drawer) { + continue; + } + // If removing the drawer that is the next in the current drawer loop, skip + // it (in a multimap, only one element iterator is invalidated). + if (is_executing_ui_drawers_ && ui_draw_next_iterator_ == it_existing) { + ++ui_draw_next_iterator_; + } + ui_drawers_.erase(it_existing); + HandleUIDrawersChangeFromUIThread(false); + return; + } +} + +void Presenter::RequestUIPaintFromUIThread() { + if (is_in_ui_thread_paint_) { + // The paint request will be done once in the end of PaintFromUIThread + // according to the actual state at the moment that happens. It's common for + // drawers to call this (even every frame), and no need to do too many OS + // paint request calls. + request_ui_paint_after_current_ui_thread_paint_ = true; + return; + } + // The connection state may be owned by the guest output thread now rather + // than the UI thread, check whether it's not pointless to make the request + // coarsely via paint_mode_. + if (!ui_drawers_.empty() && paint_mode_ != PaintMode::kNone) { + // The window must be present, otherwise the conditions wouldn't have been + // met. + window_->RequestPaint(); + } +} + +bool Presenter::InitializeCommonSurfaceIndependent() { + // Initialize UI frame rate limiting. +#if XE_PLATFORM_WIN32 + dxgi_ui_tick_thread_ = std::thread(&Presenter::DXGIUITickThread, this); +#endif // XE_PLATFORM + + return true; +} + +std::unique_lock Presenter::ConsumeGuestOutput( + uint32_t& mailbox_index_or_max_if_inactive_out, + GuestOutputProperties* properties_out, + GuestOutputPaintConfig* paint_config_out) { + if (paint_config_out) { + // Get the up-to-date guest output paint configuration settings set by the + // UI thread. + std::unique_lock config_lock(guest_output_paint_config_mutex_); + *paint_config_out = guest_output_paint_config_; + } + + // Lock the mutex to make sure the image that will be acquired now is owned + // exclusively by the calling thread for the time while this mutex is still + // locked (it needs to be held by the consumer while working with anything + // that depends on the image now being acquired or its index in the mailbox). + std::unique_lock consumer_lock( + guest_output_mailbox_consumer_mutex_); + // Acquire the up-to-date ready guest image (may be new, in this case the last + // acquired one will be released, or still the same or no refresh has happened + // since the last consumption). + // memory_order_relaxed here because the ready index from this load will be + // used directly only if it's the same as during the last consumption - thus + // the image has already been acquired previously, no need for + // memory_order_acquire (if the image has been acquired by a different + // consumer though, the consumer mutex performs memory access ordering). + uint32_t old_acquired_and_ready = + guest_output_mailbox_acquired_and_ready_.load(std::memory_order_relaxed); + // Desired acquired = current ready. + // Desired ready = current ready (changed only by the producer). + uint32_t desired_acquired_and_ready = + (old_acquired_and_ready & ~uint32_t(3)) | (old_acquired_and_ready >> 2); + // Either the same image as during the last consumption, or a new one, is + // satisfying. However, if it's new, using memory_order_acq_rel to acquire the + // new ready image (to make it acquired) and to release the old acquired image + // (to let the producer take it as writable). + while (old_acquired_and_ready != desired_acquired_and_ready && + !guest_output_mailbox_acquired_and_ready_.compare_exchange_weak( + old_acquired_and_ready, desired_acquired_and_ready, + std::memory_order_acq_rel, std::memory_order_relaxed)) { + desired_acquired_and_ready = + (old_acquired_and_ready & ~uint32_t(3)) | (old_acquired_and_ready >> 2); + } + uint32_t mailbox_index = desired_acquired_and_ready & 3; + // Give the current acquired image to the caller, or UINT32_MAX if it's + // inactive. + const GuestOutputProperties& properties = + guest_output_properties_[mailbox_index]; + mailbox_index_or_max_if_inactive_out = + properties.IsActive() ? mailbox_index : UINT32_MAX; + if (properties_out) { + *properties_out = properties; + } + return std::move(consumer_lock); +} + +Presenter::GuestOutputPaintFlow Presenter::GetGuestOutputPaintFlow( + const GuestOutputProperties& properties, uint32_t host_rt_width, + uint32_t host_rt_height, uint32_t max_rt_width, uint32_t max_rt_height, + const GuestOutputPaintConfig& config) const { + GuestOutputPaintFlow flow = {}; + + // FIXME(Triang3l): Configuration variables racing with per-game config + // loading. + + assert_not_zero(max_rt_width); + assert_not_zero(max_rt_height); + + // Initialize one clear rectangle for the case of drawing no guest output, for + // consistency with fewer state dependencies. + flow.letterbox_clear_rectangle_count = 1; + flow.letterbox_clear_rectangles[0].width = host_rt_width; + flow.letterbox_clear_rectangles[0].height = host_rt_height; + + // For safety such as division by zero prevention. + if (!properties.IsActive() || !host_rt_width || !host_rt_height || + !surface_width_in_paint_connection_ || + !surface_height_in_paint_connection_) { + return flow; + } + + flow.properties = properties; + + // Multiplication-division rounding to the nearest. + auto rescale_unsigned = [](uint32_t value, uint32_t new_scale, + uint32_t old_scale) -> uint32_t { + return uint32_t((uint64_t(value) * new_scale + (old_scale >> 1)) / + old_scale); + }; + auto rescale_signed = [](int32_t value, uint32_t new_scale, + uint32_t old_scale) -> int32_t { + // Plus old_scale / 2 for positive values, minus old_scale / 2 for + // negative values for consistent rounding for both positive and + // negative values (as the `/` operator rounds towards zero). + // Example: + // (-3 - 1) / 3 == -1 + // (-2 - 1) / 3 == -1 + // (-1 - 1) / 3 == 0 + // --- + // (0 + 1) / 3 == 0 + // (1 + 1) / 3 == 0 + // (2 + 1) / 3 == 1 + return int32_t((int64_t(value) * new_scale + + int32_t(old_scale >> 1) * (value < 0 ? -1 : 1)) / + old_scale); + }; + + // Final output location and dimensions. + // All host location calculations are DPI-independent, conceptually depending + // only on the aspect ratios, not the absolute values. + uint32_t output_width, output_height; + if (uint64_t(surface_width_in_paint_connection_) * properties.screen_height > + uint64_t(properties.screen_width) * surface_height_in_paint_connection_) { + // The window is wider that the source - crop along Y to preserve the aspect + // ratio while stretching throughout the entire surface's width, then limit + // the Y cropping via letterboxing or stretching along X. + uint32_t present_safe_area; + if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) { + present_safe_area = uint32_t(cvars::present_safe_area_y); + } else { + present_safe_area = 100; + } + // Scale the desired width by the H:W aspect ratio (inverse of W:H) to get + // the height. + output_height = + rescale_unsigned(surface_width_in_paint_connection_, + properties.screen_height, properties.screen_width); + bool letterbox = false; + if (output_height * present_safe_area > + surface_height_in_paint_connection_ * 100) { + // Don't crop out more than the safe area margin - letterbox or stretch. + output_height = rescale_unsigned(surface_height_in_paint_connection_, 100, + present_safe_area); + letterbox = true; + } + if (letterbox && cvars::present_letterbox) { + output_width = rescale_unsigned( + properties.screen_width, surface_height_in_paint_connection_ * 100, + properties.screen_height * present_safe_area); + // output_width might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_x = (int32_t(surface_width_in_paint_connection_) - + int32_t(output_width)) / + 2; + } else { + output_width = surface_width_in_paint_connection_; + flow.output_x = 0; + } + // output_height might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_y = (int32_t(surface_height_in_paint_connection_) - + int32_t(output_height)) / + 2; + } else { + // The window is taller that the source - crop along X to preserve the + // aspect ratio while stretching throughout the entire surface's height, + // then limit the X cropping via letterboxing or stretching along Y. + uint32_t present_safe_area; + if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) { + present_safe_area = uint32_t(cvars::present_safe_area_x); + } else { + present_safe_area = 100; + } + // Scale the desired height by the W:H aspect ratio to get the width. + output_width = + rescale_unsigned(surface_height_in_paint_connection_, + properties.screen_width, properties.screen_height); + bool letterbox = false; + if (output_width * present_safe_area > + surface_width_in_paint_connection_ * 100) { + // Don't crop out more than the safe area margin - letterbox or stretch. + output_width = rescale_unsigned(surface_width_in_paint_connection_, 100, + present_safe_area); + letterbox = true; + } + if (letterbox && cvars::present_letterbox) { + output_height = rescale_unsigned( + properties.screen_height, surface_width_in_paint_connection_ * 100, + properties.screen_width * present_safe_area); + // output_height might have been rounded up already by rescale_unsigned, + // so rounding down in this division. + flow.output_y = (int32_t(surface_height_in_paint_connection_) - + int32_t(output_height)) / + 2; + } else { + output_height = surface_height_in_paint_connection_; + flow.output_y = 0; + } + // output_width might have been rounded up already by rescale_unsigned, so + // rounding down in this division. + flow.output_x = + (int32_t(surface_width_in_paint_connection_) - int32_t(output_width)) / + 2; + } + + // Convert the location from surface pixels (which have 1:1 aspect ratio + // relatively to the physical display) to render target pixels (the render + // target size may be arbitrary with any aspect ratio, but if it's different + // than the surface size, the OS is expected to stretch it to the surface + // boundaries), preserving the aspect ratio. + if (host_rt_width != surface_width_in_paint_connection_) { + flow.output_x = rescale_signed(flow.output_x, host_rt_width, + surface_width_in_paint_connection_); + output_width = rescale_unsigned(output_width, host_rt_width, + surface_width_in_paint_connection_); + } + if (host_rt_height != surface_height_in_paint_connection_) { + flow.output_y = rescale_signed(flow.output_y, host_rt_height, + surface_height_in_paint_connection_); + output_height = rescale_unsigned(output_height, host_rt_height, + surface_height_in_paint_connection_); + } + + // The out-of-bounds checks are needed for correct letterbox calculations. + // Though this normally shouldn't happen, but in case of rounding issues with + // extreme values. + int32_t output_right = flow.output_x + int32_t(output_width); + int32_t output_bottom = flow.output_y + int32_t(output_height); + if (!output_width || !output_height || output_right <= 0 || + output_bottom <= 0 || flow.output_x >= int32_t(host_rt_width) || + flow.output_y >= int32_t(host_rt_height)) { + return flow; + } + + // The output image may have a part of it outside the final render target (if + // using the overscan area to stretch the image to the entire surface while + // preserving the guest aspect ratio if it differs from the host one, for + // instance). While the final render target size is known to be within the + // host render target / image size limit, the intermediate images may be + // larger than that as they include the overscan area that will be outside the + // screen. Make sure the intermediate images can't be larger than the maximum + // render target size. + uint32_t output_width_clamped = std::min(output_width, max_rt_width); + uint32_t output_height_clamped = std::min(output_height, max_rt_height); + + if (config.GetEffect() == GuestOutputPaintConfig::Effect::kCas || + config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr) { + // FidelityFX Super Resolution and Contrast Adaptive Sharpening only work + // good for up to 2x2 upscaling due to the way they fetch texels. + // CAS is primarily a sharpening filter, not an upscaling one (its upscaling + // eliminates reduces blurriness, but doesn't preserve the shapes of edges, + // and executing it multiple times will only result in oversharpening. So, + // using it for scales only of up to 2x2, then simply stretching with + // bilinear filtering. + // EASU of FSR, however, preserves edges, it's not supposed to blur them or + // to make them jagged, so it can be executed multiple times - running + // multiple EASU passes for scale factors of over 2x2. + // Just one EASU pass rather than multiple for scaling to factors bigger + // than 2x2 (especially significantly bigger, such as 1152x640 to 3840x2160, + // or 3.333x3.375) results in blurry edges and an overall noisy look, + // multiple passes improve visual stability. + std::pair ffx_last_size; + if (flow.effect_count) { + ffx_last_size = flow.effect_output_sizes[flow.effect_count - 1]; + } else { + ffx_last_size.first = properties.frontbuffer_width; + ffx_last_size.second = properties.frontbuffer_height; + } + if (config.GetEffect() == GuestOutputPaintConfig::Effect::kFsr && + (ffx_last_size.first < output_width_clamped || + ffx_last_size.second < output_height_clamped)) { + // AMD FidelityFX Super Resolution - upsample along at least one axis. + // Using the output size clamped to the maximum render target size here as + // EASU will always write to intermediate images, and RCAS supports only + // 1:1. + uint32_t easu_max_passes = config.GetFsrMaxUpsamplingPasses(); + uint32_t easu_pass_count = 0; + while (easu_pass_count < easu_max_passes && + (ffx_last_size.first < output_width_clamped || + ffx_last_size.second < output_height_clamped)) { + ffx_last_size.first = + std::min(ffx_last_size.first * uint32_t(2), output_width_clamped); + ffx_last_size.second = + std::min(ffx_last_size.second * uint32_t(2), output_height_clamped); + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kFsrEasu; + ++easu_pass_count; + } + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kFsrRcas; + } else { + // AMD FidelityFX Contrast Adaptive Sharpening - sharpen or downsample, or + // upsample up to 2x2 if CAS is specified to be used for upscaling too. + // Using the unclamped output size as CAS may be the last pass - if a + // bilinear pass is needed afterwards, and the CAS pass will be writing to + // an intermediate image, the CAS pass output size will be clamped while + // adding the bilinear stretch. + std::pair pre_cas_size = ffx_last_size; + ffx_last_size.first = + std::min(ffx_last_size.first * uint32_t(2), output_width); + ffx_last_size.second = + std::min(ffx_last_size.second * uint32_t(2), output_height); + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = ffx_last_size; + flow.effects[flow.effect_count++] = + ffx_last_size == pre_cas_size ? GuestOutputPaintEffect::kCasSharpen + : GuestOutputPaintEffect::kCasResample; + } + } + + std::pair* last_pre_bilinear_effect_size = + flow.effect_count ? &flow.effect_output_sizes[flow.effect_count - 1] + : nullptr; + if (!last_pre_bilinear_effect_size || + last_pre_bilinear_effect_size->first != output_width || + last_pre_bilinear_effect_size->second != output_height) { + // If not using FidelityFX, or it has reached its upscaling capabilities, + // but more is needed, stretch via bilinear filtering. + // Clamp the output size of the last effect to the maximum render target + // size because it will go to an intermediate image now. + if (last_pre_bilinear_effect_size) { + // RCAS only works for 1:1, clamping must be done explicitly for FSR. + assert_false(flow.effects[flow.effect_count - 1] == + GuestOutputPaintEffect::kFsrRcas && + (last_pre_bilinear_effect_size->first > max_rt_width || + last_pre_bilinear_effect_size->second > max_rt_height)); + last_pre_bilinear_effect_size->first = + std::min(last_pre_bilinear_effect_size->first, max_rt_width); + last_pre_bilinear_effect_size->second = + std::min(last_pre_bilinear_effect_size->second, max_rt_height); + } + assert_true(flow.effect_count < flow.effects.size()); + flow.effect_output_sizes[flow.effect_count] = + std::make_pair(output_width, output_height); + flow.effects[flow.effect_count++] = GuestOutputPaintEffect::kBilinear; + } + + assert_not_zero(flow.effect_count); + + if (config.GetDither()) { + // Dithering must be applied only to the final effect since resampling and + // sharpening filters may considering the dithering noise features and + // amplify it. + GuestOutputPaintEffect& last_effect = flow.effects[flow.effect_count - 1]; + switch (last_effect) { + case GuestOutputPaintEffect::kBilinear: + // Dithering has no effect for 1:1 copying of a 8bpc image. + if (!properties.is_8bpc || flow.effect_count > 1 || + output_width != properties.frontbuffer_width || + output_height != properties.frontbuffer_height) { + last_effect = GuestOutputPaintEffect::kBilinearDither; + } + break; + case GuestOutputPaintEffect::kCasSharpen: + last_effect = GuestOutputPaintEffect::kCasSharpenDither; + break; + case GuestOutputPaintEffect::kCasResample: + last_effect = GuestOutputPaintEffect::kCasResampleDither; + break; + case GuestOutputPaintEffect::kFsrRcas: + last_effect = GuestOutputPaintEffect::kFsrRcasDither; + break; + default: + break; + } + } + +#ifndef NDEBUG + for (size_t i = 0; i + 1 < flow.effect_count; ++i) { + assert_true(CanGuestOutputPaintEffectBeIntermediate(flow.effects[i])); + } + assert_true( + CanGuestOutputPaintEffectBeFinal(flow.effects[flow.effect_count - 1])); +#endif + + // Calculate the letterbox geometry. + if (flow.effect_count) { + flow.letterbox_clear_rectangle_count = 0; + uint32_t letterbox_mid_top = uint32_t(std::max(flow.output_y, int32_t(0))); + // Top. + if (letterbox_mid_top) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_top = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_top.x = 0; + letterbox_clear_rectangle_top.y = 0; + letterbox_clear_rectangle_top.width = host_rt_width; + letterbox_clear_rectangle_top.height = letterbox_mid_top; + } + uint32_t letterbox_mid_bottom = + std::min(uint32_t(output_bottom), host_rt_height); + uint32_t letterbox_mid_height = letterbox_mid_bottom - letterbox_mid_top; + // Middle-left. + if (flow.output_x > 0) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_left = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_left.x = 0; + letterbox_clear_rectangle_left.y = letterbox_mid_top; + letterbox_clear_rectangle_left.width = uint32_t(flow.output_x); + letterbox_clear_rectangle_left.height = letterbox_mid_height; + } + // Middle-right. + if (uint32_t(output_right) < host_rt_width) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_right = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_right.x = uint32_t(output_right); + letterbox_clear_rectangle_right.y = letterbox_mid_top; + letterbox_clear_rectangle_right.width = + host_rt_width - uint32_t(output_right); + letterbox_clear_rectangle_right.height = letterbox_mid_height; + } + // Bottom. + if (letterbox_mid_bottom < host_rt_height) { + assert_true(flow.letterbox_clear_rectangle_count < + flow.letterbox_clear_rectangles.size()); + GuestOutputPaintFlow::ClearRectangle& letterbox_clear_rectangle_top = + flow.letterbox_clear_rectangles + [flow.letterbox_clear_rectangle_count++]; + letterbox_clear_rectangle_top.x = 0; + letterbox_clear_rectangle_top.y = letterbox_mid_bottom; + letterbox_clear_rectangle_top.width = host_rt_width; + letterbox_clear_rectangle_top.height = + host_rt_height - letterbox_mid_bottom; + } + } + + return flow; +} + +void Presenter::ExecuteUIDrawersFromUIThread(UIDrawContext& ui_draw_context) { + // May be called by the implementations only when requested. + assert_true(is_in_ui_thread_paint_); + // Drawers can add or remove drawers (including themselves), need to ensure + // iterator validity in this case. + assert_false(is_executing_ui_drawers_); + ui_draw_next_iterator_ = ui_drawers_.begin(); + is_executing_ui_drawers_ = true; + while (ui_draw_next_iterator_ != ui_drawers_.end()) { + // The current iterator may be invalidated, and ui_draw_next_iterator_ may + // be changed, during the execution of the drawer if the list of the drawers + // is modified by it - don't assume that after the call + // ui_draw_next_iterator_ will be the same as + // std::next(ui_draw_next_iterator_) before it. + auto it_current = ui_draw_next_iterator_++; + // Don't draw twice if already drawn in this frame (may happen if the Z + // order of a drawer was increased from below the current one to above it by + // one of the drawers). + if (it_current->second.last_draw != ui_draw_current_) { + ui_draw_current_z_order_ = it_current->first; + it_current->second.last_draw = ui_draw_current_; + it_current->second.drawer->Draw(ui_draw_context); + } + } + is_executing_ui_drawers_ = false; + ++ui_draw_current_; +} + +void Presenter::SetPaintModeFromUIThread(PaintMode new_mode) { + // Can be modified only from the UI thread, so can skip locking if it's the + // same. + if (paint_mode_ == new_mode) { + return; + } + { + std::lock_guard lock(paint_mode_mutex_); + paint_mode_ = new_mode; + } + UpdateUITicksNeededFromUIThread(); +} + +Presenter::PaintMode Presenter::GetDesiredPaintModeFromUIThread( + bool is_paintable) const { + if (!is_paintable) { + // The only case when kNone can be returned, for surface connection updates + // when it's known that the UI thread currently has access to the connection + // lifecycle. + return PaintMode::kNone; + } + if (!cvars::host_present_from_non_ui_thread) { + return PaintMode::kUIThreadOnRequest; + } + if (surface_paint_connection_has_implicit_vsync_) { + // Don't be causing host vertical sync CPU waits in the thread generating + // the guest output. + return PaintMode::kUIThreadOnRequest; + } + if (!ui_drawers_.empty()) { + // The UI can be drawn only by the UI thread, and it needs to be drawn - + // paint in the UI thread. + return PaintMode::kUIThreadOnRequest; + } + // Only the guest output needs to be drawn - let the guest output thread + // present immediately for a lower latency. + return PaintMode::kGuestOutputThreadImmediately; +} + +void Presenter::DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState new_state) { + assert_false(IsConnectedSurfacePaintConnectionState(new_state)); + if (IsConnectedSurfacePaintConnectionState(surface_paint_connection_state_)) { + DisconnectPaintingFromSurfaceFromUIThreadImpl(); + } + surface_paint_connection_state_ = new_state; + surface_paint_connection_has_implicit_vsync_ = false; + surface_width_in_paint_connection_ = 0; + surface_height_in_paint_connection_ = 0; +} + +void Presenter::UpdateSurfacePaintConnectionFromUIThread( + bool* repaint_needed_out, bool update_paint_mode_to_desired) { + assert_not_null(surface_); + + // Validate that painting lifecycle is accessible by the UI thread currently, + // not given to the guest output thread. The mode can be modified only by + // the UI thread, so no need to lock the mutex. + assert_true(paint_mode_ != PaintMode::kGuestOutputThreadImmediately); + + // Initialize repaint_needed_out for failure cases. + if (repaint_needed_out) { + *repaint_needed_out = false; + } + + // If the connection state is kUnconnectedSurfaceReportedUnusable, the + // implementation has reported that the surface is not usable by the presenter + // at all, and it's pointless to retry connecting to it. + if (surface_paint_connection_state_ != + SurfacePaintConnectionState::kUnconnectedSurfaceReportedUnusable) { + uint32_t surface_width = 0, surface_height = 0; + bool surface_area_available = + surface_->GetSize(surface_width, surface_height); + if (!surface_area_available) { + // The surface is currently zero-area (or has become zero-area), try again + // when it's resized. + DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange); + } else { + bool is_reconnect = IsConnectedSurfacePaintConnectionState( + surface_paint_connection_state_); + bool is_vsync_implicit = false; + SurfacePaintConnectResult connect_result = + ConnectOrReconnectPaintingToSurfaceFromUIThread( + *surface_, surface_width, surface_height, + surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable, + is_vsync_implicit); + switch (connect_result) { + case SurfacePaintConnectResult::kSuccess: + if (repaint_needed_out) { + *repaint_needed_out = true; + } + // Fallthrough to common success handling. + case SurfacePaintConnectResult::kSuccessUnchanged: + // Don't know yet what the first result was (success or suboptimal). + surface_paint_connection_was_optimal_at_successful_paint_ = false; + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedPaintable; + surface_paint_connection_has_implicit_vsync_ = is_vsync_implicit; + surface_width_in_paint_connection_ = surface_width; + surface_height_in_paint_connection_ = surface_height; + if (!is_reconnect) { + *repaint_needed_out = true; + } + break; + case SurfacePaintConnectResult::kFailure: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange; + break; + case SurfacePaintConnectResult::kFailureSurfaceUnusable: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedSurfaceReportedUnusable; + break; + } + } + } + + if (update_paint_mode_to_desired) { + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread( + surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable)); + } +} + +bool Presenter::RequestPaintOrConnectionRecoveryViaWindow( + bool force_ui_thread_paint_tick) { + // Can be called from any thread if an existing window_ is available in it, + // and it's known to have a Surface that will be the same throughout this + // call - not doing any checks whether this request can be satisfied + // theoretically. For safety, check whether the window exists unconditionally. + assert_not_null(window_); + assert_not_null(surface_); + if (ui_thread_paint_requested_.exchange(true, std::memory_order_relaxed)) { + // Invalidation pending already, no need to do it twice. + return false; + } + if (force_ui_thread_paint_tick) { + ForceUIThreadPaintTick(); + } + window_->RequestPaint(); + return true; +} + +void Presenter::UpdateSurfaceMonitorFromUIThread( + bool old_monitor_potentially_disconnected) { + // For dropping the monitor when the window is closing and is losing its + // surface, the existence of `surface_` (which implies that `window_` exists + // too) must be the condition for a non-null monitor, not just the existence + // of `window_`. +#if XE_PLATFORM_WIN32 + HMONITOR surface_new_win32_monitor = nullptr; + if (surface_) { + HWND hwnd = static_cast(window_)->hwnd(); + // The HWND may be non-existent if the window has been closed and destroyed + // (the HWND, not the xe::ui::Window) already. + if (hwnd) { + surface_new_win32_monitor = + MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); + } + } + if (old_monitor_potentially_disconnected || + surface_win32_monitor_ != surface_new_win32_monitor) { + surface_win32_monitor_ = surface_new_win32_monitor; + if (dxgi_ui_tick_factory_ && !dxgi_ui_tick_factory_->IsCurrent()) { + // If a monitor has been newly connected, it won't appear in the old + // factory, need to recreate it. + { + Microsoft::WRL::ComPtr old_factory_output_to_release; + { + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + old_factory_output_to_release = std::move(dxgi_ui_tick_output_); + } + } + dxgi_ui_tick_factory_.Reset(); + } + if (!dxgi_ui_tick_factory_) { + if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_ui_tick_factory_)))) { + XELOGE("Presenter: Failed to create a DXGI factory"); + } + } + Microsoft::WRL::ComPtr new_dxgi_output; + if (dxgi_ui_tick_factory_ && surface_new_win32_monitor) { + new_dxgi_output = GetDXGIOutputForMonitor(dxgi_ui_tick_factory_.Get(), + surface_new_win32_monitor); + } + // If the adapter was recreated, and the old output was released before its + // destruction, notifying is still required - the vertical blank wait thread + // might have entered the condition variable wait already as the output was + // null. + bool signal_dxgi_ui_tick_control; + { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + bool dxgi_output_was_null = (dxgi_ui_tick_output_ == nullptr); + dxgi_ui_tick_output_ = new_dxgi_output; + signal_dxgi_ui_tick_control = + dxgi_output_was_null && AreDXGIUITicksWaitable(dxgi_ui_tick_lock); + } + if (signal_dxgi_ui_tick_control) { + dxgi_ui_tick_control_condition_.notify_all(); + } + } +#endif // XE_PLATFORM +} + +bool Presenter::InSurfaceOnMonitorFromUIThread() const { + if (!surface_) { + return false; + } +#if XE_PLATFORM_WIN32 + return surface_win32_monitor_ != nullptr; +#else + return true; +#endif // XE_PLATFORM +} + +Presenter::PaintResult Presenter::PaintAndPresent(bool execute_ui_drawers) { + assert_false(execute_ui_drawers && !is_in_ui_thread_paint_); + assert_true(surface_paint_connection_state_ == + SurfacePaintConnectionState::kConnectedPaintable); + PaintResult result = PaintAndPresentImpl(execute_ui_drawers); + switch (result) { + case PaintResult::kPresented: + surface_paint_connection_was_optimal_at_successful_paint_ = true; + break; + case PaintResult::kPresentedSuboptimal: + // Make outdated if previously optimal, now suboptimal, but don't cause + // the connection to become outdated if it has been suboptimal from the + // very beginning. + if (surface_paint_connection_was_optimal_at_successful_paint_) { + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedOutdated; + } + break; + case PaintResult::kNotPresentedConnectionOutdated: + surface_paint_connection_state_ = + SurfacePaintConnectionState::kConnectedOutdated; + break; + default: + // Another issue not directly related to the surface connection. + break; + } + return result; +} + +void Presenter::HandleUIDrawersChangeFromUIThread(bool drawers_were_empty) { + if (is_in_ui_thread_paint_) { + // Defer the refresh so no dangerous lifecycle-related changes happen during + // drawing. + if (!ui_drawers_.empty()) { + request_ui_paint_after_current_ui_thread_paint_ = true; + } + return; + } + + if (paint_mode_ == PaintMode::kNone) { + // Not connected, no point in refreshing (checking a more conservative + // paint_mode_ because the actual connection state may currently be owned by + // the guest output thread instead) or in toggling the ownership (the rest + // of the function can assume it's not kNone). + return; + } + + if (ui_drawers_.empty() != drawers_were_empty) { + // Require the UI thread to paint if it needs the UI, or let the guest + // output thread paint immediately if not. + SetPaintModeFromUIThread(GetDesiredPaintModeFromUIThread(true)); + // Make sure the ticks for limiting the UI frame rate are sent. + UpdateUITicksNeededFromUIThread(); + } + + // Request painting so the changes to the UI drawer list are reflected as + // quickly as possible. + // RequestUIPaintFromUIThread is not enough, because a paint request is also + // needed if disabling the UI, to force paint a frame without the UI as soon + // as possible - it can't be dropped if ui_drawers_ is empty. + // The coarse painting availability (and thus the availability of `window_`, + // which is required for the paint mode to be anything else than kNone) has + // already been checked above. + ForceUIThreadPaintTick(); + window_->RequestPaint(); +} + +void Presenter::UpdateUITicksNeededFromUIThread() { +#if XE_PLATFORM_WIN32 + bool new_needed = AreUITicksNeededFromUIThread(); + if (dxgi_ui_ticks_needed_ == new_needed) { + return; + } + bool signal_dxgi_ui_tick_control; + { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_ticks_needed_ = new_needed; + signal_dxgi_ui_tick_control = AreDXGIUITicksWaitable(dxgi_ui_tick_lock); + } + if (signal_dxgi_ui_tick_control) { + dxgi_ui_tick_control_condition_.notify_all(); + } +#endif +} + +void Presenter::WaitForUITickFromUIThread() { +#if XE_PLATFORM_WIN32 + if (!AreUITicksNeededFromUIThread()) { + return; + } + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + uint64_t last_vblank_before_wait = dxgi_ui_tick_last_vblank_; + while (true) { + // Guest output present requests should interrupt the wait as quickly as + // possible as they should be fulfilled as early as possible. + if (dxgi_ui_tick_force_requested_) { + dxgi_ui_tick_force_requested_ = false; + return; + } + if (!AreDXGIUITicksWaitable(dxgi_ui_tick_lock)) { + return; + } + if (dxgi_ui_tick_last_vblank_ > dxgi_ui_tick_last_draw_) { + // If there have been multiple vblanks during the wait for some reason, + // next time draw the UI immediately. + dxgi_ui_tick_last_draw_ = std::min(last_vblank_before_wait + uint64_t(1), + dxgi_ui_tick_last_vblank_); + return; + } + dxgi_ui_tick_signal_condition_.wait(dxgi_ui_tick_lock); + } +#endif // XE_PLATFORM +} + +void Presenter::ForceUIThreadPaintTick() { +#if XE_PLATFORM_WIN32 + std::scoped_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + dxgi_ui_tick_force_requested_ = true; +#endif // XE_PLATFORM +} + +#if XE_PLATFORM_WIN32 +Microsoft::WRL::ComPtr Presenter::GetDXGIOutputForMonitor( + IDXGIFactory1* factory, HMONITOR monitor) { + Microsoft::WRL::ComPtr adapter; + for (UINT adapter_index = 0; SUCCEEDED(factory->EnumAdapters( + adapter_index, adapter.ReleaseAndGetAddressOf())); + ++adapter_index) { + Microsoft::WRL::ComPtr output; + for (UINT output_index = 0; + SUCCEEDED(adapter->EnumOutputs(output_index, &output)); + ++output_index) { + DXGI_OUTPUT_DESC output_desc; + if (SUCCEEDED(output->GetDesc(&output_desc)) && + output_desc.Monitor == monitor) { + return std::move(output); + } + } + } + return nullptr; +} + +void Presenter::DXGIUITickThread() { + std::unique_lock dxgi_ui_tick_lock(dxgi_ui_tick_mutex_); + while (true) { + if (dxgi_ui_tick_thread_shutdown_) { + return; + } + if (!AreDXGIUITicksWaitable(dxgi_ui_tick_lock)) { + dxgi_ui_tick_control_condition_.wait(dxgi_ui_tick_lock); + continue; + } + // Wait for vertical blank, with the mutex unlocked (holding a new reference + // to the current output while it's happening) so subscribers can still do + // early-out checks. + bool wait_succeeded; + { + Microsoft::WRL::ComPtr dxgi_output = dxgi_ui_tick_output_; + dxgi_ui_tick_lock.unlock(); + wait_succeeded = SUCCEEDED(dxgi_ui_tick_output_->WaitForVBlank()); + } + dxgi_ui_tick_lock.lock(); + if (wait_succeeded) { + ++dxgi_ui_tick_last_vblank_; + } else { + // Lost the ability to wait for a vertical blank on this output, notify + // the waiting threads, and wait for a new one. + dxgi_ui_tick_output_.Reset(); + } + dxgi_ui_tick_signal_condition_.notify_all(); + } +} +#endif // XE_PLATFORM + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/presenter.h b/src/xenia/ui/presenter.h new file mode 100644 index 000000000..9e89c8573 --- /dev/null +++ b/src/xenia/ui/presenter.h @@ -0,0 +1,1034 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_PRESENTER_H_ +#define XENIA_UI_PRESENTER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/byte_order.h" +#include "xenia/base/cvar.h" +#include "xenia/base/math.h" +#include "xenia/base/platform.h" +#include "xenia/ui/surface.h" +#include "xenia/ui/ui_drawer.h" + +#if XE_PLATFORM_WIN32 +// Must be included before DXGI for things like NOMINMAX, and also needed for +// Windows handle types. +#include "xenia/base/platform_win.h" + +#include +#include +#endif // XE_PLATFORM + +// For implementation use. +DECLARE_bool(present_render_pass_clear); + +namespace xe { +namespace ui { + +class Presenter; +class Window; +class Win32Window; + +class UIDrawContext { + public: + UIDrawContext(const UIDrawContext& context) = delete; + UIDrawContext& operator=(const UIDrawContext& context) = delete; + virtual ~UIDrawContext() = default; + + Presenter& presenter() const { return presenter_; } + + // It's assumed that the render target size will be either equal to the size + // of the surface, or the render target will be stretched to cover the entire + // surface (not in the corner of the surface). + uint32_t render_target_width() const { return render_target_width_; } + uint32_t render_target_height() const { return render_target_height_; } + + protected: + explicit UIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height) + : presenter_(presenter), + render_target_width_(render_target_width), + render_target_height_(render_target_height) {} + + private: + Presenter& presenter_; + uint32_t render_target_width_; + uint32_t render_target_height_; +}; + +struct RawImage { + uint32_t width = 0; + uint32_t height = 0; + size_t stride = 0; + // R8 G8 B8 X8. The last row is not required to be padded to the stride. + std::vector data; +}; + +// The presenter displays up to two layers of content on a host surface: +// - Guest output image, focusing on lowering latency and maintaining stable +// frame pacing, with various scaling and sharpening methods and letterboxing; +// - Xenia's internal UI (such as the profiler and Dear ImGui). +// +// The guest output image may be refreshed from any thread generating it +// (usually the GPU emulation thread), as long as there are no multiple threads +// doing that simultaneously (since that would functionally be a race condition +// even if refreshing is performed in a critical section). +// +// The UI overlays are managed entirely by the UI thread. +// +// Painting on the host surface may occur in two places: +// - If there are no UI overlays, painting of the guest output may be performed +// immediately from the thread refreshing it, to bypass the OS scheduling and +// event handling. This is especially important on platforms where the native +// surface paint event has a frame rate limit (such as the display refresh +// rate), and the limit may differ greatly from the guest frame rate (such as +// presenting a 30 or 60 FPS guest to a 144 Hz host surface). +// - If the UI overlays (owned by the UI thread) are present, painting of both +// the guest output (is available) and the UI is done exclusively from the +// platform paint event handler. The guest output without UI overlays may also +// be painted from the platform paint callback in certain cases, such as when +// an additional paint beyond the guest's frame rate may be needed (like when +// resizing the window), or when painting from the thread refreshing the guest +// output is undesirable (for instance, if it will result in waiting for host +// vertical sync in that thread too early if host vertical sync can't be +// disabled on the platform, blocking the next frame of GPU emulation). +// +// The composition of the guest and the UI is done by Xenia manually, as opposed +// to using platform functionality such as DirectComposition, in order to have +// more predictability of GPU queue scheduling, but primarily to be able to take +// advantage of independent host presentation where it's available, so variable +// refresh rate may be used where possible, and latency may be significantly +// reduced. Also, at least on some configurations (checked on Windows 11 21H2 on +// Nvidia GeForce GTX 1070 with driver version 472.12), when in borderless +// fullscreen, any composition causes the DXGI Present to wait for vertical sync +// on the GPU even if the sync interval 0 is specified. +// +// An intermediate image with the size requested by the guest is used for guest +// output in all cases. Even though it adds some GPU overhead, especially in the +// 1:1 size case, using it solves multiple issues: +// - Presentation may be done more often than by the guest. +// - There is clear separation between pre-scaling and mid- / post-scaling +// operations. The gamma ramp, for instance, may be applied before scaling, +// with one lookup per pixel rather than four with fetch4. +// - A simpler compute shader may be used instead of setting up the whole +// graphics pipeline for copying in the GPU command processor in all cases, +// while Direct3D 12 does not allow UAVs for swap chain buffers. +// +// The presenter limits the frame rate of the UI overlay (when possible) to a +// value that's ideally the refresh rate of the monitor containing the window if +// the platform's paint event doesn't have an internal limiter. However, where +// possible, the arrival of a new guest output image will interrupt the UI tick +// wait. +// +// Because the UI overlays preclude the possibility of presenting directly from +// the thread refreshing the guest output, and on some platforms, result in the +// frame rate limiting of paint events manifesting itself, there must be no +// persistent UI overlays that haven't been explicitly requested by the user. +// However, for temporary (primarily non-modal) UI elements such as various +// timed notifications, using the Presenter should be preferred to implementing +// them via overlaying native windows on top of the presentation surface on +// platforms where the concept of independent presentation exists, as multiple +// windows will result in native composition disabling it. +// +// The painting connection between the Presenter and the Surface can be managed +// only by the UI thread. However, the thread refreshing the guest output may +// still mark the current connection as outdated and ask the UI thread (by +// requesting painting) to try to recover - but the guest output refresh thread +// must not try to reconnect by itself, as methods of the Surface are available +// only to the UI thread. +class Presenter { + public: + // May be actually called on the UI thread even if statically_from_ui_thread + // is false, such as when the guest output is refreshed by the UI thread. + using HostGpuLossCallback = + std::function; + static void FatalErrorHostGpuLossCallback(bool is_responsible, + bool statically_from_ui_thread); + + class GuestOutputRefreshContext { + public: + GuestOutputRefreshContext(const GuestOutputRefreshContext& context) = + delete; + GuestOutputRefreshContext& operator=( + const GuestOutputRefreshContext& context) = delete; + virtual ~GuestOutputRefreshContext() = default; + + // Sets whether the source actually has no more than 8 bits of precision + // (though the image provided by the refresher may still have a higher + // storage precision). If never called, assuming it's false. + void SetIs8bpc(bool is_8bpc) { is_8bpc_out_ref_ = is_8bpc; } + + protected: + GuestOutputRefreshContext(bool& is_8bpc_out_ref) + : is_8bpc_out_ref_(is_8bpc_out_ref) { + is_8bpc_out_ref = false; + } + + private: + bool& is_8bpc_out_ref_; + }; + + class GuestOutputPaintConfig { + public: + enum class Effect { + kBilinear, + kCas, + // AMD FidelityFX Super Resolution upsampling, Contrast Adaptive + // Sharpening otherwise. + kFsr, + }; + + // This value is used as a lerp factor. + static constexpr float kCasAdditionalSharpnessMin = 0.0f; + static constexpr float kCasAdditionalSharpnessMax = 1.0f; + static constexpr float kCasAdditionalSharpnessDefault = 0.0f; + static_assert(kCasAdditionalSharpnessDefault >= + kCasAdditionalSharpnessMin && + kCasAdditionalSharpnessDefault <= kCasAdditionalSharpnessMax); + + // EASU (as well as CAS) is designed for scaling by factors of up to 2x2. + // Some sensible limit for unusual cases, when the game for some reason + // presents a very small back buffer. + // This is enough for 480p > 960p > 1920p > 3840p > 7680p (bigger than 8K, + // or 4320p). + static constexpr uint32_t kFsrMaxUpscalingPassesMax = 4; + + static constexpr float kFsrSharpnessReductionMin = 0.0f; + // "Values above 2.0 won't make a visible difference." + // https://raw.githubusercontent.com/GPUOpen-Effects/FidelityFX-FSR/master/docs/FidelityFX-FSR-Overview-Integration.pdf + static constexpr float kFsrSharpnessReductionMax = 2.0f; + static constexpr float kFsrSharpnessReductionDefault = 0.2f; + static_assert(kFsrSharpnessReductionDefault >= kFsrSharpnessReductionMin && + kFsrSharpnessReductionDefault <= kFsrSharpnessReductionMax); + + // In the sharpness setters, min / max with a constant as the first argument + // also drops NaNs. + + Effect GetEffect() const { return effect_; } + void SetEffect(Effect new_effect) { effect_ = new_effect; } + + float GetCasAdditionalSharpness() const { + return cas_additional_sharpness_; + } + void SetCasAdditionalSharpness(float new_cas_additional_sharpness) { + cas_additional_sharpness_ = std::min( + kCasAdditionalSharpnessMax, + std::max(kCasAdditionalSharpnessMin, new_cas_additional_sharpness)); + } + + uint32_t GetFsrMaxUpsamplingPasses() const { + return fsr_max_upsampling_passes_; + } + void SetFsrMaxUpsamplingPasses(uint32_t new_fsr_max_upsampling_passes) { + fsr_max_upsampling_passes_ = + std::min(kFsrMaxUpscalingPassesMax, + std::max(uint32_t(1), new_fsr_max_upsampling_passes)); + } + + // In stops. + float GetFsrSharpnessReduction() const { return fsr_sharpness_reduction_; } + void SetFsrSharpnessReduction(float new_fsr_sharpness_reduction) { + fsr_sharpness_reduction_ = std::min( + kFsrSharpnessReductionMax, + std::max(kFsrSharpnessReductionMin, new_fsr_sharpness_reduction)); + } + + // Very tiny effect, but highly noticeable, for instance, on the sky in the + // 4D5307E6 main menu (prominently in Custom Games, especially with FSR - + // banding around the clouds can be clearly seen without dithering with 8bpc + // final host output). + bool GetDither() const { return dither_; } + void SetDither(bool new_dither) { dither_ = new_dither; } + + private: + // Tools, rather than the emulator itself, must use kBilinear as the image + // must be as close to the original front buffer as possible. + Effect effect_ = Effect::kBilinear; + float cas_additional_sharpness_ = kCasAdditionalSharpnessDefault; + uint32_t fsr_max_upsampling_passes_ = kFsrMaxUpscalingPassesMax; + float fsr_sharpness_reduction_ = kFsrSharpnessReductionDefault; + bool dither_ = false; + }; + + Presenter(const Presenter& presenter) = delete; + Presenter& operator=(const Presenter& presenter) = delete; + virtual ~Presenter(); + + virtual Surface::TypeFlags GetSupportedSurfaceTypes() const = 0; + + // For calling from the Window for the Presenter attached to it. + // May be called from the destructor of the presenter through the window. + void SetWindowSurfaceFromUIThread(Window* new_window, Surface* new_surface); + void OnSurfaceMonitorUpdateFromUIThread( + bool old_monitor_potentially_disconnected); + void OnSurfaceResizeFromUIThread(); + + // For calling from the platform paint event handler. Refreshes the surface + // connection if needed, and also paints if possible and if needed (if there + // are no UI overlays, and the guest output is presented directly from the + // thread refreshing it, the paint may be skipped unless there has been an + // explicit request previously or force_paint is true). If painting happens, + // both the guest output and the UI overlays (if any are active) are drawn. + // The background / letterbox of the painted context will be black - windows + // should preferably have a black background before a Presenter is attached to + // them too. + void PaintFromUIThread(bool force_paint = false); + + // Pass 0 as width or height to disable guest output until the next refresh + // with an actual size. The callback will receive a backend-specific context, + // and will not be called in case of an error such as the wrong size, or if + // guest output is disabled. Returns whether the callback was called and it + // returned true. The callback must submit all updating work to the host GPU + // before successfully returning, and also signal all the GPU synchronization + // primitives required by the GuestOutputRefreshContext implementation. + bool RefreshGuestOutput( + uint32_t frontbuffer_width, uint32_t frontbuffer_height, + uint32_t screen_width, uint32_t screen_height, + std::function refresher); + // The implementation must be callable from any thread, including from + // multiple at the same time, and it should acquire the latest guest output + // image via ConsumeGuestOutput. + virtual bool CaptureGuestOutput(RawImage& image_out) = 0; + const GuestOutputPaintConfig& GetGuestOutputPaintConfigFromUIThread() const { + return guest_output_paint_config_; + } + // For simplicity, may be called repeatedly even if no changes have been made. + void SetGuestOutputPaintConfigFromUIThread( + const GuestOutputPaintConfig& new_config); + + void AddUIDrawerFromUIThread(UIDrawer* drawer, size_t z_order); + void RemoveUIDrawerFromUIThread(UIDrawer* drawer); + + // Requests (re)painting with the UI if there's UI to draw. + void RequestUIPaintFromUIThread(); + + protected: + enum class PaintResult { + kPresented, + kPresentedSuboptimal, + // Refused for internal reasons or a host API side failure, but still may + // try to present without resetting the graphics provider in the future. + kNotPresented, + kNotPresentedConnectionOutdated, + kGpuLostExternally, + kGpuLostResponsible, + }; + + enum class SurfacePaintConnectResult { + // Redrawing not necessary, nothing changed. Must not be returned for a new + // connection (when was previously disconnected from the surface). + kSuccessUnchanged, + kSuccess, + kFailure, + kFailureSurfaceUnusable, + }; + + static constexpr uint32_t kGuestOutputMailboxSize = 3; + + struct GuestOutputProperties { + // At least any value being 0 here means the guest output is disabled for + // this frame. + uint32_t frontbuffer_width; + uint32_t frontbuffer_height; + // Guest screen size (primarily for the target aspect ratio, which may be + // different than that of the frontbuffer). + uint32_t screen_width; + uint32_t screen_height; + bool is_8bpc; + + GuestOutputProperties() { SetToInactive(); } + + bool IsActive() const { + return frontbuffer_width && frontbuffer_height && screen_width && + screen_height; + } + + void SetToInactive() { + frontbuffer_width = 0; + frontbuffer_height = 0; + screen_width = 0; + screen_height = 0; + is_8bpc = false; + } + }; + + enum class GuestOutputPaintEffect { + kBilinear, + kBilinearDither, + kCasSharpen, + kCasSharpenDither, + kCasResample, + kCasResampleDither, + kFsrEasu, + kFsrRcas, + kFsrRcasDither, + + kCount, + }; + + static constexpr bool CanGuestOutputPaintEffectBeIntermediate( + GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + // Dithering is never performed in intermediate passes because it may be + // interpreted as features by the subsequent passes. + case GuestOutputPaintEffect::kBilinearDither: + case GuestOutputPaintEffect::kCasSharpenDither: + case GuestOutputPaintEffect::kCasResampleDither: + case GuestOutputPaintEffect::kFsrRcasDither: + return false; + default: + // The result of any other effect can be stretched with bilinear + // filtering to the final resolution. + return true; + }; + } + + static constexpr bool CanGuestOutputPaintEffectBeFinal( + GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kFsrEasu: + return false; + default: + return true; + }; + } + + // The longest path is kFsrMaxUpscalingPassesMax + optionally RCAS + + // optionally bilinear, when upscaling by more than + // 2^kFsrMaxUpscalingPassesMax along any direction. + // Non-FSR paths are either only bilinear, only CAS, or (when upscaling by + // more than 2 along any direction) CAS followed by bilinear. + static constexpr size_t kMaxGuestOutputPaintEffects = + GuestOutputPaintConfig::kFsrMaxUpscalingPassesMax + 2; + + struct GuestOutputPaintFlow { + // Letterbox on up to 4 sides. + static constexpr size_t kMaxClearRectangles = 4; + + struct ClearRectangle { + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + }; + + GuestOutputProperties properties; + + // If 0, don't display the guest output. + size_t effect_count; + std::array effects; + std::array, kMaxGuestOutputPaintEffects> + effect_output_sizes; + + // Offset of the rectangle for final drawing to the host window with + // letterboxing. + int32_t output_x; + int32_t output_y; + + // If there is guest output (effect_count is not 0), contains the letterbox + // rectangles around the guest output. + size_t letterbox_clear_rectangle_count; + std::array letterbox_clear_rectangles; + + void GetEffectInputSize(size_t effect_index, uint32_t& width_out, + uint32_t& height_out) const { + assert_true(effect_index < effect_count); + if (!effect_index) { + width_out = properties.frontbuffer_width; + height_out = properties.frontbuffer_height; + return; + } + const std::pair& intermediate_size = + effect_output_sizes[effect_index - 1]; + width_out = intermediate_size.first; + height_out = intermediate_size.second; + } + + void GetEffectOutputOffset(size_t effect_index, int32_t& x_out, + int32_t& y_out) const { + assert_true(effect_index < effect_count); + if (effect_index + 1 < effect_count) { + x_out = 0; + y_out = 0; + return; + } + x_out = output_x; + y_out = output_y; + } + }; + + struct BilinearConstants { + int32_t output_offset[2]; + float output_size_inv[2]; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + output_size_inv[0] = 1.0f / float(output_size.first); + output_size_inv[1] = 1.0f / float(output_size.second); + } + }; + + static constexpr float CalculateCasPostSetupSharpness(float sharpness) { + // CasSetup const1.x. + return -1.0f / (8.0f - 3.0f * sharpness); + } + + struct CasSharpenConstants { + int32_t output_offset[2]; + float sharpness_post_setup; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + sharpness_post_setup = + CalculateCasPostSetupSharpness(config.GetCasAdditionalSharpness()); + } + }; + + struct CasResampleConstants { + int32_t output_offset[2]; + // Input size / output size. + float input_output_size_ratio[2]; + float sharpness_post_setup; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + uint32_t input_width, input_height; + flow.GetEffectInputSize(effect_index, input_width, input_height); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + input_output_size_ratio[0] = + float(input_width) / float(output_size.first); + input_output_size_ratio[1] = + float(input_height) / float(output_size.second); + sharpness_post_setup = + CalculateCasPostSetupSharpness(config.GetCasAdditionalSharpness()); + } + }; + + struct FsrEasuConstants { + // No output offset because the EASU pass is always done to an intermediate + // framebuffer. + float input_output_size_ratio[2]; + float input_size_inv[2]; + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index) { + uint32_t input_width, input_height; + flow.GetEffectInputSize(effect_index, input_width, input_height); + const std::pair& output_size = + flow.effect_output_sizes[effect_index]; + input_output_size_ratio[0] = + float(input_width) / float(output_size.first); + input_output_size_ratio[1] = + float(input_height) / float(output_size.second); + input_size_inv[0] = 1.0f / float(input_width); + input_size_inv[1] = 1.0f / float(input_height); + } + }; + + struct FsrRcasConstants { + int32_t output_offset[2]; + float sharpness_post_setup; + + static float CalculatePostSetupSharpness(float sharpness_reduction_stops) { + // FsrRcasCon const0.x. + return std::exp2f(-sharpness_reduction_stops); + } + + void Initialize(const GuestOutputPaintFlow& flow, size_t effect_index, + const GuestOutputPaintConfig& config) { + flow.GetEffectOutputOffset(effect_index, output_offset[0], + output_offset[1]); + sharpness_post_setup = + CalculatePostSetupSharpness(config.GetFsrSharpnessReduction()); + } + }; + + explicit Presenter(HostGpuLossCallback host_gpu_loss_callback) + : host_gpu_loss_callback_(host_gpu_loss_callback) {} + + // Must be called by the implementation's initialization, before the presenter + // is used for anything. + bool InitializeCommonSurfaceIndependent(); + + // ConnectOrReconnect and Disconnect are callable only by the UI thread and + // only when it has access to painting (PaintMode is not + // kGuestOutputThreadImmediately). + // Called only for a non-zero-area surface potentially supporting painting via + // the presenter. In case of a failure, internally no resources referencing + // the surface must be held by the implementation anymore - the implementation + // must be left in the same state as after + // DisconnectPaintingFromSurfaceFromUIThreadImpl. If the call is successful, + // the implementation must write to is_vsync_implicit_out whether the + // connection will now have vertical sync forced by the host window system, + // which may cause undesirable waits on the CPU when beginning or ending + // frames. + virtual SurfacePaintConnectResult + ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) = 0; + // Releases resources referencing the surface in the implementation if they + // are held by it. Call through DisconnectPaintingFromSurfaceFromUIThread to + // ensure the implementation is only called while the connection is active. + virtual void DisconnectPaintingFromSurfaceFromUIThreadImpl() = 0; + + // The returned lock interlocks multiple consumers (but not the producer and + // the consumer) and must be held while accessing implementation-specific + // objects that depend on the image or its index in the mailbox (unless there + // are other locking mechanisms involved for the resources, such as reference + // counting for the guest output images, which doesn't have to be atomic + // though for the reason described later in this paragraph, or assumptions + // like of main target painting being possible only in at most one thread at + // once). While this lock is held, the currently acquired image index can't be + // changed (by other consumers advancing the acquired image index to the new + // ready image index), so the image with the index given by this function + // can't be released and be made writable or given to a different consumer + // (thus it's owned exclusively by the consumer who has called this function). + // The properties are returned by copy rather than returning a pointer to them + // or asking the consumer to pull them for the current mailbox index, so there + // are less things to take into consideration while leaving the guest output + // consumer critical section earlier (as if a pointer was returned, the data + // behind it could be overwritten at any time after leaving the consumer + // critical section) if the implementation has its own synchronization + // mechanisms that allow for doing so as described earlier. Returns UINT32_MAX + // as the mailbox index if the image is inactive (if it's active, it has + // proper properties though). + [[nodiscard]] std::unique_lock ConsumeGuestOutput( + uint32_t& mailbox_index_or_max_if_inactive_out, + GuestOutputProperties* properties_out, + GuestOutputPaintConfig* paint_config_out); + // The properties are passed explicitly, not taken from the current acquired + // image, so it can be called for a copy of the acquired image's properties + // outside the consumer lock if the implementation has its own synchronization + // (like reference counting for the guest output images) that makes it + // possible to leave the consumer critical section earlier. Also, the guest + // output paint configuration is passed explicitly too so calling this + // function multiple times is safer. + GuestOutputPaintFlow GetGuestOutputPaintFlow( + const GuestOutputProperties& properties, uint32_t host_rt_width, + uint32_t host_rt_height, uint32_t max_rt_width, uint32_t max_rt_height, + const GuestOutputPaintConfig& config) const; + // is_8bpc_out_ref is where to write whether the source actually has no more + // than 8 bits of precision per channel (though the image provided by the + // refresher may still have a higher storage precision) - if not written, it + // will be assumed to be false. + virtual bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) = 0; + + // For guest output capturing (for debugging use thus - shouldn't be adding + // any noise like dithering that's not present in the original image), + // converting a 10bpc RGB pixel to 8bpc that can be stored in common image + // formats. + static uint32_t Packed10bpcRGBTo8bpcBytes(uint32_t rgb10) { + // Conversion almost according to the Direct3D 10+ rules (unorm > float > + // unorm), but with one multiplication rather than separate division and + // multiplication - the results are the same for unorm10 to unorm8. + if constexpr (std::endian::native == std::endian::big) { + return (uint32_t(float(rgb10 & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 24) | + (uint32_t(float((rgb10 >> 10) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 16) | + (uint32_t(float((rgb10 >> 20) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 8) | + uint32_t(0xFF); + } + return uint32_t(float(rgb10 & 0x3FF) * (255.0f / 1023.0f) + 0.5f) | + (uint32_t(float((rgb10 >> 10) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 8) | + (uint32_t(float((rgb10 >> 20) & 0x3FF) * (255.0f / 1023.0f) + 0.5f) + << 16) | + (uint32_t(0xFF) << 24); + } + + // Paints and presents the guest output if available (or just solid black + // color), and if requested, the UI on top of it. + // + // May be called from the non-UI thread, but only to paint the guest output + // (no UI drawing, with execute_ui_drawers disabled). + // + // Call via PaintAndPresent. + virtual PaintResult PaintAndPresentImpl(bool execute_ui_drawers) = 0; + + // For calling from the painting implementations if requested. + void ExecuteUIDrawersFromUIThread(UIDrawContext& ui_draw_context); + + private: + enum class PaintMode { + // Don't paint at all. + // Painting lifecycle is accessible only by the UI thread. + // window_->RequestPaint() must not be called in this mode at all regardless + // of whether the Window object exists because the Window object in this + // case may correspond to a window without a paintable Surface (in a closed + // state, or in the middle of a surface change), and non-UI threads (such as + // the guest output thread) may result in a race condition internally inside + // Window::RequestPaint during the access to the Window's state, such as the + // availability of the Surface that can handle the paint (therefore, if + // there's no Surface, this is the only valid mode). + kNone, + // Guest output refreshing notifies the `window_`, which must be valid and + // safe to call RequestPaint for, that painting should be done in the UI + // thread (including the UI if needed). Painting is possible, and painting + // lifecycle is accessible, only by the UI thread. + kUIThreadOnRequest, + // Paint immediately in the guest output thread for lower latency. The + // `window_`, however, may be notified that the surface painting connection + // has become outdated (via RequestPaint, as in this case the UI thread will + // need to repaint as sooner as possible after reconnecting anyway), and + // change the surface connection state accordingly (only to + // kConnectedOutdated). + // Painting is possible only by the guest output thread, lifecycle + // management cannot be done from the UI thread until it takes over. + kGuestOutputThreadImmediately, + }; + + enum class SurfacePaintConnectionState { + // No surface at all, or couldn't connect with the current state of the + // surface (such as because the surface was zero-sized because the window + // was minimized, for example). Or, the connection has become outdated, and + // the attempt to reconnect at kRetryConnectingSoon has failed. Try to + // reconnect if anything changes in the state of the surface, such as its + // size. + kUnconnectedRetryAtStateChange, + // Can't connect to the current existing surface (the surface has been lost + // or it's completely incompatible). No point in retrying connecting until + // the surface is replaced. + kUnconnectedSurfaceReportedUnusable, + // Everything is fine, can paint. The connection might have become + // suboptimal though, and haven't tried refreshing yet, but still usable for + // painting nonetheless. + kConnectedPaintable, + // The implementation still holds resources associated with the connection, + // but presentation has reported that it has become outdated, try + // reconnecting as soon as possible (at the next paint attempt, requesting + // it if needed). This is the only state that the guest output thread may + // transition the connection to (from kConnectedPaintable only) if it has + // access to painting (the paint mode is kGuestOutputThreadImmediately). + kConnectedOutdated, + }; + + static constexpr bool IsConnectedSurfacePaintConnectionState( + SurfacePaintConnectionState connection_state) { + return connection_state == + SurfacePaintConnectionState::kConnectedPaintable || + connection_state == SurfacePaintConnectionState::kConnectedOutdated; + } + + struct UIDrawerReference { + UIDrawer* drawer; + uint64_t last_draw; + + explicit UIDrawerReference(UIDrawer* drawer, + uint64_t last_draw = UINT64_MAX) + : drawer(drawer), last_draw(last_draw) {} + }; + + void SetPaintModeFromUIThread(PaintMode new_mode); + // Based on conditions like whether UI needs to be drawn and whether vertical + // sync is implicit - see the implementation for the requirements. + // is_paintable is an explicit parameter because this function may be called + // in two scenarios: + // - After connection updates - painting connection is owned by the UI thread, + // so the actual state can be obtained and passed here so kNone can be + // returned. + // - When merely toggling something local to the UI thread - only to toggle + // between the two threads, but not to switch from or to kNone (make sure + // it's not kNone before calling), pass `true` in this case. + PaintMode GetDesiredPaintModeFromUIThread(bool is_paintable) const; + + // Callable only by the UI thread and only when it has access to painting + // (PaintMode is not kGuestOutputThreadImmediately). + // This can be called to a surface after having not been connected to any (in + // this case, surface_paint_connection_state_ must be + // kUnconnectedRetryAtStateChange, not kUnconnectedNoUsableSurface, otherwise + // the call will be dropped), or to handle surface state changes such as + // resizing. However, this must not be called to change directly from one + // surface to another - need to disconnect prior to that, because the + // implementation may assume that the surface is still the same, and may try + // to, for instance, resize the buffers for the existing surface. + void UpdateSurfacePaintConnectionFromUIThread( + bool* repaint_needed_out, bool update_paint_mode_to_desired); + // Callable only by the UI thread and only when it has access to painting + // (PaintMode is not kGuestOutputThreadImmediately). + // See DisconnectPaintingFromSurfaceFromUIThreadImpl for more information. + void DisconnectPaintingFromSurfaceFromUIThread( + SurfacePaintConnectionState new_state); + + // Can be called from any thread if an existing window_ safe to RequestPaint + // (not closed) is available in it, so doesn't check the surface painting + // connection state. Returns whether the window_->RequestPaint() call has been + // made. + bool RequestPaintOrConnectionRecoveryViaWindow( + bool force_ui_thread_paint_tick); + + // Platform-specific function refreshing the monitor the current window + // surface is on, through the Surface or its Window. A reference to the + // monitor is held only when a Surface is available, so it's automatically + // dropped when the Window loses its Surface when it's being closed (but the + // Window object keeps being attached to the Presenter), for instance. + void UpdateSurfaceMonitorFromUIThread( + bool old_monitor_potentially_disconnected); + // Platform-specific function returning whether the surface the presenter is + // currently attached it is actually visible on any monitor. UI thread + // painting may be dropped if this returns false - need to request painting if + // the surface appears on a monitor again. May be using the state cached at + // window / surface state changes, not the actual state from the platform. + bool InSurfaceOnMonitorFromUIThread() const; + + // Calls PaintAndPresentImpl and does post-paint checks that are safe to do on + // both the UI thread and the guest output thread. See the information about + // PaintAndPresentImpl for details. + // A kPresentedSuboptimal result is returned as is, but the connection may or + // may not be made outdated if that happens - though if it's + // kPresentedSuboptimal rather than kNotPresentedConnectionOutdated, the image + // has been successfully sent to the OS presentation at least. + PaintResult PaintAndPresent(bool execute_ui_drawers); + + void HandleUIDrawersChangeFromUIThread(bool drawers_were_empty); + + bool AreUITicksNeededFromUIThread() const { + // UI drawing should be done, and painting needs to be possible (coarsely + // checking because the actual connection state, including outdated, may be + // currently unavailable from the UI thread). + // There's no need to limit the frame rate manually if there is vertical + // sync in the presentation already as that might result in inconsistent + // frame pacing and potentially skipped vertical sync intervals. + return !ui_drawers_.empty() && paint_mode_ != PaintMode::kNone && + !surface_paint_connection_has_implicit_vsync_; + } + void UpdateUITicksNeededFromUIThread(); + void WaitForUITickFromUIThread(); + // May be called from any thread. + void ForceUIThreadPaintTick(); + + // Must be called only in the end of entry points - reinitialization of the + // presenter may be done by the handler if it was called from the UI thread + // (even if the UI thread argument is false - such as when the guest output is + // refreshed on the UI thread). + HostGpuLossCallback host_gpu_loss_callback_; + + // May be accessed by the guest output thread if the paint mode is not kNone, + // to request painting (for kUIThreadOnRequest) or reconnection (for + // kGuestOutputThreadImmediately) in the UI thread. Set the paint mode to + // kNone before modifying (that naturally has to be done anyway by + // disconnecting painting). + Window* window_ = nullptr; + + // The surface of the `window_` the presenter is currently attached to. + Surface* surface_ = nullptr; + + // Mutex protecting paint_mode_ (and, in the guest output thread, objects + // related to painting themselves). + // + // The UI thread (as the mode is modifiable only by it) can use it as + // "barriers", like: + // 1) If needed, lock and disable guest output thread access to painting. + // 2) Interact with the painting connection. + // 3) If needed, lock and re-enable guest output thread access to the + // painting. + // + // On the other hand, the guest output thread _must_ hold it all the time it's + // painting, to ensure the mode stays the same while it's painting. + std::mutex paint_mode_mutex_; + // UI thread: writable, guest output thread: read-only. + PaintMode paint_mode_ = PaintMode::kNone; + + // These fields can be accessed _exclusively_ by either the UI thread or the + // guest output thread, depending on paint_mode_. + // If it's kGuestOutputThreadImmediately, they can be accessed _only_ by the + // guest output thread (though the UI thread can still read, but not modify, + // fields that are writable by the UI thread and readadable by both). + // Otherwise, they can be accessed _only_ by the UI thread. + // The connection state may be changed from the guest output thread, but only + // from kConnectedPaintable to kConnectedOutdated. + SurfacePaintConnectionState surface_paint_connection_state_ = + SurfacePaintConnectionState::kUnconnectedRetryAtStateChange; + // If the surface connection was optimal at the last paint attempt, but now + // has become suboptimal, need to try to reconnect. But only in this case - if + // the connection has been suboptimal from the very beginning don't try to + // reconnect every frame. + bool surface_paint_connection_was_optimal_at_successful_paint_ = false; + + // Modifiable only by the UI thread (therefore can be accessed by the UI + // thread regardless of the paint mode) while (re)connecting painting to the + // surface. + bool surface_paint_connection_has_implicit_vsync_ = false; + // Modifiable only by the UI thread, can be read by the thread that's + // painting. + uint32_t surface_width_in_paint_connection_ = 0; + uint32_t surface_height_in_paint_connection_ = 0; + + // Can be set by both the UI thread and the guest output thread before doing + // window_->RequestPaint() - whether an extra painting (preceded by + // reconnection if needed, and painting) was requested, primarily after some + // state change that may effect the surface painting connection, resulting in + // the need to refresh it as soon as possible. + // + // Relaxed memory order is enough, everything that may influence painting is + // either local to the UI thread or protected with barriers elsewhere. + // + // There's no need to bother about resetting this variable when losing + // connection as the next successful reconnection should be followed by a + // repaint request anyway. + std::atomic ui_thread_paint_requested_{false}; + + std::mutex guest_output_paint_config_mutex_; + // UI thread: writable, guest output thread: read-only. + GuestOutputPaintConfig guest_output_paint_config_; + + // Single-producer-multiple-consumers (lock-free SPSC + consumer lock) mailbox + // for presenting of the most up-to-date guest output image without long + // interlocking between guest output refreshing and painting. + static_assert(kGuestOutputMailboxSize == 3); + // The "acquired" image (in bits 0:1) is the one that is currently being read, + // or was last read, by a consumer of the guest output. The index of it can be + // modified only by the consumer and stays the same while it's processing the + // image. + // The "ready" image (in bits 2:3) is the most up-to-date image that the + // refresher has completely written, and a consumer may acquire it. It may be + // == acquired if there has been no refresh since the last acquisition. + // These two images can be accessed by painting in parallel, in an unordered + // way, with guest output refreshing. + std::atomic guest_output_mailbox_acquired_and_ready_{0}; + // The "writable" image is different than both "acquired" and "ready" and is + // accessible only by the guest output refreshing - it's the image that the + // refresher may write to. + uint32_t guest_output_mailbox_writable_ = 1; + // The guest output images may be consumed by two operations - painting, and + // capturing to a CPU-side buffer. These two usually never happen in parallel + // in reality though, as they're usually not even needed both at once in the + // same app within Xenia, so there's no need to create any + // complex lock-free synchronization between the two, but still, the situation + // when multiple consumers want the guest output image at the same is + // perfectly valid (unlike for producers, because even with a producer lock + // that would still be a race condition since the two refreshes themselves + // will be done in an undefined order) - so, a sufficient synchronization + // mechanism is used to make sure multiple consumers can acquire images + // without interfering with each other. + // While this is held, paint_mode_mutex_ must not be locked (the lock order is + // the reverse when painting in the guest output thread - painting is done + // with paint_mode_mutex_ held in this case, and guest output consumption + // happens as part of painting. + std::mutex guest_output_mailbox_consumer_mutex_; + + std::array + guest_output_properties_; + // Accessible only by refreshing, whether the last refresh contained an image + // rather than being blank. + bool guest_output_active_last_refresh_ = false; + + // Ordered by the Z order, and then by the time of addition. + // Note: All the iteration logic involving this Z ordering must be the same as + // in input handling (in the input listeners in the Window), but in reverse. + std::multimap ui_drawers_; + + size_t ui_draw_current_ = 0; + size_t ui_draw_current_z_order_; + std::multimap::iterator ui_draw_next_iterator_; + bool is_executing_ui_drawers_ = false; + + // Whether currently running the logic of PaintFromUIThread, so certain + // actions (such as changing the paint mode, requesting a redraw) must be + // deferred and be handled by the tail of PaintFromUIThread for consistency + // with what PaintFromUIThread does internally. + bool is_in_ui_thread_paint_ = false; + bool request_guest_output_paint_after_current_ui_thread_paint_; + bool request_ui_paint_after_current_ui_thread_paint_; + + // Platform-specific, but implementation-agnostic parts, primarily for + // limiting of the frame rate of the UI to avoid drawing the UI at extreme + // frame rates wasting the CPU and the GPU resources and starving everything + // else. The waits performed here must be interruptible by guest output + // presentation requests to prevent adding arbitrary amounts of latency to it. + // On GTK, this is not needed, the frame rate of draw signals is limited to + // the display refresh rate internally. +#if XE_PLATFORM_WIN32 + static Microsoft::WRL::ComPtr GetDXGIOutputForMonitor( + IDXGIFactory1* factory, HMONITOR monitor); + bool AreDXGIUITicksWaitable( + [[maybe_unused]] const std::unique_lock& dxgi_ui_tick_lock) { + return dxgi_ui_ticks_needed_ && !dxgi_ui_tick_thread_shutdown_ && + dxgi_ui_tick_output_; + } + void DXGIUITickThread(); + + // Accessible only from the UI thread, to avoid updating monitor-dependent + // information such as the DXGI output if the monitor hasn't actually been + // changed in the current state change (such as window positioning changes). + HMONITOR surface_win32_monitor_ = nullptr; + + // Requiring the lowest version of DXGI for IDXGIOutput::WaitForVBlank, which + // is available even on Windows Vista, but for IDXGIFactory1::IsCurrent, + // DXGI 1.1 is needed (available starting from Windows 7; also mixing DXGI 1.0 + // and 1.1+ in the Direct3D 12 code is not supported, see CreateDXGIFactory on + // MSDN). The factory is created when it's needed, and may be released and + // recreated when it's not current anymore and that becomes relevant. + Microsoft::WRL::ComPtr dxgi_ui_tick_factory_; + + // Accessible only from the UI thread, though the value is taken from the + // tick-mutex-protected variable. + uint64_t dxgi_ui_tick_last_draw_ = 0; + + std::mutex dxgi_ui_tick_mutex_; + uint64_t dxgi_ui_tick_last_vblank_ = 1; + // If output is null or shutdown is true, the signal may not be sent, either + // don't limit the frame rate in this case (an exceptional situation, such as + // a failure to find the output in DXGI), or don't draw at all if the window + // was removed from a connected monitor. + Microsoft::WRL::ComPtr dxgi_ui_tick_output_; + // To avoid allocating processing resources to the thread when nothing needs + // the ticks (not drawing the UI), the thread waits for vertical blanking + // intervals only when the UI drawing ticks are needed, and sleeping waiting + // for the control condition variable signals otherwise. Modifiable only from + // the UI thread, so readable by it without locking the mutex. + bool dxgi_ui_ticks_needed_ = false; + // The shutdown flag is modifiable only from the UI thread. + bool dxgi_ui_tick_thread_shutdown_ = false; + bool dxgi_ui_tick_force_requested_ = false; + + std::condition_variable dxgi_ui_tick_control_condition_; + // May be signaled by guest output refreshing. + std::condition_variable dxgi_ui_tick_signal_condition_; + + std::thread dxgi_ui_tick_thread_; +#endif // XE_PLATFORM +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_PRESENTER_H_ diff --git a/src/xenia/ui/renderdoc_api.cc b/src/xenia/ui/renderdoc_api.cc new file mode 100644 index 000000000..7c5f7ef99 --- /dev/null +++ b/src/xenia/ui/renderdoc_api.cc @@ -0,0 +1,76 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/renderdoc_api.h" + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" + +#if XE_PLATFORM_LINUX +#include +#elif XE_PLATFORM_WIN32 +#include "xenia/base/platform_win.h" +#endif + +namespace xe { +namespace ui { + +bool RenderdocApi::Initialize() { + Shutdown(); + pRENDERDOC_GetAPI get_api = nullptr; + // The RenderDoc library should be already loaded into the process if + // RenderDoc is attached - this is why RTLD_NOLOAD or GetModuleHandle instead + // of LoadLibrary. +#if XE_PLATFORM_LINUX +#if XE_PLATFORM_ANDROID + const char* librenderdoc_name = "libVkLayer_GLES_RenderDoc.so"; +#else + const char* librenderdoc_name = "librenderdoc.so"; +#endif + library_ = dlopen(librenderdoc_name, RTLD_NOW | RTLD_NOLOAD); + if (library_) { + get_api = pRENDERDOC_GetAPI(dlsym(library_, "RENDERDOC_GetAPI")); + } +#elif XE_PLATFORM_WIN32 + library_ = GetModuleHandleA("renderdoc.dll"); + if (library_) { + get_api = pRENDERDOC_GetAPI( + GetProcAddress(HMODULE(library_), "RENDERDOC_GetAPI")); + } +#endif + if (!get_api) { + Shutdown(); + return false; + } + // get_api will be null if RenderDoc is not attached, or the API isn't + // available on this platform, or there was an error. + if (!get_api || !get_api(eRENDERDOC_API_Version_1_0_0, (void**)&api_1_0_0_) || + !api_1_0_0_) { + Shutdown(); + return false; + } + XELOGI("RenderDoc API initialized"); + return true; +} + +void RenderdocApi::Shutdown() { + api_1_0_0_ = nullptr; + if (library_) { +#if XE_PLATFORM_LINUX + dlclose(library_); +#endif + // Not calling FreeLibrary on Windows as GetModuleHandle doesn't increment + // the reference count. + library_ = nullptr; + } +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/renderdoc_api.h b/src/xenia/ui/renderdoc_api.h new file mode 100644 index 000000000..1a07fe116 --- /dev/null +++ b/src/xenia/ui/renderdoc_api.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_RENDERDOC_API_H_ +#define XENIA_UI_RENDERDOC_API_H_ + +#include "third_party/renderdoc/renderdoc_app.h" + +namespace xe { +namespace ui { + +class RenderdocApi { + public: + RenderdocApi() = default; + RenderdocApi(const RenderdocApi& renderdoc_api) = delete; + RenderdocApi& operator=(const RenderdocApi& renderdoc_api) = delete; + ~RenderdocApi() { Shutdown(); } + + bool Initialize(); + void Shutdown(); + + // nullptr if not attached. + const RENDERDOC_API_1_0_0* api_1_0_0() const { return api_1_0_0_; } + + private: + void* library_ = nullptr; + const RENDERDOC_API_1_0_0* api_1_0_0_ = nullptr; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_RENDERDOC_API_H_ \ No newline at end of file diff --git a/src/xenia/ui/shaders/bytecode/.clang-format b/src/xenia/ui/shaders/bytecode/.clang-format index e3845288a..9d159247d 100644 --- a/src/xenia/ui/shaders/bytecode/.clang-format +++ b/src/xenia/ui/shaders/bytecode/.clang-format @@ -1 +1,2 @@ DisableFormat: true +SortIncludes: false diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h new file mode 100644 index 000000000..3c22503d1 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_dither_ps.h @@ -0,0 +1,1226 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeBilinearConstants +// { +// +// int2 xe_bilinear_output_offset; // Offset: 0 Size: 8 +// float2 xe_bilinear_output_size_inv;// Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_texture texture float3 2d T0 t0 1 +// XeBilinearConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 2 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +utof r0.zw, r0.xxxy +add r0.zw, r0.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000) +mul r0.zw, r0.zzzw, CB0[0][0].zzzw +sample_l r1.xyz, r0.zwzz, T0[0].xyzw, S0[0], l(0.000000) +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 11 instruction slots used +#endif + +const BYTE guest_output_bilinear_dither_ps[] = +{ + 68, 88, 66, 67, 238, 251, + 7, 36, 12, 102, 119, 199, + 78, 59, 74, 185, 195, 243, + 55, 64, 1, 0, 0, 0, + 56, 21, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 68, 2, 0, 0, 120, 2, + 0, 0, 172, 2, 0, 0, + 156, 20, 0, 0, 82, 68, + 69, 70, 8, 2, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 224, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 180, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 66, 105, 108, 105, 110, + 101, 97, 114, 67, 111, 110, + 115, 116, 97, 110, 116, 115, + 0, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 116, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 152, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 188, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 98, 105, 108, 105, 110, + 101, 97, 114, 95, 111, 117, + 116, 112, 117, 116, 95, 111, + 102, 102, 115, 101, 116, 0, + 105, 110, 116, 50, 0, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 110, 1, 0, 0, + 120, 101, 95, 98, 105, 108, + 105, 110, 101, 97, 114, 95, + 111, 117, 116, 112, 117, 116, + 95, 115, 105, 122, 101, 95, + 105, 110, 118, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 232, 17, + 0, 0, 81, 0, 0, 0, + 122, 4, 0, 0, 106, 8, + 0, 1, 53, 24, 0, 0, + 2, 4, 0, 0, 132, 131, + 131, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 132, 131, 131, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 90, 0, 0, 6, 70, 110, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 63, + 0, 0, 0, 63, 56, 0, + 0, 9, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 0, 0, 0, 0, + 166, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 6, 144, 144, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 11, 0, + 0, 0, 2, 0, 0, 0, + 0, 1, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h similarity index 53% rename from src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h index b0ff6436a..c12024a7a 100644 --- a/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_bilinear_ps.h @@ -5,10 +5,11 @@ // // Buffer Definitions: // -// cbuffer XeStretchGammaRootConstants +// cbuffer XeBilinearConstants // { // -// float xe_gamma_ramp_inv_size; // Offset: 0 Size: 4 +// int2 xe_bilinear_output_offset; // Offset: 0 Size: 8 +// float2 xe_bilinear_output_size_inv;// Offset: 8 Size: 8 // // } // @@ -19,8 +20,7 @@ // ------------------------------ ---------- ------- ----------- ------- -------------- ------ // xe_sampler_linear_clamp sampler NA NA S0 s0 1 // xe_texture texture float3 2d T0 t0 1 -// xe_gamma_ramp texture float3 1d T1 t1 1 -// XeStretchGammaRootConstants cbuffer NA NA CB0 cb0 1 +// XeBilinearConstants cbuffer NA NA CB0 cb0 1 // // // @@ -28,7 +28,7 @@ // // Name Index Mask Register SysValue Format Used // -------------------- ----- ------ -------- -------- ------- ------ -// TEXCOORD 0 xy 0 NONE float xy +// SV_Position 0 xyzw 0 POS float xy // // // Output signature: @@ -42,107 +42,113 @@ dcl_globalFlags refactoringAllowed dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 dcl_sampler S0[0:0], mode_default, space=0 dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 -dcl_resource_texture1d (float,float,float,float) T1[1:1], space=0 -dcl_input_ps linear v0.xy +dcl_input_ps_siv linear noperspective v0.xy, position dcl_output o0.xyzw -dcl_temps 2 -sample_l r0.xyz, v0.xyxx, T0[0].xyzw, S0[0], l(0.000000) -add r0.w, -CB0[0][0].x, l(1.000000) -mul r1.x, CB0[0][0].x, l(0.500000) -mad r0.xyz, r0.xyzx, r0.wwww, r1.xxxx -sample_l r0.x, r0.x, T1[1].xyzw, S0[0], l(0.000000) -sample_l r0.y, r0.y, T1[1].xyzw, S0[0], l(0.000000) -sample_l r0.z, r0.z, T1[1].xyzw, S0[0], l(0.000000) +dcl_temps 1 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +utof r0.xy, r0.xyxx +add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000) +mul r0.xy, r0.xyxx, CB0[0][0].zwzz +sample_l r0.xyz, r0.xyxx, T0[0].xyzw, S0[0], l(0.000000) mov o0.xyz, r0.xyzx mov o0.w, l(1.000000) ret -// Approximately 10 instruction slots used +// Approximately 9 instruction slots used #endif -const BYTE stretch_gamma_ps[] = +const BYTE guest_output_bilinear_ps[] = { - 68, 88, 66, 67, 4, 222, - 150, 161, 149, 185, 43, 51, - 177, 110, 80, 244, 108, 113, - 108, 20, 1, 0, 0, 0, - 36, 5, 0, 0, 5, 0, + 68, 88, 66, 67, 195, 73, + 6, 106, 30, 227, 35, 134, + 146, 186, 4, 157, 98, 172, + 18, 157, 1, 0, 0, 0, + 204, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, - 20, 2, 0, 0, 72, 2, - 0, 0, 124, 2, 0, 0, - 136, 4, 0, 0, 82, 68, - 69, 70, 216, 1, 0, 0, - 1, 0, 0, 0, 44, 1, - 0, 0, 4, 0, 0, 0, + 68, 2, 0, 0, 120, 2, + 0, 0, 172, 2, 0, 0, + 48, 4, 0, 0, 82, 68, + 69, 70, 8, 2, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, - 176, 1, 0, 0, 19, 19, + 255, 255, 0, 5, 0, 0, + 224, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 36, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, - 220, 0, 0, 0, 3, 0, + 180, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 244, 0, + 0, 0, 0, 0, 204, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 255, 0, 0, 0, - 2, 0, 0, 0, 5, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 66, 105, 108, 105, 110, + 101, 97, 114, 67, 111, 110, + 115, 116, 97, 110, 116, 115, + 0, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, - 255, 255, 255, 255, 1, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 13, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 120, 101, - 95, 115, 97, 109, 112, 108, - 101, 114, 95, 108, 105, 110, - 101, 97, 114, 95, 99, 108, - 97, 109, 112, 0, 120, 101, - 95, 116, 101, 120, 116, 117, - 114, 101, 0, 120, 101, 95, - 103, 97, 109, 109, 97, 95, - 114, 97, 109, 112, 0, 88, - 101, 83, 116, 114, 101, 116, - 99, 104, 71, 97, 109, 109, - 97, 82, 111, 111, 116, 67, - 111, 110, 115, 116, 97, 110, - 116, 115, 0, 171, 171, 171, - 13, 1, 0, 0, 1, 0, - 0, 0, 68, 1, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 108, 1, 0, 0, 0, 0, - 0, 0, 4, 0, 0, 0, - 2, 0, 0, 0, 140, 1, + 116, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 152, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 188, 1, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 120, 101, - 95, 103, 97, 109, 109, 97, - 95, 114, 97, 109, 112, 95, - 105, 110, 118, 95, 115, 105, - 122, 101, 0, 102, 108, 111, - 97, 116, 0, 171, 171, 171, - 0, 0, 3, 0, 1, 0, - 1, 0, 0, 0, 0, 0, + 95, 98, 105, 108, 105, 110, + 101, 97, 114, 95, 111, 117, + 116, 112, 117, 116, 95, 111, + 102, 102, 115, 101, 116, 0, + 105, 110, 116, 50, 0, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 131, 1, 0, 0, + 0, 0, 110, 1, 0, 0, + 120, 101, 95, 98, 105, 108, + 105, 110, 101, 97, 114, 95, + 111, 117, 116, 112, 117, 116, + 95, 115, 105, 122, 101, 95, + 105, 110, 118, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 1, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, @@ -153,12 +159,12 @@ const BYTE stretch_gamma_ps[] = 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 3, 3, - 0, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171, 79, 83, 71, 78, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, @@ -167,9 +173,9 @@ const BYTE stretch_gamma_ps[] = 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171, - 83, 72, 69, 88, 4, 2, + 83, 72, 69, 88, 124, 1, 0, 0, 81, 0, 0, 0, - 129, 0, 0, 0, 106, 8, + 95, 0, 0, 0, 106, 8, 0, 1, 89, 0, 0, 7, 70, 142, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -183,92 +189,71 @@ const BYTE stretch_gamma_ps[] = 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 0, 0, - 0, 0, 0, 0, 88, 16, - 0, 7, 70, 126, 48, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 1, 0, 0, 0, - 85, 85, 0, 0, 0, 0, - 0, 0, 98, 16, 0, 3, - 50, 16, 16, 0, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, - 2, 0, 0, 0, 72, 0, - 0, 13, 114, 0, 16, 0, + 1, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 9, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 230, 138, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, + 0, 13, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, 70, 126, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, - 130, 0, 16, 0, 0, 0, - 0, 0, 10, 128, 48, 128, - 65, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, - 56, 0, 0, 9, 18, 0, - 16, 0, 1, 0, 0, 0, - 10, 128, 48, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 50, 0, 0, 9, 114, 0, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 246, 15, 16, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 1, 0, 0, 0, - 72, 0, 0, 13, 18, 0, - 16, 0, 0, 0, 0, 0, - 10, 0, 16, 0, 0, 0, - 0, 0, 70, 126, 32, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 0, 96, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 0, 0, 0, 0, 72, 0, - 0, 13, 34, 0, 16, 0, - 0, 0, 0, 0, 26, 0, - 16, 0, 0, 0, 0, 0, - 70, 126, 32, 0, 1, 0, + 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, - 0, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 13, - 66, 0, 16, 0, 0, 0, - 0, 0, 42, 0, 16, 0, - 0, 0, 0, 0, 70, 126, - 32, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 96, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, - 54, 0, 0, 5, 114, 32, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 54, 0, 0, 5, - 130, 32, 16, 0, 0, 0, - 0, 0, 1, 64, 0, 0, - 0, 0, 128, 63, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 10, 0, - 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, - 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -278,7 +263,5 @@ const BYTE stretch_gamma_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0 + 0, 0, 0, 0 }; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h new file mode 100644 index 000000000..924aed761 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_dither_ps.h @@ -0,0 +1,2227 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasResampleConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float2 xe_cas_input_output_size_ratio;// Offset: 8 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 16 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasResampleConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 14 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +mad r0.zw, CB0[0][0].zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), l(0.000000, 0.000000, -0.500000, -0.500000) +utof r1.xy, r0.xyxx +mad r0.zw, r1.xxxy, CB0[0][0].zzzw, r0.zzzw +round_ni r1.xy, r0.zwzz +add r0.zw, r0.zzzw, -r1.xxxy +ftoi r1.xy, r1.xyxx +iadd r2.xyzw, r1.xyxy, l(-1, 0, 0, -1) +mov r3.xy, r2.zwzz +mov r3.zw, l(0,0,0,0) +ld r3.xyz, r3.xyzw, T0[0].xyzw +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r4.xyz, r1.xyzw, T0[0].xyzw +iadd r5.xyzw, r1.xyxy, l(1, 0, 1, -1) +mov r6.xy, r5.zwzz +mov r6.zw, l(0,0,0,0) +ld r6.xyz, r6.xyzw, T0[0].xyzw +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +iadd r7.xyzw, r1.xyxy, l(-1, 1, 2, 0) +mov r8.xy, r7.zwzz +mov r8.zw, l(0,0,0,0) +ld r8.xyz, r8.xyzw, T0[0].xyzw +mov r7.zw, l(0,0,0,0) +ld r7.xyz, r7.xyzw, T0[0].xyzw +iadd r9.xyzw, r1.xyxy, l(0, 2, 0, 1) +mov r10.xy, r9.zwzz +mov r10.zw, l(0,0,0,0) +ld r10.xyz, r10.xyzw, T0[0].xyzw +mov r9.zw, l(0,0,0,0) +ld r9.xyz, r9.xyzw, T0[0].xyzw +iadd r11.xyzw, r1.xyxy, l(2, 1, 1, 1) +mov r12.xy, r11.zwzz +mov r12.zw, l(0,0,0,0) +ld r12.xyz, r12.xyzw, T0[0].xyzw +mov r11.zw, l(0,0,0,0) +ld r11.xyz, r11.xyzw, T0[0].xyzw +iadd r1.xy, r1.xyxx, l(1, 2, 0, 0) +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mul r3.xyz, r3.xyzx, r3.xyzx +mul r6.xyz, r6.xyzx, r6.xyzx +mul r2.xyz, r2.xyzx, r2.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +mul r5.xyz, r5.xyzx, r5.xyzx +mul r8.xyz, r8.xyzx, r8.xyzx +mul r7.xyz, r7.xyzx, r7.xyzx +mul r10.xyz, r10.xyzx, r10.xyzx +mul r12.xyz, r12.xyzx, r12.xyzx +mul r11.xyz, r11.xyzx, r11.xyzx +mul r9.xyz, r9.xyzx, r9.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +min r1.w, r2.y, r4.y +min r1.w, r1.w, r3.y +min r2.w, r5.y, r10.y +min r1.w, r1.w, r2.w +max r2.w, r2.y, r4.y +max r2.w, r2.w, r3.y +max r3.w, r5.y, r10.y +max r2.w, r2.w, r3.w +min r3.w, r4.y, r5.y +min r3.w, r3.w, r6.y +min r4.w, r8.y, r12.y +min r3.w, r3.w, r4.w +max r4.w, r4.y, r5.y +max r4.w, r4.w, r6.y +max r5.w, r8.y, r12.y +max r4.w, r4.w, r5.w +min r5.w, r7.y, r10.y +min r5.w, r4.y, r5.w +min r6.w, r9.y, r12.y +min r5.w, r5.w, r6.w +max r6.w, r7.y, r10.y +max r6.w, r4.y, r6.w +max r7.w, r9.y, r12.y +max r6.w, r6.w, r7.w +min r7.w, r10.y, r12.y +min r7.w, r5.y, r7.w +min r8.w, r1.y, r11.y +min r7.w, r7.w, r8.w +max r8.w, r10.y, r12.y +max r8.w, r5.y, r8.w +max r9.w, r1.y, r11.y +max r8.w, r8.w, r9.w +iadd r9.w, -r2.w, l(0x7ef07ebb) +iadd r10.w, -r4.w, l(0x7ef07ebb) +iadd r11.w, -r6.w, l(0x7ef07ebb) +iadd r12.w, -r8.w, l(0x7ef07ebb) +add r13.x, -r2.w, l(1.000000) +min r13.x, r1.w, r13.x +mul_sat r9.w, r9.w, r13.x +add r13.x, -r4.w, l(1.000000) +min r13.x, r3.w, r13.x +mul_sat r10.w, r10.w, r13.x +add r13.x, -r6.w, l(1.000000) +min r13.x, r5.w, r13.x +mul_sat r11.w, r11.w, r13.x +add r13.x, -r8.w, l(1.000000) +min r13.x, r7.w, r13.x +mul_sat r12.w, r12.w, r13.x +ushr r9.w, r9.w, l(1) +iadd r9.w, r9.w, l(0x1fbc4639) +ushr r10.w, r10.w, l(1) +iadd r10.w, r10.w, l(0x1fbc4639) +ushr r11.w, r11.w, l(1) +iadd r11.w, r11.w, l(0x1fbc4639) +ushr r12.w, r12.w, l(1) +iadd r12.w, r12.w, l(0x1fbc4639) +mul r9.w, r9.w, CB0[0][1].x +mul r10.w, r10.w, CB0[0][1].x +mul r11.w, r11.w, CB0[0][1].x +mul r12.w, r12.w, CB0[0][1].x +add r13.xy, -r0.wzww, l(1.000000, 1.000000, 0.000000, 0.000000) +mul r13.z, r13.x, r13.y +mul r13.xy, r0.zwzz, r13.xyxx +mul r0.z, r0.w, r0.z +add r0.w, -r1.w, r2.w +add r0.w, r0.w, l(0.031250) +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r1.w, r0.w, r13.z +add r2.w, -r3.w, r4.w +add r2.w, r2.w, l(0.031250) +iadd r2.w, -r2.w, l(0x7ef07ebb) +mul r3.w, r2.w, r13.x +add r4.w, -r5.w, r6.w +add r4.w, r4.w, l(0.031250) +iadd r4.w, -r4.w, l(0x7ef07ebb) +mul r5.w, r4.w, r13.y +add r6.w, -r7.w, r8.w +add r6.w, r6.w, l(0.031250) +iadd r6.w, -r6.w, l(0x7ef07ebb) +mul r7.w, r0.z, r6.w +mul r8.w, r1.w, r9.w +mul r13.w, r3.w, r10.w +mul r5.w, r5.w, r11.w +mad r3.w, r10.w, r3.w, r5.w +mad r0.w, r13.z, r0.w, r3.w +mul r7.w, r7.w, r12.w +mad r1.w, r9.w, r1.w, r7.w +mad r2.w, r13.x, r2.w, r1.w +mad r1.w, r13.y, r4.w, r1.w +mad r0.z, r0.z, r6.w, r3.w +add r3.w, r13.w, r13.w +mad r3.w, r8.w, l(2.000000), r3.w +mad r3.w, r5.w, l(2.000000), r3.w +mad r3.w, r7.w, l(2.000000), r3.w +add r3.w, r0.w, r3.w +add r3.w, r2.w, r3.w +add r3.w, r1.w, r3.w +add r3.w, r0.z, r3.w +iadd r4.w, -r3.w, l(0x7ef19fff) +mad r3.w, -r4.w, r3.w, l(2.000000) +mul r3.w, r3.w, r4.w +mul r2.xyz, r2.xyzx, r8.wwww +mad r2.xyz, r3.xyzx, r8.wwww, r2.xyzx +mad r2.xyz, r6.xyzx, r13.wwww, r2.xyzx +mad r2.xyz, r8.xyzx, r13.wwww, r2.xyzx +mad r2.xyz, r7.xyzx, r5.wwww, r2.xyzx +mad r2.xyz, r9.xyzx, r5.wwww, r2.xyzx +mad r2.xyz, r11.xyzx, r7.wwww, r2.xyzx +mad r1.xyz, r1.xyzx, r7.wwww, r2.xyzx +mad r1.xyz, r4.xyzx, r0.wwww, r1.xyzx +mad r1.xyz, r5.xyzx, r2.wwww, r1.xyzx +mad r1.xyz, r10.xyzx, r1.wwww, r1.xyzx +mad r1.xyz, r12.xyzx, r0.zzzz, r1.xyzx +mul_sat r1.xyz, r3.wwww, r1.xyzx +sqrt r1.xyz, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 175 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_resample_dither_ps[] = +{ + 68, 88, 66, 67, 162, 124, + 243, 114, 220, 254, 28, 54, + 81, 63, 203, 49, 205, 242, + 53, 186, 1, 0, 0, 0, + 220, 40, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 120, 2, 0, 0, 172, 2, + 0, 0, 224, 2, 0, 0, + 64, 40, 0, 0, 82, 68, + 69, 70, 60, 2, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 20, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 82, 101, 115, 97, 109, 112, + 108, 101, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 151, 0, 0, 0, + 3, 0, 0, 0, 200, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 64, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 92, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 128, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 240, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 111, 117, 116, + 112, 117, 116, 95, 111, 102, + 102, 115, 101, 116, 0, 105, + 110, 116, 50, 0, 171, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 1, 0, 0, + 120, 101, 95, 99, 97, 115, + 95, 105, 110, 112, 117, 116, + 95, 111, 117, 116, 112, 117, + 116, 95, 115, 105, 122, 101, + 95, 114, 97, 116, 105, 111, + 0, 102, 108, 111, 97, 116, + 50, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 1, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 115, + 104, 97, 114, 112, 110, 101, + 115, 115, 95, 112, 111, 115, + 116, 95, 115, 101, 116, 117, + 112, 0, 102, 108, 111, 97, + 116, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 88, 37, 0, 0, + 81, 0, 0, 0, 86, 9, + 0, 0, 106, 8, 0, 1, + 53, 24, 0, 0, 2, 4, + 0, 0, 132, 131, 131, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 231, 230, 102, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 204, 203, 203, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 168, 167, 167, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 159, 158, + 30, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 182, 181, 181, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 135, 134, 6, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 210, 209, + 209, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 155, 154, 26, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 145, + 145, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 143, 142, + 14, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 137, 136, 8, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 158, 157, 157, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 138, 137, 137, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 253, 252, + 252, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 144, 143, 143, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 209, 208, + 208, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 139, 138, 10, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 188, 187, 187, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 254, 253, + 253, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 183, 182, 54, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 160, 32, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 186, + 58, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 172, 171, 171, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 144, 143, 143, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 229, 229, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 220, 219, 219, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 194, 193, + 193, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 157, 156, 156, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 216, 215, 215, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 208, 207, + 207, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 232, 231, + 231, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 227, 226, 98, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 243, 242, 114, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 170, 169, 169, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 211, 210, 82, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 191, + 191, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 236, 235, 235, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 223, 222, + 94, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 237, 236, 236, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 140, 139, 139, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 152, + 24, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 186, 185, 185, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 213, 212, 212, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 208, 207, + 207, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 171, 170, 42, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 145, 144, 144, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 221, 220, + 220, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 175, 174, 46, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 156, 155, 155, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 190, 189, + 189, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 198, + 70, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 170, 169, 169, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 131, 130, 2, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 243, + 243, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 173, 172, 172, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 179, + 179, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 214, 213, 213, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 191, 190, + 62, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 239, 238, 110, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 195, 194, + 66, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 154, 153, 153, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 145, 144, 144, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 196, 195, + 195, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 126, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 251, 250, 122, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 254, 253, + 253, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 139, 138, 10, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 225, 224, 96, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 202, 201, 201, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 128, + 0, 183, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 165, 164, 164, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 176, 175, 175, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 156, 155, 155, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 203, 202, + 74, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 141, 140, 140, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 194, 193, + 193, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 137, 136, 8, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 205, 204, 204, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 251, 250, 122, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 135, 135, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 179, 178, + 50, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 132, 131, 131, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 221, 220, + 220, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 234, 233, 233, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 249, 248, 120, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 163, 162, + 34, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 217, 217, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 142, 141, 141, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 207, 206, + 78, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 234, 233, 233, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 129, + 129, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 174, 173, 173, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 185, 184, 56, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 198, 197, + 197, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 212, 211, 211, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 152, 151, 151, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 229, 228, 228, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 201, 200, 72, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 196, 195, + 195, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 150, 149, 149, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 248, 247, + 247, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 184, 183, 183, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 147, 146, 18, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 241, 240, + 240, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 151, 150, 22, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 174, 173, 173, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 233, 232, 104, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 199, 198, + 70, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 178, 177, 177, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 147, 146, 18, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 237, + 237, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 226, 225, 225, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 152, 151, 151, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 195, 194, + 66, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 160, 159, + 159, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 240, 239, 239, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 55, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 252, 251, + 251, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 228, 227, 227, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 224, 223, 223, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 162, 161, 161, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 217, 216, + 88, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 138, 137, 137, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 165, 164, 164, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 247, 246, 118, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 181, 180, 180, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 134, 133, 133, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 206, 205, 205, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 193, 192, + 192, 183, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 211, 210, 82, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 234, + 106, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 176, + 176, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 239, 238, 110, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 59, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 167, 166, 38, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 215, 214, + 86, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 164, 163, 163, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 133, 132, 132, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 199, + 199, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 148, 147, 147, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 189, 188, 188, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 250, 249, 249, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 182, 181, 181, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 146, 145, + 145, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 212, 211, 211, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 231, 230, 102, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 152, + 24, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 142, 141, 141, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 225, 224, 96, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 148, + 148, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 222, 221, 221, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 165, 165, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 169, 168, 40, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 246, 245, 245, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 219, 218, + 90, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 167, 166, 38, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 55, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 197, 196, 196, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 213, 212, 212, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 162, 161, 161, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 247, 246, 118, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 241, + 241, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 245, 244, 244, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 14, 0, + 0, 0, 27, 0, 0, 5, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 128, 48, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 17, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 0, 0, 0, 191, 86, 0, + 0, 5, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 194, 0, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 65, 0, 0, 5, + 50, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 6, 0, 0, 0, + 230, 10, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 4, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 8, 0, + 0, 0, 230, 10, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 4, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 10, 0, 0, 0, 230, 10, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 12, 0, 0, 0, + 230, 10, 16, 0, 11, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 12, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 30, 0, + 0, 8, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 30, 0, 0, 8, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 30, 0, 0, 8, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 8, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 0, 0, + 0, 8, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 0, 0, 0, 8, + 18, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 51, 0, 0, 7, + 18, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 56, 32, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 0, 0, + 0, 8, 18, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 10, 0, 16, 0, + 13, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 85, 0, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 57, 70, 188, 31, + 85, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 85, 0, 0, 7, + 130, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 56, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 11, 50, 0, 16, 0, + 13, 0, 0, 0, 182, 15, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 66, 0, + 16, 0, 13, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 13, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 13, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 8, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 2, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 13, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 255, 159, + 241, 126, 50, 0, 0, 10, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 56, 0, 0, 7, 130, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 8, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 246, 15, + 16, 0, 13, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 10, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 56, 32, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 75, 0, 0, 5, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 6, 144, 144, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 175, 0, + 0, 0, 14, 0, 0, 0, + 0, 1, 0, 0, 2, 0, + 0, 0, 115, 0, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h new file mode 100644 index 000000000..1a7634fd6 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_resample_ps.h @@ -0,0 +1,1264 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasResampleConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float2 xe_cas_input_output_size_ratio;// Offset: 8 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 16 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasResampleConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 14 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +mad r0.zw, CB0[0][0].zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), l(0.000000, 0.000000, -0.500000, -0.500000) +utof r0.xy, r0.xyxx +mad r0.xy, r0.xyxx, CB0[0][0].zwzz, r0.zwzz +round_ni r0.zw, r0.xxxy +add r0.xy, -r0.zwzz, r0.xyxx +ftoi r1.xy, r0.zwzz +iadd r2.xyzw, r1.xyxy, l(-1, 0, 0, -1) +mov r3.xy, r2.zwzz +mov r3.zw, l(0,0,0,0) +ld r3.xyz, r3.xyzw, T0[0].xyzw +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r4.xyz, r1.xyzw, T0[0].xyzw +iadd r5.xyzw, r1.xyxy, l(1, 0, 1, -1) +mov r6.xy, r5.zwzz +mov r6.zw, l(0,0,0,0) +ld r6.xyz, r6.xyzw, T0[0].xyzw +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +iadd r7.xyzw, r1.xyxy, l(-1, 1, 2, 0) +mov r8.xy, r7.zwzz +mov r8.zw, l(0,0,0,0) +ld r8.xyz, r8.xyzw, T0[0].xyzw +mov r7.zw, l(0,0,0,0) +ld r7.xyz, r7.xyzw, T0[0].xyzw +iadd r9.xyzw, r1.xyxy, l(0, 2, 0, 1) +mov r10.xy, r9.zwzz +mov r10.zw, l(0,0,0,0) +ld r10.xyz, r10.xyzw, T0[0].xyzw +mov r9.zw, l(0,0,0,0) +ld r9.xyz, r9.xyzw, T0[0].xyzw +iadd r11.xyzw, r1.xyxy, l(2, 1, 1, 1) +mov r12.xy, r11.zwzz +mov r12.zw, l(0,0,0,0) +ld r12.xyz, r12.xyzw, T0[0].xyzw +mov r11.zw, l(0,0,0,0) +ld r11.xyz, r11.xyzw, T0[0].xyzw +iadd r1.xy, r1.xyxx, l(1, 2, 0, 0) +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mul r3.xyz, r3.xyzx, r3.xyzx +mul r6.xyz, r6.xyzx, r6.xyzx +mul r2.xyz, r2.xyzx, r2.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +mul r5.xyz, r5.xyzx, r5.xyzx +mul r8.xyz, r8.xyzx, r8.xyzx +mul r7.xyz, r7.xyzx, r7.xyzx +mul r10.xyz, r10.xyzx, r10.xyzx +mul r12.xyz, r12.xyzx, r12.xyzx +mul r11.xyz, r11.xyzx, r11.xyzx +mul r9.xyz, r9.xyzx, r9.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +min r0.z, r2.y, r4.y +min r0.z, r0.z, r3.y +min r0.w, r5.y, r10.y +min r0.z, r0.w, r0.z +max r0.w, r2.y, r4.y +max r0.w, r0.w, r3.y +max r1.w, r5.y, r10.y +max r0.w, r0.w, r1.w +min r1.w, r4.y, r5.y +min r1.w, r1.w, r6.y +min r2.w, r8.y, r12.y +min r1.w, r1.w, r2.w +max r2.w, r4.y, r5.y +max r2.w, r2.w, r6.y +max r3.w, r8.y, r12.y +max r2.w, r2.w, r3.w +min r3.w, r7.y, r10.y +min r3.w, r3.w, r4.y +min r4.w, r9.y, r12.y +min r3.w, r3.w, r4.w +max r4.w, r7.y, r10.y +max r4.w, r4.w, r4.y +max r5.w, r9.y, r12.y +max r4.w, r4.w, r5.w +min r5.w, r10.y, r12.y +min r5.w, r5.w, r5.y +min r6.w, r1.y, r11.y +min r5.w, r5.w, r6.w +max r6.w, r10.y, r12.y +max r6.w, r5.y, r6.w +max r7.w, r1.y, r11.y +max r6.w, r6.w, r7.w +iadd r7.w, -r0.w, l(0x7ef07ebb) +iadd r8.w, -r2.w, l(0x7ef07ebb) +iadd r9.w, -r4.w, l(0x7ef07ebb) +iadd r10.w, -r6.w, l(0x7ef07ebb) +add r11.w, -r0.w, l(1.000000) +min r11.w, r0.z, r11.w +mul_sat r7.w, r7.w, r11.w +add r11.w, -r2.w, l(1.000000) +min r11.w, r1.w, r11.w +mul_sat r8.w, r8.w, r11.w +add r11.w, -r4.w, l(1.000000) +min r11.w, r3.w, r11.w +mul_sat r9.w, r9.w, r11.w +add r11.w, -r6.w, l(1.000000) +min r11.w, r5.w, r11.w +mul_sat r10.w, r10.w, r11.w +ushr r7.w, r7.w, l(1) +iadd r7.w, r7.w, l(0x1fbc4639) +ushr r8.w, r8.w, l(1) +iadd r8.w, r8.w, l(0x1fbc4639) +ushr r9.w, r9.w, l(1) +iadd r9.w, r9.w, l(0x1fbc4639) +ushr r10.w, r10.w, l(1) +iadd r10.w, r10.w, l(0x1fbc4639) +mul r7.w, r7.w, CB0[0][1].x +mul r8.w, r8.w, CB0[0][1].x +mul r9.w, r9.w, CB0[0][1].x +mul r10.w, r10.w, CB0[0][1].x +add r13.xy, -r0.yxyy, l(1.000000, 1.000000, 0.000000, 0.000000) +mul r11.w, r13.x, r13.y +mul r13.xy, r0.xyxx, r13.xyxx +mul r0.x, r0.y, r0.x +add r0.y, -r0.z, r0.w +add r0.y, r0.y, l(0.031250) +iadd r0.y, -r0.y, l(0x7ef07ebb) +mul r0.z, r0.y, r11.w +add r0.w, -r1.w, r2.w +add r0.w, r0.w, l(0.031250) +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r1.w, r0.w, r13.x +add r2.w, -r3.w, r4.w +add r2.w, r2.w, l(0.031250) +iadd r2.w, -r2.w, l(0x7ef07ebb) +mul r3.w, r2.w, r13.y +add r4.w, -r5.w, r6.w +add r4.w, r4.w, l(0.031250) +iadd r4.w, -r4.w, l(0x7ef07ebb) +mul r5.w, r0.x, r4.w +mul r6.w, r0.z, r7.w +mul r12.w, r1.w, r8.w +mul r3.w, r3.w, r9.w +mad r1.w, r8.w, r1.w, r3.w +mad r0.y, r11.w, r0.y, r1.w +mul r5.w, r5.w, r10.w +mad r0.z, r7.w, r0.z, r5.w +mad r0.w, r13.x, r0.w, r0.z +mad r0.z, r13.y, r2.w, r0.z +mad r0.x, r0.x, r4.w, r1.w +add r1.w, r12.w, r12.w +mad r1.w, r6.w, l(2.000000), r1.w +mad r1.w, r3.w, l(2.000000), r1.w +mad r1.w, r5.w, l(2.000000), r1.w +add r1.w, r0.y, r1.w +add r1.w, r0.w, r1.w +add r1.w, r0.z, r1.w +add r1.w, r0.x, r1.w +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r2.xyz, r2.xyzx, r6.wwww +mad r2.xyz, r3.xyzx, r6.wwww, r2.xyzx +mad r2.xyz, r6.xyzx, r12.wwww, r2.xyzx +mad r2.xyz, r8.xyzx, r12.wwww, r2.xyzx +mad r2.xyz, r7.xyzx, r3.wwww, r2.xyzx +mad r2.xyz, r9.xyzx, r3.wwww, r2.xyzx +mad r2.xyz, r11.xyzx, r5.wwww, r2.xyzx +mad r1.xyz, r1.xyzx, r5.wwww, r2.xyzx +mad r1.xyz, r4.xyzx, r0.yyyy, r1.xyzx +mad r1.xyz, r5.xyzx, r0.wwww, r1.xyzx +mad r0.yzw, r10.xxyz, r0.zzzz, r1.xxyz +mad r0.xyz, r12.xyzx, r0.xxxx, r0.yzwy +mul_sat r0.xyz, r1.wwww, r0.xyzx +sqrt o0.xyz, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 172 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_resample_ps[] = +{ + 68, 88, 66, 67, 153, 223, + 100, 209, 57, 228, 221, 164, + 114, 23, 52, 94, 29, 110, + 188, 4, 1, 0, 0, 0, + 92, 24, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 120, 2, 0, 0, 172, 2, + 0, 0, 224, 2, 0, 0, + 192, 23, 0, 0, 82, 68, + 69, 70, 60, 2, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 20, 2, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 82, 101, 115, 97, 109, 112, + 108, 101, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 151, 0, 0, 0, + 3, 0, 0, 0, 200, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 64, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 92, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 128, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 168, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 204, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 240, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 111, 117, 116, + 112, 117, 116, 95, 111, 102, + 102, 115, 101, 116, 0, 105, + 110, 116, 50, 0, 171, 171, + 1, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 1, 0, 0, + 120, 101, 95, 99, 97, 115, + 95, 105, 110, 112, 117, 116, + 95, 111, 117, 116, 112, 117, + 116, 95, 115, 105, 122, 101, + 95, 114, 97, 116, 105, 111, + 0, 102, 108, 111, 97, 116, + 50, 0, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 1, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 115, + 104, 97, 114, 112, 110, 101, + 115, 115, 95, 112, 111, 115, + 116, 95, 115, 101, 116, 117, + 112, 0, 102, 108, 111, 97, + 116, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 216, 20, 0, 0, + 81, 0, 0, 0, 54, 5, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 14, 0, + 0, 0, 27, 0, 0, 5, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 128, 48, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 17, + 194, 0, 16, 0, 0, 0, + 0, 0, 166, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 0, 0, 0, 191, 86, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 11, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 230, 138, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 65, 0, 0, 5, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 10, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 255, 255, 255, 255, + 54, 0, 0, 5, 50, 0, + 16, 0, 6, 0, 0, 0, + 230, 10, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 14, + 16, 0, 6, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 7, 0, 0, 0, 70, 4, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 8, 0, + 0, 0, 230, 10, 16, 0, + 7, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 8, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 14, 16, 0, 8, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 7, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 14, + 16, 0, 7, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 9, 0, 0, 0, + 70, 4, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 10, 0, 0, 0, 230, 10, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 10, 0, + 0, 0, 70, 14, 16, 0, + 10, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 9, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 9, 0, 0, 0, + 70, 14, 16, 0, 9, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 242, 0, 16, 0, 11, 0, + 0, 0, 70, 4, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 50, 0, + 16, 0, 12, 0, 0, 0, + 230, 10, 16, 0, 11, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 12, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 12, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 11, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 11, 0, + 0, 0, 70, 14, 16, 0, + 11, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 1, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 10, 0, 0, 0, 70, 2, + 16, 0, 10, 0, 0, 0, + 70, 2, 16, 0, 10, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 12, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 70, 2, + 16, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 11, 0, 0, 0, + 70, 2, 16, 0, 11, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 9, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 10, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 8, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 9, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 10, 0, + 0, 0, 26, 0, 16, 0, + 12, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 26, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 6, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 6, 0, 0, 0, 58, 0, + 16, 0, 6, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 30, 0, + 0, 8, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 30, 0, 0, 8, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 30, 0, 0, 8, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 6, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 0, 0, + 0, 8, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 0, 0, 0, 8, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 51, 0, 0, 7, + 130, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 56, 32, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 0, 0, + 0, 8, 130, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 51, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 7, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 85, 0, 0, 7, + 130, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 7, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 85, 0, + 0, 7, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 7, + 130, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 8, 0, 0, 0, 1, 64, + 0, 0, 57, 70, 188, 31, + 85, 0, 0, 7, 130, 0, + 16, 0, 9, 0, 0, 0, + 58, 0, 16, 0, 9, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 85, 0, 0, 7, + 130, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 30, 0, 0, 7, 130, 0, + 16, 0, 10, 0, 0, 0, + 58, 0, 16, 0, 10, 0, + 0, 0, 1, 64, 0, 0, + 57, 70, 188, 31, 56, 0, + 0, 9, 130, 0, 16, 0, + 7, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 8, 0, 0, 0, 58, 0, + 16, 0, 8, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 9, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 9, 130, 0, 16, 0, + 10, 0, 0, 0, 58, 0, + 16, 0, 10, 0, 0, 0, + 10, 128, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 11, 50, 0, 16, 0, + 13, 0, 0, 0, 22, 5, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 13, 0, + 0, 0, 26, 0, 16, 0, + 13, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 13, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 13, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 34, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 11, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 3, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 2, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 0, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 6, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 61, + 30, 0, 0, 8, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 130, 0, 16, 0, 5, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 6, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 7, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 58, 0, + 16, 0, 9, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 5, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 58, 0, 16, 0, + 10, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 7, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 12, 0, 0, 0, + 58, 0, 16, 0, 12, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 5, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 58, 0, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 0, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 255, 159, + 241, 126, 50, 0, 0, 10, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 64, + 56, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 6, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 246, 15, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 246, 15, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 246, 15, + 16, 0, 12, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 246, 15, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 226, 0, 16, 0, 0, 0, + 0, 0, 6, 9, 16, 0, + 10, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 6, 9, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 12, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 150, 7, 16, 0, 0, 0, + 0, 0, 56, 32, 0, 7, + 114, 0, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 75, 0, 0, 5, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 32, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 172, 0, + 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 114, 0, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h new file mode 100644 index 000000000..14e7dd87b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_dither_ps.h @@ -0,0 +1,1454 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasSharpenConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasSharpenConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 6 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r4.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r5.xy, r4.zwzz +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mul r2.xyz, r2.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +mul r0.z, r3.y, r3.y +mul r5.xyz, r5.xyzx, r5.xyzx +mul r4.xyz, r4.xyzx, r4.xyzx +min r0.w, r0.z, r5.y +min r0.w, r0.w, r1.y +min r1.w, r2.y, r4.y +min r0.w, r0.w, r1.w +max r0.z, r0.z, r5.y +max r0.z, r0.z, r1.y +max r1.w, r2.y, r4.y +max r0.z, r0.z, r1.w +iadd r1.w, -r0.z, l(0x7ef07ebb) +add r0.z, -r0.z, l(1.000000) +min r0.z, r0.z, r0.w +mul_sat r0.z, r1.w, r0.z +ushr r0.z, r0.z, l(1) +iadd r0.z, r0.z, l(0x1fbc4639) +mul r0.z, r0.z, CB0[0][0].z +mad r0.w, r0.z, l(4.000000), l(1.000000) +iadd r1.w, -r0.w, l(0x7ef19fff) +mad r0.w, -r1.w, r0.w, l(2.000000) +mul r0.w, r0.w, r1.w +mul r1.xyz, r0.zzzz, r1.xyzx +mad r1.xyz, r2.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r5.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r4.xyzx, r0.zzzz, r1.xyzx +mad r1.xyz, r3.xyzx, r3.xyzx, r1.xyzx +mul_sat r1.xyz, r0.wwww, r1.xyzx +sqrt r1.xyz, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +add o0.xyz, r1.xyzx, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 52 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_sharpen_dither_ps[] = +{ + 68, 88, 66, 67, 200, 82, + 48, 235, 252, 11, 120, 26, + 79, 183, 112, 246, 236, 81, + 181, 118, 1, 0, 0, 0, + 168, 25, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 4, 2, 0, 0, 56, 2, + 0, 0, 108, 2, 0, 0, + 12, 25, 0, 0, 82, 68, + 69, 70, 200, 1, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 160, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 83, 104, 97, 114, 112, 101, + 110, 67, 111, 110, 115, 116, + 97, 110, 116, 115, 0, 171, + 171, 171, 151, 0, 0, 0, + 2, 0, 0, 0, 200, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 24, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 52, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 88, 1, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 124, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 111, + 117, 116, 112, 117, 116, 95, + 111, 102, 102, 115, 101, 116, + 0, 105, 110, 116, 50, 0, + 171, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 1, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 115, 104, 97, + 114, 112, 110, 101, 115, 115, + 95, 112, 111, 115, 116, 95, + 115, 101, 116, 117, 112, 0, + 102, 108, 111, 97, 116, 0, + 171, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 116, 1, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 152, 22, 0, 0, 81, 0, + 0, 0, 166, 5, 0, 0, + 106, 8, 0, 1, 53, 24, + 0, 0, 2, 4, 0, 0, + 132, 131, 131, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 231, 230, + 102, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 222, 221, 221, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 140, 139, 139, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 182, 181, + 181, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 178, 177, 177, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 160, 159, + 159, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 148, + 148, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 146, 145, 145, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 186, 185, 185, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 190, 189, + 189, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 137, 136, 8, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 229, 228, 228, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 138, 137, 137, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 163, 162, + 34, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 246, 245, 245, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 143, + 143, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 139, 138, 10, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 254, 253, 253, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 143, + 143, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 157, 156, 156, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 194, 193, 193, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 161, 160, 32, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 207, 206, + 78, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 240, 239, 239, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 129, + 129, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 154, 153, 153, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 185, 184, 56, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 208, 207, 207, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 181, 180, 180, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 244, 243, + 243, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 234, + 106, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 169, 168, 40, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 200, 199, + 199, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 171, 170, 42, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 170, 169, 169, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 211, 210, + 82, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 223, 222, + 94, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 153, 152, 24, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 249, 248, 120, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 155, 154, 26, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 201, 200, 72, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 210, 209, + 209, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 134, 133, 133, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 213, 212, 212, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 217, 216, + 88, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 208, 207, 207, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 145, 144, + 144, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 221, 220, 220, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 216, 215, 215, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 180, 179, + 179, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 243, 242, 114, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 155, + 155, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 151, 150, 22, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 248, 247, + 247, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 199, 198, 70, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 170, 169, 169, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 252, 251, + 251, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 217, 217, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 136, 135, 135, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 158, 157, 157, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 242, 241, + 241, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 239, 238, 110, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 238, 237, + 237, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 150, 149, 149, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 197, 196, 196, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 209, 208, + 208, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 195, 194, 66, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 145, 144, + 144, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 195, 195, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 251, 250, + 122, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 254, 253, 253, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 139, 138, 10, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 225, 224, + 96, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 164, 163, 163, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 141, 140, 140, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 183, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 165, 164, 164, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 229, 229, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 131, 130, 2, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 155, + 155, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 176, 175, 175, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 194, 193, 193, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 137, 136, 8, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 203, 202, + 74, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 172, 171, 171, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 251, 250, + 122, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 245, 244, 244, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 202, 201, 201, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 220, 219, 219, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 132, 131, + 131, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 221, 220, 220, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 234, 233, 233, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 219, 218, + 90, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 226, 225, 225, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 142, 141, 141, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 232, 231, + 231, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 234, 233, 233, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 179, 178, + 50, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 173, 173, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 173, 172, 172, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 187, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 175, 174, 46, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 212, 211, 211, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 152, 151, + 151, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 237, 236, 236, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 195, 195, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 177, 176, + 176, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 147, 146, + 18, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 166, 165, 165, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 126, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 174, 173, 173, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 199, 198, 70, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 191, + 191, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 227, 226, 98, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 189, 188, 188, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 143, 142, + 14, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 148, 147, 147, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 133, 132, 132, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 147, 146, + 18, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 152, 151, + 151, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 195, 194, 66, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 206, 205, 205, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 241, 240, + 240, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 193, 192, + 192, 55, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 186, + 58, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 204, 203, 203, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 162, 161, + 161, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 138, 137, 137, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 191, 190, + 62, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 214, 213, 213, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 165, 164, 164, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 253, 252, + 252, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 236, 235, 235, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 247, 246, 118, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 183, 182, 54, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 183, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 168, 167, 167, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 211, 210, + 82, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 188, 187, 187, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 159, 158, + 30, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 239, 238, 110, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 184, 183, 183, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 167, 166, 38, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 198, 197, + 197, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 205, 204, 204, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 182, 181, + 181, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 146, 145, 145, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 212, 211, 211, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 231, 230, + 102, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 153, 152, 24, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 142, 141, 141, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 225, 224, + 96, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 135, 134, 6, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 167, 166, 38, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 129, 128, + 0, 55, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 250, 249, 249, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 233, 232, 104, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 228, 227, 227, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 213, 212, 212, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 162, 161, + 161, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 224, 223, 223, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 247, 246, 118, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 215, 214, + 86, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 89, 0, + 0, 7, 70, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 88, 24, 0, 7, + 70, 126, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 100, 32, 0, 4, 50, 16, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 6, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 128, + 48, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 4, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 5, 0, 0, 0, 230, 10, + 16, 0, 4, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 14, 16, 0, + 5, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 1, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 26, 0, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 5, 0, 0, 0, + 52, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 56, 32, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 56, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 32, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 75, 0, 0, 5, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 140, 0, + 0, 11, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 11, 18, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 6, 144, + 144, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 52, 0, 0, 0, 6, 0, + 0, 0, 0, 1, 0, 0, + 2, 0, 0, 0, 28, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h new file mode 100644 index 000000000..5cb5f7499 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_cas_sharpen_ps.h @@ -0,0 +1,491 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeCasSharpenConstants +// { +// +// int2 xe_cas_output_offset; // Offset: 0 Size: 8 +// float xe_cas_sharpness_post_setup; // Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeCasSharpenConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 5 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r0.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r4.xy, r0.zwzz +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +mul r2.xyz, r2.xyzx, r2.xyzx +mul r1.xyz, r1.xyzx, r1.xyzx +mul r0.w, r3.y, r3.y +mul r4.xyz, r4.xyzx, r4.xyzx +mul r0.xyz, r0.xyzx, r0.xyzx +min r1.w, r0.w, r4.y +min r1.w, r1.w, r1.y +min r2.w, r0.y, r2.y +min r1.w, r1.w, r2.w +max r0.w, r0.w, r4.y +max r0.w, r0.w, r1.y +max r2.w, r0.y, r2.y +max r0.w, r0.w, r2.w +iadd r2.w, -r0.w, l(0x7ef07ebb) +add r0.w, -r0.w, l(1.000000) +min r0.w, r0.w, r1.w +mul_sat r0.w, r2.w, r0.w +ushr r0.w, r0.w, l(1) +iadd r0.w, r0.w, l(0x1fbc4639) +mul r0.w, r0.w, CB0[0][0].z +mad r1.w, r0.w, l(4.000000), l(1.000000) +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r1.xyz, r0.wwww, r1.xyzx +mad r1.xyz, r2.xyzx, r0.wwww, r1.xyzx +mad r1.xyz, r4.xyzx, r0.wwww, r1.xyzx +mad r0.xyz, r0.xyzx, r0.wwww, r1.xyzx +mad r0.xyz, r3.xyzx, r3.xyzx, r0.xyzx +mul_sat r0.xyz, r1.wwww, r0.xyzx +sqrt o0.xyz, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 49 instruction slots used +#endif + +const BYTE guest_output_ffx_cas_sharpen_ps[] = +{ + 68, 88, 66, 67, 2, 226, + 230, 16, 201, 205, 207, 54, + 189, 193, 184, 163, 140, 156, + 247, 96, 1, 0, 0, 0, + 40, 9, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 4, 2, 0, 0, 56, 2, + 0, 0, 108, 2, 0, 0, + 140, 8, 0, 0, 82, 68, + 69, 70, 200, 1, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 160, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 67, 97, 115, + 83, 104, 97, 114, 112, 101, + 110, 67, 111, 110, 115, 116, + 97, 110, 116, 115, 0, 171, + 171, 171, 151, 0, 0, 0, + 2, 0, 0, 0, 200, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 24, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 52, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 88, 1, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 124, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 99, 97, 115, 95, 111, + 117, 116, 112, 117, 116, 95, + 111, 102, 102, 115, 101, 116, + 0, 105, 110, 116, 50, 0, + 171, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 1, + 0, 0, 120, 101, 95, 99, + 97, 115, 95, 115, 104, 97, + 114, 112, 110, 101, 115, 115, + 95, 112, 111, 115, 116, 95, + 115, 101, 116, 117, 112, 0, + 102, 108, 111, 97, 116, 0, + 171, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 116, 1, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 3, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 24, 6, 0, 0, 81, 0, + 0, 0, 134, 1, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 7, 70, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 88, 24, 0, 7, + 70, 126, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, + 100, 32, 0, 4, 50, 16, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 5, 0, 0, 0, + 27, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 30, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 128, + 48, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 54, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 3, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 4, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 50, 0, 16, 0, + 4, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 26, 0, 16, 0, 3, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 4, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 26, 0, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 2, 0, 0, 0, 51, 0, + 0, 7, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 4, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 30, 0, 0, 8, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 51, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 56, 32, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 85, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 30, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 57, 70, + 188, 31, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 56, 32, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 75, 0, 0, 5, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 49, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 27, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h new file mode 100644 index 000000000..3c9a5a926 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_easu_ps.h @@ -0,0 +1,2098 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrEasuConstants +// { +// +// float2 xe_fsr_easu_input_output_size_ratio;// Offset: 0 Size: 8 +// float2 xe_fsr_easu_input_size_inv; // Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_sampler_linear_clamp sampler NA NA S0 s0 1 +// xe_texture texture float3 2d T0 t0 1 +// XeFsrEasuConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_sampler S0[0:0], mode_default, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 22 +mul r0.w, CB0[0][0].w, l(4.000000) +mad r0.xy, CB0[0][0].xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), l(-0.500000, -0.500000, 0.000000, 0.000000) +mul r1.xyz, CB0[0][0].zwwz, l(1.000000, 1.000000, -1.000000, 0.000000) +ftou r2.xy, v0.xyxx +utof r2.xy, r2.xyxx +mad r0.xy, r2.xyxx, CB0[0][0].xyxx, r0.xyxx +round_ni r2.xy, r0.xyxx +add r0.xy, r0.xyxx, -r2.xyxx +mad r1.xy, r2.xyxx, r1.xyxx, r1.xzxx +mad r2.xyzw, CB0[0][0].zwzw, l(-1.000000, 2.000000, 1.000000, 2.000000), r1.xyxy +mov r0.z, l(0) +add r0.zw, r0.zzzw, r1.xxxy +gather4 r1.zw, r1.xyxx, T0[0].zwxy, S0[0].x +gather4 r3.xy, r1.xyxx, T0[0].xyzw, S0[0].y +gather4 r4.xz, r1.xyxx, T0[0].xzyw, S0[0].z +gather4 r5.xyzw, r2.xyxx, T0[0].xyzw, S0[0].x +gather4 r6.xyzw, r2.xyxx, T0[0].xyzw, S0[0].y +gather4 r7.xyzw, r2.xyxx, T0[0].yzxw, S0[0].z +gather4 r8.xyzw, r2.zwzz, T0[0].xyzw, S0[0].x +gather4 r9.xyzw, r2.zwzz, T0[0].xyzw, S0[0].y +gather4 r2.xyzw, r2.zwzz, T0[0].xyzw, S0[0].z +gather4 r1.xy, r0.zwzz, T0[0].zwxy, S0[0].x +gather4 r3.zw, r0.zwzz, T0[0].xyzw, S0[0].y +gather4 r10.zw, r0.zwzz, T0[0].xyzw, S0[0].z +mad r0.zw, r1.zzzw, l(0.000000, 0.000000, 0.500000, 0.500000), r3.xxxy +mad r0.zw, r4.xxxz, l(0.000000, 0.000000, 0.500000, 0.500000), r0.zzzw +mad r11.xyzw, r5.zwyx, l(0.500000, 0.500000, 0.500000, 0.500000), r6.zwyx +mad r11.xyzw, r7.ywxz, l(0.500000, 0.500000, 0.500000, 0.500000), r11.xyzw +mad r12.xyzw, r8.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000), r9.xyzw +mad r12.xyzw, r2.xyzw, l(0.500000, 0.500000, 0.500000, 0.500000), r12.xyzw +mad r13.xy, r1.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000), r3.zwzz +mad r13.xy, r10.zwzz, l(0.500000, 0.500000, 0.000000, 0.000000), r13.xyxx +add r14.xyzw, -r0.xyxy, l(1.000000, 1.000000, 0.000000, -1.000000) +mul r4.w, r14.y, r14.x +add r15.xyzw, -r11.xyxz, r12.wwzx +add r16.xyz, -r11.yxwy, r11.xzzx +max r13.zw, |r15.xxxw|, |r16.xxxz| +iadd r13.zw, -r13.zzzw, l(0, 0, 0x7ef07ebb, 0x7ef07ebb) +mul_sat r11.y, r13.z, |r15.y| +mul r11.y, r11.y, r11.y +add r16.xz, -r0.zzzz, r11.xxzx +max r0.z, |r16.x|, |r16.y| +iadd r0.z, -r0.z, l(0x7ef07ebb) +mul_sat r0.z, r0.z, |r16.z| +mul r0.z, r0.z, r0.z +mul r0.z, r4.w, r0.z +mad r0.z, r11.y, r4.w, r0.z +mul r14.xy, r0.xyxx, r14.yxyy +add r17.xyz, -r12.wwxw, r12.zxyz +max r15.xw, |r15.xxxw|, |r17.xxxz| +iadd r15.xw, -r15.xxxw, l(0x7ef07ebb, 0, 0, 0x7ef07ebb) +mul r11.y, r14.x, r15.z +mad r11.y, r15.y, r4.w, r11.y +mul_sat r12.z, r15.x, |r15.z| +mul r12.z, r12.z, r12.z +mad r0.z, r12.z, r14.x, r0.z +add r15.xy, -r0.wwww, r12.wxww +max r0.w, |r15.x|, |r17.y| +iadd r0.w, -r0.w, l(0x7ef07ebb) +mul r12.z, r14.x, r15.y +mad r4.w, r16.z, r4.w, r12.z +mul_sat r0.w, r0.w, |r15.y| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r14.x, r0.z +add r12.yz, -r11.wwzw, r12.xxyx +mad r0.w, r12.y, r14.y, r11.y +mul_sat r11.y, r13.w, |r12.y| +mul r11.y, r11.y, r11.y +mad r0.z, r11.y, r14.y, r0.z +add r11.xy, -r11.zxzz, r13.yyyy +max r11.x, |r16.y|, |r11.x| +iadd r11.x, -r11.x, l(0x7ef07ebb) +mad r4.w, r11.y, r14.y, r4.w +mul_sat r11.x, r11.x, |r11.y| +mul r11.x, r11.x, r11.x +mad r0.z, r11.x, r14.y, r0.z +mul r11.x, r0.y, r0.x +mad r15.y, r12.z, r11.x, r0.w +mul_sat r0.w, r15.w, |r12.z| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r11.x, r0.z +add r11.yz, -r12.xxwx, r13.xxxx +max r0.w, |r17.y|, |r11.y| +iadd r0.w, -r0.w, l(0x7ef07ebb) +mad r15.z, r11.z, r11.x, r4.w +mul_sat r0.w, r0.w, |r11.z| +mul r0.w, r0.w, r0.w +mad r0.z, r0.w, r11.x, r0.z +mul r11.xy, r15.yzyy, r15.yzyy +add r0.w, r11.y, r11.x +lt r4.w, r0.w, l(0.000031) +ushr r0.w, r0.w, l(1) +iadd r0.w, -r0.w, l(0x5f347d74) +movc r0.w, r4.w, l(1.000000), r0.w +movc r15.x, r4.w, l(1.000000), r15.y +mul r11.xy, r0.wwww, r15.xzxx +mul r0.z, r0.z, l(0.500000) +mul r0.z, r0.z, r0.z +dp2 r0.w, r11.xyxx, r11.xyxx +max r4.w, |r11.y|, |r11.x| +iadd r4.w, -r4.w, l(0x7ef07ebb) +mad r0.w, r0.w, r4.w, l(-1.000000) +mad r12.x, r0.w, r0.z, l(1.000000) +mad r12.yz, r0.zzzz, l(0.000000, -0.500000, -0.290000, 0.000000), l(0.000000, 1.000000, 0.500000, 0.000000) +iadd r0.z, -r12.z, l(0x7ef07ebb) +mov r13.x, r8.w +mov r13.y, r9.w +mov r13.z, r2.w +mov r15.x, r5.y +mov r15.y, r6.y +mov r15.z, r7.x +min r16.xyz, r13.xyzx, r15.xyzx +mov r17.x, r5.z +mov r17.y, r6.z +mov r17.z, r7.y +min r16.xyz, r16.xyzx, r17.xyzx +mov r18.x, r8.x +mov r18.y, r9.x +mov r18.z, r2.x +min r16.xyz, r16.xyzx, r18.xyzx +max r19.xyz, r13.xyzx, r15.xyzx +max r19.xyz, r17.xyzx, r19.xyzx +max r19.xyz, r18.xyzx, r19.xyzx +dp2 r14.x, r14.zwzz, r11.xyxx +mul r0.w, r11.x, r14.w +mad r14.y, r14.z, -r11.y, r0.w +mul r5.yz, r12.xxyx, r14.xxyx +dp2 r0.w, r5.yzyy, r5.yzyy +min r0.w, r0.z, r0.w +mad r2.w, r0.w, l(0.400000), l(-1.000000) +mad r0.w, r12.z, r0.w, l(-1.000000) +mul r2.w, r2.w, r2.w +mul r0.w, r0.w, r0.w +mad r2.w, r2.w, l(1.562500), l(-0.562500) +mul r4.w, r0.w, r2.w +mov r14.x, r1.z +mov r14.y, r3.x +mov r14.z, r4.x +add r20.xyzw, -r0.xyxy, l(1.000000, -1.000000, -1.000000, 1.000000) +dp2 r21.y, r20.xyxx, r11.xyxx +mul r5.yz, r11.xxxx, r20.yywy +mad r21.zw, r20.xxxz, -r11.yyyy, r5.yyyz +mul r5.yz, r12.xxyx, r21.yyzy +dp2 r1.z, r5.yzyy, r5.yzyy +min r1.z, r0.z, r1.z +mad r3.x, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r3.x, r3.x, r3.x +mul r1.z, r1.z, r1.z +mad r3.x, r3.x, l(1.562500), l(-0.562500) +mul r1.z, r1.z, r3.x +mov r4.x, r1.w +mov r4.y, r3.y +mul r4.xyz, r1.zzzz, r4.xyzx +mad r4.xyz, r14.xyzx, r4.wwww, r4.xyzx +mad r0.w, r2.w, r0.w, r1.z +dp2 r21.x, r20.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r21.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r7.x, r5.x +mov r7.y, r6.x +mad r4.xyz, r7.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r14.xyzw, -r0.xyxy, l(0.000000, 1.000000, -1.000000, 0.000000) +dp2 r20.y, r14.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r14.yyyw +mad r20.zw, r14.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r20.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r15.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r3.x, -r0.xyxx, r11.xyxx +mul r1.z, -r0.y, r11.x +mad r3.y, r0.x, r11.y, r1.z +mul r1.zw, r12.xxxy, r3.xxxy +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r17.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r20.x, r14.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r20.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r7.z, r5.w +mov r7.x, r6.w +mad r4.xyz, r7.zxwz, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r5.xyzw, -r0.xyxy, l(1.000000, 1.000000, 2.000000, 1.000000) +dp2 r6.y, r5.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r5.yyyw +mad r6.zw, r5.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r6.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r4.xyz, r18.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r6.x, r5.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r6.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r5.x, r8.y +mov r5.y, r9.y +mov r5.z, r2.y +mad r4.xyz, r5.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r5.xyzw, -r0.xyxy, l(2.000000, 0.000000, 1.000000, 0.000000) +dp2 r6.y, r5.xyxx, r11.xyxx +mul r1.zw, r11.xxxx, r5.yyyw +mad r6.zw, r5.xxxz, -r11.yyyy, r1.zzzw +mul r1.zw, r12.xxxy, r6.yyyz +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mov r2.x, r8.z +mov r2.y, r9.z +mad r2.xyz, r2.xyzx, r2.wwww, r4.xyzx +mad r0.w, r1.w, r1.z, r0.w +dp2 r6.x, r5.zwzz, r11.xyxx +mul r1.zw, r12.xxxy, r6.xxxw +dp2 r1.z, r1.zwzz, r1.zwzz +min r1.z, r0.z, r1.z +mad r1.w, r1.z, l(0.400000), l(-1.000000) +mad r1.z, r12.z, r1.z, l(-1.000000) +mul r1.zw, r1.zzzw, r1.zzzw +mad r1.w, r1.w, l(1.562500), l(-0.562500) +mul r2.w, r1.z, r1.w +mad r2.xyz, r13.xyzx, r2.wwww, r2.xyzx +mad r0.w, r1.w, r1.z, r0.w +add r4.xyzw, -r0.xyxy, l(1.000000, 2.000000, 0.000000, 2.000000) +dp2 r5.y, r4.xyxx, r11.xyxx +mul r0.xy, r11.xxxx, r4.ywyy +mad r5.zw, r4.xxxz, -r11.yyyy, r0.xxxy +mul r0.xy, r12.xyxx, r5.yzyy +dp2 r0.x, r0.xyxx, r0.xyxx +min r0.x, r0.z, r0.x +mad r0.y, r0.x, l(0.400000), l(-1.000000) +mad r0.x, r12.z, r0.x, l(-1.000000) +mul r0.xy, r0.xyxx, r0.xyxx +mad r0.y, r0.y, l(1.562500), l(-0.562500) +mul r1.z, r0.x, r0.y +mov r10.x, r1.x +mov r10.y, r3.z +mad r1.xzw, r10.xxyz, r1.zzzz, r2.xxyz +mad r0.x, r0.y, r0.x, r0.w +dp2 r5.x, r4.zwzz, r11.xyxx +mul r0.yw, r12.xxxy, r5.xxxw +dp2 r0.y, r0.ywyy, r0.ywyy +min r0.y, r0.z, r0.y +mad r0.z, r0.y, l(0.400000), l(-1.000000) +mad r0.y, r12.z, r0.y, l(-1.000000) +mul r0.yz, r0.yyzy, r0.yyzy +mad r0.z, r0.z, l(1.562500), l(-0.562500) +mul r0.w, r0.y, r0.z +mov r10.x, r1.y +mov r10.y, r3.w +mad r1.xyz, r10.xywx, r0.wwww, r1.xzwx +mad r0.x, r0.z, r0.y, r0.x +rcp r0.x, r0.x +mul r0.xyz, r0.xxxx, r1.xyzx +max r0.xyz, r0.xyzx, r16.xyzx +min o0.xyz, r0.xyzx, r19.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 299 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_easu_ps[] = +{ + 68, 88, 66, 67, 240, 45, + 22, 153, 167, 152, 10, 67, + 48, 29, 75, 57, 104, 138, + 197, 43, 1, 0, 0, 0, + 236, 40, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 36, 2, 0, 0, 88, 2, + 0, 0, 140, 2, 0, 0, + 80, 40, 0, 0, 82, 68, + 69, 70, 232, 1, 0, 0, + 1, 0, 0, 0, 236, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 191, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 180, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 120, 101, 95, 115, 97, 109, + 112, 108, 101, 114, 95, 108, + 105, 110, 101, 97, 114, 95, + 99, 108, 97, 109, 112, 0, + 120, 101, 95, 116, 101, 120, + 116, 117, 114, 101, 0, 88, + 101, 70, 115, 114, 69, 97, + 115, 117, 67, 111, 110, 115, + 116, 97, 110, 116, 115, 0, + 171, 171, 215, 0, 0, 0, + 2, 0, 0, 0, 4, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 84, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 164, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 128, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 120, 101, + 95, 102, 115, 114, 95, 101, + 97, 115, 117, 95, 105, 110, + 112, 117, 116, 95, 111, 117, + 116, 112, 117, 116, 95, 115, + 105, 122, 101, 95, 114, 97, + 116, 105, 111, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 1, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 101, 97, 115, 117, 95, + 105, 110, 112, 117, 116, 95, + 115, 105, 122, 101, 95, 105, + 110, 118, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 49, 48, 46, 49, + 0, 171, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 3, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 188, 37, 0, 0, + 81, 0, 0, 0, 111, 9, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 90, 0, + 0, 6, 70, 110, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 24, + 0, 7, 70, 126, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 0, 0, + 0, 0, 100, 32, 0, 4, + 50, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 22, 0, + 0, 0, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 50, 0, 0, 17, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 191, 0, 0, + 0, 191, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, + 0, 12, 114, 0, 16, 0, + 1, 0, 0, 0, 230, 139, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 0, 0, 28, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 11, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 70, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 65, 0, + 0, 5, 50, 0, 16, 0, + 2, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 128, + 65, 0, 0, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 50, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 134, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 14, + 242, 0, 16, 0, 2, 0, + 0, 0, 230, 142, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 191, 0, 0, 0, 64, + 0, 0, 128, 63, 0, 0, + 0, 64, 70, 4, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 194, 0, + 16, 0, 0, 0, 0, 0, + 166, 14, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 1, 0, 0, 0, 109, 0, + 0, 11, 194, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 230, 116, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 50, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 0, 1, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 82, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 1, 0, 0, 0, 134, 125, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 0, + 16, 0, 2, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 242, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 242, 0, 16, 0, 7, 0, + 0, 0, 70, 0, 16, 0, + 2, 0, 0, 0, 150, 124, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 242, 0, 16, 0, + 8, 0, 0, 0, 230, 10, + 16, 0, 2, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 242, 0, + 16, 0, 9, 0, 0, 0, + 230, 10, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 242, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 2, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 0, + 0, 11, 50, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 0, 0, 0, 0, + 230, 116, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 10, 96, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 0, 0, 11, 194, 0, + 16, 0, 3, 0, 0, 0, + 230, 10, 16, 0, 0, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 26, 96, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 0, 0, 11, + 194, 0, 16, 0, 10, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 42, 96, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 194, 0, 16, 0, + 0, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 6, 4, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 8, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, + 0, 63, 166, 14, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 11, 0, 0, 0, 230, 1, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 230, 1, 16, 0, + 6, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 11, 0, 0, 0, 214, 8, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 8, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 9, 0, 0, 0, 50, 0, + 0, 12, 242, 0, 16, 0, + 12, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, + 0, 63, 70, 14, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 12, 50, 0, 16, 0, + 13, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 230, 10, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 12, 50, 0, 16, 0, + 13, 0, 0, 0, 230, 10, + 16, 0, 10, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 13, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 14, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 0, 0, + 0, 8, 242, 0, 16, 0, + 15, 0, 0, 0, 70, 8, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 246, 2, + 16, 0, 12, 0, 0, 0, + 0, 0, 0, 8, 114, 0, + 16, 0, 16, 0, 0, 0, + 22, 7, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 134, 2, 16, 0, 11, 0, + 0, 0, 52, 0, 0, 9, + 194, 0, 16, 0, 13, 0, + 0, 0, 6, 12, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 6, 8, 16, 128, + 129, 0, 0, 0, 16, 0, + 0, 0, 30, 0, 0, 11, + 194, 0, 16, 0, 13, 0, + 0, 0, 166, 14, 16, 128, + 65, 0, 0, 0, 13, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 126, 240, 126, + 187, 126, 240, 126, 56, 32, + 0, 8, 34, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 13, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 15, 0, 0, 0, + 56, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 0, 0, + 0, 8, 82, 0, 16, 0, + 16, 0, 0, 0, 166, 10, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 6, 2, + 16, 0, 11, 0, 0, 0, + 52, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 30, 0, 0, 8, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 56, 32, 0, 8, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 128, 129, 0, 0, 0, + 16, 0, 0, 0, 56, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 50, 0, + 16, 0, 14, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 22, 5, 16, 0, + 14, 0, 0, 0, 0, 0, + 0, 8, 114, 0, 16, 0, + 17, 0, 0, 0, 246, 12, + 16, 128, 65, 0, 0, 0, + 12, 0, 0, 0, 38, 9, + 16, 0, 12, 0, 0, 0, + 52, 0, 0, 9, 146, 0, + 16, 0, 15, 0, 0, 0, + 6, 12, 16, 128, 129, 0, + 0, 0, 15, 0, 0, 0, + 6, 8, 16, 128, 129, 0, + 0, 0, 17, 0, 0, 0, + 30, 0, 0, 11, 146, 0, + 16, 0, 15, 0, 0, 0, + 6, 12, 16, 128, 65, 0, + 0, 0, 15, 0, 0, 0, + 2, 64, 0, 0, 187, 126, + 240, 126, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 126, + 240, 126, 56, 0, 0, 7, + 34, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 15, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 56, 32, 0, 8, 66, 0, + 16, 0, 12, 0, 0, 0, + 10, 0, 16, 0, 15, 0, + 0, 0, 42, 0, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 14, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 50, 0, + 16, 0, 15, 0, 0, 0, + 246, 15, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 54, 15, 16, 0, 12, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 128, + 129, 0, 0, 0, 15, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 17, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 56, 0, + 0, 7, 66, 0, 16, 0, + 12, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 26, 0, 16, 0, 15, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 42, 0, 16, 0, + 16, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 56, 32, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 15, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 98, 0, 16, 0, 12, 0, + 0, 0, 246, 14, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 6, 1, 16, 0, + 12, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 56, 32, + 0, 8, 34, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 13, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 12, 0, 0, 0, + 56, 0, 0, 7, 34, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 50, 0, 16, 0, + 11, 0, 0, 0, 38, 10, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 86, 5, + 16, 0, 13, 0, 0, 0, + 52, 0, 0, 9, 18, 0, + 16, 0, 11, 0, 0, 0, + 26, 0, 16, 128, 129, 0, + 0, 0, 16, 0, 0, 0, + 10, 0, 16, 128, 129, 0, + 0, 0, 11, 0, 0, 0, + 30, 0, 0, 8, 18, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 1, 64, 0, 0, 187, 126, + 240, 126, 50, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 14, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 56, 32, 0, 8, + 18, 0, 16, 0, 11, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 128, 129, 0, 0, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 18, 0, 16, 0, + 11, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 26, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 11, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 15, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 32, 0, 8, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 15, 0, + 0, 0, 42, 0, 16, 128, + 129, 0, 0, 0, 12, 0, + 0, 0, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 66, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 98, 0, + 16, 0, 11, 0, 0, 0, + 6, 3, 16, 128, 65, 0, + 0, 0, 12, 0, 0, 0, + 6, 0, 16, 0, 13, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 17, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 50, 0, + 0, 9, 66, 0, 16, 0, + 15, 0, 0, 0, 42, 0, + 16, 0, 11, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 58, 0, 16, 0, + 4, 0, 0, 0, 56, 32, + 0, 8, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 129, 0, + 0, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 11, 0, 0, 0, 150, 5, + 16, 0, 15, 0, 0, 0, + 150, 5, 16, 0, 15, 0, + 0, 0, 0, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 11, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 49, 0, 0, 7, 130, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 56, 85, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 116, 125, 52, 95, 55, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 58, 0, 16, 0, + 0, 0, 0, 0, 55, 0, + 0, 9, 18, 0, 16, 0, + 15, 0, 0, 0, 58, 0, + 16, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 26, 0, 16, 0, + 15, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 11, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 134, 0, 16, 0, 15, 0, + 0, 0, 56, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 0, 63, + 56, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 15, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 52, 0, 0, 9, + 130, 0, 16, 0, 4, 0, + 0, 0, 26, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 10, 0, 16, 128, + 129, 0, 0, 0, 11, 0, + 0, 0, 30, 0, 0, 8, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 187, 126, 240, 126, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 18, 0, 16, 0, + 12, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 50, 0, + 0, 15, 98, 0, 16, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, + 225, 122, 148, 190, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 0, 0, 0, 63, + 0, 0, 0, 0, 30, 0, + 0, 8, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 128, 65, 0, 0, 0, + 12, 0, 0, 0, 1, 64, + 0, 0, 187, 126, 240, 126, + 54, 0, 0, 5, 18, 0, + 16, 0, 13, 0, 0, 0, + 58, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 13, 0, + 0, 0, 58, 0, 16, 0, + 9, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 13, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 15, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 15, 0, + 0, 0, 26, 0, 16, 0, + 6, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 15, 0, 0, 0, 10, 0, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 17, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 17, 0, 0, 0, + 42, 0, 16, 0, 6, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 17, 0, + 0, 0, 26, 0, 16, 0, + 7, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 16, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 18, 0, + 0, 0, 10, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 18, 0, 0, 0, 10, 0, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 18, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 16, 0, + 0, 0, 70, 2, 16, 0, + 16, 0, 0, 0, 70, 2, + 16, 0, 18, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 19, 0, 0, 0, + 70, 2, 16, 0, 13, 0, + 0, 0, 70, 2, 16, 0, + 15, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 19, 0, 0, 0, 70, 2, + 16, 0, 17, 0, 0, 0, + 70, 2, 16, 0, 19, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 19, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 14, 0, 0, 0, + 230, 10, 16, 0, 14, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 11, 0, 0, 0, + 58, 0, 16, 0, 14, 0, + 0, 0, 50, 0, 0, 10, + 34, 0, 16, 0, 14, 0, + 0, 0, 42, 0, 16, 0, + 14, 0, 0, 0, 26, 0, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 98, 0, + 16, 0, 5, 0, 0, 0, + 6, 1, 16, 0, 12, 0, + 0, 0, 6, 1, 16, 0, + 14, 0, 0, 0, 15, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 150, 5, + 16, 0, 5, 0, 0, 0, + 150, 5, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 14, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 14, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 14, 0, 0, 0, 10, 0, + 16, 0, 4, 0, 0, 0, + 0, 0, 0, 11, 242, 0, + 16, 0, 20, 0, 0, 0, + 70, 4, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 128, 191, 0, 0, + 128, 63, 15, 0, 0, 7, + 34, 0, 16, 0, 21, 0, + 0, 0, 70, 0, 16, 0, + 20, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 98, 0, + 16, 0, 5, 0, 0, 0, + 6, 0, 16, 0, 11, 0, + 0, 0, 86, 7, 16, 0, + 20, 0, 0, 0, 50, 0, + 0, 10, 194, 0, 16, 0, + 21, 0, 0, 0, 6, 8, + 16, 0, 20, 0, 0, 0, + 86, 5, 16, 128, 65, 0, + 0, 0, 11, 0, 0, 0, + 86, 9, 16, 0, 5, 0, + 0, 0, 56, 0, 0, 7, + 98, 0, 16, 0, 5, 0, + 0, 0, 6, 1, 16, 0, + 12, 0, 0, 0, 86, 6, + 16, 0, 21, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 150, 5, 16, 0, 5, 0, + 0, 0, 150, 5, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 18, 0, 16, 0, 3, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 18, 0, 16, 0, 3, 0, + 0, 0, 10, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 3, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 10, 0, 16, 0, 3, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 4, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 4, 0, 0, 0, 26, 0, + 16, 0, 3, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 4, 0, 0, 0, + 166, 10, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 14, 0, 0, 0, + 246, 15, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 21, 0, 0, 0, 230, 10, + 16, 0, 20, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 4, 16, 0, + 12, 0, 0, 0, 6, 12, + 16, 0, 21, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 200, 63, 1, 64, + 0, 0, 0, 0, 16, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 7, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 7, 0, 0, 0, + 10, 0, 16, 0, 6, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 7, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 11, + 242, 0, 16, 0, 14, 0, + 0, 0, 70, 4, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 0, 0, 15, 0, + 0, 7, 34, 0, 16, 0, + 20, 0, 0, 0, 70, 0, + 16, 0, 14, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 11, 0, 0, 0, 86, 13, + 16, 0, 14, 0, 0, 0, + 50, 0, 0, 10, 194, 0, + 16, 0, 20, 0, 0, 0, + 6, 8, 16, 0, 14, 0, + 0, 0, 86, 5, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 86, 9, 16, 0, 20, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 15, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 8, 18, 0, + 16, 0, 3, 0, 0, 0, + 70, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 26, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 11, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 3, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 11, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 4, 16, 0, 3, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 17, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 20, 0, 0, 0, + 230, 10, 16, 0, 14, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 12, 16, 0, 20, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 7, 0, 0, 0, + 58, 0, 16, 0, 5, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 7, 0, + 0, 0, 58, 0, 16, 0, + 6, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 4, 0, 0, 0, 38, 11, + 16, 0, 7, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 5, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 64, 0, 0, 128, 63, + 15, 0, 0, 7, 34, 0, + 16, 0, 6, 0, 0, 0, + 70, 0, 16, 0, 5, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 86, 13, 16, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 194, 0, 16, 0, 6, 0, + 0, 0, 6, 8, 16, 0, + 5, 0, 0, 0, 86, 5, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 6, 4, 16, 0, 12, 0, + 0, 0, 86, 9, 16, 0, + 6, 0, 0, 0, 15, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 18, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 15, 0, 0, 7, + 18, 0, 16, 0, 6, 0, + 0, 0, 230, 10, 16, 0, + 5, 0, 0, 0, 70, 0, + 16, 0, 11, 0, 0, 0, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 6, 4, 16, 0, 12, 0, + 0, 0, 6, 12, 16, 0, + 6, 0, 0, 0, 15, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 51, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 194, 0, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 8, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 5, 0, 0, 0, 26, 0, + 16, 0, 9, 0, 0, 0, + 54, 0, 0, 5, 66, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 2, 0, + 0, 0, 50, 0, 0, 9, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 11, + 242, 0, 16, 0, 5, 0, + 0, 0, 70, 4, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 0, 15, 0, + 0, 7, 34, 0, 16, 0, + 6, 0, 0, 0, 70, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 11, 0, 0, 0, 86, 13, + 16, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 194, 0, + 16, 0, 6, 0, 0, 0, + 6, 8, 16, 0, 5, 0, + 0, 0, 86, 5, 16, 128, + 65, 0, 0, 0, 11, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 86, 9, 16, 0, 6, 0, + 0, 0, 15, 0, 0, 7, + 66, 0, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 230, 10, + 16, 0, 1, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 194, 0, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 166, 14, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 8, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 2, 0, + 0, 0, 42, 0, 16, 0, + 9, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 6, 0, 0, 0, 230, 10, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 11, 0, + 0, 0, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 6, 4, 16, 0, + 12, 0, 0, 0, 6, 12, + 16, 0, 6, 0, 0, 0, + 15, 0, 0, 7, 66, 0, + 16, 0, 1, 0, 0, 0, + 230, 10, 16, 0, 1, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 51, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 205, 204, 204, 62, + 1, 64, 0, 0, 0, 0, + 128, 191, 50, 0, 0, 9, + 66, 0, 16, 0, 1, 0, + 0, 0, 42, 0, 16, 0, + 12, 0, 0, 0, 42, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 56, 0, 0, 7, + 194, 0, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 1, 0, 0, 0, 166, 14, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 9, 130, 0, + 16, 0, 1, 0, 0, 0, + 58, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 200, 63, 1, 64, + 0, 0, 0, 0, 16, 191, + 56, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 13, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 50, 0, + 0, 9, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 11, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 4, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 0, 64, + 15, 0, 0, 7, 34, 0, + 16, 0, 5, 0, 0, 0, + 70, 0, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 50, 0, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 11, 0, 0, 0, + 214, 5, 16, 0, 4, 0, + 0, 0, 50, 0, 0, 10, + 194, 0, 16, 0, 5, 0, + 0, 0, 6, 8, 16, 0, + 4, 0, 0, 0, 86, 5, + 16, 128, 65, 0, 0, 0, + 11, 0, 0, 0, 6, 4, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 12, 0, + 0, 0, 150, 5, 16, 0, + 5, 0, 0, 0, 15, 0, + 0, 7, 18, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 51, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 34, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 205, 204, 204, 62, 1, 64, + 0, 0, 0, 0, 128, 191, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 12, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 56, 0, 0, 7, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 34, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 200, 63, 1, 64, 0, 0, + 0, 0, 16, 191, 56, 0, + 0, 7, 66, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 18, 0, 16, 0, 10, 0, + 0, 0, 10, 0, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 10, 0, 0, 0, 42, 0, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 9, 210, 0, + 16, 0, 1, 0, 0, 0, + 6, 9, 16, 0, 10, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 6, 9, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 15, 0, 0, 7, 18, 0, + 16, 0, 5, 0, 0, 0, + 230, 10, 16, 0, 4, 0, + 0, 0, 70, 0, 16, 0, + 11, 0, 0, 0, 56, 0, + 0, 7, 162, 0, 16, 0, + 0, 0, 0, 0, 6, 4, + 16, 0, 12, 0, 0, 0, + 6, 12, 16, 0, 5, 0, + 0, 0, 15, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 214, 5, 16, 0, + 0, 0, 0, 0, 214, 5, + 16, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 34, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 66, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 205, 204, + 204, 62, 1, 64, 0, 0, + 0, 0, 128, 191, 50, 0, + 0, 9, 34, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 12, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 56, 0, + 0, 7, 98, 0, 16, 0, + 0, 0, 0, 0, 86, 6, + 16, 0, 0, 0, 0, 0, + 86, 6, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 200, 63, + 1, 64, 0, 0, 0, 0, + 16, 191, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 26, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 10, 0, 0, 0, + 26, 0, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 34, 0, 16, 0, 10, 0, + 0, 0, 58, 0, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 3, + 16, 0, 10, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 134, 3, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 18, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 129, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 16, 0, + 0, 0, 51, 0, 0, 7, + 114, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 19, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 43, 1, 0, 0, + 22, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 239, 0, 0, 0, 9, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 32, 0, 0, 0, 2, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h new file mode 100644 index 000000000..71dd6c93b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_dither_ps.h @@ -0,0 +1,1457 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrRcasConstants +// { +// +// int2 xe_fsr_rcas_output_offset; // Offset: 0 Size: 8 +// float xe_fsr_rcas_sharpness_post_setup;// Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeFsrRcasConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_immediateConstantBuffer { { -0.001003, 0, 0, 0}, + { 0.000881, 0, 0, 0}, + { 0.001693, 0, 0, 0}, + { -0.001555, 0, 0, 0}, + { 0.001279, 0, 0, 0}, + { -0.000605, 0, 0, 0}, + { 0.001065, 0, 0, 0}, + { -0.001386, 0, 0, 0}, + { 0.001356, 0, 0, 0}, + { 0.000513, 0, 0, 0}, + { 0.001218, 0, 0, 0}, + { -0.001601, 0, 0, 0}, + { 0.000590, 0, 0, 0}, + { -0.000283, 0, 0, 0}, + { 0.001111, 0, 0, 0}, + { -0.001417, 0, 0, 0}, + { 0.001448, 0, 0, 0}, + { -0.000544, 0, 0, 0}, + { 0.000130, 0, 0, 0}, + { -0.001203, 0, 0, 0}, + { 0.000437, 0, 0, 0}, + { -0.001049, 0, 0, 0}, + { 0.000620, 0, 0, 0}, + { -0.000483, 0, 0, 0}, + { 0.001877, 0, 0, 0}, + { -0.001095, 0, 0, 0}, + { -0.000100, 0, 0, 0}, + { -0.000528, 0, 0, 0}, + { 0.001432, 0, 0, 0}, + { -0.001938, 0, 0, 0}, + { -0.000697, 0, 0, 0}, + { 0.000038, 0, 0, 0}, + { 0.000712, 0, 0, 0}, + { -0.001310, 0, 0, 0}, + { 0.001095, 0, 0, 0}, + { -0.000299, 0, 0, 0}, + { 0.001754, 0, 0, 0}, + { -0.001677, 0, 0, 0}, + { 0.001478, 0, 0, 0}, + { -0.000038, 0, 0, 0}, + { 0.000789, 0, 0, 0}, + { -0.001831, 0, 0, 0}, + { 0.000299, 0, 0, 0}, + { 0.000988, 0, 0, 0}, + { -0.001172, 0, 0, 0}, + { 0.000176, 0, 0, 0}, + { 0.001647, 0, 0, 0}, + { -0.001585, 0, 0, 0}, + { 0.000345, 0, 0, 0}, + { 0.001861, 0, 0, 0}, + { -0.001769, 0, 0, 0}, + { -0.000866, 0, 0, 0}, + { 0.000896, 0, 0, 0}, + { 0.000161, 0, 0, 0}, + { -0.000927, 0, 0, 0}, + { -0.001524, 0, 0, 0}, + { -0.000651, 0, 0, 0}, + { 0.001294, 0, 0, 0}, + { -0.000804, 0, 0, 0}, + { -0.001463, 0, 0, 0}, + { 0.001800, 0, 0, 0}, + { -0.000850, 0, 0, 0}, + { 0.000850, 0, 0, 0}, + { -0.000452, 0, 0, 0}, + { -0.001065, 0, 0, 0}, + { -0.000146, 0, 0, 0}, + { 0.000237, 0, 0, 0}, + { 0.001417, 0, 0, 0}, + { -0.000590, 0, 0, 0}, + { -0.000191, 0, 0, 0}, + { 0.001601, 0, 0, 0}, + { 0.001019, 0, 0, 0}, + { 0.000406, 0, 0, 0}, + { -0.000207, 0, 0, 0}, + { 0.001585, 0, 0, 0}, + { 0.000651, 0, 0, 0}, + { -0.000069, 0, 0, 0}, + { 0.000421, 0, 0, 0}, + { -0.001647, 0, 0, 0}, + { 0.001371, 0, 0, 0}, + { 0.000927, 0, 0, 0}, + { -0.000666, 0, 0, 0}, + { 0.001187, 0, 0, 0}, + { -0.001448, 0, 0, 0}, + { 0.000574, 0, 0, 0}, + { -0.001892, 0, 0, 0}, + { 0.000758, 0, 0, 0}, + { -0.001294, 0, 0, 0}, + { 0.001922, 0, 0, 0}, + { -0.001662, 0, 0, 0}, + { -0.001034, 0, 0, 0}, + { -0.000498, 0, 0, 0}, + { -0.001861, 0, 0, 0}, + { 0.001203, 0, 0, 0}, + { -0.000329, 0, 0, 0}, + { -0.001371, 0, 0, 0}, + { 0.001631, 0, 0, 0}, + { -0.001846, 0, 0, 0}, + { 0.000728, 0, 0, 0}, + { -0.000911, 0, 0, 0}, + { 0.001815, 0, 0, 0}, + { -0.001141, 0, 0, 0}, + { -0.000375, 0, 0, 0}, + { 0.000100, 0, 0, 0}, + { -0.000743, 0, 0, 0}, + { 0.001172, 0, 0, 0}, + { 0.000069, 0, 0, 0}, + { 0.001494, 0, 0, 0}, + { 0.000973, 0, 0, 0}, + { -0.000957, 0, 0, 0}, + { 0.001938, 0, 0, 0}, + { 0.000528, 0, 0, 0}, + { 0.000054, 0, 0, 0}, + { -0.001248, 0, 0, 0}, + { -0.000268, 0, 0, 0}, + { 0.001540, 0, 0, 0}, + { -0.000008, 0, 0, 0}, + { 0.000314, 0, 0, 0}, + { 0.001340, 0, 0, 0}, + { -0.001754, 0, 0, 0}, + { 0.000498, 0, 0, 0}, + { -0.001187, 0, 0, 0}, + { 0.000774, 0, 0, 0}, + { -0.001340, 0, 0, 0}, + { 0.000268, 0, 0, 0}, + { -0.001478, 0, 0, 0}, + { -0.000130, 0, 0, 0}, + { -0.000774, 0, 0, 0}, + { 0.001310, 0, 0, 0}, + { 0.000391, 0, 0, 0}, + { 0.000957, 0, 0, 0}, + { -0.000467, 0, 0, 0}, + { -0.001540, 0, 0, 0}, + { 0.001034, 0, 0, 0}, + { -0.000682, 0, 0, 0}, + { 0.001677, 0, 0, 0}, + { 0.001003, 0, 0, 0}, + { -0.000421, 0, 0, 0}, + { 0.001785, 0, 0, 0}, + { -0.000237, 0, 0, 0}, + { -0.000620, 0, 0, 0}, + { 0.001662, 0, 0, 0}, + { 0.000835, 0, 0, 0}, + { -0.001723, 0, 0, 0}, + { -0.001080, 0, 0, 0}, + { 0.001769, 0, 0, 0}, + { -0.000789, 0, 0, 0}, + { -0.001785, 0, 0, 0}, + { 0.000682, 0, 0, 0}, + { -0.000988, 0, 0, 0}, + { -0.001325, 0, 0, 0}, + { -0.000176, 0, 0, 0}, + { -0.001509, 0, 0, 0}, + { 0.000329, 0, 0, 0}, + { -0.001953, 0, 0, 0}, + { 0.000666, 0, 0, 0}, + { -0.001616, 0, 0, 0}, + { 0.001157, 0, 0, 0}, + { 0.000452, 0, 0, 0}, + { -0.000437, 0, 0, 0}, + { 0.000191, 0, 0, 0}, + { -0.001494, 0, 0, 0}, + { 0.001141, 0, 0, 0}, + { 0.000084, 0, 0, 0}, + { 0.001892, 0, 0, 0}, + { 0.001402, 0, 0, 0}, + { 0.000559, 0, 0, 0}, + { 0.000115, 0, 0, 0}, + { 0.001264, 0, 0, 0}, + { -0.000574, 0, 0, 0}, + { -0.000973, 0, 0, 0}, + { 0.001325, 0, 0, 0}, + { 0.000222, 0, 0, 0}, + { -0.000758, 0, 0, 0}, + { -0.001356, 0, 0, 0}, + { 0.001463, 0, 0, 0}, + { 0.000866, 0, 0, 0}, + { -0.000360, 0, 0, 0}, + { 0.000544, 0, 0, 0}, + { -0.001126, 0, 0, 0}, + { -0.000253, 0, 0, 0}, + { -0.000559, 0, 0, 0}, + { -0.001815, 0, 0, 0}, + { 0.001723, 0, 0, 0}, + { -0.001157, 0, 0, 0}, + { 0.000743, 0, 0, 0}, + { 0.001570, 0, 0, 0}, + { -0.000115, 0, 0, 0}, + { -0.001218, 0, 0, 0}, + { 0.001831, 0, 0, 0}, + { 0.000023, 0, 0, 0}, + { -0.001922, 0, 0, 0}, + { 0.001739, 0, 0, 0}, + { -0.000712, 0, 0, 0}, + { 0.001555, 0, 0, 0}, + { -0.001708, 0, 0, 0}, + { 0.001233, 0, 0, 0}, + { 0.000207, 0, 0, 0}, + { 0.001049, 0, 0, 0}, + { -0.000728, 0, 0, 0}, + { -0.001631, 0, 0, 0}, + { -0.000314, 0, 0, 0}, + { 0.000483, 0, 0, 0}, + { -0.001800, 0, 0, 0}, + { 0.000942, 0, 0, 0}, + { -0.000345, 0, 0, 0}, + { 0.000697, 0, 0, 0}, + { -0.001019, 0, 0, 0}, + { -0.001570, 0, 0, 0}, + { -0.000023, 0, 0, 0}, + { -0.001279, 0, 0, 0}, + { 0.000804, 0, 0, 0}, + { -0.000896, 0, 0, 0}, + { -0.001432, 0, 0, 0}, + { 0.000605, 0, 0, 0}, + { -0.000084, 0, 0, 0}, + { 0.000911, 0, 0, 0}, + { 0.001953, 0, 0, 0}, + { -0.001402, 0, 0, 0}, + { -0.000636, 0, 0, 0}, + { 0.001509, 0, 0, 0}, + { -0.000820, 0, 0, 0}, + { 0.001248, 0, 0, 0}, + { 0.000253, 0, 0, 0}, + { 0.001524, 0, 0, 0}, + { 0.001126, 0, 0, 0}, + { 0.000360, 0, 0, 0}, + { -0.000391, 0, 0, 0}, + { 0.001907, 0, 0, 0}, + { 0.001386, 0, 0, 0}, + { -0.001111, 0, 0, 0}, + { 0.001616, 0, 0, 0}, + { -0.000881, 0, 0, 0}, + { 0.000146, 0, 0, 0}, + { 0.001080, 0, 0, 0}, + { -0.000054, 0, 0, 0}, + { 0.000283, 0, 0, 0}, + { -0.001693, 0, 0, 0}, + { -0.001264, 0, 0, 0}, + { -0.000513, 0, 0, 0}, + { -0.000161, 0, 0, 0}, + { -0.001877, 0, 0, 0}, + { -0.000835, 0, 0, 0}, + { 0.000636, 0, 0, 0}, + { 0.000008, 0, 0, 0}, + { -0.001907, 0, 0, 0}, + { -0.000222, 0, 0, 0}, + { 0.000375, 0, 0, 0}, + { -0.001739, 0, 0, 0}, + { -0.000406, 0, 0, 0}, + { -0.001233, 0, 0, 0}, + { 0.001708, 0, 0, 0}, + { -0.000942, 0, 0, 0}, + { 0.000820, 0, 0, 0}, + { 0.001846, 0, 0, 0}, + { 0.000467, 0, 0, 0} } +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 10 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r4.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r5.xy, r4.zwzz +mov r5.zw, l(0,0,0,0) +ld r5.xyz, r5.xyzw, T0[0].xyzw +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +min r6.xyz, r1.xyzx, r5.xyzx +min r6.xyz, r2.xyzx, r6.xyzx +min r6.xyz, r4.xyzx, r6.xyzx +max r7.xyz, r1.xyzx, r5.xyzx +max r7.xyz, r2.xyzx, r7.xyzx +max r7.xyz, r4.xyzx, r7.xyzx +min r8.xyz, r3.xyzx, r6.xyzx +mul r9.xyz, r7.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000) +rcp r9.xyz, r9.xyzx +mul r8.xyz, r8.xyzx, r9.xyzx +max r7.xyz, r3.xyzx, r7.xyzx +add r7.xyz, -r7.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) +mad r6.xyz, r6.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000), l(-4.000000, -4.000000, -4.000000, 0.000000) +rcp r6.xyz, r6.xyzx +mul r6.xyz, r6.xyzx, r7.xyzx +max r6.xyz, r6.xyzx, -r8.xyzx +max r0.z, r6.z, r6.y +max r0.z, r0.z, r6.x +min r0.z, r0.z, l(0.000000) +max r0.z, r0.z, l(-0.187500) +mul r0.z, r0.z, CB0[0][0].z +mad r0.w, r0.z, l(4.000000), l(1.000000) +iadd r1.w, -r0.w, l(0x7ef19fff) +mad r0.w, -r1.w, r0.w, l(2.000000) +mul r0.w, r0.w, r1.w +mul r1.xyz, r1.xyzx, r0.zzzz +mad r1.xyz, r0.zzzz, r2.xyzx, r1.xyzx +mad r1.xyz, r0.zzzz, r4.xyzx, r1.xyzx +mad r1.xyz, r0.zzzz, r5.xyzx, r1.xyzx +add r1.xyz, r3.xyzx, r1.xyzx +bfi r0.y, l(4), l(4), r0.y, l(0) +bfi r0.x, l(4), l(0), r0.x, r0.y +mad o0.xyz, r1.xyzx, r0.wwww, icb[r0.x + 0].xxxx +mov o0.w, l(1.000000) +ret +// Approximately 51 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_rcas_dither_ps[] = +{ + 68, 88, 66, 67, 171, 87, + 217, 222, 87, 57, 211, 199, + 141, 108, 123, 139, 108, 18, + 226, 124, 1, 0, 0, 0, + 192, 25, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 8, 2, 0, 0, 60, 2, + 0, 0, 112, 2, 0, 0, + 36, 25, 0, 0, 82, 68, + 69, 70, 204, 1, 0, 0, + 1, 0, 0, 0, 172, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 164, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 70, 115, 114, + 82, 99, 97, 115, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 151, 0, + 0, 0, 2, 0, 0, 0, + 196, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 52, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 88, 1, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 114, 99, 97, 115, 95, + 111, 117, 116, 112, 117, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 105, 110, 116, 50, + 0, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 1, + 0, 0, 120, 101, 95, 102, + 115, 114, 95, 114, 99, 97, + 115, 95, 115, 104, 97, 114, + 112, 110, 101, 115, 115, 95, + 112, 111, 115, 116, 95, 115, + 101, 116, 117, 112, 0, 102, + 108, 111, 97, 116, 0, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 121, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 172, 22, + 0, 0, 81, 0, 0, 0, + 171, 5, 0, 0, 106, 8, + 0, 1, 53, 24, 0, 0, + 2, 4, 0, 0, 132, 131, + 131, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 222, 221, 221, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 204, 203, + 203, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 168, 167, 167, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 159, 158, 30, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 140, 139, + 139, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 178, 177, 177, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 134, + 6, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 160, 159, 159, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 210, 209, 209, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 155, 154, + 26, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 149, 148, 148, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 186, 185, + 185, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 190, 189, 189, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 143, 142, 14, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 158, 157, 157, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 229, 228, 228, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 163, 162, 34, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 253, 252, 252, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 246, 245, + 245, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 209, 208, 208, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 188, 187, 187, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 183, 182, + 54, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 161, 160, 32, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 187, 186, 58, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 172, 171, + 171, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 144, 143, 143, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 157, 156, 156, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 229, + 229, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 220, 219, 219, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 160, + 32, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 207, 206, 78, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 240, 239, 239, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 157, 156, + 156, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 130, 129, 129, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 154, 153, 153, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 185, 184, + 56, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 216, 215, 215, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 180, + 180, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 244, 243, 243, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 232, 231, 231, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 227, 226, + 98, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 235, 234, 106, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 169, 168, 40, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 243, 242, + 114, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 200, 199, 199, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 171, 170, 42, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 192, 191, 191, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 235, + 235, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 223, 222, 94, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 223, 222, 94, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 236, + 236, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 139, 139, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 249, 248, + 120, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 186, 185, 185, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 155, 154, 26, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 201, 200, + 72, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 210, 209, 209, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 134, 133, 133, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 217, 216, 88, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 208, 207, 207, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 171, 170, + 42, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 216, 215, + 215, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 180, 179, 179, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 243, 242, 114, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 174, + 46, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 190, 189, 189, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 150, + 22, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 248, 247, 247, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 170, 169, + 169, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 252, 251, 251, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 218, 217, 217, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 135, + 135, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 131, 130, 2, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 244, 243, 243, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 157, + 157, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 173, 172, 172, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 180, 179, 179, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 213, + 213, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 242, 241, 241, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 191, 190, 62, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 238, 237, 237, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 150, 149, 149, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 197, 196, + 196, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 209, 208, 208, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 154, 153, + 153, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 145, 144, 144, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 254, + 126, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 254, 253, 253, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 138, + 10, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 164, 163, 163, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 140, + 140, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 202, 201, 201, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 129, 128, 0, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 176, 175, 175, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 230, 229, 229, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 130, + 2, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 156, 155, 155, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 203, 202, 74, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 176, 175, + 175, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 141, 140, 140, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 194, 193, 193, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, + 8, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 203, 202, 74, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 172, 171, 171, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 204, + 204, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 251, 250, 122, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 245, 244, 244, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 202, 201, + 201, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 136, 135, 135, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 179, 178, 50, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 219, + 219, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 132, 131, 131, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 221, 220, 220, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 249, 248, 120, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 163, 162, 34, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 218, 217, + 217, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 219, 218, 90, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 226, 225, 225, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 232, 231, 231, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 207, 206, 78, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 233, + 233, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 179, 178, 50, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 130, 129, 129, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 185, 184, 56, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 198, 197, 197, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 173, 172, + 172, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 175, 174, 46, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 237, 236, 236, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 229, 228, + 228, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 201, 200, 72, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 196, 195, 195, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 149, + 149, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 177, 176, 176, 56, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 248, 247, 247, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 183, + 183, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 241, 240, 240, 56, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 166, 165, + 165, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 151, 150, 22, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 255, 254, 126, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 173, + 173, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 233, 232, 104, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 199, 198, 70, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 178, 177, + 177, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 192, 191, 191, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 227, 226, 98, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 188, + 188, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 143, 142, 14, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 148, 147, 147, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 133, 132, + 132, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 147, 146, 18, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 238, 237, 237, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 226, 225, + 225, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 152, 151, 151, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 195, 194, 66, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 206, 205, + 205, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 241, 240, 240, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 160, 159, 159, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 240, 239, + 239, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 193, 192, 192, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 252, 251, 251, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 227, + 227, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 187, 186, 58, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 204, 203, 203, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 223, + 223, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 217, 216, 88, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 138, 137, + 137, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 191, 190, 62, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 214, 213, 213, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 165, 164, + 164, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 253, 252, 252, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 235, 235, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 181, 180, 180, 185, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 183, 182, 54, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 134, 133, + 133, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 206, 205, 205, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 193, 192, 192, 183, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 167, + 167, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 211, 210, 82, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 235, 234, 106, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 188, 187, + 187, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 159, 158, 30, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 177, 176, 176, 184, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 239, 238, + 110, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 59, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 184, 183, 183, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 198, 197, 197, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 215, 214, 86, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 164, 163, + 163, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 133, 132, 132, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 200, 199, 199, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 148, 147, + 147, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 189, 188, 188, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 205, 204, 204, 185, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 250, 249, + 249, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 182, 181, 181, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 145, 145, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 211, + 211, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 231, 230, 102, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 153, 152, 24, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 142, 141, + 141, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 225, 224, 96, 184, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 149, 148, 148, 57, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 222, 221, + 221, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 166, 165, 165, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 135, 134, 6, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 169, 168, + 40, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 246, 245, 245, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 219, 218, 90, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 166, + 38, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 129, 128, 0, 55, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 250, 249, 249, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 233, 232, + 104, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 197, 196, 196, 57, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 228, 227, 227, 186, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 212, + 212, 185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 162, 161, 161, 186, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 224, 223, 223, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 247, 246, + 118, 186, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 215, 214, 86, 58, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 242, 241, 241, 58, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 245, 244, + 244, 57, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 10, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 54, 0, 0, 5, + 50, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 5, 0, + 0, 0, 230, 10, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 14, 16, 0, 5, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 9, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 64, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 9, 0, + 0, 0, 70, 2, 16, 0, + 9, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 8, 0, 0, 0, + 70, 2, 16, 0, 9, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 7, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 0, 0, 0, 11, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 7, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 50, 0, 0, 15, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 128, 64, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 192, 0, 0, 128, 192, + 0, 0, 128, 192, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 7, 0, + 0, 0, 52, 0, 0, 8, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 8, 0, 0, 0, 52, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 6, 0, 0, 0, + 26, 0, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 6, 0, 0, 0, + 51, 0, 0, 7, 66, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 190, 56, 0, 0, 9, + 66, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 166, 10, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 140, 0, 0, 11, + 34, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 4, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 26, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 140, 0, + 0, 11, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 4, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 26, 0, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 114, 32, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 6, 144, + 144, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 32, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 51, 0, 0, 0, 10, 0, + 0, 0, 0, 1, 0, 0, + 2, 0, 0, 0, 28, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h new file mode 100644 index 000000000..f1c967f88 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_ffx_fsr_rcas_ps.h @@ -0,0 +1,498 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeFsrRcasConstants +// { +// +// int2 xe_fsr_rcas_output_offset; // Offset: 0 Size: 8 +// float xe_fsr_rcas_sharpness_post_setup;// Offset: 8 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// xe_texture texture float3 2d T0 t0 1 +// XeFsrRcasConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xy +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_resource_texture2d (float,float,float,float) T0[0:0], space=0 +dcl_input_ps_siv linear noperspective v0.xy, position +dcl_output o0.xyzw +dcl_temps 9 +ftoi r0.xy, v0.xyxx +iadd r0.xy, r0.xyxx, -CB0[0][0].xyxx +iadd r1.xyzw, r0.xyxy, l(-1, 0, 0, -1) +mov r2.xy, r1.zwzz +mov r2.zw, l(0,0,0,0) +ld r2.xyz, r2.xyzw, T0[0].xyzw +mov r1.zw, l(0,0,0,0) +ld r1.xyz, r1.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r3.xyz, r0.xyzw, T0[0].xyzw +iadd r0.xyzw, r0.xyxy, l(0, 1, 1, 0) +mov r4.xy, r0.zwzz +mov r4.zw, l(0,0,0,0) +ld r4.xyz, r4.xyzw, T0[0].xyzw +mov r0.zw, l(0,0,0,0) +ld r0.xyz, r0.xyzw, T0[0].xyzw +min r5.xyz, r1.xyzx, r4.xyzx +min r5.xyz, r2.xyzx, r5.xyzx +min r5.xyz, r0.xyzx, r5.xyzx +max r6.xyz, r1.xyzx, r4.xyzx +max r6.xyz, r2.xyzx, r6.xyzx +max r6.xyz, r0.xyzx, r6.xyzx +min r7.xyz, r3.xyzx, r5.xyzx +mul r8.xyz, r6.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000) +rcp r8.xyz, r8.xyzx +mul r7.xyz, r7.xyzx, r8.xyzx +max r6.xyz, r3.xyzx, r6.xyzx +add r6.xyz, -r6.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) +mad r5.xyz, r5.xyzx, l(4.000000, 4.000000, 4.000000, 0.000000), l(-4.000000, -4.000000, -4.000000, 0.000000) +rcp r5.xyz, r5.xyzx +mul r5.xyz, r5.xyzx, r6.xyzx +max r5.xyz, r5.xyzx, -r7.xyzx +max r0.w, r5.z, r5.y +max r0.w, r0.w, r5.x +min r0.w, r0.w, l(0.000000) +max r0.w, r0.w, l(-0.187500) +mul r0.w, r0.w, CB0[0][0].z +mad r1.w, r0.w, l(4.000000), l(1.000000) +iadd r2.w, -r1.w, l(0x7ef19fff) +mad r1.w, -r2.w, r1.w, l(2.000000) +mul r1.w, r1.w, r2.w +mul r1.xyz, r1.xyzx, r0.wwww +mad r1.xyz, r0.wwww, r2.xyzx, r1.xyzx +mad r0.xyz, r0.wwww, r0.xyzx, r1.xyzx +mad r0.xyz, r0.wwww, r4.xyzx, r0.xyzx +add r0.xyz, r3.xyzx, r0.xyzx +mul o0.xyz, r1.wwww, r0.xyzx +mov o0.w, l(1.000000) +ret +// Approximately 49 instruction slots used +#endif + +const BYTE guest_output_ffx_fsr_rcas_ps[] = +{ + 68, 88, 66, 67, 185, 223, + 242, 110, 212, 184, 173, 198, + 168, 143, 147, 205, 178, 152, + 68, 191, 1, 0, 0, 0, + 84, 9, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 8, 2, 0, 0, 60, 2, + 0, 0, 112, 2, 0, 0, + 184, 8, 0, 0, 82, 68, + 69, 70, 204, 1, 0, 0, + 1, 0, 0, 0, 172, 0, + 0, 0, 2, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 255, 255, 0, 5, 0, 0, + 164, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 151, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 120, 101, 95, 116, + 101, 120, 116, 117, 114, 101, + 0, 88, 101, 70, 115, 114, + 82, 99, 97, 115, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 151, 0, + 0, 0, 2, 0, 0, 0, + 196, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 52, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 88, 1, 0, 0, + 8, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 120, 101, 95, 102, 115, 114, + 95, 114, 99, 97, 115, 95, + 111, 117, 116, 112, 117, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 105, 110, 116, 50, + 0, 171, 1, 0, 2, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 1, + 0, 0, 120, 101, 95, 102, + 115, 114, 95, 114, 99, 97, + 115, 95, 115, 104, 97, 114, + 112, 110, 101, 115, 115, 95, + 112, 111, 115, 116, 95, 115, + 101, 116, 117, 112, 0, 102, + 108, 111, 97, 116, 0, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 121, 1, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 3, + 0, 0, 83, 86, 95, 80, + 111, 115, 105, 116, 105, 111, + 110, 0, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 97, 114, + 103, 101, 116, 0, 171, 171, + 83, 72, 69, 88, 64, 6, + 0, 0, 81, 0, 0, 0, + 144, 1, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 88, 24, 0, 7, 70, 126, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 0, 0, 0, 0, 100, 32, + 0, 4, 50, 16, 16, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 9, 0, 0, 0, 27, 0, + 0, 5, 50, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 30, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 54, 0, 0, 5, + 50, 0, 16, 0, 2, 0, + 0, 0, 230, 10, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 45, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 126, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 0, + 0, 10, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 4, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 0, 16, 0, 4, 0, + 0, 0, 230, 10, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 0, 16, 0, + 4, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 45, 0, 0, 8, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 14, 16, 0, 4, 0, + 0, 0, 70, 126, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 51, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 51, 0, 0, 7, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 52, 0, 0, 7, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 52, 0, + 0, 7, 114, 0, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 51, 0, 0, 7, 114, 0, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 8, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 64, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 8, 0, + 0, 0, 70, 2, 16, 0, + 8, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 7, 0, 0, 0, 70, 2, + 16, 0, 7, 0, 0, 0, + 70, 2, 16, 0, 8, 0, + 0, 0, 52, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 6, 0, 0, 0, + 0, 0, 0, 11, 114, 0, + 16, 0, 6, 0, 0, 0, + 70, 2, 16, 128, 65, 0, + 0, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 0, 0, 50, 0, 0, 15, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 64, + 0, 0, 128, 64, 0, 0, + 128, 64, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 192, 0, 0, 128, 192, + 0, 0, 128, 192, 0, 0, + 0, 0, 129, 0, 0, 5, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 6, 0, + 0, 0, 52, 0, 0, 8, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 7, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 5, 0, 0, 0, + 26, 0, 16, 0, 5, 0, + 0, 0, 52, 0, 0, 7, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 5, 0, 0, 0, + 51, 0, 0, 7, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 190, 56, 0, 0, 9, + 130, 0, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 42, 128, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 50, 0, 0, 9, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 64, + 1, 64, 0, 0, 0, 0, + 128, 63, 30, 0, 0, 8, + 130, 0, 16, 0, 2, 0, + 0, 0, 58, 0, 16, 128, + 65, 0, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 255, 159, 241, 126, 50, 0, + 0, 10, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 56, 0, 0, 7, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 9, 114, 0, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 7, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 114, 32, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 32, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 49, 0, 0, 0, + 9, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 28, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h new file mode 100644 index 000000000..ccdcc1495 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/guest_output_triangle_strip_rect_vs.h @@ -0,0 +1,220 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer XeTriangleStripRectConstants +// { +// +// float2 xe_triangle_strip_rect_offset;// Offset: 0 Size: 8 +// float2 xe_triangle_strip_rect_size;// Offset: 8 Size: 8 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// XeTriangleStripRectConstants cbuffer NA NA CB0 cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_VertexID 0 x 0 VERTID uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float xyzw +// +vs_5_1 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[0:0][1], immediateIndexed, space=0 +dcl_input_sgv v0.x, vertex_id +dcl_output_siv o0.xyzw, position +dcl_temps 1 +ushr r0.y, v0.x, l(1) +mov r0.x, v0.x +and r0.xy, r0.xyxx, l(1, 1, 0, 0) +utof r0.xy, r0.xyxx +mad o0.xy, r0.xyxx, CB0[0][0].zwzz, CB0[0][0].xyxx +mov o0.zw, l(0,0,0,1.000000) +ret +// Approximately 7 instruction slots used +#endif + +const BYTE guest_output_triangle_strip_rect_vs[] = +{ + 68, 88, 66, 67, 67, 209, + 250, 163, 3, 195, 64, 100, + 167, 54, 190, 31, 173, 113, + 120, 163, 1, 0, 0, 0, + 216, 3, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 184, 1, 0, 0, 236, 1, + 0, 0, 32, 2, 0, 0, + 60, 3, 0, 0, 82, 68, + 69, 70, 124, 1, 0, 0, + 1, 0, 0, 0, 132, 0, + 0, 0, 1, 0, 0, 0, + 60, 0, 0, 0, 1, 5, + 254, 255, 0, 5, 0, 0, + 84, 1, 0, 0, 19, 19, + 68, 37, 60, 0, 0, 0, + 24, 0, 0, 0, 40, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 88, 101, + 84, 114, 105, 97, 110, 103, + 108, 101, 83, 116, 114, 105, + 112, 82, 101, 99, 116, 67, + 111, 110, 115, 116, 97, 110, + 116, 115, 0, 171, 171, 171, + 100, 0, 0, 0, 2, 0, + 0, 0, 156, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 236, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 20, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 56, 1, + 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 20, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 120, 101, 95, 116, + 114, 105, 97, 110, 103, 108, + 101, 95, 115, 116, 114, 105, + 112, 95, 114, 101, 99, 116, + 95, 111, 102, 102, 115, 101, + 116, 0, 102, 108, 111, 97, + 116, 50, 0, 171, 171, 171, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 10, 1, 0, 0, + 120, 101, 95, 116, 114, 105, + 97, 110, 103, 108, 101, 95, + 115, 116, 114, 105, 112, 95, + 114, 101, 99, 116, 95, 115, + 105, 122, 101, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, + 83, 86, 95, 86, 101, 114, + 116, 101, 120, 73, 68, 0, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 83, 72, + 69, 88, 20, 1, 0, 0, + 81, 0, 1, 0, 69, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 7, 70, 142, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 96, 0, + 0, 4, 18, 16, 16, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 85, 0, 0, 7, + 34, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 16, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 10, + 50, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 50, 0, 0, 13, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 48, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 128, 48, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 8, 194, 32, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 63, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 7, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 +}; diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h index 6a0bd31ac..09255e348 100644 --- a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h @@ -42,10 +42,10 @@ ret const BYTE immediate_ps[] = { - 68, 88, 66, 67, 204, 46, - 131, 39, 62, 129, 239, 95, - 188, 170, 211, 224, 226, 155, - 212, 68, 1, 0, 0, 0, + 68, 88, 66, 67, 218, 200, + 108, 196, 58, 28, 70, 226, + 98, 137, 89, 199, 218, 58, + 155, 172, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 28, 1, 0, 0, 104, 1, @@ -55,7 +55,7 @@ const BYTE immediate_ps[] = 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 255, 255, 0, 5, 4, 0, + 255, 255, 0, 5, 0, 0, 182, 0, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, diff --git a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h index 03385fb28..dc36315ba 100644 --- a/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h +++ b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h @@ -8,7 +8,7 @@ // cbuffer XeImmediateVertexConstants // { // -// float2 xe_viewport_size_inv; // Offset: 0 Size: 8 +// float2 xe_coordinate_space_size_inv;// Offset: 0 Size: 8 // // } // @@ -59,21 +59,21 @@ ret const BYTE immediate_vs[] = { - 68, 88, 66, 67, 88, 56, - 35, 17, 155, 211, 230, 48, - 9, 16, 27, 220, 163, 42, - 194, 218, 1, 0, 0, 0, - 16, 4, 0, 0, 5, 0, + 68, 88, 66, 67, 141, 232, + 76, 204, 152, 38, 127, 131, + 125, 87, 10, 113, 217, 159, + 27, 143, 1, 0, 0, 0, + 24, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, - 100, 1, 0, 0, 212, 1, - 0, 0, 68, 2, 0, 0, - 116, 3, 0, 0, 82, 68, - 69, 70, 40, 1, 0, 0, + 108, 1, 0, 0, 220, 1, + 0, 0, 76, 2, 0, 0, + 124, 3, 0, 0, 82, 68, + 69, 70, 48, 1, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 60, 0, 0, 0, 1, 5, - 254, 255, 0, 5, 4, 0, - 0, 1, 0, 0, 19, 19, + 254, 255, 0, 5, 0, 0, + 8, 1, 0, 0, 19, 19, 68, 37, 60, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, @@ -97,122 +97,123 @@ const BYTE immediate_vs[] = 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, - 220, 0, 0, 0, 0, 0, + 228, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, - 120, 101, 95, 118, 105, 101, - 119, 112, 111, 114, 116, 95, - 115, 105, 122, 101, 95, 105, - 110, 118, 0, 102, 108, 111, - 97, 116, 50, 0, 1, 0, - 3, 0, 1, 0, 2, 0, + 120, 101, 95, 99, 111, 111, + 114, 100, 105, 110, 97, 116, + 101, 95, 115, 112, 97, 99, + 101, 95, 115, 105, 122, 101, + 95, 105, 110, 118, 0, 102, + 108, 111, 97, 116, 50, 0, + 1, 0, 3, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 221, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 104, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 213, 0, 0, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 49, 48, 46, - 49, 0, 73, 83, 71, 78, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 3, + 0, 0, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 15, + 0, 0, 80, 79, 83, 73, + 84, 73, 79, 78, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 79, 83, 71, 78, 104, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 3, 3, 0, 0, - 89, 0, 0, 0, 0, 0, + 0, 0, 3, 12, 0, 0, + 80, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, - 0, 0, 3, 3, 0, 0, - 98, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 89, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, - 0, 0, 15, 15, 0, 0, - 80, 79, 83, 73, 84, 73, - 79, 78, 0, 84, 69, 88, - 67, 79, 79, 82, 68, 0, - 67, 79, 76, 79, 82, 0, - 79, 83, 71, 78, 104, 0, - 0, 0, 3, 0, 0, 0, - 8, 0, 0, 0, 80, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 111, 115, 105, 116, 105, + 111, 110, 0, 171, 171, 171, + 83, 72, 69, 88, 40, 1, + 0, 0, 81, 0, 1, 0, + 74, 0, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 7, + 70, 142, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 3, 12, 0, 0, 80, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 15, 0, 0, 0, 89, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 2, 0, 0, 0, - 15, 0, 0, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 83, 86, 95, 80, 111, - 115, 105, 116, 105, 111, 110, - 0, 171, 171, 171, 83, 72, - 69, 88, 40, 1, 0, 0, - 81, 0, 1, 0, 74, 0, - 0, 0, 106, 8, 0, 1, - 89, 0, 0, 7, 70, 142, - 48, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 0, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 1, 0, 0, 0, 95, 0, - 0, 3, 242, 16, 16, 0, - 2, 0, 0, 0, 101, 0, - 0, 3, 50, 32, 16, 0, - 0, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 1, 0, 0, 0, 103, 0, - 0, 4, 242, 32, 16, 0, - 2, 0, 0, 0, 1, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 56, 0, - 0, 9, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 16, + 95, 0, 0, 3, 50, 16, 16, 0, 0, 0, 0, 0, - 70, 128, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, - 0, 15, 50, 32, 16, 0, - 2, 0, 0, 0, 70, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 50, 32, 16, 0, 0, 0, 0, 0, - 2, 64, 0, 0, 0, 0, - 0, 64, 0, 0, 0, 192, + 101, 0, 0, 3, 242, 32, + 16, 0, 1, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 56, 0, 0, 9, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 70, 128, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 15, 50, 32, + 16, 0, 2, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 192, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 191, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 2, 0, + 0, 0, 54, 0, 0, 8, + 194, 32, 16, 0, 2, 0, 0, 0, 2, 64, 0, 0, - 0, 0, 128, 191, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 54, 0, - 0, 5, 242, 32, 16, 0, - 1, 0, 0, 0, 70, 30, - 16, 0, 2, 0, 0, 0, - 54, 0, 0, 8, 194, 32, - 16, 0, 2, 0, 0, 0, - 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128, 63, 54, 0, 0, 5, - 50, 32, 16, 0, 0, 0, - 0, 0, 70, 16, 16, 0, - 1, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 148, 0, 0, 0, 6, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 2, 0, 0, 0, + 0, 0, 128, 63, 54, 0, + 0, 5, 50, 32, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, + 6, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -220,7 +221,7 @@ const BYTE immediate_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -232,5 +233,5 @@ const BYTE immediate_vs[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 + 0, 0, 0, 0 }; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h new file mode 100644 index 000000000..57f769dfe --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h @@ -0,0 +1,592 @@ +// generated from `xb genspirv` +// source: guest_output_bilinear_dither.frag +const uint8_t guest_output_bilinear_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x72, 0x01, 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, + 0x29, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x29, 0x01, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, + 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x30, 0x01, 0x00, 0x00, 0x58, 0x65, 0x42, 0x69, + 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, + 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, 0x69, 0x6C, 0x69, 0x6E, + 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x62, + 0x69, 0x6C, 0x69, 0x6E, 0x65, 0x61, 0x72, 0x5F, 0x6F, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, + 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x3E, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x3E, 0x01, 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, + 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0xA8, 0xA7, 0xA7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x95, 0x94, 0x94, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x9E, 0x9D, 0x9D, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBC, 0xBB, 0xBB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xA1, 0xA0, 0x20, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x90, 0x8F, 0x8F, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xDC, 0xDB, 0xDB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, + 0xD8, 0xD7, 0xD7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4C, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x8C, 0x8B, 0x8B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0xBA, 0xB9, 0xB9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x83, 0x82, 0x02, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xAD, 0xAC, 0xAC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x91, 0x90, 0x90, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0xCA, 0xC9, 0xC9, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0xB0, 0xAF, 0xAF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0x9C, 0x9B, 0x9B, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x8D, 0x8C, 0x8C, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0xFB, 0xFA, 0x7A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x88, 0x87, 0x87, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x84, 0x83, 0x83, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xF9, 0xF8, 0x78, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xB9, 0xB8, 0x38, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xBB, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0x98, 0x97, 0x97, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xC9, 0xC8, 0x48, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0x97, 0x96, 0x16, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xE9, 0xE8, 0x68, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0x93, 0x92, 0x12, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x98, 0x97, 0x97, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xB5, 0xB4, 0xB4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xCE, 0xCD, 0xCD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xD3, 0xD2, 0x52, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3B, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0x85, 0x84, 0x84, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xBD, 0xBC, 0xBC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xB6, 0xB5, 0xB5, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xE7, 0xE6, 0x66, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xE1, 0xE0, 0x60, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0xA6, 0xA5, 0xA5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0xF6, 0xF5, 0xF5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x81, 0x80, 0x00, 0x37, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0xC5, 0xC4, 0xC4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0xA2, 0xA1, 0xA1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, + 0x2C, 0x00, 0x03, 0x01, 0x13, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x4A, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, + 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, + 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, + 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, + 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, + 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, + 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, + 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, + 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, + 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, + 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, + 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, + 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, + 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, + 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, + 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, + 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, + 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, + 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, + 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, + 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, + 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, + 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, + 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, + 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, + 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, + 0x13, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x1F, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x21, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x28, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x31, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x2D, 0x01, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x34, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x39, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x39, 0x01, 0x00, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, + 0x3B, 0x01, 0x00, 0x00, 0x09, 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, + 0x3C, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x3D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x46, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x06, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3F, 0x2C, 0x00, 0x06, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0x59, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, + 0x58, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x5E, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0E, 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, + 0x1F, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2E, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x2F, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x3C, 0x01, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x41, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x70, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x46, 0x01, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x2A, 0x01, 0x00, 0x00, + 0x49, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x58, 0x00, 0x07, 0x00, 0x27, 0x01, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x4F, 0x00, 0x08, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0x71, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x01, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, + 0x67, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6A, 0x01, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6B, 0x01, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x6A, 0x01, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x60, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x21, 0x01, 0x00, 0x00, 0x6C, 0x01, 0x00, 0x00, + 0x60, 0x01, 0x00, 0x00, 0x6B, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, 0x6C, 0x01, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, + 0x6D, 0x01, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, + 0x51, 0x01, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x4C, 0x01, 0x00, 0x00, 0x5A, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, + 0x59, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x27, 0x01, 0x00, 0x00, + 0x5B, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x00, 0x5B, 0x01, 0x00, 0x00, + 0x5A, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x3A, 0x01, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x5E, 0x01, 0x00, 0x00, 0x5F, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x5D, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x5F, 0x01, 0x00, 0x00, + 0x58, 0x01, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..ade34879138b54cf7c4faca8e0ae51a055ed6a8c GIT binary patch literal 7056 zcmZ{p1(;RU8io&z=tUGoF%V1yL`5V81cX6E5CajFp#~U)85{;g^eWxm9n#(1-QCjN z-RXV5nX|u#`#krahu5>;_5UmOT6?d(&zLOfYpFt^B%w5+)SIRik4Rc$+{0NJpN^>42kTv>FPH zpgcLfMU;t*C|53`Oo_2RAk-gn5f7a(Q#4Lo%;<5l0a>PD7~t6HmgY;0T&x(uaY1n*H^F{)U!`luRLJT|65eASrv2GmHC z5K~^`sK{#Jgvi*2@%0(V$ zWIU18W9!DoC6uQK6;3RVk7^v>FphJL;7m03$B91)rKqhj>+>3ZS7sP-&jPfsn?%aX74O9?nh6 zvBn(u(;Vx4wbJm#dZ7)v~1C0Uf|E-r%u)^5O@as;DH17=kN{d*E?V5J!bT1 z$1~zX24`~o1-xU24vxQw&zd>Y@t5#vQ>QxqGTx?jO1tK7=#U}ySMY6Hx4M32d_eyf z9M^pI>e+K{Fn-N<_io)B*ILb+JJy|?heg9bUC z6+dzOxZ`i*?c23;JR3gzuUFlEcKpHp`yO8o{N{}tj=zI&*vk2^QN+n7s4-Jy5#zWar*Q87Qvf0 zYv%lq@&5h#Ilm}AcTPU%7sL1L-tGM2_?FF^o&O0wbH)tkm%y)IyXO3o_~}!poF9Q7 zJ6g?N3O{$Yj`Kgo$BxPB_DbW|uEsh4GkneJ)%G&@_;K0npX1}kj&*xw@$K8bbi5qC zWbtDA7x?*e=bT?2KXkCN<6kDa<6q$y&YzzftpC?I_owr}!Ta@n-th|fo!gClKHuWp zKW?ug&i&{5-{EW5lydz_IQOgbzsFm*YGwZc-??Ll+y4>YyQiY-SH@W{=SSkqm%R$! zt!r0bPgU^)`}e!OYB=jZFF4=o_>Ae(U0)9+*2m8FADTQVr}Jy#0|yLnycW)W;dpJl zPwxzlN8`6|-EzDRzIs(j$A7|EU&rg>_wU_vydM7d-o1|NA>Ou48+$C?qIpt#eVpsn z{xi=0R3JFtIDF!S37*deIOp$tJx_P--0A#=_|+>{9B+g#UR2oeU+_y8V;pacU%YU^ z@n7-Yy?Qy`1Yfygh5P>vXFv1)^E8;Ow9FmiUpwRos3ne8lkKuHPE()Ul(--v(c|cCG8T#hWz^%?{?f z9X@iz2w#8g@hOuhJHG?Ye(Cl*;;g6Rop7!<$2;Te*Ohj>3r>5Ecf}c>`|F0Y-#XqM z=lSLF_rPh-@t!#Qz1#1FZ``oK?e)f)PsjV#CiX)55l>B-Tq+w?3pu;55d`w93P7Fe0BT7aPA-H|Ap`SyOMo4e)Px@=a0ZU zcj{yxiL>83e-zI1$??%R@?)G1SZzs$ke?;M|t&zU{jJ`eBF{b~Dr{L1CauD<{uHFBim3vu?-dBOQE!nwcg zi*e@D`AhIKr)zusOL6vF=P$!~zqBvMd49V73Y_P;eI>qd!2-|EDxCL0$5-P$d-QO7 zYw%VrTRML&&iOjN4rhO~ugAIm+};M9^>Tb8&VK0lCVbPzjrPqr^EW4$pDj4=$F9E> z=l#j~+wi4JmgEicx8po-oWBDvtaK zdFuEDoKL}Ey)Gi$Pj2rLK6=!f_RBc?hwER#ckim;_*I3-q(FTDR6#|Ii3>d`C(6mGyesG z^GS{K{P+F!7|wh+KMl_QEgv!};-e&^2-N|q!&bNLMZ4ByW}26zshhm7z7ya+GB%a93Pfy|HvUWM1- zb$A2bgts6oybakPJLG_OASb*F@4@?!3qF9{@FC=ZypRv_LjfoVA3-4~3`O8$C^3u;3&)PbL%F4ThQ+dU+4$@VE_z-K`=06KsYpuobq!cGv+sVHfO%J+K%4hJCOf4!}V;1c%`W z9ED?W98SPVI0dKS44j2?a2_teMYsf);R;-ZYj7QIz)iRXx8V-lg?n%x9>7ER2ejvD zpVQu^{Y-n9_ATvI+Ml#1X&=(wqy0vEjP@1nCE7o&zBA*m zaGZ+c^kL5u_Q!Dj9r7()$H~L-tT_J?$_r8|*WXZ8ru=LiC_gFa@0#!6nK=&PIXO_7 z;+cr+@2DzMJ&osmzExl4YG1Cu?W#=USKSXlALZu`$JB;AKi|oSY22zW*WYJVmXTHp za;&!a`maymFOvBYqCB-%C>%&A3%mZlt55K3D3<6&g7KBWRiyeQIZ%H(zaYP~f_yYz zWx{cdF9)k5{}z-J5Y($kSt!)BNRam(uCf5-X?=gBOzo-v%Hd;;AqRio);Q{e#w=8( z_5YdUw0w&^lxcmm=K83u+mxi>TXU*wrV6NDAzX8v9dsR(qf~w52$!i`AAQA;t95!8 z6fa7PTE7oLYpiuud&` z)A_4!txW`|Z>^cyQC=xfd8=@}PdQdyl~<%^o$qI${uI+(mF7E`i?ST+nk&c3E4Lh| zOm#G;nn$gZ=Cv^YO~@q{)c=Cx#QLcdu7~ot%7i}pQlG17N%IgzfzDHFSe`PqU5jIt z^N;67Vp(lO<+}faygD2!PoJjYyq|F8DyH#it@Zw(In(}77gVM^jak=Ly>R&#;cNIC zTx9`T16|t{Kl~n@%aepMnb^Ytw4(8)~jvt-RA8?ha-v66V+sg?UAxzq~q&*=G@2Jnfgp?-k6$cm<99Plxx+@h%si-%oR51eC)Kde9%5P ze2ikr)C(b+WixMPWx?lO6ti(f*b!EwgI59l)s@wl-wK*lwV-2zZa3(>v;FbdX8D&< zXh%^T+Ch|t{X9Ak(Jf5rqPRbr45kI16w`G*^-Jxuk$s=`&Q6jf9mqAFI=Ci#8orIF z(MwN~ILmu+o++YH?4i2|?Wam$lSw|F^u8!83m+6s&#acPA~=p7;I0dS>Y-z{6v!*EGn#JvuIo1_3C(f@loAS9oIJ6tmHe`K)J^IDx9(;W-%hm+=7nRSs z;LtD0q9+%%R%Ly`?O)YD9Q!-k=WKAqk$+wGk^oPBeC7?eSLNH(KMOrGVvij7w`6&} zu0MR{1-B*TZCU!GpXufNZ7F?ipd(+i62Z|A{%*z554rA^{%hCYefc$k_y@A|$N8MT zt$&vD4+`&l5zjpw3iM0-QT0!qeZ3j-91GM0N8*?z_roIYj~Gw(rC9ggxTCIant0wC zZxFEPHI|kct_keFQ3htaB`|+xPChg@1o)rQ;BO1W!GDv6_jFT$C&rg;3CwLQpC0ZA zXnrUM{=JIhY}96MdjhqYCwb8A3-G_HxQF^D7XDO~IqxHZdh9Wqw%}&*ME|^pu5JbG kQvr?`X2{&Q1LpWjU$kiGiMx0vz;Q?H<8yz1HN|7$9~fF}Q~&?~ literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt new file mode 100644 index 000000000..26ba8b3c9 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.txt @@ -0,0 +1,81 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 57 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeBilinearConstants "XeBilinearConstants" + OpMemberName %XeBilinearConstants 0 "xe_bilinear_output_offset" + OpMemberName %XeBilinearConstants 1 "xe_bilinear_output_size_inv" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpName %xe_texture "xe_texture" + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeBilinearConstants 0 Offset 16 + OpMemberDecorate %XeBilinearConstants 1 Offset 24 + OpDecorate %XeBilinearConstants Block + OpDecorate %xe_frag_color Location 0 + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input + %v2float = OpTypeVector %float 2 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 +%XeBilinearConstants = OpTypeStruct %v2int %v2float +%_ptr_PushConstant_XeBilinearConstants = OpTypePointer PushConstant %XeBilinearConstants + %_ = OpVariable %_ptr_PushConstant_XeBilinearConstants PushConstant + %int_0 = OpConstant %int 0 +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output + %31 = OpTypeImage %float 2D 0 0 0 1 Unknown + %32 = OpTypeSampledImage %31 +%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32 + %xe_texture = OpVariable %_ptr_UniformConstant_32 UniformConstant + %float_0_5 = OpConstant %float 0.5 + %int_1 = OpConstant %int 1 +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %uint_3 = OpConstant %uint 3 +%_ptr_Output_float = OpTypePointer Output %float + %56 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %main = OpFunction %void None %3 + %5 = OpLabel + %15 = OpLoad %v4float %gl_FragCoord + %16 = OpVectorShuffle %v2float %15 %15 0 1 + %19 = OpConvertFToS %v2int %16 + %25 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %26 = OpLoad %v2int %25 + %27 = OpISub %v2int %19 %26 + %28 = OpBitcast %v2uint %27 + %35 = OpLoad %32 %xe_texture + %37 = OpConvertUToF %v2float %28 + %40 = OpFAdd %v2float %37 %56 + %43 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %44 = OpLoad %v2float %43 + %45 = OpFMul %v2float %40 %44 + %47 = OpImageSampleExplicitLod %v4float %35 %45 Lod %float_0 + %50 = OpLoad %v4float %xe_frag_color + %51 = OpVectorShuffle %v4float %50 %47 4 5 6 3 + OpStore %xe_frag_color %51 + %55 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %55 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h new file mode 100644 index 000000000..1feff3326 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h @@ -0,0 +1,1216 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_resample_dither.frag +const uint8_t guest_output_ffx_cas_resample_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x7E, 0x1A, 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, + 0xB4, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x69, + 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, + 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xAB, 0x01, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xAB, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xB4, 0x09, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xE1, 0x09, 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, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1C, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, + 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, + 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5A, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5D, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x95, 0x94, 0x94, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6C, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x75, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, + 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7B, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x81, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, + 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x87, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, + 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8D, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, + 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA2, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA8, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, + 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAB, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB1, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB4, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, + 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB7, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBD, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, + 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC3, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, + 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC9, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCF, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, + 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD8, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDB, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE1, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE4, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE7, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xED, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x98, 0x97, 0x97, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, + 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF3, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF6, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x93, 0x92, 0x12, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF9, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, + 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x93, 0x92, 0x12, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x98, 0x97, 0x97, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x01, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x11, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, + 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x01, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1A, 0x01, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, + 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, + 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x23, 0x01, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x26, 0x01, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2F, 0x01, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, + 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x35, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x38, 0x01, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3B, 0x01, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, + 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, + 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x41, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x44, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x81, 0x80, 0x00, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, + 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, + 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, 0x2C, 0x00, 0x03, 0x01, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, + 0x1E, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0x39, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0x3C, 0x01, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x5B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x09, 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, 0xA9, 0x01, 0x00, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xAA, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xA9, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xAA, 0x01, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xF7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, + 0x20, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xB9, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xB9, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xBB, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xC1, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x20, 0x00, 0x04, 0x00, 0xD2, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xE0, 0x09, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xE0, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xEF, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x01, 0x0A, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x02, 0x0A, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0A, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x6D, 0x1A, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, + 0xC5, 0x09, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x7D, 0x1A, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4B, 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, 0x5B, 0x01, 0x00, 0x00, + 0xA9, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0x9E, 0x03, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, + 0xB5, 0x09, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xB7, 0x09, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xBB, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0xB7, 0x09, 0x00, 0x00, + 0xBD, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xBF, 0x09, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC1, 0x09, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0xC3, 0x09, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, 0xC3, 0x09, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0xC8, 0x09, 0x00, 0x00, + 0xC3, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, 0xC8, 0x09, 0x00, 0x00, + 0x6D, 0x1A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xCB, 0x09, 0x00, 0x00, 0xCA, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xD2, 0x09, 0x00, 0x00, 0xD3, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD4, 0x09, 0x00, 0x00, 0xD3, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, 0xD4, 0x09, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0x01, 0x0C, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0x01, 0x0C, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x60, 0x0D, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x66, 0x0D, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x67, 0x0D, 0x00, 0x00, + 0x60, 0x0D, 0x00, 0x00, 0x66, 0x0D, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x6D, 0x0D, 0x00, 0x00, 0xCB, 0x09, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, + 0x67, 0x0D, 0x00, 0x00, 0x6D, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x70, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x73, 0x0D, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, + 0x70, 0x0D, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x75, 0x0D, 0x00, 0x00, 0x70, 0x0D, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x7A, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, + 0xCE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xA9, 0x01, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xB2, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xB3, 0x13, 0x00, 0x00, + 0xB2, 0x13, 0x00, 0x00, 0x7A, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xB9, 0x13, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xBA, 0x13, 0x00, 0x00, 0xB9, 0x13, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xC0, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xC1, 0x13, 0x00, 0x00, + 0xC0, 0x13, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x82, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xC7, 0x13, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xC8, 0x13, 0x00, 0x00, 0xC7, 0x13, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xD5, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xD6, 0x13, 0x00, 0x00, 0xD5, 0x13, 0x00, 0x00, + 0x88, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, + 0x75, 0x0D, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xDC, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xDD, 0x13, 0x00, 0x00, + 0xDC, 0x13, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x8E, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xE3, 0x13, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xE4, 0x13, 0x00, 0x00, 0xE3, 0x13, 0x00, 0x00, 0x8E, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x91, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, + 0xF1, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xEA, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xEB, 0x13, 0x00, 0x00, 0xEA, 0x13, 0x00, 0x00, + 0x91, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, + 0x75, 0x0D, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xF8, 0x13, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF9, 0x13, 0x00, 0x00, + 0xF8, 0x13, 0x00, 0x00, 0x97, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x9A, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, 0xF7, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xFF, 0x13, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0xFF, 0x13, 0x00, 0x00, 0x9A, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x9D, 0x0D, 0x00, 0x00, 0x75, 0x0D, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x06, 0x14, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, + 0x9D, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xA0, 0x0D, 0x00, 0x00, + 0x75, 0x0D, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x0D, 0x14, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, + 0x0D, 0x14, 0x00, 0x00, 0xA0, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB3, 0x0D, 0x00, 0x00, 0xB3, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB5, 0x0D, 0x00, 0x00, + 0xB3, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB7, 0x0D, 0x00, 0x00, 0xB3, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x24, 0x14, 0x00, 0x00, 0xB3, 0x0D, 0x00, 0x00, 0xB3, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x27, 0x14, 0x00, 0x00, + 0xB5, 0x0D, 0x00, 0x00, 0xB5, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x14, 0x00, 0x00, 0xB7, 0x0D, 0x00, 0x00, + 0xB7, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x0D, 0x00, 0x00, 0xC8, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC2, 0x0D, 0x00, 0x00, + 0xC8, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC4, 0x0D, 0x00, 0x00, 0xC8, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2E, 0x14, 0x00, 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xC0, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0x14, 0x00, 0x00, + 0xC2, 0x0D, 0x00, 0x00, 0xC2, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x34, 0x14, 0x00, 0x00, 0xC4, 0x0D, 0x00, 0x00, + 0xC4, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDA, 0x0D, 0x00, 0x00, 0xBA, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDC, 0x0D, 0x00, 0x00, + 0xBA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDE, 0x0D, 0x00, 0x00, 0xBA, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x14, 0x00, 0x00, 0xDA, 0x0D, 0x00, 0x00, 0xDA, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, + 0xDC, 0x0D, 0x00, 0x00, 0xDC, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, 0xDE, 0x0D, 0x00, 0x00, + 0xDE, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE7, 0x0D, 0x00, 0x00, 0xC1, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE9, 0x0D, 0x00, 0x00, + 0xC1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x0D, 0x00, 0x00, 0xC1, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4C, 0x14, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0xE9, 0x0D, 0x00, 0x00, 0xE9, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, 0xEB, 0x0D, 0x00, 0x00, + 0xEB, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF4, 0x0D, 0x00, 0x00, 0xD6, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF6, 0x0D, 0x00, 0x00, + 0xD6, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, 0xD6, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x56, 0x14, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, + 0xF6, 0x0D, 0x00, 0x00, 0xF6, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5C, 0x14, 0x00, 0x00, 0xF8, 0x0D, 0x00, 0x00, + 0xF8, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x01, 0x0E, 0x00, 0x00, 0xDD, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x00, + 0xDD, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x0E, 0x00, 0x00, 0xDD, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x14, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x14, 0x00, 0x00, + 0x03, 0x0E, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, 0x05, 0x0E, 0x00, 0x00, + 0x05, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x0E, 0x00, 0x00, 0xE4, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, + 0xE4, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x00, 0x00, 0xE4, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6A, 0x14, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6D, 0x14, 0x00, 0x00, + 0x10, 0x0E, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x12, 0x0E, 0x00, 0x00, + 0x12, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1B, 0x0E, 0x00, 0x00, 0xEB, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1D, 0x0E, 0x00, 0x00, + 0xEB, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1F, 0x0E, 0x00, 0x00, 0xEB, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x74, 0x14, 0x00, 0x00, 0x1B, 0x0E, 0x00, 0x00, 0x1B, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x14, 0x00, 0x00, + 0x1D, 0x0E, 0x00, 0x00, 0x1D, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x14, 0x00, 0x00, 0x1F, 0x0E, 0x00, 0x00, + 0x1F, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x28, 0x0E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x0E, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2C, 0x0E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7E, 0x14, 0x00, 0x00, 0x28, 0x0E, 0x00, 0x00, 0x28, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, + 0x2A, 0x0E, 0x00, 0x00, 0x2A, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x84, 0x14, 0x00, 0x00, 0x2C, 0x0E, 0x00, 0x00, + 0x2C, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x35, 0x0E, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x0E, 0x00, 0x00, + 0x07, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x39, 0x0E, 0x00, 0x00, 0x07, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x88, 0x14, 0x00, 0x00, 0x35, 0x0E, 0x00, 0x00, 0x35, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8B, 0x14, 0x00, 0x00, + 0x37, 0x0E, 0x00, 0x00, 0x37, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, 0x39, 0x0E, 0x00, 0x00, + 0x39, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x0E, 0x00, 0x00, 0xF9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x0E, 0x00, 0x00, + 0xF9, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, 0xF9, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x14, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9F, 0x14, 0x00, 0x00, + 0x51, 0x0E, 0x00, 0x00, 0x51, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA2, 0x14, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, + 0x53, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5C, 0x0E, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5E, 0x0E, 0x00, 0x00, + 0x0E, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x60, 0x0E, 0x00, 0x00, 0x0E, 0x14, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA6, 0x14, 0x00, 0x00, 0x5C, 0x0E, 0x00, 0x00, 0x5C, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA9, 0x14, 0x00, 0x00, + 0x5E, 0x0E, 0x00, 0x00, 0x5E, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAC, 0x14, 0x00, 0x00, 0x60, 0x0E, 0x00, 0x00, + 0x60, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCA, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x45, 0x14, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCB, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x27, 0x14, 0x00, 0x00, 0xCA, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, + 0x77, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xCB, 0x14, 0x00, 0x00, 0xD1, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF4, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF5, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x14, 0x00, 0x00, + 0xF4, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFB, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x59, 0x14, 0x00, 0x00, 0x77, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xF5, 0x14, 0x00, 0x00, 0xFB, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0x59, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1F, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x31, 0x14, 0x00, 0x00, 0x1E, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x25, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x63, 0x14, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1F, 0x15, 0x00, 0x00, + 0x25, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x48, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x4F, 0x14, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x49, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x31, 0x14, 0x00, 0x00, 0x48, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x63, 0x14, 0x00, 0x00, + 0x81, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x50, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x49, 0x15, 0x00, 0x00, 0x4F, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x72, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x6D, 0x14, 0x00, 0x00, 0x77, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0x72, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x79, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x81, 0x14, 0x00, 0x00, 0x9F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7A, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x73, 0x15, 0x00, 0x00, 0x79, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9C, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6D, 0x14, 0x00, 0x00, + 0x77, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9D, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x4F, 0x14, 0x00, 0x00, 0x9C, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, 0x9F, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x9D, 0x15, 0x00, 0x00, + 0xA3, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x77, 0x14, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC7, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, 0xC6, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCD, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x8B, 0x14, 0x00, 0x00, + 0xA9, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCE, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xC7, 0x15, 0x00, 0x00, 0xCD, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF0, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x77, 0x14, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF1, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, + 0xF0, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF7, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x8B, 0x14, 0x00, 0x00, 0xA9, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF8, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xF1, 0x15, 0x00, 0x00, 0xF7, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x16, 0x00, 0x00, + 0xFC, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x18, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x17, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x16, 0x00, 0x00, + 0x18, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x38, 0x16, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x39, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x38, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3A, 0x16, 0x00, 0x00, 0x39, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x59, 0x16, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5A, 0x16, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x59, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x16, 0x00, 0x00, 0x5A, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7A, 0x16, 0x00, 0x00, + 0xF8, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7B, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x7A, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7C, 0x16, 0x00, 0x00, + 0x7B, 0x16, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xD2, 0x14, 0x00, 0x00, + 0xB8, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBB, 0x0F, 0x00, 0x00, 0xB9, 0x0F, 0x00, 0x00, 0x19, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA6, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xBB, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x50, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD1, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x26, 0x15, 0x00, 0x00, 0xD0, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD3, 0x0F, 0x00, 0x00, 0xD1, 0x0F, 0x00, 0x00, + 0x3A, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD9, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xD3, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE8, 0x0F, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE9, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x7A, 0x15, 0x00, 0x00, 0xE8, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEB, 0x0F, 0x00, 0x00, + 0xE9, 0x0F, 0x00, 0x00, 0x5B, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xEB, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xF8, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xCE, 0x15, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x7C, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3F, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6D, 0x17, 0x00, 0x00, 0xA6, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6F, 0x17, 0x00, 0x00, + 0x6D, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x71, 0x17, 0x00, 0x00, 0x6F, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x72, 0x17, 0x00, 0x00, 0x71, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x17, 0x00, 0x00, 0xD9, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA2, 0x17, 0x00, 0x00, + 0xA0, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA4, 0x17, 0x00, 0x00, 0xA2, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x17, 0x00, 0x00, 0xA4, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x17, 0x00, 0x00, 0x0C, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD5, 0x17, 0x00, 0x00, + 0xD3, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD7, 0x17, 0x00, 0x00, 0xD5, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD8, 0x17, 0x00, 0x00, 0xD7, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x3F, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, + 0x06, 0x18, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x18, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x18, 0x00, 0x00, 0x0A, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2D, 0x10, 0x00, 0x00, + 0x72, 0x17, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0xA5, 0x17, 0x00, 0x00, + 0x27, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3F, 0x10, 0x00, 0x00, 0xD8, 0x17, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, + 0x0B, 0x18, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4E, 0x10, 0x00, 0x00, 0x73, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x4E, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, + 0x73, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x52, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x54, 0x10, 0x00, 0x00, 0x4F, 0x10, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, + 0x4E, 0x10, 0x00, 0x00, 0x53, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, 0x4F, 0x10, 0x00, 0x00, + 0x52, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x10, 0x00, 0x00, 0x4E, 0x10, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x10, 0x00, 0x00, + 0xFC, 0x14, 0x00, 0x00, 0xD2, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6C, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x6B, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x34, 0x18, 0x00, 0x00, 0x6C, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x35, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x34, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x36, 0x18, 0x00, 0x00, 0x35, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, + 0x36, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, + 0x0A, 0x08, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3F, 0x18, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x18, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x3F, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x18, 0x00, 0x00, 0x40, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, + 0x5B, 0x10, 0x00, 0x00, 0x41, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7B, 0x10, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, + 0x7A, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x7B, 0x10, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x18, 0x00, 0x00, + 0x7C, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x4A, 0x18, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x18, 0x00, 0x00, + 0x4B, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7F, 0x10, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, 0x4C, 0x18, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0xF8, 0x15, 0x00, 0x00, 0xCE, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x83, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x18, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x56, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x55, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x18, 0x00, 0x00, 0x56, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, 0x67, 0x10, 0x00, 0x00, + 0x57, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x2D, 0x10, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, + 0x36, 0x10, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x00, + 0x7F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA9, 0x10, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0xA9, 0x10, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, + 0x87, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC4, 0x10, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x10, 0x00, 0x00, + 0xC4, 0x10, 0x00, 0x00, 0x77, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE1, 0x10, 0x00, 0x00, 0xC4, 0x10, 0x00, 0x00, + 0x7F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFC, 0x10, 0x00, 0x00, 0xA9, 0x10, 0x00, 0x00, 0x87, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x1A, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6F, 0x1A, 0x00, 0x00, 0x6E, 0x1A, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x1A, 0x00, 0x00, 0x6F, 0x1A, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x11, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x70, 0x1A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x28, 0x11, 0x00, 0x00, 0x26, 0x11, 0x00, 0x00, + 0xAB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2A, 0x11, 0x00, 0x00, 0x28, 0x11, 0x00, 0x00, 0xC6, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x11, 0x00, 0x00, + 0x2A, 0x11, 0x00, 0x00, 0xE1, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, 0x2C, 0x11, 0x00, 0x00, + 0xFC, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6E, 0x18, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6F, 0x18, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, + 0x6E, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x00, 0x00, 0x6F, 0x18, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x18, 0x00, 0x00, 0x70, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, + 0x73, 0x18, 0x00, 0x00, 0x2E, 0x11, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x77, 0x18, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x70, 0x18, 0x00, 0x00, 0x77, 0x18, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x1A, 0x00, 0x00, + 0x24, 0x14, 0x00, 0x00, 0x42, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x11, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x71, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3C, 0x11, 0x00, 0x00, 0x2E, 0x14, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3D, 0x11, 0x00, 0x00, + 0x38, 0x11, 0x00, 0x00, 0x3C, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, 0x60, 0x14, 0x00, 0x00, + 0x96, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x42, 0x11, 0x00, 0x00, 0x3D, 0x11, 0x00, 0x00, 0x41, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, + 0x6A, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x42, 0x11, 0x00, 0x00, + 0x46, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4B, 0x11, 0x00, 0x00, 0x9C, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x11, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x4B, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x50, 0x11, 0x00, 0x00, 0x88, 0x14, 0x00, 0x00, + 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x51, 0x11, 0x00, 0x00, 0x4C, 0x11, 0x00, 0x00, 0x50, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x55, 0x11, 0x00, 0x00, + 0xA6, 0x14, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x56, 0x11, 0x00, 0x00, 0x51, 0x11, 0x00, 0x00, + 0x55, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5A, 0x11, 0x00, 0x00, 0x4C, 0x14, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5B, 0x11, 0x00, 0x00, + 0x56, 0x11, 0x00, 0x00, 0x5A, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x11, 0x00, 0x00, 0x56, 0x14, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x11, 0x00, 0x00, 0x5B, 0x11, 0x00, 0x00, 0x5F, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x64, 0x11, 0x00, 0x00, + 0x74, 0x14, 0x00, 0x00, 0xE1, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x11, 0x00, 0x00, 0x60, 0x11, 0x00, 0x00, + 0x64, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x11, 0x00, 0x00, 0x7E, 0x14, 0x00, 0x00, 0xFC, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6A, 0x11, 0x00, 0x00, + 0x65, 0x11, 0x00, 0x00, 0x69, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6C, 0x11, 0x00, 0x00, 0x6A, 0x11, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x86, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x6C, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x1A, 0x00, 0x00, + 0x27, 0x14, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x11, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x72, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7A, 0x11, 0x00, 0x00, 0x31, 0x14, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7B, 0x11, 0x00, 0x00, + 0x76, 0x11, 0x00, 0x00, 0x7A, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x11, 0x00, 0x00, 0x63, 0x14, 0x00, 0x00, + 0x96, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x80, 0x11, 0x00, 0x00, 0x7B, 0x11, 0x00, 0x00, 0x7F, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x11, 0x00, 0x00, + 0x6D, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x11, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, + 0x84, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x89, 0x11, 0x00, 0x00, 0x9F, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8A, 0x11, 0x00, 0x00, + 0x85, 0x11, 0x00, 0x00, 0x89, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8E, 0x11, 0x00, 0x00, 0x8B, 0x14, 0x00, 0x00, + 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8F, 0x11, 0x00, 0x00, 0x8A, 0x11, 0x00, 0x00, 0x8E, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x11, 0x00, 0x00, + 0xA9, 0x14, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x8F, 0x11, 0x00, 0x00, + 0x93, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x98, 0x11, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x99, 0x11, 0x00, 0x00, + 0x94, 0x11, 0x00, 0x00, 0x98, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9D, 0x11, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9E, 0x11, 0x00, 0x00, 0x99, 0x11, 0x00, 0x00, 0x9D, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA2, 0x11, 0x00, 0x00, + 0x77, 0x14, 0x00, 0x00, 0xE1, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x11, 0x00, 0x00, 0x9E, 0x11, 0x00, 0x00, + 0xA2, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA7, 0x11, 0x00, 0x00, 0x81, 0x14, 0x00, 0x00, 0xFC, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x11, 0x00, 0x00, + 0xA3, 0x11, 0x00, 0x00, 0xA7, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAA, 0x11, 0x00, 0x00, 0xA8, 0x11, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xAA, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x1A, 0x00, 0x00, + 0x2A, 0x14, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB4, 0x11, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, + 0x73, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x11, 0x00, 0x00, 0x34, 0x14, 0x00, 0x00, 0x96, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x11, 0x00, 0x00, + 0xB4, 0x11, 0x00, 0x00, 0xB8, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBD, 0x11, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, + 0x96, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBE, 0x11, 0x00, 0x00, 0xB9, 0x11, 0x00, 0x00, 0xBD, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC2, 0x11, 0x00, 0x00, + 0x70, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC3, 0x11, 0x00, 0x00, 0xBE, 0x11, 0x00, 0x00, + 0xC2, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x11, 0x00, 0x00, 0xA2, 0x14, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x11, 0x00, 0x00, + 0xC3, 0x11, 0x00, 0x00, 0xC7, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCC, 0x11, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, + 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCD, 0x11, 0x00, 0x00, 0xC8, 0x11, 0x00, 0x00, 0xCC, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x11, 0x00, 0x00, + 0xAC, 0x14, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD2, 0x11, 0x00, 0x00, 0xCD, 0x11, 0x00, 0x00, + 0xD1, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x11, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x11, 0x00, 0x00, + 0xD2, 0x11, 0x00, 0x00, 0xD6, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDB, 0x11, 0x00, 0x00, 0x5C, 0x14, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDC, 0x11, 0x00, 0x00, 0xD7, 0x11, 0x00, 0x00, 0xDB, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x11, 0x00, 0x00, + 0x7A, 0x14, 0x00, 0x00, 0xE1, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE1, 0x11, 0x00, 0x00, 0xDC, 0x11, 0x00, 0x00, + 0xE0, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE5, 0x11, 0x00, 0x00, 0x84, 0x14, 0x00, 0x00, 0xFC, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0x11, 0x00, 0x00, + 0xE1, 0x11, 0x00, 0x00, 0xE5, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE8, 0x11, 0x00, 0x00, 0xE6, 0x11, 0x00, 0x00, + 0x78, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA2, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xE8, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xEF, 0x09, 0x00, 0x00, 0xF0, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xF0, 0x09, 0x00, 0x00, 0x86, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xEF, 0x09, 0x00, 0x00, 0xF2, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x52, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xF2, 0x09, 0x00, 0x00, + 0x94, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xEF, 0x09, 0x00, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xF4, 0x09, 0x00, 0x00, 0xA2, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xF6, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF8, 0x09, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xF9, 0x09, 0x00, 0x00, 0xF8, 0x09, 0x00, 0x00, 0xF7, 0x09, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0xF9, 0x09, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xFA, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xFB, 0x09, 0x00, 0x00, 0xFA, 0x09, 0x00, 0x00, + 0xFA, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xAE, 0x18, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x7D, 0x1A, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB0, 0x18, 0x00, 0x00, + 0xAE, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB1, 0x18, 0x00, 0x00, 0xB0, 0x18, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB3, 0x18, 0x00, 0x00, 0xAE, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB4, 0x18, 0x00, 0x00, + 0xB1, 0x18, 0x00, 0x00, 0xB3, 0x18, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xA9, 0x18, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0xB5, 0x18, 0x00, 0x00, 0xA9, 0x18, 0x00, 0x00, + 0xB4, 0x18, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB6, 0x18, 0x00, 0x00, 0xB5, 0x18, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xFF, 0x09, 0x00, 0x00, 0xB6, 0x18, 0x00, 0x00, + 0xB6, 0x18, 0x00, 0x00, 0xB6, 0x18, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xFB, 0x09, 0x00, 0x00, + 0xFF, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x03, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x04, 0x0A, 0x00, 0x00, + 0xE1, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x05, 0x0A, 0x00, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x05, 0x0A, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xEF, 0x09, 0x00, 0x00, + 0x07, 0x0A, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0x06, 0x0A, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x07, 0x0A, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..caa33928396f2bc3911018e38773461394561f83 GIT binary patch literal 14540 zcmZ{r2b307wuOIal8Bf_MV(R9F$^;3IEsK{ehMQz8&ELd*dR363f*mYgNRB-KmR*$T|E|KZSiV@% zSdm!sTVnCQYh(FQVzDb@h2sBKtnyNoGTAxx$~^qYgEAD4CB=R6TpcSME5N@(qdIBn z3QWBs7TX7|!6%&pw36sG78_1d0jgE3l2S1_xnh;)QtD=Arex=Q&@eTnVOn}>O1-qK z)VeuoO;Y7668O^6>o#m$FEkXy5!NjjD;OI`|4matt6?&92iZvtjD98R^+Mb<%UPV`N!%JBmVjvdrIAmh8bDt6*+62=bdraWqwD%bc z(v)AC;%Zj|ZQHb&WxP84&=2)17=H=AXZLRBFT>ZYUhV!G@X@12dAufk(7@X~{tEoF zPMtjdDt!91X&!$KK6%n4kG~FY|4AX|wcvvX4RZbleAC8_p8p?szrMG4{7rbz9zAmH z_*39tbnE8v+VEMqxt?DKK5y<^kG}=)+NHS1>%u#BC{o_~(+x9lzyObPTg46@INXgUdfq&k$tLMK9-?(AJOsn4z-s#h#9&ZGn zGkdn@Yti}R;zf^Vz-LS^>pT-aWN^uH*57;Z*|REmzV4~<0zTA07__(p9oPP=*J7$dc*9pFPQ+1Dj z2466LzVpuTpN<}Ne;4?7d*1YT*F5g=&*4A+^i!_Qe>XVyr~AKv_vu~2g~d@&0OZdtal{~)}ocq=Nz2TpcU-rDmN5h$4kB@<0IDg*bW8vTK*x~VU@DAlNNui#v-&L_ZGpDNh-ehvR>{CFSFiEz%}{gdF^wr+L*WcaTqPI!C@eEz&AJU$hE z?3Z+pPlNyR^Uofi4*#-ePmj-lFI}?4>(7L!HUNz*#??FNE*gTig3z1Rp+ZnCCBscmC`%KmH}~ zRV!C|{!)0Wma!Q&-pk-4h7b4aZ#jJ8*I&DT1)TNL`(FuXK0Uq)&h_T;)$rA;Uhw!D zIQ@BiEu7=?dh6h)XaDl!-vFmSk8gyt-h2O>;A_{c@%}c$8BdRIfuA~g()-&A zXFR;WZE&tv_iu+!nf#E)zk#zqczg$(=MU%K!nuFF|DEt3j~wy%E;#Fv$9KcoU%mf5 zaPA-Xe+S?B?d#6>!oT0Q&;9%0T{?Gm{ym)a-u?UG>`xv)0Oxp|AB1y$?*9SK{^apP z@Cjdi<@_+5{mGC22z=Snr5^tg&iz{6uBW4L{$?Bh3Bvm1^?rtL*}U2Fe}VVz)yw0@ z;H>xF-*Gt4D_;Kuob}q{zrwk{yuaVz+|SAD<*R&x0N>0PoSgyZ2WR-mYz1_ZNb5z8)_OXMJ>D1kUy6 z{apcPzC2zO&U)zaE8*+bu614v&iKu=@wp1l^Red_hx7d8{;S~&7c6+x{MW$QZ`^+^ z{J{SG?!OMs^PtDChx5Ge@jt=$e)pZnZ-5USGQ{II!r8xlK5l~ZJnZojaP||=zZuT{ z!*+Bt#F=~y}v)hdERmVU*Km>H}U>&gY!J+`M1M){`GiCIL{xRe+QiLb$%zD z@$&WjE;#Qu9{($x=P~c^ZaB|>9=`|9^SJYS;k*yI|2{bPkI&!V;OwU!F9qlCF`KXZ z;oMK&UupQLk@q#C?2jJ{y9)A$d_3GpK4>-@G9)AeV_3iwhaP9~9 zKMZGo@bP^F{`DUk5_>6{OR=`gR?%n|6g$S zYahSI;k@s;{|PwntKQ#}aMl;+Pr-S=bpAA)=XF1yXW+b#dHh*8`-k)YfiwOU?0lYs zv;X`3^*o&MaDPQO>y!6i3C{D7AMd~6+<)$W0nYQV`zyn_zdT+A&i&{0{};~n@9`Jm z%)iHz;XKbduL@`XE?+v9l&>lmS~Ykz{;dvP0xyFapeA?)yb4|euY+3P4e%fECP)Fb zK^^cGs0-?WR8Su@0B?gd@D6wvGz5)6I>-Q-;60E9vOx}L44Q!VK~wMnXa+t6AAyfS zbI<~`1g$`8&<3;x?Z79XJ?H>Bf=@vw@EPa~x`3|WbI=WZ0lI@8peOhe^a8y>AJ7-{ z1O34OFc1s^gTW9m6bu8y!3Z!Ci~^&<7%&!$1LMJ0U;_9WOazm_WH1Fx1=GNEFayj4 zxnLHU4d#HkU>=wc7J!9d5m*eCfTds=SPoWzm0%TE4c36QU>#TwHh_&_6W9#4fURH~ z*bcq{JHWSKC)fpcgFWCouovtD--G?&05}MK0EfU~a0L7aj)I@S&)^qu3>*h1z^~vp za1xvXr@w5O5(3YyD;slz}CVhQQY_kao+Mt>%T3${PS~eH{J<8yZQ0v#(Tmq4LT9$SJ3Z} zcz*1uoB2{Xnzpn&iAMBi{8qk#j)BOh;~N_Vq&*h#agnBa50F10;`)|4k+%9T04%;7 z?Gk^b`DXke`Z~CBq?>08ZT^dyXDdXSJf`i8xN=Q9NL#*8I~w_&`x3Ct| zp&(87%g1Py`Bx~5ra93yr$6PMMJdR?8Ux*9V@l-RXOF{mjZUL4jb$>usm65L(ggis zVQ7XkI7Ye4q3s=D9^6bk))vZU*sM^r2eN*p^6Fj@GTMaB1fl zyL`p+#!&xeM#onBs=RZMU&m4(uH$PL9Y+JWJkrh6h_;TURpd#B%O|}URn<=>ZH>1s zeZ}p(vT2JeZgbH%;w|Y<k2cR_-8AzYe{(Y#ixbyQ1ho#ii2$X@}MCU0VXhbUib zpyh8($lnH+CU0VXrzn3fb71+q67qM$rOBI^-zCb|dTaUn6Y>whrOBI^-!015+HCnh zCgdN5OOrP-zgLv6_15ywCgh)kOOrP-zi*VUeZcZBCFIBc#NLG_Z({y{C|_&4-8v}uvXDY-Ty(v+`zRk?qq z&v-sD)9yu6zF=A@H029cV*zblm-;hpQKW@+mqc1vw+#I$U$7egKvTY8+QVqd7p%s& zv~}-=b$3NtSa(mPg>|2yKjjNn<2f|t3#L^iP)}%k>3s&PbH02AXy@95D!RqEK&bvuM z-K0nh>lTc(ux@SoQ@&s|>Y^!MFs(kC@&&6~oVM1B@O-a{w6N}Vkrvi{hyIi=SdB(# z$`?$_L{q+Cb#JAubtbI)mq-ii-X3XT-5mN;zF;-pM^nCFS~E1|3s(0&+FD=2x}_p5 ztXn$L!n)1LQ@&s|TA?XlFs&_`@&&8=2yLxPVcka~Ev#EU(!#nO$Wy*xH9DawUofo; zn(_s!n@n5laagxnq=j`~inOq9fBI9tU^NDzDPJ&cD4OyGtNR9Rt)pSxHzO^qTRYOi zx+BR`zF;-RpebK4Z9JOtgD+XkTC7zfYq8@|Oy`$a??ez&J$WtfOb|<~cQ%Nr4|(l<=B69@ z&P88(C)4{)33w-NNa^zE9=(~ibjvA6Ti1l;l!q%vy5&@$E!}cnqpfkaoY&#Xk#0G) zXiK-8X0&zemh&N8InpiXBihpSKBQxvd3D~qvd+oICKrvg_!^_NK^|L^X46*uX8I_` z+m-qlNn8H=f#P~E*Za5C*nlRkF|ZmN(Uha>ME9pWR%0`5#VZ6gb_6vPPpokmO*J%T zR^teo)zCd6kJUIzTXBt{oky{oE}w_ui8b`WO*J&eRwEyp)zEb+kJU(03~0=)#*;w} z#jS?TVI$%i&qdMol>wKg?|*v7(>3=VT)Mv5*}P`KrCUFPX=}`^pP_JRVL!v+(!+j6 zz@=M1n`vuYte>s4rG@=$hf5Fp`35fC`YFV>5}mvCQv@z8?58MPdf3mEaOrlQ_cCVs zreI_Iceu`7x@l!;>pVj3Ni-c(s8vE!|I%zMPXVg3A}?Hi&%Etj4>vb+78a)b|hFe+|*}jZZNf?}s@r>8+z{ z<`KBo0_irEWob*dw|bS~su$Ozb+`(ebgS0_zs6a*)oTOS{j7V} z>a|5vJ;khE4RWMgy_#^)$a!*$JStWEopwys%?hiRi}>zdUu z+i{JdEw5sxjiW6+>~Aq#*S6}LZwYPHR?M_zw56-AY5O8Ata|}XHNyVV`7WsbbUc=u zfhIjXzD&4u)wOfG=i0pA4-~W9`_QE8d`v3^m#*V9tu$P^j?=Uu3ztHskA{@uZ(d1Rkd{5KXdvNG`22EbY%=bKPy|;#QP!UaD#mrZkcK-xl6*PGj zGhbEOdOr)Vn`&tCDrUYKwDn#S`f8%dtC;y-r>*Z7;XKzulUFhGrAWgU&V6k(c@;BX zJ=%I-4zGt)GUm9(_-|8B%IeG_8Ud7DUkhXNqsqNXH&}O>h&o_$Oo^AbPF`s(> z(fgS7(*&R9S~1g_q3Jy$oWl>*A5hGEEokeVBJ{OHlUFhGwWY0R`f#q>p~-jwN^+1zXG4u7Nt@ny>uKS?LtC;x)(2lk4BSMG4qY3Ej^s;9>H8Io;cUp%x5Y3 z);B%tXDU9;wPL2tM0*%dIET4t@+xM&xwQ4&D)h}mlUFhGEuyXOOyL|ZMw3@D^DU>X z?-ikM1)98ynQskkeNPGJa4nj=ikWXCZGDFbeVfqaRm^_J!HD1D{gcBG|x=> z&G9(U?~wX!{fSsooNFzx_^(l1&#;P%>-w?y$tbShe-#&3P5Zs@R1{C)H&MHz!mGnsj;FM%pB}^cslfn-cl3`TNXN zG$hb6ZfxUGfOa^Z1>w?^_y3KjJT~uzX)9m9IqQ7H_5N^?s^!3c0ig!P*8l(j literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt new file mode 100644 index 000000000..947758262 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.txt @@ -0,0 +1,728 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6782 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasResampleConstants "XeCasResampleConstants" + OpMemberName %XeCasResampleConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasResampleConstants 1 "xe_cas_input_output_size_ratio" + OpMemberName %XeCasResampleConstants 2 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasResampleConstants 0 Offset 16 + OpMemberDecorate %XeCasResampleConstants 1 Offset 24 + OpMemberDecorate %XeCasResampleConstants 2 Offset 32 + OpDecorate %XeCasResampleConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %337 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %424 = OpTypeImage %float 2D 0 0 0 1 Unknown + %425 = OpTypeSampledImage %424 +%_ptr_UniformConstant_425 = OpTypePointer UniformConstant %425 + %xe_texture = OpVariable %_ptr_UniformConstant_425 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %462 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %469 = OpConstantComposite %v2int %int_1 %int_n1 + %475 = OpConstantComposite %v2int %int_n1 %int_0 + %485 = OpConstantComposite %v2int %int_1 %int_0 + %491 = OpConstantComposite %v2int %int_n1 %int_1 + %497 = OpConstantComposite %v2int %int_0 %int_1 + %503 = OpConstantComposite %v2int %int_1 %int_1 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %992 = OpConstantComposite %v2int %int_2 %int_0 + %1014 = OpConstantComposite %v2int %int_0 %int_2 + %1025 = OpConstantComposite %v2int %int_2 %int_1 + %1031 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasResampleConstants = OpTypeStruct %v2int %v2float %float +%_ptr_PushConstant_XeCasResampleConstants = OpTypePointer PushConstant %XeCasResampleConstants + %_ = OpVariable %_ptr_PushConstant_XeCasResampleConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0_5 = OpConstant %float 0.5 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %2561 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %2562 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %6765 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %6781 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %6313 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %2485 = OpLoad %v4float %gl_FragCoord + %2486 = OpVectorShuffle %v2float %2485 %2485 0 1 + %2487 = OpConvertFToS %v2int %2486 + %2492 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2493 = OpLoad %v2int %2492 + %2494 = OpISub %v2int %2487 %2493 + %2495 = OpBitcast %v2uint %2494 + %2498 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %2499 = OpLoad %v2float %2498 + %2500 = OpBitcast %v2uint %2499 + %2504 = OpVectorTimesScalar %v2float %2499 %float_0_5 + %2506 = OpFSub %v2float %2504 %6765 + %2507 = OpBitcast %v2uint %2506 + %2515 = OpAccessChain %_ptr_PushConstant_float %_ %int_2 + %2516 = OpLoad %float %2515 + %2517 = OpBitcast %uint %2516 + OpBranch %3073 + %3073 = OpLabel + %3424 = OpConvertUToF %v2float %2495 + %3430 = OpBitcast %v2float %2500 + %3431 = OpFMul %v2float %3424 %3430 + %3437 = OpBitcast %v2float %2507 + %3438 = OpFAdd %v2float %3431 %3437 + %3440 = OpExtInst %v2float %1 Floor %3438 + %3443 = OpFSub %v2float %3438 %3440 + %3445 = OpConvertFToS %v2int %3440 + %3450 = OpIAdd %v2int %3445 %462 + %5040 = OpLoad %425 %xe_texture + %5042 = OpImage %424 %5040 + %5043 = OpImageFetch %v4float %5042 %3450 Lod %int_0 + %3453 = OpIAdd %v2int %3445 %475 + %5049 = OpImage %424 %5040 + %5050 = OpImageFetch %v4float %5049 %3453 Lod %int_0 + %5056 = OpImage %424 %5040 + %5057 = OpImageFetch %v4float %5056 %3445 Lod %int_0 + %3458 = OpIAdd %v2int %3445 %469 + %5063 = OpImage %424 %5040 + %5064 = OpImageFetch %v4float %5063 %3458 Lod %int_0 + %3464 = OpIAdd %v2int %3445 %485 + %5077 = OpImage %424 %5040 + %5078 = OpImageFetch %v4float %5077 %3464 Lod %int_0 + %3467 = OpIAdd %v2int %3445 %992 + %5084 = OpImage %424 %5040 + %5085 = OpImageFetch %v4float %5084 %3467 Lod %int_0 + %3470 = OpIAdd %v2int %3445 %491 + %5091 = OpImage %424 %5040 + %5092 = OpImageFetch %v4float %5091 %3470 Lod %int_0 + %3473 = OpIAdd %v2int %3445 %497 + %5098 = OpImage %424 %5040 + %5099 = OpImageFetch %v4float %5098 %3473 Lod %int_0 + %3479 = OpIAdd %v2int %3445 %1014 + %5112 = OpImage %424 %5040 + %5113 = OpImageFetch %v4float %5112 %3479 Lod %int_0 + %3482 = OpIAdd %v2int %3445 %503 + %5119 = OpImage %424 %5040 + %5120 = OpImageFetch %v4float %5119 %3482 Lod %int_0 + %3485 = OpIAdd %v2int %3445 %1025 + %5126 = OpImage %424 %5040 + %5127 = OpImageFetch %v4float %5126 %3485 Lod %int_0 + %3488 = OpIAdd %v2int %3445 %1031 + %5133 = OpImage %424 %5040 + %5134 = OpImageFetch %v4float %5133 %3488 Lod %int_0 + %3507 = OpCompositeExtract %float %5043 0 + %3509 = OpCompositeExtract %float %5043 1 + %3511 = OpCompositeExtract %float %5043 2 + %5156 = OpFMul %float %3507 %3507 + %5159 = OpFMul %float %3509 %3509 + %5162 = OpFMul %float %3511 %3511 + %3520 = OpCompositeExtract %float %5064 0 + %3522 = OpCompositeExtract %float %5064 1 + %3524 = OpCompositeExtract %float %5064 2 + %5166 = OpFMul %float %3520 %3520 + %5169 = OpFMul %float %3522 %3522 + %5172 = OpFMul %float %3524 %3524 + %3546 = OpCompositeExtract %float %5050 0 + %3548 = OpCompositeExtract %float %5050 1 + %3550 = OpCompositeExtract %float %5050 2 + %5186 = OpFMul %float %3546 %3546 + %5189 = OpFMul %float %3548 %3548 + %5192 = OpFMul %float %3550 %3550 + %3559 = OpCompositeExtract %float %5057 0 + %3561 = OpCompositeExtract %float %5057 1 + %3563 = OpCompositeExtract %float %5057 2 + %5196 = OpFMul %float %3559 %3559 + %5199 = OpFMul %float %3561 %3561 + %5202 = OpFMul %float %3563 %3563 + %3572 = OpCompositeExtract %float %5078 0 + %3574 = OpCompositeExtract %float %5078 1 + %3576 = OpCompositeExtract %float %5078 2 + %5206 = OpFMul %float %3572 %3572 + %5209 = OpFMul %float %3574 %3574 + %5212 = OpFMul %float %3576 %3576 + %3585 = OpCompositeExtract %float %5085 0 + %3587 = OpCompositeExtract %float %5085 1 + %3589 = OpCompositeExtract %float %5085 2 + %5216 = OpFMul %float %3585 %3585 + %5219 = OpFMul %float %3587 %3587 + %5222 = OpFMul %float %3589 %3589 + %3598 = OpCompositeExtract %float %5092 0 + %3600 = OpCompositeExtract %float %5092 1 + %3602 = OpCompositeExtract %float %5092 2 + %5226 = OpFMul %float %3598 %3598 + %5229 = OpFMul %float %3600 %3600 + %5232 = OpFMul %float %3602 %3602 + %3611 = OpCompositeExtract %float %5099 0 + %3613 = OpCompositeExtract %float %5099 1 + %3615 = OpCompositeExtract %float %5099 2 + %5236 = OpFMul %float %3611 %3611 + %5239 = OpFMul %float %3613 %3613 + %5242 = OpFMul %float %3615 %3615 + %3624 = OpCompositeExtract %float %5120 0 + %3626 = OpCompositeExtract %float %5120 1 + %3628 = OpCompositeExtract %float %5120 2 + %5246 = OpFMul %float %3624 %3624 + %5249 = OpFMul %float %3626 %3626 + %5252 = OpFMul %float %3628 %3628 + %3637 = OpCompositeExtract %float %5127 0 + %3639 = OpCompositeExtract %float %5127 1 + %3641 = OpCompositeExtract %float %5127 2 + %5256 = OpFMul %float %3637 %3637 + %5259 = OpFMul %float %3639 %3639 + %5262 = OpFMul %float %3641 %3641 + %3663 = OpCompositeExtract %float %5113 0 + %3665 = OpCompositeExtract %float %5113 1 + %3667 = OpCompositeExtract %float %5113 2 + %5276 = OpFMul %float %3663 %3663 + %5279 = OpFMul %float %3665 %3665 + %5282 = OpFMul %float %3667 %3667 + %3676 = OpCompositeExtract %float %5134 0 + %3678 = OpCompositeExtract %float %5134 1 + %3680 = OpCompositeExtract %float %5134 2 + %5286 = OpFMul %float %3676 %3676 + %5289 = OpFMul %float %3678 %3678 + %5292 = OpFMul %float %3680 %3680 + %5322 = OpExtInst %float %1 FMin %5189 %5199 + %5323 = OpExtInst %float %1 FMin %5159 %5322 + %5329 = OpExtInst %float %1 FMin %5209 %5239 + %5330 = OpExtInst %float %1 FMin %5323 %5329 + %5364 = OpExtInst %float %1 FMax %5189 %5199 + %5365 = OpExtInst %float %1 FMax %5159 %5364 + %5371 = OpExtInst %float %1 FMax %5209 %5239 + %5372 = OpExtInst %float %1 FMax %5365 %5371 + %5406 = OpExtInst %float %1 FMin %5199 %5209 + %5407 = OpExtInst %float %1 FMin %5169 %5406 + %5413 = OpExtInst %float %1 FMin %5219 %5249 + %5414 = OpExtInst %float %1 FMin %5407 %5413 + %5448 = OpExtInst %float %1 FMax %5199 %5209 + %5449 = OpExtInst %float %1 FMax %5169 %5448 + %5455 = OpExtInst %float %1 FMax %5219 %5249 + %5456 = OpExtInst %float %1 FMax %5449 %5455 + %5490 = OpExtInst %float %1 FMin %5229 %5239 + %5491 = OpExtInst %float %1 FMin %5199 %5490 + %5497 = OpExtInst %float %1 FMin %5249 %5279 + %5498 = OpExtInst %float %1 FMin %5491 %5497 + %5532 = OpExtInst %float %1 FMax %5229 %5239 + %5533 = OpExtInst %float %1 FMax %5199 %5532 + %5539 = OpExtInst %float %1 FMax %5249 %5279 + %5540 = OpExtInst %float %1 FMax %5533 %5539 + %5574 = OpExtInst %float %1 FMin %5239 %5249 + %5575 = OpExtInst %float %1 FMin %5209 %5574 + %5581 = OpExtInst %float %1 FMin %5259 %5289 + %5582 = OpExtInst %float %1 FMin %5575 %5581 + %5616 = OpExtInst %float %1 FMax %5239 %5249 + %5617 = OpExtInst %float %1 FMax %5209 %5616 + %5623 = OpExtInst %float %1 FMax %5259 %5289 + %5624 = OpExtInst %float %1 FMax %5617 %5623 + %5655 = OpBitcast %uint %5372 + %5656 = OpISub %uint %uint_2129690299 %5655 + %5657 = OpBitcast %float %5656 + %5688 = OpBitcast %uint %5456 + %5689 = OpISub %uint %uint_2129690299 %5688 + %5690 = OpBitcast %float %5689 + %5721 = OpBitcast %uint %5540 + %5722 = OpISub %uint %uint_2129690299 %5721 + %5723 = OpBitcast %float %5722 + %5754 = OpBitcast %uint %5624 + %5755 = OpISub %uint %uint_2129690299 %5754 + %5756 = OpBitcast %float %5755 + %4024 = OpFSub %float %float_1 %5372 + %4025 = OpExtInst %float %1 FMin %5330 %4024 + %4027 = OpFMul %float %4025 %5657 + %5798 = OpExtInst %float %1 FClamp %4027 %float_0 %float_1 + %4048 = OpFSub %float %float_1 %5456 + %4049 = OpExtInst %float %1 FMin %5414 %4048 + %4051 = OpFMul %float %4049 %5690 + %5849 = OpExtInst %float %1 FClamp %4051 %float_0 %float_1 + %4072 = OpFSub %float %float_1 %5540 + %4073 = OpExtInst %float %1 FMin %5498 %4072 + %4075 = OpFMul %float %4073 %5723 + %5900 = OpExtInst %float %1 FClamp %4075 %float_0 %float_1 + %4096 = OpFSub %float %float_1 %5624 + %4097 = OpExtInst %float %1 FMin %5582 %4096 + %4099 = OpFMul %float %4097 %5756 + %5951 = OpExtInst %float %1 FClamp %4099 %float_0 %float_1 + %5997 = OpBitcast %uint %5798 + %5999 = OpShiftRightLogical %uint %5997 %uint_1 + %6001 = OpIAdd %uint %5999 %uint_532432441 + %6002 = OpBitcast %float %6001 + %6048 = OpBitcast %uint %5849 + %6050 = OpShiftRightLogical %uint %6048 %uint_1 + %6052 = OpIAdd %uint %6050 %uint_532432441 + %6053 = OpBitcast %float %6052 + %6099 = OpBitcast %uint %5900 + %6101 = OpShiftRightLogical %uint %6099 %uint_1 + %6103 = OpIAdd %uint %6101 %uint_532432441 + %6104 = OpBitcast %float %6103 + %6150 = OpBitcast %uint %5951 + %6152 = OpShiftRightLogical %uint %6150 %uint_1 + %6154 = OpIAdd %uint %6152 %uint_532432441 + %6155 = OpBitcast %float %6154 + %4135 = OpBitcast %float %2517 + %4141 = OpFMul %float %6002 %4135 + %4150 = OpFMul %float %6053 %4135 + %4159 = OpFMul %float %6104 %4135 + %4168 = OpFMul %float %6155 %4135 + %4174 = OpCompositeExtract %float %3443 0 + %4175 = OpFSub %float %float_1 %4174 + %4178 = OpCompositeExtract %float %3443 1 + %4179 = OpFSub %float %float_1 %4178 + %4180 = OpFMul %float %4175 %4179 + %4187 = OpFMul %float %4174 %4179 + %4194 = OpFMul %float %4175 %4178 + %4199 = OpFMul %float %4174 %4178 + %4203 = OpFSub %float %5372 %5330 + %4204 = OpFAdd %float %float_0_03125 %4203 + %6196 = OpBitcast %uint %4204 + %6197 = OpISub %uint %uint_2129690299 %6196 + %6198 = OpBitcast %float %6197 + %4207 = OpFMul %float %4180 %6198 + %4211 = OpFSub %float %5456 %5414 + %4212 = OpFAdd %float %float_0_03125 %4211 + %6207 = OpBitcast %uint %4212 + %6208 = OpISub %uint %uint_2129690299 %6207 + %6209 = OpBitcast %float %6208 + %4215 = OpFMul %float %4187 %6209 + %4219 = OpFSub %float %5540 %5498 + %4220 = OpFAdd %float %float_0_03125 %4219 + %6218 = OpBitcast %uint %4220 + %6219 = OpISub %uint %uint_2129690299 %6218 + %6220 = OpBitcast %float %6219 + %4223 = OpFMul %float %4194 %6220 + %4227 = OpFSub %float %5624 %5582 + %4228 = OpFAdd %float %float_0_03125 %4227 + %6229 = OpBitcast %uint %4228 + %6230 = OpISub %uint %uint_2129690299 %6229 + %6231 = OpBitcast %float %6230 + %4231 = OpFMul %float %4199 %6231 + %4237 = OpFMul %float %4141 %4207 + %4246 = OpFMul %float %4150 %4215 + %4264 = OpFMul %float %4159 %4223 + %4265 = OpFAdd %float %4246 %4264 + %4267 = OpFAdd %float %4265 %4207 + %4291 = OpFMul %float %4168 %4231 + %4292 = OpFAdd %float %4237 %4291 + %4294 = OpFAdd %float %4292 %4215 + %4321 = OpFAdd %float %4292 %4223 + %4348 = OpFAdd %float %4265 %4231 + %6766 = OpFAdd %float %4237 %4246 + %6767 = OpFAdd %float %6766 %4264 + %6768 = OpFAdd %float %6767 %4291 + %4390 = OpFMul %float %float_2 %6768 + %4392 = OpFAdd %float %4390 %4267 + %4394 = OpFAdd %float %4392 %4294 + %4396 = OpFAdd %float %4394 %4321 + %4398 = OpFAdd %float %4396 %4348 + %6254 = OpBitcast %uint %4398 + %6255 = OpISub %uint %uint_2129764351 %6254 + %6256 = OpBitcast %float %6255 + %6259 = OpFNegate %float %6256 + %6261 = OpFMul %float %6259 %4398 + %6263 = OpFAdd %float %6261 %float_2 + %6264 = OpFMul %float %6256 %6263 + %6769 = OpFAdd %float %5156 %5186 + %4408 = OpFMul %float %4237 %6769 + %4412 = OpFMul %float %5166 %4246 + %4413 = OpFAdd %float %4408 %4412 + %4417 = OpFMul %float %5216 %4246 + %4418 = OpFAdd %float %4413 %4417 + %4422 = OpFMul %float %5226 %4264 + %4423 = OpFAdd %float %4418 %4422 + %4427 = OpFMul %float %5276 %4264 + %4428 = OpFAdd %float %4423 %4427 + %4432 = OpFMul %float %5256 %4291 + %4433 = OpFAdd %float %4428 %4432 + %4437 = OpFMul %float %5286 %4291 + %4438 = OpFAdd %float %4433 %4437 + %4442 = OpFMul %float %5196 %4267 + %4443 = OpFAdd %float %4438 %4442 + %4447 = OpFMul %float %5206 %4294 + %4448 = OpFAdd %float %4443 %4447 + %4452 = OpFMul %float %5236 %4321 + %4453 = OpFAdd %float %4448 %4452 + %4457 = OpFMul %float %5246 %4348 + %4458 = OpFAdd %float %4453 %4457 + %4460 = OpFMul %float %4458 %6264 + %6278 = OpExtInst %float %1 FClamp %4460 %float_0 %float_1 + %6770 = OpFAdd %float %5159 %5189 + %4470 = OpFMul %float %4237 %6770 + %4474 = OpFMul %float %5169 %4246 + %4475 = OpFAdd %float %4470 %4474 + %4479 = OpFMul %float %5219 %4246 + %4480 = OpFAdd %float %4475 %4479 + %4484 = OpFMul %float %5229 %4264 + %4485 = OpFAdd %float %4480 %4484 + %4489 = OpFMul %float %5279 %4264 + %4490 = OpFAdd %float %4485 %4489 + %4494 = OpFMul %float %5259 %4291 + %4495 = OpFAdd %float %4490 %4494 + %4499 = OpFMul %float %5289 %4291 + %4500 = OpFAdd %float %4495 %4499 + %4504 = OpFMul %float %5199 %4267 + %4505 = OpFAdd %float %4500 %4504 + %4509 = OpFMul %float %5209 %4294 + %4510 = OpFAdd %float %4505 %4509 + %4514 = OpFMul %float %5239 %4321 + %4515 = OpFAdd %float %4510 %4514 + %4519 = OpFMul %float %5249 %4348 + %4520 = OpFAdd %float %4515 %4519 + %4522 = OpFMul %float %4520 %6264 + %6292 = OpExtInst %float %1 FClamp %4522 %float_0 %float_1 + %6771 = OpFAdd %float %5162 %5192 + %4532 = OpFMul %float %4237 %6771 + %4536 = OpFMul %float %5172 %4246 + %4537 = OpFAdd %float %4532 %4536 + %4541 = OpFMul %float %5222 %4246 + %4542 = OpFAdd %float %4537 %4541 + %4546 = OpFMul %float %5232 %4264 + %4547 = OpFAdd %float %4542 %4546 + %4551 = OpFMul %float %5282 %4264 + %4552 = OpFAdd %float %4547 %4551 + %4556 = OpFMul %float %5262 %4291 + %4557 = OpFAdd %float %4552 %4556 + %4561 = OpFMul %float %5292 %4291 + %4562 = OpFAdd %float %4557 %4561 + %4566 = OpFMul %float %5202 %4267 + %4567 = OpFAdd %float %4562 %4566 + %4571 = OpFMul %float %5212 %4294 + %4572 = OpFAdd %float %4567 %4571 + %4576 = OpFMul %float %5242 %4321 + %4577 = OpFAdd %float %4572 %4576 + %4581 = OpFMul %float %5252 %4348 + %4582 = OpFAdd %float %4577 %4581 + %4584 = OpFMul %float %4582 %6264 + %6306 = OpExtInst %float %1 FClamp %4584 %float_0 %float_1 + %2544 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2544 %6278 + %2546 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2546 %6292 + %2548 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2548 %6306 + %2549 = OpLoad %v4float %xe_frag_color + %2550 = OpVectorShuffle %v3float %2549 %2549 0 1 2 + %2551 = OpExtInst %v3float %1 Sqrt %2550 + %2552 = OpLoad %v4float %xe_frag_color + %2553 = OpVectorShuffle %v4float %2552 %2551 4 5 6 3 + OpStore %xe_frag_color %2553 + %2554 = OpLoad %v4float %xe_frag_color + %2555 = OpVectorShuffle %v3float %2554 %2554 0 1 2 + %6318 = OpBitwiseAnd %v2uint %2495 %6781 + %6320 = OpCompositeExtract %uint %6318 1 + %6321 = OpIMul %uint %6320 %uint_16 + %6323 = OpCompositeExtract %uint %6318 0 + %6324 = OpIAdd %uint %6321 %6323 + OpStore %6313 %337 + %6325 = OpAccessChain %_ptr_Function_float %6313 %6324 + %6326 = OpLoad %float %6325 + %2559 = OpCompositeConstruct %v3float %6326 %6326 %6326 + %2560 = OpFAdd %v3float %2555 %2559 + %2563 = OpExtInst %v3float %1 FClamp %2560 %2561 %2562 + %2564 = OpLoad %v4float %xe_frag_color + %2565 = OpVectorShuffle %v4float %2564 %2563 4 5 6 3 + OpStore %xe_frag_color %2565 + %2567 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2567 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h new file mode 100644 index 000000000..39b69a5f1 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h @@ -0,0 +1,745 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_resample.frag +const uint8_t guest_output_ffx_cas_resample_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x40, 0x19, 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, + 0x9C, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x92, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x52, 0x65, 0x73, + 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x73, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x69, + 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x70, + 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, 0xA2, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x9C, 0x08, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xC9, 0x08, 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, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0x8F, 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, 0x90, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xC8, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xEF, 0x02, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3D, 0x20, 0x00, 0x04, 0x00, 0x9B, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x9B, 0x08, 0x00, 0x00, 0x9C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xA1, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xA1, 0x08, 0x00, 0x00, 0xA2, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xA3, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xA9, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x20, 0x00, 0x04, 0x00, 0xBA, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xC8, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xC8, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE2, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x39, 0x19, 0x00, 0x00, + 0xAD, 0x08, 0x00, 0x00, 0xAD, 0x08, 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, 0x97, 0x00, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x9E, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x9F, 0x08, 0x00, 0x00, 0x9E, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xA3, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x9F, 0x08, 0x00, 0x00, 0xA5, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xA9, 0x08, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0xAB, 0x08, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0xAC, 0x08, 0x00, 0x00, + 0xAB, 0x08, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0xB0, 0x08, 0x00, 0x00, 0xAB, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0xB2, 0x08, 0x00, 0x00, + 0xB0, 0x08, 0x00, 0x00, 0x39, 0x19, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x37, 0x00, 0x00, 0x00, 0xB3, 0x08, 0x00, 0x00, 0xB2, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xBA, 0x08, 0x00, 0x00, 0xBB, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBC, 0x08, 0x00, 0x00, 0xBB, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xBD, 0x08, 0x00, 0x00, + 0xBC, 0x08, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xDD, 0x0A, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xDD, 0x0A, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x42, 0x0C, 0x00, 0x00, + 0xAC, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x43, 0x0C, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x00, 0x42, 0x0C, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x49, 0x0C, 0x00, 0x00, + 0xB3, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x4A, 0x0C, 0x00, 0x00, 0x43, 0x0C, 0x00, 0x00, 0x49, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x86, 0x02, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4A, 0x0C, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x4F, 0x0C, 0x00, 0x00, + 0x4A, 0x0C, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x56, 0x0C, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x8E, 0x12, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x8F, 0x12, 0x00, 0x00, 0x8E, 0x12, 0x00, 0x00, 0x56, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x59, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x95, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x96, 0x12, 0x00, 0x00, 0x95, 0x12, 0x00, 0x00, + 0x59, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x9C, 0x12, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x9D, 0x12, 0x00, 0x00, 0x9C, 0x12, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x5E, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xA3, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xA4, 0x12, 0x00, 0x00, 0xA3, 0x12, 0x00, 0x00, + 0x5E, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xB1, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xB2, 0x12, 0x00, 0x00, + 0xB1, 0x12, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x67, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0xC8, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xB8, 0x12, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xB9, 0x12, 0x00, 0x00, 0xB8, 0x12, 0x00, 0x00, 0x67, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x6A, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xBF, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xC0, 0x12, 0x00, 0x00, 0xBF, 0x12, 0x00, 0x00, + 0x6A, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x6D, 0x0C, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xC6, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xC7, 0x12, 0x00, 0x00, + 0xC6, 0x12, 0x00, 0x00, 0x6D, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x73, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xD4, 0x12, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xD5, 0x12, 0x00, 0x00, 0xD4, 0x12, 0x00, 0x00, 0x73, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xDB, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xDC, 0x12, 0x00, 0x00, 0xDB, 0x12, 0x00, 0x00, + 0x76, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x79, 0x0C, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xE2, 0x12, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xE3, 0x12, 0x00, 0x00, + 0xE2, 0x12, 0x00, 0x00, 0x79, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x7C, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, 0xEF, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xE9, 0x12, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xEA, 0x12, 0x00, 0x00, 0xE9, 0x12, 0x00, 0x00, 0x7C, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, 0x8F, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x91, 0x0C, 0x00, 0x00, 0x8F, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, + 0x8F, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, + 0x8F, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x13, 0x00, 0x00, 0x91, 0x0C, 0x00, 0x00, 0x91, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, + 0x93, 0x0C, 0x00, 0x00, 0x93, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9C, 0x0C, 0x00, 0x00, 0xA4, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9E, 0x0C, 0x00, 0x00, 0xA4, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, + 0xA4, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x13, 0x00, 0x00, 0x9C, 0x0C, 0x00, 0x00, + 0x9C, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0D, 0x13, 0x00, 0x00, 0x9E, 0x0C, 0x00, 0x00, 0x9E, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, + 0xA0, 0x0C, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, 0x96, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB8, 0x0C, 0x00, 0x00, 0x96, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, + 0x96, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, + 0xB6, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x21, 0x13, 0x00, 0x00, 0xB8, 0x0C, 0x00, 0x00, 0xB8, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, + 0xBA, 0x0C, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, 0x9D, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC5, 0x0C, 0x00, 0x00, 0x9D, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, + 0x9D, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0xC3, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0xC5, 0x0C, 0x00, 0x00, 0xC5, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x13, 0x00, 0x00, + 0xC7, 0x0C, 0x00, 0x00, 0xC7, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, 0xB2, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD2, 0x0C, 0x00, 0x00, 0xB2, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, + 0xB2, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x13, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, + 0xD0, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x35, 0x13, 0x00, 0x00, 0xD2, 0x0C, 0x00, 0x00, 0xD2, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x13, 0x00, 0x00, + 0xD4, 0x0C, 0x00, 0x00, 0xD4, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, 0xB9, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDF, 0x0C, 0x00, 0x00, 0xB9, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, + 0xB9, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3C, 0x13, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, + 0xDD, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3F, 0x13, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, 0xDF, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0xE1, 0x0C, 0x00, 0x00, 0xE1, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xC0, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEC, 0x0C, 0x00, 0x00, 0xC0, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, + 0xC0, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, + 0xEA, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x49, 0x13, 0x00, 0x00, 0xEC, 0x0C, 0x00, 0x00, 0xEC, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, + 0xEE, 0x0C, 0x00, 0x00, 0xEE, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, 0xC7, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x0C, 0x00, 0x00, 0xC7, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, + 0xC7, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, + 0xF7, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x13, 0x00, 0x00, 0xF9, 0x0C, 0x00, 0x00, 0xF9, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x13, 0x00, 0x00, + 0xFB, 0x0C, 0x00, 0x00, 0xFB, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, 0xDC, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0D, 0x00, 0x00, 0xDC, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, + 0xDC, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x13, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x13, 0x00, 0x00, 0x06, 0x0D, 0x00, 0x00, 0x06, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x13, 0x00, 0x00, + 0x08, 0x0D, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x0D, 0x00, 0x00, 0xE3, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x13, 0x0D, 0x00, 0x00, 0xE3, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, + 0xE3, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, 0x11, 0x0D, 0x00, 0x00, + 0x11, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x13, 0x00, 0x00, 0x13, 0x0D, 0x00, 0x00, 0x13, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6A, 0x13, 0x00, 0x00, + 0x15, 0x0D, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, 0xD5, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2D, 0x0D, 0x00, 0x00, 0xD5, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, + 0xD5, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x78, 0x13, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, + 0x2B, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7B, 0x13, 0x00, 0x00, 0x2D, 0x0D, 0x00, 0x00, 0x2D, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7E, 0x13, 0x00, 0x00, + 0x2F, 0x0D, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x38, 0x0D, 0x00, 0x00, 0xEA, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3A, 0x0D, 0x00, 0x00, 0xEA, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3C, 0x0D, 0x00, 0x00, + 0xEA, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x82, 0x13, 0x00, 0x00, 0x38, 0x0D, 0x00, 0x00, + 0x38, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x85, 0x13, 0x00, 0x00, 0x3A, 0x0D, 0x00, 0x00, 0x3A, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, + 0x3C, 0x0D, 0x00, 0x00, 0x3C, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA6, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, + 0xA6, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAD, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x35, 0x13, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAE, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xA7, 0x13, 0x00, 0x00, 0xAD, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x03, 0x13, 0x00, 0x00, 0xD0, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD7, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD8, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xD1, 0x13, 0x00, 0x00, + 0xD7, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFB, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x0D, 0x13, 0x00, 0x00, 0xFA, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3F, 0x13, 0x00, 0x00, + 0x5D, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xFB, 0x13, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0D, 0x13, 0x00, 0x00, + 0x24, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x3F, 0x13, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2C, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x14, 0x00, 0x00, 0x2B, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4E, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, + 0x53, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4F, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0x4E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x55, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, 0x7B, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0x55, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x78, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x49, 0x13, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x79, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, 0x78, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, + 0x7B, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x79, 0x14, 0x00, 0x00, 0x7F, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, + 0xA2, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA9, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x67, 0x13, 0x00, 0x00, 0x85, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAA, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xA3, 0x14, 0x00, 0x00, 0xA9, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCC, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, + 0x5D, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCD, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x35, 0x13, 0x00, 0x00, 0xCC, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x67, 0x13, 0x00, 0x00, 0x85, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD4, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xCD, 0x14, 0x00, 0x00, + 0xD3, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xF3, 0x14, 0x00, 0x00, 0xD8, 0x13, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xF4, 0x14, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xF3, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF5, 0x14, 0x00, 0x00, 0xF4, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x00, 0x2C, 0x14, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x16, 0x15, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x35, 0x15, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x36, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x35, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x15, 0x00, 0x00, + 0x36, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x56, 0x15, 0x00, 0x00, 0xD4, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x57, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x56, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x58, 0x15, 0x00, 0x00, 0x57, 0x15, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x94, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xD8, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xAE, 0x13, 0x00, 0x00, 0x94, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x97, 0x0E, 0x00, 0x00, 0x95, 0x0E, 0x00, 0x00, + 0xF5, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x82, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x97, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAC, 0x0E, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x2C, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAD, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0xAC, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAF, 0x0E, 0x00, 0x00, + 0xAD, 0x0E, 0x00, 0x00, 0x16, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB5, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xAF, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC4, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC5, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x56, 0x14, 0x00, 0x00, + 0xC4, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC7, 0x0E, 0x00, 0x00, 0xC5, 0x0E, 0x00, 0x00, 0x37, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE8, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xC7, 0x0E, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDC, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xD4, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDD, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xAA, 0x14, 0x00, 0x00, 0xDC, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDF, 0x0E, 0x00, 0x00, 0xDD, 0x0E, 0x00, 0x00, + 0x58, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1B, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xDF, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x49, 0x16, 0x00, 0x00, + 0x82, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x4B, 0x16, 0x00, 0x00, 0x49, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4D, 0x16, 0x00, 0x00, + 0x4B, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4E, 0x16, 0x00, 0x00, 0x4D, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x16, 0x00, 0x00, + 0xB5, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x00, 0x00, 0x7C, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x16, 0x00, 0x00, + 0x7E, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x81, 0x16, 0x00, 0x00, 0x80, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xAF, 0x16, 0x00, 0x00, + 0xE8, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xB1, 0x16, 0x00, 0x00, 0xAF, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB3, 0x16, 0x00, 0x00, + 0xB1, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB4, 0x16, 0x00, 0x00, 0xB3, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE2, 0x16, 0x00, 0x00, + 0x1B, 0x16, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE4, 0x16, 0x00, 0x00, 0xE2, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE6, 0x16, 0x00, 0x00, + 0xE4, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE7, 0x16, 0x00, 0x00, 0xE6, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x00, + 0xBD, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x09, 0x0F, 0x00, 0x00, 0x4E, 0x16, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x0F, 0x00, 0x00, + 0x81, 0x16, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, 0xB4, 0x16, 0x00, 0x00, + 0x03, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x0F, 0x00, 0x00, 0xE7, 0x16, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x0F, 0x00, 0x00, + 0x4F, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0F, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x2A, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2E, 0x0F, 0x00, 0x00, 0x4F, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0F, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x00, 0x00, 0x2B, 0x0F, 0x00, 0x00, + 0x2F, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x37, 0x0F, 0x00, 0x00, 0x2A, 0x0F, 0x00, 0x00, 0x2F, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, + 0x2B, 0x0F, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x43, 0x0F, 0x00, 0x00, 0x2A, 0x0F, 0x00, 0x00, + 0x2E, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x47, 0x0F, 0x00, 0x00, 0xD8, 0x13, 0x00, 0x00, 0xAE, 0x13, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x47, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x10, 0x17, 0x00, 0x00, 0x48, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x11, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x10, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x12, 0x17, 0x00, 0x00, 0x11, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4B, 0x0F, 0x00, 0x00, + 0x30, 0x0F, 0x00, 0x00, 0x12, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, 0x2C, 0x14, 0x00, 0x00, + 0x02, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x50, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1B, 0x17, 0x00, 0x00, + 0x50, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x1C, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x1B, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x00, 0x00, + 0x1C, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x0F, 0x00, 0x00, 0x37, 0x0F, 0x00, 0x00, 0x1D, 0x17, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x57, 0x0F, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x56, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x58, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x57, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x26, 0x17, 0x00, 0x00, 0x58, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x27, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x26, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x17, 0x00, 0x00, 0x27, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, + 0x28, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x0F, 0x00, 0x00, 0xD4, 0x14, 0x00, 0x00, 0xAA, 0x14, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x31, 0x17, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x32, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x31, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x33, 0x17, 0x00, 0x00, 0x32, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x0F, 0x00, 0x00, + 0x43, 0x0F, 0x00, 0x00, 0x33, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x69, 0x0F, 0x00, 0x00, 0x09, 0x0F, 0x00, 0x00, + 0x4B, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x72, 0x0F, 0x00, 0x00, 0x12, 0x0F, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, + 0x1B, 0x0F, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x85, 0x0F, 0x00, 0x00, 0x72, 0x0F, 0x00, 0x00, + 0x84, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x87, 0x0F, 0x00, 0x00, 0x85, 0x0F, 0x00, 0x00, 0x4B, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, + 0x24, 0x0F, 0x00, 0x00, 0x63, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0F, 0x00, 0x00, 0x69, 0x0F, 0x00, 0x00, + 0x9F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x0F, 0x00, 0x00, 0xA0, 0x0F, 0x00, 0x00, 0x53, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBD, 0x0F, 0x00, 0x00, + 0xA0, 0x0F, 0x00, 0x00, 0x5B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD8, 0x0F, 0x00, 0x00, 0x85, 0x0F, 0x00, 0x00, + 0x63, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3A, 0x19, 0x00, 0x00, 0x69, 0x0F, 0x00, 0x00, 0x72, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x19, 0x00, 0x00, + 0x3A, 0x19, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3C, 0x19, 0x00, 0x00, 0x3B, 0x19, 0x00, 0x00, + 0x9F, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3C, 0x19, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x87, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0xA2, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0xBD, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x10, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0xD8, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x4A, 0x17, 0x00, 0x00, 0x0A, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x4B, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x4A, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4C, 0x17, 0x00, 0x00, 0x4B, 0x17, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x17, 0x00, 0x00, + 0x4C, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x51, 0x17, 0x00, 0x00, 0x4F, 0x17, 0x00, 0x00, 0x0A, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x17, 0x00, 0x00, + 0x51, 0x17, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x54, 0x17, 0x00, 0x00, 0x4C, 0x17, 0x00, 0x00, + 0x53, 0x17, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3D, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x1E, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, + 0x69, 0x0F, 0x00, 0x00, 0x3D, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, 0x0A, 0x13, 0x00, 0x00, + 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x19, 0x10, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x10, 0x00, 0x00, + 0x3C, 0x13, 0x00, 0x00, 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x10, 0x00, 0x00, 0x19, 0x10, 0x00, 0x00, + 0x1D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x22, 0x10, 0x00, 0x00, 0x46, 0x13, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, + 0x1E, 0x10, 0x00, 0x00, 0x22, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x78, 0x13, 0x00, 0x00, + 0x84, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2C, 0x10, 0x00, 0x00, + 0x64, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2D, 0x10, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0x2C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x31, 0x10, 0x00, 0x00, 0x82, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, + 0x2D, 0x10, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x28, 0x13, 0x00, 0x00, + 0x87, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x37, 0x10, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x10, 0x00, 0x00, + 0x32, 0x13, 0x00, 0x00, 0xA2, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3C, 0x10, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, + 0x3B, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x40, 0x10, 0x00, 0x00, 0x50, 0x13, 0x00, 0x00, 0xBD, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, + 0x3C, 0x10, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0x5A, 0x13, 0x00, 0x00, + 0xD8, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, + 0x46, 0x10, 0x00, 0x00, 0x54, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x62, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3E, 0x19, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, + 0x69, 0x0F, 0x00, 0x00, 0x3E, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, 0x0D, 0x13, 0x00, 0x00, + 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x10, 0x00, 0x00, 0x52, 0x10, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, + 0x3F, 0x13, 0x00, 0x00, 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x10, 0x00, 0x00, 0x57, 0x10, 0x00, 0x00, + 0x5B, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x60, 0x10, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x10, 0x00, 0x00, + 0x5C, 0x10, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x65, 0x10, 0x00, 0x00, 0x7B, 0x13, 0x00, 0x00, + 0x84, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x66, 0x10, 0x00, 0x00, 0x61, 0x10, 0x00, 0x00, 0x65, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, + 0x67, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6B, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, + 0x6A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6F, 0x10, 0x00, 0x00, 0x85, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x70, 0x10, 0x00, 0x00, + 0x6B, 0x10, 0x00, 0x00, 0x6F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, + 0x87, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x75, 0x10, 0x00, 0x00, 0x70, 0x10, 0x00, 0x00, 0x74, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x79, 0x10, 0x00, 0x00, + 0x35, 0x13, 0x00, 0x00, 0xA2, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7A, 0x10, 0x00, 0x00, 0x75, 0x10, 0x00, 0x00, + 0x79, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7E, 0x10, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, 0xBD, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, + 0x7A, 0x10, 0x00, 0x00, 0x7E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, + 0xD8, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x10, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x54, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x86, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3F, 0x19, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x90, 0x10, 0x00, 0x00, + 0x69, 0x0F, 0x00, 0x00, 0x3F, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x94, 0x10, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, + 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x10, 0x00, 0x00, 0x90, 0x10, 0x00, 0x00, 0x94, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x99, 0x10, 0x00, 0x00, + 0x42, 0x13, 0x00, 0x00, 0x72, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00, + 0x99, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9E, 0x10, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x9A, 0x10, 0x00, 0x00, 0x9E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, 0x7E, 0x13, 0x00, 0x00, + 0x84, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA4, 0x10, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0xA3, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x6A, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA9, 0x10, 0x00, 0x00, 0xA4, 0x10, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAD, 0x10, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAE, 0x10, 0x00, 0x00, + 0xA9, 0x10, 0x00, 0x00, 0xAD, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x2E, 0x13, 0x00, 0x00, + 0x87, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB3, 0x10, 0x00, 0x00, 0xAE, 0x10, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB7, 0x10, 0x00, 0x00, + 0x38, 0x13, 0x00, 0x00, 0xA2, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB8, 0x10, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0xB7, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBC, 0x10, 0x00, 0x00, 0x56, 0x13, 0x00, 0x00, 0xBD, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBD, 0x10, 0x00, 0x00, + 0xB8, 0x10, 0x00, 0x00, 0xBC, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC1, 0x10, 0x00, 0x00, 0x60, 0x13, 0x00, 0x00, + 0xD8, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC2, 0x10, 0x00, 0x00, 0xBD, 0x10, 0x00, 0x00, 0xC1, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC4, 0x10, 0x00, 0x00, + 0xC2, 0x10, 0x00, 0x00, 0x54, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7E, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xC4, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xD7, 0x08, 0x00, 0x00, + 0xD8, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xD8, 0x08, 0x00, 0x00, 0x62, 0x17, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xD7, 0x08, 0x00, 0x00, 0xDA, 0x08, 0x00, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDA, 0x08, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xD7, 0x08, 0x00, 0x00, 0xDC, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xDC, 0x08, 0x00, 0x00, + 0x7E, 0x17, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xDD, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0xDE, 0x08, 0x00, 0x00, 0xDD, 0x08, 0x00, 0x00, + 0xDD, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xDF, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0xDE, 0x08, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xE0, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xE1, 0x08, 0x00, 0x00, 0xE0, 0x08, 0x00, 0x00, + 0xDF, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0xE1, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xD7, 0x08, 0x00, 0x00, 0xE3, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0xE2, 0x08, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE3, 0x08, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..515bcb2abc9ee88bd7d93d6d1fdc7b0e7190b2f7 GIT binary patch literal 8892 zcmZvhe~?vm8O9GRy8@yD0_uy3uuYPQ)+&uOp<8OsPv&c>xP+S@yuMG@XR+b(=zaYke5fnup~c}Ht;MtfVS+}KtwWvc2^$-`B@rp8jC zy{p{ORW7tISyC#N!E3Za^k5wlr=_hz>1LK%9w`<&8_O;2aQjxctU=xnm(}>|NmC@hvL-KE*dH6cV ztl^>6e_8E#mE!ld{k0O)e}hbiE{8tZMmb>gi-+T(8tGF?z#A_8rxOWma*Ek24)mDo zrb^U3zs>UL&w1?pUit6o7^8h-eGbT|0XOH6e8ynTVfkQij2%rewZ@LihZnIEi3e`p zslA$eV(YxF04$E@Y>L6ndpq&sc>XMm7#{j) z{f$3aHkG~jn$A_$h&5&}h`BDnhNWwQ_4PQZ`MUCbgmKPOL(KIEMt*1VsUzNxXfvrF!IyYfw}IIF@N@lesI2#@O9!4Kc|>F@KxeW z6!yG)aQd)DFUaV_e$j_I}@!65aHbo@n0H3kkt(ftxPve-O7!J5Ov*k0EM-%5> z#qhxUX%zISm(O~OmXY_o8srm`_g>6R@mlp`o#!hCJ0PEVagX`Jz^wAWpjk2ZpeGfB z6|~pv{YLp<)JndxkM8%0)bFTp*Kf+ze_1gYT-TesCC7bMF&JYs*IJ)WTHL2xzcW|A zOEDPSe0_7OKOX8|&eiWz3bYIgTc+$FH7|&g8mP3^*>Y$1~*^7 zJk@hwwf;|X^~V&0!Oho~Qa$%Z*PqPQ|57m++S;bU~u#Gt5QApY}db?tG}oi46f_v>fGo0-6)K6nZwxA3FCS)_N9bT&$UXezNmE9 zD`%`q81G%Hm^CgFMm=V%zcA`CYkXHe*Iv{; zn6Rk(O2VSu7%z-^%-AGh)MM5?BcJO&>Yhtj)O{;qQFn^^ zQIA<;nlS1yV|NRq9<%O6`P?s}?jI8tb^nyGs5?{rsK=}^TNw42v3gM?7~6GlB|Y`!q+G3)laEX%mRMBSQ%Mcv*Bi@KjwKk6}Sd`cMg zn6bsesK=~3KtA`SsC#9?qVC{?McrogqaL%yQeo6%#+C`A9!RYI0oS=VQf~DB(ffJGp$FG>Z-!i6 z?^MXq1Fq}-lXA?Dxl!xfyCKK@9jNTIeNf#-Hw!Fe#|ZI!_JUnU*WoLcgS(=b3HisLdekru5-szj``*Feim}* z!FAm)LN2d&GUVt1*UvM5m(TgjGnsC?**_F_>JuCe*XTdxgS%$XU_D7H5MzDja-Lzj=j657B+U01 z?hSB!PueV>Jag=)rz?7_Q$P5%GV+V`Nl$CMD2$jju*M!?*5LYtV~v;OlOLkK);JI} z$mca)6@~_DW{uZ`S%Yf?jx~?WYn%~g4bD?I);K4hJZo-^ zp+nwZEArOx9?n*t^*ox+uQ`grc-O`=9_QRg6@&A>&HH+vVsQ6aC7(5OpVj1KvCmq? z;IYr6ioxCICHbt2`@F0eEcV&27(Dj*j$&~4IWM2NyU%asgT+3-Qw$#a{9ZA*=UJr} zt-Mq48uwAm+`)|vl+QdOHdGj6ir6S&^au0*^_%4Lj)24GZ>=!)ot$}N6OX+&@0P?P z=ds)>pL%k}Cd#K*#O_oKFV@aTJTPn2$>;vVb;)rpVZhT!jX9g(d zUI6a394H^$#-#tUw}2E|;rT%*>zUl@AitT$9O;MV(qV)VeRcddMI>&+9NwE(x? z0>xazT(8z!C=5Mv*88Apz^!+qV)VeRH(EZp^&S+Tbq2RyK{3}e*RJ&z3qy~b^=?xQ zxb?;t3xnxc6(0;#JZF_kPvO2VawQ|KDzq z59V>sl@CTAYt2&(&iKvym}2V4nKxB)<9!J42+SL#KCBrzV^<5~{Y6~IYlOiiXWq5) zc@B=eVZz{&Gw*u&Jh#R@7%2=cIrDCm&+|{@jTQ!%oOxs9^L!T1o12BfC1>7k@_DX_ zym7+dk~43DeBNKgeV!-`E;;iigNYaSeu^--^9DI#x?Fu3H*TP&aN^l=Xxg~26fUQs^J3z4@(7+iAZEtAi8;kbtn34=?{ymtH? zuR|EzN-q6hDl6u>BJOpUFu3I0Z>9Xo^FY{}M})y8XWnZ0e8-P_y+#;Za^^iIpXZLa z*N+Q>OU}F}$>)7k-0P#l z;F2@%Rr%m?uUCh?ChxtTuJf1Q2T#fP&5++-@6<1c#M}#<|5eKK9hN*X=a2KJQ~qMg z6Qjv*N}Gk9N%;mnM~zW@RxudH!99ofM*OBl{+w{I>tt}<=Qr{hXM=t{rSDtv!Qk_I iWwlISXEeg@al(b;abA!Q#_ylZgP8BT|CQP#+5Z519+SlY literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt new file mode 100644 index 000000000..b2368939f --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.txt @@ -0,0 +1,445 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6464 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasResampleConstants "XeCasResampleConstants" + OpMemberName %XeCasResampleConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasResampleConstants 1 "xe_cas_input_output_size_ratio" + OpMemberName %XeCasResampleConstants 2 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasResampleConstants 0 Offset 16 + OpMemberDecorate %XeCasResampleConstants 1 Offset 24 + OpMemberDecorate %XeCasResampleConstants 2 Offset 32 + OpDecorate %XeCasResampleConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %v2uint = OpTypeVector %uint 2 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %uint_1 = OpConstant %uint 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %143 = OpTypeImage %float 2D 0 0 0 1 Unknown + %144 = OpTypeSampledImage %143 +%_ptr_UniformConstant_144 = OpTypePointer UniformConstant %144 + %xe_texture = OpVariable %_ptr_UniformConstant_144 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %181 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %188 = OpConstantComposite %v2int %int_1 %int_n1 + %194 = OpConstantComposite %v2int %int_n1 %int_0 + %204 = OpConstantComposite %v2int %int_1 %int_0 + %210 = OpConstantComposite %v2int %int_n1 %int_1 + %216 = OpConstantComposite %v2int %int_0 %int_1 + %222 = OpConstantComposite %v2int %int_1 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %712 = OpConstantComposite %v2int %int_2 %int_0 + %734 = OpConstantComposite %v2int %int_0 %int_2 + %745 = OpConstantComposite %v2int %int_2 %int_1 + %751 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasResampleConstants = OpTypeStruct %v2int %v2float %float +%_ptr_PushConstant_XeCasResampleConstants = OpTypePointer PushConstant %XeCasResampleConstants + %_ = OpVariable %_ptr_PushConstant_XeCasResampleConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_0_5 = OpConstant %float 0.5 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %6457 = OpConstantComposite %v2float %float_0_5 %float_0_5 + %main = OpFunction %void None %3 + %5 = OpLabel + %2205 = OpLoad %v4float %gl_FragCoord + %2206 = OpVectorShuffle %v2float %2205 %2205 0 1 + %2207 = OpConvertFToS %v2int %2206 + %2212 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2213 = OpLoad %v2int %2212 + %2214 = OpISub %v2int %2207 %2213 + %2215 = OpBitcast %v2uint %2214 + %2218 = OpAccessChain %_ptr_PushConstant_v2float %_ %int_1 + %2219 = OpLoad %v2float %2218 + %2220 = OpBitcast %v2uint %2219 + %2224 = OpVectorTimesScalar %v2float %2219 %float_0_5 + %2226 = OpFSub %v2float %2224 %6457 + %2227 = OpBitcast %v2uint %2226 + %2235 = OpAccessChain %_ptr_PushConstant_float %_ %int_2 + %2236 = OpLoad %float %2235 + %2237 = OpBitcast %uint %2236 + OpBranch %2781 + %2781 = OpLabel + %3132 = OpConvertUToF %v2float %2215 + %3138 = OpBitcast %v2float %2220 + %3139 = OpFMul %v2float %3132 %3138 + %3145 = OpBitcast %v2float %2227 + %3146 = OpFAdd %v2float %3139 %3145 + %3148 = OpExtInst %v2float %1 Floor %3146 + %3151 = OpFSub %v2float %3146 %3148 + %3153 = OpConvertFToS %v2int %3148 + %3158 = OpIAdd %v2int %3153 %181 + %4748 = OpLoad %144 %xe_texture + %4750 = OpImage %143 %4748 + %4751 = OpImageFetch %v4float %4750 %3158 Lod %int_0 + %3161 = OpIAdd %v2int %3153 %194 + %4757 = OpImage %143 %4748 + %4758 = OpImageFetch %v4float %4757 %3161 Lod %int_0 + %4764 = OpImage %143 %4748 + %4765 = OpImageFetch %v4float %4764 %3153 Lod %int_0 + %3166 = OpIAdd %v2int %3153 %188 + %4771 = OpImage %143 %4748 + %4772 = OpImageFetch %v4float %4771 %3166 Lod %int_0 + %3172 = OpIAdd %v2int %3153 %204 + %4785 = OpImage %143 %4748 + %4786 = OpImageFetch %v4float %4785 %3172 Lod %int_0 + %3175 = OpIAdd %v2int %3153 %712 + %4792 = OpImage %143 %4748 + %4793 = OpImageFetch %v4float %4792 %3175 Lod %int_0 + %3178 = OpIAdd %v2int %3153 %210 + %4799 = OpImage %143 %4748 + %4800 = OpImageFetch %v4float %4799 %3178 Lod %int_0 + %3181 = OpIAdd %v2int %3153 %216 + %4806 = OpImage %143 %4748 + %4807 = OpImageFetch %v4float %4806 %3181 Lod %int_0 + %3187 = OpIAdd %v2int %3153 %734 + %4820 = OpImage %143 %4748 + %4821 = OpImageFetch %v4float %4820 %3187 Lod %int_0 + %3190 = OpIAdd %v2int %3153 %222 + %4827 = OpImage %143 %4748 + %4828 = OpImageFetch %v4float %4827 %3190 Lod %int_0 + %3193 = OpIAdd %v2int %3153 %745 + %4834 = OpImage %143 %4748 + %4835 = OpImageFetch %v4float %4834 %3193 Lod %int_0 + %3196 = OpIAdd %v2int %3153 %751 + %4841 = OpImage %143 %4748 + %4842 = OpImageFetch %v4float %4841 %3196 Lod %int_0 + %3215 = OpCompositeExtract %float %4751 0 + %3217 = OpCompositeExtract %float %4751 1 + %3219 = OpCompositeExtract %float %4751 2 + %4864 = OpFMul %float %3215 %3215 + %4867 = OpFMul %float %3217 %3217 + %4870 = OpFMul %float %3219 %3219 + %3228 = OpCompositeExtract %float %4772 0 + %3230 = OpCompositeExtract %float %4772 1 + %3232 = OpCompositeExtract %float %4772 2 + %4874 = OpFMul %float %3228 %3228 + %4877 = OpFMul %float %3230 %3230 + %4880 = OpFMul %float %3232 %3232 + %3254 = OpCompositeExtract %float %4758 0 + %3256 = OpCompositeExtract %float %4758 1 + %3258 = OpCompositeExtract %float %4758 2 + %4894 = OpFMul %float %3254 %3254 + %4897 = OpFMul %float %3256 %3256 + %4900 = OpFMul %float %3258 %3258 + %3267 = OpCompositeExtract %float %4765 0 + %3269 = OpCompositeExtract %float %4765 1 + %3271 = OpCompositeExtract %float %4765 2 + %4904 = OpFMul %float %3267 %3267 + %4907 = OpFMul %float %3269 %3269 + %4910 = OpFMul %float %3271 %3271 + %3280 = OpCompositeExtract %float %4786 0 + %3282 = OpCompositeExtract %float %4786 1 + %3284 = OpCompositeExtract %float %4786 2 + %4914 = OpFMul %float %3280 %3280 + %4917 = OpFMul %float %3282 %3282 + %4920 = OpFMul %float %3284 %3284 + %3293 = OpCompositeExtract %float %4793 0 + %3295 = OpCompositeExtract %float %4793 1 + %3297 = OpCompositeExtract %float %4793 2 + %4924 = OpFMul %float %3293 %3293 + %4927 = OpFMul %float %3295 %3295 + %4930 = OpFMul %float %3297 %3297 + %3306 = OpCompositeExtract %float %4800 0 + %3308 = OpCompositeExtract %float %4800 1 + %3310 = OpCompositeExtract %float %4800 2 + %4934 = OpFMul %float %3306 %3306 + %4937 = OpFMul %float %3308 %3308 + %4940 = OpFMul %float %3310 %3310 + %3319 = OpCompositeExtract %float %4807 0 + %3321 = OpCompositeExtract %float %4807 1 + %3323 = OpCompositeExtract %float %4807 2 + %4944 = OpFMul %float %3319 %3319 + %4947 = OpFMul %float %3321 %3321 + %4950 = OpFMul %float %3323 %3323 + %3332 = OpCompositeExtract %float %4828 0 + %3334 = OpCompositeExtract %float %4828 1 + %3336 = OpCompositeExtract %float %4828 2 + %4954 = OpFMul %float %3332 %3332 + %4957 = OpFMul %float %3334 %3334 + %4960 = OpFMul %float %3336 %3336 + %3345 = OpCompositeExtract %float %4835 0 + %3347 = OpCompositeExtract %float %4835 1 + %3349 = OpCompositeExtract %float %4835 2 + %4964 = OpFMul %float %3345 %3345 + %4967 = OpFMul %float %3347 %3347 + %4970 = OpFMul %float %3349 %3349 + %3371 = OpCompositeExtract %float %4821 0 + %3373 = OpCompositeExtract %float %4821 1 + %3375 = OpCompositeExtract %float %4821 2 + %4984 = OpFMul %float %3371 %3371 + %4987 = OpFMul %float %3373 %3373 + %4990 = OpFMul %float %3375 %3375 + %3384 = OpCompositeExtract %float %4842 0 + %3386 = OpCompositeExtract %float %4842 1 + %3388 = OpCompositeExtract %float %4842 2 + %4994 = OpFMul %float %3384 %3384 + %4997 = OpFMul %float %3386 %3386 + %5000 = OpFMul %float %3388 %3388 + %5030 = OpExtInst %float %1 FMin %4897 %4907 + %5031 = OpExtInst %float %1 FMin %4867 %5030 + %5037 = OpExtInst %float %1 FMin %4917 %4947 + %5038 = OpExtInst %float %1 FMin %5031 %5037 + %5072 = OpExtInst %float %1 FMax %4897 %4907 + %5073 = OpExtInst %float %1 FMax %4867 %5072 + %5079 = OpExtInst %float %1 FMax %4917 %4947 + %5080 = OpExtInst %float %1 FMax %5073 %5079 + %5114 = OpExtInst %float %1 FMin %4907 %4917 + %5115 = OpExtInst %float %1 FMin %4877 %5114 + %5121 = OpExtInst %float %1 FMin %4927 %4957 + %5122 = OpExtInst %float %1 FMin %5115 %5121 + %5156 = OpExtInst %float %1 FMax %4907 %4917 + %5157 = OpExtInst %float %1 FMax %4877 %5156 + %5163 = OpExtInst %float %1 FMax %4927 %4957 + %5164 = OpExtInst %float %1 FMax %5157 %5163 + %5198 = OpExtInst %float %1 FMin %4937 %4947 + %5199 = OpExtInst %float %1 FMin %4907 %5198 + %5205 = OpExtInst %float %1 FMin %4957 %4987 + %5206 = OpExtInst %float %1 FMin %5199 %5205 + %5240 = OpExtInst %float %1 FMax %4937 %4947 + %5241 = OpExtInst %float %1 FMax %4907 %5240 + %5247 = OpExtInst %float %1 FMax %4957 %4987 + %5248 = OpExtInst %float %1 FMax %5241 %5247 + %5282 = OpExtInst %float %1 FMin %4947 %4957 + %5283 = OpExtInst %float %1 FMin %4917 %5282 + %5289 = OpExtInst %float %1 FMin %4967 %4997 + %5290 = OpExtInst %float %1 FMin %5283 %5289 + %5324 = OpExtInst %float %1 FMax %4947 %4957 + %5325 = OpExtInst %float %1 FMax %4917 %5324 + %5331 = OpExtInst %float %1 FMax %4967 %4997 + %5332 = OpExtInst %float %1 FMax %5325 %5331 + %5363 = OpBitcast %uint %5080 + %5364 = OpISub %uint %uint_2129690299 %5363 + %5365 = OpBitcast %float %5364 + %5396 = OpBitcast %uint %5164 + %5397 = OpISub %uint %uint_2129690299 %5396 + %5398 = OpBitcast %float %5397 + %5429 = OpBitcast %uint %5248 + %5430 = OpISub %uint %uint_2129690299 %5429 + %5431 = OpBitcast %float %5430 + %5462 = OpBitcast %uint %5332 + %5463 = OpISub %uint %uint_2129690299 %5462 + %5464 = OpBitcast %float %5463 + %3732 = OpFSub %float %float_1 %5080 + %3733 = OpExtInst %float %1 FMin %5038 %3732 + %3735 = OpFMul %float %3733 %5365 + %5506 = OpExtInst %float %1 FClamp %3735 %float_0 %float_1 + %3756 = OpFSub %float %float_1 %5164 + %3757 = OpExtInst %float %1 FMin %5122 %3756 + %3759 = OpFMul %float %3757 %5398 + %5557 = OpExtInst %float %1 FClamp %3759 %float_0 %float_1 + %3780 = OpFSub %float %float_1 %5248 + %3781 = OpExtInst %float %1 FMin %5206 %3780 + %3783 = OpFMul %float %3781 %5431 + %5608 = OpExtInst %float %1 FClamp %3783 %float_0 %float_1 + %3804 = OpFSub %float %float_1 %5332 + %3805 = OpExtInst %float %1 FMin %5290 %3804 + %3807 = OpFMul %float %3805 %5464 + %5659 = OpExtInst %float %1 FClamp %3807 %float_0 %float_1 + %5705 = OpBitcast %uint %5506 + %5707 = OpShiftRightLogical %uint %5705 %uint_1 + %5709 = OpIAdd %uint %5707 %uint_532432441 + %5710 = OpBitcast %float %5709 + %5756 = OpBitcast %uint %5557 + %5758 = OpShiftRightLogical %uint %5756 %uint_1 + %5760 = OpIAdd %uint %5758 %uint_532432441 + %5761 = OpBitcast %float %5760 + %5807 = OpBitcast %uint %5608 + %5809 = OpShiftRightLogical %uint %5807 %uint_1 + %5811 = OpIAdd %uint %5809 %uint_532432441 + %5812 = OpBitcast %float %5811 + %5858 = OpBitcast %uint %5659 + %5860 = OpShiftRightLogical %uint %5858 %uint_1 + %5862 = OpIAdd %uint %5860 %uint_532432441 + %5863 = OpBitcast %float %5862 + %3843 = OpBitcast %float %2237 + %3849 = OpFMul %float %5710 %3843 + %3858 = OpFMul %float %5761 %3843 + %3867 = OpFMul %float %5812 %3843 + %3876 = OpFMul %float %5863 %3843 + %3882 = OpCompositeExtract %float %3151 0 + %3883 = OpFSub %float %float_1 %3882 + %3886 = OpCompositeExtract %float %3151 1 + %3887 = OpFSub %float %float_1 %3886 + %3888 = OpFMul %float %3883 %3887 + %3895 = OpFMul %float %3882 %3887 + %3902 = OpFMul %float %3883 %3886 + %3907 = OpFMul %float %3882 %3886 + %3911 = OpFSub %float %5080 %5038 + %3912 = OpFAdd %float %float_0_03125 %3911 + %5904 = OpBitcast %uint %3912 + %5905 = OpISub %uint %uint_2129690299 %5904 + %5906 = OpBitcast %float %5905 + %3915 = OpFMul %float %3888 %5906 + %3919 = OpFSub %float %5164 %5122 + %3920 = OpFAdd %float %float_0_03125 %3919 + %5915 = OpBitcast %uint %3920 + %5916 = OpISub %uint %uint_2129690299 %5915 + %5917 = OpBitcast %float %5916 + %3923 = OpFMul %float %3895 %5917 + %3927 = OpFSub %float %5248 %5206 + %3928 = OpFAdd %float %float_0_03125 %3927 + %5926 = OpBitcast %uint %3928 + %5927 = OpISub %uint %uint_2129690299 %5926 + %5928 = OpBitcast %float %5927 + %3931 = OpFMul %float %3902 %5928 + %3935 = OpFSub %float %5332 %5290 + %3936 = OpFAdd %float %float_0_03125 %3935 + %5937 = OpBitcast %uint %3936 + %5938 = OpISub %uint %uint_2129690299 %5937 + %5939 = OpBitcast %float %5938 + %3939 = OpFMul %float %3907 %5939 + %3945 = OpFMul %float %3849 %3915 + %3954 = OpFMul %float %3858 %3923 + %3972 = OpFMul %float %3867 %3931 + %3973 = OpFAdd %float %3954 %3972 + %3975 = OpFAdd %float %3973 %3915 + %3999 = OpFMul %float %3876 %3939 + %4000 = OpFAdd %float %3945 %3999 + %4002 = OpFAdd %float %4000 %3923 + %4029 = OpFAdd %float %4000 %3931 + %4056 = OpFAdd %float %3973 %3939 + %6458 = OpFAdd %float %3945 %3954 + %6459 = OpFAdd %float %6458 %3972 + %6460 = OpFAdd %float %6459 %3999 + %4098 = OpFMul %float %float_2 %6460 + %4100 = OpFAdd %float %4098 %3975 + %4102 = OpFAdd %float %4100 %4002 + %4104 = OpFAdd %float %4102 %4029 + %4106 = OpFAdd %float %4104 %4056 + %5962 = OpBitcast %uint %4106 + %5963 = OpISub %uint %uint_2129764351 %5962 + %5964 = OpBitcast %float %5963 + %5967 = OpFNegate %float %5964 + %5969 = OpFMul %float %5967 %4106 + %5971 = OpFAdd %float %5969 %float_2 + %5972 = OpFMul %float %5964 %5971 + %6461 = OpFAdd %float %4864 %4894 + %4116 = OpFMul %float %3945 %6461 + %4120 = OpFMul %float %4874 %3954 + %4121 = OpFAdd %float %4116 %4120 + %4125 = OpFMul %float %4924 %3954 + %4126 = OpFAdd %float %4121 %4125 + %4130 = OpFMul %float %4934 %3972 + %4131 = OpFAdd %float %4126 %4130 + %4135 = OpFMul %float %4984 %3972 + %4136 = OpFAdd %float %4131 %4135 + %4140 = OpFMul %float %4964 %3999 + %4141 = OpFAdd %float %4136 %4140 + %4145 = OpFMul %float %4994 %3999 + %4146 = OpFAdd %float %4141 %4145 + %4150 = OpFMul %float %4904 %3975 + %4151 = OpFAdd %float %4146 %4150 + %4155 = OpFMul %float %4914 %4002 + %4156 = OpFAdd %float %4151 %4155 + %4160 = OpFMul %float %4944 %4029 + %4161 = OpFAdd %float %4156 %4160 + %4165 = OpFMul %float %4954 %4056 + %4166 = OpFAdd %float %4161 %4165 + %4168 = OpFMul %float %4166 %5972 + %5986 = OpExtInst %float %1 FClamp %4168 %float_0 %float_1 + %6462 = OpFAdd %float %4867 %4897 + %4178 = OpFMul %float %3945 %6462 + %4182 = OpFMul %float %4877 %3954 + %4183 = OpFAdd %float %4178 %4182 + %4187 = OpFMul %float %4927 %3954 + %4188 = OpFAdd %float %4183 %4187 + %4192 = OpFMul %float %4937 %3972 + %4193 = OpFAdd %float %4188 %4192 + %4197 = OpFMul %float %4987 %3972 + %4198 = OpFAdd %float %4193 %4197 + %4202 = OpFMul %float %4967 %3999 + %4203 = OpFAdd %float %4198 %4202 + %4207 = OpFMul %float %4997 %3999 + %4208 = OpFAdd %float %4203 %4207 + %4212 = OpFMul %float %4907 %3975 + %4213 = OpFAdd %float %4208 %4212 + %4217 = OpFMul %float %4917 %4002 + %4218 = OpFAdd %float %4213 %4217 + %4222 = OpFMul %float %4947 %4029 + %4223 = OpFAdd %float %4218 %4222 + %4227 = OpFMul %float %4957 %4056 + %4228 = OpFAdd %float %4223 %4227 + %4230 = OpFMul %float %4228 %5972 + %6000 = OpExtInst %float %1 FClamp %4230 %float_0 %float_1 + %6463 = OpFAdd %float %4870 %4900 + %4240 = OpFMul %float %3945 %6463 + %4244 = OpFMul %float %4880 %3954 + %4245 = OpFAdd %float %4240 %4244 + %4249 = OpFMul %float %4930 %3954 + %4250 = OpFAdd %float %4245 %4249 + %4254 = OpFMul %float %4940 %3972 + %4255 = OpFAdd %float %4250 %4254 + %4259 = OpFMul %float %4990 %3972 + %4260 = OpFAdd %float %4255 %4259 + %4264 = OpFMul %float %4970 %3999 + %4265 = OpFAdd %float %4260 %4264 + %4269 = OpFMul %float %5000 %3999 + %4270 = OpFAdd %float %4265 %4269 + %4274 = OpFMul %float %4910 %3975 + %4275 = OpFAdd %float %4270 %4274 + %4279 = OpFMul %float %4920 %4002 + %4280 = OpFAdd %float %4275 %4279 + %4284 = OpFMul %float %4950 %4029 + %4285 = OpFAdd %float %4280 %4284 + %4289 = OpFMul %float %4960 %4056 + %4290 = OpFAdd %float %4285 %4289 + %4292 = OpFMul %float %4290 %5972 + %6014 = OpExtInst %float %1 FClamp %4292 %float_0 %float_1 + %2264 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2264 %5986 + %2266 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2266 %6000 + %2268 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2268 %6014 + %2269 = OpLoad %v4float %xe_frag_color + %2270 = OpVectorShuffle %v3float %2269 %2269 0 1 2 + %2271 = OpExtInst %v3float %1 Sqrt %2270 + %2272 = OpLoad %v4float %xe_frag_color + %2273 = OpVectorShuffle %v4float %2272 %2271 4 5 6 3 + OpStore %xe_frag_color %2273 + %2275 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2275 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h new file mode 100644 index 000000000..9e01621fa --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h @@ -0,0 +1,1212 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_sharpen_dither.frag +const uint8_t guest_output_ffx_cas_sharpen_dither_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x6C, 0x1A, 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, + 0xB4, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x53, 0x68, 0x61, + 0x72, 0x70, 0x65, 0x6E, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, + 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, + 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, + 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, + 0xBA, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, + 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xAB, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xB4, 0x09, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xB8, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0xB8, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xD0, 0x09, 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, + 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x1C, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, + 0xDE, 0xDD, 0xDD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0xCC, 0xCB, 0xCB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x9F, 0x9E, 0x1E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, + 0xB2, 0xB1, 0xB1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5A, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0xA0, 0x9F, 0x9F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0xD2, 0xD1, 0xD1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5D, 0x00, 0x00, 0x00, 0x9B, 0x9A, 0x1A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x95, 0x94, 0x94, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x92, 0x91, 0x91, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xBE, 0xBD, 0xBD, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x8F, 0x8E, 0x0E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x63, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xE5, 0xE4, 0xE4, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0x8A, 0x89, 0x89, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0xA3, 0xA2, 0x22, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, + 0xFD, 0xFC, 0xFC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0xD1, 0xD0, 0xD0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6C, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x00, 0x00, 0x00, 0xB7, 0xB6, 0x36, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, + 0xBB, 0xBA, 0x3A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xAC, 0xAB, 0xAB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x90, 0x8F, 0x8F, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x9D, 0x9C, 0x9C, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x75, 0x00, 0x00, 0x00, 0xE6, 0xE5, 0xE5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xA1, 0xA0, 0x20, 0xB8, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0xCF, 0xCE, 0x4E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, + 0xF0, 0xEF, 0xEF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7B, 0x00, 0x00, 0x00, 0x9D, 0x9C, 0x9C, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x82, 0x81, 0x81, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x9A, 0x99, 0x99, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x81, 0x00, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0xF4, 0xF3, 0xF3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, + 0xE8, 0xE7, 0xE7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0xE3, 0xE2, 0x62, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0xEB, 0xEA, 0x6A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, + 0xA9, 0xA8, 0x28, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x87, 0x00, 0x00, 0x00, 0xF3, 0xF2, 0x72, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xC8, 0xC7, 0xC7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, + 0xAB, 0xAA, 0x2A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, + 0xC0, 0xBF, 0xBF, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8D, 0x00, 0x00, 0x00, 0xEC, 0xEB, 0xEB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0xDF, 0xDE, 0x5E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xDF, 0xDE, 0x5E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0xED, 0xEC, 0xEC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x8C, 0x8B, 0x8B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x99, 0x98, 0x18, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0xBA, 0xB9, 0xB9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x9B, 0x9A, 0x1A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0xD2, 0xD1, 0xD1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, + 0x86, 0x85, 0x85, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0xD9, 0xD8, 0x58, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0xD0, 0xCF, 0xCF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9C, 0x00, 0x00, 0x00, 0xAB, 0xAA, 0x2A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x9F, 0x00, 0x00, 0x00, 0xD8, 0xD7, 0xD7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0xB4, 0xB3, 0xB3, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, + 0xF3, 0xF2, 0x72, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA2, 0x00, 0x00, 0x00, 0xAF, 0xAE, 0x2E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, + 0xBE, 0xBD, 0xBD, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x00, 0xF8, 0xF7, 0xF7, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA8, 0x00, 0x00, 0x00, 0xAA, 0xA9, 0xA9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xFC, 0xFB, 0xFB, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, + 0xDA, 0xD9, 0xD9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAB, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, + 0xF4, 0xF3, 0xF3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x9E, 0x9D, 0x9D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, + 0xB4, 0xB3, 0xB3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB1, 0x00, 0x00, 0x00, 0xD6, 0xD5, 0xD5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xF1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, + 0xBF, 0xBE, 0x3E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB4, 0x00, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0xEE, 0xED, 0xED, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, + 0x96, 0x95, 0x95, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB7, 0x00, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0xD1, 0xD0, 0xD0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x9A, 0x99, 0x99, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x91, 0x90, 0x90, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBD, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x7E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, + 0xFE, 0xFD, 0xFD, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x8B, 0x8A, 0x0A, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, + 0xA4, 0xA3, 0xA3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC3, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, + 0x81, 0x80, 0x00, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0xE6, 0xE5, 0xE5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC9, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x9C, 0x9B, 0x9B, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, + 0xCB, 0xCA, 0x4A, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xB0, 0xAF, 0xAF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x8D, 0x8C, 0x8C, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, + 0xC2, 0xC1, 0xC1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCF, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0xCB, 0xCA, 0x4A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0xAC, 0xAB, 0xAB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0xCD, 0xCC, 0xCC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD3, 0x00, 0x00, 0x00, 0xFB, 0xFA, 0x7A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, + 0xF5, 0xF4, 0xF4, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD5, 0x00, 0x00, 0x00, 0xCA, 0xC9, 0xC9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD6, 0x00, 0x00, 0x00, 0x88, 0x87, 0x87, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, + 0xB3, 0xB2, 0x32, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD8, 0x00, 0x00, 0x00, 0xDC, 0xDB, 0xDB, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0x84, 0x83, 0x83, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, + 0xDD, 0xDC, 0xDC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDB, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0xF9, 0xF8, 0x78, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, + 0xA3, 0xA2, 0x22, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xDA, 0xD9, 0xD9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0xDB, 0xDA, 0x5A, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0xE2, 0xE1, 0xE1, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE1, 0x00, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xE7, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0xCF, 0xCE, 0x4E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE4, 0x00, 0x00, 0x00, 0xEA, 0xE9, 0xE9, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x32, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, + 0x82, 0x81, 0x81, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE7, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0xB9, 0xB8, 0x38, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, + 0xC6, 0xC5, 0xC5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xAD, 0xAC, 0xAC, 0x39, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0xAF, 0xAE, 0x2E, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xED, 0x00, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x98, 0x97, 0x97, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, + 0xED, 0xEC, 0xEC, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0xE5, 0xE4, 0xE4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0xC9, 0xC8, 0x48, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, + 0xC4, 0xC3, 0xC3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF3, 0x00, 0x00, 0x00, 0x96, 0x95, 0x95, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0xB1, 0xB0, 0xB0, 0x38, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF6, 0x00, 0x00, 0x00, 0xB8, 0xB7, 0xB7, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x93, 0x92, 0x12, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0xF1, 0xF0, 0xF0, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF9, 0x00, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, + 0xFF, 0xFE, 0x7E, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0xAE, 0xAD, 0xAD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xC7, 0xC6, 0x46, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xB2, 0xB1, 0xB1, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xC0, 0xBF, 0xBF, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xE3, 0xE2, 0x62, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x8F, 0x8E, 0x0E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x94, 0x93, 0x93, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x93, 0x92, 0x12, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, + 0xEE, 0xED, 0xED, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0xE2, 0xE1, 0xE1, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x98, 0x97, 0x97, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, + 0xC3, 0xC2, 0x42, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0B, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0xF1, 0xF0, 0xF0, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, + 0xA0, 0x9F, 0x9F, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x01, 0x00, 0x00, 0xF0, 0xEF, 0xEF, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0xC1, 0xC0, 0xC0, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0xFC, 0xFB, 0xFB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x11, 0x01, 0x00, 0x00, 0xE4, 0xE3, 0xE3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0xBB, 0xBA, 0x3A, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, + 0xCC, 0xCB, 0xCB, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xE0, 0xDF, 0xDF, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, + 0xD9, 0xD8, 0x58, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x01, 0x00, 0x00, 0x8A, 0x89, 0x89, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xBF, 0xBE, 0x3E, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0xD6, 0xD5, 0xD5, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1A, 0x01, 0x00, 0x00, 0xA5, 0xA4, 0xA4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, 0xFD, 0xFC, 0xFC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, + 0xEC, 0xEB, 0xEB, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x00, 0x00, 0xB5, 0xB4, 0xB4, 0xB9, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, + 0xB7, 0xB6, 0x36, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x86, 0x85, 0x85, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0xCE, 0xCD, 0xCD, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, + 0xC1, 0xC0, 0xC0, 0xB7, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x23, 0x01, 0x00, 0x00, 0xA8, 0xA7, 0xA7, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0xD3, 0xD2, 0x52, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, + 0xEB, 0xEA, 0x6A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x26, 0x01, 0x00, 0x00, 0xBC, 0xBB, 0xBB, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x9F, 0x9E, 0x1E, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, + 0xB1, 0xB0, 0xB0, 0xB8, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0xEF, 0xEE, 0x6E, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, + 0xB8, 0xB7, 0xB7, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2D, 0x01, 0x00, 0x00, 0xC6, 0xC5, 0xC5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, + 0xD7, 0xD6, 0x56, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2F, 0x01, 0x00, 0x00, 0xA4, 0xA3, 0xA3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x85, 0x84, 0x84, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, + 0xC8, 0xC7, 0xC7, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x32, 0x01, 0x00, 0x00, 0x94, 0x93, 0x93, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x33, 0x01, 0x00, 0x00, 0xBD, 0xBC, 0xBC, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, + 0xCD, 0xCC, 0xCC, 0xB9, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x35, 0x01, 0x00, 0x00, 0xFA, 0xF9, 0xF9, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0xB6, 0xB5, 0xB5, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, + 0x92, 0x91, 0x91, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x38, 0x01, 0x00, 0x00, 0xD4, 0xD3, 0xD3, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0xE7, 0xE6, 0x66, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, + 0x99, 0x98, 0x18, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3B, 0x01, 0x00, 0x00, 0x8E, 0x8D, 0x8D, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x00, 0xE1, 0xE0, 0x60, 0xB8, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, + 0x95, 0x94, 0x94, 0x39, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x01, 0x00, 0x00, 0xDE, 0xDD, 0xDD, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3F, 0x01, 0x00, 0x00, 0xA6, 0xA5, 0xA5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, + 0x87, 0x86, 0x06, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x41, 0x01, 0x00, 0x00, 0xA9, 0xA8, 0x28, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0xF6, 0xF5, 0xF5, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, + 0xDB, 0xDA, 0x5A, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x44, 0x01, 0x00, 0x00, 0xA7, 0xA6, 0x26, 0x3A, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x81, 0x80, 0x00, 0x37, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, + 0xFA, 0xF9, 0xF9, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x47, 0x01, 0x00, 0x00, 0xE9, 0xE8, 0x68, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0xC5, 0xC4, 0xC4, 0x39, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, + 0xE4, 0xE3, 0xE3, 0xBA, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4A, 0x01, 0x00, 0x00, 0xD5, 0xD4, 0xD4, 0xB9, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4B, 0x01, 0x00, 0x00, 0xA2, 0xA1, 0xA1, 0xBA, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, + 0xE0, 0xDF, 0xDF, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4D, 0x01, 0x00, 0x00, 0xF7, 0xF6, 0x76, 0xBA, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, 0xD7, 0xD6, 0x56, 0x3A, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, + 0xF2, 0xF1, 0xF1, 0x3A, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0xF5, 0xF4, 0xF4, 0x39, 0x2C, 0x00, 0x03, 0x01, + 0x50, 0x00, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x5B, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, + 0x5E, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0x6A, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x6D, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0x82, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, + 0x8B, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, + 0x8E, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x9C, 0x00, 0x00, 0x00, + 0x9D, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0xAF, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, + 0xB2, 0x00, 0x00, 0x00, 0xB3, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, + 0xB5, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC4, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, + 0xCA, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0xCD, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xD3, 0x00, 0x00, 0x00, 0xD4, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, + 0xD6, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, + 0xD9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, + 0xDC, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, + 0xE2, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, + 0xE5, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0xE8, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, + 0xEB, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xF1, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, + 0xF4, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, + 0xF7, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, + 0x06, 0x01, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x09, 0x01, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, + 0x0C, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0x12, 0x01, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x15, 0x01, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, + 0x18, 0x01, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, + 0x1B, 0x01, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x1D, 0x01, 0x00, 0x00, + 0x1E, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x21, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0x27, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x29, 0x01, 0x00, 0x00, + 0x2A, 0x01, 0x00, 0x00, 0x2B, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x2D, 0x01, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0x2F, 0x01, 0x00, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, + 0x33, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0x37, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, + 0x39, 0x01, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x00, 0x3B, 0x01, 0x00, 0x00, + 0x3C, 0x01, 0x00, 0x00, 0x3D, 0x01, 0x00, 0x00, 0x3E, 0x01, 0x00, 0x00, + 0x3F, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, + 0x42, 0x01, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x45, 0x01, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x4A, 0x01, 0x00, 0x00, + 0x4B, 0x01, 0x00, 0x00, 0x4C, 0x01, 0x00, 0x00, 0x4D, 0x01, 0x00, 0x00, + 0x4E, 0x01, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x5B, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA1, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0x09, 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, 0xA9, 0x01, 0x00, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xAA, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xA9, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xAA, 0x01, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xCE, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0xC7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xF7, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0xD4, 0x03, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0xD4, 0x01, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, + 0x20, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB3, 0x09, 0x00, 0x00, + 0xB4, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xB9, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB8, 0x09, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB9, 0x09, 0x00, 0x00, + 0xBA, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xBB, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xC1, 0x09, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xC4, 0x09, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xCF, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0xCF, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xDE, 0x09, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xF0, 0x09, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x06, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xF1, 0x09, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6B, 0x1A, 0x00, 0x00, + 0x4B, 0x00, 0x00, 0x00, 0x4B, 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, 0x5B, 0x01, 0x00, 0x00, 0x98, 0x18, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xB5, 0x09, 0x00, 0x00, 0xB4, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0xB6, 0x09, 0x00, 0x00, 0xB5, 0x09, 0x00, 0x00, + 0xB5, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0xB7, 0x09, 0x00, 0x00, + 0xB6, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xBB, 0x09, 0x00, 0x00, + 0xBC, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0xBD, 0x09, 0x00, 0x00, + 0xBC, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0xBE, 0x09, 0x00, 0x00, 0xB7, 0x09, 0x00, 0x00, 0xBD, 0x09, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, + 0xBE, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0xC2, 0x09, 0x00, 0x00, 0xC1, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC4, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0xBA, 0x09, 0x00, 0x00, + 0xD4, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC6, 0x09, 0x00, 0x00, 0xC5, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x09, 0x00, 0x00, 0xC6, 0x09, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0xF0, 0x0B, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0xF0, 0x0B, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x9E, 0x03, 0x00, 0x00, + 0x4F, 0x0D, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x52, 0x0D, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x53, 0x0D, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x54, 0x0D, 0x00, 0x00, + 0x52, 0x0D, 0x00, 0x00, 0x53, 0x0D, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x55, 0x0D, 0x00, 0x00, 0x54, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x56, 0x0D, 0x00, 0x00, + 0x4F, 0x0D, 0x00, 0x00, 0x55, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x59, 0x0D, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5A, 0x0D, 0x00, 0x00, 0xC2, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5B, 0x0D, 0x00, 0x00, + 0x59, 0x0D, 0x00, 0x00, 0x5A, 0x0D, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x5C, 0x0D, 0x00, 0x00, 0x5B, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x9E, 0x03, 0x00, 0x00, 0x5D, 0x0D, 0x00, 0x00, + 0x56, 0x0D, 0x00, 0x00, 0x5C, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x5F, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x5D, 0x0D, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x9E, 0x03, 0x00, 0x00, 0x62, 0x0D, 0x00, 0x00, 0x5D, 0x0D, 0x00, 0x00, + 0x5F, 0x0D, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x64, 0x0D, 0x00, 0x00, 0x5F, 0x0D, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x69, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, + 0xCE, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xA9, 0x01, 0x00, 0x00, + 0x9F, 0x13, 0x00, 0x00, 0xAB, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xA1, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xA2, 0x13, 0x00, 0x00, + 0xA1, 0x13, 0x00, 0x00, 0x69, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x6C, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, 0xDB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xA8, 0x13, 0x00, 0x00, + 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xA9, 0x13, 0x00, 0x00, 0xA8, 0x13, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xAF, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0xAF, 0x13, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x71, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, 0xD5, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xB6, 0x13, 0x00, 0x00, + 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xB7, 0x13, 0x00, 0x00, 0xB6, 0x13, 0x00, 0x00, 0x71, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x77, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, + 0xE5, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xC4, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xC5, 0x13, 0x00, 0x00, 0xC4, 0x13, 0x00, 0x00, + 0x77, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7A, 0x0D, 0x00, 0x00, + 0x64, 0x0D, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xCB, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xCC, 0x13, 0x00, 0x00, + 0xCB, 0x13, 0x00, 0x00, 0x7A, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x7D, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, 0xEB, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xD2, 0x13, 0x00, 0x00, + 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xD3, 0x13, 0x00, 0x00, 0xD2, 0x13, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x80, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, + 0xF1, 0x01, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xD9, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xDA, 0x13, 0x00, 0x00, 0xD9, 0x13, 0x00, 0x00, + 0x80, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x86, 0x0D, 0x00, 0x00, + 0x64, 0x0D, 0x00, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xE7, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xE8, 0x13, 0x00, 0x00, + 0xE7, 0x13, 0x00, 0x00, 0x86, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x89, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, 0xF7, 0x01, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, 0xEE, 0x13, 0x00, 0x00, + 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xEF, 0x13, 0x00, 0x00, 0xEE, 0x13, 0x00, 0x00, 0x89, 0x0D, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x8C, 0x0D, 0x00, 0x00, 0x64, 0x0D, 0x00, 0x00, + 0x01, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0xA8, 0x01, 0x00, 0x00, + 0xF5, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0xB0, 0x01, 0x00, 0x00, 0xF6, 0x13, 0x00, 0x00, 0xF5, 0x13, 0x00, 0x00, + 0x8C, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8F, 0x0D, 0x00, 0x00, + 0x64, 0x0D, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0xA8, 0x01, 0x00, 0x00, 0xFC, 0x13, 0x00, 0x00, 0x9F, 0x13, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xFD, 0x13, 0x00, 0x00, + 0xFC, 0x13, 0x00, 0x00, 0x8F, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xAE, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA2, 0x0D, 0x00, 0x00, 0xA2, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA4, 0x0D, 0x00, 0x00, + 0xA2, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA6, 0x0D, 0x00, 0x00, 0xA2, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x13, 0x14, 0x00, 0x00, 0xA2, 0x0D, 0x00, 0x00, 0xA2, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, + 0xA4, 0x0D, 0x00, 0x00, 0xA4, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x19, 0x14, 0x00, 0x00, 0xA6, 0x0D, 0x00, 0x00, + 0xA6, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAF, 0x0D, 0x00, 0x00, 0xB7, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x0D, 0x00, 0x00, + 0xB7, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB3, 0x0D, 0x00, 0x00, 0xB7, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1D, 0x14, 0x00, 0x00, 0xAF, 0x0D, 0x00, 0x00, 0xAF, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x14, 0x00, 0x00, + 0xB1, 0x0D, 0x00, 0x00, 0xB1, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0xB3, 0x0D, 0x00, 0x00, + 0xB3, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC9, 0x0D, 0x00, 0x00, 0xA9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCB, 0x0D, 0x00, 0x00, + 0xA9, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCD, 0x0D, 0x00, 0x00, 0xA9, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x31, 0x14, 0x00, 0x00, 0xC9, 0x0D, 0x00, 0x00, 0xC9, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x14, 0x00, 0x00, + 0xCB, 0x0D, 0x00, 0x00, 0xCB, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x37, 0x14, 0x00, 0x00, 0xCD, 0x0D, 0x00, 0x00, + 0xCD, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD6, 0x0D, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD8, 0x0D, 0x00, 0x00, + 0xB0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDA, 0x0D, 0x00, 0x00, 0xB0, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3B, 0x14, 0x00, 0x00, 0xD6, 0x0D, 0x00, 0x00, 0xD6, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, + 0xD8, 0x0D, 0x00, 0x00, 0xD8, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0xDA, 0x0D, 0x00, 0x00, + 0xDA, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE3, 0x0D, 0x00, 0x00, 0xC5, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE5, 0x0D, 0x00, 0x00, + 0xC5, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, 0xC5, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x45, 0x14, 0x00, 0x00, 0xE3, 0x0D, 0x00, 0x00, 0xE3, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, + 0xE5, 0x0D, 0x00, 0x00, 0xE5, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4B, 0x14, 0x00, 0x00, 0xE7, 0x0D, 0x00, 0x00, + 0xE7, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF0, 0x0D, 0x00, 0x00, 0xCC, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF2, 0x0D, 0x00, 0x00, + 0xCC, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, 0xCC, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x14, 0x00, 0x00, 0xF0, 0x0D, 0x00, 0x00, 0xF0, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, + 0xF2, 0x0D, 0x00, 0x00, 0xF2, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x55, 0x14, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, + 0xF4, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFD, 0x0D, 0x00, 0x00, 0xD3, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xFF, 0x0D, 0x00, 0x00, + 0xD3, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0xD3, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x59, 0x14, 0x00, 0x00, 0xFD, 0x0D, 0x00, 0x00, 0xFD, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5C, 0x14, 0x00, 0x00, + 0xFF, 0x0D, 0x00, 0x00, 0xFF, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5F, 0x14, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, + 0x01, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0A, 0x0E, 0x00, 0x00, 0xDA, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x00, 0x00, + 0xDA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0xDA, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x63, 0x14, 0x00, 0x00, 0x0A, 0x0E, 0x00, 0x00, 0x0A, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, + 0x0C, 0x0E, 0x00, 0x00, 0x0C, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x69, 0x14, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, + 0x0E, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x17, 0x0E, 0x00, 0x00, 0xEF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x0E, 0x00, 0x00, + 0xEF, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1B, 0x0E, 0x00, 0x00, 0xEF, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6D, 0x14, 0x00, 0x00, 0x17, 0x0E, 0x00, 0x00, 0x17, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, + 0x19, 0x0E, 0x00, 0x00, 0x19, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x14, 0x00, 0x00, 0x1B, 0x0E, 0x00, 0x00, + 0x1B, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x24, 0x0E, 0x00, 0x00, 0xF6, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0x0E, 0x00, 0x00, + 0xF6, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x28, 0x0E, 0x00, 0x00, 0xF6, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x77, 0x14, 0x00, 0x00, 0x24, 0x0E, 0x00, 0x00, 0x24, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7A, 0x14, 0x00, 0x00, + 0x26, 0x0E, 0x00, 0x00, 0x26, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x14, 0x00, 0x00, 0x28, 0x0E, 0x00, 0x00, + 0x28, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x0E, 0x00, 0x00, 0xE8, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x0E, 0x00, 0x00, + 0xE8, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, 0xE8, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8B, 0x14, 0x00, 0x00, 0x3E, 0x0E, 0x00, 0x00, 0x3E, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, + 0x40, 0x0E, 0x00, 0x00, 0x40, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x91, 0x14, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, + 0x42, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4B, 0x0E, 0x00, 0x00, 0xFD, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4D, 0x0E, 0x00, 0x00, + 0xFD, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, 0xFD, 0x13, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x95, 0x14, 0x00, 0x00, 0x4B, 0x0E, 0x00, 0x00, 0x4B, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x98, 0x14, 0x00, 0x00, + 0x4D, 0x0E, 0x00, 0x00, 0x4D, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x9B, 0x14, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, + 0x4F, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB9, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x34, 0x14, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBA, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, 0xB9, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, + 0x66, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC1, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xBA, 0x14, 0x00, 0x00, 0xC0, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE3, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x34, 0x14, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE4, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x16, 0x14, 0x00, 0x00, + 0xE3, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEA, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x48, 0x14, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xEB, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE4, 0x14, 0x00, 0x00, 0xEA, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, + 0x48, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x20, 0x14, 0x00, 0x00, 0x0D, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0E, 0x15, 0x00, 0x00, + 0x14, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x37, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x3E, 0x14, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x38, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x20, 0x14, 0x00, 0x00, 0x37, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3E, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, + 0x70, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3F, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x38, 0x15, 0x00, 0x00, 0x3E, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x61, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x5C, 0x14, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, + 0x61, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x68, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x70, 0x14, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x69, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x62, 0x15, 0x00, 0x00, 0x68, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x8B, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x5C, 0x14, 0x00, 0x00, + 0x66, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8C, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x3E, 0x14, 0x00, 0x00, 0x8B, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x8C, 0x15, 0x00, 0x00, + 0x92, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB5, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x66, 0x14, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB6, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, 0xB5, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xBC, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x7A, 0x14, 0x00, 0x00, + 0x98, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBD, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xB6, 0x15, 0x00, 0x00, 0xBC, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xDF, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x66, 0x14, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE0, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, + 0xDF, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xE6, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x7A, 0x14, 0x00, 0x00, 0x98, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xE7, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0xE0, 0x15, 0x00, 0x00, 0xE6, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00, + 0xEB, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x16, 0x00, 0x00, + 0x07, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x27, 0x16, 0x00, 0x00, 0x3F, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x27, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x29, 0x16, 0x00, 0x00, 0x28, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x48, 0x16, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x16, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x48, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4A, 0x16, 0x00, 0x00, 0x49, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x16, 0x00, 0x00, + 0xE7, 0x15, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6A, 0x16, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x69, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6B, 0x16, 0x00, 0x00, + 0x6A, 0x16, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA7, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xEB, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xC1, 0x14, 0x00, 0x00, + 0xA7, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAA, 0x0F, 0x00, 0x00, 0xA8, 0x0F, 0x00, 0x00, 0x08, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x95, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xAA, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBF, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x3F, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x15, 0x15, 0x00, 0x00, 0xBF, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC2, 0x0F, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, + 0x29, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC8, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xC2, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD7, 0x0F, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD8, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x69, 0x15, 0x00, 0x00, 0xD7, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xDA, 0x0F, 0x00, 0x00, + 0xD8, 0x0F, 0x00, 0x00, 0x4A, 0x16, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xFB, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xDA, 0x0F, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEF, 0x0F, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0xE7, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xBD, 0x15, 0x00, 0x00, + 0xEF, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xF2, 0x0F, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x6B, 0x16, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xF2, 0x0F, 0x00, 0x00, + 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x17, 0x00, 0x00, 0x95, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5E, 0x17, 0x00, 0x00, + 0x5C, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x60, 0x17, 0x00, 0x00, 0x5E, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x61, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8F, 0x17, 0x00, 0x00, 0xC8, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x17, 0x00, 0x00, + 0x8F, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x93, 0x17, 0x00, 0x00, 0x91, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x94, 0x17, 0x00, 0x00, 0x93, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC2, 0x17, 0x00, 0x00, 0xFB, 0x16, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC4, 0x17, 0x00, 0x00, + 0xC2, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC6, 0x17, 0x00, 0x00, 0xC4, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC7, 0x17, 0x00, 0x00, 0xC6, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF5, 0x17, 0x00, 0x00, 0x2E, 0x17, 0x00, 0x00, + 0xC2, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF7, 0x17, 0x00, 0x00, + 0xF5, 0x17, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF9, 0x17, 0x00, 0x00, 0xF7, 0x17, 0x00, 0x00, + 0x84, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xFA, 0x17, 0x00, 0x00, 0xF9, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0xC7, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, + 0x61, 0x17, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x94, 0x17, 0x00, 0x00, + 0x16, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2E, 0x10, 0x00, 0x00, 0xC7, 0x17, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, + 0xFA, 0x17, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3D, 0x10, 0x00, 0x00, 0x62, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3E, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, 0x3D, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, + 0x62, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x42, 0x10, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x41, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x43, 0x10, 0x00, 0x00, 0x3E, 0x10, 0x00, 0x00, 0x42, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0x3D, 0x10, 0x00, 0x00, 0x42, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, 0x3E, 0x10, 0x00, 0x00, + 0x41, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x56, 0x10, 0x00, 0x00, 0x3D, 0x10, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0xEB, 0x14, 0x00, 0x00, 0xC1, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x5A, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x23, 0x18, 0x00, 0x00, 0x5B, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x23, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x25, 0x18, 0x00, 0x00, 0x24, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x43, 0x10, 0x00, 0x00, + 0x25, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x00, 0x3F, 0x15, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x0A, 0x08, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2E, 0x18, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x18, 0x00, 0x00, + 0x8B, 0x01, 0x00, 0x00, 0x2E, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x2F, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, + 0x4A, 0x10, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, 0x93, 0x15, 0x00, 0x00, + 0x69, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6B, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, 0x6A, 0x10, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x18, 0x00, 0x00, + 0x6B, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3A, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x39, 0x18, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3B, 0x18, 0x00, 0x00, + 0x3A, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6E, 0x10, 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, 0x3B, 0x18, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, + 0xE7, 0x15, 0x00, 0x00, 0xBD, 0x15, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, 0x0A, 0x08, 0x00, 0x00, + 0x72, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x44, 0x18, 0x00, 0x00, 0x73, 0x10, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x45, 0x18, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, + 0x44, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x46, 0x18, 0x00, 0x00, 0x45, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x76, 0x10, 0x00, 0x00, 0x56, 0x10, 0x00, 0x00, + 0x46, 0x18, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7C, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, + 0x25, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, 0x2E, 0x10, 0x00, 0x00, + 0x6E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x98, 0x10, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, + 0x98, 0x10, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, + 0x76, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB3, 0x10, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB5, 0x10, 0x00, 0x00, + 0xB3, 0x10, 0x00, 0x00, 0x66, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0x6E, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xEB, 0x10, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, 0x76, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5C, 0x1A, 0x00, 0x00, + 0x7C, 0x10, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5D, 0x1A, 0x00, 0x00, 0x5C, 0x1A, 0x00, 0x00, + 0x97, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5E, 0x1A, 0x00, 0x00, 0x5D, 0x1A, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x5E, 0x1A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, + 0x9A, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x19, 0x11, 0x00, 0x00, 0x17, 0x11, 0x00, 0x00, 0xB5, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1B, 0x11, 0x00, 0x00, + 0x19, 0x11, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1D, 0x11, 0x00, 0x00, 0x1B, 0x11, 0x00, 0x00, + 0xEB, 0x10, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x18, 0x00, 0x00, 0x1D, 0x11, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5E, 0x18, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, + 0x5D, 0x18, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5F, 0x18, 0x00, 0x00, 0x5E, 0x18, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x62, 0x18, 0x00, 0x00, 0x5F, 0x18, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x64, 0x18, 0x00, 0x00, + 0x62, 0x18, 0x00, 0x00, 0x1D, 0x11, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x64, 0x18, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x67, 0x18, 0x00, 0x00, 0x5F, 0x18, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5F, 0x1A, 0x00, 0x00, + 0x13, 0x14, 0x00, 0x00, 0x31, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x27, 0x11, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, + 0x5F, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2B, 0x11, 0x00, 0x00, 0x1D, 0x14, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x11, 0x00, 0x00, + 0x27, 0x11, 0x00, 0x00, 0x2B, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, 0x4F, 0x14, 0x00, 0x00, + 0x85, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x31, 0x11, 0x00, 0x00, 0x2C, 0x11, 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x35, 0x11, 0x00, 0x00, + 0x59, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, + 0x35, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x3A, 0x11, 0x00, 0x00, 0x8B, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3B, 0x11, 0x00, 0x00, + 0x36, 0x11, 0x00, 0x00, 0x3A, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x00, 0x00, 0x77, 0x14, 0x00, 0x00, + 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x40, 0x11, 0x00, 0x00, 0x3B, 0x11, 0x00, 0x00, 0x3F, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x44, 0x11, 0x00, 0x00, + 0x95, 0x14, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x45, 0x11, 0x00, 0x00, 0x40, 0x11, 0x00, 0x00, + 0x44, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x49, 0x11, 0x00, 0x00, 0x3B, 0x14, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4A, 0x11, 0x00, 0x00, + 0x45, 0x11, 0x00, 0x00, 0x49, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x4E, 0x11, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x4F, 0x11, 0x00, 0x00, 0x4A, 0x11, 0x00, 0x00, 0x4E, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x53, 0x11, 0x00, 0x00, + 0x63, 0x14, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x54, 0x11, 0x00, 0x00, 0x4F, 0x11, 0x00, 0x00, + 0x53, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x58, 0x11, 0x00, 0x00, 0x6D, 0x14, 0x00, 0x00, 0xEB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x59, 0x11, 0x00, 0x00, + 0x54, 0x11, 0x00, 0x00, 0x58, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x5B, 0x11, 0x00, 0x00, 0x59, 0x11, 0x00, 0x00, + 0x67, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x75, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x5B, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x60, 0x1A, 0x00, 0x00, + 0x16, 0x14, 0x00, 0x00, 0x34, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x65, 0x11, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, + 0x60, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x69, 0x11, 0x00, 0x00, 0x20, 0x14, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6A, 0x11, 0x00, 0x00, + 0x65, 0x11, 0x00, 0x00, 0x69, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x6E, 0x11, 0x00, 0x00, 0x52, 0x14, 0x00, 0x00, + 0x85, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x6F, 0x11, 0x00, 0x00, 0x6A, 0x11, 0x00, 0x00, 0x6E, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, + 0x5C, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x74, 0x11, 0x00, 0x00, 0x6F, 0x11, 0x00, 0x00, + 0x73, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x11, 0x00, 0x00, 0x8E, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x79, 0x11, 0x00, 0x00, + 0x74, 0x11, 0x00, 0x00, 0x78, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x7D, 0x11, 0x00, 0x00, 0x7A, 0x14, 0x00, 0x00, + 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x7E, 0x11, 0x00, 0x00, 0x79, 0x11, 0x00, 0x00, 0x7D, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x82, 0x11, 0x00, 0x00, + 0x98, 0x14, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x83, 0x11, 0x00, 0x00, 0x7E, 0x11, 0x00, 0x00, + 0x82, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x87, 0x11, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, + 0x83, 0x11, 0x00, 0x00, 0x87, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x8C, 0x11, 0x00, 0x00, 0x48, 0x14, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x8D, 0x11, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, 0x8C, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x91, 0x11, 0x00, 0x00, + 0x66, 0x14, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x92, 0x11, 0x00, 0x00, 0x8D, 0x11, 0x00, 0x00, + 0x91, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x96, 0x11, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0xEB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x97, 0x11, 0x00, 0x00, + 0x92, 0x11, 0x00, 0x00, 0x96, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x99, 0x11, 0x00, 0x00, 0x97, 0x11, 0x00, 0x00, + 0x67, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x83, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x99, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x61, 0x1A, 0x00, 0x00, + 0x19, 0x14, 0x00, 0x00, 0x37, 0x14, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA3, 0x11, 0x00, 0x00, 0x7C, 0x10, 0x00, 0x00, + 0x61, 0x1A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA7, 0x11, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xA8, 0x11, 0x00, 0x00, + 0xA3, 0x11, 0x00, 0x00, 0xA7, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xAC, 0x11, 0x00, 0x00, 0x55, 0x14, 0x00, 0x00, + 0x85, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xAD, 0x11, 0x00, 0x00, 0xA8, 0x11, 0x00, 0x00, 0xAC, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB1, 0x11, 0x00, 0x00, + 0x5F, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xB2, 0x11, 0x00, 0x00, 0xAD, 0x11, 0x00, 0x00, + 0xB1, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xB6, 0x11, 0x00, 0x00, 0x91, 0x14, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xB7, 0x11, 0x00, 0x00, + 0xB2, 0x11, 0x00, 0x00, 0xB6, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0x11, 0x00, 0x00, 0x7D, 0x14, 0x00, 0x00, + 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xBC, 0x11, 0x00, 0x00, 0xB7, 0x11, 0x00, 0x00, 0xBB, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC0, 0x11, 0x00, 0x00, + 0x9B, 0x14, 0x00, 0x00, 0xB2, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xC1, 0x11, 0x00, 0x00, 0xBC, 0x11, 0x00, 0x00, + 0xC0, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xC5, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC6, 0x11, 0x00, 0x00, + 0xC1, 0x11, 0x00, 0x00, 0xC5, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xCA, 0x11, 0x00, 0x00, 0x4B, 0x14, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xCB, 0x11, 0x00, 0x00, 0xC6, 0x11, 0x00, 0x00, 0xCA, 0x11, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xCF, 0x11, 0x00, 0x00, + 0x69, 0x14, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD0, 0x11, 0x00, 0x00, 0xCB, 0x11, 0x00, 0x00, + 0xCF, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xD4, 0x11, 0x00, 0x00, 0x73, 0x14, 0x00, 0x00, 0xEB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xD5, 0x11, 0x00, 0x00, + 0xD0, 0x11, 0x00, 0x00, 0xD4, 0x11, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xD7, 0x11, 0x00, 0x00, 0xD5, 0x11, 0x00, 0x00, + 0x67, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x91, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xD7, 0x11, 0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xDE, 0x09, 0x00, 0x00, 0xDF, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xDF, 0x09, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xDE, 0x09, 0x00, 0x00, 0xE1, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0x52, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xE1, 0x09, 0x00, 0x00, + 0x83, 0x18, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xDE, 0x09, 0x00, 0x00, + 0xE3, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xE3, 0x09, 0x00, 0x00, 0x91, 0x18, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xE5, 0x09, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xE5, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xE7, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xE8, 0x09, 0x00, 0x00, 0xE7, 0x09, 0x00, 0x00, 0xE6, 0x09, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0xE8, 0x09, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xE9, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, 0xE9, 0x09, 0x00, 0x00, + 0xE9, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x9D, 0x18, 0x00, 0x00, 0xBF, 0x09, 0x00, 0x00, 0x6B, 0x1A, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9F, 0x18, 0x00, 0x00, + 0x9D, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x18, 0x00, 0x00, 0x9F, 0x18, 0x00, 0x00, + 0x55, 0x01, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x18, 0x00, 0x00, 0x9D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA3, 0x18, 0x00, 0x00, + 0xA0, 0x18, 0x00, 0x00, 0xA2, 0x18, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x98, 0x18, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0xA4, 0x18, 0x00, 0x00, 0x98, 0x18, 0x00, 0x00, + 0xA3, 0x18, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xA5, 0x18, 0x00, 0x00, 0xA4, 0x18, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xEE, 0x09, 0x00, 0x00, 0xA5, 0x18, 0x00, 0x00, + 0xA5, 0x18, 0x00, 0x00, 0xA5, 0x18, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x32, 0x00, 0x00, 0x00, 0xEF, 0x09, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, + 0xEE, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x32, 0x00, 0x00, 0x00, + 0xF2, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xEF, 0x09, 0x00, 0x00, 0xF0, 0x09, 0x00, 0x00, 0xF1, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0xB0, 0x01, 0x00, 0x00, 0xF3, 0x09, 0x00, 0x00, + 0xD0, 0x09, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0xB0, 0x01, 0x00, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0xF3, 0x09, 0x00, 0x00, 0xF2, 0x09, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xD0, 0x09, 0x00, 0x00, + 0xF4, 0x09, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xDE, 0x09, 0x00, 0x00, + 0xF6, 0x09, 0x00, 0x00, 0xD0, 0x09, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x79, 0x01, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..02044065f36008117d1f3fea04602b37e783d5a8 GIT binary patch literal 14492 zcmZ{r3D}ln+Q%OvSq3x4K4Z)nGiLZOz8ULhAIo4S`&fIWg-A8MWgCo2wz7oCnh04# z+KWmFSwdN|gd~I(vd8!Pz3+XVuH!kr?>YQ?&;S42?)$p#`?~J?c@8aB+-#LvZH3xu zwN|yx8`YXVKdr5ZQmd_AYuWU7zk?1tXzRuv?YI8(U$!-1&0345IAhkTtx{Wwzv8sE zox13FWYt=2CRm#|bsAu`plYo)l%$pDw%GTf9wJPE|b!peRXZtc>Wg^PHE7w-8-Any5J2dp@aAuF5-KnuM=iu?2 z)VX2b?rl%nyKC3(?KuqeR<$wcM|Ie{ZR24lx9#4oLzlg~c4_R5vp(GUQ!{owVr{!=6IS9{Xr5m+bGK>Io5#dl zFBmm*<=gSsSg#=YuKcyO^SCAdY99zZ$Kb889pqo&KN!<|HT~L$fD8Kc85jIe_=5L4 z?i~Cu_*-wjnf!40Gc#sn{1NbBciol#BjJN@*(Ck{g!k{)Fa1ZsM~xhr{-fa!KlD)g zkAYuwVaw#l!fzcsIQen#7hiZG^N)w$c*92NZv!8A%{61=_#5C?4H%IA6X4^sOJrE%gr~ZpWCE1|GoFp-w}T4C6}cCB>3&O{U+<5 z3}61;cX@oB;9o3Tmi|-VS6*>N=AR0GVdl&+(Z4gi-=(Xi|1|i7@#8b!MdbVC%hTT# zK6=#l$-BXa+`8$GQSV>y@#A*ReDA0G?!7nTy`MRr^n3H(eA7*N{5|3C&!3_zl-zpYi9x z$Bx-C4t4;c^Xy)m^68_1@ACHas9{}h6%=oL|*ALnt{a3@k{_4y;pKIXU zKUr@eock~HuZ2JLEadE!4!XFtiBJ+p9nV;mh!G}Mvb;jQgzv;#s(?1l> zdXfG+;MZNdUi$BZfA!^;>Awp;{fT|kKMcdA)K1u&5__YHErhhbi+SIApe+-=UEZ3j0@W-d@mGR@?+|OBWJe>K> z_zCc-k3XLNiSQr3KQH;C@Nd64JL^3LXFW{+BslA5^2zXb-aaAgPk|4;{r1d%9DZ5< z{(1aU;ZHyHROU~E_d35eI>!46_#H!s=Jhun{^0Q88UG}l^)l-}1!q3f|1_NIE&Vg# zGoC&m{m;Oum;Ptr9AEZ(4$gX;{^#NBUwQm9;nYk23vkx^tp6hX*=L@~dN08l&-BlN zFZ=xStT!9Zcx1ho;asm7{|bD>!`r3*RXF=Y`d@?d{E>VPoclNHzYhQC!w=K{2AuUM z{cpnAU$g#OaPFUsp9_C|&N0c~hQIsHI~o5D{PN2#Oa3mL^*-b0!P%eE{~nyXLOgMSQReae2Hz-PVm zQs#dOA9USy>0bnAz0Z1!;XJQo|0QtN>+~;$bAM&M&*0q8S?_cBLk~Wf_scRk>s|W4 zfR7nHI{BCItFQW5@~_}a7B9~HuiUfwP{Di}U>!&i$SIJ2>N+@yp>KesFRg z|Mzg#+l>DK&huq*pM}{!Gk*m*`+4#e;S(oJ$nj|b=Xo&wE5Wb1`s%E=GQ95v7i4@( zIOm)GRp6|T$y>p>{<7YxaONxhtHD_h)4w|Wxo4kEz6PA}8x!O66FASunZG8S=ckNc z3qE<$q#YuDZ8-Z)#{U%l-n@Ak|1&txgXv!f&hviye-3|p?%edR3%_m1ko2zyXaCOm zSRc;waQZiZv!7)ChH&Hi&^=kesfhx0y^@ms*T ze{%l*0B1i<{~zIec8U4g63+dU^|pfFb?5Jr{}-I~BlEY0zw+{t>E8yv=wV z!FeA`|K4!+kK})aGyXfr`RoH{|IhntUpV8D@%zD9pR)e`aGrf0H{>%6S;5-j! z{DE-puk;@T=l;w7e}{AZr~e;t=0E+d;XKbJKN!ybz0+2;7AqXgg?0%15dIzt4g-gS zBfyd1pWrBPG&lwv3yuTFgEpW6oB-N_6G1!B9&`X5!Aam`&EH}-CO8Y64gL+z0q27Az<?YYFab;ikAla*Brq9F0gr>JU>bM= zOb1Vbr@+%-26zTM3!VedgPGt3@FI8#%mTB)%itC8DtHad0k4BMz?W!Vd4+gOoo?iKbpVh?A-#zMI0N-if z3BL;74?h09#peYd2>)U5k|w??b%!+N*Y?rik3hiPG^UQd-0$DjHi7${y5q^8n(<>XwAGE5`<=g< z{_&M<&Q@G?&edczuP@pmQCNWFNQ=-|AxK< zJ$m{##(r5*e;*i)rhiW=I!+USW9PhD&oP@=>Ai`OKMFTb{TyOE=Etzr<-5YC zU^~XvbxfxL>pJh&#jHJ1>E^h8Ooyv|&G{`}z4<)-+YP_x(fTLNeGZ{!(|QB9kDt&E zt2EE?VB$Qs!_f`}`s`(`Be2!`5+gqn+xqHJ>u7B2JN}^^Q)#4R{bSLL)fe@T!&dKA z)juBF9_njw^!9AP_Bg%t_4lb_PsEn%k9lfe@$-ps4m!cro~y>wb!zZBJR|V8J?H2; zHUzHLz$kcK+=i`YuIJ<&N4?HfJ=dDZA6A!tH(brw$dB0Jb+He^)jY+{d3@?8TXe`;O+G`O0v_4#L4`L1D+Kcg=H8MvCU_4(&k`L4H-|6*PK zOK>$~>+{dA@?D!F|FydOIdC;&>+>(H@?CEue?eXT2XHlG>+>(E^4$j_|I@nsMQ}A^ z>+}0p`L6AezpO6*3%HuG_4!v+`R)Ue|6N`Fa=4nYk?%d|?S31Y*Rr3`hE^JX|R1$EIlJi_kVh zGhalHr?9>E%Dyuyt?c`3rImgEL_PCG^!PKH`69F((99Rn_hoGFqXi3he|8^uCQivT-o<%>X|R1 z$8l)pi_jX-%oovjHEh?JvhNy|R`y-9(#pQ=sAs;29v#ul7ol}RGhamC^|4)F%Dx*` zTG@BwN-O)GMm_UI^yr3Wz6h-m&3qAke~az9RQCN{rImfRsI;>08PqdhM31x4%om}Z zi)OxvzPn+&9+!RhsI;>0UX@n%?MFTHMfA8F&3qBs05tPO^gR&Ub+qjJ_ev}Kwyw0Y z??CFAFQUgFH1kDhH=>y@*5EnAHFhkT^*0BuHQx8(8&~*Tca06-q{8Pt+jKouH76H7 zYZx1O^D5sK|3|;~3ZMOqjl7QvUwyxYh0hwsM&3`>{qg)fH*>?cX5n*vH#U4fFMO^I zUbo>}xA0lR*zoO8`8>b+emfRE`xzT~yA{6re!CYwYZx1OZ7ZMi=UP(E!-<8@V=*@J zPA+_&o7ZXhIu$-^7#qHRmCy65@7KTZ+0WR>yQ=Wj_q)3AS;N@K8(H~0KhLe4hf#&k zc{MijCKNvJeeZ|xO)PxYFgAR1E1&0A-|y|hXFp>j@BPA8-)}+Tvxc$p9@TO^zAK}a z?`ys%tpe}I4XJL7_h>6@^~m`>w%0`DYyme%J#zkltsXi1V>`}~^EbFT>XCB*wtD1r z!uHrB=M=a(>XCCQwz}^_9_w9eHNQ7|PBAva&`4`qV_X}Ii8bjSZ2hgMu?BBf))k~n1p7I*NOM1G0|fRw*Eg9J)SIj=&$eb3Yt9}v*__ETJ-Q9 zF(!J#(8{O^w3}5V-cD?9OLM*7%h5uof;E8mSXF7%%jKF>;E`b`lCn8;c@sK z&neaQ)dsHS_kX_QdCi>wSNA)+nAf&&^{8_Nwqq7`2Ef(II#xvwHOF4)=cc-i>~ZX!g?={r*ahdi2`|Za?+t zw=cGO^gEq+=TJSgbKqXHj&*2#vAt#;kI=5e_L}vWYh(%8^YB+&d@f7t9zWG{SvP3amIWd&zP&ne6@l58-{w!R|B^Cf2w`^L~OM<&i2@9 z)`?yn;p+bW5pgHM&C?fg4V;_bhxi>q#QmN+j+wsDwnX#$i*g*dLNiuh#BGc1dvF=| zCp2UAMciMoeQz!2V0$!U^+nvy*!}9_c0n^%U&QT>?fY4I-Ryy8tiFi*E4J@7W!ye! z#_Ef>zhV3RMLEw0pc$(#;{KsVTsilx(Tvp>aff01zFb}phoc#*FXE2E_WjmtBHGge>3 zb;0(XqKxZ`W~{!5YsB`MzMShGXvXS`xHGYRUnt|wLNiuh#GQ-nvv4_w=b;&^FXDP* z`+Q!;^+7XMU&LL6?R!Nz*B7H1t1sgEV>i7I6mxSKnz8yKZUDB=_~l$*g=Vb2h`Scs z_l|O|uR}9dU&LLHtzOP`pJJ}{*UxoZ=5s@8`<-6Yxt%!YT3={)p>1YNaZba~jMW!$ z_hI|JRT+0bnz8yK?jdZyXDa9LVKig)McgQCzpp6cMxz<4FXF~y`+Z6|hZE3@)faJ- zu>BsQjGK&RtiFhwhVA!_!Da2AZ+@BJO!?zuzk7dM28&`XX)? zw%#d!)au?^bKk#9a%*|4!xi8CJjC z>nHs4D!;$~>X+LyeoK6>^0($aYCG1K`EWJi$2G_Ajr>hZ|NH1_zXHZaodwt)XKS7Y z{VnPPY&GNg8Gy5C{(q7DUCrY#)|klu5W6|Q`8Ym;s|i1G9Mh@fZ+c^H z`%W?#P2JcFD(zOd`Voi`cUu)lSiaBPj%KVrkI&y+4yF@m0jI674*&oF literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt new file mode 100644 index 000000000..487844679 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.txt @@ -0,0 +1,726 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6764 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasSharpenConstants "XeCasSharpenConstants" + OpMemberName %XeCasSharpenConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasSharpenConstants 1 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasSharpenConstants 0 Offset 16 + OpMemberDecorate %XeCasSharpenConstants 1 Offset 24 + OpDecorate %XeCasSharpenConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %float = OpTypeFloat 32 +%_ptr_Function_float = OpTypePointer Function %float + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %v4uint = OpTypeVector %uint 4 + %uint_15 = OpConstant %uint 15 + %uint_256 = OpConstant %uint 256 +%_arr_float_uint_256 = OpTypeArray %float %uint_256 +%float_n0_00100337015 = OpConstant %float -0.00100337015 +%float_0_000880821084 = OpConstant %float 0.000880821084 +%float_0_00169270835 = OpConstant %float 0.00169270835 +%float_n0_00155484071 = OpConstant %float -0.00155484071 +%float_0_00127910543 = OpConstant %float 0.00127910543 +%float_n0_000605085806 = OpConstant %float -0.000605085806 +%float_0_00106464466 = OpConstant %float 0.00106464466 +%float_n0_00138633582 = OpConstant %float -0.00138633582 +%float_0_00135569857 = OpConstant %float 0.00135569857 +%float_0_000513174047 = OpConstant %float 0.000513174047 +%float_0_00121783093 = OpConstant %float 0.00121783093 +%float_n0_00160079659 = OpConstant %float -0.00160079659 +%float_0_00058976718 = OpConstant %float 0.00058976718 +%float_n0_00028339462 = OpConstant %float -0.00028339462 +%float_0_00111060054 = OpConstant %float 0.00111060054 +%float_n0_00141697307 = OpConstant %float -0.00141697307 +%float_0_00144761032 = OpConstant %float 0.00144761032 +%float_n0_0005438113 = OpConstant %float -0.0005438113 +%float_0_00013020834 = OpConstant %float 0.00013020834 +%float_n0_0012025123 = OpConstant %float -0.0012025123 +%float_0_000436580885 = OpConstant %float 0.000436580885 +%float_n0_00104932603 = OpConstant %float -0.00104932603 +%float_0_000620404433 = OpConstant %float 0.000620404433 +%float_n0_000482536765 = OpConstant %float -0.000482536765 +%float_0_00187653187 = OpConstant %float 0.00187653187 +%float_n0_00109528191 = OpConstant %float -0.00109528191 +%float_n9_95710798en05 = OpConstant %float -9.95710798e-05 +%float_n0_000528492674 = OpConstant %float -0.000528492674 +%float_0_0014322917 = OpConstant %float 0.0014322917 +%float_n0_00193780637 = OpConstant %float -0.00193780637 +%float_n0_000696997566 = OpConstant %float -0.000696997566 +%float_3_829657en05 = OpConstant %float 3.829657e-05 +%float_0_000712316192 = OpConstant %float 0.000712316192 +%float_n0_00130974269 = OpConstant %float -0.00130974269 +%float_0_00109528191 = OpConstant %float 0.00109528191 +%float_n0_000298713247 = OpConstant %float -0.000298713247 +%float_0_00175398286 = OpConstant %float 0.00175398286 +%float_n0_00167738972 = OpConstant %float -0.00167738972 +%float_0_00147824758 = OpConstant %float 0.00147824758 +%float_n3_829657en05 = OpConstant %float -3.829657e-05 +%float_0_000788909325 = OpConstant %float 0.000788909325 +%float_n0_00183057599 = OpConstant %float -0.00183057599 +%float_0_000298713247 = OpConstant %float 0.000298713247 +%float_0_000988051528 = OpConstant %float 0.000988051528 +%float_n0_00117187505 = OpConstant %float -0.00117187505 +%float_0_00017616422 = OpConstant %float 0.00017616422 +%float_0_00164675247 = OpConstant %float 0.00164675247 +%float_n0_00158547796 = OpConstant %float -0.00158547796 +%float_0_000344669126 = OpConstant %float 0.000344669126 +%float_0_00186121324 = OpConstant %float 0.00186121324 +%float_n0_00176930148 = OpConstant %float -0.00176930148 +%float_n0_000865502458 = OpConstant %float -0.000865502458 +%float_0_000896139711 = OpConstant %float 0.000896139711 +%float_0_000160845593 = OpConstant %float 0.000160845593 +%float_n0_000926776964 = OpConstant %float -0.000926776964 +%float_n0_00152420346 = OpConstant %float -0.00152420346 +%float_n0_000651041686 = OpConstant %float -0.000651041686 +%float_0_00129442406 = OpConstant %float 0.00129442406 +%float_n0_000804227951 = OpConstant %float -0.000804227951 +%float_n0_00146292895 = OpConstant %float -0.00146292895 +%float_0_00179993873 = OpConstant %float 0.00179993873 +%float_n0_000850183831 = OpConstant %float -0.000850183831 +%float_0_000850183831 = OpConstant %float 0.000850183831 +%float_n0_000451899512 = OpConstant %float -0.000451899512 +%float_n0_00106464466 = OpConstant %float -0.00106464466 +%float_n0_000145526967 = OpConstant %float -0.000145526967 +%float_0_000237438726 = OpConstant %float 0.000237438726 +%float_0_00141697307 = OpConstant %float 0.00141697307 +%float_n0_00058976718 = OpConstant %float -0.00058976718 +%float_n0_000191482846 = OpConstant %float -0.000191482846 +%float_0_00160079659 = OpConstant %float 0.00160079659 +%float_0_00101868878 = OpConstant %float 0.00101868878 +%float_0_000405943632 = OpConstant %float 0.000405943632 +%float_n0_000206801473 = OpConstant %float -0.000206801473 +%float_0_00158547796 = OpConstant %float 0.00158547796 +%float_0_000651041686 = OpConstant %float 0.000651041686 +%float_n6_89338267en05 = OpConstant %float -6.89338267e-05 +%float_0_000421262259 = OpConstant %float 0.000421262259 +%float_n0_00164675247 = OpConstant %float -0.00164675247 +%float_0_00137101719 = OpConstant %float 0.00137101719 +%float_0_000926776964 = OpConstant %float 0.000926776964 +%float_n0_000666360313 = OpConstant %float -0.000666360313 +%float_0_00118719367 = OpConstant %float 0.00118719367 +%float_n0_00144761032 = OpConstant %float -0.00144761032 +%float_0_000574448553 = OpConstant %float 0.000574448553 +%float_n0_00189185049 = OpConstant %float -0.00189185049 +%float_0_000758272072 = OpConstant %float 0.000758272072 +%float_n0_00129442406 = OpConstant %float -0.00129442406 +%float_0_00192248775 = OpConstant %float 0.00192248775 +%float_n0_0016620711 = OpConstant %float -0.0016620711 +%float_n0_00103400741 = OpConstant %float -0.00103400741 +%float_n0_000497855421 = OpConstant %float -0.000497855421 +%float_n0_00186121324 = OpConstant %float -0.00186121324 +%float_0_0012025123 = OpConstant %float 0.0012025123 +%float_n0_0003293505 = OpConstant %float -0.0003293505 +%float_n0_00137101719 = OpConstant %float -0.00137101719 +%float_0_00163143384 = OpConstant %float 0.00163143384 +%float_n0_00184589461 = OpConstant %float -0.00184589461 +%float_0_000727634819 = OpConstant %float 0.000727634819 +%float_n0_000911458337 = OpConstant %float -0.000911458337 +%float_0_00181525736 = OpConstant %float 0.00181525736 +%float_n0_00114123779 = OpConstant %float -0.00114123779 +%float_n0_000375306379 = OpConstant %float -0.000375306379 +%float_9_95710798en05 = OpConstant %float 9.95710798e-05 +%float_n0_000742953445 = OpConstant %float -0.000742953445 +%float_0_00117187505 = OpConstant %float 0.00117187505 +%float_6_89338267en05 = OpConstant %float 6.89338267e-05 +%float_0_0014935662 = OpConstant %float 0.0014935662 +%float_0_000972732843 = OpConstant %float 0.000972732843 +%float_n0_000957414217 = OpConstant %float -0.000957414217 +%float_0_00193780637 = OpConstant %float 0.00193780637 +%float_0_000528492674 = OpConstant %float 0.000528492674 +%float_5_36151965en05 = OpConstant %float 5.36151965e-05 +%float_n0_00124846818 = OpConstant %float -0.00124846818 +%float_n0_000268075994 = OpConstant %float -0.000268075994 +%float_0_00153952208 = OpConstant %float 0.00153952208 +%float_n7_65931418en06 = OpConstant %float -7.65931418e-06 +%float_0_000314031873 = OpConstant %float 0.000314031873 +%float_0_00134037994 = OpConstant %float 0.00134037994 +%float_n0_00175398286 = OpConstant %float -0.00175398286 +%float_0_000497855421 = OpConstant %float 0.000497855421 +%float_n0_00118719367 = OpConstant %float -0.00118719367 +%float_0_000773590698 = OpConstant %float 0.000773590698 +%float_n0_00134037994 = OpConstant %float -0.00134037994 +%float_0_000268075994 = OpConstant %float 0.000268075994 +%float_n0_00147824758 = OpConstant %float -0.00147824758 +%float_n0_00013020834 = OpConstant %float -0.00013020834 +%float_n0_000773590698 = OpConstant %float -0.000773590698 +%float_0_00130974269 = OpConstant %float 0.00130974269 +%float_0_000390625006 = OpConstant %float 0.000390625006 +%float_0_000957414217 = OpConstant %float 0.000957414217 +%float_n0_000467218139 = OpConstant %float -0.000467218139 +%float_n0_00153952208 = OpConstant %float -0.00153952208 +%float_0_00103400741 = OpConstant %float 0.00103400741 +%float_n0_000681678939 = OpConstant %float -0.000681678939 +%float_0_00167738972 = OpConstant %float 0.00167738972 +%float_0_00100337015 = OpConstant %float 0.00100337015 +%float_n0_000421262259 = OpConstant %float -0.000421262259 +%float_0_00178462011 = OpConstant %float 0.00178462011 +%float_n0_000237438726 = OpConstant %float -0.000237438726 +%float_n0_000620404433 = OpConstant %float -0.000620404433 +%float_0_0016620711 = OpConstant %float 0.0016620711 +%float_0_000834865205 = OpConstant %float 0.000834865205 +%float_n0_0017233456 = OpConstant %float -0.0017233456 +%float_n0_00107996329 = OpConstant %float -0.00107996329 +%float_0_00176930148 = OpConstant %float 0.00176930148 +%float_n0_000788909325 = OpConstant %float -0.000788909325 +%float_n0_00178462011 = OpConstant %float -0.00178462011 +%float_0_000681678939 = OpConstant %float 0.000681678939 +%float_n0_000988051528 = OpConstant %float -0.000988051528 +%float_n0_00132506131 = OpConstant %float -0.00132506131 +%float_n0_00017616422 = OpConstant %float -0.00017616422 +%float_n0_00150888483 = OpConstant %float -0.00150888483 +%float_0_0003293505 = OpConstant %float 0.0003293505 +%float_n0_001953125 = OpConstant %float -0.001953125 +%float_0_000666360313 = OpConstant %float 0.000666360313 +%float_n0_00161611522 = OpConstant %float -0.00161611522 +%float_0_00115655642 = OpConstant %float 0.00115655642 +%float_0_000451899512 = OpConstant %float 0.000451899512 +%float_n0_000436580885 = OpConstant %float -0.000436580885 +%float_0_000191482846 = OpConstant %float 0.000191482846 +%float_n0_0014935662 = OpConstant %float -0.0014935662 +%float_0_00114123779 = OpConstant %float 0.00114123779 +%float_8_42524532en05 = OpConstant %float 8.42524532e-05 +%float_0_00189185049 = OpConstant %float 0.00189185049 +%float_0_00140165444 = OpConstant %float 0.00140165444 +%float_0_000559129927 = OpConstant %float 0.000559129927 +%float_0_000114889706 = OpConstant %float 0.000114889706 +%float_0_00126378681 = OpConstant %float 0.00126378681 +%float_n0_000574448553 = OpConstant %float -0.000574448553 +%float_n0_000972732843 = OpConstant %float -0.000972732843 +%float_0_00132506131 = OpConstant %float 0.00132506131 +%float_0_000222120099 = OpConstant %float 0.000222120099 +%float_n0_000758272072 = OpConstant %float -0.000758272072 +%float_n0_00135569857 = OpConstant %float -0.00135569857 +%float_0_00146292895 = OpConstant %float 0.00146292895 +%float_0_000865502458 = OpConstant %float 0.000865502458 +%float_n0_000359987753 = OpConstant %float -0.000359987753 +%float_0_0005438113 = OpConstant %float 0.0005438113 +%float_n0_00112591917 = OpConstant %float -0.00112591917 +%float_n0_000252757367 = OpConstant %float -0.000252757367 +%float_n0_000559129927 = OpConstant %float -0.000559129927 +%float_n0_00181525736 = OpConstant %float -0.00181525736 +%float_0_0017233456 = OpConstant %float 0.0017233456 +%float_n0_00115655642 = OpConstant %float -0.00115655642 +%float_0_000742953445 = OpConstant %float 0.000742953445 +%float_0_00157015934 = OpConstant %float 0.00157015934 +%float_n0_000114889706 = OpConstant %float -0.000114889706 +%float_n0_00121783093 = OpConstant %float -0.00121783093 +%float_0_00183057599 = OpConstant %float 0.00183057599 +%float_2_29779416en05 = OpConstant %float 2.29779416e-05 +%float_n0_00192248775 = OpConstant %float -0.00192248775 +%float_0_00173866423 = OpConstant %float 0.00173866423 +%float_n0_000712316192 = OpConstant %float -0.000712316192 +%float_0_00155484071 = OpConstant %float 0.00155484071 +%float_n0_00170802698 = OpConstant %float -0.00170802698 +%float_0_00123314955 = OpConstant %float 0.00123314955 +%float_0_000206801473 = OpConstant %float 0.000206801473 +%float_0_00104932603 = OpConstant %float 0.00104932603 +%float_n0_000727634819 = OpConstant %float -0.000727634819 +%float_n0_00163143384 = OpConstant %float -0.00163143384 +%float_n0_000314031873 = OpConstant %float -0.000314031873 +%float_0_000482536765 = OpConstant %float 0.000482536765 +%float_n0_00179993873 = OpConstant %float -0.00179993873 +%float_0_00094209559 = OpConstant %float 0.00094209559 +%float_n0_000344669126 = OpConstant %float -0.000344669126 +%float_0_000696997566 = OpConstant %float 0.000696997566 +%float_n0_00101868878 = OpConstant %float -0.00101868878 +%float_n0_00157015934 = OpConstant %float -0.00157015934 +%float_n2_29779416en05 = OpConstant %float -2.29779416e-05 +%float_n0_00127910543 = OpConstant %float -0.00127910543 +%float_0_000804227951 = OpConstant %float 0.000804227951 +%float_n0_000896139711 = OpConstant %float -0.000896139711 +%float_n0_0014322917 = OpConstant %float -0.0014322917 +%float_0_000605085806 = OpConstant %float 0.000605085806 +%float_n8_42524532en05 = OpConstant %float -8.42524532e-05 +%float_0_000911458337 = OpConstant %float 0.000911458337 +%float_0_001953125 = OpConstant %float 0.001953125 +%float_n0_00140165444 = OpConstant %float -0.00140165444 +%float_n0_00063572306 = OpConstant %float -0.00063572306 +%float_0_00150888483 = OpConstant %float 0.00150888483 +%float_n0_000819546578 = OpConstant %float -0.000819546578 +%float_0_00124846818 = OpConstant %float 0.00124846818 +%float_0_000252757367 = OpConstant %float 0.000252757367 +%float_0_00152420346 = OpConstant %float 0.00152420346 +%float_0_00112591917 = OpConstant %float 0.00112591917 +%float_0_000359987753 = OpConstant %float 0.000359987753 +%float_n0_000390625006 = OpConstant %float -0.000390625006 +%float_0_00190716912 = OpConstant %float 0.00190716912 +%float_0_00138633582 = OpConstant %float 0.00138633582 +%float_n0_00111060054 = OpConstant %float -0.00111060054 +%float_0_00161611522 = OpConstant %float 0.00161611522 +%float_n0_000880821084 = OpConstant %float -0.000880821084 +%float_0_000145526967 = OpConstant %float 0.000145526967 +%float_0_00107996329 = OpConstant %float 0.00107996329 +%float_n5_36151965en05 = OpConstant %float -5.36151965e-05 +%float_0_00028339462 = OpConstant %float 0.00028339462 +%float_n0_00169270835 = OpConstant %float -0.00169270835 +%float_n0_00126378681 = OpConstant %float -0.00126378681 +%float_n0_000513174047 = OpConstant %float -0.000513174047 +%float_n0_000160845593 = OpConstant %float -0.000160845593 +%float_n0_00187653187 = OpConstant %float -0.00187653187 +%float_n0_000834865205 = OpConstant %float -0.000834865205 +%float_0_00063572306 = OpConstant %float 0.00063572306 +%float_7_65931418en06 = OpConstant %float 7.65931418e-06 +%float_n0_00190716912 = OpConstant %float -0.00190716912 +%float_n0_000222120099 = OpConstant %float -0.000222120099 +%float_0_000375306379 = OpConstant %float 0.000375306379 +%float_n0_00173866423 = OpConstant %float -0.00173866423 +%float_n0_000405943632 = OpConstant %float -0.000405943632 +%float_n0_00123314955 = OpConstant %float -0.00123314955 +%float_0_00170802698 = OpConstant %float 0.00170802698 +%float_n0_00094209559 = OpConstant %float -0.00094209559 +%float_0_000819546578 = OpConstant %float 0.000819546578 +%float_0_00184589461 = OpConstant %float 0.00184589461 +%float_0_000467218139 = OpConstant %float 0.000467218139 + %337 = OpConstantComposite %_arr_float_uint_256 %float_n0_00100337015 %float_0_000880821084 %float_0_00169270835 %float_n0_00155484071 %float_0_00127910543 %float_n0_000605085806 %float_0_00106464466 %float_n0_00138633582 %float_0_00135569857 %float_0_000513174047 %float_0_00121783093 %float_n0_00160079659 %float_0_00058976718 %float_n0_00028339462 %float_0_00111060054 %float_n0_00141697307 %float_0_00144761032 %float_n0_0005438113 %float_0_00013020834 %float_n0_0012025123 %float_0_000436580885 %float_n0_00104932603 %float_0_000620404433 %float_n0_000482536765 %float_0_00187653187 %float_n0_00109528191 %float_n9_95710798en05 %float_n0_000528492674 %float_0_0014322917 %float_n0_00193780637 %float_n0_000696997566 %float_3_829657en05 %float_0_000712316192 %float_n0_00130974269 %float_0_00109528191 %float_n0_000298713247 %float_0_00175398286 %float_n0_00167738972 %float_0_00147824758 %float_n3_829657en05 %float_0_000788909325 %float_n0_00183057599 %float_0_000298713247 %float_0_000988051528 %float_n0_00117187505 %float_0_00017616422 %float_0_00164675247 %float_n0_00158547796 %float_0_000344669126 %float_0_00186121324 %float_n0_00176930148 %float_n0_000865502458 %float_0_000896139711 %float_0_000160845593 %float_n0_000926776964 %float_n0_00152420346 %float_n0_000651041686 %float_0_00129442406 %float_n0_000804227951 %float_n0_00146292895 %float_0_00179993873 %float_n0_000850183831 %float_0_000850183831 %float_n0_000451899512 %float_n0_00106464466 %float_n0_000145526967 %float_0_000237438726 %float_0_00141697307 %float_n0_00058976718 %float_n0_000191482846 %float_0_00160079659 %float_0_00101868878 %float_0_000405943632 %float_n0_000206801473 %float_0_00158547796 %float_0_000651041686 %float_n6_89338267en05 %float_0_000421262259 %float_n0_00164675247 %float_0_00137101719 %float_0_000926776964 %float_n0_000666360313 %float_0_00118719367 %float_n0_00144761032 %float_0_000574448553 %float_n0_00189185049 %float_0_000758272072 %float_n0_00129442406 %float_0_00192248775 %float_n0_0016620711 %float_n0_00103400741 %float_n0_000497855421 %float_n0_00186121324 %float_0_0012025123 %float_n0_0003293505 %float_n0_00137101719 %float_0_00163143384 %float_n0_00184589461 %float_0_000727634819 %float_n0_000911458337 %float_0_00181525736 %float_n0_00114123779 %float_n0_000375306379 %float_9_95710798en05 %float_n0_000742953445 %float_0_00117187505 %float_6_89338267en05 %float_0_0014935662 %float_0_000972732843 %float_n0_000957414217 %float_0_00193780637 %float_0_000528492674 %float_5_36151965en05 %float_n0_00124846818 %float_n0_000268075994 %float_0_00153952208 %float_n7_65931418en06 %float_0_000314031873 %float_0_00134037994 %float_n0_00175398286 %float_0_000497855421 %float_n0_00118719367 %float_0_000773590698 %float_n0_00134037994 %float_0_000268075994 %float_n0_00147824758 %float_n0_00013020834 %float_n0_000773590698 %float_0_00130974269 %float_0_000390625006 %float_0_000957414217 %float_n0_000467218139 %float_n0_00153952208 %float_0_00103400741 %float_n0_000681678939 %float_0_00167738972 %float_0_00100337015 %float_n0_000421262259 %float_0_00178462011 %float_n0_000237438726 %float_n0_000620404433 %float_0_0016620711 %float_0_000834865205 %float_n0_0017233456 %float_n0_00107996329 %float_0_00176930148 %float_n0_000788909325 %float_n0_00178462011 %float_0_000681678939 %float_n0_000988051528 %float_n0_00132506131 %float_n0_00017616422 %float_n0_00150888483 %float_0_0003293505 %float_n0_001953125 %float_0_000666360313 %float_n0_00161611522 %float_0_00115655642 %float_0_000451899512 %float_n0_000436580885 %float_0_000191482846 %float_n0_0014935662 %float_0_00114123779 %float_8_42524532en05 %float_0_00189185049 %float_0_00140165444 %float_0_000559129927 %float_0_000114889706 %float_0_00126378681 %float_n0_000574448553 %float_n0_000972732843 %float_0_00132506131 %float_0_000222120099 %float_n0_000758272072 %float_n0_00135569857 %float_0_00146292895 %float_0_000865502458 %float_n0_000359987753 %float_0_0005438113 %float_n0_00112591917 %float_n0_000252757367 %float_n0_000559129927 %float_n0_00181525736 %float_0_0017233456 %float_n0_00115655642 %float_0_000742953445 %float_0_00157015934 %float_n0_000114889706 %float_n0_00121783093 %float_0_00183057599 %float_2_29779416en05 %float_n0_00192248775 %float_0_00173866423 %float_n0_000712316192 %float_0_00155484071 %float_n0_00170802698 %float_0_00123314955 %float_0_000206801473 %float_0_00104932603 %float_n0_000727634819 %float_n0_00163143384 %float_n0_000314031873 %float_0_000482536765 %float_n0_00179993873 %float_0_00094209559 %float_n0_000344669126 %float_0_000696997566 %float_n0_00101868878 %float_n0_00157015934 %float_n2_29779416en05 %float_n0_00127910543 %float_0_000804227951 %float_n0_000896139711 %float_n0_0014322917 %float_0_000605085806 %float_n8_42524532en05 %float_0_000911458337 %float_0_001953125 %float_n0_00140165444 %float_n0_00063572306 %float_0_00150888483 %float_n0_000819546578 %float_0_00124846818 %float_0_000252757367 %float_0_00152420346 %float_0_00112591917 %float_0_000359987753 %float_n0_000390625006 %float_0_00190716912 %float_0_00138633582 %float_n0_00111060054 %float_0_00161611522 %float_n0_000880821084 %float_0_000145526967 %float_0_00107996329 %float_n5_36151965en05 %float_0_00028339462 %float_n0_00169270835 %float_n0_00126378681 %float_n0_000513174047 %float_n0_000160845593 %float_n0_00187653187 %float_n0_000834865205 %float_0_00063572306 %float_7_65931418en06 %float_n0_00190716912 %float_n0_000222120099 %float_0_000375306379 %float_n0_00173866423 %float_n0_000405943632 %float_n0_00123314955 %float_0_00170802698 %float_n0_00094209559 %float_0_000819546578 %float_0_00184589461 %float_0_000467218139 + %uint_1 = OpConstant %uint 1 + %uint_16 = OpConstant %uint 16 + %uint_0 = OpConstant %uint 0 +%_ptr_Function__arr_float_uint_256 = OpTypePointer Function %_arr_float_uint_256 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %424 = OpTypeImage %float 2D 0 0 0 1 Unknown + %425 = OpTypeSampledImage %424 +%_ptr_UniformConstant_425 = OpTypePointer UniformConstant %425 + %xe_texture = OpVariable %_ptr_UniformConstant_425 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %462 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %469 = OpConstantComposite %v2int %int_1 %int_n1 + %475 = OpConstantComposite %v2int %int_n1 %int_0 + %485 = OpConstantComposite %v2int %int_1 %int_0 + %491 = OpConstantComposite %v2int %int_n1 %int_1 + %497 = OpConstantComposite %v2int %int_0 %int_1 + %503 = OpConstantComposite %v2int %int_1 %int_1 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %992 = OpConstantComposite %v2int %int_2 %int_0 + %1014 = OpConstantComposite %v2int %int_0 %int_2 + %1025 = OpConstantComposite %v2int %int_2 %int_1 + %1031 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasSharpenConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeCasSharpenConstants = OpTypePointer PushConstant %XeCasSharpenConstants + %_ = OpVariable %_ptr_PushConstant_XeCasSharpenConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int + %2497 = OpConstantComposite %v4float %float_1 %float_1 %float_0 %float_0 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %2544 = OpConstantComposite %v3float %float_0 %float_0 %float_0 + %2545 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %uint_3 = OpConstant %uint 3 + %6763 = OpConstantComposite %v2uint %uint_15 %uint_15 + %main = OpFunction %void None %3 + %5 = OpLabel + %6296 = OpVariable %_ptr_Function__arr_float_uint_256 Function + %2485 = OpLoad %v4float %gl_FragCoord + %2486 = OpVectorShuffle %v2float %2485 %2485 0 1 + %2487 = OpConvertFToS %v2int %2486 + %2492 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2493 = OpLoad %v2int %2492 + %2494 = OpISub %v2int %2487 %2493 + %2495 = OpBitcast %v2uint %2494 + %2498 = OpBitcast %v4uint %2497 + %2501 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %2502 = OpLoad %float %2501 + %2503 = OpBitcast %uint %2502 + OpBranch %3056 + %3056 = OpLabel + %3407 = OpConvertUToF %v2float %2495 + %3410 = OpCompositeExtract %uint %2498 0 + %3411 = OpCompositeExtract %uint %2498 1 + %3412 = OpCompositeConstruct %v2uint %3410 %3411 + %3413 = OpBitcast %v2float %3412 + %3414 = OpFMul %v2float %3407 %3413 + %3417 = OpCompositeExtract %uint %2498 2 + %3418 = OpCompositeExtract %uint %2498 3 + %3419 = OpCompositeConstruct %v2uint %3417 %3418 + %3420 = OpBitcast %v2float %3419 + %3421 = OpFAdd %v2float %3414 %3420 + %3423 = OpExtInst %v2float %1 Floor %3421 + %3426 = OpFSub %v2float %3421 %3423 + %3428 = OpConvertFToS %v2int %3423 + %3433 = OpIAdd %v2int %3428 %462 + %5023 = OpLoad %425 %xe_texture + %5025 = OpImage %424 %5023 + %5026 = OpImageFetch %v4float %5025 %3433 Lod %int_0 + %3436 = OpIAdd %v2int %3428 %475 + %5032 = OpImage %424 %5023 + %5033 = OpImageFetch %v4float %5032 %3436 Lod %int_0 + %5039 = OpImage %424 %5023 + %5040 = OpImageFetch %v4float %5039 %3428 Lod %int_0 + %3441 = OpIAdd %v2int %3428 %469 + %5046 = OpImage %424 %5023 + %5047 = OpImageFetch %v4float %5046 %3441 Lod %int_0 + %3447 = OpIAdd %v2int %3428 %485 + %5060 = OpImage %424 %5023 + %5061 = OpImageFetch %v4float %5060 %3447 Lod %int_0 + %3450 = OpIAdd %v2int %3428 %992 + %5067 = OpImage %424 %5023 + %5068 = OpImageFetch %v4float %5067 %3450 Lod %int_0 + %3453 = OpIAdd %v2int %3428 %491 + %5074 = OpImage %424 %5023 + %5075 = OpImageFetch %v4float %5074 %3453 Lod %int_0 + %3456 = OpIAdd %v2int %3428 %497 + %5081 = OpImage %424 %5023 + %5082 = OpImageFetch %v4float %5081 %3456 Lod %int_0 + %3462 = OpIAdd %v2int %3428 %1014 + %5095 = OpImage %424 %5023 + %5096 = OpImageFetch %v4float %5095 %3462 Lod %int_0 + %3465 = OpIAdd %v2int %3428 %503 + %5102 = OpImage %424 %5023 + %5103 = OpImageFetch %v4float %5102 %3465 Lod %int_0 + %3468 = OpIAdd %v2int %3428 %1025 + %5109 = OpImage %424 %5023 + %5110 = OpImageFetch %v4float %5109 %3468 Lod %int_0 + %3471 = OpIAdd %v2int %3428 %1031 + %5116 = OpImage %424 %5023 + %5117 = OpImageFetch %v4float %5116 %3471 Lod %int_0 + %3490 = OpCompositeExtract %float %5026 0 + %3492 = OpCompositeExtract %float %5026 1 + %3494 = OpCompositeExtract %float %5026 2 + %5139 = OpFMul %float %3490 %3490 + %5142 = OpFMul %float %3492 %3492 + %5145 = OpFMul %float %3494 %3494 + %3503 = OpCompositeExtract %float %5047 0 + %3505 = OpCompositeExtract %float %5047 1 + %3507 = OpCompositeExtract %float %5047 2 + %5149 = OpFMul %float %3503 %3503 + %5152 = OpFMul %float %3505 %3505 + %5155 = OpFMul %float %3507 %3507 + %3529 = OpCompositeExtract %float %5033 0 + %3531 = OpCompositeExtract %float %5033 1 + %3533 = OpCompositeExtract %float %5033 2 + %5169 = OpFMul %float %3529 %3529 + %5172 = OpFMul %float %3531 %3531 + %5175 = OpFMul %float %3533 %3533 + %3542 = OpCompositeExtract %float %5040 0 + %3544 = OpCompositeExtract %float %5040 1 + %3546 = OpCompositeExtract %float %5040 2 + %5179 = OpFMul %float %3542 %3542 + %5182 = OpFMul %float %3544 %3544 + %5185 = OpFMul %float %3546 %3546 + %3555 = OpCompositeExtract %float %5061 0 + %3557 = OpCompositeExtract %float %5061 1 + %3559 = OpCompositeExtract %float %5061 2 + %5189 = OpFMul %float %3555 %3555 + %5192 = OpFMul %float %3557 %3557 + %5195 = OpFMul %float %3559 %3559 + %3568 = OpCompositeExtract %float %5068 0 + %3570 = OpCompositeExtract %float %5068 1 + %3572 = OpCompositeExtract %float %5068 2 + %5199 = OpFMul %float %3568 %3568 + %5202 = OpFMul %float %3570 %3570 + %5205 = OpFMul %float %3572 %3572 + %3581 = OpCompositeExtract %float %5075 0 + %3583 = OpCompositeExtract %float %5075 1 + %3585 = OpCompositeExtract %float %5075 2 + %5209 = OpFMul %float %3581 %3581 + %5212 = OpFMul %float %3583 %3583 + %5215 = OpFMul %float %3585 %3585 + %3594 = OpCompositeExtract %float %5082 0 + %3596 = OpCompositeExtract %float %5082 1 + %3598 = OpCompositeExtract %float %5082 2 + %5219 = OpFMul %float %3594 %3594 + %5222 = OpFMul %float %3596 %3596 + %5225 = OpFMul %float %3598 %3598 + %3607 = OpCompositeExtract %float %5103 0 + %3609 = OpCompositeExtract %float %5103 1 + %3611 = OpCompositeExtract %float %5103 2 + %5229 = OpFMul %float %3607 %3607 + %5232 = OpFMul %float %3609 %3609 + %5235 = OpFMul %float %3611 %3611 + %3620 = OpCompositeExtract %float %5110 0 + %3622 = OpCompositeExtract %float %5110 1 + %3624 = OpCompositeExtract %float %5110 2 + %5239 = OpFMul %float %3620 %3620 + %5242 = OpFMul %float %3622 %3622 + %5245 = OpFMul %float %3624 %3624 + %3646 = OpCompositeExtract %float %5096 0 + %3648 = OpCompositeExtract %float %5096 1 + %3650 = OpCompositeExtract %float %5096 2 + %5259 = OpFMul %float %3646 %3646 + %5262 = OpFMul %float %3648 %3648 + %5265 = OpFMul %float %3650 %3650 + %3659 = OpCompositeExtract %float %5117 0 + %3661 = OpCompositeExtract %float %5117 1 + %3663 = OpCompositeExtract %float %5117 2 + %5269 = OpFMul %float %3659 %3659 + %5272 = OpFMul %float %3661 %3661 + %5275 = OpFMul %float %3663 %3663 + %5305 = OpExtInst %float %1 FMin %5172 %5182 + %5306 = OpExtInst %float %1 FMin %5142 %5305 + %5312 = OpExtInst %float %1 FMin %5192 %5222 + %5313 = OpExtInst %float %1 FMin %5306 %5312 + %5347 = OpExtInst %float %1 FMax %5172 %5182 + %5348 = OpExtInst %float %1 FMax %5142 %5347 + %5354 = OpExtInst %float %1 FMax %5192 %5222 + %5355 = OpExtInst %float %1 FMax %5348 %5354 + %5389 = OpExtInst %float %1 FMin %5182 %5192 + %5390 = OpExtInst %float %1 FMin %5152 %5389 + %5396 = OpExtInst %float %1 FMin %5202 %5232 + %5397 = OpExtInst %float %1 FMin %5390 %5396 + %5431 = OpExtInst %float %1 FMax %5182 %5192 + %5432 = OpExtInst %float %1 FMax %5152 %5431 + %5438 = OpExtInst %float %1 FMax %5202 %5232 + %5439 = OpExtInst %float %1 FMax %5432 %5438 + %5473 = OpExtInst %float %1 FMin %5212 %5222 + %5474 = OpExtInst %float %1 FMin %5182 %5473 + %5480 = OpExtInst %float %1 FMin %5232 %5262 + %5481 = OpExtInst %float %1 FMin %5474 %5480 + %5515 = OpExtInst %float %1 FMax %5212 %5222 + %5516 = OpExtInst %float %1 FMax %5182 %5515 + %5522 = OpExtInst %float %1 FMax %5232 %5262 + %5523 = OpExtInst %float %1 FMax %5516 %5522 + %5557 = OpExtInst %float %1 FMin %5222 %5232 + %5558 = OpExtInst %float %1 FMin %5192 %5557 + %5564 = OpExtInst %float %1 FMin %5242 %5272 + %5565 = OpExtInst %float %1 FMin %5558 %5564 + %5599 = OpExtInst %float %1 FMax %5222 %5232 + %5600 = OpExtInst %float %1 FMax %5192 %5599 + %5606 = OpExtInst %float %1 FMax %5242 %5272 + %5607 = OpExtInst %float %1 FMax %5600 %5606 + %5638 = OpBitcast %uint %5355 + %5639 = OpISub %uint %uint_2129690299 %5638 + %5640 = OpBitcast %float %5639 + %5671 = OpBitcast %uint %5439 + %5672 = OpISub %uint %uint_2129690299 %5671 + %5673 = OpBitcast %float %5672 + %5704 = OpBitcast %uint %5523 + %5705 = OpISub %uint %uint_2129690299 %5704 + %5706 = OpBitcast %float %5705 + %5737 = OpBitcast %uint %5607 + %5738 = OpISub %uint %uint_2129690299 %5737 + %5739 = OpBitcast %float %5738 + %4007 = OpFSub %float %float_1 %5355 + %4008 = OpExtInst %float %1 FMin %5313 %4007 + %4010 = OpFMul %float %4008 %5640 + %5781 = OpExtInst %float %1 FClamp %4010 %float_0 %float_1 + %4031 = OpFSub %float %float_1 %5439 + %4032 = OpExtInst %float %1 FMin %5397 %4031 + %4034 = OpFMul %float %4032 %5673 + %5832 = OpExtInst %float %1 FClamp %4034 %float_0 %float_1 + %4055 = OpFSub %float %float_1 %5523 + %4056 = OpExtInst %float %1 FMin %5481 %4055 + %4058 = OpFMul %float %4056 %5706 + %5883 = OpExtInst %float %1 FClamp %4058 %float_0 %float_1 + %4079 = OpFSub %float %float_1 %5607 + %4080 = OpExtInst %float %1 FMin %5565 %4079 + %4082 = OpFMul %float %4080 %5739 + %5934 = OpExtInst %float %1 FClamp %4082 %float_0 %float_1 + %5980 = OpBitcast %uint %5781 + %5982 = OpShiftRightLogical %uint %5980 %uint_1 + %5984 = OpIAdd %uint %5982 %uint_532432441 + %5985 = OpBitcast %float %5984 + %6031 = OpBitcast %uint %5832 + %6033 = OpShiftRightLogical %uint %6031 %uint_1 + %6035 = OpIAdd %uint %6033 %uint_532432441 + %6036 = OpBitcast %float %6035 + %6082 = OpBitcast %uint %5883 + %6084 = OpShiftRightLogical %uint %6082 %uint_1 + %6086 = OpIAdd %uint %6084 %uint_532432441 + %6087 = OpBitcast %float %6086 + %6133 = OpBitcast %uint %5934 + %6135 = OpShiftRightLogical %uint %6133 %uint_1 + %6137 = OpIAdd %uint %6135 %uint_532432441 + %6138 = OpBitcast %float %6137 + %4118 = OpBitcast %float %2503 + %4124 = OpFMul %float %5985 %4118 + %4133 = OpFMul %float %6036 %4118 + %4142 = OpFMul %float %6087 %4118 + %4151 = OpFMul %float %6138 %4118 + %4157 = OpCompositeExtract %float %3426 0 + %4158 = OpFSub %float %float_1 %4157 + %4161 = OpCompositeExtract %float %3426 1 + %4162 = OpFSub %float %float_1 %4161 + %4163 = OpFMul %float %4158 %4162 + %4170 = OpFMul %float %4157 %4162 + %4177 = OpFMul %float %4158 %4161 + %4182 = OpFMul %float %4157 %4161 + %4186 = OpFSub %float %5355 %5313 + %4187 = OpFAdd %float %float_0_03125 %4186 + %6179 = OpBitcast %uint %4187 + %6180 = OpISub %uint %uint_2129690299 %6179 + %6181 = OpBitcast %float %6180 + %4190 = OpFMul %float %4163 %6181 + %4194 = OpFSub %float %5439 %5397 + %4195 = OpFAdd %float %float_0_03125 %4194 + %6190 = OpBitcast %uint %4195 + %6191 = OpISub %uint %uint_2129690299 %6190 + %6192 = OpBitcast %float %6191 + %4198 = OpFMul %float %4170 %6192 + %4202 = OpFSub %float %5523 %5481 + %4203 = OpFAdd %float %float_0_03125 %4202 + %6201 = OpBitcast %uint %4203 + %6202 = OpISub %uint %uint_2129690299 %6201 + %6203 = OpBitcast %float %6202 + %4206 = OpFMul %float %4177 %6203 + %4210 = OpFSub %float %5607 %5565 + %4211 = OpFAdd %float %float_0_03125 %4210 + %6212 = OpBitcast %uint %4211 + %6213 = OpISub %uint %uint_2129690299 %6212 + %6214 = OpBitcast %float %6213 + %4214 = OpFMul %float %4182 %6214 + %4220 = OpFMul %float %4124 %4190 + %4229 = OpFMul %float %4133 %4198 + %4247 = OpFMul %float %4142 %4206 + %4248 = OpFAdd %float %4229 %4247 + %4250 = OpFAdd %float %4248 %4190 + %4274 = OpFMul %float %4151 %4214 + %4275 = OpFAdd %float %4220 %4274 + %4277 = OpFAdd %float %4275 %4198 + %4304 = OpFAdd %float %4275 %4206 + %4331 = OpFAdd %float %4248 %4214 + %6748 = OpFAdd %float %4220 %4229 + %6749 = OpFAdd %float %6748 %4247 + %6750 = OpFAdd %float %6749 %4274 + %4373 = OpFMul %float %float_2 %6750 + %4375 = OpFAdd %float %4373 %4250 + %4377 = OpFAdd %float %4375 %4277 + %4379 = OpFAdd %float %4377 %4304 + %4381 = OpFAdd %float %4379 %4331 + %6237 = OpBitcast %uint %4381 + %6238 = OpISub %uint %uint_2129764351 %6237 + %6239 = OpBitcast %float %6238 + %6242 = OpFNegate %float %6239 + %6244 = OpFMul %float %6242 %4381 + %6246 = OpFAdd %float %6244 %float_2 + %6247 = OpFMul %float %6239 %6246 + %6751 = OpFAdd %float %5139 %5169 + %4391 = OpFMul %float %4220 %6751 + %4395 = OpFMul %float %5149 %4229 + %4396 = OpFAdd %float %4391 %4395 + %4400 = OpFMul %float %5199 %4229 + %4401 = OpFAdd %float %4396 %4400 + %4405 = OpFMul %float %5209 %4247 + %4406 = OpFAdd %float %4401 %4405 + %4410 = OpFMul %float %5259 %4247 + %4411 = OpFAdd %float %4406 %4410 + %4415 = OpFMul %float %5239 %4274 + %4416 = OpFAdd %float %4411 %4415 + %4420 = OpFMul %float %5269 %4274 + %4421 = OpFAdd %float %4416 %4420 + %4425 = OpFMul %float %5179 %4250 + %4426 = OpFAdd %float %4421 %4425 + %4430 = OpFMul %float %5189 %4277 + %4431 = OpFAdd %float %4426 %4430 + %4435 = OpFMul %float %5219 %4304 + %4436 = OpFAdd %float %4431 %4435 + %4440 = OpFMul %float %5229 %4331 + %4441 = OpFAdd %float %4436 %4440 + %4443 = OpFMul %float %4441 %6247 + %6261 = OpExtInst %float %1 FClamp %4443 %float_0 %float_1 + %6752 = OpFAdd %float %5142 %5172 + %4453 = OpFMul %float %4220 %6752 + %4457 = OpFMul %float %5152 %4229 + %4458 = OpFAdd %float %4453 %4457 + %4462 = OpFMul %float %5202 %4229 + %4463 = OpFAdd %float %4458 %4462 + %4467 = OpFMul %float %5212 %4247 + %4468 = OpFAdd %float %4463 %4467 + %4472 = OpFMul %float %5262 %4247 + %4473 = OpFAdd %float %4468 %4472 + %4477 = OpFMul %float %5242 %4274 + %4478 = OpFAdd %float %4473 %4477 + %4482 = OpFMul %float %5272 %4274 + %4483 = OpFAdd %float %4478 %4482 + %4487 = OpFMul %float %5182 %4250 + %4488 = OpFAdd %float %4483 %4487 + %4492 = OpFMul %float %5192 %4277 + %4493 = OpFAdd %float %4488 %4492 + %4497 = OpFMul %float %5222 %4304 + %4498 = OpFAdd %float %4493 %4497 + %4502 = OpFMul %float %5232 %4331 + %4503 = OpFAdd %float %4498 %4502 + %4505 = OpFMul %float %4503 %6247 + %6275 = OpExtInst %float %1 FClamp %4505 %float_0 %float_1 + %6753 = OpFAdd %float %5145 %5175 + %4515 = OpFMul %float %4220 %6753 + %4519 = OpFMul %float %5155 %4229 + %4520 = OpFAdd %float %4515 %4519 + %4524 = OpFMul %float %5205 %4229 + %4525 = OpFAdd %float %4520 %4524 + %4529 = OpFMul %float %5215 %4247 + %4530 = OpFAdd %float %4525 %4529 + %4534 = OpFMul %float %5265 %4247 + %4535 = OpFAdd %float %4530 %4534 + %4539 = OpFMul %float %5245 %4274 + %4540 = OpFAdd %float %4535 %4539 + %4544 = OpFMul %float %5275 %4274 + %4545 = OpFAdd %float %4540 %4544 + %4549 = OpFMul %float %5185 %4250 + %4550 = OpFAdd %float %4545 %4549 + %4554 = OpFMul %float %5195 %4277 + %4555 = OpFAdd %float %4550 %4554 + %4559 = OpFMul %float %5225 %4304 + %4560 = OpFAdd %float %4555 %4559 + %4564 = OpFMul %float %5235 %4331 + %4565 = OpFAdd %float %4560 %4564 + %4567 = OpFMul %float %4565 %6247 + %6289 = OpExtInst %float %1 FClamp %4567 %float_0 %float_1 + %2527 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2527 %6261 + %2529 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2529 %6275 + %2531 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2531 %6289 + %2532 = OpLoad %v4float %xe_frag_color + %2533 = OpVectorShuffle %v3float %2532 %2532 0 1 2 + %2534 = OpExtInst %v3float %1 Sqrt %2533 + %2535 = OpLoad %v4float %xe_frag_color + %2536 = OpVectorShuffle %v4float %2535 %2534 4 5 6 3 + OpStore %xe_frag_color %2536 + %2537 = OpLoad %v4float %xe_frag_color + %2538 = OpVectorShuffle %v3float %2537 %2537 0 1 2 + %6301 = OpBitwiseAnd %v2uint %2495 %6763 + %6303 = OpCompositeExtract %uint %6301 1 + %6304 = OpIMul %uint %6303 %uint_16 + %6306 = OpCompositeExtract %uint %6301 0 + %6307 = OpIAdd %uint %6304 %6306 + OpStore %6296 %337 + %6308 = OpAccessChain %_ptr_Function_float %6296 %6307 + %6309 = OpLoad %float %6308 + %2542 = OpCompositeConstruct %v3float %6309 %6309 %6309 + %2543 = OpFAdd %v3float %2538 %2542 + %2546 = OpExtInst %v3float %1 FClamp %2543 %2544 %2545 + %2547 = OpLoad %v4float %xe_frag_color + %2548 = OpVectorShuffle %v4float %2547 %2546 4 5 6 3 + OpStore %xe_frag_color %2548 + %2550 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2550 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h new file mode 100644 index 000000000..225d5e0e3 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h @@ -0,0 +1,741 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_cas_sharpen.frag +const uint8_t guest_output_ffx_cas_sharpen_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2E, 0x19, 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, + 0x9C, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x92, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x9C, 0x08, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x58, 0x65, 0x43, 0x61, 0x73, 0x53, 0x68, 0x61, + 0x72, 0x70, 0x65, 0x6E, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, + 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x6F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x61, 0x73, 0x5F, 0x73, + 0x68, 0x61, 0x72, 0x70, 0x6E, 0x65, 0x73, 0x73, 0x5F, 0x70, 0x6F, 0x73, + 0x74, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x70, 0x00, 0x05, 0x00, 0x03, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, + 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x92, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x9C, 0x08, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xA0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xA0, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xB8, 0x08, 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, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x39, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, + 0x39, 0x46, 0xBC, 0x1F, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF1, 0x7E, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x19, 0x00, 0x09, 0x00, 0x8F, 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, 0x90, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x91, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xCC, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xC8, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xEF, 0x02, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3D, 0x20, 0x00, 0x04, 0x00, 0x9B, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x9B, 0x08, 0x00, 0x00, 0x9C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x04, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0xA1, 0x08, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0xA1, 0x08, 0x00, 0x00, 0xA2, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xA3, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xA9, 0x08, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xAC, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xB7, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xB7, 0x08, 0x00, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xC6, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xD1, 0x08, 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, 0x3D, 0x00, 0x04, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, 0x9C, 0x08, 0x00, 0x00, + 0x4F, 0x00, 0x07, 0x00, 0x86, 0x02, 0x00, 0x00, 0x9E, 0x08, 0x00, 0x00, + 0x9D, 0x08, 0x00, 0x00, 0x9D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x9F, 0x08, 0x00, 0x00, 0x9E, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xA3, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, 0xA2, 0x08, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0xA5, 0x08, 0x00, 0x00, 0xA4, 0x08, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, 0x9F, 0x08, 0x00, 0x00, + 0xA5, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xA7, 0x08, 0x00, 0x00, 0xA6, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x39, 0x00, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, 0xA9, 0x08, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xAC, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0xA2, 0x08, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAE, 0x08, 0x00, 0x00, 0xAD, 0x08, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xAF, 0x08, 0x00, 0x00, + 0xAE, 0x08, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xCC, 0x0A, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xCC, 0x0A, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x86, 0x02, 0x00, 0x00, 0x2B, 0x0C, 0x00, 0x00, 0xA7, 0x08, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2E, 0x0C, 0x00, 0x00, + 0xAA, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2F, 0x0C, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x30, 0x0C, 0x00, 0x00, 0x2E, 0x0C, 0x00, 0x00, 0x2F, 0x0C, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x31, 0x0C, 0x00, 0x00, + 0x30, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x32, 0x0C, 0x00, 0x00, 0x2B, 0x0C, 0x00, 0x00, 0x31, 0x0C, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x00, + 0xAA, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x36, 0x0C, 0x00, 0x00, 0xAA, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x37, 0x0C, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x00, 0x36, 0x0C, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x86, 0x02, 0x00, 0x00, 0x38, 0x0C, 0x00, 0x00, + 0x37, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x39, 0x0C, 0x00, 0x00, 0x32, 0x0C, 0x00, 0x00, 0x38, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x86, 0x02, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x39, 0x0C, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x86, 0x02, 0x00, 0x00, 0x3E, 0x0C, 0x00, 0x00, + 0x39, 0x0C, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x04, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x3B, 0x0C, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x45, 0x0C, 0x00, 0x00, + 0x40, 0x0C, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x7D, 0x12, 0x00, 0x00, + 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x7E, 0x12, 0x00, 0x00, 0x7D, 0x12, 0x00, 0x00, 0x45, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x48, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0xC2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x84, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x85, 0x12, 0x00, 0x00, 0x84, 0x12, 0x00, 0x00, + 0x48, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x8B, 0x12, 0x00, 0x00, + 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x8B, 0x12, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x4D, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0x92, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0x93, 0x12, 0x00, 0x00, 0x92, 0x12, 0x00, 0x00, + 0x4D, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, + 0x40, 0x0C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xA1, 0x12, 0x00, 0x00, + 0xA0, 0x12, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x56, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0xC8, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xA7, 0x12, 0x00, 0x00, + 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xA8, 0x12, 0x00, 0x00, 0xA7, 0x12, 0x00, 0x00, 0x56, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x59, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0xD2, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xAE, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xAF, 0x12, 0x00, 0x00, 0xAE, 0x12, 0x00, 0x00, + 0x59, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, + 0x40, 0x0C, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xB5, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, + 0xB5, 0x12, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x62, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0xDE, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x00, 0x00, + 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xC4, 0x12, 0x00, 0x00, 0xC3, 0x12, 0x00, 0x00, 0x62, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x65, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0xDE, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, + 0xCA, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, 0xCA, 0x12, 0x00, 0x00, + 0x65, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, + 0x40, 0x0C, 0x00, 0x00, 0xE9, 0x02, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, + 0x8F, 0x00, 0x00, 0x00, 0xD1, 0x12, 0x00, 0x00, 0x7B, 0x12, 0x00, 0x00, + 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, 0xD2, 0x12, 0x00, 0x00, + 0xD1, 0x12, 0x00, 0x00, 0x68, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x6B, 0x0C, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0xEF, 0x02, 0x00, 0x00, + 0x64, 0x00, 0x04, 0x00, 0x8F, 0x00, 0x00, 0x00, 0xD8, 0x12, 0x00, 0x00, + 0x7B, 0x12, 0x00, 0x00, 0x5F, 0x00, 0x07, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xD9, 0x12, 0x00, 0x00, 0xD8, 0x12, 0x00, 0x00, 0x6B, 0x0C, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7E, 0x0C, 0x00, 0x00, 0x7E, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x80, 0x0C, 0x00, 0x00, 0x7E, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x0C, 0x00, 0x00, + 0x7E, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEF, 0x12, 0x00, 0x00, 0x7E, 0x0C, 0x00, 0x00, + 0x7E, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF2, 0x12, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF5, 0x12, 0x00, 0x00, + 0x82, 0x0C, 0x00, 0x00, 0x82, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8B, 0x0C, 0x00, 0x00, 0x93, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8D, 0x0C, 0x00, 0x00, 0x93, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, + 0x93, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF9, 0x12, 0x00, 0x00, 0x8B, 0x0C, 0x00, 0x00, + 0x8B, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFC, 0x12, 0x00, 0x00, 0x8D, 0x0C, 0x00, 0x00, 0x8D, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0x12, 0x00, 0x00, + 0x8F, 0x0C, 0x00, 0x00, 0x8F, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA5, 0x0C, 0x00, 0x00, 0x85, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA7, 0x0C, 0x00, 0x00, 0x85, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x00, + 0x85, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0D, 0x13, 0x00, 0x00, 0xA5, 0x0C, 0x00, 0x00, + 0xA5, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x10, 0x13, 0x00, 0x00, 0xA7, 0x0C, 0x00, 0x00, 0xA7, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, + 0xA9, 0x0C, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB2, 0x0C, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB4, 0x0C, 0x00, 0x00, 0x8C, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, + 0x8C, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x17, 0x13, 0x00, 0x00, 0xB2, 0x0C, 0x00, 0x00, + 0xB2, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1A, 0x13, 0x00, 0x00, 0xB4, 0x0C, 0x00, 0x00, 0xB4, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x13, 0x00, 0x00, + 0xB6, 0x0C, 0x00, 0x00, 0xB6, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBF, 0x0C, 0x00, 0x00, 0xA1, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC1, 0x0C, 0x00, 0x00, 0xA1, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0xA1, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x21, 0x13, 0x00, 0x00, 0xBF, 0x0C, 0x00, 0x00, + 0xBF, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x13, 0x00, 0x00, 0xC1, 0x0C, 0x00, 0x00, 0xC1, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x13, 0x00, 0x00, + 0xC3, 0x0C, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCC, 0x0C, 0x00, 0x00, 0xA8, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCE, 0x0C, 0x00, 0x00, 0xA8, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, + 0xA8, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x13, 0x00, 0x00, 0xCC, 0x0C, 0x00, 0x00, + 0xCC, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2E, 0x13, 0x00, 0x00, 0xCE, 0x0C, 0x00, 0x00, 0xCE, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x31, 0x13, 0x00, 0x00, + 0xD0, 0x0C, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD9, 0x0C, 0x00, 0x00, 0xAF, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDB, 0x0C, 0x00, 0x00, 0xAF, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, + 0xAF, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, 0xD9, 0x0C, 0x00, 0x00, + 0xD9, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x38, 0x13, 0x00, 0x00, 0xDB, 0x0C, 0x00, 0x00, 0xDB, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x13, 0x00, 0x00, + 0xDD, 0x0C, 0x00, 0x00, 0xDD, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE6, 0x0C, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE8, 0x0C, 0x00, 0x00, 0xB6, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, + 0xB6, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3F, 0x13, 0x00, 0x00, 0xE6, 0x0C, 0x00, 0x00, + 0xE6, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x13, 0x00, 0x00, 0xE8, 0x0C, 0x00, 0x00, 0xE8, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x13, 0x00, 0x00, + 0xEA, 0x0C, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF5, 0x0C, 0x00, 0x00, 0xCB, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, + 0xCB, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, 0xF3, 0x0C, 0x00, 0x00, + 0xF3, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4C, 0x13, 0x00, 0x00, 0xF5, 0x0C, 0x00, 0x00, 0xF5, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x13, 0x00, 0x00, + 0xF7, 0x0C, 0x00, 0x00, 0xF7, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0xD2, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x0D, 0x00, 0x00, 0xD2, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, + 0xD2, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x53, 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, + 0x00, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x56, 0x13, 0x00, 0x00, 0x02, 0x0D, 0x00, 0x00, 0x02, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x13, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xC4, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1C, 0x0D, 0x00, 0x00, 0xC4, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, + 0xC4, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x67, 0x13, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, + 0x1A, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6A, 0x13, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, 0x1C, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x13, 0x00, 0x00, + 0x1E, 0x0D, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x27, 0x0D, 0x00, 0x00, 0xD9, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x29, 0x0D, 0x00, 0x00, 0xD9, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, + 0xD9, 0x12, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x71, 0x13, 0x00, 0x00, 0x27, 0x0D, 0x00, 0x00, + 0x27, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x74, 0x13, 0x00, 0x00, 0x29, 0x0D, 0x00, 0x00, 0x29, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x77, 0x13, 0x00, 0x00, + 0x2B, 0x0D, 0x00, 0x00, 0x2B, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x95, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, 0x1A, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x00, 0x00, + 0x95, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9C, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x24, 0x13, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9D, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x96, 0x13, 0x00, 0x00, 0x9C, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBF, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, + 0x1A, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xF2, 0x12, 0x00, 0x00, 0xBF, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC6, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xC0, 0x13, 0x00, 0x00, + 0xC6, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE9, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1A, 0x13, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEA, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xFC, 0x12, 0x00, 0x00, 0xE9, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF0, 0x13, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2E, 0x13, 0x00, 0x00, + 0x4C, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF1, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xEA, 0x13, 0x00, 0x00, 0xF0, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1A, 0x13, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xFC, 0x12, 0x00, 0x00, + 0x13, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1A, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x2E, 0x13, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x1A, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3D, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x38, 0x13, 0x00, 0x00, + 0x42, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3E, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1A, 0x13, 0x00, 0x00, 0x3D, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x44, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, 0x6A, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3E, 0x14, 0x00, 0x00, + 0x44, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x38, 0x13, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x68, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1A, 0x13, 0x00, 0x00, 0x67, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, + 0x6A, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6F, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x68, 0x14, 0x00, 0x00, 0x6E, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x91, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x92, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x13, 0x00, 0x00, + 0x91, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x98, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x56, 0x13, 0x00, 0x00, 0x74, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x99, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x92, 0x14, 0x00, 0x00, 0x98, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x4C, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBC, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x24, 0x13, 0x00, 0x00, 0xBB, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC2, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x56, 0x13, 0x00, 0x00, 0x74, 0x13, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x14, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xBC, 0x14, 0x00, 0x00, + 0xC2, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE2, 0x14, 0x00, 0x00, 0xC7, 0x13, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x14, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xE2, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE4, 0x14, 0x00, 0x00, 0xE3, 0x14, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x1B, 0x14, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x24, 0x15, 0x00, 0x00, + 0x6F, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x25, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x24, 0x15, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, + 0x25, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x45, 0x15, 0x00, 0x00, 0xC3, 0x14, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x45, 0x15, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x47, 0x15, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x83, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xC7, 0x13, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x9D, 0x13, 0x00, 0x00, 0x83, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x86, 0x0E, 0x00, 0x00, 0x84, 0x0E, 0x00, 0x00, + 0xE4, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x71, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x86, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9B, 0x0E, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x1B, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xF1, 0x13, 0x00, 0x00, 0x9B, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9E, 0x0E, 0x00, 0x00, + 0x9C, 0x0E, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x9E, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB3, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x6F, 0x14, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, + 0xB3, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB6, 0x0E, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, 0x26, 0x15, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xB6, 0x0E, 0x00, 0x00, + 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCB, 0x0E, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0xC3, 0x14, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCC, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x99, 0x14, 0x00, 0x00, 0xCB, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCE, 0x0E, 0x00, 0x00, 0xCC, 0x0E, 0x00, 0x00, + 0x47, 0x15, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xCE, 0x0E, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x16, 0x00, 0x00, + 0x71, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x3A, 0x16, 0x00, 0x00, 0x38, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, + 0x3A, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3D, 0x16, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6B, 0x16, 0x00, 0x00, + 0xA4, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x6D, 0x16, 0x00, 0x00, 0x6B, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6F, 0x16, 0x00, 0x00, + 0x6D, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x70, 0x16, 0x00, 0x00, 0x6F, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x9E, 0x16, 0x00, 0x00, + 0xD7, 0x15, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA0, 0x16, 0x00, 0x00, 0x9E, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xA2, 0x16, 0x00, 0x00, + 0xA0, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA3, 0x16, 0x00, 0x00, 0xA2, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xD1, 0x16, 0x00, 0x00, + 0x0A, 0x16, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD3, 0x16, 0x00, 0x00, 0xD1, 0x16, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xD5, 0x16, 0x00, 0x00, + 0xD3, 0x16, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD6, 0x16, 0x00, 0x00, 0xD5, 0x16, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x0E, 0x00, 0x00, + 0xAF, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF8, 0x0E, 0x00, 0x00, 0x3D, 0x16, 0x00, 0x00, 0xF2, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, 0x00, + 0x70, 0x16, 0x00, 0x00, 0xF2, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x0F, 0x00, 0x00, 0xA3, 0x16, 0x00, 0x00, + 0xF2, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x13, 0x0F, 0x00, 0x00, 0xD6, 0x16, 0x00, 0x00, 0xF2, 0x0E, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x0F, 0x00, 0x00, + 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1A, 0x0F, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x19, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1D, 0x0F, 0x00, 0x00, 0x3E, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x00, 0x00, 0x1A, 0x0F, 0x00, 0x00, + 0x1E, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x0F, 0x00, 0x00, 0x19, 0x0F, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2D, 0x0F, 0x00, 0x00, + 0x1A, 0x0F, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x32, 0x0F, 0x00, 0x00, 0x19, 0x0F, 0x00, 0x00, + 0x1D, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x36, 0x0F, 0x00, 0x00, 0xC7, 0x13, 0x00, 0x00, 0x9D, 0x13, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x36, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xFF, 0x16, 0x00, 0x00, 0x37, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0xFF, 0x16, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3A, 0x0F, 0x00, 0x00, + 0x1F, 0x0F, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, 0x1B, 0x14, 0x00, 0x00, + 0xF1, 0x13, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3F, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x3E, 0x0F, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x00, 0x00, + 0x3F, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0B, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x17, 0x00, 0x00, + 0x0B, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x42, 0x0F, 0x00, 0x00, 0x26, 0x0F, 0x00, 0x00, 0x0C, 0x17, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x0F, 0x00, 0x00, + 0x6F, 0x14, 0x00, 0x00, 0x45, 0x14, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x0F, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, + 0x46, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x15, 0x17, 0x00, 0x00, 0x47, 0x0F, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x15, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x17, 0x17, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4A, 0x0F, 0x00, 0x00, 0x2D, 0x0F, 0x00, 0x00, + 0x17, 0x17, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4E, 0x0F, 0x00, 0x00, 0xC3, 0x14, 0x00, 0x00, 0x99, 0x14, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x4E, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x20, 0x17, 0x00, 0x00, 0x4F, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x21, 0x17, 0x00, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x20, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x17, 0x00, 0x00, 0x21, 0x17, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x0F, 0x00, 0x00, + 0x32, 0x0F, 0x00, 0x00, 0x22, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x58, 0x0F, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, + 0x3A, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x61, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, + 0x0A, 0x0F, 0x00, 0x00, 0x4A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x0F, 0x00, 0x00, 0x61, 0x0F, 0x00, 0x00, + 0x73, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x74, 0x0F, 0x00, 0x00, 0x3A, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, + 0x13, 0x0F, 0x00, 0x00, 0x52, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0F, 0x00, 0x00, 0x58, 0x0F, 0x00, 0x00, + 0x8E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x91, 0x0F, 0x00, 0x00, 0x8F, 0x0F, 0x00, 0x00, 0x42, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAC, 0x0F, 0x00, 0x00, + 0x8F, 0x0F, 0x00, 0x00, 0x4A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0F, 0x00, 0x00, 0x74, 0x0F, 0x00, 0x00, + 0x52, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x19, 0x00, 0x00, 0x58, 0x0F, 0x00, 0x00, 0x61, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x19, 0x00, 0x00, + 0x28, 0x19, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2A, 0x19, 0x00, 0x00, 0x29, 0x19, 0x00, 0x00, + 0x8E, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF1, 0x0F, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x2A, 0x19, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, + 0xF1, 0x0F, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF5, 0x0F, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, + 0x91, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF7, 0x0F, 0x00, 0x00, 0xF5, 0x0F, 0x00, 0x00, 0xAC, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF9, 0x0F, 0x00, 0x00, + 0xF7, 0x0F, 0x00, 0x00, 0xC7, 0x0F, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x39, 0x17, 0x00, 0x00, 0xF9, 0x0F, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3A, 0x17, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x39, 0x17, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3B, 0x17, 0x00, 0x00, 0x3A, 0x17, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x17, 0x00, 0x00, + 0x3B, 0x17, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x40, 0x17, 0x00, 0x00, 0x3E, 0x17, 0x00, 0x00, 0xF9, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x42, 0x17, 0x00, 0x00, + 0x40, 0x17, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x43, 0x17, 0x00, 0x00, 0x3B, 0x17, 0x00, 0x00, + 0x42, 0x17, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x19, 0x00, 0x00, 0xEF, 0x12, 0x00, 0x00, 0x0D, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, + 0x58, 0x0F, 0x00, 0x00, 0x2B, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0xF9, 0x12, 0x00, 0x00, + 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x10, 0x00, 0x00, + 0x2B, 0x13, 0x00, 0x00, 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0D, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, + 0x0C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x11, 0x10, 0x00, 0x00, 0x35, 0x13, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, + 0x0D, 0x10, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x67, 0x13, 0x00, 0x00, + 0x73, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x17, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x16, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1B, 0x10, 0x00, 0x00, + 0x53, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, + 0x1B, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x10, 0x00, 0x00, 0x71, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, + 0x1C, 0x10, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x17, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x10, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x10, 0x00, 0x00, + 0x21, 0x13, 0x00, 0x00, 0x91, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x10, 0x00, 0x00, 0x26, 0x10, 0x00, 0x00, + 0x2A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2F, 0x10, 0x00, 0x00, 0x3F, 0x13, 0x00, 0x00, 0xAC, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, + 0x2B, 0x10, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, 0x49, 0x13, 0x00, 0x00, + 0xC7, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x35, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, + 0x35, 0x10, 0x00, 0x00, 0x43, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x51, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x19, 0x00, 0x00, 0xF2, 0x12, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, + 0x58, 0x0F, 0x00, 0x00, 0x2C, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, 0xFC, 0x12, 0x00, 0x00, + 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, 0x45, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0x2E, 0x13, 0x00, 0x00, 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4B, 0x10, 0x00, 0x00, 0x46, 0x10, 0x00, 0x00, + 0x4A, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4F, 0x10, 0x00, 0x00, 0x38, 0x13, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, + 0x4B, 0x10, 0x00, 0x00, 0x4F, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, 0x6A, 0x13, 0x00, 0x00, + 0x73, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x55, 0x10, 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x10, 0x00, 0x00, + 0x56, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, 0x55, 0x10, 0x00, 0x00, + 0x59, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5E, 0x10, 0x00, 0x00, 0x74, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x10, 0x00, 0x00, + 0x5A, 0x10, 0x00, 0x00, 0x5E, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, 0x1A, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x64, 0x10, 0x00, 0x00, 0x5F, 0x10, 0x00, 0x00, 0x63, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, + 0x24, 0x13, 0x00, 0x00, 0x91, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x69, 0x10, 0x00, 0x00, 0x64, 0x10, 0x00, 0x00, + 0x68, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6D, 0x10, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0xAC, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, + 0x69, 0x10, 0x00, 0x00, 0x6D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, 0x4C, 0x13, 0x00, 0x00, + 0xC7, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x6E, 0x10, 0x00, 0x00, 0x72, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x10, 0x00, 0x00, + 0x73, 0x10, 0x00, 0x00, 0x43, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5F, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x75, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2D, 0x19, 0x00, 0x00, 0xF5, 0x12, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, + 0x58, 0x0F, 0x00, 0x00, 0x2D, 0x19, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0xFF, 0x12, 0x00, 0x00, + 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x10, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, + 0x31, 0x13, 0x00, 0x00, 0x61, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x89, 0x10, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, + 0x88, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8D, 0x10, 0x00, 0x00, 0x3B, 0x13, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x10, 0x00, 0x00, + 0x89, 0x10, 0x00, 0x00, 0x8D, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x92, 0x10, 0x00, 0x00, 0x6D, 0x13, 0x00, 0x00, + 0x73, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x10, 0x00, 0x00, 0x8E, 0x10, 0x00, 0x00, 0x92, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x10, 0x00, 0x00, + 0x59, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, 0x93, 0x10, 0x00, 0x00, + 0x97, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9C, 0x10, 0x00, 0x00, 0x77, 0x13, 0x00, 0x00, 0x8E, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, + 0x98, 0x10, 0x00, 0x00, 0x9C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA1, 0x10, 0x00, 0x00, 0x1D, 0x13, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x10, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, 0xA1, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA6, 0x10, 0x00, 0x00, + 0x27, 0x13, 0x00, 0x00, 0x91, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x10, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, + 0xA6, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAB, 0x10, 0x00, 0x00, 0x45, 0x13, 0x00, 0x00, 0xAC, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAC, 0x10, 0x00, 0x00, + 0xA7, 0x10, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x4F, 0x13, 0x00, 0x00, + 0xC7, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB1, 0x10, 0x00, 0x00, 0xAC, 0x10, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, + 0xB1, 0x10, 0x00, 0x00, 0x43, 0x17, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6D, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xC6, 0x08, 0x00, 0x00, + 0xC7, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0xC7, 0x08, 0x00, 0x00, 0x51, 0x17, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0xC6, 0x08, 0x00, 0x00, 0xC9, 0x08, 0x00, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xC9, 0x08, 0x00, 0x00, 0x5F, 0x17, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC6, 0x08, 0x00, 0x00, 0xCB, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xCB, 0x08, 0x00, 0x00, + 0x6D, 0x17, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xCC, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x08, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0xCD, 0x08, 0x00, 0x00, 0xCC, 0x08, 0x00, 0x00, + 0xCC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xCE, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0xCD, 0x08, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, + 0xCF, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, + 0x97, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0xCF, 0x08, 0x00, 0x00, + 0xCE, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0xB8, 0x08, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0xC6, 0x08, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, + 0xD1, 0x08, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xD2, 0x08, 0x00, 0x00, + 0x5F, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..1edd8d2aa19384dcfd538d57ff35438a9588c9bc GIT binary patch literal 8844 zcmZvheUO!98OC2&77!Li5eQH|R6tlnaO69XkCru~R-+tgoX%{!hh+nH*F9&=CPD&q za7+mt!$v?rlq|wZp=Mylf<`Jf5}Hb<$v>iLl7AE&MwzLh>v#6K>YjIcXP!Oxecji6 zU(d(;JbT{vRQ0~OUzYXC24wxSsUxz=b#2yLNR|!E`c^*cmn~m5wN!4NdgqL35U$Ru zDm*yXWc{)}`lPLGY;7a3vwxQTTy3y;;1ZBkrK(xBUrBwWR==!J-_TIMtgg`1(NQRs zzrLneSku~8EHt-v7Mseg4;SI}54_g4rZrv7kx(s0)UD2{v+dG&q*y2yA1QZrsz$ZO zKz~}+6qa^2wk&CH?`#%Dc>ipV@CS-Z8cWMpHFkCs+m^JqmCB86<&xrkv#Tm`xT@FG zSSqx4l{>o1h4z&zOT{vHUyXwr%tPXosMJ<0l?om0rE)>Ut`2EcW&6bAqCd=y_$$?) zLR0&i_DPthm&+#&e0^hpiJ=OmwX zt5qECgKAv%3l(p}UHIg-sG(47ByW9M`%sA z$^fHYyzGxs&%dJpys^^XmPlaplFvGEp~u*tt$01--65O$9v|^TYFBhk(V8(|ht
4Q1PWP`ymc0Bpy8taw~FJfmC58S-B6DMNt3d5&)?#{{PvVUH-*Y0r{j1AxY zJ|+j>I=_|!7W?yV^1;n}FY#i3-WP@skNRj`Zw#(hbHdoXcb`)BgG$K4lv_7)iYHo9qd534%O?+foj9|E9gq!<&p!QuZ03WyjQ>Y!)MbsR%h(PjoE-M*tMb7v zYdqZpdd9_PhvJN*RwQ)pQ%(3&^#>g;W49-aG2Sa4eVZl>E-|#IHC;CNW8&c7A)ET( zt~En8^%edvHZx(&yX(&q2A7!Y&z24TtyF)GY&5`YG|>nr{sgd&F8O5`JBVnKa#T<=NQ+?QO&o=RBM-I}nd zds%tp)2#6?VdT?{T@gk;%^EKe&*>gWSk!$bVNrL`5S`P)D>c#_3>HRyrAESr2qT|n z-Ji;4AII^&p0KEUBwDl*6o(fzK^=66Bc#fN?6pbRXy@))|e`ce44T8!pNst_Z``s7g6^w z35&XaO<2^Op?c)gtT9^{`7~qmgpp6P?muL6&P3gRCM@cnPgvBwOZCX7S!1y<@@dBE zgpp6P?uW8DU!v}%ghkzt5*Bqot$O6stg%cO`7~npM*u- z<*G+M%^LR$BcEn$g)s7I)*UIE^O(!n4GD|7qZ1Z&TU3vHnl-*EjC`80wZh1!S!1GX z&e5nlDPd8!HepfsA=M+FW{t8i@@dAtCX9SqjlO4a#y%^I`s39&YuNXWeK*87ci}p= zGsM`l+)s|}3NdQHb?l84yY>I*{UXHBgX_FELoBa%GQ_9>*Lm-y7~^AX93GV|<(?aUB+f z7=3~3yibJ~W8*$`tS-c;0oSpX6k~jOy;UKG9$e?Og;-v%J;bO1*LmAgjPWtHxDMMx zjCFwH8mDCwXU?rLVA%iWinukrhO-rCK98sSYp#4S-nH?J z$36E+`QW^7^SaKL5AHgvWiw~4vlhNutkW*Pf`>XC!oXc;w`}Icb@s>yi*@$N2ao-E zQ9iiqoRQ7gUFQ$7!D5|1$_I~i{v;pVrTwP8xxPUH*a*}5p!S0$R?kdu?e!N6|vjo!;86hBp#SG zX3A!-vM+i6!Ty^ijQ4TGJl|I|F7S=%p3zI+%2@#Jx$Gqj-2Iv>KK%u^-U9jTTlT2+ z?h=L`G3yOb4!HFO%IE9>w_c5GaO*7=pSb|H-ctGOVfL%_>V=_4%z8tW18%)x^3emg z-f-FA*1Jc1<{8|2pOepiX75_BK^S_(tT$FU;MN-_A3bpE-6R{_dY>1cH3T>IfPC&* z=Gs`JZ0=d+!&pf+_bh#Ozsj=V5;OL&Z17m`Y5CmS=$p4yHrm9DZIca-uCap&i@GO; zp%Lrds^6rjM}M3zS-(>mV=z44yWN*>j5p(W`!oV4iu}iYS>8G)eWP{UBW0z%v z(@(G09L+hn*K4l)b(coCi2D!gGDyK zaEY0ByKJ79V;<47mjMWL_IU=s%Qekk3nRkzDo+%>lGs55!Gp|85-|6F8-zy9*G4sA4 zo9Bhd`=T(o#LQbEoA1JL4ZkD|E-~}IESvA=kyj7~mza4?vU#qEYuzjiE-~{~$*w#P zgtciE2A7z5Yi08tKdyC~Fu26b>y*uNM_lWYFu26b>yix~*SZkans|P#Z_|46{*rfk zuJfpPtTi!Xn}qScF|OfeVQ`6=w?+1J)r!0)gux|d-cz!9&lK12X<=}QnYUdw?<*qj z8DVgVnYTkW?^EI$J|_$=G4poH<~>B@?Ggr;n0b3;^S&{z^*&*6iJAAZ?1|#VeSJU} zTw><^P&V(k;#waR2A7z5KbFn=sJPZY5eAo-d9TR^k88a)tTl13^&)*|;&;N6YW#M1 zPWyg=enG_NEO7icDb9CT;`rP@j-N{L^C^yxrhiN9PVojkM@JG);k_`r*-!iM!^mV548z}vR3&;IDD;td8L5bt@efQr| Ho2~XA&SG+5 literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt new file mode 100644 index 000000000..71d71da9a --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.txt @@ -0,0 +1,443 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 6446 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeCasSharpenConstants "XeCasSharpenConstants" + OpMemberName %XeCasSharpenConstants 0 "xe_cas_output_offset" + OpMemberName %XeCasSharpenConstants 1 "xe_cas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeCasSharpenConstants 0 Offset 16 + OpMemberDecorate %XeCasSharpenConstants 1 Offset 24 + OpDecorate %XeCasSharpenConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v3float = OpTypeVector %float 3 + %v2uint = OpTypeVector %uint 2 + %v4uint = OpTypeVector %uint 4 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 + %uint_1 = OpConstant %uint 1 +%uint_532432441 = OpConstant %uint 532432441 +%uint_2129690299 = OpConstant %uint 2129690299 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %143 = OpTypeImage %float 2D 0 0 0 1 Unknown + %144 = OpTypeSampledImage %143 +%_ptr_UniformConstant_144 = OpTypePointer UniformConstant %144 + %xe_texture = OpVariable %_ptr_UniformConstant_144 UniformConstant + %int_0 = OpConstant %int 0 + %v4float = OpTypeVector %float 4 + %int_n1 = OpConstant %int -1 + %181 = OpConstantComposite %v2int %int_0 %int_n1 + %int_1 = OpConstant %int 1 + %188 = OpConstantComposite %v2int %int_1 %int_n1 + %194 = OpConstantComposite %v2int %int_n1 %int_0 + %204 = OpConstantComposite %v2int %int_1 %int_0 + %210 = OpConstantComposite %v2int %int_n1 %int_1 + %216 = OpConstantComposite %v2int %int_0 %int_1 + %222 = OpConstantComposite %v2int %int_1 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_2 = OpConstant %uint 2 + %v2float = OpTypeVector %float 2 + %int_2 = OpConstant %int 2 + %712 = OpConstantComposite %v2int %int_2 %int_0 + %734 = OpConstantComposite %v2int %int_0 %int_2 + %745 = OpConstantComposite %v2int %int_2 %int_1 + %751 = OpConstantComposite %v2int %int_1 %int_2 +%float_0_03125 = OpConstant %float 0.03125 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeCasSharpenConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeCasSharpenConstants = OpTypePointer PushConstant %XeCasSharpenConstants + %_ = OpVariable %_ptr_PushConstant_XeCasSharpenConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int + %2217 = OpConstantComposite %v4float %float_1 %float_1 %float_0 %float_0 +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %main = OpFunction %void None %3 + %5 = OpLabel + %2205 = OpLoad %v4float %gl_FragCoord + %2206 = OpVectorShuffle %v2float %2205 %2205 0 1 + %2207 = OpConvertFToS %v2int %2206 + %2212 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %2213 = OpLoad %v2int %2212 + %2214 = OpISub %v2int %2207 %2213 + %2215 = OpBitcast %v2uint %2214 + %2218 = OpBitcast %v4uint %2217 + %2221 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %2222 = OpLoad %float %2221 + %2223 = OpBitcast %uint %2222 + OpBranch %2764 + %2764 = OpLabel + %3115 = OpConvertUToF %v2float %2215 + %3118 = OpCompositeExtract %uint %2218 0 + %3119 = OpCompositeExtract %uint %2218 1 + %3120 = OpCompositeConstruct %v2uint %3118 %3119 + %3121 = OpBitcast %v2float %3120 + %3122 = OpFMul %v2float %3115 %3121 + %3125 = OpCompositeExtract %uint %2218 2 + %3126 = OpCompositeExtract %uint %2218 3 + %3127 = OpCompositeConstruct %v2uint %3125 %3126 + %3128 = OpBitcast %v2float %3127 + %3129 = OpFAdd %v2float %3122 %3128 + %3131 = OpExtInst %v2float %1 Floor %3129 + %3134 = OpFSub %v2float %3129 %3131 + %3136 = OpConvertFToS %v2int %3131 + %3141 = OpIAdd %v2int %3136 %181 + %4731 = OpLoad %144 %xe_texture + %4733 = OpImage %143 %4731 + %4734 = OpImageFetch %v4float %4733 %3141 Lod %int_0 + %3144 = OpIAdd %v2int %3136 %194 + %4740 = OpImage %143 %4731 + %4741 = OpImageFetch %v4float %4740 %3144 Lod %int_0 + %4747 = OpImage %143 %4731 + %4748 = OpImageFetch %v4float %4747 %3136 Lod %int_0 + %3149 = OpIAdd %v2int %3136 %188 + %4754 = OpImage %143 %4731 + %4755 = OpImageFetch %v4float %4754 %3149 Lod %int_0 + %3155 = OpIAdd %v2int %3136 %204 + %4768 = OpImage %143 %4731 + %4769 = OpImageFetch %v4float %4768 %3155 Lod %int_0 + %3158 = OpIAdd %v2int %3136 %712 + %4775 = OpImage %143 %4731 + %4776 = OpImageFetch %v4float %4775 %3158 Lod %int_0 + %3161 = OpIAdd %v2int %3136 %210 + %4782 = OpImage %143 %4731 + %4783 = OpImageFetch %v4float %4782 %3161 Lod %int_0 + %3164 = OpIAdd %v2int %3136 %216 + %4789 = OpImage %143 %4731 + %4790 = OpImageFetch %v4float %4789 %3164 Lod %int_0 + %3170 = OpIAdd %v2int %3136 %734 + %4803 = OpImage %143 %4731 + %4804 = OpImageFetch %v4float %4803 %3170 Lod %int_0 + %3173 = OpIAdd %v2int %3136 %222 + %4810 = OpImage %143 %4731 + %4811 = OpImageFetch %v4float %4810 %3173 Lod %int_0 + %3176 = OpIAdd %v2int %3136 %745 + %4817 = OpImage %143 %4731 + %4818 = OpImageFetch %v4float %4817 %3176 Lod %int_0 + %3179 = OpIAdd %v2int %3136 %751 + %4824 = OpImage %143 %4731 + %4825 = OpImageFetch %v4float %4824 %3179 Lod %int_0 + %3198 = OpCompositeExtract %float %4734 0 + %3200 = OpCompositeExtract %float %4734 1 + %3202 = OpCompositeExtract %float %4734 2 + %4847 = OpFMul %float %3198 %3198 + %4850 = OpFMul %float %3200 %3200 + %4853 = OpFMul %float %3202 %3202 + %3211 = OpCompositeExtract %float %4755 0 + %3213 = OpCompositeExtract %float %4755 1 + %3215 = OpCompositeExtract %float %4755 2 + %4857 = OpFMul %float %3211 %3211 + %4860 = OpFMul %float %3213 %3213 + %4863 = OpFMul %float %3215 %3215 + %3237 = OpCompositeExtract %float %4741 0 + %3239 = OpCompositeExtract %float %4741 1 + %3241 = OpCompositeExtract %float %4741 2 + %4877 = OpFMul %float %3237 %3237 + %4880 = OpFMul %float %3239 %3239 + %4883 = OpFMul %float %3241 %3241 + %3250 = OpCompositeExtract %float %4748 0 + %3252 = OpCompositeExtract %float %4748 1 + %3254 = OpCompositeExtract %float %4748 2 + %4887 = OpFMul %float %3250 %3250 + %4890 = OpFMul %float %3252 %3252 + %4893 = OpFMul %float %3254 %3254 + %3263 = OpCompositeExtract %float %4769 0 + %3265 = OpCompositeExtract %float %4769 1 + %3267 = OpCompositeExtract %float %4769 2 + %4897 = OpFMul %float %3263 %3263 + %4900 = OpFMul %float %3265 %3265 + %4903 = OpFMul %float %3267 %3267 + %3276 = OpCompositeExtract %float %4776 0 + %3278 = OpCompositeExtract %float %4776 1 + %3280 = OpCompositeExtract %float %4776 2 + %4907 = OpFMul %float %3276 %3276 + %4910 = OpFMul %float %3278 %3278 + %4913 = OpFMul %float %3280 %3280 + %3289 = OpCompositeExtract %float %4783 0 + %3291 = OpCompositeExtract %float %4783 1 + %3293 = OpCompositeExtract %float %4783 2 + %4917 = OpFMul %float %3289 %3289 + %4920 = OpFMul %float %3291 %3291 + %4923 = OpFMul %float %3293 %3293 + %3302 = OpCompositeExtract %float %4790 0 + %3304 = OpCompositeExtract %float %4790 1 + %3306 = OpCompositeExtract %float %4790 2 + %4927 = OpFMul %float %3302 %3302 + %4930 = OpFMul %float %3304 %3304 + %4933 = OpFMul %float %3306 %3306 + %3315 = OpCompositeExtract %float %4811 0 + %3317 = OpCompositeExtract %float %4811 1 + %3319 = OpCompositeExtract %float %4811 2 + %4937 = OpFMul %float %3315 %3315 + %4940 = OpFMul %float %3317 %3317 + %4943 = OpFMul %float %3319 %3319 + %3328 = OpCompositeExtract %float %4818 0 + %3330 = OpCompositeExtract %float %4818 1 + %3332 = OpCompositeExtract %float %4818 2 + %4947 = OpFMul %float %3328 %3328 + %4950 = OpFMul %float %3330 %3330 + %4953 = OpFMul %float %3332 %3332 + %3354 = OpCompositeExtract %float %4804 0 + %3356 = OpCompositeExtract %float %4804 1 + %3358 = OpCompositeExtract %float %4804 2 + %4967 = OpFMul %float %3354 %3354 + %4970 = OpFMul %float %3356 %3356 + %4973 = OpFMul %float %3358 %3358 + %3367 = OpCompositeExtract %float %4825 0 + %3369 = OpCompositeExtract %float %4825 1 + %3371 = OpCompositeExtract %float %4825 2 + %4977 = OpFMul %float %3367 %3367 + %4980 = OpFMul %float %3369 %3369 + %4983 = OpFMul %float %3371 %3371 + %5013 = OpExtInst %float %1 FMin %4880 %4890 + %5014 = OpExtInst %float %1 FMin %4850 %5013 + %5020 = OpExtInst %float %1 FMin %4900 %4930 + %5021 = OpExtInst %float %1 FMin %5014 %5020 + %5055 = OpExtInst %float %1 FMax %4880 %4890 + %5056 = OpExtInst %float %1 FMax %4850 %5055 + %5062 = OpExtInst %float %1 FMax %4900 %4930 + %5063 = OpExtInst %float %1 FMax %5056 %5062 + %5097 = OpExtInst %float %1 FMin %4890 %4900 + %5098 = OpExtInst %float %1 FMin %4860 %5097 + %5104 = OpExtInst %float %1 FMin %4910 %4940 + %5105 = OpExtInst %float %1 FMin %5098 %5104 + %5139 = OpExtInst %float %1 FMax %4890 %4900 + %5140 = OpExtInst %float %1 FMax %4860 %5139 + %5146 = OpExtInst %float %1 FMax %4910 %4940 + %5147 = OpExtInst %float %1 FMax %5140 %5146 + %5181 = OpExtInst %float %1 FMin %4920 %4930 + %5182 = OpExtInst %float %1 FMin %4890 %5181 + %5188 = OpExtInst %float %1 FMin %4940 %4970 + %5189 = OpExtInst %float %1 FMin %5182 %5188 + %5223 = OpExtInst %float %1 FMax %4920 %4930 + %5224 = OpExtInst %float %1 FMax %4890 %5223 + %5230 = OpExtInst %float %1 FMax %4940 %4970 + %5231 = OpExtInst %float %1 FMax %5224 %5230 + %5265 = OpExtInst %float %1 FMin %4930 %4940 + %5266 = OpExtInst %float %1 FMin %4900 %5265 + %5272 = OpExtInst %float %1 FMin %4950 %4980 + %5273 = OpExtInst %float %1 FMin %5266 %5272 + %5307 = OpExtInst %float %1 FMax %4930 %4940 + %5308 = OpExtInst %float %1 FMax %4900 %5307 + %5314 = OpExtInst %float %1 FMax %4950 %4980 + %5315 = OpExtInst %float %1 FMax %5308 %5314 + %5346 = OpBitcast %uint %5063 + %5347 = OpISub %uint %uint_2129690299 %5346 + %5348 = OpBitcast %float %5347 + %5379 = OpBitcast %uint %5147 + %5380 = OpISub %uint %uint_2129690299 %5379 + %5381 = OpBitcast %float %5380 + %5412 = OpBitcast %uint %5231 + %5413 = OpISub %uint %uint_2129690299 %5412 + %5414 = OpBitcast %float %5413 + %5445 = OpBitcast %uint %5315 + %5446 = OpISub %uint %uint_2129690299 %5445 + %5447 = OpBitcast %float %5446 + %3715 = OpFSub %float %float_1 %5063 + %3716 = OpExtInst %float %1 FMin %5021 %3715 + %3718 = OpFMul %float %3716 %5348 + %5489 = OpExtInst %float %1 FClamp %3718 %float_0 %float_1 + %3739 = OpFSub %float %float_1 %5147 + %3740 = OpExtInst %float %1 FMin %5105 %3739 + %3742 = OpFMul %float %3740 %5381 + %5540 = OpExtInst %float %1 FClamp %3742 %float_0 %float_1 + %3763 = OpFSub %float %float_1 %5231 + %3764 = OpExtInst %float %1 FMin %5189 %3763 + %3766 = OpFMul %float %3764 %5414 + %5591 = OpExtInst %float %1 FClamp %3766 %float_0 %float_1 + %3787 = OpFSub %float %float_1 %5315 + %3788 = OpExtInst %float %1 FMin %5273 %3787 + %3790 = OpFMul %float %3788 %5447 + %5642 = OpExtInst %float %1 FClamp %3790 %float_0 %float_1 + %5688 = OpBitcast %uint %5489 + %5690 = OpShiftRightLogical %uint %5688 %uint_1 + %5692 = OpIAdd %uint %5690 %uint_532432441 + %5693 = OpBitcast %float %5692 + %5739 = OpBitcast %uint %5540 + %5741 = OpShiftRightLogical %uint %5739 %uint_1 + %5743 = OpIAdd %uint %5741 %uint_532432441 + %5744 = OpBitcast %float %5743 + %5790 = OpBitcast %uint %5591 + %5792 = OpShiftRightLogical %uint %5790 %uint_1 + %5794 = OpIAdd %uint %5792 %uint_532432441 + %5795 = OpBitcast %float %5794 + %5841 = OpBitcast %uint %5642 + %5843 = OpShiftRightLogical %uint %5841 %uint_1 + %5845 = OpIAdd %uint %5843 %uint_532432441 + %5846 = OpBitcast %float %5845 + %3826 = OpBitcast %float %2223 + %3832 = OpFMul %float %5693 %3826 + %3841 = OpFMul %float %5744 %3826 + %3850 = OpFMul %float %5795 %3826 + %3859 = OpFMul %float %5846 %3826 + %3865 = OpCompositeExtract %float %3134 0 + %3866 = OpFSub %float %float_1 %3865 + %3869 = OpCompositeExtract %float %3134 1 + %3870 = OpFSub %float %float_1 %3869 + %3871 = OpFMul %float %3866 %3870 + %3878 = OpFMul %float %3865 %3870 + %3885 = OpFMul %float %3866 %3869 + %3890 = OpFMul %float %3865 %3869 + %3894 = OpFSub %float %5063 %5021 + %3895 = OpFAdd %float %float_0_03125 %3894 + %5887 = OpBitcast %uint %3895 + %5888 = OpISub %uint %uint_2129690299 %5887 + %5889 = OpBitcast %float %5888 + %3898 = OpFMul %float %3871 %5889 + %3902 = OpFSub %float %5147 %5105 + %3903 = OpFAdd %float %float_0_03125 %3902 + %5898 = OpBitcast %uint %3903 + %5899 = OpISub %uint %uint_2129690299 %5898 + %5900 = OpBitcast %float %5899 + %3906 = OpFMul %float %3878 %5900 + %3910 = OpFSub %float %5231 %5189 + %3911 = OpFAdd %float %float_0_03125 %3910 + %5909 = OpBitcast %uint %3911 + %5910 = OpISub %uint %uint_2129690299 %5909 + %5911 = OpBitcast %float %5910 + %3914 = OpFMul %float %3885 %5911 + %3918 = OpFSub %float %5315 %5273 + %3919 = OpFAdd %float %float_0_03125 %3918 + %5920 = OpBitcast %uint %3919 + %5921 = OpISub %uint %uint_2129690299 %5920 + %5922 = OpBitcast %float %5921 + %3922 = OpFMul %float %3890 %5922 + %3928 = OpFMul %float %3832 %3898 + %3937 = OpFMul %float %3841 %3906 + %3955 = OpFMul %float %3850 %3914 + %3956 = OpFAdd %float %3937 %3955 + %3958 = OpFAdd %float %3956 %3898 + %3982 = OpFMul %float %3859 %3922 + %3983 = OpFAdd %float %3928 %3982 + %3985 = OpFAdd %float %3983 %3906 + %4012 = OpFAdd %float %3983 %3914 + %4039 = OpFAdd %float %3956 %3922 + %6440 = OpFAdd %float %3928 %3937 + %6441 = OpFAdd %float %6440 %3955 + %6442 = OpFAdd %float %6441 %3982 + %4081 = OpFMul %float %float_2 %6442 + %4083 = OpFAdd %float %4081 %3958 + %4085 = OpFAdd %float %4083 %3985 + %4087 = OpFAdd %float %4085 %4012 + %4089 = OpFAdd %float %4087 %4039 + %5945 = OpBitcast %uint %4089 + %5946 = OpISub %uint %uint_2129764351 %5945 + %5947 = OpBitcast %float %5946 + %5950 = OpFNegate %float %5947 + %5952 = OpFMul %float %5950 %4089 + %5954 = OpFAdd %float %5952 %float_2 + %5955 = OpFMul %float %5947 %5954 + %6443 = OpFAdd %float %4847 %4877 + %4099 = OpFMul %float %3928 %6443 + %4103 = OpFMul %float %4857 %3937 + %4104 = OpFAdd %float %4099 %4103 + %4108 = OpFMul %float %4907 %3937 + %4109 = OpFAdd %float %4104 %4108 + %4113 = OpFMul %float %4917 %3955 + %4114 = OpFAdd %float %4109 %4113 + %4118 = OpFMul %float %4967 %3955 + %4119 = OpFAdd %float %4114 %4118 + %4123 = OpFMul %float %4947 %3982 + %4124 = OpFAdd %float %4119 %4123 + %4128 = OpFMul %float %4977 %3982 + %4129 = OpFAdd %float %4124 %4128 + %4133 = OpFMul %float %4887 %3958 + %4134 = OpFAdd %float %4129 %4133 + %4138 = OpFMul %float %4897 %3985 + %4139 = OpFAdd %float %4134 %4138 + %4143 = OpFMul %float %4927 %4012 + %4144 = OpFAdd %float %4139 %4143 + %4148 = OpFMul %float %4937 %4039 + %4149 = OpFAdd %float %4144 %4148 + %4151 = OpFMul %float %4149 %5955 + %5969 = OpExtInst %float %1 FClamp %4151 %float_0 %float_1 + %6444 = OpFAdd %float %4850 %4880 + %4161 = OpFMul %float %3928 %6444 + %4165 = OpFMul %float %4860 %3937 + %4166 = OpFAdd %float %4161 %4165 + %4170 = OpFMul %float %4910 %3937 + %4171 = OpFAdd %float %4166 %4170 + %4175 = OpFMul %float %4920 %3955 + %4176 = OpFAdd %float %4171 %4175 + %4180 = OpFMul %float %4970 %3955 + %4181 = OpFAdd %float %4176 %4180 + %4185 = OpFMul %float %4950 %3982 + %4186 = OpFAdd %float %4181 %4185 + %4190 = OpFMul %float %4980 %3982 + %4191 = OpFAdd %float %4186 %4190 + %4195 = OpFMul %float %4890 %3958 + %4196 = OpFAdd %float %4191 %4195 + %4200 = OpFMul %float %4900 %3985 + %4201 = OpFAdd %float %4196 %4200 + %4205 = OpFMul %float %4930 %4012 + %4206 = OpFAdd %float %4201 %4205 + %4210 = OpFMul %float %4940 %4039 + %4211 = OpFAdd %float %4206 %4210 + %4213 = OpFMul %float %4211 %5955 + %5983 = OpExtInst %float %1 FClamp %4213 %float_0 %float_1 + %6445 = OpFAdd %float %4853 %4883 + %4223 = OpFMul %float %3928 %6445 + %4227 = OpFMul %float %4863 %3937 + %4228 = OpFAdd %float %4223 %4227 + %4232 = OpFMul %float %4913 %3937 + %4233 = OpFAdd %float %4228 %4232 + %4237 = OpFMul %float %4923 %3955 + %4238 = OpFAdd %float %4233 %4237 + %4242 = OpFMul %float %4973 %3955 + %4243 = OpFAdd %float %4238 %4242 + %4247 = OpFMul %float %4953 %3982 + %4248 = OpFAdd %float %4243 %4247 + %4252 = OpFMul %float %4983 %3982 + %4253 = OpFAdd %float %4248 %4252 + %4257 = OpFMul %float %4893 %3958 + %4258 = OpFAdd %float %4253 %4257 + %4262 = OpFMul %float %4903 %3985 + %4263 = OpFAdd %float %4258 %4262 + %4267 = OpFMul %float %4933 %4012 + %4268 = OpFAdd %float %4263 %4267 + %4272 = OpFMul %float %4943 %4039 + %4273 = OpFAdd %float %4268 %4272 + %4275 = OpFMul %float %4273 %5955 + %5997 = OpExtInst %float %1 FClamp %4275 %float_0 %float_1 + %2247 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %2247 %5969 + %2249 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %2249 %5983 + %2251 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %2251 %5997 + %2252 = OpLoad %v4float %xe_frag_color + %2253 = OpVectorShuffle %v3float %2252 %2252 0 1 2 + %2254 = OpExtInst %v3float %1 Sqrt %2253 + %2255 = OpLoad %v4float %xe_frag_color + %2256 = OpVectorShuffle %v4float %2255 %2254 4 5 6 3 + OpStore %xe_frag_color %2256 + %2258 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %2258 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h new file mode 100644 index 000000000..c32ba006b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h @@ -0,0 +1,1332 @@ +// generated from `xb genspirv` +// source: guest_output_ffx_fsr_easu.frag +const uint8_t guest_output_ffx_fsr_easu_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x5A, 0x12, 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, + 0x08, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0A, 0x00, + 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, 0x45, 0x5F, 0x63, 0x70, + 0x70, 0x5F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x5F, 0x6C, 0x69, 0x6E, 0x65, + 0x5F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x47, 0x4C, 0x5F, 0x47, 0x4F, 0x4F, 0x47, 0x4C, + 0x45, 0x5F, 0x69, 0x6E, 0x63, 0x6C, 0x75, 0x64, 0x65, 0x5F, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0xBC, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x58, 0x65, 0x46, 0x73, 0x72, 0x45, 0x61, 0x73, + 0x75, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, + 0x06, 0x00, 0x0C, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x65, 0x61, 0x73, 0x75, 0x5F, + 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x00, + 0x06, 0x00, 0x0A, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x73, 0x72, 0x5F, 0x65, 0x61, 0x73, 0x75, 0x5F, + 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, + 0x6E, 0x76, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0xE0, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0A, 0x05, 0x00, 0x00, + 0x67, 0x6C, 0x5F, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6F, 0x72, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xDE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xDE, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0A, 0x05, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 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, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x02, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xBB, 0x7E, 0xF0, 0x7E, 0x2B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0x74, 0x7D, 0x34, 0x5F, 0x2B, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0xB9, 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, 0xBA, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xBB, 0x00, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0xBF, 0x00, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xCD, 0xCC, 0xCC, 0x3E, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x3F, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x10, 0xBF, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x2B, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE6, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0xE1, 0x7A, 0x94, 0xBE, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x8D, 0x03, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xA8, 0x03, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xC3, 0x03, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xDE, 0x03, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2F, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x4B, 0x04, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x66, 0x04, 0x00, 0x00, + 0x4A, 0x04, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x81, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x9C, 0x04, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB7, 0x04, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0xDF, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xDE, 0x04, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0xDF, 0x04, 0x00, 0x00, + 0xE0, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xE1, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF1, 0x04, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, + 0xF8, 0x04, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x4A, 0x04, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, + 0x20, 0x00, 0x04, 0x00, 0x01, 0x05, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x05, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x07, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x09, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x09, 0x05, 0x00, 0x00, + 0x0A, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x1C, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x35, 0x12, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x59, 0x12, 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, 0xE1, 0x04, 0x00, 0x00, + 0xE2, 0x04, 0x00, 0x00, 0xE0, 0x04, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xE3, 0x04, 0x00, 0x00, + 0xE2, 0x04, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xE4, 0x04, 0x00, 0x00, 0xE3, 0x04, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE7, 0x04, 0x00, 0x00, 0xE3, 0x04, 0x00, 0x00, + 0x21, 0x02, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xE9, 0x04, 0x00, 0x00, 0xE7, 0x04, 0x00, 0x00, 0x35, 0x12, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, + 0xE9, 0x04, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0xE1, 0x04, 0x00, 0x00, + 0xF2, 0x04, 0x00, 0x00, 0xE0, 0x04, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xF3, 0x04, 0x00, 0x00, + 0xF2, 0x04, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0x16, 0x00, 0x00, 0x00, + 0xF4, 0x04, 0x00, 0x00, 0xF3, 0x04, 0x00, 0x00, 0xF3, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0xF5, 0x04, 0x00, 0x00, 0xF1, 0x04, 0x00, 0x00, 0xF4, 0x04, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, + 0xF5, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0xFC, 0x04, 0x00, 0x00, 0xF8, 0x04, 0x00, 0x00, 0xF4, 0x04, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, + 0xFC, 0x04, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xFF, 0x04, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, + 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0xE0, 0x04, 0x00, 0x00, + 0xC6, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x0B, 0x05, 0x00, 0x00, + 0x0A, 0x05, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x05, 0x00, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x0B, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x04, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x0D, 0x05, 0x00, 0x00, 0x0C, 0x05, 0x00, 0x00, + 0x70, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, + 0x0D, 0x05, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x15, 0x06, 0x00, 0x00, 0xE4, 0x04, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x16, 0x06, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, + 0x15, 0x06, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x1C, 0x06, 0x00, 0x00, 0xEA, 0x04, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x1D, 0x06, 0x00, 0x00, 0x16, 0x06, 0x00, 0x00, + 0x1C, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x1F, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1D, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x1D, 0x06, 0x00, 0x00, 0x1F, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, + 0xF6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x27, 0x06, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x28, 0x06, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x27, 0x06, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x29, 0x06, 0x00, 0x00, + 0x28, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2A, 0x06, 0x00, 0x00, 0x1F, 0x06, 0x00, 0x00, 0x29, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2D, 0x06, 0x00, 0x00, + 0xF6, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0xF6, 0x04, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x2F, 0x06, 0x00, 0x00, 0x2D, 0x06, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, + 0x2F, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x31, 0x06, 0x00, 0x00, 0x2A, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, + 0xFD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x37, 0x06, 0x00, 0x00, 0x35, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x06, 0x00, 0x00, + 0x37, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x39, 0x06, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, 0x38, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, + 0xFD, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x3E, 0x06, 0x00, 0x00, 0xFD, 0x04, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x3F, 0x06, 0x00, 0x00, 0x3D, 0x06, 0x00, 0x00, 0x3E, 0x06, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, + 0x3F, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x41, 0x06, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, + 0x50, 0x00, 0x05, 0x00, 0x60, 0x00, 0x00, 0x00, 0x47, 0x06, 0x00, 0x00, + 0xFF, 0x04, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x48, 0x06, 0x00, 0x00, 0x47, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x49, 0x06, 0x00, 0x00, + 0x31, 0x06, 0x00, 0x00, 0x48, 0x06, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0xBA, 0x00, 0x00, 0x00, 0x3C, 0x08, 0x00, 0x00, 0xBC, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3E, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x43, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x31, 0x06, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x57, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x5C, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x41, 0x06, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x41, 0x06, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x66, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x41, 0x06, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6B, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x49, 0x06, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x49, 0x06, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x75, 0x08, 0x00, 0x00, + 0x3C, 0x08, 0x00, 0x00, 0x49, 0x06, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x64, 0x06, 0x00, 0x00, + 0x48, 0x08, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x67, 0x06, 0x00, 0x00, 0x3E, 0x08, 0x00, 0x00, + 0x36, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x69, 0x06, 0x00, 0x00, 0x67, 0x06, 0x00, 0x00, 0x43, 0x08, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6A, 0x06, 0x00, 0x00, + 0x64, 0x06, 0x00, 0x00, 0x69, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x6D, 0x06, 0x00, 0x00, 0x57, 0x08, 0x00, 0x00, + 0x36, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x70, 0x06, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x72, 0x06, 0x00, 0x00, + 0x70, 0x06, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x73, 0x06, 0x00, 0x00, 0x6D, 0x06, 0x00, 0x00, + 0x72, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x76, 0x06, 0x00, 0x00, 0x66, 0x08, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x79, 0x06, 0x00, 0x00, + 0x5C, 0x08, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x7B, 0x06, 0x00, 0x00, 0x79, 0x06, 0x00, 0x00, + 0x61, 0x08, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x7C, 0x06, 0x00, 0x00, 0x76, 0x06, 0x00, 0x00, 0x7B, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x7F, 0x06, 0x00, 0x00, + 0x75, 0x08, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x82, 0x06, 0x00, 0x00, 0x6B, 0x08, 0x00, 0x00, + 0x36, 0x12, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x84, 0x06, 0x00, 0x00, 0x82, 0x06, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x85, 0x06, 0x00, 0x00, + 0x7F, 0x06, 0x00, 0x00, 0x84, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x06, 0x00, 0x00, 0x6A, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x89, 0x06, 0x00, 0x00, 0x6A, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, + 0x73, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, 0x73, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8F, 0x06, 0x00, 0x00, 0x73, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, + 0x73, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, 0x7C, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x95, 0x06, 0x00, 0x00, 0x7C, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x7C, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, 0x7C, 0x06, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9B, 0x06, 0x00, 0x00, 0x85, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, + 0x85, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCE, 0x08, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCF, 0x08, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xCE, 0x08, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x08, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0xD2, 0x08, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD4, 0x08, 0x00, 0x00, 0xCF, 0x08, 0x00, 0x00, 0xD3, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF4, 0x08, 0x00, 0x00, + 0x99, 0x06, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF7, 0x08, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, + 0x91, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xF4, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFB, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xF7, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFC, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xF9, 0x08, 0x00, 0x00, 0xFB, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x4E, 0x09, 0x00, 0x00, 0xFC, 0x08, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x4F, 0x09, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x4E, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x50, 0x09, 0x00, 0x00, 0x4F, 0x09, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, + 0x99, 0x06, 0x00, 0x00, 0x91, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, + 0xD4, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x09, 0x00, 0x00, 0x0A, 0x09, 0x00, 0x00, 0x50, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0C, 0x09, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x5B, 0x09, 0x00, 0x00, + 0x5B, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x13, 0x09, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0xD4, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x09, 0x00, 0x00, + 0x8D, 0x06, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x09, 0x00, 0x00, 0x8F, 0x06, 0x00, 0x00, + 0x87, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1D, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x18, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1F, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1B, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x1D, 0x09, 0x00, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x67, 0x09, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x67, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x69, 0x09, 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x09, 0x00, 0x00, + 0x8D, 0x06, 0x00, 0x00, 0x87, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x25, 0x09, 0x00, 0x00, + 0xD4, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2E, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x25, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x30, 0x09, 0x00, 0x00, 0x2E, 0x09, 0x00, 0x00, 0x69, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, + 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00, 0x74, 0x09, 0x00, 0x00, + 0x74, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x37, 0x09, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00, 0xD4, 0x08, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, + 0x13, 0x09, 0x00, 0x00, 0x37, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA3, 0x09, 0x00, 0x00, 0xCE, 0x08, 0x00, 0x00, + 0xD3, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB9, 0x09, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB9, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC1, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xBE, 0x09, 0x00, 0x00, + 0xF9, 0x08, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x13, 0x0A, 0x00, 0x00, 0xC1, 0x09, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x14, 0x0A, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x13, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x15, 0x0A, 0x00, 0x00, 0x14, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC6, 0x09, 0x00, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x8F, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC9, 0x09, 0x00, 0x00, 0xC6, 0x09, 0x00, 0x00, 0xA3, 0x09, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCC, 0x09, 0x00, 0x00, + 0x04, 0x09, 0x00, 0x00, 0xC9, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCF, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xC6, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD1, 0x09, 0x00, 0x00, 0xCF, 0x09, 0x00, 0x00, + 0x15, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xD1, 0x09, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, + 0x20, 0x0A, 0x00, 0x00, 0x20, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD8, 0x09, 0x00, 0x00, 0xD5, 0x09, 0x00, 0x00, + 0xA3, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDA, 0x09, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0xD8, 0x09, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x09, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE0, 0x09, 0x00, 0x00, 0x99, 0x06, 0x00, 0x00, + 0x89, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE2, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xDD, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE4, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xE0, 0x09, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE5, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xE2, 0x09, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x2C, 0x0A, 0x00, 0x00, 0xE5, 0x09, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2D, 0x0A, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x2C, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2E, 0x0A, 0x00, 0x00, 0x2D, 0x0A, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x89, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xED, 0x09, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, + 0xA3, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF0, 0x09, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0xED, 0x09, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF3, 0x09, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEA, 0x09, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, + 0xF3, 0x09, 0x00, 0x00, 0x2E, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x39, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0xF5, 0x09, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF9, 0x09, 0x00, 0x00, 0x39, 0x0A, 0x00, 0x00, 0x39, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x00, + 0xF9, 0x09, 0x00, 0x00, 0xA3, 0x09, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, 0xDA, 0x09, 0x00, 0x00, + 0xFC, 0x09, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x72, 0x0A, 0x00, 0x00, 0xCF, 0x08, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7E, 0x0A, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x81, 0x0A, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, + 0x8B, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x83, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x7E, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x85, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x81, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x86, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x83, 0x0A, 0x00, 0x00, 0x85, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xD8, 0x0A, 0x00, 0x00, 0x86, 0x0A, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xD9, 0x0A, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0xD8, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDA, 0x0A, 0x00, 0x00, 0xD9, 0x0A, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8B, 0x0A, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x8B, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8E, 0x0A, 0x00, 0x00, 0x8B, 0x0A, 0x00, 0x00, + 0x72, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x91, 0x0A, 0x00, 0x00, 0xCC, 0x09, 0x00, 0x00, 0x8E, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x94, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8B, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x96, 0x0A, 0x00, 0x00, + 0x94, 0x0A, 0x00, 0x00, 0xDA, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE5, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x96, 0x0A, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9A, 0x0A, 0x00, 0x00, 0xE5, 0x0A, 0x00, 0x00, 0xE5, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9D, 0x0A, 0x00, 0x00, + 0x9A, 0x0A, 0x00, 0x00, 0x72, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0A, 0x00, 0x00, 0xFE, 0x09, 0x00, 0x00, + 0x9D, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x0A, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA7, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xA2, 0x0A, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAA, 0x0A, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xA7, 0x0A, 0x00, 0x00, + 0x1D, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xF1, 0x0A, 0x00, 0x00, 0xAA, 0x0A, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xF2, 0x0A, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xF1, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF3, 0x0A, 0x00, 0x00, 0xF2, 0x0A, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAF, 0x0A, 0x00, 0x00, 0x9D, 0x06, 0x00, 0x00, + 0x8F, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB2, 0x0A, 0x00, 0x00, 0xAF, 0x0A, 0x00, 0x00, 0x72, 0x0A, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB5, 0x0A, 0x00, 0x00, + 0xF0, 0x09, 0x00, 0x00, 0xB2, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB8, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xAF, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBA, 0x0A, 0x00, 0x00, 0xB8, 0x0A, 0x00, 0x00, + 0xF3, 0x0A, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFE, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0xBA, 0x0A, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0A, 0x00, 0x00, + 0xFE, 0x0A, 0x00, 0x00, 0xFE, 0x0A, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC1, 0x0A, 0x00, 0x00, 0xBE, 0x0A, 0x00, 0x00, + 0x72, 0x0A, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC3, 0x0A, 0x00, 0x00, 0x9F, 0x0A, 0x00, 0x00, 0xC1, 0x0A, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x0B, 0x00, 0x00, + 0xCE, 0x08, 0x00, 0x00, 0xD2, 0x08, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x43, 0x0B, 0x00, 0x00, 0x95, 0x06, 0x00, 0x00, + 0x93, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x48, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x43, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4B, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x48, 0x0B, 0x00, 0x00, 0x83, 0x0A, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x9D, 0x0B, 0x00, 0x00, 0x4B, 0x0B, 0x00, 0x00, + 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x9E, 0x0B, 0x00, 0x00, + 0xA3, 0x00, 0x00, 0x00, 0x9D, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0B, 0x00, 0x00, 0x9E, 0x0B, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x0B, 0x00, 0x00, + 0x95, 0x06, 0x00, 0x00, 0x8D, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x53, 0x0B, 0x00, 0x00, 0x50, 0x0B, 0x00, 0x00, + 0x3F, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x56, 0x0B, 0x00, 0x00, 0x91, 0x0A, 0x00, 0x00, 0x53, 0x0B, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2A, 0x11, 0x00, 0x00, + 0x56, 0x0B, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x59, 0x0B, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x50, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0B, 0x00, 0x00, + 0x59, 0x0B, 0x00, 0x00, 0x9F, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAA, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x5B, 0x0B, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x0B, 0x00, 0x00, 0xAA, 0x0B, 0x00, 0x00, 0xAA, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x0B, 0x00, 0x00, + 0x5F, 0x0B, 0x00, 0x00, 0x3F, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x64, 0x0B, 0x00, 0x00, 0xC3, 0x0A, 0x00, 0x00, + 0x62, 0x0B, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x0B, 0x00, 0x00, 0x9B, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x0B, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x67, 0x0B, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6F, 0x0B, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6C, 0x0B, 0x00, 0x00, + 0xE2, 0x09, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xB6, 0x0B, 0x00, 0x00, 0x6F, 0x0B, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xB7, 0x0B, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0xB6, 0x0B, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB8, 0x0B, 0x00, 0x00, 0xB7, 0x0B, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x74, 0x0B, 0x00, 0x00, 0x9B, 0x06, 0x00, 0x00, + 0x99, 0x06, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x77, 0x0B, 0x00, 0x00, 0x74, 0x0B, 0x00, 0x00, 0x3F, 0x0B, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7A, 0x0B, 0x00, 0x00, + 0xB5, 0x0A, 0x00, 0x00, 0x77, 0x0B, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x11, 0x00, 0x00, 0x7A, 0x0B, 0x00, 0x00, + 0x2A, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7D, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x74, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7F, 0x0B, 0x00, 0x00, 0x7D, 0x0B, 0x00, 0x00, + 0xB8, 0x0B, 0x00, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC3, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x7F, 0x0B, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x83, 0x0B, 0x00, 0x00, + 0xC3, 0x0B, 0x00, 0x00, 0xC3, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x86, 0x0B, 0x00, 0x00, 0x83, 0x0B, 0x00, 0x00, + 0x3F, 0x0B, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x88, 0x0B, 0x00, 0x00, 0x64, 0x0B, 0x00, 0x00, 0x86, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xCE, 0x06, 0x00, 0x00, + 0x2D, 0x11, 0x00, 0x00, 0x2D, 0x11, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD0, 0x06, 0x00, 0x00, 0xCE, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD2, 0x06, 0x00, 0x00, 0xCE, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD3, 0x06, 0x00, 0x00, + 0xD0, 0x06, 0x00, 0x00, 0xD2, 0x06, 0x00, 0x00, 0xB8, 0x00, 0x05, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, 0xD3, 0x06, 0x00, 0x00, + 0xE6, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xD3, 0x0B, 0x00, 0x00, 0xD3, 0x06, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0xD5, 0x0B, 0x00, 0x00, 0xD3, 0x0B, 0x00, 0x00, + 0xB1, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xD6, 0x0B, 0x00, 0x00, 0xAC, 0x00, 0x00, 0x00, 0xD5, 0x0B, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x0B, 0x00, 0x00, + 0xD6, 0x0B, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xDE, 0x06, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xDE, 0x06, 0x00, 0x00, 0xA9, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x58, 0x12, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xD7, 0x0B, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, + 0xE6, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, + 0xD6, 0x06, 0x00, 0x00, 0xE1, 0x06, 0x00, 0x00, 0xE3, 0x06, 0x00, 0x00, + 0xF8, 0x00, 0x02, 0x00, 0xE3, 0x06, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, + 0xE6, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xE1, 0x06, 0x00, 0x00, + 0xF9, 0x00, 0x02, 0x00, 0xE6, 0x06, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, + 0xE6, 0x06, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3A, 0x12, 0x00, 0x00, 0x56, 0x0B, 0x00, 0x00, 0xE3, 0x06, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xE1, 0x06, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x32, 0x11, 0x00, 0x00, 0x3A, 0x12, 0x00, 0x00, + 0x2D, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE8, 0x0B, 0x00, 0x00, 0x58, 0x12, 0x00, 0x00, + 0x58, 0x12, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xEC, 0x06, 0x00, 0x00, 0x32, 0x11, 0x00, 0x00, 0xE8, 0x0B, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEF, 0x06, 0x00, 0x00, + 0x88, 0x0B, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0xEF, 0x06, 0x00, 0x00, + 0xEF, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0xEC, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF7, 0x06, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0xEC, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFC, 0x06, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, + 0xF7, 0x06, 0x00, 0x00, 0xFC, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0xF1, 0x0B, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0xF2, 0x0B, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0xF1, 0x0B, 0x00, 0x00, + 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF3, 0x0B, 0x00, 0x00, + 0xF2, 0x0B, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x07, 0x00, 0x00, 0xFD, 0x06, 0x00, 0x00, 0xF3, 0x0B, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x07, 0x00, 0x00, + 0x06, 0x07, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x07, 0x00, 0x00, 0x0A, 0x07, 0x00, 0x00, + 0xF2, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0D, 0x07, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x0C, 0x07, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x07, 0x00, 0x00, + 0x2F, 0x03, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x12, 0x07, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, + 0x11, 0x07, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x13, 0x07, 0x00, 0x00, 0x0D, 0x07, 0x00, 0x00, 0x12, 0x07, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x07, 0x00, 0x00, + 0x39, 0x03, 0x00, 0x00, 0xF2, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, + 0x17, 0x07, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x0E, 0x0C, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x0F, 0x0C, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x0E, 0x0C, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x0F, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1E, 0x07, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, + 0x57, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x21, 0x07, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, + 0x1E, 0x07, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x23, 0x07, 0x00, 0x00, 0x5C, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x25, 0x07, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x07, 0x00, 0x00, + 0x66, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, 0x23, 0x07, 0x00, 0x00, + 0x25, 0x07, 0x00, 0x00, 0x27, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2A, 0x07, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x07, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x07, 0x00, 0x00, + 0x57, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x2F, 0x07, 0x00, 0x00, 0x2A, 0x07, 0x00, 0x00, + 0x2C, 0x07, 0x00, 0x00, 0x2E, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x19, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, 0x2F, 0x07, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1A, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x21, 0x07, 0x00, 0x00, + 0x19, 0x0C, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x07, 0x00, 0x00, 0x5C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x07, 0x00, 0x00, + 0x61, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x66, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x37, 0x07, 0x00, 0x00, 0x32, 0x07, 0x00, 0x00, 0x34, 0x07, 0x00, 0x00, + 0x36, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x38, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x1A, 0x0C, 0x00, 0x00, 0x37, 0x07, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x20, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, 0x2F, 0x07, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x21, 0x07, 0x00, 0x00, + 0x20, 0x0C, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x56, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x21, 0x0C, 0x00, 0x00, 0x37, 0x07, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x5A, 0x07, 0x00, 0x00, 0x8D, 0x03, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5C, 0x07, 0x00, 0x00, 0x3E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5E, 0x07, 0x00, 0x00, + 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x61, 0x07, 0x00, 0x00, 0x5C, 0x07, 0x00, 0x00, 0x5E, 0x07, 0x00, 0x00, + 0x60, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x37, 0x0C, 0x00, 0x00, 0x5A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3A, 0x0C, 0x00, 0x00, + 0x37, 0x0C, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x00, 0x5A, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3F, 0x0C, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0x3A, 0x0C, 0x00, 0x00, 0x3F, 0x0C, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x59, 0x11, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, + 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x47, 0x0C, 0x00, 0x00, + 0x37, 0x0C, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, 0x3C, 0x0C, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4D, 0x0C, 0x00, 0x00, 0x47, 0x0C, 0x00, 0x00, 0x4C, 0x0C, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x5F, 0x11, 0x00, 0x00, + 0x4D, 0x0C, 0x00, 0x00, 0x59, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0x5F, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x51, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x56, 0x0C, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, 0x53, 0x0C, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x0C, 0x00, 0x00, + 0x51, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0C, 0x00, 0x00, 0x58, 0x0C, 0x00, 0x00, + 0x58, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5C, 0x0C, 0x00, 0x00, 0x56, 0x0C, 0x00, 0x00, 0x5B, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5F, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x62, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x5F, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00, + 0x62, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x67, 0x0C, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, + 0x5F, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x69, 0x0C, 0x00, 0x00, 0x67, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x0C, 0x00, 0x00, + 0x64, 0x0C, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6F, 0x0C, 0x00, 0x00, 0x69, 0x0C, 0x00, 0x00, + 0x69, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x72, 0x0C, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x6C, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x0C, 0x00, 0x00, + 0x72, 0x0C, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x77, 0x0C, 0x00, 0x00, 0x74, 0x0C, 0x00, 0x00, + 0x6F, 0x0C, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x7A, 0x0C, 0x00, 0x00, 0x61, 0x07, 0x00, 0x00, 0x77, 0x0C, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6C, 0x07, 0x00, 0x00, + 0xA8, 0x03, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6E, 0x07, 0x00, 0x00, 0x3E, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x70, 0x07, 0x00, 0x00, 0x43, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x72, 0x07, 0x00, 0x00, + 0x48, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x73, 0x07, 0x00, 0x00, 0x6E, 0x07, 0x00, 0x00, + 0x70, 0x07, 0x00, 0x00, 0x72, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9B, 0x0C, 0x00, 0x00, 0x6C, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9E, 0x0C, 0x00, 0x00, 0x9B, 0x0C, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, + 0x6C, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA3, 0x0C, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, + 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0x9E, 0x0C, 0x00, 0x00, 0xA3, 0x0C, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6C, 0x11, 0x00, 0x00, + 0xA4, 0x0C, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAB, 0x0C, 0x00, 0x00, + 0x9B, 0x0C, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB0, 0x0C, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB1, 0x0C, 0x00, 0x00, 0xAB, 0x0C, 0x00, 0x00, 0xB0, 0x0C, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x72, 0x11, 0x00, 0x00, + 0xB1, 0x0C, 0x00, 0x00, 0x6C, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB5, 0x0C, 0x00, 0x00, + 0x72, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB7, 0x0C, 0x00, 0x00, 0xB5, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBA, 0x0C, 0x00, 0x00, 0xB7, 0x0C, 0x00, 0x00, 0xB7, 0x0C, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBC, 0x0C, 0x00, 0x00, + 0xB5, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBF, 0x0C, 0x00, 0x00, 0xBC, 0x0C, 0x00, 0x00, + 0xBC, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x0C, 0x00, 0x00, 0xBA, 0x0C, 0x00, 0x00, 0xBF, 0x0C, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC6, 0x0C, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xC3, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC8, 0x0C, 0x00, 0x00, + 0xC6, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCB, 0x0C, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, + 0xC3, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCD, 0x0C, 0x00, 0x00, 0xCB, 0x0C, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, + 0xC8, 0x0C, 0x00, 0x00, 0xC8, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD3, 0x0C, 0x00, 0x00, 0xCD, 0x0C, 0x00, 0x00, + 0xCD, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xD6, 0x0C, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, + 0xD6, 0x0C, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDB, 0x0C, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00, + 0xD3, 0x0C, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xDE, 0x0C, 0x00, 0x00, 0x73, 0x07, 0x00, 0x00, 0xDB, 0x0C, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x00, + 0x7A, 0x0C, 0x00, 0x00, 0xDE, 0x0C, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE3, 0x0C, 0x00, 0x00, 0x77, 0x0C, 0x00, 0x00, + 0xDB, 0x0C, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x7E, 0x07, 0x00, 0x00, 0xC3, 0x03, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, + 0x4D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x84, 0x07, 0x00, 0x00, 0x57, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0x85, 0x07, 0x00, 0x00, + 0x80, 0x07, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, 0x84, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0x0C, 0x00, 0x00, + 0x7E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x0D, 0x00, 0x00, 0xFF, 0x0C, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0x7E, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x0D, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0x02, 0x0D, 0x00, 0x00, + 0x07, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x7F, 0x11, 0x00, 0x00, 0x08, 0x0D, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0F, 0x0D, 0x00, 0x00, 0xFF, 0x0C, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00, + 0x04, 0x0D, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, 0x0F, 0x0D, 0x00, 0x00, + 0x14, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x85, 0x11, 0x00, 0x00, 0x15, 0x0D, 0x00, 0x00, 0x7F, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x19, 0x0D, 0x00, 0x00, 0x85, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1B, 0x0D, 0x00, 0x00, + 0x19, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, 0x1B, 0x0D, 0x00, 0x00, + 0x1B, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x0D, 0x00, 0x00, 0x19, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x0D, 0x00, 0x00, + 0x20, 0x0D, 0x00, 0x00, 0x20, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x0D, 0x00, 0x00, 0x1E, 0x0D, 0x00, 0x00, + 0x23, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x27, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x24, 0x0D, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2A, 0x0D, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x27, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2C, 0x0D, 0x00, 0x00, 0x2A, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, + 0x18, 0x07, 0x00, 0x00, 0x27, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x31, 0x0D, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x34, 0x0D, 0x00, 0x00, 0x2C, 0x0D, 0x00, 0x00, 0x2C, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x37, 0x0D, 0x00, 0x00, + 0x31, 0x0D, 0x00, 0x00, 0x31, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x3A, 0x0D, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x34, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3C, 0x0D, 0x00, 0x00, 0x3A, 0x0D, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3F, 0x0D, 0x00, 0x00, + 0x3C, 0x0D, 0x00, 0x00, 0x37, 0x0D, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x42, 0x0D, 0x00, 0x00, 0x85, 0x07, 0x00, 0x00, + 0x3F, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x44, 0x0D, 0x00, 0x00, 0xE0, 0x0C, 0x00, 0x00, 0x42, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x47, 0x0D, 0x00, 0x00, + 0xE3, 0x0C, 0x00, 0x00, 0x3F, 0x0D, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0xDE, 0x03, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x63, 0x0D, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x66, 0x0D, 0x00, 0x00, + 0x63, 0x0D, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x68, 0x0D, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6B, 0x0D, 0x00, 0x00, 0x68, 0x0D, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0x66, 0x0D, 0x00, 0x00, 0x6B, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x92, 0x11, 0x00, 0x00, 0x6C, 0x0D, 0x00, 0x00, + 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x73, 0x0D, 0x00, 0x00, 0x63, 0x0D, 0x00, 0x00, + 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x78, 0x0D, 0x00, 0x00, 0x68, 0x0D, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x79, 0x0D, 0x00, 0x00, + 0x73, 0x0D, 0x00, 0x00, 0x78, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x98, 0x11, 0x00, 0x00, 0x79, 0x0D, 0x00, 0x00, + 0x92, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0x98, 0x11, 0x00, 0x00, + 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7F, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x82, 0x0D, 0x00, 0x00, + 0x7F, 0x0D, 0x00, 0x00, 0x7F, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x84, 0x0D, 0x00, 0x00, 0x7D, 0x0D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x87, 0x0D, 0x00, 0x00, 0x84, 0x0D, 0x00, 0x00, 0x84, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, + 0x82, 0x0D, 0x00, 0x00, 0x87, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x88, 0x0D, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x0D, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x90, 0x0D, 0x00, 0x00, 0x8E, 0x0D, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x93, 0x0D, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x8B, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x95, 0x0D, 0x00, 0x00, + 0x93, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x0D, 0x00, 0x00, 0x90, 0x0D, 0x00, 0x00, + 0x90, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9B, 0x0D, 0x00, 0x00, 0x95, 0x0D, 0x00, 0x00, 0x95, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9E, 0x0D, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0x98, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA0, 0x0D, 0x00, 0x00, 0x9E, 0x0D, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA3, 0x0D, 0x00, 0x00, 0xA0, 0x0D, 0x00, 0x00, 0x9B, 0x0D, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0xA6, 0x0D, 0x00, 0x00, + 0x2F, 0x07, 0x00, 0x00, 0xA3, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xA8, 0x0D, 0x00, 0x00, 0x44, 0x0D, 0x00, 0x00, + 0xA6, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAB, 0x0D, 0x00, 0x00, 0x47, 0x0D, 0x00, 0x00, 0xA3, 0x0D, 0x00, 0x00, + 0x7F, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xA2, 0x07, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC7, 0x0D, 0x00, 0x00, 0xA2, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCA, 0x0D, 0x00, 0x00, + 0xC7, 0x0D, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCC, 0x0D, 0x00, 0x00, 0xA2, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCF, 0x0D, 0x00, 0x00, 0xCC, 0x0D, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0D, 0x00, 0x00, + 0xCA, 0x0D, 0x00, 0x00, 0xCF, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xA5, 0x11, 0x00, 0x00, 0xD0, 0x0D, 0x00, 0x00, + 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD7, 0x0D, 0x00, 0x00, 0xC7, 0x0D, 0x00, 0x00, + 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDC, 0x0D, 0x00, 0x00, 0xCC, 0x0D, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDD, 0x0D, 0x00, 0x00, + 0xD7, 0x0D, 0x00, 0x00, 0xDC, 0x0D, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xAB, 0x11, 0x00, 0x00, 0xDD, 0x0D, 0x00, 0x00, + 0xA5, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE1, 0x0D, 0x00, 0x00, 0xAB, 0x11, 0x00, 0x00, + 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE3, 0x0D, 0x00, 0x00, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xE6, 0x0D, 0x00, 0x00, + 0xE3, 0x0D, 0x00, 0x00, 0xE3, 0x0D, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE8, 0x0D, 0x00, 0x00, 0xE1, 0x0D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEB, 0x0D, 0x00, 0x00, 0xE8, 0x0D, 0x00, 0x00, 0xE8, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, + 0xE6, 0x0D, 0x00, 0x00, 0xEB, 0x0D, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF2, 0x0D, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, 0xF2, 0x0D, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF7, 0x0D, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0xEF, 0x0D, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF9, 0x0D, 0x00, 0x00, + 0xF7, 0x0D, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, 0xF4, 0x0D, 0x00, 0x00, + 0xF4, 0x0D, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFF, 0x0D, 0x00, 0x00, 0xF9, 0x0D, 0x00, 0x00, 0xF9, 0x0D, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x0E, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0xFC, 0x0D, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x00, 0x00, 0x02, 0x0E, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x0E, 0x00, 0x00, 0x04, 0x0E, 0x00, 0x00, 0xFF, 0x0D, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x00, 0x00, + 0x21, 0x07, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x00, 0x00, 0xA8, 0x0D, 0x00, 0x00, + 0x0A, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0F, 0x0E, 0x00, 0x00, 0xAB, 0x0D, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB4, 0x07, 0x00, 0x00, + 0x14, 0x04, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB6, 0x07, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB8, 0x07, 0x00, 0x00, 0x52, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, + 0x57, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xBB, 0x07, 0x00, 0x00, 0xB6, 0x07, 0x00, 0x00, + 0xB8, 0x07, 0x00, 0x00, 0xBA, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2B, 0x0E, 0x00, 0x00, 0xB4, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2E, 0x0E, 0x00, 0x00, 0x2B, 0x0E, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, + 0xB4, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x33, 0x0E, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, + 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0x2E, 0x0E, 0x00, 0x00, 0x33, 0x0E, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xB8, 0x11, 0x00, 0x00, + 0x34, 0x0E, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3B, 0x0E, 0x00, 0x00, + 0x2B, 0x0E, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x0E, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x41, 0x0E, 0x00, 0x00, 0x3B, 0x0E, 0x00, 0x00, 0x40, 0x0E, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xBE, 0x11, 0x00, 0x00, + 0x41, 0x0E, 0x00, 0x00, 0xB8, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x45, 0x0E, 0x00, 0x00, + 0xBE, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x0E, 0x00, 0x00, 0x45, 0x0E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4A, 0x0E, 0x00, 0x00, 0x47, 0x0E, 0x00, 0x00, 0x47, 0x0E, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4C, 0x0E, 0x00, 0x00, + 0x45, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, 0x4C, 0x0E, 0x00, 0x00, + 0x4C, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x50, 0x0E, 0x00, 0x00, 0x4A, 0x0E, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x50, 0x0E, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x56, 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x53, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x0E, 0x00, 0x00, + 0x56, 0x0E, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5B, 0x0E, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, + 0x53, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5D, 0x0E, 0x00, 0x00, 0x5B, 0x0E, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x60, 0x0E, 0x00, 0x00, + 0x58, 0x0E, 0x00, 0x00, 0x58, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x63, 0x0E, 0x00, 0x00, 0x5D, 0x0E, 0x00, 0x00, + 0x5D, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x66, 0x0E, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x60, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x68, 0x0E, 0x00, 0x00, + 0x66, 0x0E, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6B, 0x0E, 0x00, 0x00, 0x68, 0x0E, 0x00, 0x00, + 0x63, 0x0E, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x6E, 0x0E, 0x00, 0x00, 0xBB, 0x07, 0x00, 0x00, 0x6B, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x70, 0x0E, 0x00, 0x00, + 0x0C, 0x0E, 0x00, 0x00, 0x6E, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x73, 0x0E, 0x00, 0x00, 0x0F, 0x0E, 0x00, 0x00, + 0x6B, 0x0E, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xC6, 0x07, 0x00, 0x00, 0x2F, 0x04, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0E, 0x00, 0x00, + 0xC6, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x92, 0x0E, 0x00, 0x00, 0x8F, 0x0E, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x94, 0x0E, 0x00, 0x00, 0xC6, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x97, 0x0E, 0x00, 0x00, + 0x94, 0x0E, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0x92, 0x0E, 0x00, 0x00, + 0x97, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xCB, 0x11, 0x00, 0x00, 0x98, 0x0E, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x9F, 0x0E, 0x00, 0x00, 0x8F, 0x0E, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA4, 0x0E, 0x00, 0x00, + 0x94, 0x0E, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA5, 0x0E, 0x00, 0x00, 0x9F, 0x0E, 0x00, 0x00, + 0xA4, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD1, 0x11, 0x00, 0x00, 0xA5, 0x0E, 0x00, 0x00, 0xCB, 0x11, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xA9, 0x0E, 0x00, 0x00, 0xD1, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAB, 0x0E, 0x00, 0x00, + 0xA9, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xAE, 0x0E, 0x00, 0x00, 0xAB, 0x0E, 0x00, 0x00, + 0xAB, 0x0E, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB0, 0x0E, 0x00, 0x00, 0xA9, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB3, 0x0E, 0x00, 0x00, + 0xB0, 0x0E, 0x00, 0x00, 0xB0, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB4, 0x0E, 0x00, 0x00, 0xAE, 0x0E, 0x00, 0x00, + 0xB3, 0x0E, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB7, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xB4, 0x0E, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBA, 0x0E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xB7, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBC, 0x0E, 0x00, 0x00, 0xBA, 0x0E, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBF, 0x0E, 0x00, 0x00, + 0x18, 0x07, 0x00, 0x00, 0xB7, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC1, 0x0E, 0x00, 0x00, 0xBF, 0x0E, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC4, 0x0E, 0x00, 0x00, 0xBC, 0x0E, 0x00, 0x00, 0xBC, 0x0E, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC7, 0x0E, 0x00, 0x00, + 0xC1, 0x0E, 0x00, 0x00, 0xC1, 0x0E, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCA, 0x0E, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xC4, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCC, 0x0E, 0x00, 0x00, 0xCA, 0x0E, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xCF, 0x0E, 0x00, 0x00, + 0xCC, 0x0E, 0x00, 0x00, 0xC7, 0x0E, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xD2, 0x0E, 0x00, 0x00, 0x37, 0x07, 0x00, 0x00, + 0xCF, 0x0E, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xD4, 0x0E, 0x00, 0x00, 0x70, 0x0E, 0x00, 0x00, 0xD2, 0x0E, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x0E, 0x00, 0x00, + 0x73, 0x0E, 0x00, 0x00, 0xCF, 0x0E, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xD8, 0x07, 0x00, 0x00, 0x4B, 0x04, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDA, 0x07, 0x00, 0x00, 0x5C, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDC, 0x07, 0x00, 0x00, + 0x61, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDE, 0x07, 0x00, 0x00, 0x66, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xDF, 0x07, 0x00, 0x00, 0xDA, 0x07, 0x00, 0x00, 0xDC, 0x07, 0x00, 0x00, + 0xDE, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF3, 0x0E, 0x00, 0x00, 0xD8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF6, 0x0E, 0x00, 0x00, + 0xF3, 0x0E, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, 0xD8, 0x07, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xFB, 0x0E, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0xF6, 0x0E, 0x00, 0x00, 0xFB, 0x0E, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xDE, 0x11, 0x00, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x00, 0x00, 0xF3, 0x0E, 0x00, 0x00, + 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x0F, 0x00, 0x00, 0xF8, 0x0E, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x0F, 0x00, 0x00, + 0x03, 0x0F, 0x00, 0x00, 0x08, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0xE4, 0x11, 0x00, 0x00, 0x09, 0x0F, 0x00, 0x00, + 0xDE, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x0F, 0x00, 0x00, 0xE4, 0x11, 0x00, 0x00, + 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0F, 0x0F, 0x00, 0x00, 0x0D, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x0F, 0x00, 0x00, + 0x0F, 0x0F, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x0F, 0x00, 0x00, 0x0D, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x17, 0x0F, 0x00, 0x00, 0x14, 0x0F, 0x00, 0x00, 0x14, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x0F, 0x00, 0x00, + 0x12, 0x0F, 0x00, 0x00, 0x17, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x18, 0x0F, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x23, 0x0F, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x1B, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x0F, 0x00, 0x00, + 0x23, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x28, 0x0F, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, + 0x20, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x2B, 0x0F, 0x00, 0x00, 0x25, 0x0F, 0x00, 0x00, 0x25, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0x28, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x00, 0x00, 0x2E, 0x0F, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x33, 0x0F, 0x00, 0x00, 0x30, 0x0F, 0x00, 0x00, 0x2B, 0x0F, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x36, 0x0F, 0x00, 0x00, + 0xDF, 0x07, 0x00, 0x00, 0x33, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x38, 0x0F, 0x00, 0x00, 0xD4, 0x0E, 0x00, 0x00, + 0x36, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3B, 0x0F, 0x00, 0x00, 0xD7, 0x0E, 0x00, 0x00, 0x33, 0x0F, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xEA, 0x07, 0x00, 0x00, + 0x66, 0x04, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xEC, 0x07, 0x00, 0x00, 0x5C, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xEE, 0x07, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, + 0x66, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xF1, 0x07, 0x00, 0x00, 0xEC, 0x07, 0x00, 0x00, + 0xEE, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x57, 0x0F, 0x00, 0x00, 0xEA, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5A, 0x0F, 0x00, 0x00, 0x57, 0x0F, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, + 0xEA, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, + 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x00, 0x5A, 0x0F, 0x00, 0x00, 0x5F, 0x0F, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xF1, 0x11, 0x00, 0x00, + 0x60, 0x0F, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x67, 0x0F, 0x00, 0x00, + 0x57, 0x0F, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x6C, 0x0F, 0x00, 0x00, 0x5C, 0x0F, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x6D, 0x0F, 0x00, 0x00, 0x67, 0x0F, 0x00, 0x00, 0x6C, 0x0F, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xF7, 0x11, 0x00, 0x00, + 0x6D, 0x0F, 0x00, 0x00, 0xF1, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x71, 0x0F, 0x00, 0x00, + 0xF7, 0x11, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, 0x71, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x76, 0x0F, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, 0x73, 0x0F, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x78, 0x0F, 0x00, 0x00, + 0x71, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x7B, 0x0F, 0x00, 0x00, 0x78, 0x0F, 0x00, 0x00, + 0x78, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x7C, 0x0F, 0x00, 0x00, 0x76, 0x0F, 0x00, 0x00, 0x7B, 0x0F, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7F, 0x0F, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x7C, 0x0F, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x82, 0x0F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, + 0x82, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x87, 0x0F, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, + 0x7F, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x89, 0x0F, 0x00, 0x00, 0x87, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8C, 0x0F, 0x00, 0x00, + 0x84, 0x0F, 0x00, 0x00, 0x84, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8F, 0x0F, 0x00, 0x00, 0x89, 0x0F, 0x00, 0x00, + 0x89, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x92, 0x0F, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x8C, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x94, 0x0F, 0x00, 0x00, + 0x92, 0x0F, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x97, 0x0F, 0x00, 0x00, 0x94, 0x0F, 0x00, 0x00, + 0x8F, 0x0F, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x9A, 0x0F, 0x00, 0x00, 0xF1, 0x07, 0x00, 0x00, 0x97, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x9C, 0x0F, 0x00, 0x00, + 0x38, 0x0F, 0x00, 0x00, 0x9A, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x0F, 0x00, 0x00, 0x3B, 0x0F, 0x00, 0x00, + 0x97, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xFC, 0x07, 0x00, 0x00, 0x81, 0x04, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xBB, 0x0F, 0x00, 0x00, + 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBE, 0x0F, 0x00, 0x00, 0xBB, 0x0F, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0xFC, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC4, 0x0F, 0x00, 0x00, 0xBE, 0x0F, 0x00, 0x00, + 0xC3, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x04, 0x12, 0x00, 0x00, 0xC4, 0x0F, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xCB, 0x0F, 0x00, 0x00, 0xBB, 0x0F, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD0, 0x0F, 0x00, 0x00, + 0xC0, 0x0F, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xD1, 0x0F, 0x00, 0x00, 0xCB, 0x0F, 0x00, 0x00, + 0xD0, 0x0F, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x12, 0x00, 0x00, 0xD1, 0x0F, 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0xD5, 0x0F, 0x00, 0x00, 0x0A, 0x12, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xD7, 0x0F, 0x00, 0x00, + 0xD5, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xDA, 0x0F, 0x00, 0x00, 0xD7, 0x0F, 0x00, 0x00, + 0xD7, 0x0F, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xDC, 0x0F, 0x00, 0x00, 0xD5, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xDF, 0x0F, 0x00, 0x00, + 0xDC, 0x0F, 0x00, 0x00, 0xDC, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xDA, 0x0F, 0x00, 0x00, + 0xDF, 0x0F, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE3, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xE0, 0x0F, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xE6, 0x0F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xE3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE8, 0x0F, 0x00, 0x00, 0xE6, 0x0F, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEB, 0x0F, 0x00, 0x00, + 0x18, 0x07, 0x00, 0x00, 0xE3, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xED, 0x0F, 0x00, 0x00, 0xEB, 0x0F, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF0, 0x0F, 0x00, 0x00, 0xE8, 0x0F, 0x00, 0x00, 0xE8, 0x0F, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, + 0xED, 0x0F, 0x00, 0x00, 0xED, 0x0F, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xF6, 0x0F, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0xF0, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xF8, 0x0F, 0x00, 0x00, 0xF6, 0x0F, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFB, 0x0F, 0x00, 0x00, + 0xF8, 0x0F, 0x00, 0x00, 0xF3, 0x0F, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0x28, 0x07, 0x00, 0x00, + 0xFB, 0x0F, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x9C, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, + 0x9F, 0x0F, 0x00, 0x00, 0xFB, 0x0F, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x08, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00, + 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x00, 0x00, 0x6B, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, + 0x70, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x75, 0x08, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x15, 0x08, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, + 0x14, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1F, 0x10, 0x00, 0x00, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x10, 0x00, 0x00, + 0x1F, 0x10, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x0E, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x27, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0xF9, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0x22, 0x10, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x17, 0x12, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, + 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x2F, 0x10, 0x00, 0x00, 0x1F, 0x10, 0x00, 0x00, + 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x34, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, + 0x2F, 0x10, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x1D, 0x12, 0x00, 0x00, 0x35, 0x10, 0x00, 0x00, + 0x17, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x39, 0x10, 0x00, 0x00, 0x1D, 0x12, 0x00, 0x00, + 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x3B, 0x10, 0x00, 0x00, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3E, 0x10, 0x00, 0x00, + 0x3B, 0x10, 0x00, 0x00, 0x3B, 0x10, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x39, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x43, 0x10, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, + 0x3E, 0x10, 0x00, 0x00, 0x43, 0x10, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x4C, 0x10, 0x00, 0x00, 0x4A, 0x10, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x4F, 0x10, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x47, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, + 0x4F, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, 0x4C, 0x10, 0x00, 0x00, + 0x4C, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x57, 0x10, 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, 0x51, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0x14, 0x01, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x5C, 0x10, 0x00, 0x00, 0x5A, 0x10, 0x00, 0x00, + 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x5F, 0x10, 0x00, 0x00, 0x5C, 0x10, 0x00, 0x00, 0x57, 0x10, 0x00, 0x00, + 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, + 0x15, 0x08, 0x00, 0x00, 0x5F, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x64, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x67, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x5F, 0x10, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, + 0xB7, 0x04, 0x00, 0x00, 0x22, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x22, 0x08, 0x00, 0x00, 0x6B, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x24, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x08, 0x00, 0x00, + 0x75, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x27, 0x08, 0x00, 0x00, 0x22, 0x08, 0x00, 0x00, + 0x24, 0x08, 0x00, 0x00, 0x26, 0x08, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x86, 0x10, 0x00, 0x00, 0x83, 0x10, 0x00, 0x00, 0xF4, 0x06, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, + 0x20, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x8B, 0x10, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, + 0xF9, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0x86, 0x10, 0x00, 0x00, 0x8B, 0x10, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2A, 0x12, 0x00, 0x00, + 0x8C, 0x10, 0x00, 0x00, 0x59, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x10, 0x00, 0x00, + 0x83, 0x10, 0x00, 0x00, 0x46, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, + 0xF4, 0x06, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x99, 0x10, 0x00, 0x00, 0x93, 0x10, 0x00, 0x00, 0x98, 0x10, 0x00, 0x00, + 0x52, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x30, 0x12, 0x00, 0x00, + 0x99, 0x10, 0x00, 0x00, 0x2A, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, + 0x30, 0x12, 0x00, 0x00, 0x13, 0x07, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x9D, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA2, 0x10, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x00, 0x00, + 0x9D, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xA7, 0x10, 0x00, 0x00, 0xA4, 0x10, 0x00, 0x00, + 0xA4, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xA8, 0x10, 0x00, 0x00, 0xA2, 0x10, 0x00, 0x00, 0xA7, 0x10, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xA8, 0x10, 0x00, 0x00, + 0x10, 0x0C, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xAE, 0x10, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xAB, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, + 0xAE, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, + 0xAB, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0xB3, 0x10, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xB8, 0x10, 0x00, 0x00, + 0xB0, 0x10, 0x00, 0x00, 0xB0, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xBB, 0x10, 0x00, 0x00, 0xB5, 0x10, 0x00, 0x00, + 0xB5, 0x10, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xBE, 0x10, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0xB8, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xC0, 0x10, 0x00, 0x00, + 0xBE, 0x10, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, 0xC0, 0x10, 0x00, 0x00, + 0xBB, 0x10, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, + 0xC6, 0x10, 0x00, 0x00, 0x27, 0x08, 0x00, 0x00, 0xC3, 0x10, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0xC8, 0x10, 0x00, 0x00, + 0x64, 0x10, 0x00, 0x00, 0xC6, 0x10, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, 0x67, 0x10, 0x00, 0x00, + 0xC3, 0x10, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0xE0, 0x10, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0xCB, 0x10, 0x00, 0x00, + 0x50, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, + 0xE0, 0x10, 0x00, 0x00, 0xE0, 0x10, 0x00, 0x00, 0xE0, 0x10, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x37, 0x08, 0x00, 0x00, + 0xC8, 0x10, 0x00, 0x00, 0xE9, 0x10, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x38, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x38, 0x07, 0x00, 0x00, 0x37, 0x08, 0x00, 0x00, + 0x0C, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x56, 0x07, 0x00, 0x00, + 0x38, 0x08, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x1A, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x1B, 0x05, 0x00, 0x00, 0x1A, 0x05, 0x00, 0x00, + 0x39, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x08, 0x05, 0x00, 0x00, 0x1B, 0x05, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x1C, 0x05, 0x00, 0x00, 0x1D, 0x05, 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, + 0x61, 0x02, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x05, 0x00, 0x00, + 0x93, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..f58c4026f10eaf00aaa06485b970f6acdfba23e4 GIT binary patch literal 15936 zcmZXb3zU}Cb%s9$6cGg#Z^6rWi_{B{1O?P6*63J6ikB|$?SOzd6@ktSMvW2gnq{Ji znrdRyEH#aZS*bQL5_KV#EMg;xw|J>Fh|ySMOrzqpqV{=)?`7>Z{nk4Cdp~=hea_k6 z`+qb1Gc#!YT{di*^_pSL(B{O=oBnIFW_?K0Y}{kes#H21T{S+l$PW}nr! zu!kB$SbZf)$Im{jx989qy$cVSKd-lM#=O4XhSLr2k1@qLr}p-A%_gI(d)|VDeO>bx z_W9D=ea`Hzo*8}J^T{99pYOTr_q;P*b5OI&jd2ZOmi;ilXU3eane*q)?`gR` znlrcSF!&+!=l9GqzmpSrhMje|;_tN9Z4RfR=keNwF_IDHzGT}lI@yDH_S_ooVFzq4 zeb?R?djw+(vdr75|1PbavlaFRunxx7yvE(j zM~q*uSaD$dK_)lnKM;RZzyHv>^KaYlk6ahu$zn~@ANTw-@VyV2|MJ@Sr1;|uHqE;E zlks0T=h`KEp(XF@*YI!P)qRBB4)Z=#whX2(Pu|LQZe^pmndVtDdE;Q_II^!Jyy;Cd zB{`qRm(^OQwyf5=pv|f5J1uj5>fM8Fj%){d@B6{?I=t7<<8Op5_g?F-YMJpDTHE}+ zc#f#?H()u3uWS3WHufGd{hYzqoRwB{oj=98>tVaDTF~DRpEmZ_cOUw`UuDKO!lvxH zxW4aSnepw~TkglS+qe_g}969)$AE!Tf7Ke$QCN zSPJ_rna+K&<>%s0$A1Z5b|rI+|99)V=0z?0BTVi-Gw)S=dDeOp+qITcBWtb3mrtXE z-jBDiWezWU;^pfltYyyI#Jq3jy4ESMcd+HjS%dBUt2rOy%bhctIUi%Ir-Qk3-oy17 z*`LoG_vk$s)W)o>KiCE`d1~#AZGH6_HnwHzH1)^9%r%z!!+|?L!MguV0*v4!uD-h-Ty?GxyDj|61F_`Cu6&YJheWHZT-6c16x-2e-O-EW2rv{ zTb}v{V_RRIb9Z8^Pj!`fhr{HV_cz$ildC(w#vQ=T_3PVo?zuWV5MO5A(!viZe0kxA z7rvtKFSOiV)H+8OUh5oJc&&4C%RO_gGo$cY=hVV$ozq)x4{DtSh1WU@3%5?56SJ7_ znSGXq&4JlBnZ34;-7vX*3;RcW=Nrr1Gq62-t+xPX|7yJ+nB4xQUN64$jiuh1*!G~- zI~!&nYrQYQ>i%=6W} z8(UWMenUTeUV8cb)O-Zy_YTIgm&e;Y_maFP+B{?459j_C+xf7H_)!7#b!%6^8)nD0J~C3iTsG3yTJtCDM+gl+Dg4C8)%wzrux5@wDgYzu6; zYi4iT;H$6N!_hE(HJiO{56j-16TV~N&PxwFT0Vw7IoG`Oa1OTd^zbxndniv2yRqfj z=Wf{U(>>)pV_@>y!?F0;r?KRY$2Ml&^so;*Jv2VBhZA7tI8tXKw%j#+zq6fYGQPbv zmb_cB)p^zH&tbmL)I$2V1eX08PyZflx&1Ro4X1xw3~L(W>E9@P`zKHTw#1gFf6K{t zZSQOL_#ZI2d(Bx^V5?1I+2bSF*`xWH{}{G0*Gf-2u+vlH1AF=;%p6DRJOh*0eLRbA zUybDqzr*%+_mngK878l1d>vm68_OP7V`uN?Xa3vR##}4Co{XJd8z0!~_hIHZQfCcJ zUia}4zWp|qydLKGy!9EJbDanCT)q#(E`aI#bt`AM2$nNAC;XDaotOS!+H(8vT=UZZ zXRwW@|Nn_?|K;ibv)J7H_)D`9fa6|H{*TfH009h}&n{d~*qsX6L0J-rd% zczSvhwmp@nr#EBE)6*ldUEBMaJsty-yVq#)SZsA^>}bBa45#iMeCR0mvkI^5{RCL{ zZk^OU$y|neNUwj0on9Ls*y}EsIgZph1zTSCHw)i>8_U_|VEcVx?dx1v_GUbNo!@f% zYL3s_^z~=>#?#k(u;5jsx3|X3^S=LvGr31czF&S6Cie<^ zyk+hqI(hu(^LtWr-{teRmkn_JFW=!Bdx7yH!@0g%%N%`U)tA5Bet*6n zwU4EybF6P}?&+uLm2rFK<>v(U@)h#klOz3ojd|u9%f0yv%zNQyc42SA+NuPdU#fZH}?j+YH;!uv{oJAcpLPe>(F0fq z%+D;$I}(*Ev7KPfH{W<_`qM=}dtl4!*lsXCcc^T4n4eq7QgaN<`Q{r>%{{Q)r&6-`ujqL{_rj>piUZm_dyu??VDkE` zn1b(oV|nhKz|EBBdxS;pXAy_NoSS-`_^vAtn~Lok?j`TvFW{SNENgVJhTOHXN8IKp z{xRnJHfKHtCiluZ$KuQTW84FlYmRU8QcrdgOzy~jPR4e=G4HK;UD(l!ao^Wj>lAE% z-e^v0%)*xYv#R9H!S{Jl^SWX3nl~5U`Hsw;k8Q3atOwhlW163J`>^HyJTrM;#Ftyc zpBK@-<{WG_WGot;i|@}Qt48O+)Tn1qzZbyNXk|SxH7bindtuHu-+1QVz?!b*l|9}B zlUI#?x6QL=@@|F6t443bcfPUcXD)}7N28g42h4SiBwFmI!j@;L!*v>Z=O)kTBp3hU`Rg=r{)ucJ8 z@esDWYVBcsHCgk14U^ZrNAaES$a$W?HrEmM6tQB8 zT3$Kx`kU}`A$Zm9V3>LJzHSJUSM3hPcfPUcY!L^S57h1mnCn#Sj)GaUYIjR~bB(3u zCDfE#JA0y3vn|Y6)$VAR+$(3?0blM&FFLTzOFgx_3%=Zu`?V{!^NmHjyJI^~?HaGz z-2-3knv)uPVaux~$Kk8pn)fM~yyi{7cfKR%nTTz!BWyoxwQGLXJpfx?wR;f0+#1pD zUt_BoW6q_e&F8Syud&qY#8$uNMY~^Tp1NdFU)nS&d$QOX4To*_~sf*&FiTtw|4fV&b|yYR&}-rCilu2FT|HS zqO*&!%}YIXb{W3hk=|a8?R;a=*%jE%Q)kAj&aT8)XXd2F*RkbQKiA-^vzqr!n7rm) zkMDd(&T|8{xsI@#u+^FQS@*lx@~X32@#WTt&i)14@0*P|mzFlSW2-e|sdopqS~Jh@ z&%6h>Ft2Ltm&9aV+1syR@~W{FZC>sFBQSZ@*rWK)Hx@m7j}6KPYV2v4>r{_wQ|D`$KeU+##;Ucojm_0-s(@a2y5^)+ng8;i#N zg6%vtX1r?bO?)+GPHMb`Ew9>n7hjFly!T=9nzshu`Hr0DV{CIBVe4V5qTOkTA+0pIz?qO-*uTs}~{ z`@>wPYIh30HLG?H#y8hkYA&Is+}hcb+C3CztZKItCilu2kHD8Z(u=9s=B1w6orW)W zgD{2j`w-K&Vpy|TZn zVe+c8Yumhf53YmBtIn>+cfPS`;$b!^AE>jNVXjkkb{oDmtIocMZ?3V_e2kiMYiCdD z><2JoRcCj==g-;8b!JX# z+>b4<`gs6foz=VtVe*>y3w-B0a-Lseo9hVs6}CDvKkKf*mRFrUf-kp5boMy5pYIrR zE-h_-i>=m-rQXxnYR$ap>>1|yd$?6+&%*qS%O0iQ&%ykRtFo0aKjV_+8TmZS`Q{tX z{MD@KT3$KxJ1}|G?t5*XHIw%NOkTCS2H*L{qO+A8Ts}~{gZQO)*Qwea3bSU_?nW?k zjiu&G)RbF0ds4fbz>HPxj)2L%viHsL<&N}X6t;P(r*^l-mpgL5w!wD3v1oTRw)51k z@v7Y&@YSw4snLNgubSKiU+vbs-C**XHwNGNj+|#tY;zr9W3kn)`B`^7w!CWhGx&0A zM7#T9s~Ka?rKQazZ1rm__4dbBzve}|uQJcy7q8lV4W@SMXWIV*Q@fSD?%b9|yKlgp zZ@%%|uj5$LwY+lX6JheI-ILqAdSAO>@~YkG_|7*LoxQ=q{_$-Q#MGx6n)^x`aR^HNXkehFXh$o)DO+xf<#-9^~W zQ@h5ib}z(NyXK_E#n|$y$;N3w-ArizWv1b3pk(ojnY5ovO1(@vT{P_87jo#!_<_HRaaMp48csFk@9`Ps8M1 zIpeeVaz}Lb9JYC>r_P?ompjtiRoKoq7M;C_?L2j6yz1;_e063{YP^Ciulo5DzB;RU ze}>6x-s||zcjP>)vCVaay@RdJ%+I>-Vauz|KERh-BRcyC+n@aybFMn`55d%$vD6y` zQ)}i$XPfej^KWIU&PKxgect*!+#KKE<*jTKzP}4B%QJFIeCL~QJojry)^;tgoOx%M zylQvXHm}~--C^>o-7)yiHx`|3jh5sCwL1>xI#s(9@U2<3yAQs(#!_>8YRavhJ*nNv zFk@A_`@`g3Ipcx&az}bG1>3yTQ@e-Y%N@C2pTl;(v1qpw+j(l&c-8I^_-faj)R>Ab zubP~OuXbzRQ80PU`#XH+J93`mu+4RZortY=&Cj|gW6P^{yYS`Kh;~oGRx`$&t9EB$ zt6yWOHwRn&niuVMFwei~s@mNdrgrQ9)px~LyOn(sU+vcazweIkeDjUxeqF?xuH}_8 zU+O*>RlAqBdG)?t0h3qleih&O#-g)5(2{(hcCUfCPSx)9_|~l2{T9Bt#!_=UHRaaM zp49G*Fk@A_H^by!IpZz(az}b`8@73=r*^-OFL&gA-Hz>iW6|y%*v?bC#;bOJjIVah zNsT+P3&U4}2WMzp&eTg@1A zuG)PFTm2eKy@#>YuX&e~XU|q)`@15>^6dO0wmic zw=w(d&-u;G-<5r0$lAXp%-_q6#+NyVw-PI^{X0b87YFk0@b3=IIhcrlSGYYxHiL)0 NaedG6A-kEx_&>)}{f+~;bv0=SH2u(~d1;Ik^y@lQhz4s7$ z?=^(pd#?$-yzjp`v)5Uycl9^(?Y(EunK|d|nR}Pnvc8lv5Xch99mo}^OiQ1~0$H&H z0(k;qp}*l(zN}I_F1}9jci($U{(OOK`V;cy59ADFr!DKANE?-=O=*UJ1 zb^HN2i13e_BakDINdBf#!T6}A@d>fy$iW{D>^H!e09OGGdxA--`!d@!bN-MFZDd|`pSp*XFT zKQ69*t=PuVQE_p>#xZg6L4p$+D_0KIU@~K7w!=beq<&miFfyi5Oe~IYW~4b3$qX|t z>|@O*51b!WB&+73&r7HPayDI;Y|o%@##Wr}fyU7NDM(wNC$P$1ICPgXW1b`?3|k?j z&(pB(qil+Oir7c^TPURLJQJDsSvK`87P4nPBkKDGESvg@-{h}ib^l)Hzsg%4X-W+q6k>{26@eWZhDZtH1{j95DVI-ne0d#aD&Lj~i$H2zdCg zg66LVckR-}{9nLx=gcvGb$I5C8Rq{I?$AEW_$zqC@ZrW^!`ruQv;N<}g9kll{%_&L zzJ2Gr>#qU#?$yiu-@z&K=Ue~p;l+yUlSfZs)*&U1>d`S*RHQNd_5z>{E=|a9zCqTUbJmnw0dC!@ zmBlxK2Mru(@xR0KlS^29Q+W5TT^8RA-nwOr#s2}%nLXR$|Af=8U9wX3lf-wIy4W{q)cc+$kzjN8ByCrq$>ZQ<1I)y>}y zUbUc)>gFsJz?Hgi|+-uZ`aPaH=MR(hvn}B@7Z0$`uByoUlyMTvtGvi z;9fm@+Vj*OKCpkk;P3-b?y z`}cdw{KMg!H*T1J1iWT-1@n)DxxeNg1>e1M$NZz=y?geUKMC&Gp@Z=lxJ~P<#$#cg zSL1Oo^{JGb?|691lX=xTe3BG#eiuotQOBR7Qw|tvn*2D5`fq7mnek(j{<~!!! z2D3kye>=?i!#EY@{k8l%;In7Wm_H4s9+`h9%>HWmcfq_r7QY+bxA%MFJ@C;ZM=X9X z+`U^j<9#so-s1Pe>`&%D0CPRY2Vv%C@rPjcC-WbMr%st-d<15Hvgz;cKMhmwE#DcK^NNjs7N%aC{~XNwW%aE4!ggIXt--6jct^aM9{oMEtylCMVcsXpR}>yM_7&q-VCskU{};S#=Qrkm6=pv(|G#0LS6k25 zV9ulFe;wxeHZBJ9K3M!4F#Ch8Z*lncty>oVCd~IcNF|_f7Nv z2j=`~dlvrz%=cBxR|2NK7?*_kera3^=Dcq6`4Hy&nE5|~ z**}c`3$y;E+V zKs`|})Eo6deNiInhx(%dXdoJd2BRTpC>n-_qY-E%8ihuqBs2z%MdQ$TGyzRSlh9-| z1x-cM&~!8d%|x@%Y%~YWMe|THnvYV@0<;h&_Q$v9Y#mcQFII)M<>upbPAnD zXV6)64xL9A&_#3!T}D^XRdfxdqYQK%-9R_dEp!{*L3hzTbRRuH+IzL%YLC^vs=ZYE zr}j+kliC}#A8HTOzNfuT`s`0Aps^zNRs@ba3s?Dm$s==zesp`=aB6~j}twc@)x7~0FU)s>0sK*pA9+x1Z)rZ6yx{bH?U8H)kk(`o8htS zuHPcs{A)3b0ofGe`mOR_mYyEd%(=*}Z>}lBb>^Qmg+T-QWnueY={!^ZO()-x79NCdR zgi;T(V$Gb7p3kR=SHJ%f^(KGE5u`PVz^e5gPg^!gAG)yjWd6=R0h|0~$*8rMinKnu z$I7R5ndaGB6C<7utDo$D5u>qZ(3V|!w1%^h^60rx9<9$D&#pdtPUgb0iIulDlT@CT z-Z*t&+4Q_Bhu(qBOkB@@9a!(kR#>(mSE0FYqb-~IYTY!CFUY6yQ?bjhkF)LYY=oID z&9kY$yO#Riwdg%@WA7u*KlXlDHpM*K~g`NzHr%cj_e$4wHhZuAky`4bIoz*H8CZ>)?DHd_FyYigmtcVV6^JnuGIo^YznnqIGn>?mnNM zU&T7#i@uzpIG?Yt*YDN;GxtQFPjgqS%URURseX#{&wa43-@|hs;`3?ligh_(_vKWa zf9|7v{T`nCXrE7WSFFqVwl8NW&gXmA^A%+%-AlbY9lcsHnK_=hs#lkw))8Da#V$tL-#}1 zthu!Dt~-LZ_8i5y9Mx%SpVhoud2wIUmR3uIG2!?t0|Ynz`6!wDlag*gt8z zSot(R7yCDD-ESA$g0_p5PuJpn>0FQVDW_tcFT>~4wJFy5+QaHs6e&*U7U%2W`Se`r z9Hv<9*P3%@+S%9C&#iM$+Oq4OxU)bQhX~nq#^4eHIbofnWq0G{ zq8+k(>t#RdZadTkV z&mtE$kGAaoaVyX#4clSl`i5hZU3;XnRfJ{NUgPqurmb=1b8%~7+0P*tx1P4_8nfCcjwM@BAA*zrJJ0FV;Bj?7PYHNAUjx=`6k( zmQB(JQ|RolhU?+70x$3%ojEJ6o$8sGvmjoV`dqVXfk~nQeQ08cW8h z2>erOS{8j$Q$Na3Bg;x6`p`dpj6qOje=3M5h<*e?guTzX`=!m$fz4U#ec!d#UVHCz z?zv5q7q^BmDNGMj!@QP|Uvt7_AtB5NE&09BwZ3ao$kx@PKLz7qfbCxIR=>j%M}1d^QheYpXq**ObfE zK1qbPhR229SzKGI-rCz!TT?F8>OG};Ehu7o&Y@GT{#rGwN|BX^>Xo5-R_^bw73<@RA#xlcbcZ)L0Rd8Yq3VVhB4*^HeaKl+USsyll@sBn`^F6@J0D9H8f|*<~S_W zm?wQ(v~|n<3!+brv&CPiI~aNJFV>xS_6L8N?&N@9A|LKHjSxmx+25G^4IZtwFPwhi zj}h}*8+_+EVOkiLO%Cd(m;G}!|7{}BEmXbxqX_Kk=(EmTqW=u918e^|VADlS)J*>fH|A=hz*nd}cx_-Ch&5o{QeLs`U zdZhf94gN#o;l6J8o%WX_4xJycK99)3@kPnurS9*U#HW;x= zmG`ku`KW(TI6RlJLlI+5j2(^`@t(_daW0&B*M3L3wDwW?U}z`Seor_&m+QPAv9$KF zh!O8P9|=qAd@LV~wV7DwQ{nJju5&zMX`K@hOMAR2_Bf_k*Zy3(wDuSB!O%{uJuV!c z%e7BNEUo=j#M0W`u{Q4p*ZxMjwD!01!O%{u{he@lF4sO4v9$L05hK1$XNGgJK@Sg_ z4h{B+KFn=QIL;4RbH8gIjzh;B%xy~I*k{(kTyMg0{?MBHGs%gL9?T6Sahwy@(cG4V z}uKMgmeA1@?D>`VhvrtAe;JVoa08>)Mve2|7Ky}Y5h-PeK^N<%O)q> z4*d@C4p}Fk^Wpidm+kq$v1ZoZE}L^;?H#hMg`+=f?~=`aTf0HFwQ$VE+_>grj+|)C zolH39hSuCB`NVZ-pyONATyNxf&iQ6S%kMQk_sixt-0QMgK6-FtTV%7&a9-y@+2HJn zzXg6!U2wiJ_%`@aeo=RD*ZWB}xYy=q*#L7&z}XW3%Lgj|+3Y?Xu|)&bkr#;5>)cjmie6zIC$|!+VhTq_K8k;HMI7j(qTw z!kllHZ0f=}c8`4U;~LiOl?|TOJwq{vg&osy>|9~syd#aBDIc8Q8s~dSHg(~w8+-$7QeV9Itc&?KBhU9gJU;U`|5oJrKLC$U9rJHHUUztW M&e=aY;VU%$1+wdxIRF3v literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt new file mode 100644 index 000000000..ca7e98acf --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.txt @@ -0,0 +1,207 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 1557 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %gl_FragCoord %xe_frag_color + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 420 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %main "main" + OpName %xe_texture "xe_texture" + OpName %gl_FragCoord "gl_FragCoord" + OpName %XeFsrRcasConstants "XeFsrRcasConstants" + OpMemberName %XeFsrRcasConstants 0 "xe_fsr_rcas_output_offset" + OpMemberName %XeFsrRcasConstants 1 "xe_fsr_rcas_sharpness_post_setup" + OpName %_ "" + OpName %xe_frag_color "xe_frag_color" + OpDecorate %xe_texture DescriptorSet 0 + OpDecorate %xe_texture Binding 0 + OpDecorate %gl_FragCoord BuiltIn FragCoord + OpMemberDecorate %XeFsrRcasConstants 0 Offset 16 + OpMemberDecorate %XeFsrRcasConstants 1 Offset 24 + OpDecorate %XeFsrRcasConstants Block + OpDecorate %xe_frag_color Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %int = OpTypeInt 32 1 + %v2int = OpTypeVector %int 2 + %v4float = OpTypeVector %float 4 + %v2uint = OpTypeVector %uint 2 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 +%uint_2129764351 = OpConstant %uint 2129764351 + %float_2 = OpConstant %float 2 + %120 = OpTypeImage %float 2D 0 0 0 1 Unknown + %121 = OpTypeSampledImage %120 +%_ptr_UniformConstant_121 = OpTypePointer UniformConstant %121 + %xe_texture = OpVariable %_ptr_UniformConstant_121 UniformConstant + %int_0 = OpConstant %int 0 + %int_n1 = OpConstant %int -1 + %144 = OpConstantComposite %v2int %int_0 %int_n1 + %151 = OpConstantComposite %v2int %int_n1 %int_0 + %int_1 = OpConstant %int 1 + %164 = OpConstantComposite %v2int %int_1 %int_0 + %171 = OpConstantComposite %v2int %int_0 %int_1 + %uint_0 = OpConstant %uint 0 + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 + %float_0_25 = OpConstant %float 0.25 + %v2float = OpTypeVector %float 2 + %float_n4 = OpConstant %float -4 + %float_4 = OpConstant %float 4 +%float_n0_1875 = OpConstant %float -0.1875 +%_ptr_Input_v4float = OpTypePointer Input %v4float +%gl_FragCoord = OpVariable %_ptr_Input_v4float Input +%XeFsrRcasConstants = OpTypeStruct %v2int %float +%_ptr_PushConstant_XeFsrRcasConstants = OpTypePointer PushConstant %XeFsrRcasConstants + %_ = OpVariable %_ptr_PushConstant_XeFsrRcasConstants PushConstant +%_ptr_PushConstant_v2int = OpTypePointer PushConstant %v2int +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Output_float = OpTypePointer Output %float + %uint_3 = OpConstant %uint 3 + %main = OpFunction %void None %3 + %5 = OpLabel + %655 = OpLoad %v4float %gl_FragCoord + %656 = OpVectorShuffle %v2float %655 %655 0 1 + %657 = OpConvertFToS %v2int %656 + %662 = OpAccessChain %_ptr_PushConstant_v2int %_ %int_0 + %663 = OpLoad %v2int %662 + %664 = OpISub %v2int %657 %663 + %665 = OpBitcast %v2uint %664 + %668 = OpAccessChain %_ptr_PushConstant_float %_ %int_1 + %669 = OpLoad %float %668 + %670 = OpBitcast %uint %669 + %830 = OpBitcast %v2int %665 + %832 = OpIAdd %v2int %830 %144 + %1194 = OpLoad %121 %xe_texture + %1196 = OpImage %120 %1194 + %1197 = OpImageFetch %v4float %1196 %832 Lod %int_0 + %1199 = OpCompositeExtract %float %1197 0 + %1200 = OpCompositeExtract %float %1197 1 + %1201 = OpCompositeExtract %float %1197 2 + %836 = OpIAdd %v2int %830 %151 + %1207 = OpImage %120 %1194 + %1208 = OpImageFetch %v4float %1207 %836 Lod %int_0 + %1210 = OpCompositeExtract %float %1208 0 + %1211 = OpCompositeExtract %float %1208 1 + %1212 = OpCompositeExtract %float %1208 2 + %1218 = OpImage %120 %1194 + %1219 = OpImageFetch %v4float %1218 %830 Lod %int_0 + %1221 = OpCompositeExtract %float %1219 0 + %1222 = OpCompositeExtract %float %1219 1 + %1223 = OpCompositeExtract %float %1219 2 + %843 = OpIAdd %v2int %830 %164 + %1229 = OpImage %120 %1194 + %1230 = OpImageFetch %v4float %1229 %843 Lod %int_0 + %1232 = OpCompositeExtract %float %1230 0 + %1233 = OpCompositeExtract %float %1230 1 + %1234 = OpCompositeExtract %float %1230 2 + %847 = OpIAdd %v2int %830 %171 + %1240 = OpImage %120 %1194 + %1241 = OpImageFetch %v4float %1240 %847 Lod %int_0 + %1243 = OpCompositeExtract %float %1241 0 + %1244 = OpCompositeExtract %float %1241 1 + %1245 = OpCompositeExtract %float %1241 2 + %1371 = OpExtInst %float %1 FMin %1210 %1232 + %1372 = OpExtInst %float %1 FMin %1199 %1371 + %1007 = OpExtInst %float %1 FMin %1372 %1243 + %1378 = OpExtInst %float %1 FMin %1211 %1233 + %1379 = OpExtInst %float %1 FMin %1200 %1378 + %1013 = OpExtInst %float %1 FMin %1379 %1244 + %1385 = OpExtInst %float %1 FMin %1212 %1234 + %1386 = OpExtInst %float %1 FMin %1201 %1385 + %1019 = OpExtInst %float %1 FMin %1386 %1245 + %1392 = OpExtInst %float %1 FMax %1210 %1232 + %1393 = OpExtInst %float %1 FMax %1199 %1392 + %1025 = OpExtInst %float %1 FMax %1393 %1243 + %1399 = OpExtInst %float %1 FMax %1211 %1233 + %1400 = OpExtInst %float %1 FMax %1200 %1399 + %1031 = OpExtInst %float %1 FMax %1400 %1244 + %1406 = OpExtInst %float %1 FMax %1212 %1234 + %1407 = OpExtInst %float %1 FMax %1201 %1406 + %1037 = OpExtInst %float %1 FMax %1407 %1245 + %1040 = OpExtInst %float %1 FMin %1007 %1221 + %1416 = OpFDiv %float %float_0_25 %1025 + %1045 = OpFMul %float %1040 %1416 + %1048 = OpExtInst %float %1 FMin %1013 %1222 + %1428 = OpFDiv %float %float_0_25 %1031 + %1053 = OpFMul %float %1048 %1428 + %1056 = OpExtInst %float %1 FMin %1019 %1223 + %1440 = OpFDiv %float %float_0_25 %1037 + %1061 = OpFMul %float %1056 %1440 + %1066 = OpExtInst %float %1 FMax %1025 %1221 + %1067 = OpFSub %float %float_1 %1066 + %1070 = OpFMul %float %float_4 %1007 + %1073 = OpFAdd %float %1070 %float_n4 + %1452 = OpFDiv %float %float_1 %1073 + %1075 = OpFMul %float %1067 %1452 + %1080 = OpExtInst %float %1 FMax %1031 %1222 + %1081 = OpFSub %float %float_1 %1080 + %1084 = OpFMul %float %float_4 %1013 + %1087 = OpFAdd %float %1084 %float_n4 + %1464 = OpFDiv %float %float_1 %1087 + %1089 = OpFMul %float %1081 %1464 + %1094 = OpExtInst %float %1 FMax %1037 %1223 + %1095 = OpFSub %float %float_1 %1094 + %1098 = OpFMul %float %float_4 %1019 + %1101 = OpFAdd %float %1098 %float_n4 + %1476 = OpFDiv %float %float_1 %1101 + %1103 = OpFMul %float %1095 %1476 + %1105 = OpFNegate %float %1045 + %1107 = OpExtInst %float %1 FMax %1105 %1075 + %1109 = OpFNegate %float %1053 + %1111 = OpExtInst %float %1 FMax %1109 %1089 + %1113 = OpFNegate %float %1061 + %1115 = OpExtInst %float %1 FMax %1113 %1103 + %1488 = OpExtInst %float %1 FMax %1111 %1115 + %1489 = OpExtInst %float %1 FMax %1107 %1488 + %1122 = OpExtInst %float %1 FMin %1489 %float_0 + %1123 = OpExtInst %float %1 FMax %float_n0_1875 %1122 + %1126 = OpBitcast %float %670 + %1127 = OpFMul %float %1123 %1126 + %1130 = OpFMul %float %float_4 %1127 + %1132 = OpFAdd %float %1130 %float_1 + %1506 = OpBitcast %uint %1132 + %1507 = OpISub %uint %uint_2129764351 %1506 + %1508 = OpBitcast %float %1507 + %1511 = OpFNegate %float %1508 + %1513 = OpFMul %float %1511 %1132 + %1515 = OpFAdd %float %1513 %float_2 + %1516 = OpFMul %float %1508 %1515 + %1548 = OpFAdd %float %1199 %1210 + %1549 = OpFAdd %float %1548 %1243 + %1550 = OpFAdd %float %1549 %1232 + %1148 = OpFMul %float %1127 %1550 + %1150 = OpFAdd %float %1148 %1221 + %1152 = OpFMul %float %1150 %1516 + %1551 = OpFAdd %float %1200 %1211 + %1552 = OpFAdd %float %1551 %1244 + %1553 = OpFAdd %float %1552 %1233 + %1167 = OpFMul %float %1127 %1553 + %1169 = OpFAdd %float %1167 %1222 + %1171 = OpFMul %float %1169 %1516 + %1554 = OpFAdd %float %1201 %1212 + %1555 = OpFAdd %float %1554 %1245 + %1556 = OpFAdd %float %1555 %1234 + %1186 = OpFMul %float %1127 %1556 + %1188 = OpFAdd %float %1186 %1223 + %1190 = OpFMul %float %1188 %1516 + %688 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_0 + OpStore %688 %1152 + %690 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_1 + OpStore %690 %1171 + %692 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_2 + OpStore %692 %1190 + %694 = OpAccessChain %_ptr_Output_float %xe_frag_color %uint_3 + OpStore %694 %float_1 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h new file mode 100644 index 000000000..e5e48733c --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h @@ -0,0 +1,109 @@ +// generated from `xb genspirv` +// source: guest_output_triangle_strip_rect.vert +const uint8_t guest_output_triangle_strip_rect_vert[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2F, 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, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 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, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x58, 0x65, 0x54, 0x72, 0x69, 0x61, 0x6E, 0x67, 0x6C, 0x65, 0x53, 0x74, + 0x72, 0x69, 0x70, 0x52, 0x65, 0x63, 0x74, 0x43, 0x6F, 0x6E, 0x73, 0x74, + 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0B, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, + 0x72, 0x69, 0x61, 0x6E, 0x67, 0x6C, 0x65, 0x5F, 0x73, 0x74, 0x72, 0x69, + 0x70, 0x5F, 0x72, 0x65, 0x63, 0x74, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x74, 0x72, 0x69, 0x61, 0x6E, + 0x67, 0x6C, 0x65, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x70, 0x5F, 0x72, 0x65, + 0x63, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x56, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x00, 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, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x2A, 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, 0x17, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x20, 0x00, 0x04, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x1C, 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, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0xC7, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x70, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x05, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, + 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..3c2de3d30a70a3f4cad64f7f7257ee3c70d5f9ea GIT binary patch literal 1252 zcmZ{iO=}ZT6o#*fNo%Y9u(tKHOpV{I(S;U4RK!ITx`;-^T?p;84Ae=<%%X@3UHHe` z_?O%WKF{QixbcKH_nh~>_k1PIMrS63Q(-R5h6iD4%b@`i!hC2~XK#0~+bzod?xV*K zRV;*NB~-H*c#fS0pGH}(KL=JplaHDmzFH{$)wIYx%iZD8u%Avoq?0l|A%vas`reI; ztjxwa>`bLMU&Uv6ImkYz>RQyXrq;q+;QW}rpJb!_@F*RWlkE6ix>vp$=S4Zn%R*h7 z>C|Z_=@3mN9u}&H6Xe73!9kIh+_z&+YyU@E*ou8DnGkb6cR;Vx;oju?PWYM|=ho(@ z$6wC;a-KbMscQh=)V+3ywVG2ar`9*>eA8pw);HfhumUT;iN;?~e+{qAnSgcl{*uQ2 zP8)oiv*r@wGsM1?e;Q-=F1Jc-tpwQ9R*cW$Yvw=4X?|;)-(KZ}`4>5@A#Z+T_bKQ7 za`bEc1!8MiSG}<_%h}I5X96_qU#iY&ef#tNikDa&U&Z(RHak~;4XBZ?XS$BB#@Kmo z1FeqlRMFQL_PmYne%xc7vx{#&u|pmA;m$R+zhGLNFZp)n^T0j0%V#K^e+9@JJO3JR z_AkWFbun`NILGD4$^VGl2EM#A{)}9LFK>^>vDPMj0_uJ``1a!->V9tE%YP@2{oMq< zlm8aETln_v-CHvJoV(isYQ1yc?%00Z?|tC^(EU7TgU0HAli>;Y E1K{La5C8xG literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt new file mode 100644 index 000000000..e78174fa6 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.txt @@ -0,0 +1,74 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 47 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %_ %gl_VertexIndex + OpSource ESSL 310 + OpName %main "main" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpName %_ "" + OpName %XeTriangleStripRectConstants "XeTriangleStripRectConstants" + OpMemberName %XeTriangleStripRectConstants 0 "xe_triangle_strip_rect_offset" + OpMemberName %XeTriangleStripRectConstants 1 "xe_triangle_strip_rect_size" + OpName %__0 "" + OpName %gl_VertexIndex "gl_VertexIndex" + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpDecorate %gl_PerVertex Block + OpMemberDecorate %XeTriangleStripRectConstants 0 Offset 0 + OpMemberDecorate %XeTriangleStripRectConstants 1 Offset 8 + OpDecorate %XeTriangleStripRectConstants Block + OpDecorate %gl_VertexIndex BuiltIn VertexIndex + %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 + %v2float = OpTypeVector %float 2 +%XeTriangleStripRectConstants = OpTypeStruct %v2float %v2float +%_ptr_PushConstant_XeTriangleStripRectConstants = OpTypePointer PushConstant %XeTriangleStripRectConstants + %__0 = OpVariable %_ptr_PushConstant_XeTriangleStripRectConstants PushConstant +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float +%_ptr_Input_int = OpTypePointer Input %int +%gl_VertexIndex = OpVariable %_ptr_Input_int Input + %uint = OpTypeInt 32 0 + %v2uint = OpTypeVector %uint 2 + %uint_0 = OpConstant %uint 0 + %uint_1 = OpConstant %uint 1 + %29 = OpConstantComposite %v2uint %uint_0 %uint_1 + %int_1 = OpConstant %int 1 + %float_0 = OpConstant %float 0 + %float_1 = OpConstant %float 1 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %46 = OpConstantComposite %v2uint %uint_1 %uint_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %18 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_0 + %19 = OpLoad %v2float %18 + %22 = OpLoad %int %gl_VertexIndex + %24 = OpBitcast %uint %22 + %26 = OpCompositeConstruct %v2uint %24 %24 + %30 = OpShiftRightLogical %v2uint %26 %29 + %32 = OpBitwiseAnd %v2uint %30 %46 + %33 = OpConvertUToF %v2float %32 + %35 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_1 + %36 = OpLoad %v2float %35 + %37 = OpFMul %v2float %33 %36 + %38 = OpFAdd %v2float %19 %37 + %41 = OpCompositeExtract %float %38 0 + %42 = OpCompositeExtract %float %38 1 + %43 = OpCompositeConstruct %v4float %41 %42 %float_0 %float_1 + %45 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %45 %43 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h new file mode 100644 index 000000000..dc4a7f3df --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h @@ -0,0 +1,71 @@ +// generated from `xb genspirv` +// source: immediate.frag +const uint8_t immediate_frag[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x19, 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, 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, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, + 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x69, 0x6D, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, + 0x5F, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x76, + 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x18, 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, + 0x19, 0x00, 0x09, 0x00, 0x0D, 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, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x16, 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, 0x3D, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x58, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d0d4c2beb39b4e5ae4d0e3df14bca25110865ce1 GIT binary patch literal 804 zcmYk3%}&Bl5QPT{SV2KVL1JP+mL|l75)-4_ZrHhTM;fSxL~K&4;RSqWHzuC%($-Eg zojGTI@6@YK_RK2QG~b4{lde_8n6<3oY%qVCPe0Pt^yc=OjJA0$k(`d|YO?4iT)z|8 zm$sxQ(j(;((-3){>o-$jU2M6gu36M=qs2=SzAl#WTbu~P(@XqUm=v^lU%ef_-fW`P zI!vQQ8g0|hBogiFn4i@tvW(+oWr22J4iabs{0oP`o|~1&m`jXz5<4Iu!Dlu?5By7q z{_(iLo^=bq=5A7+Hz;DBon?Mc_pizyYYvyj@5^h*j-&(4FE=!Kj)v2ujdGzaKNpQ>q=Qm-$V`2KSJNZ3Xdcl(q=KsK5 z36tBGA~XFx>UbN%8-B#pWgo=y2L1*6gV})_Gat;1Qz`wQl}$c(CI^0ZPqS}zB*xw8 QN6w?BaW}YMZFeXA1AaL#>Hq)$ literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.txt new file mode 100644 index 000000000..54583cc1b --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.txt @@ -0,0 +1,54 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 25 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %xe_frag_color %xe_var_color %xe_var_texcoord + OpExecutionMode %main OriginUpperLeft + OpSource ESSL 310 + OpName %main "main" + OpName %xe_frag_color "xe_frag_color" + OpName %xe_var_color "xe_var_color" + OpName %xe_immediate_texture "xe_immediate_texture" + OpName %xe_var_texcoord "xe_var_texcoord" + OpDecorate %xe_frag_color RelaxedPrecision + OpDecorate %xe_frag_color Location 0 + OpDecorate %xe_var_color RelaxedPrecision + OpDecorate %xe_var_color Location 1 + OpDecorate %12 RelaxedPrecision + OpDecorate %xe_immediate_texture RelaxedPrecision + OpDecorate %xe_immediate_texture DescriptorSet 0 + OpDecorate %xe_immediate_texture Binding 0 + OpDecorate %17 RelaxedPrecision + OpDecorate %xe_var_texcoord Location 0 + OpDecorate %23 RelaxedPrecision + OpDecorate %24 RelaxedPrecision + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_frag_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Input_v4float = OpTypePointer Input %v4float +%xe_var_color = OpVariable %_ptr_Input_v4float Input + %13 = OpTypeImage %float 2D 0 0 0 1 Unknown + %14 = OpTypeSampledImage %13 +%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 +%xe_immediate_texture = OpVariable %_ptr_UniformConstant_14 UniformConstant + %v2float = OpTypeVector %float 2 +%_ptr_Input_v2float = OpTypePointer Input %v2float +%xe_var_texcoord = OpVariable %_ptr_Input_v2float Input + %float_0 = OpConstant %float 0 + %main = OpFunction %void None %3 + %5 = OpLabel + %12 = OpLoad %v4float %xe_var_color + %17 = OpLoad %14 %xe_immediate_texture + %21 = OpLoad %v2float %xe_var_texcoord + %23 = OpImageSampleExplicitLod %v4float %17 %21 Lod %float_0 + %24 = OpFMul %v4float %12 %23 + OpStore %xe_frag_color %24 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h new file mode 100644 index 000000000..1a1299653 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h @@ -0,0 +1,117 @@ +// generated from `xb genspirv` +// source: immediate.vert +const uint8_t immediate_vert[] = { + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, + 0x2C, 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, + 0x09, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F, + 0x6F, 0x72, 0x64, 0x00, 0x05, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x78, 0x65, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, + 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x63, + 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x5F, + 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, + 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, + 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x13, 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, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x61, + 0x74, 0x74, 0x72, 0x5F, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x58, 0x65, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, + 0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, + 0x69, 0x6E, 0x61, 0x74, 0x65, 0x5F, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5F, + 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x03, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x47, 0x00, 0x03, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, + 0x1A, 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, 0x02, 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, + 0x17, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x3B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x23, 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, + 0x3D, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x03, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, +}; diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..b2c19c5f0658e04ef87ad8182aeb67139529f967 GIT binary patch literal 1352 zcmYk5%WD)t5XL(@+1)%eG3MnnnYj3t;6Z~RzVNUfa##t7w_(@}aUjlwnKlGZf_U}s z^&O?;1M)rhs zU-v)99dPk3;=25K+d=G$8qAH1y2E;dBYs`KoO|k**Mz+#YoIfgZmT~%OvCt6;RT(< z!oLidUBKaA(n(*@501T3@3JuUd3VIG=p+}OdSLby>s^sez32zCGq@eaGkdH_y$xY< z;i(7ajlgXRZ|O{>NSzmp;Jw*a>fmUEyP= z;Fxz^HgmpHHTvewFblhgF}s2P6?#jB$%FqLxI3~_DRce|++Er5%<@qjd$=!!MuPVHd{sU>6V;ukh literal 0 HcmV?d00001 diff --git a/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt new file mode 100644 index 000000000..d5b18f232 --- /dev/null +++ b/src/xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.txt @@ -0,0 +1,82 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 44 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %main "main" %xe_var_texcoord %xe_attr_texcoord %xe_var_color %xe_attr_color %_ %xe_attr_position + OpSource ESSL 310 + OpName %main "main" + OpName %xe_var_texcoord "xe_var_texcoord" + OpName %xe_attr_texcoord "xe_attr_texcoord" + OpName %xe_var_color "xe_var_color" + OpName %xe_attr_color "xe_attr_color" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpMemberName %gl_PerVertex 1 "gl_PointSize" + OpName %_ "" + OpName %xe_attr_position "xe_attr_position" + OpName %XePushConstants "XePushConstants" + OpMemberName %XePushConstants 0 "xe_coordinate_space_size_inv" + OpName %__0 "" + OpDecorate %xe_var_texcoord Location 0 + OpDecorate %xe_attr_texcoord Location 1 + OpDecorate %xe_var_color RelaxedPrecision + OpDecorate %xe_var_color Location 1 + OpDecorate %xe_attr_color RelaxedPrecision + OpDecorate %xe_attr_color Location 2 + OpDecorate %18 RelaxedPrecision + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize + OpDecorate %gl_PerVertex Block + OpDecorate %xe_attr_position Location 0 + OpMemberDecorate %XePushConstants 0 Offset 0 + OpDecorate %XePushConstants Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v2float = OpTypeVector %float 2 +%_ptr_Output_v2float = OpTypePointer Output %v2float +%xe_var_texcoord = OpVariable %_ptr_Output_v2float Output +%_ptr_Input_v2float = OpTypePointer Input %v2float +%xe_attr_texcoord = OpVariable %_ptr_Input_v2float Input + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%xe_var_color = OpVariable %_ptr_Output_v4float Output +%_ptr_Input_v4float = OpTypePointer Input %v4float +%xe_attr_color = OpVariable %_ptr_Input_v4float Input +%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 +%xe_attr_position = OpVariable %_ptr_Input_v2float Input +%XePushConstants = OpTypeStruct %v2float +%_ptr_PushConstant_XePushConstants = OpTypePointer PushConstant %XePushConstants + %__0 = OpVariable %_ptr_PushConstant_XePushConstants PushConstant +%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float + %float_2 = OpConstant %float 2 + %float_1 = OpConstant %float 1 + %float_0 = OpConstant %float 0 + %43 = OpConstantComposite %v2float %float_1 %float_1 + %main = OpFunction %void None %3 + %5 = OpLabel + %12 = OpLoad %v2float %xe_attr_texcoord + OpStore %xe_var_texcoord %12 + %18 = OpLoad %v4float %xe_attr_color + OpStore %xe_var_color %18 + %25 = OpLoad %v2float %xe_attr_position + %30 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_0 + %31 = OpLoad %v2float %30 + %32 = OpFMul %v2float %25 %31 + %34 = OpVectorTimesScalar %v2float %32 %float_2 + %37 = OpFSub %v2float %34 %43 + %39 = OpCompositeExtract %float %37 0 + %40 = OpCompositeExtract %float %37 1 + %41 = OpCompositeConstruct %v4float %39 %40 %float_0 %float_1 + %42 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %42 %41 + OpReturn + OpFunctionEnd diff --git a/src/xenia/ui/shaders/dither_8bpc.xesli b/src/xenia/ui/shaders/dither_8bpc.xesli new file mode 100644 index 000000000..1f8b2946c --- /dev/null +++ b/src/xenia/ui/shaders/dither_8bpc.xesli @@ -0,0 +1,34 @@ +#ifndef XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ +#define XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ + +#include "xesl.xesli" + +#include "noise.xesli" + +xesl_static const float xe_dither_8bpc_noise[] = { + // The conversion to 8bpc in the fixed-function output-merger is done as + // floor(saturate(color) * 255.0 + 0.5). This dithering function effectively + // replaces that 0.5 offset, done for rounding to the nearest, with the noise. + // To do that, first, 0.5/255 needs to be subtracted from the color, and + // then the noise value `[0, 255/256] / 255` from xe_dither_8bpc_noise needs + // to be added. However, due to rounding (because division by 255.0 is + // inexact), subtracting 0.5/255 from exact 8-bit integer color values + // (including, for instance, 1.0, or 255/255) may result in the result being + // smaller than the original exact 8-bit value where the noise value is 0. So, + // remapping the noise to the `[0.5/256, 255.5/256] / 255` range. Another way + // of preventing rounding issues is doing it manually and returning only exact + // integer 8-bit color values divided by 255, but that would assume that the + // render target is specifically 8bpc, so it's better to avoid that in case + // the window system, for instance, provides a 10bpc render target (for which + // dithering is still done here for more consistency between displays, but + // some addition precision would still be desirable). + XeBlueNoise16x16Values0Until256(1.0 / 256.0 / 255.0, + (-0.5 + 0.5 / 256.0) / 255.0) +}; + +float XeDitherOffset8bpc(xesl_uint2 pixel_coord) { + pixel_coord &= 15u; + return xe_dither_8bpc_noise[pixel_coord.y * 16u + pixel_coord.x]; +} + +#endif // XENIA_UI_SHADERS_DITHER_8BPC_XESLI_ diff --git a/src/xenia/ui/shaders/guest_output_bilinear.frag b/src/xenia/ui/shaders/guest_output_bilinear.frag new file mode 100644 index 000000000..42fc74087 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_bilinear.glsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear.glsli b/src/xenia/ui/shaders/guest_output_bilinear.glsli new file mode 100644 index 000000000..bffd8842e --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.glsli @@ -0,0 +1,38 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeBilinearConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_bilinear_output_offset; + layout(offset = 24) vec2 xe_bilinear_output_size_inv; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_bilinear_output_offset); + // + 0.5 so the origin is at the pixel center, and at 1:1 the original pixel + // is taken. + // Interpolating the four colors in the perceptual space because doing it in + // linear space causes, in particular, bright text on a dark background to + // become too thick, and aliasing of bright parts on top of dark areas to be + // too apparent (4D5307E6 HUD, for example, mainly the edges of the + // multiplayer score bars). + xe_frag_color.rgb = + textureLod(xe_texture, + (vec2(pixel_coord) + 0.5) * xe_bilinear_output_size_inv, + 0.0).rgb; + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_bilinear.hlsli b/src/xenia/ui/shaders/guest_output_bilinear.hlsli new file mode 100644 index 000000000..6685bfc29 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.hlsli @@ -0,0 +1,31 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeBilinearConstants : register(b0) { + int2 xe_bilinear_output_offset; + float2 xe_bilinear_output_size_inv; +}; + +Texture2D xe_texture : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_bilinear_output_offset); + // + 0.5 so the origin is at the pixel center, and at 1:1 the original pixel + // is taken. + // Interpolating the four colors in the perceptual space because doing it in + // linear space causes, in particular, bright text on a dark background to + // become too thick, and aliasing of bright parts on top of dark areas to be + // too apparent (4D5307E6 HUD, for example, mainly the edges of the + // multiplayer score bars). + float3 color = xe_texture.SampleLevel( + xe_sampler_linear_clamp, + (float2(pixel_coord) + 0.5f) * xe_bilinear_output_size_inv, + 0.0f); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl b/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl new file mode 100644 index 000000000..dd4e37b28 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_bilinear.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear_dither.frag b/src/xenia/ui/shaders/guest_output_bilinear_dither.frag new file mode 100644 index 000000000..b78b5a9a4 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_bilinear.glsli" diff --git a/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl new file mode 100644 index 000000000..13995e2bb --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_bilinear_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_bilinear.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag new file mode 100644 index 000000000..a495b7bb4 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_cas_resample.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli new file mode 100644 index 000000000..21a35528e --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.glsli @@ -0,0 +1,57 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeCasResampleConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_cas_output_offset; + // CasSetup const0.xy. + layout(offset = 24) vec2 xe_cas_input_output_size_ratio; + // CasSetup const1.x. + layout(offset = 32) float xe_cas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +vec3 CasLoad(ivec2 p) { + return texelFetch(xe_texture, p, 0).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_cas_output_offset); + // CasSetup with smaller push constant usage. + uvec4 cas_const_0 = + uvec4(floatBitsToUint(xe_cas_input_output_size_ratio), + floatBitsToUint(0.5 * xe_cas_input_output_size_ratio - 0.5)); + uvec4 cas_const_1 = + uvec4(floatBitsToUint(xe_cas_sharpness_post_setup), + packHalf2x16(vec2(xe_cas_sharpness_post_setup, 0.0)), + floatBitsToUint(8.0 * xe_cas_input_output_size_ratio.x), 0u); + CasFilter(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + cas_const_0, cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + xe_frag_color.rgb = sqrt(xe_frag_color.rgb); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli new file mode 100644 index 000000000..843a00caa --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.hlsli @@ -0,0 +1,49 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeCasResampleConstants : register(b0) { + int2 xe_cas_output_offset; + // CasSetup const0.xy. + float2 xe_cas_input_output_size_ratio; + // CasSetup const1.x. + float xe_cas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +float3 CasLoad(int2 p) { + return xe_texture.Load(int3(p, 0)).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_cas_output_offset); + // CasSetup with smaller root signature usage. + uint4 cas_const_0 = + uint4(asuint(xe_cas_input_output_size_ratio), + asuint(0.5f * xe_cas_input_output_size_ratio - 0.5f)); + uint4 cas_const_1 = + uint4(asuint(xe_cas_sharpness_post_setup), + f32tof16(xe_cas_sharpness_post_setup), + asuint(8.0f * xe_cas_input_output_size_ratio.x), 0u); + float3 cas_color; + CasFilter(cas_color.r, cas_color.g, cas_color.b, pixel_coord, cas_const_0, + cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + cas_color = sqrt(cas_color); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + cas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(cas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl new file mode 100644 index 000000000..f970e5404 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_cas_resample.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag new file mode 100644 index 000000000..476c02dd3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_resample.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl new file mode 100644 index 000000000..4e76285b2 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_resample_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_resample.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag new file mode 100644 index 000000000..059ea939d --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_cas_sharpen.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli new file mode 100644 index 000000000..0cb6ea359 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.glsli @@ -0,0 +1,53 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeCasSharpenConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_cas_output_offset; + // CasSetup const1.x. + layout(offset = 24) float xe_cas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +vec3 CasLoad(ivec2 p) { + return texelFetch(xe_texture, p, 0).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_cas_output_offset); + // CasSetup with smaller push constant usage. + uvec4 cas_const_0 = floatBitsToUint(vec4(1.0, 1.0, 0.0, 0.0)); + uvec4 cas_const_1 = + uvec4(floatBitsToUint(xe_cas_sharpness_post_setup), + packHalf2x16(vec2(xe_cas_sharpness_post_setup, 0.0)), + floatBitsToUint(8.0), 0u); + CasFilter(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + cas_const_0, cas_const_1, false); + // Linear conversion approximation as recommended in the CAS presentation. + xe_frag_color.rgb = sqrt(xe_frag_color.rgb); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli new file mode 100644 index 000000000..0c47cc0e3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.hlsli @@ -0,0 +1,44 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeCasSharpenConstants : register(b0) { + int2 xe_cas_output_offset; + // CasSetup const1.x. + float xe_cas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_a.h" +float3 CasLoad(int2 p) { + return xe_texture.Load(int3(p, 0)).rgb; +} +void CasInput(inout float r, inout float g, inout float b) { + // Linear conversion approximation as recommended in the CAS presentation. + r *= r; + g *= g; + b *= b; +} +#include "../../../../third_party/FidelityFX-CAS/ffx-cas/ffx_cas.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_cas_output_offset); + // CasSetup with smaller root signature usage. + uint4 cas_const_0 = asuint(float4(1.0f, 1.0f, 0.0f, 0.0f)); + uint4 cas_const_1 = + uint4(asuint(xe_cas_sharpness_post_setup), + f32tof16(xe_cas_sharpness_post_setup), asuint(8.0f), 0u); + float3 cas_color; + CasFilter(cas_color.r, cas_color.g, cas_color.b, pixel_coord, cas_const_0, + cas_const_1, true); + // Linear conversion approximation as recommended in the CAS presentation. + cas_color = sqrt(cas_color); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + cas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(cas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl new file mode 100644 index 000000000..3ff89fe34 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_cas_sharpen.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag new file mode 100644 index 000000000..60c6b2f8b --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_sharpen.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl new file mode 100644 index 000000000..3ad7b01b7 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_cas_sharpen_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_cas_sharpen.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag new file mode 100644 index 000000000..d5b2f1900 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.frag @@ -0,0 +1,38 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require + +layout(push_constant) uniform XeFsrEasuConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) vec2 xe_fsr_easu_input_output_size_ratio; + layout(offset = 24) vec2 xe_fsr_easu_input_size_inv; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_EASU_F 1 +vec4 FsrEasuRF(vec2 p) { return textureGather(xe_texture, p, 0); } +vec4 FsrEasuGF(vec2 p) { return textureGather(xe_texture, p, 1); } +vec4 FsrEasuBF(vec2 p) { return textureGather(xe_texture, p, 2); } +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +void main() { + // FsrEasuCon with smaller push constant usage. + uvec4 easu_const_0 = + uvec4(floatBitsToUint(xe_fsr_easu_input_output_size_ratio), + floatBitsToUint(0.5 * xe_fsr_easu_input_output_size_ratio - 0.5)); + uvec4 easu_const_1 = floatBitsToUint(vec4(1.0, 1.0, 1.0, -1.0) * + xe_fsr_easu_input_size_inv.xyxy); + uvec4 easu_const_2 = floatBitsToUint(vec4(-1.0, 2.0, 1.0, 2.0) * + xe_fsr_easu_input_size_inv.xyxy); + uvec4 easu_const_3 = + uvec4(floatBitsToUint(0.0), + floatBitsToUint(4.0 * xe_fsr_easu_input_size_inv.y), 0u, 0u); + FsrEasuF(xe_frag_color.rgb, uvec2(gl_FragCoord.xy), easu_const_0, + easu_const_1, easu_const_2, easu_const_3); + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl new file mode 100644 index 000000000..bd95e7a46 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_easu.ps.hlsl @@ -0,0 +1,39 @@ +cbuffer XeFsrEasuConstants : register(b0) { + float2 xe_fsr_easu_input_output_size_ratio; + float2 xe_fsr_easu_input_size_inv; +}; + +Texture2D xe_texture : register(t0); +SamplerState xe_sampler_linear_clamp : register(s0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_EASU_F 1 +float4 FsrEasuRF(float2 p) { + return xe_texture.GatherRed(xe_sampler_linear_clamp, p); +} +float4 FsrEasuGF(float2 p) { + return xe_texture.GatherGreen(xe_sampler_linear_clamp, p); +} +float4 FsrEasuBF(float2 p) { + return xe_texture.GatherBlue(xe_sampler_linear_clamp, p); +} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + // FsrEasuCon with smaller root signature usage. + uint4 easu_const_0 = + uint4(asuint(xe_fsr_easu_input_output_size_ratio), + asuint(0.5f * xe_fsr_easu_input_output_size_ratio - 0.5f)); + uint4 easu_const_1 = + asuint(float4(1.0f, 1.0f, 1.0f, -1.0f) * xe_fsr_easu_input_size_inv.xyxy); + uint4 easu_const_2 = + asuint(float4(-1.0f, 2.0f, 1.0f, 2.0f) * xe_fsr_easu_input_size_inv.xyxy); + uint4 easu_const_3 = + uint4(asuint(0.0f), asuint(4.0f * xe_fsr_easu_input_size_inv.y), 0u, 0u); + float3 easu_color; + FsrEasuF(easu_color, uint2(xe_position.xy), easu_const_0, easu_const_1, + easu_const_2, easu_const_3); + return float4(easu_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag new file mode 100644 index 000000000..a5bb9f7af --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.frag @@ -0,0 +1,3 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#include "guest_output_ffx_fsr_rcas.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli new file mode 100644 index 000000000..5c60cd8ea --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.glsli @@ -0,0 +1,45 @@ +// At least #version 420. + +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +layout(push_constant) uniform XeFsrRcasConstants { + // 16 occupied by the vertex shader. + layout(offset = 16) ivec2 xe_fsr_rcas_output_offset; + // FsrRcasCon const0.x. + layout(offset = 24) float xe_fsr_rcas_sharpness_post_setup; +}; + +layout(set = 0, binding = 0) uniform sampler2D xe_texture; + +layout(location = 0) out vec4 xe_frag_color; + +#define A_GPU 1 +#define A_GLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_RCAS_F 1 +vec4 FsrRcasLoadF(ivec2 p) { + return vec4(texelFetch(xe_texture, p, 0).rgb, 1.0); +} +void FsrRcasInputF(inout float r, inout float g, inout float b) {} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +void main() { + uvec2 pixel_coord = uvec2(ivec2(gl_FragCoord.xy) - xe_fsr_rcas_output_offset); + // FsrRcasCon with smaller push constant usage. + uvec4 rcas_const = + uvec4(floatBitsToUint(xe_fsr_rcas_sharpness_post_setup), + packHalf2x16(vec2(xe_fsr_rcas_sharpness_post_setup)), 0u, 0u); + FsrRcasF(xe_frag_color.r, xe_frag_color.g, xe_frag_color.b, pixel_coord, + rcas_const); + #if XE_GUEST_OUTPUT_DITHER + // Clamping because on Vulkan, the surface may specify any format, including + // floating-point. + xe_frag_color.rgb = + clamp(xe_frag_color.rgb + XeDitherOffset8bpc(pixel_coord), + vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); + #endif // XE_GUEST_OUTPUT_DITHER + // Force alpha to 1 to make sure the surface won't be translucent. + xe_frag_color.a = 1.0; +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli new file mode 100644 index 000000000..c9bc3e7bf --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.hlsli @@ -0,0 +1,36 @@ +#if XE_GUEST_OUTPUT_DITHER + #include "dither_8bpc.xesli" +#endif // XE_GUEST_OUTPUT_DITHER + +cbuffer XeFsrRcasConstants : register(b0) { + int2 xe_fsr_rcas_output_offset; + // FsrRcasCon const0.x. + float xe_fsr_rcas_sharpness_post_setup; +}; + +Texture2D xe_texture : register(t0); + +#define A_GPU 1 +#define A_HLSL 1 +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_a.h" +#define FSR_RCAS_F 1 +float4 FsrRcasLoadF(int2 p) { + return float4(xe_texture.Load(int3(p, 0)).rgb, 1.0f); +} +void FsrRcasInputF(inout float r, inout float g, inout float b) {} +#include "../../../../third_party/FidelityFX-FSR/ffx-fsr/ffx_fsr1.h" + +float4 main(float4 xe_position : SV_Position) : SV_Target { + uint2 pixel_coord = uint2(int2(xe_position.xy) - xe_fsr_rcas_output_offset); + // FsrRcasCon with smaller root signature usage. + uint4 rcas_const = + uint4(asuint(xe_fsr_rcas_sharpness_post_setup), + f32tof16(xe_fsr_rcas_sharpness_post_setup) * 0x00010001u, 0u, 0u); + float3 rcas_color; + FsrRcasF(rcas_color.r, rcas_color.g, rcas_color.b, pixel_coord, rcas_const); + #if XE_GUEST_OUTPUT_DITHER + // Not clamping because a normalized format is explicitly requested on DXGI. + rcas_color += XeDitherOffset8bpc(pixel_coord); + #endif // XE_GUEST_OUTPUT_DITHER + return float4(rcas_color, 1.0f); +} diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl new file mode 100644 index 000000000..6133ff540 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas.ps.hlsl @@ -0,0 +1 @@ +#include "guest_output_ffx_fsr_rcas.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag new file mode 100644 index 000000000..2e0f18cb8 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.frag @@ -0,0 +1,4 @@ +#version 420 +#extension GL_GOOGLE_include_directive : require +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_fsr_rcas.glsli" diff --git a/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl new file mode 100644 index 000000000..ed669fa64 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_ffx_fsr_rcas_dither.ps.hlsl @@ -0,0 +1,2 @@ +#define XE_GUEST_OUTPUT_DITHER 1 +#include "guest_output_ffx_fsr_rcas.hlsli" diff --git a/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert new file mode 100644 index 000000000..5127c10ae --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vert @@ -0,0 +1,17 @@ +#version 310 es + +layout(push_constant) uniform XeTriangleStripRectConstants { + // If the layout is changed, update the base offset in all guest output + // fragment shaders! + vec2 xe_triangle_strip_rect_offset; + // Can be negative. + vec2 xe_triangle_strip_rect_size; +}; + +void main() { + // Passthrough - coordinate system differences are to be handled externally. + gl_Position = vec4(xe_triangle_strip_rect_offset + + vec2((uvec2(gl_VertexIndex) >> uvec2(0u, 1u)) & 1u) * + xe_triangle_strip_rect_size, + 0.0, 1.0); +} diff --git a/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl new file mode 100644 index 000000000..f265ac0a3 --- /dev/null +++ b/src/xenia/ui/shaders/guest_output_triangle_strip_rect.vs.hlsl @@ -0,0 +1,14 @@ +cbuffer XeTriangleStripRectConstants : register(b0) { + float2 xe_triangle_strip_rect_offset; + // Can be negative. + float2 xe_triangle_strip_rect_size; +}; + +void main(uint xe_vertex_id : SV_VertexID, + out float4 xe_position : SV_Position) { + // Passthrough - coordinate system differences are to be handled externally. + xe_position = float4(xe_triangle_strip_rect_offset + + float2((xe_vertex_id >> uint2(0u, 1u)) & 1u) * + xe_triangle_strip_rect_size, + 0.0f, 1.0f); +} diff --git a/src/xenia/ui/shaders/immediate.frag b/src/xenia/ui/shaders/immediate.frag new file mode 100644 index 000000000..29e32f2bb --- /dev/null +++ b/src/xenia/ui/shaders/immediate.frag @@ -0,0 +1,14 @@ +#version 310 es +precision highp float; + +layout(set = 0, binding = 0) uniform lowp sampler2D xe_immediate_texture; + +layout(location = 0) in vec2 xe_var_texcoord; +layout(location = 1) in lowp vec4 xe_var_color; + +layout(location = 0) out lowp vec4 xe_frag_color; + +void main() { + xe_frag_color = + xe_var_color * textureLod(xe_immediate_texture, xe_var_texcoord, 0.0); +} diff --git a/src/xenia/ui/shaders/immediate.vert b/src/xenia/ui/shaders/immediate.vert new file mode 100644 index 000000000..ce84d6311 --- /dev/null +++ b/src/xenia/ui/shaders/immediate.vert @@ -0,0 +1,20 @@ +#version 310 es + +layout(push_constant) uniform XePushConstants { + vec2 xe_coordinate_space_size_inv; +}; + +layout(location = 0) in vec2 xe_attr_position; +layout(location = 1) in vec2 xe_attr_texcoord; +layout(location = 2) in lowp vec4 xe_attr_color; + +layout(location = 0) out vec2 xe_var_texcoord; +layout(location = 1) out lowp vec4 xe_var_color; + +void main() { + xe_var_texcoord = xe_attr_texcoord; + xe_var_color = xe_attr_color; + gl_Position = + vec4(xe_attr_position * xe_coordinate_space_size_inv * 2.0 - 1.0, 0.0, + 1.0); +} diff --git a/src/xenia/ui/shaders/immediate.vs.hlsl b/src/xenia/ui/shaders/immediate.vs.hlsl index d003fa030..0746fa4c4 100644 --- a/src/xenia/ui/shaders/immediate.vs.hlsl +++ b/src/xenia/ui/shaders/immediate.vs.hlsl @@ -1,5 +1,5 @@ cbuffer XeImmediateVertexConstants : register(b0) { - float2 xe_viewport_size_inv; + float2 xe_coordinate_space_size_inv; }; struct XeVertexShaderInput { @@ -17,7 +17,7 @@ struct XeVertexShaderOutput { XeVertexShaderOutput main(XeVertexShaderInput input) { XeVertexShaderOutput output; output.position = float4( - input.position * xe_viewport_size_inv * float2(2.0, -2.0) + + input.position * xe_coordinate_space_size_inv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); output.texcoord = input.texcoord; output.color = input.color; diff --git a/src/xenia/ui/shaders/noise.xesli b/src/xenia/ui/shaders/noise.xesli new file mode 100644 index 000000000..4e3c897fa --- /dev/null +++ b/src/xenia/ui/shaders/noise.xesli @@ -0,0 +1,47 @@ +#ifndef XENIA_UI_SHADERS_NOISE_XESLI_ +#define XENIA_UI_SHADERS_NOISE_XESLI_ + +#define XeNoiseRow16(scale, offset, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, \ + va, vb, vc, vd, ve, vf) \ + v0 * scale + offset, v1 * scale + offset, v2 * scale + offset, \ + v3 * scale + offset, v4 * scale + offset, v5 * scale + offset, \ + v6 * scale + offset, v7 * scale + offset, v8 * scale + offset, \ + v9 * scale + offset, va * scale + offset, vb * scale + offset, \ + vc * scale + offset, vd * scale + offset, ve * scale + offset, \ + vf * scale + offset + +#define XeBlueNoise16x16Values0Until256(scale, offset) \ + XeNoiseRow16(scale, offset, 62, 185, 238, 26, 211, 88, 197, 37, 216, 161, \ + 207, 23, 166, 109, 200, 35), \ + XeNoiseRow16(scale, offset, 222, 92, 136, 49, 156, 59, 168, 96, 250, 56, \ + 121, 93, 221, 1, 82, 130), \ + XeNoiseRow16(scale, offset, 174, 42, 199, 108, 242, 18, 224, 125, 179, 8, \ + 147, 192, 51, 139, 235, 24), \ + XeNoiseRow16(scale, offset, 150, 249, 12, 71, 186, 138, 67, 28, 85, 212, 75, \ + 32, 245, 72, 183, 98), \ + XeNoiseRow16(scale, offset, 58, 118, 143, 220, 89, 115, 232, 194, 154, 114, \ + 231, 170, 123, 155, 20, 217), \ + XeNoiseRow16(scale, offset, 188, 84, 205, 33, 165, 4, 177, 43, 253, 19, 60, \ + 95, 6, 206, 106, 38), \ + XeNoiseRow16(scale, offset, 234, 7, 175, 68, 246, 53, 103, 134, 79, 204, \ + 132, 225, 191, 65, 254, 162), \ + XeNoiseRow16(scale, offset, 131, 46, 110, 228, 127, 148, 215, 13, 160, 50, \ + 178, 40, 145, 31, 119, 77), \ + XeNoiseRow16(scale, offset, 213, 153, 190, 97, 27, 195, 83, 237, 193, 100, \ + 244, 112, 87, 236, 182, 15), \ + XeNoiseRow16(scale, offset, 57, 243, 76, 11, 172, 63, 41, 116, 29, 149, 0, \ + 171, 22, 203, 157, 99), \ + XeNoiseRow16(scale, offset, 140, 30, 202, 133, 251, 219, 164, 135, 210, 90, \ + 64, 214, 142, 78, 39, 223), \ + XeNoiseRow16(scale, offset, 184, 104, 163, 54, 111, 91, 9, 240, 52, 176, \ + 230, 120, 48, 247, 129, 2), \ + XeNoiseRow16(scale, offset, 241, 81, 229, 16, 208, 141, 196, 80, 21, 107, \ + 159, 10, 189, 105, 173, 61), \ + XeNoiseRow16(scale, offset, 25, 126, 44, 180, 69, 34, 167, 122, 187, 255, \ + 36, 86, 226, 74, 209, 144), \ + XeNoiseRow16(scale, offset, 227, 201, 151, 102, 252, 218, 55, 233, 70, 137, \ + 198, 124, 146, 17, 45, 94), \ + XeNoiseRow16(scale, offset, 117, 5, 73, 169, 128, 3, 113, 152, 14, 101, 47, \ + 239, 66, 181, 248, 158) + +#endif // XENIA_UI_SHADERS_NOISE_XESLI_ diff --git a/src/xenia/ui/shaders/xesl.xesli b/src/xenia/ui/shaders/xesl.xesli new file mode 100644 index 000000000..d112c08a2 --- /dev/null +++ b/src/xenia/ui/shaders/xesl.xesli @@ -0,0 +1,45 @@ +#ifndef XENIA_UI_SHADERS_XESL_XESLI_ +#define XENIA_UI_SHADERS_XESL_XESLI_ + +// XESL_LANGUAGE_GLSL / HLSL are expected to be defined via compiler arguments. + +// Vectors. +#if XESL_LANGUAGE_GLSL + #define xesl_bool2 bvec2 + #define xesl_bool3 bvec3 + #define xesl_bool4 bvec4 + #define xesl_int2 ivec2 + #define xesl_int3 ivec3 + #define xesl_int4 ivec4 + #define xesl_uint2 uvec2 + #define xesl_uint3 uvec3 + #define xesl_uint4 uvec4 + #define xesl_float2 vec2 + #define xesl_float3 vec3 + #define xesl_float4 vec4 +#else + #define xesl_bool2 bool2 + #define xesl_bool3 bool3 + #define xesl_bool4 bool4 + #define xesl_int2 int2 + #define xesl_int3 int3 + #define xesl_int4 int4 + #define xesl_uint2 uint2 + #define xesl_uint3 uint3 + #define xesl_uint4 uint4 + #define xesl_float2 float2 + #define xesl_float3 float3 + #define xesl_float4 float4 +#endif // XESL_LANGUAGE_GLSL + +// Declarations. +#if XESL_LANGUAGE_HLSL + // HLSL requires static const to declare a constant in the global scope so it + // doesn't go to $Globals instead. + #define xesl_static static +#else + // GLSL requires just const to declare a constant in the global scope. + #define xesl_static +#endif // XESL_LANGUAGE_HLSL + +#endif // XENIA_UI_SHADERS_XESL_XESLI_ diff --git a/src/xenia/ui/surface.h b/src/xenia/ui/surface.h new file mode 100644 index 000000000..a37bcd8a3 --- /dev/null +++ b/src/xenia/ui/surface.h @@ -0,0 +1,83 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_H_ +#define XENIA_UI_SURFACE_H_ + +#include + +#include "xenia/base/assert.h" + +namespace xe { +namespace ui { + +// Represents a surface that presenting can be performed to. +// Surface methods can be called only from the UI thread. + +class Surface { + public: + enum TypeIndex { + // Within one platform, the more preferable surface types are earlier in + // this enumeration, so xe::bit_scan_forward can be used to try creating + // surfaces of all types supported by both the graphics provider and the + // window. + // Android. + kTypeIndex_AndroidNativeWindow, + // GNU/Linux. + kTypeIndex_XcbWindow, + // Windows. + kTypeIndex_Win32Hwnd, + }; + using TypeFlags = uint32_t; + enum : TypeFlags { + kTypeFlag_AndroidNativeWindow = TypeFlags(1) + << kTypeIndex_AndroidNativeWindow, + kTypeFlag_XcbWindow = TypeFlags(1) << kTypeIndex_XcbWindow, + kTypeFlag_Win32Hwnd = TypeFlags(1) << kTypeIndex_Win32Hwnd, + }; + + Surface(const Surface& surface) = delete; + Surface& operator=(const Surface& surface) = delete; + virtual ~Surface() = default; + + virtual TypeIndex GetType() const = 0; + + // Returns the up-to-date size (and true), or zeros (and false) if not ready + // to open a presentation connection yet. The size preferably should be + // exactly the dimensions of the surface in physical pixels of the display + // (without stretching performed by the platform's composition), but even if + // stretching happens, it is required that surface pixels have 1:1 aspect + // ratio relatively to the physical display. + bool GetSize(uint32_t& width_out, uint32_t& height_out) { + // If any dimension is 0 (like, resized completely to zero in one direction, + // but not in another), the surface is zero-area - don't try to present to + // it. + uint32_t width, height; + if (!GetSizeImpl(width, height) || !width || !height) { + width_out = 0; + height_out = 0; + return false; + } + width_out = width; + height_out = height; + return true; + } + + protected: + Surface() = default; + + // Returns the up-to-date size in physical pixels (and true), or zeros (and + // optionally false) if not ready to open a presentation connection yet. + virtual bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const = 0; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_H_ diff --git a/src/xenia/ui/surface_android.cc b/src/xenia/ui/surface_android.cc new file mode 100644 index 000000000..f4ea30a39 --- /dev/null +++ b/src/xenia/ui/surface_android.cc @@ -0,0 +1,34 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_android.h" + +#include + +namespace xe { +namespace ui { + +bool AndroidNativeWindowSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + if (!window_) { + return false; + } + int width = ANativeWindow_getWidth(window_); + int height = ANativeWindow_getHeight(window_); + // Negative value is returned in case of an error. + if (width <= 0 || height <= 0) { + return false; + } + width_out = uint32_t(width); + height_out = uint32_t(height); + return true; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_android.h b/src/xenia/ui/surface_android.h new file mode 100644 index 000000000..7b9c684bd --- /dev/null +++ b/src/xenia/ui/surface_android.h @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_ANDROID_H_ +#define XENIA_UI_SURFACE_ANDROID_H_ + +#include + +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { + +class AndroidNativeWindowSurface : public Surface { + public: + explicit AndroidNativeWindowSurface(ANativeWindow* window) + : window_(window) {} + TypeIndex GetType() const override { return kTypeIndex_AndroidNativeWindow; } + ANativeWindow* window() const { return window_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + ANativeWindow* window_; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_ANDROID_H_ diff --git a/src/xenia/ui/surface_gnulinux.cc b/src/xenia/ui/surface_gnulinux.cc new file mode 100644 index 000000000..9d3a990aa --- /dev/null +++ b/src/xenia/ui/surface_gnulinux.cc @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_gnulinux.h" + +#include + +namespace xe { +namespace ui { + +bool XcbWindowSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + xcb_get_geometry_reply_t* reply = xcb_get_geometry_reply( + connection_, xcb_get_geometry(connection_, window_), nullptr); + if (!reply) { + return false; + } + width_out = reply->width; + height_out = reply->height; + std::free(reply); + return true; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_gnulinux.h b/src/xenia/ui/surface_gnulinux.h new file mode 100644 index 000000000..44c6b98bc --- /dev/null +++ b/src/xenia/ui/surface_gnulinux.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_GNULINUX_H_ +#define XENIA_UI_SURFACE_GNULINUX_H_ + +#include + +#include "xenia/ui/surface.h" + +namespace xe { +namespace ui { + +class XcbWindowSurface final : public Surface { + public: + explicit XcbWindowSurface(xcb_connection_t* connection, xcb_window_t window) + : connection_(connection), window_(window) {} + TypeIndex GetType() const override { return kTypeIndex_XcbWindow; } + xcb_connection_t* connection() const { return connection_; } + xcb_window_t window() const { return window_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + xcb_connection_t* connection_; + xcb_window_t window_; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_LINUX_H_ diff --git a/src/xenia/ui/surface_win.cc b/src/xenia/ui/surface_win.cc new file mode 100644 index 000000000..3cdc0e271 --- /dev/null +++ b/src/xenia/ui/surface_win.cc @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/surface_win.h" + +#include +#include + +#include "xenia/base/logging.h" + +namespace xe { +namespace ui { + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) +bool Win32HwndSurface::GetSizeImpl(uint32_t& width_out, + uint32_t& height_out) const { + RECT client_rect; + if (!GetClientRect(hwnd(), &client_rect)) { + return false; + } + width_out = uint32_t(std::max(client_rect.right - client_rect.left, LONG(0))); + height_out = + uint32_t(std::max(client_rect.bottom - client_rect.top, LONG(0))); + return true; +} +#endif + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/surface_win.h b/src/xenia/ui/surface_win.h new file mode 100644 index 000000000..68d6f0e5f --- /dev/null +++ b/src/xenia/ui/surface_win.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SURFACE_WIN_H_ +#define XENIA_UI_SURFACE_WIN_H_ + +#include +#include + +#include "xenia/ui/surface.h" + +// Must be included before Windows headers for things like NOMINMAX. +#include "xenia/base/platform_win.h" + +namespace xe { +namespace ui { + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) +class Win32HwndSurface final : public Surface { + public: + explicit Win32HwndSurface(HINSTANCE hinstance, HWND hwnd) + : hinstance_(hinstance), hwnd_(hwnd) {} + TypeIndex GetType() const override { return kTypeIndex_Win32Hwnd; } + HINSTANCE hinstance() const { return hinstance_; } + HWND hwnd() const { return hwnd_; } + + protected: + bool GetSizeImpl(uint32_t& width_out, uint32_t& height_out) const override; + + private: + HINSTANCE hinstance_; + HWND hwnd_; +}; +#endif + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SURFACE_WIN_H_ diff --git a/src/xenia/ui/ui_drawer.h b/src/xenia/ui/ui_drawer.h new file mode 100644 index 000000000..b5173dfd6 --- /dev/null +++ b/src/xenia/ui/ui_drawer.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_UI_DRAWER_H_ +#define XENIA_UI_UI_DRAWER_H_ + +#include + +namespace xe { +namespace ui { + +class UIDrawContext; + +class UIDrawer { + public: + // No preparation or finishing callbacks because drawers may register or + // unregister each other, so between the loops the list may be different. + + // The draw function may register or unregister drawers (and depending on the + // Z order the changes may or may not effect immediately). However, they must + // not perform any lifetime management of the presenter and of its connection + // to the surface. Ideally drawing should not be changing any state at all, + // however, in Dear ImGui, input is handled directly during drawing - any + // quitting or resizing, if done in the UI, must be deferred via something + // like WindowedAppContext::CallInUIThreadDeferred. + virtual void Draw(UIDrawContext& context) = 0; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_UI_DRAWER_H_ diff --git a/src/xenia/ui/ui_event.h b/src/xenia/ui/ui_event.h index 993eda672..4d5520782 100644 --- a/src/xenia/ui/ui_event.h +++ b/src/xenia/ui/ui_event.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -27,12 +27,40 @@ class UIEvent { Window* target() const { return target_; } private: - Window* target_ = nullptr; + Window* target_; +}; + +class UISetupEvent : public UIEvent { + public: + explicit UISetupEvent(Window* target = nullptr, bool is_initial_setup = false) + : UIEvent(target), is_initial_setup_(is_initial_setup) {} + + bool is_initial_setup() const { return is_initial_setup_; } + + private: + bool is_initial_setup_; +}; + +class MonitorUpdateEvent : public UISetupEvent { + public: + explicit MonitorUpdateEvent(Window* target, + bool old_monitor_potentially_disconnected, + bool is_initial_setup = false) + : UISetupEvent(target, is_initial_setup), + old_monitor_potentially_disconnected_( + old_monitor_potentially_disconnected) {} + + bool old_monitor_potentially_disconnected() const { + return old_monitor_potentially_disconnected_; + } + + private: + bool old_monitor_potentially_disconnected_; }; class FileDropEvent : public UIEvent { public: - FileDropEvent(Window* target, std::filesystem::path filename) + explicit FileDropEvent(Window* target, std::filesystem::path filename) : UIEvent(target), filename_(std::move(filename)) {} ~FileDropEvent() override = default; @@ -44,10 +72,10 @@ class FileDropEvent : public UIEvent { class KeyEvent : public UIEvent { public: - KeyEvent(Window* target, VirtualKey virtual_key, int repeat_count, - bool prev_state, bool modifier_shift_pressed, - bool modifier_ctrl_pressed, bool modifier_alt_pressed, - bool modifier_super_pressed) + explicit KeyEvent(Window* target, VirtualKey virtual_key, int repeat_count, + bool prev_state, bool modifier_shift_pressed, + bool modifier_ctrl_pressed, bool modifier_alt_pressed, + bool modifier_super_pressed) : UIEvent(target), virtual_key_(virtual_key), repeat_count_(repeat_count), @@ -96,9 +124,17 @@ class MouseEvent : public UIEvent { }; public: - MouseEvent(Window* target, Button button, int32_t x, int32_t y, - int32_t dx = 0, int32_t dy = 0) - : UIEvent(target), button_(button), x_(x), y_(y), dx_(dx), dy_(dy) {} + // Matching Windows WHEEL_DELTA. + static constexpr uint32_t kScrollPerDetent = 120; + + explicit MouseEvent(Window* target, Button button, int32_t x, int32_t y, + int32_t scroll_x = 0, int32_t scroll_y = 0) + : UIEvent(target), + button_(button), + x_(x), + y_(y), + scroll_x_(scroll_x), + scroll_y_(scroll_y) {} ~MouseEvent() override = default; bool is_handled() const { return handled_; } @@ -107,16 +143,17 @@ class MouseEvent : public UIEvent { Button button() const { return button_; } int32_t x() const { return x_; } int32_t y() const { return y_; } - int32_t dx() const { return dx_; } - int32_t dy() const { return dy_; } + int32_t scroll_x() const { return scroll_x_; } + int32_t scroll_y() const { return scroll_y_; } private: bool handled_ = false; Button button_; int32_t x_ = 0; int32_t y_ = 0; - int32_t dx_ = 0; - int32_t dy_ = 0; + int32_t scroll_x_ = 0; + // Positive is up (away from the user), negative is down (towards the user). + int32_t scroll_y_ = 0; }; } // namespace ui diff --git a/src/xenia/ui/vulkan/blitter.cc b/src/xenia/ui/vulkan/blitter.cc index 165301d3c..25c6be7eb 100644 --- a/src/xenia/ui/vulkan/blitter.cc +++ b/src/xenia/ui/vulkan/blitter.cc @@ -10,23 +10,25 @@ #include "xenia/ui/vulkan/blitter.h" #include "xenia/base/math.h" #include "xenia/ui/vulkan/fenced_pools.h" +#include "xenia/ui/vulkan/vulkan_util.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" +using util::CheckResult; -Blitter::Blitter() {} +// Generated with `xenia-build genspirv`. +#include "xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_color_frag.h" +#include "xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.h" +#include "xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.h" + +Blitter::Blitter(const VulkanProvider& provider) : provider_(provider) {} Blitter::~Blitter() { Shutdown(); } -VkResult Blitter::Initialize(VulkanDevice* device) { - device_ = device; - - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); +VkResult Blitter::Initialize() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Shaders @@ -35,39 +37,36 @@ VkResult Blitter::Initialize(VulkanDevice* device) { 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 = dfn.vkCreateShaderModule(*device_, &shader_create_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(blit_vertex_), "S(B): Vertex"); shader_create_info.codeSize = sizeof(blit_color_frag); shader_create_info.pCode = reinterpret_cast(blit_color_frag); - status = dfn.vkCreateShaderModule(*device_, &shader_create_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(blit_color_), "S(B): Color"); shader_create_info.codeSize = sizeof(blit_depth_frag); shader_create_info.pCode = reinterpret_cast(blit_depth_frag); - status = dfn.vkCreateShaderModule(*device_, &shader_create_info, nullptr, + status = dfn.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"); + provider_.SetDeviceObjectName(VK_OBJECT_TYPE_SHADER_MODULE, + uint64_t(blit_depth_), "S(B): Depth"); // Create the descriptor set layout used for our texture sampler. // As it changes almost every draw we cache it per texture. @@ -84,7 +83,7 @@ VkResult Blitter::Initialize(VulkanDevice* device) { texture_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; texture_binding.pImmutableSamplers = nullptr; texture_set_layout_info.pBindings = &texture_binding; - status = dfn.vkCreateDescriptorSetLayout(*device_, &texture_set_layout_info, + status = dfn.vkCreateDescriptorSetLayout(device, &texture_set_layout_info, nullptr, &descriptor_set_layout_); CheckResult(status, "vkCreateDescriptorSetLayout"); if (status != VK_SUCCESS) { @@ -96,7 +95,7 @@ VkResult Blitter::Initialize(VulkanDevice* device) { pool_sizes[0].descriptorCount = 4096; pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; descriptor_pool_ = std::make_unique( - *device_, 4096, + provider_, 4096, std::vector(pool_sizes, std::end(pool_sizes))); // Create the pipeline layout used for our pipeline. @@ -120,7 +119,7 @@ VkResult Blitter::Initialize(VulkanDevice* device) { pipeline_layout_info.pushConstantRangeCount = static_cast(xe::countof(push_constant_ranges)); pipeline_layout_info.pPushConstantRanges = push_constant_ranges; - status = dfn.vkCreatePipelineLayout(*device_, &pipeline_layout_info, nullptr, + status = dfn.vkCreatePipelineLayout(device, &pipeline_layout_info, nullptr, &pipeline_layout_); CheckResult(status, "vkCreatePipelineLayout"); if (status != VK_SUCCESS) { @@ -148,7 +147,7 @@ VkResult Blitter::Initialize(VulkanDevice* device) { VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, VK_FALSE, }; - status = dfn.vkCreateSampler(*device_, &sampler_create_info, nullptr, + status = dfn.vkCreateSampler(device, &sampler_create_info, nullptr, &samp_nearest_); CheckResult(status, "vkCreateSampler"); if (status != VK_SUCCESS) { @@ -158,8 +157,8 @@ VkResult Blitter::Initialize(VulkanDevice* device) { sampler_create_info.minFilter = VK_FILTER_LINEAR; sampler_create_info.magFilter = VK_FILTER_LINEAR; sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - status = dfn.vkCreateSampler(*device_, &sampler_create_info, nullptr, - &samp_linear_); + status = + dfn.vkCreateSampler(device, &sampler_create_info, nullptr, &samp_linear_); CheckResult(status, "vkCreateSampler"); if (status != VK_SUCCESS) { return status; @@ -169,50 +168,26 @@ VkResult Blitter::Initialize(VulkanDevice* device) { } void Blitter::Shutdown() { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - if (samp_nearest_) { - dfn.vkDestroySampler(*device_, samp_nearest_, nullptr); - samp_nearest_ = nullptr; - } - if (samp_linear_) { - dfn.vkDestroySampler(*device_, samp_linear_, nullptr); - samp_linear_ = nullptr; - } - if (blit_vertex_) { - dfn.vkDestroyShaderModule(*device_, blit_vertex_, nullptr); - blit_vertex_ = nullptr; - } - if (blit_color_) { - dfn.vkDestroyShaderModule(*device_, blit_color_, nullptr); - blit_color_ = nullptr; - } - if (blit_depth_) { - dfn.vkDestroyShaderModule(*device_, blit_depth_, nullptr); - blit_depth_ = nullptr; - } - if (pipeline_color_) { - dfn.vkDestroyPipeline(*device_, pipeline_color_, nullptr); - pipeline_color_ = nullptr; - } - if (pipeline_depth_) { - dfn.vkDestroyPipeline(*device_, pipeline_depth_, nullptr); - pipeline_depth_ = nullptr; - } - if (pipeline_layout_) { - dfn.vkDestroyPipelineLayout(*device_, pipeline_layout_, nullptr); - pipeline_layout_ = nullptr; - } - if (descriptor_set_layout_) { - dfn.vkDestroyDescriptorSetLayout(*device_, descriptor_set_layout_, nullptr); - descriptor_set_layout_ = nullptr; - } + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + util::DestroyAndNullHandle(dfn.vkDestroySampler, device, samp_nearest_); + util::DestroyAndNullHandle(dfn.vkDestroySampler, device, samp_linear_); + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, blit_vertex_); + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, blit_color_); + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, blit_depth_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_color_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_depth_); + util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + pipeline_layout_); + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, + descriptor_set_layout_); for (auto& pipeline : pipelines_) { - dfn.vkDestroyPipeline(*device_, pipeline.second, nullptr); + dfn.vkDestroyPipeline(device, pipeline.second, nullptr); } pipelines_.clear(); for (auto& pass : render_passes_) { - dfn.vkDestroyRenderPass(*device_, pass.second, nullptr); + dfn.vkDestroyRenderPass(device, pass.second, nullptr); } render_passes_.clear(); } @@ -232,7 +207,8 @@ void Blitter::BlitTexture2D(VkCommandBuffer command_buffer, VkFence fence, VkFramebuffer dst_framebuffer, VkViewport viewport, VkRect2D scissor, VkFilter filter, bool color_or_depth, bool swap_channels) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Do we need a full draw, or can we cheap out with a blit command? bool full_draw = swap_channels || true; @@ -291,7 +267,7 @@ void Blitter::BlitTexture2D(VkCommandBuffer command_buffer, VkFence fence, write.pImageInfo = ℑ write.pBufferInfo = nullptr; write.pTexelBufferView = nullptr; - dfn.vkUpdateDescriptorSets(*device_, 1, &write, 0, nullptr); + dfn.vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); dfn.vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0, 1, &set, 0, nullptr); @@ -425,9 +401,10 @@ VkRenderPass Blitter::CreateRenderPass(VkFormat output_format, nullptr, }; VkRenderPass renderpass = nullptr; - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult result = - dfn.vkCreateRenderPass(*device_, &renderpass_info, nullptr, &renderpass); + dfn.vkCreateRenderPass(device, &renderpass_info, nullptr, &renderpass); CheckResult(result, "vkCreateRenderPass"); return renderpass; @@ -436,7 +413,8 @@ VkRenderPass Blitter::CreateRenderPass(VkFormat output_format, VkPipeline Blitter::CreatePipeline(VkRenderPass render_pass, VkShaderModule frag_shader, bool color_or_depth) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult result = VK_SUCCESS; // Pipeline @@ -582,7 +560,7 @@ VkPipeline Blitter::CreatePipeline(VkRenderPass render_pass, pipeline_info.basePipelineIndex = -1; VkPipeline pipeline = nullptr; - result = dfn.vkCreateGraphicsPipelines(*device_, nullptr, 1, &pipeline_info, + result = dfn.vkCreateGraphicsPipelines(device, nullptr, 1, &pipeline_info, nullptr, &pipeline); CheckResult(result, "vkCreateGraphicsPipelines"); diff --git a/src/xenia/ui/vulkan/blitter.h b/src/xenia/ui/vulkan/blitter.h index 2de0997d1..817b5efc7 100644 --- a/src/xenia/ui/vulkan/blitter.h +++ b/src/xenia/ui/vulkan/blitter.h @@ -13,8 +13,7 @@ #include #include -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace ui { @@ -24,10 +23,10 @@ class DescriptorPool; class Blitter { public: - Blitter(); + Blitter(const VulkanProvider& provider); ~Blitter(); - VkResult Initialize(VulkanDevice* device); + VkResult Initialize(); void Scavenge(); void Shutdown(); @@ -79,7 +78,7 @@ class Blitter { VkShaderModule frag_shader, bool color_or_depth); std::unique_ptr descriptor_pool_ = nullptr; - VulkanDevice* device_ = nullptr; + const VulkanProvider& provider_; VkPipeline pipeline_color_ = nullptr; VkPipeline pipeline_depth_ = nullptr; VkPipelineLayout pipeline_layout_ = nullptr; diff --git a/src/xenia/ui/vulkan/circular_buffer.cc b/src/xenia/ui/vulkan/circular_buffer.cc index 543342efe..30ba025cf 100644 --- a/src/xenia/ui/vulkan/circular_buffer.cc +++ b/src/xenia/ui/vulkan/circular_buffer.cc @@ -7,22 +7,27 @@ ****************************************************************************** */ +#include "xenia/ui/vulkan/circular_buffer.h" + #include #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" - -#include "xenia/ui/vulkan/circular_buffer.h" +#include "xenia/ui/vulkan/vulkan_util.h" namespace xe { namespace ui { namespace vulkan { -CircularBuffer::CircularBuffer(VulkanDevice* device, VkBufferUsageFlags usage, - VkDeviceSize capacity, VkDeviceSize alignment) - : device_(device), capacity_(capacity) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); +using util::CheckResult; + +CircularBuffer::CircularBuffer(const VulkanProvider& provider, + VkBufferUsageFlags usage, VkDeviceSize capacity, + VkDeviceSize alignment) + : provider_(provider), capacity_(capacity) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Create our internal buffer. @@ -35,14 +40,14 @@ CircularBuffer::CircularBuffer(VulkanDevice* device, VkBufferUsageFlags usage, buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; buffer_info.queueFamilyIndexCount = 0; buffer_info.pQueueFamilyIndices = nullptr; - status = dfn.vkCreateBuffer(*device_, &buffer_info, nullptr, &gpu_buffer_); + status = dfn.vkCreateBuffer(device, &buffer_info, nullptr, &gpu_buffer_); CheckResult(status, "vkCreateBuffer"); if (status != VK_SUCCESS) { assert_always(); } VkMemoryRequirements reqs; - dfn.vkGetBufferMemoryRequirements(*device_, gpu_buffer_, &reqs); + dfn.vkGetBufferMemoryRequirements(device, gpu_buffer_, &reqs); alignment_ = xe::round_up(alignment, reqs.alignment); } CircularBuffer::~CircularBuffer() { Shutdown(); } @@ -53,12 +58,12 @@ VkResult CircularBuffer::Initialize(VkDeviceMemory memory, gpu_memory_ = memory; gpu_base_ = offset; - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; // Bind the buffer to its backing memory. - status = - dfn.vkBindBufferMemory(*device_, gpu_buffer_, gpu_memory_, gpu_base_); + status = dfn.vkBindBufferMemory(device, gpu_buffer_, gpu_memory_, gpu_base_); CheckResult(status, "vkBindBufferMemory"); if (status != VK_SUCCESS) { XELOGE("CircularBuffer::Initialize - Failed to bind memory!"); @@ -67,7 +72,7 @@ VkResult CircularBuffer::Initialize(VkDeviceMemory memory, } // Map the memory so we can access it. - status = dfn.vkMapMemory(*device_, gpu_memory_, gpu_base_, capacity_, 0, + status = dfn.vkMapMemory(device, gpu_memory_, gpu_base_, capacity_, 0, reinterpret_cast(&host_base_)); CheckResult(status, "vkMapMemory"); if (status != VK_SUCCESS) { @@ -80,27 +85,39 @@ VkResult CircularBuffer::Initialize(VkDeviceMemory memory, } VkResult CircularBuffer::Initialize() { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); VkResult status = VK_SUCCESS; VkMemoryRequirements reqs; - dfn.vkGetBufferMemoryRequirements(*device_, gpu_buffer_, &reqs); + dfn.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!"); + VkMemoryAllocateInfo memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = reqs.size; + memory_allocate_info.memoryTypeIndex = ui::vulkan::util::ChooseHostMemoryType( + provider_, reqs.memoryTypeBits, false); + if (memory_allocate_info.memoryTypeIndex == UINT32_MAX) { + XELOGE("CircularBuffer::Initialize - Failed to get memory type!"); Shutdown(); return VK_ERROR_INITIALIZATION_FAILED; } + status = dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, + &gpu_memory_); + if (status != VK_SUCCESS) { + XELOGE("CircularBuffer::Initialize - Failed to allocate memory!"); + Shutdown(); + return status; + } capacity_ = reqs.size; gpu_base_ = 0; // Bind the buffer to its backing memory. - status = - dfn.vkBindBufferMemory(*device_, gpu_buffer_, gpu_memory_, gpu_base_); + status = dfn.vkBindBufferMemory(device, gpu_buffer_, gpu_memory_, gpu_base_); CheckResult(status, "vkBindBufferMemory"); if (status != VK_SUCCESS) { XELOGE("CircularBuffer::Initialize - Failed to bind memory!"); @@ -109,7 +126,7 @@ VkResult CircularBuffer::Initialize() { } // Map the memory so we can access it. - status = dfn.vkMapMemory(*device_, gpu_memory_, gpu_base_, capacity_, 0, + status = dfn.vkMapMemory(device, gpu_memory_, gpu_base_, capacity_, 0, reinterpret_cast(&host_base_)); CheckResult(status, "vkMapMemory"); if (status != VK_SUCCESS) { @@ -123,24 +140,26 @@ VkResult CircularBuffer::Initialize() { void CircularBuffer::Shutdown() { Clear(); - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); if (host_base_) { - dfn.vkUnmapMemory(*device_, gpu_memory_); + dfn.vkUnmapMemory(device, gpu_memory_); host_base_ = nullptr; } if (gpu_buffer_) { - dfn.vkDestroyBuffer(*device_, gpu_buffer_, nullptr); + dfn.vkDestroyBuffer(device, gpu_buffer_, nullptr); gpu_buffer_ = nullptr; } if (gpu_memory_ && owns_gpu_memory_) { - dfn.vkFreeMemory(*device_, gpu_memory_, nullptr); + dfn.vkFreeMemory(device, gpu_memory_, nullptr); gpu_memory_ = nullptr; } } void CircularBuffer::GetBufferMemoryRequirements(VkMemoryRequirements* reqs) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - dfn.vkGetBufferMemoryRequirements(*device_, gpu_buffer_, reqs); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkGetBufferMemoryRequirements(device, gpu_buffer_, reqs); } bool CircularBuffer::CanAcquire(VkDeviceSize length) { @@ -231,25 +250,27 @@ CircularBuffer::Allocation* CircularBuffer::Acquire(VkDeviceSize length, } void CircularBuffer::Flush(Allocation* allocation) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); 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; - dfn.vkFlushMappedMemoryRanges(*device_, 1, &range); + dfn.vkFlushMappedMemoryRanges(device, 1, &range); } void CircularBuffer::Flush(VkDeviceSize offset, VkDeviceSize length) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); 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; - dfn.vkFlushMappedMemoryRanges(*device_, 1, &range); + dfn.vkFlushMappedMemoryRanges(device, 1, &range); } void CircularBuffer::Clear() { @@ -258,14 +279,15 @@ void CircularBuffer::Clear() { } void CircularBuffer::Scavenge() { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Stash the last signalled fence VkFence fence = nullptr; while (!allocations_.empty()) { Allocation& alloc = allocations_.front(); if (fence != alloc.fence && - dfn.vkGetFenceStatus(*device_, alloc.fence) != VK_SUCCESS) { + dfn.vkGetFenceStatus(device, alloc.fence) != VK_SUCCESS) { // Don't bother freeing following allocations to ensure proper ordering. break; } diff --git a/src/xenia/ui/vulkan/circular_buffer.h b/src/xenia/ui/vulkan/circular_buffer.h index 85b069aa0..9f54b706a 100644 --- a/src/xenia/ui/vulkan/circular_buffer.h +++ b/src/xenia/ui/vulkan/circular_buffer.h @@ -12,8 +12,7 @@ #include -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace ui { @@ -27,7 +26,7 @@ namespace vulkan { // ends of the buffer), where trailing older allocations are freed after use. class CircularBuffer { public: - CircularBuffer(VulkanDevice* device, VkBufferUsageFlags usage, + CircularBuffer(const VulkanProvider& provider, VkBufferUsageFlags usage, VkDeviceSize capacity, VkDeviceSize alignment = 256); ~CircularBuffer(); @@ -76,7 +75,7 @@ class CircularBuffer { VkDeviceSize write_head_ = 0; VkDeviceSize read_head_ = 0; - VulkanDevice* device_; + const VulkanProvider& provider_; bool owns_gpu_memory_ = false; VkBuffer gpu_buffer_ = nullptr; VkDeviceMemory gpu_memory_ = nullptr; diff --git a/src/xenia/ui/vulkan/fenced_pools.cc b/src/xenia/ui/vulkan/fenced_pools.cc index f6ce79662..ef4794c71 100644 --- a/src/xenia/ui/vulkan/fenced_pools.cc +++ b/src/xenia/ui/vulkan/fenced_pools.cc @@ -17,12 +17,13 @@ namespace xe { namespace ui { namespace vulkan { -using xe::ui::vulkan::CheckResult; +using util::CheckResult; -CommandBufferPool::CommandBufferPool(const VulkanDevice& device, +CommandBufferPool::CommandBufferPool(const VulkanProvider& provider, uint32_t queue_family_index) - : BaseFencedPool(device) { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + : BaseFencedPool(provider) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // Create the pool used for allocating buffers. // They are marked as transient (short-lived) and cycled frequently. @@ -33,7 +34,7 @@ CommandBufferPool::CommandBufferPool(const VulkanDevice& device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; cmd_pool_info.queueFamilyIndex = queue_family_index; auto err = - dfn.vkCreateCommandPool(device_, &cmd_pool_info, nullptr, &command_pool_); + dfn.vkCreateCommandPool(device, &cmd_pool_info, nullptr, &command_pool_); CheckResult(err, "vkCreateCommandPool"); // Allocate a bunch of command buffers to start. @@ -45,7 +46,7 @@ CommandBufferPool::CommandBufferPool(const VulkanDevice& device, command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; command_buffer_info.commandBufferCount = kDefaultCount; VkCommandBuffer command_buffers[kDefaultCount]; - err = dfn.vkAllocateCommandBuffers(device_, &command_buffer_info, + err = dfn.vkAllocateCommandBuffers(device, &command_buffer_info, command_buffers); CheckResult(err, "vkCreateCommandBuffer"); for (size_t i = 0; i < xe::countof(command_buffers); ++i) { @@ -55,8 +56,9 @@ CommandBufferPool::CommandBufferPool(const VulkanDevice& device, CommandBufferPool::~CommandBufferPool() { FreeAllEntries(); - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkDestroyCommandPool(device_, command_pool_, nullptr); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyCommandPool(device, command_pool_, nullptr); command_pool_ = nullptr; } @@ -70,21 +72,24 @@ VkCommandBuffer CommandBufferPool::AllocateEntry(void* data) { VkCommandBufferLevel(reinterpret_cast(data)); command_buffer_info.commandBufferCount = 1; VkCommandBuffer command_buffer; - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - auto err = dfn.vkAllocateCommandBuffers(device_, &command_buffer_info, + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + auto err = dfn.vkAllocateCommandBuffers(device, &command_buffer_info, &command_buffer); CheckResult(err, "vkCreateCommandBuffer"); return command_buffer; } void CommandBufferPool::FreeEntry(VkCommandBuffer handle) { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkFreeCommandBuffers(device_, command_pool_, 1, &handle); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkFreeCommandBuffers(device, command_pool_, 1, &handle); } -DescriptorPool::DescriptorPool(const VulkanDevice& device, uint32_t max_count, +DescriptorPool::DescriptorPool(const VulkanProvider& provider, + uint32_t max_count, std::vector pool_sizes) - : BaseFencedPool(device) { + : BaseFencedPool(provider) { VkDescriptorPoolCreateInfo descriptor_pool_info; descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptor_pool_info.pNext = nullptr; @@ -93,15 +98,17 @@ DescriptorPool::DescriptorPool(const VulkanDevice& device, uint32_t max_count, descriptor_pool_info.maxSets = max_count; descriptor_pool_info.poolSizeCount = uint32_t(pool_sizes.size()); descriptor_pool_info.pPoolSizes = pool_sizes.data(); - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); auto err = dfn.vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool_); CheckResult(err, "vkCreateDescriptorPool"); } DescriptorPool::~DescriptorPool() { FreeAllEntries(); - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkDestroyDescriptorPool(device_, descriptor_pool_, nullptr); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyDescriptorPool(device, descriptor_pool_, nullptr); descriptor_pool_ = nullptr; } @@ -115,17 +122,19 @@ VkDescriptorSet DescriptorPool::AllocateEntry(void* data) { set_alloc_info.descriptorPool = descriptor_pool_; set_alloc_info.descriptorSetCount = 1; set_alloc_info.pSetLayouts = &layout; - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); auto err = - dfn.vkAllocateDescriptorSets(device_, &set_alloc_info, &descriptor_set); + dfn.vkAllocateDescriptorSets(device, &set_alloc_info, &descriptor_set); CheckResult(err, "vkAllocateDescriptorSets"); return descriptor_set; } void DescriptorPool::FreeEntry(VkDescriptorSet handle) { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - dfn.vkFreeDescriptorSets(device_, descriptor_pool_, 1, &handle); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkFreeDescriptorSets(device, descriptor_pool_, 1, &handle); } } // namespace vulkan diff --git a/src/xenia/ui/vulkan/fenced_pools.h b/src/xenia/ui/vulkan/fenced_pools.h index 0af6dd694..728b7aaae 100644 --- a/src/xenia/ui/vulkan/fenced_pools.h +++ b/src/xenia/ui/vulkan/fenced_pools.h @@ -13,8 +13,7 @@ #include #include "xenia/base/assert.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" +#include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_util.h" namespace xe { @@ -29,7 +28,7 @@ namespace vulkan { template class BaseFencedPool { public: - BaseFencedPool(const VulkanDevice& device) : device_(device) {} + BaseFencedPool(const VulkanProvider& provider) : provider_(provider) {} virtual ~BaseFencedPool() { // TODO(benvanik): wait on fence until done. @@ -48,12 +47,13 @@ class BaseFencedPool { // Checks all pending batches for completion and scavenges their entries. // This should be called as frequently as reasonable. void Scavenge() { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); while (pending_batch_list_head_) { auto batch = pending_batch_list_head_; assert_not_null(batch->fence); - VkResult status = dfn.vkGetFenceStatus(device_, batch->fence); + VkResult status = dfn.vkGetFenceStatus(device, batch->fence); if (status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST) { // Batch has completed. Reclaim. pending_batch_list_head_ = batch->next; @@ -82,7 +82,8 @@ class BaseFencedPool { VkFence BeginBatch(VkFence fence = nullptr) { assert_null(open_batch_); Batch* batch = nullptr; - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); if (free_batch_list_head_) { // Reuse a batch. batch = free_batch_list_head_; @@ -91,10 +92,10 @@ class BaseFencedPool { if (batch->flags & kBatchOwnsFence && !fence) { // Reset owned fence. - dfn.vkResetFences(device_, 1, &batch->fence); + dfn.vkResetFences(device, 1, &batch->fence); } else if ((batch->flags & kBatchOwnsFence) && fence) { // Transfer owned -> external - dfn.vkDestroyFence(device_, batch->fence, nullptr); + dfn.vkDestroyFence(device, batch->fence, nullptr); batch->fence = fence; batch->flags &= ~kBatchOwnsFence; } else if (!(batch->flags & kBatchOwnsFence) && !fence) { @@ -103,8 +104,7 @@ class BaseFencedPool { info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; info.pNext = nullptr; info.flags = 0; - VkResult res = - dfn.vkCreateFence(device_, &info, nullptr, &batch->fence); + VkResult res = dfn.vkCreateFence(device, &info, nullptr, &batch->fence); if (res != VK_SUCCESS) { assert_always(); } @@ -125,8 +125,7 @@ class BaseFencedPool { info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; info.pNext = nullptr; info.flags = 0; - VkResult res = - dfn.vkCreateFence(device_, &info, nullptr, &batch->fence); + VkResult res = dfn.vkCreateFence(device, &info, nullptr, &batch->fence); if (res != VK_SUCCESS) { assert_always(); } @@ -244,14 +243,15 @@ class BaseFencedPool { } void FreeAllEntries() { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); // 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) { - dfn.vkDestroyFence(device_, batch->fence, nullptr); + dfn.vkDestroyFence(device, batch->fence, nullptr); batch->fence = nullptr; } delete batch; @@ -264,7 +264,7 @@ class BaseFencedPool { } } - const VulkanDevice& device_; + const VulkanProvider& provider_; private: struct Entry { @@ -294,7 +294,8 @@ class CommandBufferPool public: typedef BaseFencedPool Base; - CommandBufferPool(const VulkanDevice& device, uint32_t queue_family_index); + CommandBufferPool(const VulkanProvider& provider, + uint32_t queue_family_index); ~CommandBufferPool() override; VkCommandBuffer AcquireEntry( @@ -314,7 +315,7 @@ class DescriptorPool : public BaseFencedPool { public: typedef BaseFencedPool Base; - DescriptorPool(const VulkanDevice& device, uint32_t max_count, + DescriptorPool(const VulkanProvider& provider, uint32_t max_count, std::vector pool_sizes); ~DescriptorPool() override; diff --git a/src/xenia/ui/vulkan/functions/device_1_0.inc b/src/xenia/ui/vulkan/functions/device_1_0.inc index aed4f435a..58e18bb7f 100644 --- a/src/xenia/ui/vulkan/functions/device_1_0.inc +++ b/src/xenia/ui/vulkan/functions/device_1_0.inc @@ -3,16 +3,18 @@ XE_UI_VULKAN_FUNCTION(vkAllocateCommandBuffers) XE_UI_VULKAN_FUNCTION(vkAllocateDescriptorSets) XE_UI_VULKAN_FUNCTION(vkAllocateMemory) XE_UI_VULKAN_FUNCTION(vkBeginCommandBuffer) -XE_UI_VULKAN_FUNCTION(vkCmdBeginRenderPass) -XE_UI_VULKAN_FUNCTION(vkCmdBindDescriptorSets) XE_UI_VULKAN_FUNCTION(vkBindBufferMemory) XE_UI_VULKAN_FUNCTION(vkBindImageMemory) +XE_UI_VULKAN_FUNCTION(vkCmdBeginRenderPass) +XE_UI_VULKAN_FUNCTION(vkCmdBindDescriptorSets) XE_UI_VULKAN_FUNCTION(vkCmdBindIndexBuffer) XE_UI_VULKAN_FUNCTION(vkCmdBindPipeline) XE_UI_VULKAN_FUNCTION(vkCmdBindVertexBuffers) XE_UI_VULKAN_FUNCTION(vkCmdBlitImage) +XE_UI_VULKAN_FUNCTION(vkCmdClearAttachments) XE_UI_VULKAN_FUNCTION(vkCmdClearColorImage) XE_UI_VULKAN_FUNCTION(vkCmdClearDepthStencilImage) +XE_UI_VULKAN_FUNCTION(vkCmdCopyBuffer) XE_UI_VULKAN_FUNCTION(vkCmdCopyBufferToImage) XE_UI_VULKAN_FUNCTION(vkCmdCopyImageToBuffer) XE_UI_VULKAN_FUNCTION(vkCmdDraw) @@ -67,17 +69,20 @@ XE_UI_VULKAN_FUNCTION(vkFlushMappedMemoryRanges) XE_UI_VULKAN_FUNCTION(vkFreeCommandBuffers) XE_UI_VULKAN_FUNCTION(vkFreeDescriptorSets) XE_UI_VULKAN_FUNCTION(vkFreeMemory) -XE_UI_VULKAN_FUNCTION(vkGetDeviceQueue) XE_UI_VULKAN_FUNCTION(vkGetBufferMemoryRequirements) +XE_UI_VULKAN_FUNCTION(vkGetDeviceQueue) XE_UI_VULKAN_FUNCTION(vkGetFenceStatus) XE_UI_VULKAN_FUNCTION(vkGetImageMemoryRequirements) XE_UI_VULKAN_FUNCTION(vkGetImageSubresourceLayout) XE_UI_VULKAN_FUNCTION(vkGetPipelineCacheData) +XE_UI_VULKAN_FUNCTION(vkInvalidateMappedMemoryRanges) XE_UI_VULKAN_FUNCTION(vkMapMemory) +XE_UI_VULKAN_FUNCTION(vkResetCommandBuffer) +XE_UI_VULKAN_FUNCTION(vkResetCommandPool) +XE_UI_VULKAN_FUNCTION(vkResetDescriptorPool) +XE_UI_VULKAN_FUNCTION(vkResetFences) XE_UI_VULKAN_FUNCTION(vkQueueSubmit) XE_UI_VULKAN_FUNCTION(vkQueueWaitIdle) -XE_UI_VULKAN_FUNCTION(vkResetCommandBuffer) -XE_UI_VULKAN_FUNCTION(vkResetFences) XE_UI_VULKAN_FUNCTION(vkUnmapMemory) XE_UI_VULKAN_FUNCTION(vkUpdateDescriptorSets) XE_UI_VULKAN_FUNCTION(vkWaitForFences) diff --git a/src/xenia/ui/vulkan/functions/device_ext_debug_marker.inc b/src/xenia/ui/vulkan/functions/device_ext_debug_marker.inc deleted file mode 100644 index 11a44aa81..000000000 --- a/src/xenia/ui/vulkan/functions/device_ext_debug_marker.inc +++ /dev/null @@ -1,5 +0,0 @@ -// VK_EXT_debug_marker functions used in Xenia. -XE_UI_VULKAN_FUNCTION(vkDebugMarkerSetObjectNameEXT) -XE_UI_VULKAN_FUNCTION(vkCmdDebugMarkerBeginEXT) -XE_UI_VULKAN_FUNCTION(vkCmdDebugMarkerEndEXT) -XE_UI_VULKAN_FUNCTION(vkCmdDebugMarkerInsertEXT) diff --git a/src/xenia/ui/vulkan/functions/instance_1_0.inc b/src/xenia/ui/vulkan/functions/instance_1_0.inc index 8fbb7f8ca..0da71a57c 100644 --- a/src/xenia/ui/vulkan/functions/instance_1_0.inc +++ b/src/xenia/ui/vulkan/functions/instance_1_0.inc @@ -2,7 +2,6 @@ XE_UI_VULKAN_FUNCTION(vkCreateDevice) XE_UI_VULKAN_FUNCTION(vkDestroyDevice) XE_UI_VULKAN_FUNCTION(vkEnumerateDeviceExtensionProperties) -XE_UI_VULKAN_FUNCTION(vkEnumerateDeviceLayerProperties) XE_UI_VULKAN_FUNCTION(vkEnumeratePhysicalDevices) XE_UI_VULKAN_FUNCTION(vkGetDeviceProcAddr) XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceFeatures) diff --git a/src/xenia/ui/vulkan/functions/instance_ext_debug_report.inc b/src/xenia/ui/vulkan/functions/instance_ext_debug_report.inc deleted file mode 100644 index 4d57b9552..000000000 --- a/src/xenia/ui/vulkan/functions/instance_ext_debug_report.inc +++ /dev/null @@ -1,3 +0,0 @@ -// VK_EXT_debug_report functions used in Xenia. -XE_UI_VULKAN_FUNCTION(vkCreateDebugReportCallbackEXT) -XE_UI_VULKAN_FUNCTION(vkDestroyDebugReportCallbackEXT) diff --git a/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc b/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc new file mode 100644 index 000000000..c0c9df20c --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_ext_debug_utils.inc @@ -0,0 +1,4 @@ +// VK_EXT_debug_utils functions used in Xenia. +XE_UI_VULKAN_FUNCTION(vkCreateDebugUtilsMessengerEXT) +XE_UI_VULKAN_FUNCTION(vkDestroyDebugUtilsMessengerEXT) +XE_UI_VULKAN_FUNCTION(vkSetDebugUtilsObjectNameEXT) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc new file mode 100644 index 000000000..05b2fe800 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc @@ -0,0 +1,4 @@ +// VK_KHR_get_physical_device_properties2 functions used in Xenia. +// Promoted to Vulkan 1.1 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceProperties2KHR, + vkGetPhysicalDeviceProperties2) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc b/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc index bbda68af6..9b6d673d5 100644 --- a/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc +++ b/src/xenia/ui/vulkan/functions/instance_khr_win32_surface.inc @@ -1,2 +1,3 @@ // VK_KHR_win32_surface functions used in Xenia. XE_UI_VULKAN_FUNCTION(vkCreateWin32SurfaceKHR) +XE_UI_VULKAN_FUNCTION(vkGetPhysicalDeviceWin32PresentationSupportKHR) 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&2exQGeyF1(;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_=r#fx|$D0tyz2rASIV{kXt|I~lcKh-J- zKF?+sGcY@6-g(cQch1?$XmdPbBqn1bKF7f3V-zG}Dr$LbonD;orrGuG{0iVa`;E8hps|sBs{<5hGI?S(9bI<*;wQ9_;P9Lt?+09edf4Ir{ z_Iu2p+Wkj4wOAoP@29_x@4IQ%>1HW;jf%L|?scw>C8pN&cc&-j{#9a+{q3vw1}#*n zV@ncdu9lrVd(Rs~xw=aJ$n!e^=FYN!JI5s~?{*QFBYs2&^@#nXu7(Xxi96Q_t~pn!P0lmbvY+u4=6C!J D32Qgg literal 0 HcmV?d00001 diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.txt b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_color_frag.txt similarity index 98% rename from src/xenia/ui/vulkan/shaders/bin/blit_color_frag.txt rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_color_frag.txt index 5720bad67..36ae0fb3f 100644 --- a/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.txt +++ b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_color_frag.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 36 ; Schema: 0 OpCapability Shader diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.h b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.h similarity index 98% rename from src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.h rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.h index ac499a78f..ceec5cedb 100644 --- a/src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.h +++ b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.h @@ -1,7 +1,7 @@ // generated from `xb genspirv` // source: blit_depth.frag const uint8_t blit_depth_frag[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x1E, 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, diff --git a/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.spv b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..59b51dfd660e6af10033a4c71225857585e7d9f8 GIT binary patch literal 660 zcmYk3OH0F05QWF2skPPCTBwK*`q&p2DuU=nv72thh09PhRKXYNZRzjxSGf^9--JLX z40F%9XC8MFN5f6C4XaztPOPxDMPkevR`ocZJWfXQ@G?3(KSj~B*oA0X%Bv{iAJex_ zE^6{!`LV~?@6<$Gao*NB))y)Ms7NBkdVZq5)R?`e_xW^omwks z*K@BJ?_@i0SIP%71Kfda=_~Ho-MW?dP|CV4(Djth>=+#Nz`Oz57j7!ji@DIZ6sZM| z9?YBI(C;atXW!_L6qyYkJ(xGcU1*!sMT^1xib)i&#WK^5oO!_XY|H8QBo#F~ay0M{ U;^@u4fX8lBmHoi|Y069aKf)*=>i_@% literal 0 HcmV?d00001 diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.txt b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.txt similarity index 97% rename from src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.txt rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.txt index e2bd81d13..563dc1550 100644 --- a/src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.txt +++ b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_depth_frag.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 30 ; Schema: 0 OpCapability Shader diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_vert.h b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.h similarity index 99% rename from src/xenia/ui/vulkan/shaders/bin/blit_vert.h rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.h index f101b89c9..53e39aa65 100644 --- a/src/xenia/ui/vulkan/shaders/bin/blit_vert.h +++ b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.h @@ -1,7 +1,7 @@ // generated from `xb genspirv` // source: blit.vert const uint8_t blit_vert[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x4C, 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, diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_vert.spv b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.spv similarity index 59% rename from src/xenia/ui/vulkan/shaders/bin/blit_vert.spv rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.spv index f68aabdb86a17173775b417187502b5e319b9fbc..4a7dc6d1784d06a14808b667186bedac6a4aa3e4 100644 GIT binary patch delta 18 ZcmX@YdxV#hnMs+Qfq{{MYa{1wHUJ{h17QFF delta 18 ZcmX@YdxV#hnMs+Qfq{{MZ6oJyHUJ{N16=?B diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_vert.txt b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.txt similarity index 98% rename from src/xenia/ui/vulkan/shaders/bin/blit_vert.txt rename to src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.txt index 7f423f63d..216c2cbec 100644 --- a/src/xenia/ui/vulkan/shaders/bin/blit_vert.txt +++ b/src/xenia/ui/vulkan/shaders/bytecode/vulkan_spirv/blit_vert.txt @@ -1,6 +1,6 @@ ; SPIR-V ; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 +; Generator: Khronos Glslang Reference Front End; 10 ; Bound: 76 ; Schema: 0 OpCapability Shader diff --git a/src/xenia/ui/vulkan/shaders/immediate.frag b/src/xenia/ui/vulkan/shaders/immediate.frag deleted file mode 100644 index bf505bf46..000000000 --- a/src/xenia/ui/vulkan/shaders/immediate.frag +++ /dev/null @@ -1,28 +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 -precision highp float; - -layout(push_constant) uniform PushConstants { - layout(offset = 64) int restrict_texture_samples; -} push_constants; - -layout(set = 0, binding = 0) uniform sampler2D texture_sampler; - -layout(set = 0, binding = 1) uniform sampler1D tex1D; -layout(set = 0, binding = 1) uniform sampler2D tex2D; - -layout(location = 0) in vec2 vtx_uv; -layout(location = 1) in vec4 vtx_color; - -layout(location = 0) out vec4 out_color; - -void main() { - out_color = vtx_color; - if (push_constants.restrict_texture_samples == 0 || vtx_uv.x <= 1.0) { - vec4 tex_color = texture(texture_sampler, vtx_uv); - out_color *= tex_color; - // TODO(benvanik): microprofiler shadows. - } -} diff --git a/src/xenia/ui/vulkan/shaders/immediate.vert b/src/xenia/ui/vulkan/shaders/immediate.vert deleted file mode 100644 index 8ac6c4b70..000000000 --- a/src/xenia/ui/vulkan/shaders/immediate.vert +++ /dev/null @@ -1,23 +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 -precision highp float; - -layout(push_constant) uniform PushConstants { - layout(offset = 0) mat4 projection_matrix; -} push_constants; - -layout(location = 0) in vec2 in_pos; -layout(location = 1) in vec2 in_uv; -layout(location = 2) in vec4 in_color; - -layout(location = 0) out vec2 vtx_uv; -layout(location = 1) out vec4 vtx_color; - -void main() { - gl_Position = push_constants.projection_matrix * vec4(in_pos.xy, 0.0, 1.0); - gl_Position.y = -gl_Position.y; - vtx_uv = in_uv; - vtx_color = in_color; -} diff --git a/src/xenia/ui/vulkan/vulkan.cc b/src/xenia/ui/vulkan/vulkan.cc deleted file mode 100644 index 5bc610557..000000000 --- a/src/xenia/ui/vulkan/vulkan.cc +++ /dev/null @@ -1,18 +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.h" - -DEFINE_bool(vulkan_validation, false, "Enable Vulkan validation layers.", - "Vulkan"); - -DEFINE_bool(vulkan_primary_queue_only, false, - "Force the use of the primary queue, ignoring any additional that " - "may be present.", - "Vulkan"); diff --git a/src/xenia/ui/vulkan/vulkan.h b/src/xenia/ui/vulkan/vulkan.h deleted file mode 100644 index 9ba44197c..000000000 --- a/src/xenia/ui/vulkan/vulkan.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_UI_VULKAN_VULKAN_H_ -#define XENIA_UI_VULKAN_VULKAN_H_ - -#include "xenia/base/cvar.h" -#include "xenia/base/platform.h" - -#if XE_PLATFORM_ANDROID -#ifndef VK_USE_PLATFORM_ANDROID_KHR -#define VK_USE_PLATFORM_ANDROID_KHR 1 -#endif -#elif XE_PLATFORM_GNU_LINUX -#ifndef VK_USE_PLATFORM_XCB_KHR -#define VK_USE_PLATFORM_XCB_KHR 1 -#endif -#elif XE_PLATFORM_WIN32 -// Must be included before vulkan.h with VK_USE_PLATFORM_WIN32_KHR because it -// includes Windows.h too. -#include "xenia/base/platform_win.h" -#ifndef VK_USE_PLATFORM_WIN32_KHR -#define VK_USE_PLATFORM_WIN32_KHR 1 -#endif -#endif - -#ifndef VK_NO_PROTOTYPES -#define VK_NO_PROTOTYPES 1 -#endif -#include "third_party/vulkan/vulkan.h" - -#define XELOGVK XELOGI - -DECLARE_bool(vulkan_validation); -DECLARE_bool(vulkan_primary_queue_only); - -#endif // XENIA_UI_VULKAN_VULKAN_H_ diff --git a/src/xenia/ui/vulkan/vulkan_context.cc b/src/xenia/ui/vulkan/vulkan_context.cc deleted file mode 100644 index 50a4e7a8a..000000000 --- a/src/xenia/ui/vulkan/vulkan_context.cc +++ /dev/null @@ -1,206 +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_context.h" - -#include -#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_GNU_LINUX -#include "xenia/ui/window_gtk.h" - -#include -#endif - -namespace xe { -namespace ui { -namespace vulkan { - -VulkanContext::VulkanContext(VulkanProvider* provider, Window* target_window) - : GraphicsContext(provider, target_window) {} - -VulkanContext::~VulkanContext() { - VkResult status; - auto provider = static_cast(provider_); - VulkanDevice* device = provider->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - { - std::lock_guard queue_lock(device->primary_queue_mutex()); - status = dfn.vkQueueWaitIdle(device->primary_queue()); - } - immediate_drawer_.reset(); - swap_chain_.reset(); -} - -bool VulkanContext::Initialize() { - auto provider = static_cast(provider_); - VulkanInstance* instance = provider->instance(); - const VulkanInstance::InstanceFunctions& ifn = instance->ifn(); - - 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 = ifn.vkCreateWin32SurfaceKHR(*provider->instance(), &create_info, - nullptr, &surface); - CheckResult(status, "vkCreateWin32SurfaceKHR"); -#elif XE_PLATFORM_GNU_LINUX -#ifdef GDK_WINDOWING_X11 - GtkWidget* window_handle = - dynamic_cast(target_window_)->native_window_handle(); - 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 = ifn.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(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; -} - -ImmediateDrawer* VulkanContext::immediate_drawer() { - return immediate_drawer_.get(); -} - -VulkanInstance* VulkanContext::instance() const { - return static_cast(provider_)->instance(); -} - -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() {} - -bool VulkanContext::BeginSwap() { - SCOPE_profile_cpu_f("gpu"); - auto provider = static_cast(provider_); - VulkanDevice* device = provider->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - - 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 = dfn.vkQueueWaitIdle(device->primary_queue()); - - return true; -} - -void VulkanContext::EndSwap() { - SCOPE_profile_cpu_f("gpu"); - auto provider = static_cast(provider_); - VulkanDevice* device = provider->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - - 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 = dfn.vkQueueWaitIdle(device->primary_queue()); -} - -std::unique_ptr VulkanContext::Capture() { - // TODO(benvanik): read back swap chain front buffer. - return nullptr; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_context.h b/src/xenia/ui/vulkan/vulkan_context.h deleted file mode 100644 index f5658bdd1..000000000 --- a/src/xenia/ui/vulkan/vulkan_context.h +++ /dev/null @@ -1,67 +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_CONTEXT_H_ -#define XENIA_UI_VULKAN_VULKAN_CONTEXT_H_ - -#include - -#include "xenia/ui/graphics_context.h" -#include "xenia/ui/vulkan/vulkan.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_; } - - bool BeginSwap() override; - void EndSwap() override; - - std::unique_ptr Capture() override; - - protected: - bool context_lost_ = false; - - private: - friend class VulkanProvider; - - explicit VulkanContext(VulkanProvider* provider, Window* target_window); - - private: - bool Initialize(); - - std::unique_ptr swap_chain_; - std::unique_ptr immediate_drawer_; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_CONTEXT_H_ diff --git a/src/xenia/ui/vulkan/vulkan_device.cc b/src/xenia/ui/vulkan/vulkan_device.cc deleted file mode 100644 index 704e43c2d..000000000 --- a/src/xenia/ui/vulkan/vulkan_device.cc +++ /dev/null @@ -1,427 +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 - -#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) { - const VulkanInstance::InstanceFunctions& ifn = instance_->ifn(); - ifn.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; - } - - const VulkanInstance::InstanceFunctions& ifn = instance_->ifn(); - - // Query supported features so we can make sure we have what we need. - VkPhysicalDeviceFeatures supported_features; - ifn.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 = - ifn.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; - } - - // Get device functions. - std::memset(&dfn_, 0, sizeof(dfn_)); - bool device_functions_loaded = true; - debug_marker_ena_ = false; -#define XE_UI_VULKAN_FUNCTION(name) \ - device_functions_loaded &= \ - (dfn_.name = PFN_##name(ifn.vkGetDeviceProcAddr(handle, #name))) != \ - nullptr; -#include "xenia/ui/vulkan/functions/device_1_0.inc" -#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" - if (HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) { -#include "xenia/ui/vulkan/functions/device_amd_shader_info.inc" - } - debug_marker_ena_ = HasEnabledExtension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); - if (debug_marker_ena_) { -#include "xenia/ui/vulkan/functions/device_ext_debug_marker.inc" - } -#undef XE_UI_VULKAN_FUNCTION - if (!device_functions_loaded) { - XELOGE("Failed to get Vulkan device function pointers"); - return false; - } - - device_info_ = std::move(device_info); - queue_family_index_ = ideal_queue_family_index; - - // Get the primary queue used for most submissions/etc. - dfn_.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; - } - - dfn_.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, - const std::string& name) const { - if (!debug_marker_ena_) { - // 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(); - dfn_.vkDebugMarkerSetObjectNameEXT(*this, &info); -} - -void VulkanDevice::DbgMarkerBegin(VkCommandBuffer command_buffer, - std::string name, float r, float g, float b, - float a) const { - if (!debug_marker_ena_) { - // 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; - dfn_.vkCmdDebugMarkerBeginEXT(command_buffer, &info); -} - -void VulkanDevice::DbgMarkerEnd(VkCommandBuffer command_buffer) const { - if (!debug_marker_ena_) { - // Extension disabled. - return; - } - - dfn_.vkCmdDebugMarkerEndEXT(command_buffer); -} - -void VulkanDevice::DbgMarkerInsert(VkCommandBuffer command_buffer, - std::string name, float r, float g, float b, - float a) const { - if (!debug_marker_ena_) { - // 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; - dfn_.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) const { - // 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 = dfn_.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 30af10040..000000000 --- a/src/xenia/ui/vulkan/vulkan_device.h +++ /dev/null @@ -1,145 +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(); - - VulkanInstance* instance() const { return instance_; } - - VkDevice handle = nullptr; - - operator VkDevice() const { return handle; } - operator VkPhysicalDevice() const { return device_info_.handle; } - - struct DeviceFunctions { -#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; -#include "xenia/ui/vulkan/functions/device_1_0.inc" -#include "xenia/ui/vulkan/functions/device_amd_shader_info.inc" -#include "xenia/ui/vulkan/functions/device_ext_debug_marker.inc" -#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" -#undef XE_UI_VULKAN_FUNCTION - }; - const DeviceFunctions& dfn() const { return dfn_; } - - // 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, - const std::string& name) const; - - void DbgMarkerBegin(VkCommandBuffer command_buffer, std::string name, - float r = 0.0f, float g = 0.0f, float b = 0.0f, - float a = 0.0f) const; - void DbgMarkerEnd(VkCommandBuffer command_buffer) const; - - void DbgMarkerInsert(VkCommandBuffer command_buffer, std::string name, - float r = 0.0f, float g = 0.0f, float b = 0.0f, - float a = 0.0f) const; - - // 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) const; - - private: - VulkanInstance* instance_ = nullptr; - - std::vector required_layers_; - std::vector required_extensions_; - std::vector enabled_extensions_; - - DeviceFunctions dfn_ = {}; - - 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 6d95143ba..7d2753a28 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc @@ -2,920 +2,1065 @@ ****************************************************************************** * 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 +#include +#include +#include + #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" +#include "xenia/ui/vulkan/vulkan_presenter.h" +#include "xenia/ui/vulkan/vulkan_util.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" +// Generated with `xb buildshaders`. +#include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h" -constexpr uint32_t kCircularBufferCapacity = 2 * 1024 * 1024; - -class LightweightCircularBuffer { - public: - LightweightCircularBuffer(const VulkanDevice* device) : device_(*device) { - buffer_capacity_ = xe::round_up(kCircularBufferCapacity, 4096); - - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - - // 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 = dfn.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 = dfn.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; - dfn.vkGetBufferMemoryRequirements(device_, index_buffer_, - &buffer_requirements); - buffer_memory_ = device->AllocateMemory( - buffer_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - dfn.vkBindBufferMemory(*device, index_buffer_, buffer_memory_, 0); - dfn.vkBindBufferMemory(*device, vertex_buffer_, buffer_memory_, 0); - - // Persistent mapping. - status = dfn.vkMapMemory(device_, buffer_memory_, 0, VK_WHOLE_SIZE, 0, - &buffer_data_); - CheckResult(status, "vkMapMemory"); +VulkanImmediateDrawer::VulkanImmediateTexture::~VulkanImmediateTexture() { + if (immediate_drawer_) { + immediate_drawer_->OnImmediateTextureDestroyed(*this); } - - ~LightweightCircularBuffer() { - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - - if (buffer_memory_) { - dfn.vkUnmapMemory(device_, buffer_memory_); - buffer_memory_ = nullptr; - } - - DestroyAndNullHandle(dfn.vkDestroyBuffer, device_, index_buffer_); - DestroyAndNullHandle(dfn.vkDestroyBuffer, device_, vertex_buffer_); - DestroyAndNullHandle(dfn.vkFreeMemory, device_, buffer_memory_); - } - - 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. - const VulkanDevice::DeviceFunctions& dfn = device_.dfn(); - 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; - dfn.vkFlushMappedMemoryRanges(device_, 1, &dirty_range); - return offset; - } - - private: - const VulkanDevice& device_; - - 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) { - image_view_ = image_view; - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = dfn.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; - dfn.vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); - - return VK_SUCCESS; - } - - VkResult Initialize(VkDescriptorSetLayout descriptor_set_layout) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = dfn.vkCreateImage(*device_, &image_info, nullptr, &image_); - CheckResult(status, "vkCreateImage"); - if (status != VK_SUCCESS) { - return status; - } - - // Allocate memory for the image. - VkMemoryRequirements memory_requirements; - dfn.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 = dfn.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 = dfn.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 = dfn.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; - dfn.vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); - - return VK_SUCCESS; - } - - void Shutdown() { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - if (descriptor_set_) { - dfn.vkFreeDescriptorSets(*device_, descriptor_pool_, 1, &descriptor_set_); - descriptor_set_ = nullptr; - } - - DestroyAndNullHandle(dfn.vkDestroyImageView, *device_, image_view_); - DestroyAndNullHandle(dfn.vkDestroyImage, *device_, image_); - DestroyAndNullHandle(dfn.vkFreeMemory, *device_, device_memory_); - } - - VkResult Upload(const uint8_t* src_data) { - // TODO(benvanik): assert not in use? textures aren't dynamic right now. - - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - // Get device image layout. - VkImageSubresource subresource; - subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource.mipLevel = 0; - subresource.arrayLayer = 0; - VkSubresourceLayout layout; - dfn.vkGetImageSubresourceLayout(*device_, image_, &subresource, &layout); - - // Map memory for upload. - uint8_t* gpu_data = nullptr; - auto status = dfn.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); - - dfn.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) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - 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; - - dfn.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: - 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() { - const VulkanDevice* device = context_->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - - // 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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.vkCreateGraphicsPipelines(*device, nullptr, 1, &pipeline_info, - nullptr, &line_pipeline_); - CheckResult(status, "vkCreateGraphicsPipelines"); - } - - DestroyAndNullHandle(dfn.vkDestroyShaderModule, *device, vertex_shader); - DestroyAndNullHandle(dfn.vkDestroyShaderModule, *device, fragment_shader); - - // Allocate the buffer we'll use for our vertex and index data. - circular_buffer_ = std::make_unique(device); - - return status; } -void VulkanImmediateDrawer::Shutdown() { - const VulkanDevice* device = context_->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); +VulkanImmediateDrawer::~VulkanImmediateDrawer() { + // Await GPU usage completion of all draws and texture uploads (which happen + // before draws). + auto vulkan_presenter = static_cast(presenter()); + if (vulkan_presenter) { + vulkan_presenter->AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + } - circular_buffer_.reset(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); - DestroyAndNullHandle(dfn.vkDestroyPipeline, *device, line_pipeline_); - DestroyAndNullHandle(dfn.vkDestroyPipeline, *device, triangle_pipeline_); - DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, *device, pipeline_layout_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_); - DestroyAndNullHandle(dfn.vkDestroyDescriptorPool, *device, descriptor_pool_); - DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, *device, - texture_set_layout_); + util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + pipeline_layout_); - DestroyAndNullHandle(dfn.vkDestroySampler, *device, samplers_.nearest_clamp); - DestroyAndNullHandle(dfn.vkDestroySampler, *device, samplers_.nearest_repeat); - DestroyAndNullHandle(dfn.vkDestroySampler, *device, samplers_.linear_clamp); - DestroyAndNullHandle(dfn.vkDestroySampler, *device, samplers_.linear_repeat); + for (auto& deleted_texture : textures_deleted_) { + DestroyTextureResource(deleted_texture.first); + } + for (SubmittedTextureUploadBuffer& submitted_texture_upload_buffer : + texture_upload_buffers_submitted_) { + dfn.vkDestroyBuffer(device, submitted_texture_upload_buffer.buffer, + nullptr); + dfn.vkFreeMemory(device, submitted_texture_upload_buffer.buffer_memory, + nullptr); + } + for (PendingTextureUpload& pending_texture_upload : + texture_uploads_pending_) { + dfn.vkDestroyBuffer(device, pending_texture_upload.buffer, nullptr); + dfn.vkFreeMemory(device, pending_texture_upload.buffer_memory, nullptr); + } + for (VulkanImmediateTexture* texture : textures_) { + if (texture->immediate_drawer_ != this) { + continue; + } + texture->immediate_drawer_ = nullptr; + DestroyTextureResource(texture->resource_); + } + if (white_texture_.image != VK_NULL_HANDLE) { + DestroyTextureResource(white_texture_); + } + + for (TextureDescriptorPool* pool : texture_descriptor_pools_) { + dfn.vkDestroyDescriptorPool(device, pool->pool, nullptr); + delete pool; + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, + texture_descriptor_set_layout_); +} + +bool VulkanImmediateDrawer::Initialize() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkDescriptorSetLayoutBinding texture_descriptor_set_layout_binding; + texture_descriptor_set_layout_binding.binding = 0; + texture_descriptor_set_layout_binding.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + texture_descriptor_set_layout_binding.descriptorCount = 1; + texture_descriptor_set_layout_binding.stageFlags = + VK_SHADER_STAGE_FRAGMENT_BIT; + texture_descriptor_set_layout_binding.pImmutableSamplers = nullptr; + VkDescriptorSetLayoutCreateInfo texture_descriptor_set_layout_create_info; + texture_descriptor_set_layout_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + texture_descriptor_set_layout_create_info.pNext = nullptr; + texture_descriptor_set_layout_create_info.flags = 0; + texture_descriptor_set_layout_create_info.bindingCount = 1; + texture_descriptor_set_layout_create_info.pBindings = + &texture_descriptor_set_layout_binding; + if (dfn.vkCreateDescriptorSetLayout( + device, &texture_descriptor_set_layout_create_info, nullptr, + &texture_descriptor_set_layout_) != VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to create the combined image sampler " + "descriptor set layout"); + return false; + } + + // Create the (1, 1, 1, 1) texture as a replacement when drawing without a + // real texture. + size_t white_texture_pending_upload_index; + if (!CreateTextureResource(1, 1, ImmediateTextureFilter::kNearest, false, + nullptr, white_texture_, + white_texture_pending_upload_index)) { + XELOGE("VulkanImmediateDrawer: Failed to create a blank texture"); + return false; + } + + vertex_buffer_pool_ = std::make_unique( + provider_, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + + VkPushConstantRange push_constant_ranges[1]; + push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constant_ranges[0].offset = offsetof(PushConstants, vertex); + push_constant_ranges[0].size = sizeof(PushConstants::Vertex); + VkPipelineLayoutCreateInfo pipeline_layout_create_info; + pipeline_layout_create_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_create_info.pNext = nullptr; + pipeline_layout_create_info.flags = 0; + pipeline_layout_create_info.setLayoutCount = 1; + pipeline_layout_create_info.pSetLayouts = &texture_descriptor_set_layout_; + pipeline_layout_create_info.pushConstantRangeCount = + uint32_t(xe::countof(push_constant_ranges)); + pipeline_layout_create_info.pPushConstantRanges = push_constant_ranges; + if (dfn.vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, + &pipeline_layout_) != VK_SUCCESS) { + XELOGE("VulkanImmediateDrawer: Failed to create the pipeline layout"); + return false; + } + + // Reset the current state. + batch_open_ = false; + + return true; } 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; + uint32_t width, uint32_t height, ImmediateTextureFilter filter, + bool is_repeated, const uint8_t* data) { + assert_not_null(data); + auto texture = std::make_unique(width, height); + size_t pending_upload_index; + if (CreateTextureResource(width, height, filter, is_repeated, data, + texture->resource_, pending_upload_index)) { + // Manage by this immediate drawer. + texture->immediate_drawer_ = this; + texture->immediate_drawer_index_ = textures_.size(); + textures_.push_back(texture.get()); + texture->pending_upload_index_ = pending_upload_index; + texture_uploads_pending_[texture->pending_upload_index_].texture = + texture.get(); } - - if (data) { - texture->Upload(data); - } - return std::unique_ptr(texture.release()); + return std::move(texture); } -std::unique_ptr VulkanImmediateDrawer::WrapTexture( - VkImageView image_view, VkSampler sampler, uint32_t width, - uint32_t height) { - VkResult status; +void VulkanImmediateDrawer::Begin(UIDrawContext& ui_draw_context, + float coordinate_space_width, + float coordinate_space_height) { + ImmediateDrawer::Begin(ui_draw_context, coordinate_space_width, + coordinate_space_height); - 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; + assert_false(batch_open_); + + const VulkanUIDrawContext& vulkan_ui_draw_context = + static_cast(ui_draw_context); + + // Update the submission index to be used throughout the current immediate + // drawer paint. + last_paint_submission_index_ = + vulkan_ui_draw_context.submission_index_current(); + last_completed_submission_index_ = + vulkan_ui_draw_context.submission_index_completed(); + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + // Destroy deleted textures. + for (auto it = textures_deleted_.begin(); it != textures_deleted_.end();) { + if (it->second > last_completed_submission_index_) { + ++it; + continue; + } + DestroyTextureResource(it->first); + if (std::next(it) != textures_deleted_.end()) { + *it = textures_deleted_.back(); + } + textures_deleted_.pop_back(); } - return texture; -} + // Release upload buffers for completed texture uploads. + auto erase_texture_uploads_end = texture_upload_buffers_submitted_.begin(); + while (erase_texture_uploads_end != texture_upload_buffers_submitted_.end()) { + if (erase_texture_uploads_end->submission_index > + last_completed_submission_index_) { + break; + } + dfn.vkDestroyBuffer(device, erase_texture_uploads_end->buffer, nullptr); + dfn.vkFreeMemory(device, erase_texture_uploads_end->buffer_memory, nullptr); + ++erase_texture_uploads_end; + } + texture_upload_buffers_submitted_.erase( + texture_upload_buffers_submitted_.begin(), erase_texture_uploads_end); -void VulkanImmediateDrawer::Begin(int render_target_width, - int render_target_height) { - const VulkanDevice* device = context_->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); - 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; + vertex_buffer_pool_->Reclaim(last_completed_submission_index_); + + // Begin drawing. + + // Update the framebuffer attachment format in the pipelines - may await + // submission completion if changing. + if (!EnsurePipelinesCreatedForCurrentRenderPass()) { + // Failed to create the pipelines - don't draw anything. + return; + } + + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); - // 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.width = float(vulkan_ui_draw_context.render_target_width()); + viewport.height = float(vulkan_ui_draw_context.render_target_height()); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - dfn.vkCmdSetViewport(current_cmd_buffer_, 0, 1, &viewport); + dfn.vkCmdSetViewport(draw_command_buffer, 0, 1, &viewport); + PushConstants::Vertex push_constants_vertex; + push_constants_vertex.coordinate_space_size_inv[0] = + 1.0f / coordinate_space_width; + push_constants_vertex.coordinate_space_size_inv[1] = + 1.0f / coordinate_space_height; + dfn.vkCmdPushConstants(draw_command_buffer, pipeline_layout_, + VK_SHADER_STAGE_VERTEX_BIT, + offsetof(PushConstants, vertex), + sizeof(PushConstants::Vertex), &push_constants_vertex); + current_scissor_.offset.x = 0; + current_scissor_.offset.y = 0; + current_scissor_.extent.width = 0; + current_scissor_.extent.height = 0; - // 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}, - }; - dfn.vkCmdPushConstants(current_cmd_buffer_, pipeline_layout_, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 16, - ortho_projection); + current_pipeline_ = VK_NULL_HANDLE; + current_texture_descriptor_index_ = UINT32_MAX; } void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { - const VulkanDevice* device = context_->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); + assert_false(batch_open_); - // Upload vertices. - VkDeviceSize vertices_offset = circular_buffer_->Emplace( - batch.vertices, batch.vertex_count * sizeof(ImmediateVertex)); - if (vertices_offset == VK_WHOLE_SIZE) { - // TODO(benvanik): die? + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + + // Bind the vertices. + size_t vertex_buffer_size = sizeof(ImmediateVertex) * batch.vertex_count; + VkBuffer vertex_buffer; + VkDeviceSize vertex_buffer_offset; + void* vertex_buffer_mapping = vertex_buffer_pool_->Request( + last_paint_submission_index_, vertex_buffer_size, sizeof(float), + vertex_buffer, vertex_buffer_offset); + if (!vertex_buffer_mapping) { + XELOGE("VulkanImmediateDrawer: Failed to get a buffer for {} vertices", + batch.vertex_count); return; } - auto vertex_buffer = circular_buffer_->vertex_buffer(); - dfn.vkCmdBindVertexBuffers(current_cmd_buffer_, 0, 1, &vertex_buffer, - &vertices_offset); + std::memcpy(vertex_buffer_mapping, batch.vertices, vertex_buffer_size); + dfn.vkCmdBindVertexBuffers(draw_command_buffer, 0, 1, &vertex_buffer, + &vertex_buffer_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? + // Bind the indices. + batch_has_index_buffer_ = batch.indices != nullptr; + if (batch_has_index_buffer_) { + size_t index_buffer_size = sizeof(uint16_t) * batch.index_count; + VkBuffer index_buffer; + VkDeviceSize index_buffer_offset; + void* index_buffer_mapping = vertex_buffer_pool_->Request( + last_paint_submission_index_, index_buffer_size, sizeof(uint16_t), + index_buffer, index_buffer_offset); + if (!index_buffer_mapping) { + XELOGE("VulkanImmediateDrawer: Failed to get a buffer for {} indices", + batch.index_count); return; } - dfn.vkCmdBindIndexBuffer(current_cmd_buffer_, - circular_buffer_->index_buffer(), indices_offset, - VK_INDEX_TYPE_UINT16); + std::memcpy(index_buffer_mapping, batch.indices, index_buffer_size); + dfn.vkCmdBindIndexBuffer(draw_command_buffer, index_buffer, + index_buffer_offset, VK_INDEX_TYPE_UINT16); } - batch_has_index_buffer_ = !!batch.indices; + batch_open_ = true; } void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { - const VulkanDevice* device = context_->device(); - const VulkanDevice::DeviceFunctions& dfn = device->dfn(); + if (!batch_open_) { + // Could have been an error while obtaining the vertex and index buffers, + // for instance. + return; + } + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkCommandBuffer draw_command_buffer = + vulkan_ui_draw_context.draw_command_buffer(); + + // Get the pipeline for the current primitive type. + VkPipeline pipeline; switch (draw.primitive_type) { case ImmediatePrimitiveType::kLines: - dfn.vkCmdBindPipeline(current_cmd_buffer_, - VK_PIPELINE_BIND_POINT_GRAPHICS, line_pipeline_); + pipeline = pipeline_line_; break; case ImmediatePrimitiveType::kTriangles: - dfn.vkCmdBindPipeline(current_cmd_buffer_, - VK_PIPELINE_BIND_POINT_GRAPHICS, - triangle_pipeline_); + pipeline = pipeline_triangle_; break; + default: + assert_unhandled_case(draw.primitive_type); + return; + } + if (pipeline == VK_NULL_HANDLE) { + // Failed to create the pipeline. + return; } - // Setup texture binding. - auto texture = static_cast(draw.texture); - 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!"); - } - - dfn.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 (was used before September 26, - // 2020, now deleted). - int restrict_texture_samples = 0; - dfn.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. + // Set the scissor rectangle if enabled. 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_; + uint32_t scissor_left, scissor_top; + if (!ScissorToRenderTarget(draw, scissor_left, scissor_top, + scissor.extent.width, scissor.extent.height)) { + // Nothing is visible (zero area is used as the default current_scissor_ + // value also). + return; + } + scissor.offset.x = int32_t(scissor_left); + scissor.offset.y = int32_t(scissor_top); + if (current_scissor_.offset.x != scissor.offset.x || + current_scissor_.offset.y != scissor.offset.y || + current_scissor_.extent.width != scissor.extent.width || + current_scissor_.extent.height != scissor.extent.height) { + current_scissor_ = scissor; + dfn.vkCmdSetScissor(draw_command_buffer, 0, 1, &scissor); } - dfn.vkCmdSetScissor(current_cmd_buffer_, 0, 1, &scissor); - // Issue draw. + // Bind the pipeline for the primitive type if the scissor is not empty. + if (current_pipeline_ != pipeline) { + current_pipeline_ = pipeline; + dfn.vkCmdBindPipeline(draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline); + } + + // Bind the texture. + uint32_t texture_descriptor_index; + VulkanImmediateTexture* texture = + static_cast(draw.texture); + if (texture && texture->immediate_drawer_ == this) { + texture_descriptor_index = texture->resource_.descriptor_index; + texture->last_usage_submission_ = last_paint_submission_index_; + } else { + texture_descriptor_index = white_texture_.descriptor_index; + } + if (current_texture_descriptor_index_ != texture_descriptor_index) { + current_texture_descriptor_index_ = texture_descriptor_index; + VkDescriptorSet texture_descriptor_set = + GetTextureDescriptor(texture_descriptor_index); + dfn.vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, + 0, 1, &texture_descriptor_set, 0, nullptr); + } + + // Draw. if (batch_has_index_buffer_) { - dfn.vkCmdDrawIndexed(current_cmd_buffer_, draw.count, 1, draw.index_offset, + dfn.vkCmdDrawIndexed(draw_command_buffer, draw.count, 1, draw.index_offset, draw.base_vertex, 0); } else { - dfn.vkCmdDraw(current_cmd_buffer_, draw.count, 1, draw.base_vertex, 0); + dfn.vkCmdDraw(draw_command_buffer, draw.count, 1, draw.base_vertex, 0); } } -void VulkanImmediateDrawer::EndDrawBatch() {} +void VulkanImmediateDrawer::EndDrawBatch() { batch_open_ = false; } -void VulkanImmediateDrawer::End() { current_cmd_buffer_ = nullptr; } +void VulkanImmediateDrawer::End() { + assert_false(batch_open_); -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; + // Upload textures. + if (!texture_uploads_pending_.empty()) { + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); + VkCommandBuffer setup_command_buffer = + vulkan_presenter.AcquireUISetupCommandBufferFromUIThread(); + if (setup_command_buffer != VK_NULL_HANDLE) { + size_t texture_uploads_pending_count = texture_uploads_pending_.size(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + + // Transition to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. + std::vector image_memory_barriers; + image_memory_barriers.reserve(texture_uploads_pending_count); + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + util::InitializeSubresourceRange(image_memory_barrier.subresourceRange); + for (const PendingTextureUpload& pending_texture_upload : + texture_uploads_pending_) { + image_memory_barriers.emplace_back(image_memory_barrier).image = + pending_texture_upload.image; + } + dfn.vkCmdPipelineBarrier( + setup_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, + uint32_t(image_memory_barriers.size()), image_memory_barriers.data()); + + // Do transfer operations and transition to + // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, and also mark as used. + for (size_t i = 0; i < texture_uploads_pending_count; ++i) { + const PendingTextureUpload& pending_texture_upload = + texture_uploads_pending_[i]; + if (pending_texture_upload.buffer != VK_NULL_HANDLE) { + // Copying. + VkBufferImageCopy copy_region; + copy_region.bufferOffset = 0; + copy_region.bufferRowLength = pending_texture_upload.width; + copy_region.bufferImageHeight = pending_texture_upload.height; + copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_region.imageSubresource.mipLevel = 0; + copy_region.imageSubresource.baseArrayLayer = 0; + copy_region.imageSubresource.layerCount = 1; + copy_region.imageOffset.x = 0; + copy_region.imageOffset.y = 0; + copy_region.imageOffset.z = 0; + copy_region.imageExtent.width = pending_texture_upload.width; + copy_region.imageExtent.height = pending_texture_upload.height; + copy_region.imageExtent.depth = 1; + dfn.vkCmdCopyBufferToImage( + setup_command_buffer, pending_texture_upload.buffer, + pending_texture_upload.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); + + SubmittedTextureUploadBuffer& submitted_texture_upload_buffer = + texture_upload_buffers_submitted_.emplace_back(); + submitted_texture_upload_buffer.buffer = + pending_texture_upload.buffer; + submitted_texture_upload_buffer.buffer_memory = + pending_texture_upload.buffer_memory; + submitted_texture_upload_buffer.submission_index = + last_paint_submission_index_; + } else { + // Clearing (initializing the special empty image). + VkClearColorValue white_clear_value; + white_clear_value.float32[0] = 1.0f; + white_clear_value.float32[1] = 1.0f; + white_clear_value.float32[2] = 1.0f; + white_clear_value.float32[3] = 1.0f; + dfn.vkCmdClearColorImage( + setup_command_buffer, pending_texture_upload.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &white_clear_value, 1, + &image_memory_barrier.subresourceRange); + } + + VkImageMemoryBarrier& image_memory_barrier_current = + image_memory_barriers[i]; + image_memory_barrier_current.srcAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier_current.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier_current.oldLayout = + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + image_memory_barrier_current.newLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + if (pending_texture_upload.texture) { + pending_texture_upload.texture->last_usage_submission_ = + last_paint_submission_index_; + pending_texture_upload.texture->pending_upload_index_ = SIZE_MAX; + } + } + dfn.vkCmdPipelineBarrier( + setup_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, + uint32_t(image_memory_barriers.size()), image_memory_barriers.data()); + + texture_uploads_pending_.clear(); + } } - return sampler; + vertex_buffer_pool_->FlushWrites(); + + ImmediateDrawer::End(); +} + +void VulkanImmediateDrawer::OnLeavePresenter() { + // Leaving the presenter's submission timeline - await GPU usage completion of + // all draws and texture uploads (which happen before draws) and reset + // submission indices. + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); + vulkan_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + + for (VulkanImmediateTexture* texture : textures_) { + texture->last_usage_submission_ = 0; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + for (SubmittedTextureUploadBuffer& submitted_texture_upload_buffer : + texture_upload_buffers_submitted_) { + dfn.vkDestroyBuffer(device, submitted_texture_upload_buffer.buffer, + nullptr); + dfn.vkFreeMemory(device, submitted_texture_upload_buffer.buffer_memory, + nullptr); + } + + vertex_buffer_pool_->ChangeSubmissionTimeline(); + + last_paint_submission_index_ = 0; + last_completed_submission_index_ = 0; +} + +bool VulkanImmediateDrawer::EnsurePipelinesCreatedForCurrentRenderPass() { + const VulkanUIDrawContext& vulkan_ui_draw_context = + *static_cast(ui_draw_context()); + VkFormat render_pass_format = vulkan_ui_draw_context.render_pass_format(); + + if (render_pass_format == pipeline_framebuffer_format_) { + // Either created, or failed to create once (don't try to create every + // frame). + return pipeline_triangle_ != VK_NULL_HANDLE && + pipeline_line_ != VK_NULL_HANDLE; + } + + if (last_paint_submission_index_ && pipeline_triangle_ != VK_NULL_HANDLE && + pipeline_line_ != VK_NULL_HANDLE) { + // Make sure it's safe to delete the pipelines. + VulkanPresenter& vulkan_presenter = + *static_cast(presenter()); + vulkan_presenter.AwaitUISubmissionCompletionFromUIThread( + last_paint_submission_index_); + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + // Safe to destroy the pipelines now - if the render pass was recreated, + // completion of its usage has already been awaited. + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_); + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_); + // If creation fails now, don't try to create every frame. + pipeline_framebuffer_format_ = render_pass_format; + + // Triangle pipeline. + + VkPipelineShaderStageCreateInfo stages[2] = {}; + stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stages[0].module = util::CreateShaderModule(provider_, immediate_vert, + sizeof(immediate_vert)); + if (stages[0].module == VK_NULL_HANDLE) { + XELOGE("VulkanImmediateDrawer: Failed to create the vertex shader module"); + return false; + } + 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 = util::CreateShaderModule(provider_, immediate_frag, + sizeof(immediate_frag)); + if (stages[1].module == VK_NULL_HANDLE) { + XELOGE( + "VulkanImmediateDrawer: Failed to create the fragment shader module"); + dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); + return false; + } + stages[1].pName = "main"; + + VkVertexInputBindingDescription vertex_input_binding; + vertex_input_binding.binding = 0; + vertex_input_binding.stride = sizeof(ImmediateVertex); + vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + VkVertexInputAttributeDescription vertex_input_attributes[3]; + vertex_input_attributes[0].location = 0; + vertex_input_attributes[0].binding = 0; + vertex_input_attributes[0].format = VK_FORMAT_R32G32_SFLOAT; + vertex_input_attributes[0].offset = offsetof(ImmediateVertex, x); + vertex_input_attributes[1].location = 1; + vertex_input_attributes[1].binding = 0; + vertex_input_attributes[1].format = VK_FORMAT_R32G32_SFLOAT; + vertex_input_attributes[1].offset = offsetof(ImmediateVertex, u); + vertex_input_attributes[2].location = 2; + vertex_input_attributes[2].binding = 0; + vertex_input_attributes[2].format = VK_FORMAT_R8G8B8A8_UNORM; + vertex_input_attributes[2].offset = offsetof(ImmediateVertex, color); + VkPipelineVertexInputStateCreateInfo vertex_input_state; + vertex_input_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_state.pNext = nullptr; + vertex_input_state.flags = 0; + vertex_input_state.vertexBindingDescriptionCount = 1; + vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding; + vertex_input_state.vertexAttributeDescriptionCount = + uint32_t(xe::countof(vertex_input_attributes)); + vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state; + input_assembly_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly_state.pNext = nullptr; + input_assembly_state.flags = 0; + input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + input_assembly_state.primitiveRestartEnable = VK_FALSE; + + VkPipelineViewportStateCreateInfo viewport_state; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.pNext = nullptr; + viewport_state.flags = 0; + viewport_state.viewportCount = 1; + viewport_state.pViewports = nullptr; + viewport_state.scissorCount = 1; + viewport_state.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo rasterization_state = {}; + rasterization_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + rasterization_state.cullMode = VK_CULL_MODE_NONE; + rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterization_state.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisample_state = {}; + multisample_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state; + color_blend_attachment_state.blendEnable = VK_TRUE; + color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_blend_attachment_state.dstColorBlendFactor = + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment_state.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo color_blend_state = {}; + color_blend_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blend_state.attachmentCount = 1; + color_blend_state.pAttachments = &color_blend_attachment_state; + + static const VkDynamicState dynamic_states[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + VkPipelineDynamicStateCreateInfo dynamic_state; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.pNext = nullptr; + dynamic_state.flags = 0; + dynamic_state.dynamicStateCount = uint32_t(xe::countof(dynamic_states)); + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo pipeline_create_info; + pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_create_info.pNext = nullptr; + pipeline_create_info.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; + pipeline_create_info.stageCount = uint32_t(xe::countof(stages)); + pipeline_create_info.pStages = stages; + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly_state; + pipeline_create_info.pTessellationState = nullptr; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pRasterizationState = &rasterization_state; + pipeline_create_info.pMultisampleState = &multisample_state; + pipeline_create_info.pDepthStencilState = nullptr; + pipeline_create_info.pColorBlendState = &color_blend_state; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.layout = pipeline_layout_; + pipeline_create_info.renderPass = vulkan_ui_draw_context.render_pass(); + pipeline_create_info.subpass = 0; + pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_create_info.basePipelineIndex = UINT32_MAX; + if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, + &pipeline_create_info, nullptr, + &pipeline_triangle_) != VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to create the triangle list pipeline"); + dfn.vkDestroyShaderModule(device, stages[1].module, nullptr); + dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); + return false; + } + + // Line pipeline. + + input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + pipeline_create_info.flags = + (pipeline_create_info.flags & ~VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT) | + VK_PIPELINE_CREATE_DERIVATIVE_BIT; + pipeline_create_info.basePipelineHandle = pipeline_triangle_; + VkResult pipeline_line_create_result = dfn.vkCreateGraphicsPipelines( + device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, + &pipeline_line_); + dfn.vkDestroyShaderModule(device, stages[1].module, nullptr); + dfn.vkDestroyShaderModule(device, stages[0].module, nullptr); + if (pipeline_line_create_result != VK_SUCCESS) { + XELOGE("VulkanImmediateDrawer: Failed to create the line list pipeline"); + dfn.vkDestroyPipeline(device, pipeline_triangle_, nullptr); + pipeline_triangle_ = VK_NULL_HANDLE; + return false; + } + + return true; +} + +uint32_t VulkanImmediateDrawer::AllocateTextureDescriptor() { + // Try to reuse a recycled descriptor first. + if (texture_descriptor_pool_recycled_first_) { + TextureDescriptorPool* pool = texture_descriptor_pool_recycled_first_; + assert_not_zero(pool->recycled_bits); + uint32_t local_index; + xe::bit_scan_forward(pool->recycled_bits, &local_index); + pool->recycled_bits &= ~(uint64_t(1) << local_index); + if (!pool->recycled_bits) { + texture_descriptor_pool_recycled_first_ = pool->recycled_next; + } + return (pool->index << 6) | local_index; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkDescriptorSetAllocateInfo allocate_info; + allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocate_info.pNext = nullptr; + allocate_info.descriptorSetCount = 1; + allocate_info.pSetLayouts = &texture_descriptor_set_layout_; + + // If no recycled, try to create a new allocation within an existing pool with + // unallocated descriptors left. + while (texture_descriptor_pool_unallocated_first_) { + TextureDescriptorPool* pool = texture_descriptor_pool_unallocated_first_; + assert_not_zero(pool->unallocated_count); + allocate_info.descriptorPool = pool->pool; + uint32_t local_index = + TextureDescriptorPool::kDescriptorCount - pool->unallocated_count; + VkResult allocate_result = dfn.vkAllocateDescriptorSets( + device, &allocate_info, &pool->sets[local_index]); + if (allocate_result == VK_SUCCESS) { + --pool->unallocated_count; + } else { + // Failed to allocate for some reason, don't try again for this pool. + pool->unallocated_count = 0; + } + if (!pool->unallocated_count) { + texture_descriptor_pool_unallocated_first_ = pool->unallocated_next; + } + if (allocate_result == VK_SUCCESS) { + return (pool->index << 6) | local_index; + } + } + + // Create a new pool and allocate the descriptor from it. + VkDescriptorPoolSize descriptor_pool_size; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_pool_size.descriptorCount = + TextureDescriptorPool::kDescriptorCount; + VkDescriptorPoolCreateInfo descriptor_pool_create_info; + descriptor_pool_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = nullptr; + descriptor_pool_create_info.flags = 0; + descriptor_pool_create_info.maxSets = TextureDescriptorPool::kDescriptorCount; + descriptor_pool_create_info.poolSizeCount = 1; + descriptor_pool_create_info.pPoolSizes = &descriptor_pool_size; + VkDescriptorPool descriptor_pool; + if (dfn.vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, + &descriptor_pool) != VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to create a combined image sampler " + "descriptor pool with {} descriptors", + TextureDescriptorPool::kDescriptorCount); + return UINT32_MAX; + } + allocate_info.descriptorPool = descriptor_pool; + VkDescriptorSet descriptor_set; + if (dfn.vkAllocateDescriptorSets(device, &allocate_info, &descriptor_set) != + VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to allocate a combined image sampler " + "descriptor"); + dfn.vkDestroyDescriptorPool(device, descriptor_pool, nullptr); + return UINT32_MAX; + } + TextureDescriptorPool* new_pool = new TextureDescriptorPool; + new_pool->pool = descriptor_pool; + new_pool->sets[0] = descriptor_set; + uint32_t new_pool_index = uint32_t(texture_descriptor_pools_.size()); + new_pool->index = new_pool_index; + new_pool->unallocated_count = TextureDescriptorPool::kDescriptorCount - 1; + new_pool->recycled_bits = 0; + new_pool->unallocated_next = texture_descriptor_pool_unallocated_first_; + texture_descriptor_pool_unallocated_first_ = new_pool; + new_pool->recycled_next = nullptr; + texture_descriptor_pools_.push_back(new_pool); + return new_pool_index << 6; +} + +VkDescriptorSet VulkanImmediateDrawer::GetTextureDescriptor( + uint32_t descriptor_index) const { + uint32_t pool_index = descriptor_index >> 6; + assert_true(pool_index < texture_descriptor_pools_.size()); + const TextureDescriptorPool* pool = texture_descriptor_pools_[pool_index]; + uint32_t allocation_index = descriptor_index & 63; + assert_true(allocation_index < TextureDescriptorPool::kDescriptorCount - + pool->unallocated_count); + return pool->sets[allocation_index]; +} + +void VulkanImmediateDrawer::FreeTextureDescriptor(uint32_t descriptor_index) { + uint32_t pool_index = descriptor_index >> 6; + assert_true(pool_index < texture_descriptor_pools_.size()); + TextureDescriptorPool* pool = texture_descriptor_pools_[pool_index]; + uint32_t allocation_index = descriptor_index & 63; + assert_true(allocation_index < TextureDescriptorPool::kDescriptorCount - + pool->unallocated_count); + assert_zero(pool->recycled_bits & (uint64_t(1) << allocation_index)); + if (!pool->recycled_bits) { + // Add to the free list if not already in it. + pool->recycled_next = texture_descriptor_pool_recycled_first_; + texture_descriptor_pool_recycled_first_ = pool; + } + pool->recycled_bits |= uint64_t(1) << allocation_index; +} + +bool VulkanImmediateDrawer::CreateTextureResource( + uint32_t width, uint32_t height, ImmediateTextureFilter filter, + bool is_repeated, const uint8_t* data, + VulkanImmediateTexture::Resource& resource_out, + size_t& pending_upload_index_out) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + // Create the image and the descriptor. + + VkImageCreateInfo image_create_info; + image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_create_info.pNext = nullptr; + image_create_info.flags = 0; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + image_create_info.extent.width = width; + image_create_info.extent.height = height; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.usage = + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.queueFamilyIndexCount = 0; + image_create_info.pQueueFamilyIndices = nullptr; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImage image; + VkDeviceMemory image_memory; + if (!util::CreateDedicatedAllocationImage(provider_, image_create_info, + util::MemoryPurpose::kDeviceLocal, + image, image_memory)) { + XELOGE( + "VulkanImmediateDrawer: Failed to create an image with dedicated " + "memory for a {}x{} texture", + width, height); + return false; + } + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.image = image; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + // data == nullptr is a special case for (1, 1, 1, 1). + VkComponentSwizzle swizzle = + data ? VK_COMPONENT_SWIZZLE_IDENTITY : VK_COMPONENT_SWIZZLE_ONE; + image_view_create_info.components.r = swizzle; + image_view_create_info.components.g = swizzle; + image_view_create_info.components.b = swizzle; + image_view_create_info.components.a = swizzle; + util::InitializeSubresourceRange(image_view_create_info.subresourceRange); + VkImageView image_view; + if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, + &image_view) != VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to create an image view for a {}x{} " + "image", + width, height); + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, image_memory, nullptr); + return false; + } + + uint32_t descriptor_index = AllocateTextureDescriptor(); + if (descriptor_index == UINT32_MAX) { + XELOGE( + "VulkanImmediateDrawer: Failed to allocate a descriptor for an image"); + dfn.vkDestroyImageView(device, image_view, nullptr); + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, image_memory, nullptr); + return false; + } + VkDescriptorImageInfo descriptor_image_info; + VulkanProvider::HostSampler host_sampler; + if (filter == ImmediateTextureFilter::kLinear) { + host_sampler = is_repeated ? VulkanProvider::HostSampler::kLinearRepeat + : VulkanProvider::HostSampler::kLinearClamp; + } else { + host_sampler = is_repeated ? VulkanProvider::HostSampler::kNearestRepeat + : VulkanProvider::HostSampler::kNearestClamp; + } + descriptor_image_info.sampler = provider_.GetHostSampler(host_sampler); + descriptor_image_info.imageView = image_view; + descriptor_image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet descriptor_write; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_write.pNext = nullptr; + descriptor_write.dstSet = GetTextureDescriptor(descriptor_index); + descriptor_write.dstBinding = 0; + descriptor_write.dstArrayElement = 0; + descriptor_write.descriptorCount = 1; + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_write.pImageInfo = &descriptor_image_info; + descriptor_write.pBufferInfo = nullptr; + descriptor_write.pTexelBufferView = nullptr; + dfn.vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, nullptr); + + // Create and fill the upload buffer. + + // data == nullptr is a special case for (1, 1, 1, 1), clearing rather than + // uploading in this case. + VkBuffer upload_buffer = VK_NULL_HANDLE; + VkDeviceMemory upload_buffer_memory = VK_NULL_HANDLE; + if (data) { + size_t data_size = sizeof(uint32_t) * width * height; + uint32_t upload_buffer_memory_type; + if (!util::CreateDedicatedAllocationBuffer( + provider_, VkDeviceSize(data_size), + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, util::MemoryPurpose::kUpload, + upload_buffer, upload_buffer_memory, &upload_buffer_memory_type)) { + XELOGE( + "VulkanImmediateDrawer: Failed to create an upload buffer for a " + "{}x{} image", + width, height); + FreeTextureDescriptor(descriptor_index); + dfn.vkDestroyImageView(device, image_view, nullptr); + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, image_memory, nullptr); + return false; + } + void* upload_buffer_mapping; + if (dfn.vkMapMemory(device, upload_buffer_memory, 0, VK_WHOLE_SIZE, 0, + &upload_buffer_mapping) != VK_SUCCESS) { + XELOGE( + "VulkanImmediateDrawer: Failed to map upload buffer memory for a " + "{}x{} image", + width, height); + dfn.vkDestroyBuffer(device, upload_buffer, nullptr); + dfn.vkFreeMemory(device, upload_buffer_memory, nullptr); + FreeTextureDescriptor(descriptor_index); + dfn.vkDestroyImageView(device, image_view, nullptr); + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, image_memory, nullptr); + return false; + } + std::memcpy(upload_buffer_mapping, data, data_size); + util::FlushMappedMemoryRange(provider_, upload_buffer_memory, + upload_buffer_memory_type); + dfn.vkUnmapMemory(device, upload_buffer_memory); + } + + resource_out.image = image; + resource_out.memory = image_memory; + resource_out.image_view = image_view; + resource_out.descriptor_index = descriptor_index; + + pending_upload_index_out = texture_uploads_pending_.size(); + PendingTextureUpload& pending_upload = + texture_uploads_pending_.emplace_back(); + // The caller will set the ImmedateTexture pointer if needed. + pending_upload.texture = nullptr; + pending_upload.buffer = upload_buffer; + pending_upload.buffer_memory = upload_buffer_memory; + pending_upload.image = image; + pending_upload.width = width; + pending_upload.height = height; + + return true; +} + +void VulkanImmediateDrawer::DestroyTextureResource( + VulkanImmediateTexture::Resource& resource) { + FreeTextureDescriptor(resource.descriptor_index); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyImageView(device, resource.image_view, nullptr); + dfn.vkDestroyImage(device, resource.image, nullptr); + dfn.vkFreeMemory(device, resource.memory, nullptr); +} + +void VulkanImmediateDrawer::OnImmediateTextureDestroyed( + VulkanImmediateTexture& texture) { + // Remove from the pending uploads. + size_t pending_upload_index = texture.pending_upload_index_; + if (pending_upload_index != SIZE_MAX) { + if (pending_upload_index + 1 < texture_uploads_pending_.size()) { + PendingTextureUpload& pending_upload = + texture_uploads_pending_[pending_upload_index]; + pending_upload = texture_uploads_pending_.back(); + if (pending_upload.texture) { + pending_upload.texture->pending_upload_index_ = pending_upload_index; + } + } + texture_uploads_pending_.pop_back(); + } + + // Remove from the texture list. + VulkanImmediateTexture*& texture_at_index = + textures_[texture.immediate_drawer_index_]; + texture_at_index = textures_.back(); + texture_at_index->immediate_drawer_index_ = texture.immediate_drawer_index_; + textures_.pop_back(); + + // Destroy immediately or queue for destruction if in use. + if (texture.last_usage_submission_ > last_completed_submission_index_) { + textures_deleted_.emplace_back( + std::make_pair(texture.resource_, texture.last_usage_submission_)); + } else { + DestroyTextureResource(texture.resource_); + } } } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.h b/src/xenia/ui/vulkan/vulkan_immediate_drawer.h index 5cc66fd26..ca087e1cb 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,66 +10,166 @@ #ifndef XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_ #define XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_ +#include +#include #include +#include +#include #include "xenia/ui/immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan.h" +#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h" namespace xe { namespace ui { namespace vulkan { -class LightweightCircularBuffer; -class VulkanContext; - class VulkanImmediateDrawer : public ImmediateDrawer { public: - VulkanImmediateDrawer(VulkanContext* graphics_context); - ~VulkanImmediateDrawer() override; + static std::unique_ptr Create( + const VulkanProvider& provider) { + auto immediate_drawer = std::unique_ptr( + new VulkanImmediateDrawer(provider)); + if (!immediate_drawer->Initialize()) { + return nullptr; + } + return std::move(immediate_drawer); + } - VkResult Initialize(); - void Shutdown(); + ~VulkanImmediateDrawer(); std::unique_ptr CreateTexture(uint32_t width, uint32_t height, ImmediateTextureFilter filter, - bool repeat, + bool is_repeated, const uint8_t* data) override; - std::unique_ptr WrapTexture(VkImageView image_view, - VkSampler sampler, - uint32_t width, - uint32_t height); - void Begin(int render_target_width, int render_target_height) override; + void Begin(UIDrawContext& ui_draw_context, float coordinate_space_width, + float coordinate_space_height) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void Draw(const ImmediateDraw& draw) override; void EndDrawBatch() override; void End() override; - VkSampler GetSampler(ImmediateTextureFilter filter, bool repeat); + protected: + void OnLeavePresenter() override; private: - VulkanContext* context_ = nullptr; + struct PushConstants { + struct Vertex { + float coordinate_space_size_inv[2]; + } vertex; + }; - struct { - VkSampler nearest_clamp = nullptr; - VkSampler nearest_repeat = nullptr; - VkSampler linear_clamp = nullptr; - VkSampler linear_repeat = nullptr; - } samplers_; + class VulkanImmediateTexture : public ImmediateTexture { + public: + struct Resource { + VkImage image; + VkDeviceMemory memory; + VkImageView image_view; + uint32_t descriptor_index; + }; - VkDescriptorSetLayout texture_set_layout_ = nullptr; - VkDescriptorPool descriptor_pool_ = nullptr; - VkPipelineLayout pipeline_layout_ = nullptr; - VkPipeline triangle_pipeline_ = nullptr; - VkPipeline line_pipeline_ = nullptr; + VulkanImmediateTexture(uint32_t width, uint32_t height) + : ImmediateTexture(width, height), immediate_drawer_(nullptr) {} + ~VulkanImmediateTexture() override; - std::unique_ptr circular_buffer_; + // If null, this is either a blank texture, or the immediate drawer has been + // destroyed. + VulkanImmediateDrawer* immediate_drawer_; + size_t immediate_drawer_index_; + // Invalid if immediate_drawer_ is null, since it's managed by the immediate + // drawer. + Resource resource_; + size_t pending_upload_index_; + uint64_t last_usage_submission_ = 0; + }; - bool batch_has_index_buffer_ = false; - VkCommandBuffer current_cmd_buffer_ = nullptr; - int current_render_target_width_ = 0; - int current_render_target_height_ = 0; + struct TextureDescriptorPool { + // Using uint64_t for recycled bits. + static constexpr uint32_t kDescriptorCount = 64; + VkDescriptorPool pool; + VkDescriptorSet sets[kDescriptorCount]; + uint32_t index; + uint32_t unallocated_count; + uint64_t recycled_bits; + TextureDescriptorPool* unallocated_next; + TextureDescriptorPool* recycled_next; + }; + + VulkanImmediateDrawer(const VulkanProvider& provider) : provider_(provider) {} + bool Initialize(); + + bool EnsurePipelinesCreatedForCurrentRenderPass(); + + // Allocates a combined image sampler in a pool and returns its index, or + // UINT32_MAX in case of failure. + uint32_t AllocateTextureDescriptor(); + VkDescriptorSet GetTextureDescriptor(uint32_t descriptor_index) const; + void FreeTextureDescriptor(uint32_t descriptor_index); + + // If data is null, a (1, 1, 1, 1) image will be created, which can be used as + // a replacement when drawing without a real texture. + bool CreateTextureResource(uint32_t width, uint32_t height, + ImmediateTextureFilter filter, bool is_repeated, + const uint8_t* data, + VulkanImmediateTexture::Resource& resource_out, + size_t& pending_upload_index_out); + void DestroyTextureResource(VulkanImmediateTexture::Resource& resource); + void OnImmediateTextureDestroyed(VulkanImmediateTexture& texture); + + const VulkanProvider& provider_; + + // Combined image sampler pools for textures. + VkDescriptorSetLayout texture_descriptor_set_layout_; + std::vector texture_descriptor_pools_; + TextureDescriptorPool* texture_descriptor_pool_unallocated_first_ = nullptr; + TextureDescriptorPool* texture_descriptor_pool_recycled_first_ = nullptr; + + VulkanImmediateTexture::Resource white_texture_ = {}; + std::vector textures_; + struct PendingTextureUpload { + // Null for internal resources such as the white texture. + VulkanImmediateTexture* texture; + // VK_NULL_HANDLE if need to clear rather than to copy. + VkBuffer buffer; + VkDeviceMemory buffer_memory; + VkImage image; + uint32_t width; + uint32_t height; + }; + std::vector texture_uploads_pending_; + struct SubmittedTextureUploadBuffer { + VkBuffer buffer; + VkDeviceMemory buffer_memory; + uint64_t submission_index; + }; + std::deque texture_upload_buffers_submitted_; + // Resource and last usage submission pairs. + std::vector> + textures_deleted_; + + std::unique_ptr vertex_buffer_pool_; + + VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; + + VkFormat pipeline_framebuffer_format_ = VK_FORMAT_UNDEFINED; + VkPipeline pipeline_triangle_ = VK_NULL_HANDLE; + VkPipeline pipeline_line_ = VK_NULL_HANDLE; + + // The submission index within the current Begin (or the last, if outside + // one). + uint64_t last_paint_submission_index_ = 0; + // Completed submission index as of the latest Begin, to coarsely skip delayed + // texture deletion. + uint64_t last_completed_submission_index_ = 0; + + VkCommandBuffer current_command_buffer_ = VK_NULL_HANDLE; + VkExtent2D current_render_target_extent_; + VkRect2D current_scissor_; + VkPipeline current_pipeline_; + uint32_t current_texture_descriptor_index_; + bool batch_open_ = false; + bool batch_has_index_buffer_; }; } // 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 0ccbba7fa..000000000 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ /dev/null @@ -1,634 +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 - -#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/platform.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 -#elif XE_PLATFORM_WIN32 -#include "xenia/base/platform_win.h" -#endif - -#if XE_PLATFORM_GNU_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); - - // Load the library. - bool library_functions_loaded = true; -#if XE_PLATFORM_LINUX -#if XE_PLATFORM_ANDROID - const char* libvulkan_name = "libvulkan.so"; -#else - const char* libvulkan_name = "libvulkan.so.1"; -#endif - // http://developer.download.nvidia.com/mobile/shield/assets/Vulkan/UsingtheVulkanAPI.pdf - library_ = dlopen(libvulkan_name, RTLD_NOW | RTLD_LOCAL); - if (!library_) { - XELOGE("Failed to load {}", libvulkan_name); - return false; - } -#define XE_VULKAN_LOAD_MODULE_LFN(name) \ - library_functions_loaded &= \ - (lfn_.name = PFN_##name(dlsym(library_, #name))) != nullptr; -#elif XE_PLATFORM_WIN32 - library_ = LoadLibraryA("vulkan-1.dll"); - if (!library_) { - XELOGE("Failed to load vulkan-1.dll"); - return false; - } -#define XE_VULKAN_LOAD_MODULE_LFN(name) \ - library_functions_loaded &= \ - (lfn_.name = PFN_##name(GetProcAddress(library_, #name))) != nullptr; -#else -#error No Vulkan library loading provided for the target platform. -#endif - XE_VULKAN_LOAD_MODULE_LFN(vkGetInstanceProcAddr); - XE_VULKAN_LOAD_MODULE_LFN(vkDestroyInstance); -#undef XE_VULKAN_LOAD_MODULE_LFN - if (!library_functions_loaded) { - XELOGE("Failed to get Vulkan library function pointers"); - return false; - } - library_functions_loaded &= - (lfn_.vkCreateInstance = PFN_vkCreateInstance(lfn_.vkGetInstanceProcAddr( - VK_NULL_HANDLE, "vkCreateInstance"))) != nullptr; - library_functions_loaded &= - (lfn_.vkEnumerateInstanceExtensionProperties = - PFN_vkEnumerateInstanceExtensionProperties( - lfn_.vkGetInstanceProcAddr( - VK_NULL_HANDLE, - "vkEnumerateInstanceExtensionProperties"))) != nullptr; - library_functions_loaded &= - (lfn_.vkEnumerateInstanceLayerProperties = - PFN_vkEnumerateInstanceLayerProperties(lfn_.vkGetInstanceProcAddr( - VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"))) != - nullptr; - if (!library_functions_loaded) { - XELOGE( - "Failed to get Vulkan library function pointers via " - "vkGetInstanceProcAddr"); - 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 = lfn_.vkEnumerateInstanceLayerProperties(&count, nullptr); - CheckResult(err, "vkEnumerateInstanceLayerProperties"); - global_layer_properties.resize(count); - err = lfn_.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 = lfn_.vkEnumerateInstanceExtensionProperties( - global_layer.properties.layerName, &count, nullptr); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - global_layer.extensions.resize(count); - err = lfn_.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 = lfn_.vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - global_extensions_.resize(count); - err = lfn_.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 = lfn_.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; - } - - // Check if extensions are enabled. - dbg_report_ena_ = false; - for (const char* enabled_extension : enabled_extensions) { - if (!dbg_report_ena_ && - !std::strcmp(enabled_extension, VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) { - dbg_report_ena_ = true; - } - } - - // Get instance functions. - std::memset(&ifn_, 0, sizeof(ifn_)); - bool instance_functions_loaded = true; -#define XE_UI_VULKAN_FUNCTION(name) \ - instance_functions_loaded &= \ - (ifn_.name = PFN_##name(lfn_.vkGetInstanceProcAddr(handle, #name))) != \ - nullptr; -#include "xenia/ui/vulkan/functions/instance_1_0.inc" -#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" -#if XE_PLATFORM_ANDROID -#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" -#elif XE_PLATFORM_GNU_LINUX -#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" -#elif XE_PLATFORM_WIN32 -#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" -#endif - if (dbg_report_ena_) { -#include "xenia/ui/vulkan/functions/instance_ext_debug_report.inc" - } -#undef XE_VULKAN_LOAD_IFN - if (!instance_functions_loaded) { - XELOGE("Failed to get Vulkan instance function pointers"); - return false; - } - - // Enable debug validation, if needed. - EnableDebugValidation(); - - return true; -} - -void VulkanInstance::DestroyInstance() { - if (handle) { - DisableDebugValidation(); - lfn_.vkDestroyInstance(handle, nullptr); - handle = nullptr; - } - -#if XE_PLATFORM_LINUX - if (library_) { - dlclose(library_); - library_ = nullptr; - } -#elif XE_PLATFORM_WIN32 - if (library_) { - FreeLibrary(library_); - library_ = nullptr; - } -#endif -} - -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_ena_) { - XELOGVK("Debug validation layer not installed; ignoring"); - return; - } - if (dbg_report_callback_) { - DisableDebugValidation(); - } - 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 = ifn_.vkCreateDebugReportCallbackEXT( - 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_ena_ || !dbg_report_callback_) { - return; - } - ifn_.vkDestroyDebugReportCallbackEXT(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 = ifn_.vkEnumeratePhysicalDevices(handle, &count, nullptr); - CheckResult(err, "vkEnumeratePhysicalDevices"); - - device_handles.resize(count); - err = ifn_.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. - ifn_.vkGetPhysicalDeviceProperties(device_handle, &device_info.properties); - ifn_.vkGetPhysicalDeviceFeatures(device_handle, &device_info.features); - ifn_.vkGetPhysicalDeviceMemoryProperties(device_handle, - &device_info.memory_properties); - - // Gather queue family properties. - ifn_.vkGetPhysicalDeviceQueueFamilyProperties(device_handle, &count, - nullptr); - device_info.queue_family_properties.resize(count); - ifn_.vkGetPhysicalDeviceQueueFamilyProperties( - device_handle, &count, device_info.queue_family_properties.data()); - - // Gather layers. - std::vector layer_properties; - err = ifn_.vkEnumerateDeviceLayerProperties(device_handle, &count, nullptr); - CheckResult(err, "vkEnumerateDeviceLayerProperties"); - layer_properties.resize(count); - err = ifn_.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 = ifn_.vkEnumerateDeviceExtensionProperties( - device_handle, layer_info.properties.layerName, &count, nullptr); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - layer_info.extensions.resize(count); - err = ifn_.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 = ifn_.vkEnumerateDeviceExtensionProperties(device_handle, nullptr, - &count, nullptr); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - device_info.extensions.resize(count); - err = ifn_.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 52a92f53e..000000000 --- a/src/xenia/ui/vulkan/vulkan_instance.h +++ /dev/null @@ -1,145 +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/base/platform.h" -#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(); - - struct LibraryFunctions { - // From the module. - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; - PFN_vkDestroyInstance vkDestroyInstance; - // From vkGetInstanceProcAddr. - PFN_vkCreateInstance vkCreateInstance; - PFN_vkEnumerateInstanceExtensionProperties - vkEnumerateInstanceExtensionProperties; - PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; - }; - const LibraryFunctions& lfn() const { return lfn_; } - - VkInstance handle = nullptr; - - operator VkInstance() const { return handle; } - - struct InstanceFunctions { -#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; -#include "xenia/ui/vulkan/functions/instance_1_0.inc" -#include "xenia/ui/vulkan/functions/instance_ext_debug_report.inc" -#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" -#if XE_PLATFORM_ANDROID -#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" -#elif XE_PLATFORM_GNU_LINUX -#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" -#elif XE_PLATFORM_WIN32 -#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" -#endif -#undef XE_UI_VULKAN_FUNCTION - }; - const InstanceFunctions& ifn() const { return ifn_; } - - // 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); - -#if XE_PLATFORM_LINUX - void* library_ = nullptr; -#elif XE_PLATFORM_WIN32 - HMODULE library_ = nullptr; -#endif - - LibraryFunctions lfn_ = {}; - - std::vector required_layers_; - std::vector required_extensions_; - - InstanceFunctions ifn_ = {}; - - std::vector global_layers_; - std::vector global_extensions_; - std::vector available_devices_; - - bool dbg_report_ena_ = false; - 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 index 31a9b2c40..133a1f269 100644 --- a/src/xenia/ui/vulkan/vulkan_mem_alloc.h +++ b/src/xenia/ui/vulkan/vulkan_mem_alloc.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,20 +10,32 @@ #ifndef XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ #define XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#include "third_party/vulkan/vk_mem_alloc.h" +// Make sure vulkan.h is included from third_party (rather than from the system +// include directory) before vk_mem_alloc.h. -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_instance.h" +#include "xenia/ui/vulkan/vulkan_provider.h" + +#define VMA_STATIC_VULKAN_FUNCTIONS 0 +// Work around the pointer nullability completeness warnings on Clang. +#ifndef VMA_NULLABLE +#define VMA_NULLABLE +#endif +#ifndef VMA_NOT_NULL +#define VMA_NOT_NULL +#endif +#include "third_party/vulkan/vk_mem_alloc.h" namespace xe { namespace ui { namespace vulkan { inline void FillVMAVulkanFunctions(VmaVulkanFunctions* vma_funcs, - const VulkanDevice& device) { - const VulkanInstance::InstanceFunctions& ifn = device.instance()->ifn(); - const VulkanDevice::DeviceFunctions& dfn = device.dfn(); + const VulkanProvider& provider) { + const VulkanProvider::LibraryFunctions& lfn = provider.lfn(); + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + vma_funcs->vkGetInstanceProcAddr = lfn.vkGetInstanceProcAddr; + vma_funcs->vkGetDeviceProcAddr = ifn.vkGetDeviceProcAddr; vma_funcs->vkGetPhysicalDeviceProperties = ifn.vkGetPhysicalDeviceProperties; vma_funcs->vkGetPhysicalDeviceMemoryProperties = ifn.vkGetPhysicalDeviceMemoryProperties; @@ -31,6 +43,9 @@ inline void FillVMAVulkanFunctions(VmaVulkanFunctions* vma_funcs, vma_funcs->vkFreeMemory = dfn.vkFreeMemory; vma_funcs->vkMapMemory = dfn.vkMapMemory; vma_funcs->vkUnmapMemory = dfn.vkUnmapMemory; + vma_funcs->vkFlushMappedMemoryRanges = dfn.vkFlushMappedMemoryRanges; + vma_funcs->vkInvalidateMappedMemoryRanges = + dfn.vkInvalidateMappedMemoryRanges; vma_funcs->vkBindBufferMemory = dfn.vkBindBufferMemory; vma_funcs->vkBindImageMemory = dfn.vkBindImageMemory; vma_funcs->vkGetBufferMemoryRequirements = dfn.vkGetBufferMemoryRequirements; @@ -39,6 +54,7 @@ inline void FillVMAVulkanFunctions(VmaVulkanFunctions* vma_funcs, vma_funcs->vkDestroyBuffer = dfn.vkDestroyBuffer; vma_funcs->vkCreateImage = dfn.vkCreateImage; vma_funcs->vkDestroyImage = dfn.vkDestroyImage; + vma_funcs->vkCmdCopyBuffer = dfn.vkCmdCopyBuffer; } } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_presenter.cc b/src/xenia/ui/vulkan/vulkan_presenter.cc new file mode 100644 index 000000000..64a665c48 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_presenter.cc @@ -0,0 +1,2548 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/vulkan/vulkan_presenter.h" + +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/base/platform.h" +#include "xenia/ui/vulkan/vulkan_util.h" + +#if XE_PLATFORM_ANDROID +#include "xenia/ui/surface_android.h" +#endif +#if XE_PLATFORM_GNU_LINUX +#include "xenia/ui/surface_gnulinux.h" +#endif +#if XE_PLATFORM_WIN32 +#include "xenia/ui/surface_win.h" +#endif + +// Note: If the priorities in the description are changed, update the actual +// present mode selection logic. +DEFINE_bool( + vulkan_allow_present_mode_immediate, true, + "When available, allow the immediate presentation mode (1st priority), " + "offering the lowest latency with the possibility of tearing in certain " + "cases, and, depending on the configuration, variable refresh rate.", + "Vulkan"); +DEFINE_bool( + vulkan_allow_present_mode_mailbox, true, + "When available, allow the mailbox presentation mode (2nd priority), " + "offering low latency without the possibility of tearing.", + "Vulkan"); +DEFINE_bool( + vulkan_allow_present_mode_fifo_relaxed, true, + "When available, allow the relaxed first-in-first-out presentation mode " + "(3rd priority), which causes waiting for host display vertical sync, but " + "may present with tearing if frames don't meet the host display refresh " + "rate.", + "Vulkan"); + +namespace xe { +namespace ui { +namespace vulkan { + +// Generated with `xb buildshaders`. +namespace shaders { +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_bilinear_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_resample_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_cas_sharpen_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_easu_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_dither_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_ffx_fsr_rcas_frag.h" +#include "xenia/ui/shaders/bytecode/vulkan_spirv/guest_output_triangle_strip_rect_vert.h" +} // namespace shaders + +VulkanPresenter::PaintContext::Submission::~Submission() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + if (draw_command_pool_ != VK_NULL_HANDLE) { + dfn.vkDestroyCommandPool(device, draw_command_pool_, nullptr); + } + + if (present_semaphore_ != VK_NULL_HANDLE) { + dfn.vkDestroySemaphore(device, present_semaphore_, nullptr); + } + if (acquire_semaphore_ != VK_NULL_HANDLE) { + dfn.vkDestroySemaphore(device, acquire_semaphore_, nullptr); + } +} + +bool VulkanPresenter::PaintContext::Submission::Initialize() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkSemaphoreCreateInfo semaphore_create_info; + semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphore_create_info.pNext = nullptr; + semaphore_create_info.flags = 0; + if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, + &acquire_semaphore_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a swapchain image acquisition " + "semaphore"); + return false; + } + if (dfn.vkCreateSemaphore(device, &semaphore_create_info, nullptr, + &present_semaphore_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a swapchain image presentation " + "semaphore"); + return false; + } + + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &draw_command_pool_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a command pool for drawing to a " + "swapchain"); + return false; + } + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = draw_command_pool_; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &draw_command_buffer_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate a command buffer for drawing to a " + "swapchain"); + return false; + } + + return true; +} + +VulkanPresenter::~VulkanPresenter() { + // Destroy the swapchain after its images are not used for drawing anymore. + // This is a confusing part in Vulkan, as vkQueuePresentKHR doesn't signal a + // fence clearly indicating when it's safe to destroy a swapchain, so we + // assume that its lifetime is tracked internally in the WSI. This is also + // done before destroying the semaphore awaited by vkQueuePresentKHR, hoping + // that it will prevent the destruction during the semaphore wait in + // vkQueuePresentKHR execution (or between the vkQueueSubmit semaphore signal + // and the vkQueuePresentKHR semaphore wait). + // This will await completion of all paint submissions also. + paint_context_.DestroySwapchainAndVulkanSurface(); + + // Await completion of the usage of everything before destroying anything + // (paint submission completion already awaited). + // From most likely the latest to most likely the earliest to be signaled, so + // just one sleep will likely be needed. + ui_submission_tracker_.Shutdown(); + guest_output_image_refresher_submission_tracker_.Shutdown(); + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + if (paint_context_.swapchain_render_pass != VK_NULL_HANDLE) { + dfn.vkDestroyRenderPass(device, paint_context_.swapchain_render_pass, + nullptr); + } + + for (const PaintContext::UISetupCommandBuffer& ui_setup_command_buffer : + paint_context_.ui_setup_command_buffers) { + dfn.vkDestroyCommandPool(device, ui_setup_command_buffer.command_pool, + nullptr); + } + + for (VkFramebuffer& framebuffer : + paint_context_.guest_output_intermediate_framebuffers) { + util::DestroyAndNullHandle(dfn.vkDestroyFramebuffer, device, framebuffer); + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorPool, device, + paint_context_.guest_output_descriptor_pool); + for (PaintContext::GuestOutputPaintPipeline& guest_output_paint_pipeline : + paint_context_.guest_output_paint_pipelines) { + util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, + guest_output_paint_pipeline.swapchain_pipeline); + util::DestroyAndNullHandle( + dfn.vkDestroyPipeline, device, + guest_output_paint_pipeline.intermediate_pipeline); + } + + util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, + guest_output_intermediate_render_pass_); + for (VkShaderModule& shader_module : guest_output_paint_fs_) { + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, + shader_module); + } + util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device, + guest_output_paint_vs_); + for (VkPipelineLayout& pipeline_layout : + guest_output_paint_pipeline_layouts_) { + util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device, + pipeline_layout); + } + util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout, device, + guest_output_paint_image_descriptor_set_layout_); +} + +Surface::TypeFlags VulkanPresenter::GetSupportedSurfaceTypes() const { + if (!provider_.device_extensions().khr_swapchain) { + return 0; + } + return GetSurfaceTypesSupportedByInstance(provider_.instance_extensions()); +} + +bool VulkanPresenter::CaptureGuestOutput(RawImage& image_out) { + std::shared_ptr guest_output_image; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, nullptr, nullptr)); + if (guest_output_mailbox_index != UINT32_MAX) { + assert_true(guest_output_images_[guest_output_mailbox_index] + .ever_successfully_refreshed); + guest_output_image = + guest_output_images_[guest_output_mailbox_index].image; + } + // Incremented the reference count of the guest output image - safe to leave + // the consumer critical section now. + } + if (!guest_output_image) { + return false; + } + + VkExtent2D image_extent = guest_output_image->extent(); + size_t pixel_count = size_t(image_extent.width) * image_extent.height; + VkDeviceSize buffer_size = VkDeviceSize(sizeof(uint32_t) * pixel_count); + VkBuffer buffer; + VkDeviceMemory buffer_memory; + if (!util::CreateDedicatedAllocationBuffer( + provider_, buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, + util::MemoryPurpose::kReadback, buffer, buffer_memory)) { + XELOGE("VulkanPresenter: Failed to create the guest output capture buffer"); + return false; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + { + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + VkCommandPool command_pool; + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &command_pool) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output capturing " + "command pool"); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = command_pool; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + VkCommandBuffer command_buffer; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &command_buffer) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate the guest output capturing " + "command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + 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; + if (dfn.vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info) != + VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin recording the guest output " + "capturing command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = kGuestOutputInternalAccessMask; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + image_memory_barrier.oldLayout = kGuestOutputInternalLayout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = guest_output_image->image(); + util::InitializeSubresourceRange(image_memory_barrier.subresourceRange); + dfn.vkCmdPipelineBarrier(command_buffer, kGuestOutputInternalStageMask, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, + nullptr, 1, &image_memory_barrier); + + VkBufferImageCopy buffer_image_copy = {}; + buffer_image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + buffer_image_copy.imageSubresource.layerCount = 1; + buffer_image_copy.imageExtent.width = image_extent.width; + buffer_image_copy.imageExtent.height = image_extent.height; + buffer_image_copy.imageExtent.depth = 1; + dfn.vkCmdCopyImageToBuffer(command_buffer, guest_output_image->image(), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1, + &buffer_image_copy); + + // A fence doesn't guarantee host visibility and availability. + VkBufferMemoryBarrier buffer_memory_barrier; + buffer_memory_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buffer_memory_barrier.pNext = nullptr; + buffer_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + buffer_memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; + buffer_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + buffer_memory_barrier.buffer = buffer; + buffer_memory_barrier.offset = 0; + buffer_memory_barrier.size = VK_WHOLE_SIZE; + std::swap(image_memory_barrier.srcAccessMask, + image_memory_barrier.dstAccessMask); + std::swap(image_memory_barrier.oldLayout, image_memory_barrier.newLayout); + dfn.vkCmdPipelineBarrier( + command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_HOST_BIT | kGuestOutputInternalStageMask, 0, 0, + nullptr, 1, &buffer_memory_barrier, 1, &image_memory_barrier); + + if (dfn.vkEndCommandBuffer(command_buffer) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to end recording the guest output capturing " + "command buffer"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + VulkanSubmissionTracker submission_tracker(provider_); + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + submission_tracker.AcquireFenceToAdvanceSubmission()); + if (!fence_acqusition.fence()) { + XELOGE( + "VulkanPresenter: Failed to acquire a fence for guest output " + "capturing"); + fence_acqusition.SubmissionFailedOrDropped(); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + VkResult submit_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), + 0)); + submit_result = dfn.vkQueueSubmit( + queue_acquisition.queue, 1, &submit_info, fence_acqusition.fence()); + } + if (submit_result != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to submit the guest output capturing " + "command buffer"); + fence_acqusition.SubmissionFailedOrDropped(); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + } + if (!submission_tracker.AwaitAllSubmissionsCompletion()) { + XELOGE( + "VulkanPresenter: Failed to await the guest output capturing fence"); + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + dfn.vkDestroyCommandPool(device, command_pool, nullptr); + } + + // Don't need the buffer anymore, just its memory. + dfn.vkDestroyBuffer(device, buffer, nullptr); + + void* mapping; + if (dfn.vkMapMemory(device, buffer_memory, 0, VK_WHOLE_SIZE, 0, &mapping) != + VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to map the guest output capture memory"); + dfn.vkFreeMemory(device, buffer_memory, nullptr); + return false; + } + + image_out.width = image_extent.width; + image_out.height = image_extent.height; + image_out.stride = sizeof(uint32_t) * image_extent.width; + image_out.data.resize(size_t(buffer_size)); + uint32_t* image_out_pixels = + reinterpret_cast(image_out.data.data()); + for (size_t i = 0; i < pixel_count; ++i) { + image_out_pixels[i] = Packed10bpcRGBTo8bpcBytes( + reinterpret_cast(mapping)[i]); + } + + // Unmapping will be done by freeing. + dfn.vkFreeMemory(device, buffer_memory, nullptr); + + return true; +} + +VkCommandBuffer VulkanPresenter::AcquireUISetupCommandBufferFromUIThread() { + if (paint_context_.ui_setup_command_buffer_current_index != SIZE_MAX) { + return paint_context_ + .ui_setup_command_buffers[paint_context_ + .ui_setup_command_buffer_current_index] + .command_buffer; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + 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; + + // Try to reuse an existing command buffer. + if (!paint_context_.ui_setup_command_buffers.empty()) { + uint64_t submission_index_completed = + ui_submission_tracker_.UpdateAndGetCompletedSubmission(); + for (size_t i = 0; i < paint_context_.ui_setup_command_buffers.size(); + ++i) { + PaintContext::UISetupCommandBuffer& ui_setup_command_buffer = + paint_context_.ui_setup_command_buffers[i]; + if (ui_setup_command_buffer.last_usage_submission_index > + submission_index_completed) { + continue; + } + if (dfn.vkResetCommandPool(device, ui_setup_command_buffer.command_pool, + 0) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to reset a UI setup command pool"); + return VK_NULL_HANDLE; + } + if (dfn.vkBeginCommandBuffer(ui_setup_command_buffer.command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin UI setup command buffer " + "recording"); + return VK_NULL_HANDLE; + } + paint_context_.ui_setup_command_buffer_current_index = i; + ui_setup_command_buffer.last_usage_submission_index = + ui_submission_tracker_.GetCurrentSubmission(); + return ui_setup_command_buffer.command_buffer; + } + } + + // Create a new command buffer. + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_create_info.queueFamilyIndex = + provider_.queue_family_graphics_compute(); + VkCommandPool new_command_pool; + if (dfn.vkCreateCommandPool(device, &command_pool_create_info, nullptr, + &new_command_pool) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a UI setup command pool"); + return VK_NULL_HANDLE; + } + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.commandPool = new_command_pool; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandBufferCount = 1; + VkCommandBuffer new_command_buffer; + if (dfn.vkAllocateCommandBuffers(device, &command_buffer_allocate_info, + &new_command_buffer) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to allocate a UI setup command buffer"); + dfn.vkDestroyCommandPool(device, new_command_pool, nullptr); + return VK_NULL_HANDLE; + } + if (dfn.vkBeginCommandBuffer(new_command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to begin UI setup command buffer recording"); + dfn.vkDestroyCommandPool(device, new_command_pool, nullptr); + return VK_NULL_HANDLE; + } + paint_context_.ui_setup_command_buffer_current_index = + paint_context_.ui_setup_command_buffers.size(); + paint_context_.ui_setup_command_buffers.emplace_back( + new_command_pool, new_command_buffer, + ui_submission_tracker_.GetCurrentSubmission()); + return new_command_buffer; +} + +Presenter::SurfacePaintConnectResult +VulkanPresenter::ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) { + const VulkanProvider::InstanceFunctions& ifn = provider_.ifn(); + VkInstance instance = provider_.instance(); + VkPhysicalDevice physical_device = provider_.physical_device(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkFormat new_swapchain_format; + + // ConnectOrReconnectToSurfaceFromUIThread may be called only for the + // ui::Surface of the current swapchain or when the old swapchain and + // VkSurface have, if the ui::Surface is the same, try using the existing + // VkSurface and creating the swapchain smoothly from the existing one - if + // this doesn't succeed, start from scratch. + // The retirement or destruction of the swapchain here will also cause + // awaiting completion of the usage of the swapchain and the surface on the + // GPU. + if (paint_context_.vulkan_surface != VK_NULL_HANDLE) { + VkSwapchainKHR old_swapchain = + paint_context_.PrepareForSwapchainRetirement(); + bool surface_unusable; + paint_context_.swapchain = PaintContext::CreateSwapchainForVulkanSurface( + provider_, paint_context_.vulkan_surface, new_surface_width, + new_surface_height, old_swapchain, paint_context_.present_queue_family, + new_swapchain_format, paint_context_.swapchain_extent, + paint_context_.swapchain_is_fifo, surface_unusable); + // Destroy the old swapchain that may be retired now. + if (old_swapchain != VK_NULL_HANDLE) { + dfn.vkDestroySwapchainKHR(device, old_swapchain, nullptr); + } + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // Couldn't create the swapchain for the existing surface - start over. + paint_context_.DestroySwapchainAndVulkanSurface(); + } + } + + // If failed to create the swapchain for the previous surface, recreate the + // surface and create the new swapchain. + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // DestroySwapchainAndVulkanSurface should have been called previously. + assert_true(paint_context_.vulkan_surface == VK_NULL_HANDLE); + Surface::TypeIndex surface_type = new_surface.GetType(); + // Check if the surface type is supported according to the Vulkan + // extensions. + if (!(GetSupportedSurfaceTypes() & + (Surface::TypeFlags(1) << surface_type))) { + XELOGE( + "VulkanPresenter: Tried to create a Vulkan surface for an " + "unsupported Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + VkResult vulkan_surface_create_result = VK_ERROR_UNKNOWN; + switch (surface_type) { +#if XE_PLATFORM_ANDROID + case Surface::kTypeIndex_AndroidNativeWindow: { + auto& android_native_window_surface = + static_cast(new_surface); + VkAndroidSurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.window = android_native_window_surface.window(); + vulkan_surface_create_result = ifn.vkCreateAndroidSurfaceKHR( + instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif +#if XE_PLATFORM_GNU_LINUX + case Surface::kTypeIndex_XcbWindow: { + auto& xcb_window_surface = + static_cast(new_surface); + VkXcbSurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.connection = xcb_window_surface.connection(); + surface_create_info.window = xcb_window_surface.window(); + vulkan_surface_create_result = + ifn.vkCreateXcbSurfaceKHR(instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif +#if XE_PLATFORM_WIN32 + case Surface::kTypeIndex_Win32Hwnd: { + auto& win32_hwnd_surface = + static_cast(new_surface); + VkWin32SurfaceCreateInfoKHR surface_create_info; + surface_create_info.sType = + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surface_create_info.pNext = nullptr; + surface_create_info.flags = 0; + surface_create_info.hinstance = win32_hwnd_surface.hinstance(); + surface_create_info.hwnd = win32_hwnd_surface.hwnd(); + vulkan_surface_create_result = + ifn.vkCreateWin32SurfaceKHR(instance, &surface_create_info, nullptr, + &paint_context_.vulkan_surface); + } break; +#endif + default: + assert_unhandled_case(surface_type); + XELOGE( + "VulkanPresenter: Tried to create a Vulkan surface for an " + "unknown Xenia surface type"); + return SurfacePaintConnectResult::kFailureSurfaceUnusable; + } + if (vulkan_surface_create_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a Vulkan surface"); + return SurfacePaintConnectResult::kFailure; + } + bool surface_unusable; + paint_context_.swapchain = PaintContext::CreateSwapchainForVulkanSurface( + provider_, paint_context_.vulkan_surface, new_surface_width, + new_surface_height, VK_NULL_HANDLE, paint_context_.present_queue_family, + new_swapchain_format, paint_context_.swapchain_extent, + paint_context_.swapchain_is_fifo, surface_unusable); + if (paint_context_.swapchain == VK_NULL_HANDLE) { + // Failed to create the swapchain for the new Vulkan surface - destroy the + // Vulkan surface. + ifn.vkDestroySurfaceKHR(instance, paint_context_.vulkan_surface, nullptr); + paint_context_.vulkan_surface = VK_NULL_HANDLE; + return surface_unusable + ? SurfacePaintConnectResult::kFailureSurfaceUnusable + : SurfacePaintConnectResult::kFailure; + } + // Successfully attached (at least for now). + } + + // From now on, in case of failure, + // paint_context_.DestroySwapchainAndVulkanSurface must be called before + // returning. + + // Update the render pass to the new format. + if (paint_context_.swapchain_render_pass_format != new_swapchain_format) { + util::DestroyAndNullHandle(dfn.vkDestroyRenderPass, device, + paint_context_.swapchain_render_pass); + paint_context_.swapchain_render_pass_format = new_swapchain_format; + } + if (paint_context_.swapchain_render_pass == VK_NULL_HANDLE) { + VkAttachmentDescription render_pass_attachment; + render_pass_attachment.flags = 0; + render_pass_attachment.format = new_swapchain_format; + render_pass_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + render_pass_attachment.loadOp = cvars::present_render_pass_clear + ? VK_ATTACHMENT_LOAD_OP_CLEAR + : VK_ATTACHMENT_LOAD_OP_DONT_CARE; + render_pass_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + render_pass_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + render_pass_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + render_pass_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + render_pass_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentReference render_pass_color_attachment; + render_pass_color_attachment.attachment = 0; + render_pass_color_attachment.layout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription render_pass_subpass = {}; + render_pass_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + render_pass_subpass.colorAttachmentCount = 1; + render_pass_subpass.pColorAttachments = &render_pass_color_attachment; + VkSubpassDependency render_pass_dependencies[2]; + render_pass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + render_pass_dependencies[0].dstSubpass = 0; + // srcStageMask is the semaphore wait stage. + render_pass_dependencies[0].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + render_pass_dependencies[0].dstStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + render_pass_dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + // The main target can be used for UI drawing at any moment, which requires + // blending, so VK_ACCESS_COLOR_ATTACHMENT_READ_BIT is also included. + render_pass_dependencies[0].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + render_pass_dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + render_pass_dependencies[1].srcSubpass = 0; + render_pass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + render_pass_dependencies[1].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + // Semaphores are signaled at VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT. + render_pass_dependencies[1].dstStageMask = + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + render_pass_dependencies[1].srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + render_pass_dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + render_pass_dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + VkRenderPassCreateInfo render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_create_info.pNext = nullptr; + render_pass_create_info.flags = 0; + render_pass_create_info.attachmentCount = 1; + render_pass_create_info.pAttachments = &render_pass_attachment; + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &render_pass_subpass; + render_pass_create_info.dependencyCount = + uint32_t(xe::countof(render_pass_dependencies)); + render_pass_create_info.pDependencies = render_pass_dependencies; + VkRenderPass new_render_pass; + if (dfn.vkCreateRenderPass(device, &render_pass_create_info, nullptr, + &new_render_pass) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the render pass for drawing to " + "swapchain images"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + paint_context_.swapchain_render_pass = new_render_pass; + paint_context_.swapchain_render_pass_format = new_swapchain_format; + paint_context_.swapchain_render_pass_clear_load_op = + render_pass_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR; + } + + // Get the swapchain images. + paint_context_.swapchain_images.clear(); + VkResult swapchain_images_get_result; + for (;;) { + uint32_t swapchain_image_count = + uint32_t(paint_context_.swapchain_images.size()); + bool swapchain_images_were_empty = !swapchain_image_count; + swapchain_images_get_result = dfn.vkGetSwapchainImagesKHR( + device, paint_context_.swapchain, &swapchain_image_count, + swapchain_images_were_empty ? nullptr + : paint_context_.swapchain_images.data()); + // If the original swapchain image count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (swapchain_images_get_result == VK_SUCCESS || + swapchain_images_get_result == VK_INCOMPLETE) { + paint_context_.swapchain_images.resize(swapchain_image_count); + if (swapchain_images_get_result == VK_SUCCESS && + (!swapchain_images_were_empty || !swapchain_image_count)) { + break; + } + } else { + break; + } + } + if (swapchain_images_get_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to get swapchain images"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + + // Create the image views and the framebuffers. + assert_true(paint_context_.swapchain_framebuffers.empty()); + paint_context_.swapchain_framebuffers.reserve( + paint_context_.swapchain_images.size()); + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = new_swapchain_format; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.baseArrayLayer = 0; + image_view_create_info.subresourceRange.layerCount = 1; + VkImageView image_view; + VkFramebufferCreateInfo framebuffer_create_info; + framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_create_info.pNext = nullptr; + framebuffer_create_info.flags = 0; + framebuffer_create_info.renderPass = paint_context_.swapchain_render_pass; + framebuffer_create_info.attachmentCount = 1; + framebuffer_create_info.pAttachments = &image_view; + framebuffer_create_info.width = paint_context_.swapchain_extent.width; + framebuffer_create_info.height = paint_context_.swapchain_extent.height; + framebuffer_create_info.layers = 1; + for (VkImage image : paint_context_.swapchain_images) { + image_view_create_info.image = image; + if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, + &image_view) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain image view"); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + VkFramebuffer framebuffer; + if (dfn.vkCreateFramebuffer(device, &framebuffer_create_info, nullptr, + &framebuffer) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain framebuffer"); + dfn.vkDestroyImageView(device, image_view, nullptr); + paint_context_.DestroySwapchainAndVulkanSurface(); + return SurfacePaintConnectResult::kFailure; + } + paint_context_.swapchain_framebuffers.emplace_back(image_view, framebuffer); + } + + is_vsync_implicit_out = paint_context_.swapchain_is_fifo; + return SurfacePaintConnectResult::kSuccess; +} + +void VulkanPresenter::DisconnectPaintingFromSurfaceFromUIThreadImpl() { + paint_context_.DestroySwapchainAndVulkanSurface(); +} + +bool VulkanPresenter::RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) { + assert_not_zero(frontbuffer_width); + assert_not_zero(frontbuffer_height); + VkExtent2D max_framebuffer_extent = + util::GetMax2DFramebufferExtent(provider_); + if (frontbuffer_width > max_framebuffer_extent.width || + frontbuffer_height > max_framebuffer_extent.height) { + // Writing the guest output isn't supposed to rescale, and a guest texture + // exceeding the maximum size won't be loadable anyway. + return false; + } + + GuestOutputImageInstance& image_instance = + guest_output_images_[mailbox_index]; + if (image_instance.image && + (image_instance.image->extent().width != frontbuffer_width || + image_instance.image->extent().height != frontbuffer_height)) { + guest_output_image_refresher_submission_tracker_.AwaitSubmissionCompletion( + image_instance.last_refresher_submission); + image_instance.image.reset(); + } + if (!image_instance.image) { + std::unique_ptr new_image = GuestOutputImage::Create( + provider_, frontbuffer_width, frontbuffer_height); + if (!new_image) { + return false; + } + image_instance.SetToNewImage(std::move(new_image), + guest_output_image_next_version_++); + } + + VulkanGuestOutputRefreshContext context( + is_8bpc_out_ref, image_instance.image->image(), + image_instance.image->view(), image_instance.version, + image_instance.ever_successfully_refreshed); + bool refresher_succeeded = refresher(context); + if (refresher_succeeded) { + image_instance.ever_successfully_refreshed = true; + } + // Even if the refresher has returned false, it still might have submitted + // some commands referencing the image. It's better to put an excessive + // signal and wait slightly longer, for nothing important, while shutting down + // than to destroy the image while it's still in use. + image_instance.last_refresher_submission = + guest_output_image_refresher_submission_tracker_.GetCurrentSubmission(); + // No need to make the refresher signal the fence by itself - signal it here + // instead to have more control: + // "Fence signal operations that are defined by vkQueueSubmit additionally + // include in the first synchronization scope all commands that occur earlier + // in submission order." + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + guest_output_image_refresher_submission_tracker_ + .AcquireFenceToAdvanceSubmission()); + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); + if (dfn.vkQueueSubmit(queue_acquisition.queue, 0, nullptr, + fence_acqusition.fence()) != VK_SUCCESS) { + fence_acqusition.SubmissionSucceededSignalFailed(); + } + } + + return refresher_succeeded; +} + +VkSwapchainKHR VulkanPresenter::PaintContext::CreateSwapchainForVulkanSurface( + const VulkanProvider& provider, VkSurfaceKHR surface, uint32_t width, + uint32_t height, VkSwapchainKHR old_swapchain, + uint32_t& present_queue_family_out, VkFormat& image_format_out, + VkExtent2D& image_extent_out, bool& is_fifo_out, + bool& ui_surface_unusable_out) { + ui_surface_unusable_out = false; + + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + VkInstance instance = provider.instance(); + VkPhysicalDevice physical_device = provider.physical_device(); + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + // Get surface capabilities. + VkSurfaceCapabilitiesKHR surface_capabilities; + if (ifn.vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + physical_device, surface, &surface_capabilities) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to get Vulkan surface capabilities"); + // Some strange error, try again later. + return VK_NULL_HANDLE; + } + + // First, check if the surface is not zero-area because in this case, the rest + // of the fields in theory may not be informative as the surface doesn't need + // to go to presentation anyway, thus there's no need to return real + // information, and ui_surface_unusable_out (from which it may not be possible + // to recover on certain platforms at all) may be set to true spuriously if + // any checks set it to true. VkSurfaceKHR may have zero-area bounds in some + // window state cases on Windows, for example. Also clamp the requested size + // to the maximum supported by the physical device as long as minImageExtent + // in the instance's WSI allows that (if not, there's no way to satisfy both + // requirements - the maximum 2D framebuffer size on the specific physical + // device, and the minimum swap chain size on the whole instance - fail to + // create until the surface becomes smaller). + VkExtent2D max_framebuffer_extent = util::GetMax2DFramebufferExtent(provider); + VkExtent2D image_extent; + image_extent.width = + std::min(std::max(std::min(width, max_framebuffer_extent.width), + surface_capabilities.minImageExtent.width), + surface_capabilities.maxImageExtent.width); + image_extent.height = + std::min(std::max(std::min(height, max_framebuffer_extent.height), + surface_capabilities.minImageExtent.height), + surface_capabilities.maxImageExtent.height); + if (!image_extent.width || !image_extent.height || + image_extent.width > max_framebuffer_extent.width || + image_extent.height > max_framebuffer_extent.height) { + return VK_NULL_HANDLE; + } + + // Get the queue family for presentation. + uint32_t queue_family_index_present = UINT32_MAX; + const std::vector& queue_families = + provider.queue_families(); + VkBool32 queue_family_present_supported; + // First try the graphics and compute queue, prefer it to avoid the concurrent + // image sharing mode. + uint32_t queue_family_index_graphics_compute = + provider.queue_family_graphics_compute(); + const VulkanProvider::QueueFamily& queue_family_graphics_compute = + queue_families[queue_family_index_graphics_compute]; + if (queue_family_graphics_compute.potentially_supports_present && + queue_family_graphics_compute.queue_count && + ifn.vkGetPhysicalDeviceSurfaceSupportKHR( + physical_device, queue_family_index_graphics_compute, surface, + &queue_family_present_supported) == VK_SUCCESS && + queue_family_present_supported) { + queue_family_index_present = queue_family_index_graphics_compute; + } else { + for (uint32_t i = 0; i < uint32_t(queue_families.size()); ++i) { + const VulkanProvider::QueueFamily& queue_family = queue_families[i]; + if (queue_family.potentially_supports_present && + queue_family.queue_count && + ifn.vkGetPhysicalDeviceSurfaceSupportKHR( + physical_device, i, surface, &queue_family_present_supported) == + VK_SUCCESS && + queue_family_present_supported) { + queue_family_index_present = i; + break; + } + } + } + if (queue_family_index_present == UINT32_MAX) { + // Not unusable though - may become presentable if the window (with the same + // surface) moved to a different display, for instance. + return VK_NULL_HANDLE; + } + + // TODO(Triang3l): Support transforms. + if (!(surface_capabilities.supportedTransforms & + (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR | + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR))) { + XELOGE( + "VulkanPresenter: The surface doesn't support identity or " + "window-system-controlled transform"); + return VK_NULL_HANDLE; + } + + // Get the surface format. + std::vector surface_formats; + VkResult surface_formats_get_result; + for (;;) { + uint32_t surface_format_count = uint32_t(surface_formats.size()); + bool surface_formats_were_empty = !surface_format_count; + surface_formats_get_result = ifn.vkGetPhysicalDeviceSurfaceFormatsKHR( + physical_device, surface, &surface_format_count, + surface_formats_were_empty ? nullptr : surface_formats.data()); + // If the original presentation mode count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (surface_formats_get_result == VK_SUCCESS || + surface_formats_get_result == VK_INCOMPLETE) { + surface_formats.resize(surface_format_count); + if (surface_formats_get_result == VK_SUCCESS && + (!surface_formats_were_empty || !surface_format_count)) { + break; + } + } else { + break; + } + } + if (surface_formats_get_result != VK_SUCCESS) { + // Assuming any format in case of an error (or as some fallback in case of + // specification violation). + surface_formats.clear(); + } +#if XE_PLATFORM_ANDROID + // Android uses R8G8B8A8. + static const VkFormat kFormat8888Primary = VK_FORMAT_R8G8B8A8_UNORM; + static const VkFormat kFormat8888Secondary = VK_FORMAT_B8G8R8A8_UNORM; +#else + // GNU/Linux X11 and Windows DWM use B8G8R8A8. + static const VkFormat kFormat8888Primary = VK_FORMAT_B8G8R8A8_UNORM; + static const VkFormat kFormat8888Secondary = VK_FORMAT_R8G8B8A8_UNORM; +#endif + VkSurfaceFormatKHR image_format; + if (surface_formats.empty() || + (surface_formats.size() == 1 || + surface_formats[0].format == VK_FORMAT_UNDEFINED)) { + // Can choose any format if the implementation specifies only UNDEFINED. + image_format.format = kFormat8888Primary; + image_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + } else { + // Pick the sRGB 8888 format preferred by the OS, fall back to any sRGB + // 8888, then to 8888 with an unknown color space, and then to the first + // sRGB available, and then to the first. + auto format_8888_primary_it = surface_formats.cend(); + auto format_8888_secondary_it = surface_formats.cend(); + auto any_non_8888_srgb_it = surface_formats.cend(); + for (auto it = surface_formats.cbegin(); it != surface_formats.cend(); + ++it) { + if (it->format != kFormat8888Primary && + it->format != kFormat8888Secondary) { + if (it->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + any_non_8888_srgb_it == surface_formats.cend()) { + any_non_8888_srgb_it = it; + } + continue; + } + auto& preferred_8888_it = it->format == kFormat8888Primary + ? format_8888_primary_it + : format_8888_secondary_it; + if (preferred_8888_it == surface_formats.cend()) { + // First primary or secondary 8888 encounter. + preferred_8888_it = it; + continue; + } + // Is this a better primary or secondary 8888, that is, this is sRGB, + // while the previous encounter was not? + if (it->colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && + preferred_8888_it->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + preferred_8888_it = it; + } + } + if (format_8888_primary_it != surface_formats.cend() && + format_8888_secondary_it != surface_formats.cend()) { + // Both the primary and the secondary 8888 formats are available - prefer + // sRGB, if both are sRGB or not, prefer the primary format. + if (format_8888_primary_it->colorSpace == + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR || + format_8888_secondary_it->colorSpace != + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + image_format = *format_8888_primary_it; + } else { + image_format = *format_8888_secondary_it; + } + } else if (format_8888_primary_it != surface_formats.cend()) { + // Only primary 8888. + image_format = *format_8888_primary_it; + } else if (format_8888_secondary_it != surface_formats.cend()) { + // Only secondary 8888. + image_format = *format_8888_secondary_it; + } else if (any_non_8888_srgb_it != surface_formats.cend()) { + // No 8888, but some sRGB format is available. + image_format = *any_non_8888_srgb_it; + } else { + // Just pick any format. + image_format = surface_formats.front(); + } + } + + // Get presentation modes. + std::vector present_modes; + VkResult present_modes_get_result; + for (;;) { + uint32_t present_mode_count = uint32_t(present_modes.size()); + bool present_modes_were_empty = !present_mode_count; + present_modes_get_result = ifn.vkGetPhysicalDeviceSurfacePresentModesKHR( + physical_device, surface, &present_mode_count, + present_modes_were_empty ? nullptr : present_modes.data()); + // If the original presentation mode count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (present_modes_get_result == VK_SUCCESS || + present_modes_get_result == VK_INCOMPLETE) { + present_modes.resize(present_mode_count); + if (present_modes_get_result == VK_SUCCESS && + (!present_modes_were_empty || !present_mode_count)) { + break; + } + } else { + break; + } + } + if (present_modes_get_result != VK_SUCCESS) { + // Assuming FIFO only (required everywhere) in case of an error. + present_modes.clear(); + } + + // Create the swapchain. + VkSwapchainCreateInfoKHR swapchain_create_info; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.pNext = nullptr; + swapchain_create_info.flags = 0; + swapchain_create_info.surface = surface; + swapchain_create_info.minImageCount = + std::max(kSubmissionCount, surface_capabilities.minImageCount); + if (surface_capabilities.maxImageCount) { + swapchain_create_info.minImageCount = + std::min(swapchain_create_info.minImageCount, + surface_capabilities.maxImageCount); + } + swapchain_create_info.imageFormat = image_format.format; + swapchain_create_info.imageColorSpace = image_format.colorSpace; + swapchain_create_info.imageExtent = image_extent; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + uint32_t swapchain_queue_family_indices[2]; + if (queue_family_index_graphics_compute != queue_family_index_present) { + // Using concurrent sharing mode to avoid an explicit ownership transfer + // before presenting, which would require an additional command buffer + // submission with the acquire barrier and a semaphore between the graphics + // queue and the present queue. Different queues are an extremely rare case, + // and Xenia only uses the swapchain for the final guest output and the + // internal UI, so keeping framebuffer compression is not worth the + // additional submission complexity and possibly latency. + swapchain_queue_family_indices[0] = queue_family_index_graphics_compute; + swapchain_queue_family_indices[1] = queue_family_index_present; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapchain_create_info.queueFamilyIndexCount = 2; + swapchain_create_info.pQueueFamilyIndices = swapchain_queue_family_indices; + } else { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = nullptr; + } + swapchain_create_info.preTransform = + (surface_capabilities.supportedTransforms & + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR + : VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; + // Prefer opaque to avoid blending in the window system, or let that be + // specified via the window system if it can't be forced. As a last resort, + // just pick any - guest output will write alpha of 1 anyway. + if (surface_capabilities.supportedCompositeAlpha & + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + } else if (surface_capabilities.supportedCompositeAlpha & + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + } else { + uint32_t composite_alpha_shift; + if (!xe::bit_scan_forward( + uint32_t(surface_capabilities.supportedCompositeAlpha), + &composite_alpha_shift)) { + // Against the Vulkan specification, but breaks the logic here. + XELOGE( + "VulkanPresenter: The surface doesn't support any composite alpha " + "mode"); + return VK_NULL_HANDLE; + } + swapchain_create_info.compositeAlpha = + VkCompositeAlphaFlagBitsKHR(uint32_t(1) << composite_alpha_shift); + } + // As presentation is usually controlled by the GPU command processor, it's + // better to use modes that allow as quick acquisition as possible to avoid + // interfering with GPU command processing, and also to allow tearing so + // variable refresh rate may be used where it's available. + // Note: If the priorities here are changes, update the cvar descriptions. + if (cvars::vulkan_allow_present_mode_immediate && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.cend()) { + // Allowing tearing to reduce latency, and possibly variable refresh rate + // (though on Windows with borderless fullscreen, GDI copying is used + // instead of independent flip, so it's not supported there). + swapchain_create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } else if (cvars::vulkan_allow_present_mode_mailbox && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.cend()) { + // Allowing dropping frames to reduce latency, but no tearing. + swapchain_create_info.presentMode = VK_PRESENT_MODE_MAILBOX_KHR; + } else if (cvars::vulkan_allow_present_mode_fifo_relaxed && + std::find(present_modes.cbegin(), present_modes.cend(), + VK_PRESENT_MODE_FIFO_RELAXED_KHR) != + present_modes.cend()) { + // Limiting the frame rate, but lets too long frames cause tearing not to + // make the latency even worse. + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } else { + // Highest latency (but always guaranteed to be available). + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + } + swapchain_create_info.clipped = VK_TRUE; + swapchain_create_info.oldSwapchain = old_swapchain; + VkSwapchainKHR swapchain; + if (dfn.vkCreateSwapchainKHR(device, &swapchain_create_info, nullptr, + &swapchain) != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a swapchain"); + return VK_NULL_HANDLE; + } + XELOGVK( + "VulkanPresenter: Created {}x{} swapchain with format {}, color space " + "{}, presentation mode {}", + swapchain_create_info.imageExtent.width, + swapchain_create_info.imageExtent.height, + uint32_t(swapchain_create_info.imageFormat), + uint32_t(swapchain_create_info.imageColorSpace), + uint32_t(swapchain_create_info.presentMode)); + + present_queue_family_out = queue_family_index_present; + image_format_out = swapchain_create_info.imageFormat; + image_extent_out = swapchain_create_info.imageExtent; + is_fifo_out = + swapchain_create_info.presentMode == VK_PRESENT_MODE_FIFO_KHR || + swapchain_create_info.presentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR; + return swapchain; +} + +VkSwapchainKHR VulkanPresenter::PaintContext::PrepareForSwapchainRetirement() { + if (swapchain != VK_NULL_HANDLE) { + submission_tracker.AwaitAllSubmissionsCompletion(); + } + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + for (const SwapchainFramebuffer& framebuffer : swapchain_framebuffers) { + dfn.vkDestroyFramebuffer(device, framebuffer.framebuffer, nullptr); + dfn.vkDestroyImageView(device, framebuffer.image_view, nullptr); + } + swapchain_framebuffers.clear(); + swapchain_images.clear(); + swapchain_extent.width = 0; + swapchain_extent.height = 0; + // The old swapchain must be destroyed externally. + VkSwapchainKHR old_swapchain = swapchain; + swapchain = nullptr; + return old_swapchain; +} + +void VulkanPresenter::PaintContext::DestroySwapchainAndVulkanSurface() { + VkSwapchainKHR old_swapchain = PrepareForSwapchainRetirement(); + if (old_swapchain != VK_NULL_HANDLE) { + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + dfn.vkDestroySwapchainKHR(device, old_swapchain, nullptr); + } + present_queue_family = UINT32_MAX; + if (vulkan_surface != VK_NULL_HANDLE) { + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + VkInstance instance = provider.instance(); + ifn.vkDestroySurfaceKHR(instance, vulkan_surface, nullptr); + vulkan_surface = VK_NULL_HANDLE; + } +} + +VulkanPresenter::GuestOutputImage::~GuestOutputImage() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + if (view_ != VK_NULL_HANDLE) { + dfn.vkDestroyImageView(device, view_, nullptr); + } + if (image_ != VK_NULL_HANDLE) { + dfn.vkDestroyImage(device, image_, nullptr); + } + if (memory_ != VK_NULL_HANDLE) { + dfn.vkFreeMemory(device, memory_, nullptr); + } +} + +bool VulkanPresenter::GuestOutputImage::Initialize() { + VkImageCreateInfo image_create_info; + VkImageCreateInfo* image_create_info_last = &image_create_info; + image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_create_info.pNext = nullptr; + image_create_info.flags = 0; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.format = kGuestOutputFormat; + image_create_info.extent.width = extent_.width; + image_create_info.extent.height = extent_.height; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.queueFamilyIndexCount = 0; + image_create_info.pQueueFamilyIndices = nullptr; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if (!ui::vulkan::util::CreateDedicatedAllocationImage( + provider_, image_create_info, + ui::vulkan::util::MemoryPurpose::kDeviceLocal, image_, memory_)) { + XELOGE("VulkanPresenter: Failed to create a guest output image"); + return false; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = nullptr; + image_view_create_info.flags = 0; + image_view_create_info.image = image_; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = kGuestOutputFormat; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = 1; + image_view_create_info.subresourceRange.baseArrayLayer = 0; + image_view_create_info.subresourceRange.layerCount = 1; + if (dfn.vkCreateImageView(device, &image_view_create_info, nullptr, &view_) != + VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to create a guest output image view"); + return false; + } + + return true; +} + +Presenter::PaintResult VulkanPresenter::PaintAndPresentImpl( + bool execute_ui_drawers) { + // Begin the submission in place of the one not currently potentially used on + // the GPU. + uint64_t current_paint_submission_index = + paint_context_.submission_tracker.GetCurrentSubmission(); + uint64_t paint_submission_count = uint64_t(paint_context_.submissions.size()); + if (current_paint_submission_index >= paint_submission_count) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + current_paint_submission_index - paint_submission_count); + } + const PaintContext::Submission& paint_submission = + *paint_context_.submissions[current_paint_submission_index % + paint_submission_count]; + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkCommandPool draw_command_pool = paint_submission.draw_command_pool(); + if (dfn.vkResetCommandPool(device, draw_command_pool, 0) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to reset a command buffer for drawing to the " + "swapchain"); + return PaintResult::kNotPresented; + } + + VkCommandBuffer draw_command_buffer = paint_submission.draw_command_buffer(); + 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; + if (dfn.vkBeginCommandBuffer(draw_command_buffer, + &command_buffer_begin_info) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to being recording the command buffer for " + "drawing to the swapchain"); + return PaintResult::kNotPresented; + } + // vkResetCommandPool resets from both initial and recording states, still + // safe to return early from this function in case of an error. + + VkSemaphore acquire_semaphore = paint_submission.acquire_semaphore(); + uint32_t swapchain_image_index; + VkResult acquire_result = dfn.vkAcquireNextImageKHR( + device, paint_context_.swapchain, UINT64_MAX, acquire_semaphore, + VK_NULL_HANDLE, &swapchain_image_index); + switch (acquire_result) { + case VK_SUCCESS: + case VK_SUBOPTIMAL_KHR: + break; + case VK_ERROR_DEVICE_LOST: + XELOGE( + "VulkanPresenter: Failed to acquire the swapchain image as the " + "device has been lost"); + return PaintResult::kGpuLostResponsible; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_ERROR_SURFACE_LOST_KHR: + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + // Not an error, reporting just as info (may normally occur while resizing + // on some platforms). + XELOGVK( + "VulkanPresenter: Presentation to the swapchain image has been " + "dropped as the swapchain or the surface has become outdated"); + return PaintResult::kNotPresentedConnectionOutdated; + default: + XELOGE("VulkanPresenter: Failed to acquire the swapchain image"); + return PaintResult::kNotPresented; + } + + // Non-zero extents needed for both the viewport (width must not be zero) and + // the guest output rectangle. + assert_not_zero(paint_context_.swapchain_extent.width); + assert_not_zero(paint_context_.swapchain_extent.height); + + bool swapchain_image_clear_needed = true; + VkClearAttachment swapchain_image_clear_attachment; + swapchain_image_clear_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + swapchain_image_clear_attachment.colorAttachment = 0; + swapchain_image_clear_attachment.clearValue.color.float32[0] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[1] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[2] = 0.0f; + swapchain_image_clear_attachment.clearValue.color.float32[3] = 1.0f; + + VkRenderPassBeginInfo swapchain_render_pass_begin_info; + swapchain_render_pass_begin_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + swapchain_render_pass_begin_info.pNext = nullptr; + swapchain_render_pass_begin_info.renderPass = + paint_context_.swapchain_render_pass; + swapchain_render_pass_begin_info.framebuffer = + paint_context_.swapchain_framebuffers[swapchain_image_index].framebuffer; + swapchain_render_pass_begin_info.renderArea.offset.x = 0; + swapchain_render_pass_begin_info.renderArea.offset.y = 0; + swapchain_render_pass_begin_info.renderArea.extent = + paint_context_.swapchain_extent; + swapchain_render_pass_begin_info.clearValueCount = 0; + swapchain_render_pass_begin_info.pClearValues = nullptr; + if (paint_context_.swapchain_render_pass_clear_load_op) { + swapchain_render_pass_begin_info.clearValueCount = 1; + swapchain_render_pass_begin_info.pClearValues = + &swapchain_image_clear_attachment.clearValue; + swapchain_image_clear_needed = false; + } + + bool swapchain_image_pass_begun = false; + + GuestOutputProperties guest_output_properties; + GuestOutputPaintConfig guest_output_paint_config; + std::shared_ptr guest_output_image; + { + uint32_t guest_output_mailbox_index; + std::unique_lock guest_output_consumer_lock( + ConsumeGuestOutput(guest_output_mailbox_index, &guest_output_properties, + &guest_output_paint_config)); + if (guest_output_mailbox_index != UINT32_MAX) { + assert_true(guest_output_images_[guest_output_mailbox_index] + .ever_successfully_refreshed); + guest_output_image = + guest_output_images_[guest_output_mailbox_index].image; + } + // Incremented the reference count of the guest output image - safe to leave + // the consumer critical section now as everything here either will be using + // the new reference or is exclusively owned by main target painting (and + // multiple threads can't paint the main target at the same time). + } + + if (guest_output_image) { + VkExtent2D max_framebuffer_extent = + util::GetMax2DFramebufferExtent(provider_); + GuestOutputPaintFlow guest_output_flow = GetGuestOutputPaintFlow( + guest_output_properties, paint_context_.swapchain_extent.width, + paint_context_.swapchain_extent.height, max_framebuffer_extent.width, + max_framebuffer_extent.height, guest_output_paint_config); + if (guest_output_flow.effect_count) { + // Store the main target reference to the guest output image so it's not + // destroyed while it's still potentially in use by main target painting + // queued on the GPU. + size_t guest_output_image_paint_ref_index = SIZE_MAX; + size_t guest_output_image_paint_ref_new_index = SIZE_MAX; + // Try to find the existing reference to the same image, or an already + // released (or a taken, but never actually used) slot. + for (size_t i = 0; + i < paint_context_.guest_output_image_paint_refs.size(); ++i) { + const std::pair>& + guest_output_image_paint_ref = + paint_context_.guest_output_image_paint_refs[i]; + if (guest_output_image_paint_ref.second == guest_output_image) { + guest_output_image_paint_ref_index = i; + break; + } + if (guest_output_image_paint_ref_new_index == SIZE_MAX && + (!guest_output_image_paint_ref.second || + !guest_output_image_paint_ref.first)) { + guest_output_image_paint_ref_new_index = i; + } + } + if (guest_output_image_paint_ref_index == SIZE_MAX) { + // New image - store the reference and create the descriptors. + if (guest_output_image_paint_ref_new_index == SIZE_MAX) { + // Replace the earliest used reference. + guest_output_image_paint_ref_new_index = 0; + for (size_t i = 1; + i < paint_context_.guest_output_image_paint_refs.size(); ++i) { + if (paint_context_.guest_output_image_paint_refs[i].first < + paint_context_ + .guest_output_image_paint_refs + [guest_output_image_paint_ref_new_index] + .first) { + guest_output_image_paint_ref_new_index = i; + } + } + // Await the completion of the usage of the old guest output image and + // its descriptors. + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_image_paint_refs + [guest_output_image_paint_ref_new_index] + .first); + } + guest_output_image_paint_ref_index = + guest_output_image_paint_ref_new_index; + // The actual submission index will be set if the image is actually + // used, not dropped due to some error. + paint_context_ + .guest_output_image_paint_refs[guest_output_image_paint_ref_index] = + std::make_pair(uint64_t(0), guest_output_image); + // Create the descriptors of the new image. + VkDescriptorImageInfo guest_output_image_descriptor_image_info; + guest_output_image_descriptor_image_info.sampler = + provider_.GetHostSampler(VulkanProvider::HostSampler::kLinearClamp); + guest_output_image_descriptor_image_info.imageView = + guest_output_image->view(); + guest_output_image_descriptor_image_info.imageLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet guest_output_image_descriptor_write; + guest_output_image_descriptor_write.sType = + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + guest_output_image_descriptor_write.pNext = nullptr; + guest_output_image_descriptor_write.dstSet = + paint_context_.guest_output_descriptor_sets + [PaintContext::kGuestOutputDescriptorSetGuestOutput0Sampled + + guest_output_image_paint_ref_index]; + guest_output_image_descriptor_write.dstBinding = 0; + guest_output_image_descriptor_write.dstArrayElement = 0; + guest_output_image_descriptor_write.descriptorCount = 1; + guest_output_image_descriptor_write.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + guest_output_image_descriptor_write.pImageInfo = + &guest_output_image_descriptor_image_info; + guest_output_image_descriptor_write.pBufferInfo = nullptr; + guest_output_image_descriptor_write.pTexelBufferView = nullptr; + dfn.vkUpdateDescriptorSets( + device, 1, &guest_output_image_descriptor_write, 0, nullptr); + } + + // Make sure intermediate textures of the needed size are available, and + // unneeded intermediate textures are destroyed. + for (size_t i = 0; i < kMaxGuestOutputPaintEffects - 1; ++i) { + std::pair intermediate_needed_size(0, 0); + if (i + 1 < guest_output_flow.effect_count) { + intermediate_needed_size = guest_output_flow.effect_output_sizes[i]; + } + std::unique_ptr& intermediate_image_ptr_ref = + paint_context_.guest_output_intermediate_images[i]; + VkExtent2D intermediate_current_extent( + intermediate_image_ptr_ref ? intermediate_image_ptr_ref->extent() + : VkExtent2D{}); + if (intermediate_current_extent.width != + intermediate_needed_size.first || + intermediate_current_extent.height != + intermediate_needed_size.second) { + if (intermediate_needed_size.first && + intermediate_needed_size.second) { + // Need to replace immediately as a new image with the requested + // size is needed. + if (intermediate_image_ptr_ref) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_ + .guest_output_intermediate_image_last_submission); + intermediate_image_ptr_ref.reset(); + util::DestroyAndNullHandle( + dfn.vkDestroyFramebuffer, device, + paint_context_.guest_output_intermediate_framebuffers[i]); + } + // Image. + intermediate_image_ptr_ref = GuestOutputImage::Create( + provider_, intermediate_needed_size.first, + intermediate_needed_size.second); + if (!intermediate_image_ptr_ref) { + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + // Framebuffer. + VkImageView intermediate_framebuffer_attachment = + intermediate_image_ptr_ref->view(); + VkFramebufferCreateInfo intermediate_framebuffer_create_info; + intermediate_framebuffer_create_info.sType = + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + intermediate_framebuffer_create_info.pNext = nullptr; + intermediate_framebuffer_create_info.flags = 0; + intermediate_framebuffer_create_info.renderPass = + guest_output_intermediate_render_pass_; + intermediate_framebuffer_create_info.attachmentCount = 1; + intermediate_framebuffer_create_info.pAttachments = + &intermediate_framebuffer_attachment; + intermediate_framebuffer_create_info.width = + intermediate_needed_size.first; + intermediate_framebuffer_create_info.height = + intermediate_needed_size.second; + intermediate_framebuffer_create_info.layers = 1; + if (dfn.vkCreateFramebuffer( + device, &intermediate_framebuffer_create_info, nullptr, + &paint_context_ + .guest_output_intermediate_framebuffers[i]) != + VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a guest output " + "intermediate framebuffer"); + // Don't display the guest output, and don't try to create more + // intermediate textures (only destroy them). + guest_output_flow.effect_count = 0; + continue; + } + // Descriptors. + VkDescriptorImageInfo intermediate_descriptor_image_info; + intermediate_descriptor_image_info.sampler = + provider_.GetHostSampler( + VulkanProvider::HostSampler::kLinearClamp); + intermediate_descriptor_image_info.imageView = + intermediate_image_ptr_ref->view(); + intermediate_descriptor_image_info.imageLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet intermediate_descriptor_write; + intermediate_descriptor_write.sType = + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + intermediate_descriptor_write.pNext = nullptr; + intermediate_descriptor_write.dstSet = + paint_context_.guest_output_descriptor_sets + [PaintContext :: + kGuestOutputDescriptorSetIntermediate0Sampled + + i]; + intermediate_descriptor_write.dstBinding = 0; + intermediate_descriptor_write.dstArrayElement = 0; + intermediate_descriptor_write.descriptorCount = 1; + intermediate_descriptor_write.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + intermediate_descriptor_write.pImageInfo = + &intermediate_descriptor_image_info; + intermediate_descriptor_write.pBufferInfo = nullptr; + intermediate_descriptor_write.pTexelBufferView = nullptr; + dfn.vkUpdateDescriptorSets( + device, 1, &intermediate_descriptor_write, 0, nullptr); + } else { + // Was previously needed, but not anymore - destroy when possible. + if (intermediate_image_ptr_ref && + paint_context_.submission_tracker + .UpdateAndGetCompletedSubmission() >= + paint_context_ + .guest_output_intermediate_image_last_submission) { + intermediate_image_ptr_ref.reset(); + util::DestroyAndNullHandle( + dfn.vkDestroyFramebuffer, device, + paint_context_.guest_output_intermediate_framebuffers[i]); + } + } + } + } + + if (guest_output_flow.effect_count) { + // Check if all the intermediate effects are supported by the + // implementation. + for (size_t i = 0; i + 1 < guest_output_flow.effect_count; ++i) { + if (paint_context_ + .guest_output_paint_pipelines[size_t( + guest_output_flow.effects[i])] + .intermediate_pipeline == VK_NULL_HANDLE) { + guest_output_flow.effect_count = 0; + break; + } + } + // Ensure the pipeline exists for the final effect drawing to the + // swapchain, for the render pass with the up-to-date image format. + GuestOutputPaintEffect swapchain_effect = + guest_output_flow.effects[guest_output_flow.effect_count - 1]; + PaintContext::GuestOutputPaintPipeline& swapchain_effect_pipeline = + paint_context_ + .guest_output_paint_pipelines[size_t(swapchain_effect)]; + if (swapchain_effect_pipeline.swapchain_pipeline != VK_NULL_HANDLE && + swapchain_effect_pipeline.swapchain_format != + paint_context_.swapchain_render_pass_format) { + paint_context_.submission_tracker.AwaitSubmissionCompletion( + paint_context_.guest_output_image_paint_last_submission); + util::DestroyAndNullHandle( + dfn.vkDestroyPipeline, device, + swapchain_effect_pipeline.swapchain_pipeline); + } + if (swapchain_effect_pipeline.swapchain_pipeline == VK_NULL_HANDLE) { + assert_true(CanGuestOutputPaintEffectBeFinal(swapchain_effect)); + assert_true(guest_output_paint_fs_[size_t(swapchain_effect)] != + VK_NULL_HANDLE); + swapchain_effect_pipeline.swapchain_pipeline = + CreateGuestOutputPaintPipeline( + swapchain_effect, paint_context_.swapchain_render_pass); + if (swapchain_effect_pipeline.swapchain_pipeline == VK_NULL_HANDLE) { + guest_output_flow.effect_count = 0; + } + } + } + + if (guest_output_flow.effect_count) { + // Actually draw the guest output. + paint_context_ + .guest_output_image_paint_refs[guest_output_image_paint_ref_index] + .first = current_paint_submission_index; + paint_context_.guest_output_image_paint_last_submission = + current_paint_submission_index; + VkViewport guest_output_viewport; + guest_output_viewport.x = 0.0f; + guest_output_viewport.y = 0.0f; + guest_output_viewport.minDepth = 0.0f; + guest_output_viewport.maxDepth = 1.0f; + VkRect2D guest_output_scissor; + guest_output_scissor.offset.x = 0; + guest_output_scissor.offset.y = 0; + if (guest_output_flow.effect_count > 1) { + paint_context_.guest_output_intermediate_image_last_submission = + current_paint_submission_index; + } + for (size_t i = 0; i < guest_output_flow.effect_count; ++i) { + bool is_final_effect = i + 1 >= guest_output_flow.effect_count; + + int32_t effect_rect_x, effect_rect_y; + std::pair effect_rect_size = + guest_output_flow.effect_output_sizes[i]; + if (is_final_effect) { + effect_rect_x = guest_output_flow.output_x; + effect_rect_y = guest_output_flow.output_y; + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &swapchain_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + swapchain_image_pass_begun = true; + guest_output_viewport.width = + float(paint_context_.swapchain_extent.width); + guest_output_viewport.height = + float(paint_context_.swapchain_extent.height); + guest_output_scissor.extent.width = + paint_context_.swapchain_extent.width; + guest_output_scissor.extent.height = + paint_context_.swapchain_extent.height; + } else { + effect_rect_x = 0; + effect_rect_y = 0; + VkRenderPassBeginInfo intermediate_render_pass_begin_info; + intermediate_render_pass_begin_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + intermediate_render_pass_begin_info.pNext = nullptr; + intermediate_render_pass_begin_info.renderPass = + guest_output_intermediate_render_pass_; + intermediate_render_pass_begin_info.framebuffer = + paint_context_.guest_output_intermediate_framebuffers[i]; + intermediate_render_pass_begin_info.renderArea.offset.x = 0; + intermediate_render_pass_begin_info.renderArea.offset.y = 0; + intermediate_render_pass_begin_info.renderArea.extent.width = + effect_rect_size.first; + intermediate_render_pass_begin_info.renderArea.extent.height = + effect_rect_size.second; + intermediate_render_pass_begin_info.clearValueCount = 0; + intermediate_render_pass_begin_info.pClearValues = nullptr; + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &intermediate_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + guest_output_viewport.width = float(effect_rect_size.first); + guest_output_viewport.height = float(effect_rect_size.second); + guest_output_scissor.extent.width = effect_rect_size.first; + guest_output_scissor.extent.height = effect_rect_size.second; + } + dfn.vkCmdSetViewport(draw_command_buffer, 0, 1, + &guest_output_viewport); + dfn.vkCmdSetScissor(draw_command_buffer, 0, 1, &guest_output_scissor); + + GuestOutputPaintEffect effect = guest_output_flow.effects[i]; + + const PaintContext::GuestOutputPaintPipeline& effect_pipeline = + paint_context_.guest_output_paint_pipelines[size_t(effect)]; + VkPipeline effect_vulkan_pipeline = + is_final_effect ? effect_pipeline.swapchain_pipeline + : effect_pipeline.intermediate_pipeline; + assert_true(effect_vulkan_pipeline != VK_NULL_HANDLE); + dfn.vkCmdBindPipeline(draw_command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + effect_vulkan_pipeline); + + GuestOutputPaintPipelineLayoutIndex + guest_output_paint_pipeline_layout_index = + GetGuestOutputPaintPipelineLayoutIndex(effect); + VkPipelineLayout guest_output_paint_pipeline_layout = + guest_output_paint_pipeline_layouts_ + [guest_output_paint_pipeline_layout_index]; + + PaintContext::GuestOutputDescriptorSet effect_src_descriptor_set; + if (i) { + effect_src_descriptor_set = PaintContext::GuestOutputDescriptorSet( + PaintContext::kGuestOutputDescriptorSetIntermediate0Sampled + + (i - 1)); + } else { + effect_src_descriptor_set = PaintContext::GuestOutputDescriptorSet( + PaintContext::kGuestOutputDescriptorSetGuestOutput0Sampled + + guest_output_image_paint_ref_index); + } + dfn.vkCmdBindDescriptorSets( + draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + guest_output_paint_pipeline_layout, 0, 1, + &paint_context_ + .guest_output_descriptor_sets[effect_src_descriptor_set], + 0, nullptr); + + GuestOutputPaintRectangleConstants effect_rect_constants; + float effect_x_to_ndc = 2.0f / guest_output_viewport.width; + float effect_y_to_ndc = 2.0f / guest_output_viewport.height; + effect_rect_constants.x = + -1.0f + float(effect_rect_x) * effect_x_to_ndc; + effect_rect_constants.y = + -1.0f + float(effect_rect_y) * effect_y_to_ndc; + effect_rect_constants.width = + float(effect_rect_size.first) * effect_x_to_ndc; + effect_rect_constants.height = + float(effect_rect_size.second) * effect_y_to_ndc; + dfn.vkCmdPushConstants( + draw_command_buffer, guest_output_paint_pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(effect_rect_constants), + &effect_rect_constants); + + uint32_t effect_constants_size = 0; + union { + BilinearConstants bilinear; + CasSharpenConstants cas_sharpen; + CasResampleConstants cas_resample; + FsrEasuConstants fsr_easu; + FsrRcasConstants fsr_rcas; + } effect_constants; + switch (guest_output_paint_pipeline_layout_index) { + case kGuestOutputPaintPipelineLayoutIndexBilinear: { + effect_constants_size = sizeof(effect_constants.bilinear); + effect_constants.bilinear.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintPipelineLayoutIndexCasSharpen: { + effect_constants_size = sizeof(effect_constants.cas_sharpen); + effect_constants.cas_sharpen.Initialize( + guest_output_flow, i, guest_output_paint_config); + } break; + case kGuestOutputPaintPipelineLayoutIndexCasResample: { + effect_constants_size = sizeof(effect_constants.cas_resample); + effect_constants.cas_resample.Initialize( + guest_output_flow, i, guest_output_paint_config); + } break; + case kGuestOutputPaintPipelineLayoutIndexFsrEasu: { + effect_constants_size = sizeof(effect_constants.fsr_easu); + effect_constants.fsr_easu.Initialize(guest_output_flow, i); + } break; + case kGuestOutputPaintPipelineLayoutIndexFsrRcas: { + effect_constants_size = sizeof(effect_constants.fsr_rcas); + effect_constants.fsr_rcas.Initialize(guest_output_flow, i, + guest_output_paint_config); + } break; + default: + break; + } + if (effect_constants_size) { + dfn.vkCmdPushConstants( + draw_command_buffer, guest_output_paint_pipeline_layout, + VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(effect_rect_constants), + effect_constants_size, &effect_constants); + } + + dfn.vkCmdDraw(draw_command_buffer, 4, 1, 0, 0); + + if (is_final_effect) { + // Clear the letterbox around the guest output if the guest output + // doesn't cover the entire swapchain image. + if (swapchain_image_clear_needed && + guest_output_flow.letterbox_clear_rectangle_count) { + VkClearRect letterbox_clear_vulkan_rectangles + [GuestOutputPaintFlow::kMaxClearRectangles]; + for (size_t i = 0; + i < guest_output_flow.letterbox_clear_rectangle_count; ++i) { + VkClearRect& letterbox_clear_vulkan_rectangle = + letterbox_clear_vulkan_rectangles[i]; + const GuestOutputPaintFlow::ClearRectangle& + letterbox_clear_rectangle = + guest_output_flow.letterbox_clear_rectangles[i]; + letterbox_clear_vulkan_rectangle.rect.offset.x = + int32_t(letterbox_clear_rectangle.x); + letterbox_clear_vulkan_rectangle.rect.offset.y = + int32_t(letterbox_clear_rectangle.y); + letterbox_clear_vulkan_rectangle.rect.extent.width = + letterbox_clear_rectangle.width; + letterbox_clear_vulkan_rectangle.rect.extent.height = + letterbox_clear_rectangle.height; + letterbox_clear_vulkan_rectangle.baseArrayLayer = 0; + letterbox_clear_vulkan_rectangle.layerCount = 1; + } + dfn.vkCmdClearAttachments( + draw_command_buffer, 1, &swapchain_image_clear_attachment, + uint32_t(guest_output_flow.letterbox_clear_rectangle_count), + letterbox_clear_vulkan_rectangles); + } + swapchain_image_clear_needed = false; + } else { + // Still need the swapchain pass to be open for UI drawing. + dfn.vkCmdEndRenderPass(draw_command_buffer); + } + } + } + } + } + + // Release main target guest output image references that aren't needed + // anymore (this is done after various potential guest-output-related main + // target submission tracker waits so the completed submission value is the + // most actual). + uint64_t completed_paint_submission = + paint_context_.submission_tracker.UpdateAndGetCompletedSubmission(); + for (std::pair>& + guest_output_image_paint_ref : + paint_context_.guest_output_image_paint_refs) { + if (!guest_output_image_paint_ref.second || + guest_output_image_paint_ref.second == guest_output_image) { + continue; + } + if (completed_paint_submission >= guest_output_image_paint_ref.first) { + guest_output_image_paint_ref.second.reset(); + } + } + + // If hasn't presented the guest output, begin the pass to clear and, if + // needed, to draw the UI. + if (!swapchain_image_pass_begun) { + dfn.vkCmdBeginRenderPass(draw_command_buffer, + &swapchain_render_pass_begin_info, + VK_SUBPASS_CONTENTS_INLINE); + } + if (swapchain_image_clear_needed) { + VkClearRect swapchain_image_clear_rectangle; + swapchain_image_clear_rectangle.rect.offset.x = 0; + swapchain_image_clear_rectangle.rect.offset.y = 0; + swapchain_image_clear_rectangle.rect.extent = + paint_context_.swapchain_extent; + swapchain_image_clear_rectangle.baseArrayLayer = 0; + swapchain_image_clear_rectangle.layerCount = 1; + dfn.vkCmdClearAttachments(draw_command_buffer, 1, + &swapchain_image_clear_attachment, 1, + &swapchain_image_clear_rectangle); + swapchain_image_clear_needed = false; + } + + if (execute_ui_drawers) { + // Draw the UI. + VulkanUIDrawContext ui_draw_context( + *this, paint_context_.swapchain_extent.width, + paint_context_.swapchain_extent.height, draw_command_buffer, + ui_submission_tracker_.GetCurrentSubmission(), + ui_submission_tracker_.UpdateAndGetCompletedSubmission(), + paint_context_.swapchain_render_pass, + paint_context_.swapchain_render_pass_format); + ExecuteUIDrawersFromUIThread(ui_draw_context); + } + + dfn.vkCmdEndRenderPass(draw_command_buffer); + + dfn.vkEndCommandBuffer(draw_command_buffer); + + VkPipelineStageFlags acquire_semaphore_wait_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkCommandBuffer command_buffers[2]; + uint32_t command_buffer_count = 0; + // UI setup command buffers must be accessed only if execute_ui_drawers is not + // null, to identify the UI thread. + size_t ui_setup_command_buffer_index = + execute_ui_drawers ? paint_context_.ui_setup_command_buffer_current_index + : SIZE_MAX; + if (ui_setup_command_buffer_index != SIZE_MAX) { + PaintContext::UISetupCommandBuffer& ui_setup_command_buffer = + paint_context_.ui_setup_command_buffers[ui_setup_command_buffer_index]; + dfn.vkEndCommandBuffer(ui_setup_command_buffer.command_buffer); + command_buffers[command_buffer_count++] = + ui_setup_command_buffer.command_buffer; + // Release the current UI setup command buffer regardless of submission + // result. Failed submissions (if the UI submission index wasn't incremented + // since the previous draw) should be handled by UI drawers themselves by + // retrying all the failed work if needed. + paint_context_.ui_setup_command_buffer_current_index = SIZE_MAX; + } + command_buffers[command_buffer_count++] = draw_command_buffer; + VkSemaphore present_semaphore = paint_submission.present_semaphore(); + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &acquire_semaphore; + submit_info.pWaitDstStageMask = &acquire_semaphore_wait_stage; + submit_info.commandBufferCount = command_buffer_count; + submit_info.pCommandBuffers = command_buffers; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &present_semaphore; + { + VulkanSubmissionTracker::FenceAcquisition fence_acqusition( + paint_context_.submission_tracker.AcquireFenceToAdvanceSubmission()); + // Also update the submission tracker giving submission indices to UI draw + // callbacks if submission is successful. + VulkanSubmissionTracker::FenceAcquisition ui_fence_acquisition; + if (execute_ui_drawers) { + ui_fence_acquisition = + ui_submission_tracker_.AcquireFenceToAdvanceSubmission(); + } + VkResult submit_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(provider_.queue_family_graphics_compute(), 0)); + submit_result = dfn.vkQueueSubmit(queue_acquisition.queue, 1, + &submit_info, fence_acqusition.fence()); + if (ui_fence_acquisition.fence() != VK_NULL_HANDLE && + submit_result == VK_SUCCESS) { + if (dfn.vkQueueSubmit(queue_acquisition.queue, 0, nullptr, + ui_fence_acquisition.fence()) != VK_SUCCESS) { + ui_fence_acquisition.SubmissionSucceededSignalFailed(); + } + } + } + if (submit_result != VK_SUCCESS) { + XELOGE("VulkanPresenter: Failed to submit command buffers"); + fence_acqusition.SubmissionFailedOrDropped(); + ui_fence_acquisition.SubmissionFailedOrDropped(); + if (ui_setup_command_buffer_index != SIZE_MAX) { + // If failed to submit, make the UI setup command buffer available for + // immediate reuse, as the completed submission index won't be updated + // to the current index, and failing submissions with setup command + // buffer over and over will result in never reusing the setup command + // buffers. + paint_context_.ui_setup_command_buffers[ui_setup_command_buffer_index] + .last_usage_submission_index = 0; + } + // The image is in an acquired state - but now, it will be in it forever. + // To avoid that, recreate the swapchain - don't return just + // kNotPresented. + return PaintResult::kNotPresentedConnectionOutdated; + } + } + + VkPresentInfoKHR present_info; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.pNext = nullptr; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &present_semaphore; + present_info.swapchainCount = 1; + present_info.pSwapchains = &paint_context_.swapchain; + present_info.pImageIndices = &swapchain_image_index; + present_info.pResults = nullptr; + VkResult present_result; + { + VulkanProvider::QueueAcquisition queue_acquisition( + provider_.AcquireQueue(paint_context_.present_queue_family, 0)); + present_result = + dfn.vkQueuePresentKHR(queue_acquisition.queue, &present_info); + } + switch (present_result) { + case VK_SUCCESS: + return PaintResult::kPresented; + case VK_SUBOPTIMAL_KHR: + return PaintResult::kPresentedSuboptimal; + case VK_ERROR_DEVICE_LOST: + XELOGE( + "VulkanPresenter: Failed to present the swapchain image as the " + "device has been lost"); + return PaintResult::kGpuLostResponsible; + case VK_ERROR_OUT_OF_DATE_KHR: + case VK_ERROR_SURFACE_LOST_KHR: + case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: + // Not an error, reporting just as info (may normally occur while resizing + // on some platforms). + XELOGVK( + "VulkanPresenter: Presentation to the swapchain image has been " + "dropped as the swapchain or the surface has become outdated"); + // Note that the semaphore wait (followed by reset) has been enqueued, + // however, this should have no effect on anything here likely. + return PaintResult::kNotPresentedConnectionOutdated; + default: + XELOGE("VulkanPresenter: Failed to present the swapchain image"); + // The image is in an acquired state - but now, it will be in it forever. + // To avoid that, recreate the swapchain - don't return just + // kNotPresented. + return PaintResult::kNotPresentedConnectionOutdated; + } +} + +bool VulkanPresenter::InitializeSurfaceIndependent() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkSampler sampler_linear_clamp = + provider_.GetHostSampler(VulkanProvider::HostSampler::kLinearClamp); + VkDescriptorSetLayoutBinding guest_output_image_binding; + guest_output_image_binding.binding = 0; + guest_output_image_binding.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + guest_output_image_binding.descriptorCount = 1; + guest_output_image_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + guest_output_image_binding.pImmutableSamplers = &sampler_linear_clamp; + VkDescriptorSetLayoutCreateInfo + guest_output_paint_image_descriptor_set_layout_create_info; + guest_output_paint_image_descriptor_set_layout_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + guest_output_paint_image_descriptor_set_layout_create_info.pNext = nullptr; + guest_output_paint_image_descriptor_set_layout_create_info.flags = 0; + guest_output_paint_image_descriptor_set_layout_create_info.bindingCount = 1; + guest_output_paint_image_descriptor_set_layout_create_info.pBindings = + &guest_output_image_binding; + if (dfn.vkCreateDescriptorSetLayout( + device, &guest_output_paint_image_descriptor_set_layout_create_info, + nullptr, + &guest_output_paint_image_descriptor_set_layout_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output image descriptor " + "set layout"); + return false; + } + + VkPushConstantRange guest_output_paint_push_constant_ranges[2]; + VkPushConstantRange& guest_output_paint_push_constant_range_rect = + guest_output_paint_push_constant_ranges[0]; + guest_output_paint_push_constant_range_rect.stageFlags = + VK_SHADER_STAGE_VERTEX_BIT; + guest_output_paint_push_constant_range_rect.offset = 0; + guest_output_paint_push_constant_range_rect.size = + sizeof(GuestOutputPaintRectangleConstants); + VkPushConstantRange& guest_output_paint_push_constant_range_ffx = + guest_output_paint_push_constant_ranges[1]; + guest_output_paint_push_constant_range_ffx.stageFlags = + VK_SHADER_STAGE_FRAGMENT_BIT; + guest_output_paint_push_constant_range_ffx.offset = + guest_output_paint_push_constant_ranges[0].offset + + guest_output_paint_push_constant_ranges[0].size; + VkPipelineLayoutCreateInfo guest_output_paint_pipeline_layout_create_info; + guest_output_paint_pipeline_layout_create_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + guest_output_paint_pipeline_layout_create_info.pNext = nullptr; + guest_output_paint_pipeline_layout_create_info.flags = 0; + guest_output_paint_pipeline_layout_create_info.setLayoutCount = 1; + guest_output_paint_pipeline_layout_create_info.pSetLayouts = + &guest_output_paint_image_descriptor_set_layout_; + guest_output_paint_pipeline_layout_create_info.pPushConstantRanges = + guest_output_paint_push_constant_ranges; + for (size_t i = 0; i < size_t(kGuestOutputPaintPipelineLayoutCount); ++i) { + switch (GuestOutputPaintPipelineLayoutIndex(i)) { + case kGuestOutputPaintPipelineLayoutIndexBilinear: + guest_output_paint_push_constant_range_ffx.size = + sizeof(BilinearConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexCasSharpen: + guest_output_paint_push_constant_range_ffx.size = + sizeof(CasSharpenConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexCasResample: + guest_output_paint_push_constant_range_ffx.size = + sizeof(CasResampleConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexFsrEasu: + guest_output_paint_push_constant_range_ffx.size = + sizeof(FsrEasuConstants); + break; + case kGuestOutputPaintPipelineLayoutIndexFsrRcas: + guest_output_paint_push_constant_range_ffx.size = + sizeof(FsrRcasConstants); + break; + default: + assert_unhandled_case(GuestOutputPaintPipelineLayoutIndex(i)); + continue; + } + guest_output_paint_pipeline_layout_create_info.pushConstantRangeCount = + 1 + uint32_t(guest_output_paint_push_constant_range_ffx.size != 0); + if (dfn.vkCreatePipelineLayout( + device, &guest_output_paint_pipeline_layout_create_info, nullptr, + &guest_output_paint_pipeline_layouts_[i]) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create a guest output presentation " + "pipeline layout with {} bytes of push constants", + guest_output_paint_push_constant_range_rect.size + + guest_output_paint_push_constant_range_ffx.size); + return false; + } + } + + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0; + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_triangle_strip_rect_vert); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_triangle_strip_rect_vert); + if (dfn.vkCreateShaderModule(device, &shader_module_create_info, nullptr, + &guest_output_paint_vs_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output presentation " + "vertex shader module"); + return false; + } + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + GuestOutputPaintEffect guest_output_paint_effect = + GuestOutputPaintEffect(i); + switch (guest_output_paint_effect) { + case GuestOutputPaintEffect::kBilinear: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_bilinear_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_bilinear_frag); + break; + case GuestOutputPaintEffect::kBilinearDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_bilinear_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_bilinear_dither_frag); + break; + case GuestOutputPaintEffect::kCasSharpen: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_sharpen_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_sharpen_frag); + break; + case GuestOutputPaintEffect::kCasSharpenDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_sharpen_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_sharpen_dither_frag); + break; + case GuestOutputPaintEffect::kCasResample: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_resample_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_resample_frag); + break; + case GuestOutputPaintEffect::kCasResampleDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_cas_resample_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_cas_resample_dither_frag); + break; + case GuestOutputPaintEffect::kFsrEasu: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_easu_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_easu_frag); + break; + case GuestOutputPaintEffect::kFsrRcas: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_rcas_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_rcas_frag); + break; + case GuestOutputPaintEffect::kFsrRcasDither: + shader_module_create_info.codeSize = + sizeof(shaders::guest_output_ffx_fsr_rcas_dither_frag); + shader_module_create_info.pCode = reinterpret_cast( + shaders::guest_output_ffx_fsr_rcas_dither_frag); + break; + default: + // Not supported by this implementation. + continue; + } + if (dfn.vkCreateShaderModule(device, &shader_module_create_info, nullptr, + &guest_output_paint_fs_[i]) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting shader " + "module for effect {}", + i); + return false; + } + } + + VkAttachmentDescription intermediate_render_pass_attachment; + intermediate_render_pass_attachment.flags = 0; + intermediate_render_pass_attachment.format = kGuestOutputFormat; + intermediate_render_pass_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + intermediate_render_pass_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + intermediate_render_pass_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + intermediate_render_pass_attachment.stencilLoadOp = + VK_ATTACHMENT_LOAD_OP_DONT_CARE; + intermediate_render_pass_attachment.stencilStoreOp = + VK_ATTACHMENT_STORE_OP_DONT_CARE; + intermediate_render_pass_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + intermediate_render_pass_attachment.finalLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkAttachmentReference intermediate_render_pass_color_attachment; + intermediate_render_pass_color_attachment.attachment = 0; + intermediate_render_pass_color_attachment.layout = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription intermediate_render_pass_subpass = {}; + intermediate_render_pass_subpass.pipelineBindPoint = + VK_PIPELINE_BIND_POINT_GRAPHICS; + intermediate_render_pass_subpass.colorAttachmentCount = 1; + intermediate_render_pass_subpass.pColorAttachments = + &intermediate_render_pass_color_attachment; + VkSubpassDependency intermediate_render_pass_dependencies[2]; + intermediate_render_pass_dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + intermediate_render_pass_dependencies[0].dstSubpass = 0; + intermediate_render_pass_dependencies[0].srcStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + intermediate_render_pass_dependencies[0].dstStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + intermediate_render_pass_dependencies[0].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + intermediate_render_pass_dependencies[0].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + intermediate_render_pass_dependencies[0].dependencyFlags = 0; + intermediate_render_pass_dependencies[1].srcSubpass = 0; + intermediate_render_pass_dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + intermediate_render_pass_dependencies[1].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + intermediate_render_pass_dependencies[1].dstStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + intermediate_render_pass_dependencies[1].srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + intermediate_render_pass_dependencies[1].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + intermediate_render_pass_dependencies[1].dependencyFlags = 0; + VkRenderPassCreateInfo intermediate_render_pass_create_info; + intermediate_render_pass_create_info.sType = + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + intermediate_render_pass_create_info.pNext = nullptr; + intermediate_render_pass_create_info.flags = 0; + intermediate_render_pass_create_info.attachmentCount = 1; + intermediate_render_pass_create_info.pAttachments = + &intermediate_render_pass_attachment; + intermediate_render_pass_create_info.subpassCount = 1; + intermediate_render_pass_create_info.pSubpasses = + &intermediate_render_pass_subpass; + intermediate_render_pass_create_info.dependencyCount = + uint32_t(xe::countof(intermediate_render_pass_dependencies)); + intermediate_render_pass_create_info.pDependencies = + intermediate_render_pass_dependencies; + if (dfn.vkCreateRenderPass( + device, &intermediate_render_pass_create_info, nullptr, + &guest_output_intermediate_render_pass_) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output intermediate image " + "render pass"); + return false; + } + + // Initialize connection-independent parts of the painting context. + + for (size_t i = 0; i < paint_context_.submissions.size(); ++i) { + paint_context_.submissions[i] = PaintContext::Submission::Create(provider_); + if (!paint_context_.submissions[i]) { + return false; + } + } + + // Guest output paint pipelines drawing to intermediate images, not depending + // on runtime state unlike ones drawing to the swapchain images as those + // depend on the swapchain format. + for (size_t i = 0; i < size_t(GuestOutputPaintEffect::kCount); ++i) { + if (!CanGuestOutputPaintEffectBeIntermediate(GuestOutputPaintEffect(i)) || + guest_output_paint_fs_[i] == VK_NULL_HANDLE) { + continue; + } + VkPipeline guest_output_paint_intermediate_pipeline = + CreateGuestOutputPaintPipeline(GuestOutputPaintEffect(i), + guest_output_intermediate_render_pass_); + if (guest_output_paint_intermediate_pipeline == VK_NULL_HANDLE) { + return false; + } + paint_context_.guest_output_paint_pipelines[i].intermediate_pipeline = + guest_output_paint_intermediate_pipeline; + } + + // Guest output painting descriptor sets. + VkDescriptorPoolSize guest_output_paint_descriptor_pool_size; + guest_output_paint_descriptor_pool_size.type = + guest_output_image_binding.descriptorType; + // Each descriptor set contains only 1 descriptor. + guest_output_paint_descriptor_pool_size.descriptorCount = + PaintContext::kGuestOutputDescriptorSetCount; + VkDescriptorPoolCreateInfo guest_output_paint_descriptor_pool_create_info; + guest_output_paint_descriptor_pool_create_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + guest_output_paint_descriptor_pool_create_info.pNext = nullptr; + guest_output_paint_descriptor_pool_create_info.flags = 0; + guest_output_paint_descriptor_pool_create_info.maxSets = + PaintContext::kGuestOutputDescriptorSetCount; + guest_output_paint_descriptor_pool_create_info.poolSizeCount = 1; + guest_output_paint_descriptor_pool_create_info.pPoolSizes = + &guest_output_paint_descriptor_pool_size; + if (dfn.vkCreateDescriptorPool( + device, &guest_output_paint_descriptor_pool_create_info, nullptr, + &paint_context_.guest_output_descriptor_pool) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting " + "descriptor pool"); + return false; + } + VkDescriptorSetLayout guest_output_paint_descriptor_set_layouts + [PaintContext::kGuestOutputDescriptorSetCount]; + std::fill(guest_output_paint_descriptor_set_layouts, + guest_output_paint_descriptor_set_layouts + + xe::countof(guest_output_paint_descriptor_set_layouts), + guest_output_paint_image_descriptor_set_layout_); + VkDescriptorSetAllocateInfo guest_output_paint_descriptor_set_allocate_info; + guest_output_paint_descriptor_set_allocate_info.sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + guest_output_paint_descriptor_set_allocate_info.pNext = nullptr; + guest_output_paint_descriptor_set_allocate_info.descriptorPool = + paint_context_.guest_output_descriptor_pool; + guest_output_paint_descriptor_set_allocate_info.descriptorSetCount = + PaintContext::kGuestOutputDescriptorSetCount; + guest_output_paint_descriptor_set_allocate_info.pSetLayouts = + guest_output_paint_descriptor_set_layouts; + if (dfn.vkAllocateDescriptorSets( + device, &guest_output_paint_descriptor_set_allocate_info, + paint_context_.guest_output_descriptor_sets) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to allocate the guest output painting " + "descriptor sets"); + return false; + } + + return InitializeCommonSurfaceIndependent(); +} + +VkPipeline VulkanPresenter::CreateGuestOutputPaintPipeline( + GuestOutputPaintEffect effect, VkRenderPass render_pass) { + VkPipelineShaderStageCreateInfo stages[2] = {}; + for (uint32_t i = 0; i < 2; ++i) { + VkPipelineShaderStageCreateInfo& stage = stages[i]; + stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage.stage = i ? VK_SHADER_STAGE_FRAGMENT_BIT : VK_SHADER_STAGE_VERTEX_BIT; + stage.pName = "main"; + } + stages[0].module = guest_output_paint_vs_; + stages[1].module = guest_output_paint_fs_[size_t(effect)]; + assert_true(stages[1].module != VK_NULL_HANDLE); + + VkPipelineVertexInputStateCreateInfo vertex_input_state = {}; + vertex_input_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_state = {}; + input_assembly_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + + VkPipelineViewportStateCreateInfo viewport_state = {}; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.viewportCount = 1; + viewport_state.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo rasterization_state = {}; + rasterization_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization_state.polygonMode = VK_POLYGON_MODE_FILL; + rasterization_state.cullMode = VK_CULL_MODE_NONE; + rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterization_state.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo multisample_state = {}; + multisample_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state = {}; + color_blend_attachment_state.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + VkPipelineColorBlendStateCreateInfo color_blend_state = {}; + color_blend_state.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blend_state.attachmentCount = 1; + color_blend_state.pAttachments = &color_blend_attachment_state; + + static const VkDynamicState kPipelineDynamicStates[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state.dynamicStateCount = + uint32_t(xe::countof(kPipelineDynamicStates)); + dynamic_state.pDynamicStates = kPipelineDynamicStates; + + VkGraphicsPipelineCreateInfo pipeline_create_info; + pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_create_info.pNext = nullptr; + pipeline_create_info.flags = 0; + pipeline_create_info.stageCount = uint32_t(xe::countof(stages)); + pipeline_create_info.pStages = stages; + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly_state; + pipeline_create_info.pTessellationState = nullptr; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pRasterizationState = &rasterization_state; + pipeline_create_info.pMultisampleState = &multisample_state; + pipeline_create_info.pDepthStencilState = nullptr; + pipeline_create_info.pColorBlendState = &color_blend_state; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.layout = guest_output_paint_pipeline_layouts_ + [GetGuestOutputPaintPipelineLayoutIndex(effect)]; + pipeline_create_info.renderPass = render_pass; + pipeline_create_info.subpass = 0; + pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_create_info.basePipelineIndex = UINT32_MAX; + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkPipeline pipeline; + if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, + &pipeline_create_info, nullptr, + &pipeline) != VK_SUCCESS) { + XELOGE( + "VulkanPresenter: Failed to create the guest output painting pipeline " + "for effect {}", + size_t(effect)); + return VK_NULL_HANDLE; + } + return pipeline; +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_presenter.h b/src/xenia/ui/vulkan/vulkan_presenter.h new file mode 100644 index 000000000..91e055c6d --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_presenter.h @@ -0,0 +1,518 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VULKAN_VULKAN_PRESENTER_H_ +#define XENIA_UI_VULKAN_VULKAN_PRESENTER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/platform.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" +#include "xenia/ui/vulkan/vulkan_provider.h" +#include "xenia/ui/vulkan/vulkan_submission_tracker.h" + +namespace xe { +namespace ui { +namespace vulkan { + +class VulkanUIDrawContext final : public UIDrawContext { + public: + VulkanUIDrawContext(Presenter& presenter, uint32_t render_target_width, + uint32_t render_target_height, + VkCommandBuffer draw_command_buffer, + uint64_t submission_index_current, + uint64_t submission_index_completed, + VkRenderPass render_pass, VkFormat render_pass_format) + : UIDrawContext(presenter, render_target_width, render_target_height), + draw_command_buffer_(draw_command_buffer), + submission_index_current_(submission_index_current), + submission_index_completed_(submission_index_completed), + render_pass_(render_pass), + render_pass_format_(render_pass_format) {} + + VkCommandBuffer draw_command_buffer() const { return draw_command_buffer_; } + uint64_t submission_index_current() const { + return submission_index_current_; + } + uint64_t submission_index_completed() const { + return submission_index_completed_; + } + VkRenderPass render_pass() const { return render_pass_; } + VkFormat render_pass_format() const { return render_pass_format_; } + + private: + VkCommandBuffer draw_command_buffer_; + uint64_t submission_index_current_; + uint64_t submission_index_completed_; + // Has 1 subpass with a single render_pass_format_ attachment. + VkRenderPass render_pass_; + VkFormat render_pass_format_; +}; + +class VulkanPresenter final : public Presenter { + public: + // Maximum number of different guest output image versions still potentially + // considered alive that may be given to the refresher - this many instances + // of dependent objects (such as framebuffers) may need to be kept by the + // refresher across invocations (due to multiple-buffering of guest output + // images inside the presenter, different versions may be given even every + // invocation), to avoid recreation of dependent objects every frame. + static constexpr size_t kMaxActiveGuestOutputImageVersions = + kGuestOutputMailboxSize; + + static constexpr VkFormat kGuestOutputFormat = + VK_FORMAT_A2B10G10R10_UNORM_PACK32; + // The guest output is expected to be acquired and released in this state by + // the refresher. The exception is the first write to the current guest output + // image - in this case, a barrier is only needed from + // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT without access. Also if the image is + // being refreshed for the first time, it's in VK_IMAGE_LAYOUT_UNDEFINED (but + // it's safe, and preferred, to transition it from VK_IMAGE_LAYOUT_UNDEFINED + // when writing to it in general). + static constexpr VkPipelineStageFlagBits kGuestOutputInternalStageMask = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + static constexpr VkAccessFlags kGuestOutputInternalAccessMask = + VK_ACCESS_SHADER_READ_BIT; + static constexpr VkImageLayout kGuestOutputInternalLayout = + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + // The callback must use the graphics and compute queue 0 of the provider. + class VulkanGuestOutputRefreshContext final + : public GuestOutputRefreshContext { + public: + VulkanGuestOutputRefreshContext(bool& is_8bpc_out_ref, VkImage image, + VkImageView image_view, + uint64_t image_version, + bool image_ever_written_previously) + : GuestOutputRefreshContext(is_8bpc_out_ref), + image_(image), + image_view_(image_view), + image_version_(image_version), + image_ever_written_previously_(image_ever_written_previously) {} + + // The format is kGuestOutputFormat. + // Supports usage as a color attachment and as a sampled image, as well as + // transfer source (but the reason of that is guest output capturing). + VkImage image() const { return image_; } + VkImageView image_view() const { return image_view_; } + uint64_t image_version() const { return image_version_; } + // Whether a proper barrier must be done to acquire the image. + bool image_ever_written_previously() const { + return image_ever_written_previously_; + } + + private: + VkImage image_; + VkImageView image_view_; + uint64_t image_version_; + bool image_ever_written_previously_; + }; + + static std::unique_ptr Create( + HostGpuLossCallback host_gpu_loss_callback, VulkanProvider& provider) { + auto presenter = std::unique_ptr( + new VulkanPresenter(host_gpu_loss_callback, provider)); + if (!presenter->InitializeSurfaceIndependent()) { + return nullptr; + } + return presenter; + } + + ~VulkanPresenter(); + + VulkanProvider& provider() const { return provider_; } + + static Surface::TypeFlags GetSurfaceTypesSupportedByInstance( + const VulkanProvider::InstanceExtensions& instance_extensions) { + if (!instance_extensions.khr_surface) { + return 0; + } + Surface::TypeFlags type_flags = 0; +#if XE_PLATFORM_ANDROID + if (instance_extensions.khr_android_surface) { + type_flags |= Surface::kTypeFlag_AndroidNativeWindow; + } +#elif XE_PLATFORM_GNU_LINUX + if (instance_extensions.khr_xcb_surface) { + type_flags |= Surface::kTypeFlag_XcbWindow; + } +#elif XE_PLATFORM_WIN32 + if (instance_extensions.khr_win32_surface) { + type_flags |= Surface::kTypeFlag_Win32Hwnd; + } +#endif + return type_flags; + } + Surface::TypeFlags GetSupportedSurfaceTypes() const override; + + bool CaptureGuestOutput(RawImage& image_out) override; + + void AwaitUISubmissionCompletionFromUIThread(uint64_t submission_index) { + ui_submission_tracker_.AwaitSubmissionCompletion(submission_index); + } + VkCommandBuffer AcquireUISetupCommandBufferFromUIThread(); + + protected: + SurfacePaintConnectResult ConnectOrReconnectPaintingToSurfaceFromUIThread( + Surface& new_surface, uint32_t new_surface_width, + uint32_t new_surface_height, bool was_paintable, + bool& is_vsync_implicit_out) override; + void DisconnectPaintingFromSurfaceFromUIThreadImpl() override; + + bool RefreshGuestOutputImpl( + uint32_t mailbox_index, uint32_t frontbuffer_width, + uint32_t frontbuffer_height, + std::function refresher, + bool& is_8bpc_out_ref) override; + + PaintResult PaintAndPresentImpl(bool execute_ui_drawers) override; + + private: + // Usable for both the guest output image itself and for intermediate images. + class GuestOutputImage { + public: + static std::unique_ptr Create( + const VulkanProvider& provider, uint32_t width, uint32_t height) { + assert_not_zero(width); + assert_not_zero(height); + auto image = std::unique_ptr( + new GuestOutputImage(provider, width, height)); + if (!image->Initialize()) { + return nullptr; + } + return std::move(image); + } + + GuestOutputImage(const GuestOutputImage& image) = delete; + GuestOutputImage& operator=(const GuestOutputImage& image) = delete; + ~GuestOutputImage(); + + const VkExtent2D& extent() const { return extent_; } + + VkImage image() const { return image_; } + VkDeviceMemory memory() const { return memory_; } + VkImageView view() const { return view_; } + + private: + GuestOutputImage(const VulkanProvider& provider, uint32_t width, + uint32_t height) + : provider_(provider) { + extent_.width = width; + extent_.height = height; + } + + bool Initialize(); + + const VulkanProvider& provider_; + + VkExtent2D extent_; + VkImage image_ = VK_NULL_HANDLE; + VkDeviceMemory memory_ = VK_NULL_HANDLE; + VkImageView view_ = VK_NULL_HANDLE; + }; + + struct GuestOutputImageInstance { + // Refresher-side reference (painting has its own references for the purpose + // of destruction only after painting is done on the GPU). + std::shared_ptr image; + uint64_t version = UINT64_MAX; + uint64_t last_refresher_submission = 0; + // For choosing the barrier stage and access mask and layout depending on + // whether the image has previously been written. If an image is active + // after a refresh, it can be assumed that this is true. + bool ever_successfully_refreshed = false; + + void SetToNewImage(const std::shared_ptr& new_image, + uint64_t new_version) { + image = new_image; + version = new_version; + last_refresher_submission = 0; + ever_successfully_refreshed = false; + } + }; + + struct GuestOutputPaintRectangleConstants { + union { + struct { + float x; + float y; + }; + float offset[2]; + }; + union { + struct { + float width; + float height; + }; + float size[2]; + }; + }; + + enum GuestOutputPaintPipelineLayoutIndex : size_t { + kGuestOutputPaintPipelineLayoutIndexBilinear, + kGuestOutputPaintPipelineLayoutIndexCasSharpen, + kGuestOutputPaintPipelineLayoutIndexCasResample, + kGuestOutputPaintPipelineLayoutIndexFsrEasu, + kGuestOutputPaintPipelineLayoutIndexFsrRcas, + + kGuestOutputPaintPipelineLayoutCount, + }; + + static constexpr GuestOutputPaintPipelineLayoutIndex + GetGuestOutputPaintPipelineLayoutIndex(GuestOutputPaintEffect effect) { + switch (effect) { + case GuestOutputPaintEffect::kBilinear: + case GuestOutputPaintEffect::kBilinearDither: + return kGuestOutputPaintPipelineLayoutIndexBilinear; + case GuestOutputPaintEffect::kCasSharpen: + case GuestOutputPaintEffect::kCasSharpenDither: + return kGuestOutputPaintPipelineLayoutIndexCasSharpen; + case GuestOutputPaintEffect::kCasResample: + case GuestOutputPaintEffect::kCasResampleDither: + return kGuestOutputPaintPipelineLayoutIndexCasResample; + case GuestOutputPaintEffect::kFsrEasu: + return kGuestOutputPaintPipelineLayoutIndexFsrEasu; + case GuestOutputPaintEffect::kFsrRcas: + case GuestOutputPaintEffect::kFsrRcasDither: + return kGuestOutputPaintPipelineLayoutIndexFsrRcas; + default: + assert_unhandled_case(effect); + return kGuestOutputPaintPipelineLayoutCount; + } + } + + struct PaintContext { + class Submission { + public: + static std::unique_ptr Create( + const VulkanProvider& provider) { + auto submission = std::unique_ptr(new Submission(provider)); + if (!submission->Initialize()) { + return nullptr; + } + return submission; + } + + Submission(const Submission& submission) = delete; + Submission& operator=(const Submission& submission) = delete; + ~Submission(); + + VkSemaphore acquire_semaphore() const { return acquire_semaphore_; } + VkSemaphore present_semaphore() const { return present_semaphore_; } + VkCommandPool draw_command_pool() const { return draw_command_pool_; } + VkCommandBuffer draw_command_buffer() const { + return draw_command_buffer_; + } + + private: + explicit Submission(const VulkanProvider& provider) + : provider_(provider) {} + bool Initialize(); + + const VulkanProvider& provider_; + VkSemaphore acquire_semaphore_ = VK_NULL_HANDLE; + VkSemaphore present_semaphore_ = VK_NULL_HANDLE; + VkCommandPool draw_command_pool_ = VK_NULL_HANDLE; + VkCommandBuffer draw_command_buffer_ = VK_NULL_HANDLE; + }; + + static constexpr uint32_t kSubmissionCount = 3; + + struct GuestOutputPaintPipeline { + // Created on initialization. + VkPipeline intermediate_pipeline = VK_NULL_HANDLE; + // Created during guest output painting (after awaiting the last guest + // output paint if outdated and needs to be recreated), when needed, for + // the up-to-date render pass that draws to the swapchain with the actual + // image format. + VkPipeline swapchain_pipeline = VK_NULL_HANDLE; + VkFormat swapchain_format = VK_FORMAT_UNDEFINED; + }; + + enum GuestOutputDescriptorSet : uint32_t { + kGuestOutputDescriptorSetGuestOutput0Sampled, + + kGuestOutputDescriptorSetIntermediate0Sampled = + kGuestOutputDescriptorSetGuestOutput0Sampled + + kGuestOutputMailboxSize, + + kGuestOutputDescriptorSetCount = + kGuestOutputDescriptorSetIntermediate0Sampled + + kMaxGuestOutputPaintEffects - 1, + }; + + struct UISetupCommandBuffer { + UISetupCommandBuffer(VkCommandPool command_pool, + VkCommandBuffer command_buffer, + uint64_t last_usage_submission_index = 0) + : command_pool(command_pool), + command_buffer(command_buffer), + last_usage_submission_index(last_usage_submission_index) {} + + VkCommandPool command_pool; + VkCommandBuffer command_buffer; + uint64_t last_usage_submission_index; + }; + + struct SwapchainFramebuffer { + SwapchainFramebuffer(VkImageView image_view, VkFramebuffer framebuffer) + : image_view(image_view), framebuffer(framebuffer) {} + + VkImageView image_view; + VkFramebuffer framebuffer; + }; + + explicit PaintContext(VulkanProvider& provider) + : provider(provider), submission_tracker(provider) {} + PaintContext(const PaintContext& paint_context) = delete; + PaintContext& operator=(const PaintContext& paint_context) = delete; + + // The old swapchain, if passed, should be assumed to be retired after this + // call (though it may fail before the vkCreateSwapchainKHR that will + // technically retire it, so it will be in an undefined state), and needs to + // be destroyed externally no matter what the result is. + static VkSwapchainKHR CreateSwapchainForVulkanSurface( + const VulkanProvider& provider, VkSurfaceKHR surface, uint32_t width, + uint32_t height, VkSwapchainKHR old_swapchain, + uint32_t& present_queue_family_out, VkFormat& image_format_out, + VkExtent2D& image_extent_out, bool& is_fifo_out, + bool& ui_surface_unusable_out); + + // Destroys the swapchain and its derivatives, nulls `swapchain` and returns + // the original swapchain object, if it existed, for use as oldSwapchain if + // needed and for destruction. + VkSwapchainKHR PrepareForSwapchainRetirement(); + // May be called from the destructor of the presenter. + void DestroySwapchainAndVulkanSurface(); + + // Connection-indepedent. + + const VulkanProvider& provider; + + std::array, kSubmissionCount> + submissions; + VulkanSubmissionTracker submission_tracker; + + std::array + guest_output_paint_pipelines; + + VkDescriptorPool guest_output_descriptor_pool = VK_NULL_HANDLE; + // Descriptors are updated while painting if they're out of date. + VkDescriptorSet + guest_output_descriptor_sets[kGuestOutputDescriptorSetCount]; + + // Refreshed and cleaned up during guest output painting. The first is the + // paint submission index in which the guest output image (and its + // descriptors) was last used, the second is the reference to the image, + // which may be null. The indices are not mailbox indices here, rather, if + // the reference is not in this array yet, the most outdated reference, if + // needed, is replaced with the new one, awaiting the usage completion of + // the last paint usage. + std::array>, + kGuestOutputMailboxSize> + guest_output_image_paint_refs; + // The latest submission index at which any guest output image was drawn. + uint64_t guest_output_image_paint_last_submission = 0; + + // Current intermediate images for guest output painting, refreshed when + // painting guest output. + std::array, + kMaxGuestOutputPaintEffects - 1> + guest_output_intermediate_images; + // Created and destroyed alongside the images. UNORM only. + std::array + guest_output_intermediate_framebuffers = {}; + uint64_t guest_output_intermediate_image_last_submission = 0; + + // Command buffers optionally executed before the draw command buffer, + // outside the painting render pass. + std::vector ui_setup_command_buffers; + size_t ui_setup_command_buffer_current_index = SIZE_MAX; + + // Connection-specific. + + // May be reused between connections if the format stays the same. + VkRenderPass swapchain_render_pass = VK_NULL_HANDLE; + VkFormat swapchain_render_pass_format = VK_FORMAT_UNDEFINED; + bool swapchain_render_pass_clear_load_op = false; + + VkSurfaceKHR vulkan_surface = VK_NULL_HANDLE; + uint32_t present_queue_family = UINT32_MAX; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + VkExtent2D swapchain_extent = {}; + bool swapchain_is_fifo = false; + std::vector swapchain_images; + std::vector swapchain_framebuffers; + }; + + explicit VulkanPresenter(HostGpuLossCallback host_gpu_loss_callback, + VulkanProvider& provider) + : Presenter(host_gpu_loss_callback), + provider_(provider), + guest_output_image_refresher_submission_tracker_(provider), + ui_submission_tracker_(provider), + paint_context_(provider) {} + + bool InitializeSurfaceIndependent(); + + [[nodiscard]] VkPipeline CreateGuestOutputPaintPipeline( + GuestOutputPaintEffect effect, VkRenderPass render_pass); + + VulkanProvider& provider_; + + // Static objects for guest output presentation, used only when painting the + // main target (can be destroyed only after awaiting main target usage + // completion). + VkDescriptorSetLayout guest_output_paint_image_descriptor_set_layout_ = + VK_NULL_HANDLE; + std::array + guest_output_paint_pipeline_layouts_ = {}; + VkShaderModule guest_output_paint_vs_ = VK_NULL_HANDLE; + std::array + guest_output_paint_fs_ = {}; + // Not compatible with the swapchain render pass even if the format is the + // same due to different dependencies (this is shader read > color + // attachment > shader read). + VkRenderPass guest_output_intermediate_render_pass_ = VK_NULL_HANDLE; + + // Value monotonically increased every time a new guest output image is + // initialized, for recreation of dependent objects such as framebuffers in + // the refreshers - saving and comparing the handle in the refresher is not + // enough as Create > Destroy > Create may result in the same handle for + // actually different objects without the refresher being aware of the + // destruction. + uint64_t guest_output_image_next_version_ = 0; + std::array + guest_output_images_; + VulkanSubmissionTracker guest_output_image_refresher_submission_tracker_; + + // UI submission tracker with the submission index that can be given to UI + // drawers (accessible from the UI thread only, at any time). + VulkanSubmissionTracker ui_submission_tracker_; + + // Accessible only by painting and by surface connection lifetime management + // (ConnectOrReconnectPaintingToSurfaceFromUIThread, + // DisconnectPaintingFromSurfaceFromUIThreadImpl) by the thread doing it, as + // well as by presenter initialization and shutdown. + PaintContext paint_context_; +}; + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_D3D12_D3D12_PRESENTER_H_ diff --git a/src/xenia/ui/vulkan/vulkan_provider.cc b/src/xenia/ui/vulkan/vulkan_provider.cc index d67a5e263..5b1ef5794 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.cc +++ b/src/xenia/ui/vulkan/vulkan_provider.cc @@ -2,36 +2,74 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2022 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 +#include +#include +#include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #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" +#include "xenia/base/math.h" +#include "xenia/base/platform.h" +#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" +#include "xenia/ui/vulkan/vulkan_presenter.h" -DEFINE_uint64(vulkan_device_index, 0, "Index of the physical device to use.", - "Vulkan"); +#if XE_PLATFORM_LINUX +#include +#elif XE_PLATFORM_WIN32 +#include "xenia/base/platform_win.h" +#endif + +// Implement AMD's VMA here. +#define VMA_IMPLEMENTATION +#include "xenia/ui/vulkan/vulkan_mem_alloc.h" + +// TODO(Triang3l): Disable Vulkan validation before releasing a stable version. +DEFINE_bool( + vulkan_validation, true, + "Enable Vulkan validation (VK_LAYER_KHRONOS_validation). Messages will be " + "written to the OS debug log without vulkan_debug_messenger or to the " + "Xenia log with it.", + "Vulkan"); +DEFINE_bool( + vulkan_debug_utils_messenger, false, + "Enable writing Vulkan debug messages via VK_EXT_debug_utils to the Xenia " + "log.", + "Vulkan"); +DEFINE_uint32( + vulkan_debug_utils_messenger_severity, 2, + "Maximum severity of messages to log via the Vulkan debug messenger: 0 - " + "error, 1 - warning, 2 - info, 3 - verbose.", + "Vulkan"); +DEFINE_bool(vulkan_debug_utils_names, false, + "Enable naming Vulkan objects via VK_EXT_debug_utils.", "Vulkan"); +DEFINE_int32( + vulkan_device, -1, + "Index of the physical device to use, or -1 for any compatible device.", + "Vulkan"); namespace xe { namespace ui { namespace vulkan { -std::unique_ptr VulkanProvider::Create() { - std::unique_ptr provider(new VulkanProvider); +std::unique_ptr VulkanProvider::Create( + bool is_surface_required) { + std::unique_ptr provider( + new VulkanProvider(is_surface_required)); if (!provider->Initialize()) { xe::FatalError( "Unable to initialize Vulkan 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."); @@ -41,71 +79,1078 @@ std::unique_ptr VulkanProvider::Create() { } VulkanProvider::~VulkanProvider() { - device_.reset(); - instance_.reset(); + for (size_t i = 0; i < size_t(HostSampler::kCount); ++i) { + if (host_samplers_[i] != VK_NULL_HANDLE) { + dfn_.vkDestroySampler(device_, host_samplers_[i], nullptr); + } + } + + if (device_ != VK_NULL_HANDLE) { + ifn_.vkDestroyDevice(device_, nullptr); + } + if (instance_ != VK_NULL_HANDLE) { + if (debug_messenger_ != VK_NULL_HANDLE) { + ifn_.vkDestroyDebugUtilsMessengerEXT(instance_, debug_messenger_, + nullptr); + } + lfn_.vkDestroyInstance(instance_, nullptr); + } + +#if XE_PLATFORM_LINUX + if (library_) { + dlclose(library_); + } +#elif XE_PLATFORM_WIN32 + if (library_) { + FreeLibrary(library_); + } +#endif } bool VulkanProvider::Initialize() { - instance_ = std::make_unique(); + renderdoc_api_.Initialize(); - // Always enable the swapchain. -#if XE_PLATFORM_GNU_LINUX || XE_PLATFORM_WIN32 - instance_->DeclareRequiredExtension("VK_KHR_surface", Version::Make(0, 0, 0), - false); -#if XE_PLATFORM_GNU_LINUX - instance_->DeclareRequiredExtension("VK_KHR_xcb_surface", - Version::Make(0, 0, 0), false); + // Load the library. + bool library_functions_loaded = true; +#if XE_PLATFORM_LINUX +#if XE_PLATFORM_ANDROID + const char* libvulkan_name = "libvulkan.so"; +#else + const char* libvulkan_name = "libvulkan.so.1"; +#endif + // http://developer.download.nvidia.com/mobile/shield/assets/Vulkan/UsingtheVulkanAPI.pdf + library_ = dlopen(libvulkan_name, RTLD_NOW | RTLD_LOCAL); + if (!library_) { + XELOGE("Failed to load {}", libvulkan_name); + return false; + } +#define XE_VULKAN_LOAD_MODULE_LFN(name) \ + library_functions_loaded &= \ + (lfn_.name = PFN_##name(dlsym(library_, #name))) != nullptr; #elif XE_PLATFORM_WIN32 - instance_->DeclareRequiredExtension("VK_KHR_win32_surface", - Version::Make(0, 0, 0), false); -#endif + library_ = LoadLibraryA("vulkan-1.dll"); + if (!library_) { + XELOGE("Failed to load vulkan-1.dll"); + return false; + } +#define XE_VULKAN_LOAD_MODULE_LFN(name) \ + library_functions_loaded &= \ + (lfn_.name = PFN_##name(GetProcAddress(library_, #name))) != nullptr; +#else +#error No Vulkan library loading provided for the target platform. #endif + XE_VULKAN_LOAD_MODULE_LFN(vkGetInstanceProcAddr); + XE_VULKAN_LOAD_MODULE_LFN(vkDestroyInstance); +#undef XE_VULKAN_LOAD_MODULE_LFN + if (!library_functions_loaded) { + XELOGE("Failed to get Vulkan library function pointers"); + return false; + } + library_functions_loaded &= + (lfn_.vkCreateInstance = PFN_vkCreateInstance(lfn_.vkGetInstanceProcAddr( + VK_NULL_HANDLE, "vkCreateInstance"))) != nullptr; + library_functions_loaded &= + (lfn_.vkEnumerateInstanceExtensionProperties = + PFN_vkEnumerateInstanceExtensionProperties( + lfn_.vkGetInstanceProcAddr( + VK_NULL_HANDLE, + "vkEnumerateInstanceExtensionProperties"))) != nullptr; + library_functions_loaded &= + (lfn_.vkEnumerateInstanceLayerProperties = + PFN_vkEnumerateInstanceLayerProperties(lfn_.vkGetInstanceProcAddr( + VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"))) != + nullptr; + if (!library_functions_loaded) { + XELOGE( + "Failed to get Vulkan library function pointers via " + "vkGetInstanceProcAddr"); + return false; + } + lfn_.v_1_1.vkEnumerateInstanceVersion = PFN_vkEnumerateInstanceVersion( + lfn_.vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion")); - // Attempt initialization and device query. - if (!instance_->Initialize()) { - XELOGE("Failed to initialize vulkan instance"); + // Get the API version. + uint32_t instance_api_version; + if (!lfn_.v_1_1.vkEnumerateInstanceVersion || + lfn_.v_1_1.vkEnumerateInstanceVersion(&instance_api_version) != + VK_SUCCESS) { + instance_api_version = VK_API_VERSION_1_0; + } + XELOGVK("Vulkan instance version: {}.{}.{}", + VK_VERSION_MAJOR(instance_api_version), + VK_VERSION_MINOR(instance_api_version), + VK_VERSION_PATCH(instance_api_version)); + + // Get the instance extensions without layers, as well as extensions promoted + // to the core. + bool debug_utils_messenger_requested = cvars::vulkan_debug_utils_messenger; + bool debug_utils_names_requested = cvars::vulkan_debug_utils_names; + bool debug_utils_requested = + debug_utils_messenger_requested || debug_utils_names_requested; + std::memset(&instance_extensions_, 0, sizeof(instance_extensions_)); + if (instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { + instance_extensions_.khr_get_physical_device_properties2 = true; + } + std::vector instance_extensions_enabled; + std::vector instance_or_layer_extension_properties; + VkResult instance_extensions_enumerate_result; + for (;;) { + uint32_t instance_extension_count = + uint32_t(instance_or_layer_extension_properties.size()); + bool instance_extensions_were_empty = !instance_extension_count; + instance_extensions_enumerate_result = + lfn_.vkEnumerateInstanceExtensionProperties( + nullptr, &instance_extension_count, + instance_extensions_were_empty + ? nullptr + : instance_or_layer_extension_properties.data()); + // If the original extension count was 0 (first call), SUCCESS is returned, + // not INCOMPLETE. + if (instance_extensions_enumerate_result == VK_SUCCESS || + instance_extensions_enumerate_result == VK_INCOMPLETE) { + instance_or_layer_extension_properties.resize(instance_extension_count); + if (instance_extensions_enumerate_result == VK_SUCCESS && + (!instance_extensions_were_empty || !instance_extension_count)) { + break; + } + } else { + break; + } + } + if (instance_extensions_enumerate_result == VK_SUCCESS) { + AccumulateInstanceExtensions(instance_or_layer_extension_properties.size(), + instance_or_layer_extension_properties.data(), + debug_utils_requested, instance_extensions_, + instance_extensions_enabled); + } + size_t instance_extensions_enabled_count_without_layers = + instance_extensions_enabled.size(); + InstanceExtensions instance_extensions_without_layers = instance_extensions_; + + // Get the instance layers and their extensions. + std::vector layer_properties; + VkResult layers_enumerate_result; + for (;;) { + uint32_t layer_count = uint32_t(layer_properties.size()); + bool layers_were_empty = !layer_count; + layers_enumerate_result = lfn_.vkEnumerateInstanceLayerProperties( + &layer_count, layers_were_empty ? nullptr : layer_properties.data()); + // If the original layer count was 0 (first call), SUCCESS is returned, not + // INCOMPLETE. + if (layers_enumerate_result == VK_SUCCESS || + layers_enumerate_result == VK_INCOMPLETE) { + layer_properties.resize(layer_count); + if (layers_enumerate_result == VK_SUCCESS && + (!layers_were_empty || !layer_count)) { + break; + } + } else { + break; + } + } + if (layers_enumerate_result != VK_SUCCESS) { + layer_properties.clear(); + } + struct { + bool khronos_validation; + } layer_enabled_flags = {}; + std::vector layers_enabled; + for (const VkLayerProperties& layer : layer_properties) { + // Check if the layer is needed. + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons. Adding literals to layers_enabled for the most C + // string lifetime safety. + if (!layer_enabled_flags.khronos_validation && cvars::vulkan_validation && + !std::strcmp(layer.layerName, "VK_LAYER_KHRONOS_validation")) { + layers_enabled.push_back("VK_LAYER_KHRONOS_validation"); + layer_enabled_flags.khronos_validation = true; + } else { + // Not enabling this layer, so don't need the extensions from it as well. + continue; + } + // Load extensions from the layer. + instance_or_layer_extension_properties.clear(); + for (;;) { + uint32_t instance_extension_count = + uint32_t(instance_or_layer_extension_properties.size()); + bool instance_extensions_were_empty = !instance_extension_count; + instance_extensions_enumerate_result = + lfn_.vkEnumerateInstanceExtensionProperties( + layer.layerName, &instance_extension_count, + instance_extensions_were_empty + ? nullptr + : instance_or_layer_extension_properties.data()); + // If the original extension count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (instance_extensions_enumerate_result == VK_SUCCESS || + instance_extensions_enumerate_result == VK_INCOMPLETE) { + instance_or_layer_extension_properties.resize(instance_extension_count); + if (instance_extensions_enumerate_result == VK_SUCCESS && + (!instance_extensions_were_empty || !instance_extension_count)) { + break; + } + } else { + break; + } + } + if (instance_extensions_enumerate_result == VK_SUCCESS) { + AccumulateInstanceExtensions( + instance_or_layer_extension_properties.size(), + instance_or_layer_extension_properties.data(), debug_utils_requested, + instance_extensions_, instance_extensions_enabled); + } + } + + // Create the instance. + 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 = nullptr; + application_info.engineVersion = 0; + // "apiVersion must be the highest version of Vulkan that the application is + // designed to use" + // "Vulkan 1.0 implementations were required to return + // VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0" + application_info.apiVersion = + instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0) + ? VK_HEADER_VERSION_COMPLETE + : instance_api_version; + VkInstanceCreateInfo instance_create_info; + instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instance_create_info.pNext = nullptr; + instance_create_info.flags = 0; + instance_create_info.pApplicationInfo = &application_info; + instance_create_info.enabledLayerCount = uint32_t(layers_enabled.size()); + instance_create_info.ppEnabledLayerNames = layers_enabled.data(); + instance_create_info.enabledExtensionCount = + uint32_t(instance_extensions_enabled.size()); + instance_create_info.ppEnabledExtensionNames = + instance_extensions_enabled.data(); + VkResult instance_create_result = + lfn_.vkCreateInstance(&instance_create_info, nullptr, &instance_); + if (instance_create_result != VK_SUCCESS) { + if ((instance_create_result == VK_ERROR_LAYER_NOT_PRESENT || + instance_create_result == VK_ERROR_EXTENSION_NOT_PRESENT) && + !layers_enabled.empty()) { + XELOGE("Failed to enable Vulkan layers"); + // Try to create without layers and their extensions. + std::memset(&layer_enabled_flags, 0, sizeof(layer_enabled_flags)); + instance_create_info.enabledLayerCount = 0; + instance_create_info.ppEnabledLayerNames = nullptr; + instance_create_info.enabledExtensionCount = + uint32_t(instance_extensions_enabled_count_without_layers); + instance_extensions_ = instance_extensions_without_layers; + instance_create_result = + lfn_.vkCreateInstance(&instance_create_info, nullptr, &instance_); + } + if (instance_create_result != VK_SUCCESS) { + XELOGE("Failed to create a Vulkan instance"); + return false; + } + } + + // Get instance functions. + std::memset(&ifn_, 0, sizeof(ifn_)); +#define XE_UI_VULKAN_FUNCTION(name) \ + functions_loaded &= (ifn_.name = PFN_##name(lfn_.vkGetInstanceProcAddr( \ + instance_, #name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_DONT_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (ifn_.extension_name = PFN_##extension_name(lfn_.vkGetInstanceProcAddr( \ + instance_, #extension_name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (ifn_.extension_name = PFN_##extension_name( \ + lfn_.vkGetInstanceProcAddr(instance_, #core_name))) != nullptr; + // Core - require unconditionally. + { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_1_0.inc" + if (!functions_loaded) { + XELOGE("Failed to get Vulkan instance function pointers"); + return false; + } + } + // Extensions - disable the specific extension if failed to get its functions. + if (instance_extensions_.ext_debug_utils) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_ext_debug_utils.inc" + instance_extensions_.ext_debug_utils = functions_loaded; + } + if (instance_extensions_.khr_get_physical_device_properties2) { + bool functions_loaded = true; + if (instance_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_PROMOTE +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } else { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } + instance_extensions_.khr_get_physical_device_properties2 = functions_loaded; + } + if (instance_extensions_.khr_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" + instance_extensions_.khr_surface = functions_loaded; + } +#if XE_PLATFORM_ANDROID + if (instance_extensions_.khr_android_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" + instance_extensions_.khr_android_surface = functions_loaded; + } +#elif XE_PLATFORM_GNU_LINUX + if (instance_extensions_.khr_xcb_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" + instance_extensions_.khr_xcb_surface = functions_loaded; + } +#elif XE_PLATFORM_WIN32 + if (instance_extensions_.khr_win32_surface) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" + instance_extensions_.khr_win32_surface = functions_loaded; + } +#endif // XE_PLATFORM +#undef XE_UI_VULKAN_FUNCTION_PROMOTE +#undef XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#undef XE_UI_VULKAN_FUNCTION + + // Check if surface is supported after verifying that surface extension + // function pointers could be obtained. + if (is_surface_required_ && + !VulkanPresenter::GetSurfaceTypesSupportedByInstance( + instance_extensions_)) { + XELOGE( + "The Vulkan instance doesn't support the required surface extension " + "for the platform"); return false; } - // Pick the device to use. - auto available_devices = instance_->available_devices(); - if (available_devices.empty()) { - XELOGE("No devices available for use"); + // Report instance information after verifying that extension function + // pointers could be obtained. + XELOGVK("Vulkan layers enabled by Xenia:"); + XELOGVK("* VK_LAYER_KHRONOS_validation: {}", + layer_enabled_flags.khronos_validation ? "yes" : "no"); + XELOGVK("Vulkan instance extensions:"); + XELOGVK("* VK_EXT_debug_utils: {}", + instance_extensions_.ext_debug_utils + ? "yes" + : (debug_utils_requested ? "no" : "not requested")); + XELOGVK( + "* VK_KHR_get_physical_device_properties2: {}", + instance_extensions_.khr_get_physical_device_properties2 ? "yes" : "no"); + XELOGVK("* VK_KHR_surface: {}", + instance_extensions_.khr_surface ? "yes" : "no"); +#if XE_PLATFORM_ANDROID + XELOGVK(" * VK_KHR_android_surface: {}", + instance_extensions_.khr_android_surface ? "yes" : "no"); +#elif XE_PLATFORM_GNU_LINUX + XELOGVK(" * VK_KHR_xcb_surface: {}", + instance_extensions_.khr_xcb_surface ? "yes" : "no"); +#elif XE_PLATFORM_WIN32 + XELOGVK(" * VK_KHR_win32_surface: {}", + instance_extensions_.khr_win32_surface ? "yes" : "no"); +#endif + + // Enable the debug messenger. + if (debug_utils_messenger_requested) { + if (instance_extensions_.ext_debug_utils) { + VkDebugUtilsMessengerCreateInfoEXT debug_messenger_create_info; + debug_messenger_create_info.sType = + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debug_messenger_create_info.pNext = nullptr; + debug_messenger_create_info.flags = 0; + debug_messenger_create_info.messageSeverity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 1) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 2) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT; + if (cvars::vulkan_debug_utils_messenger_severity >= 3) { + debug_messenger_create_info.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; + } + } + } + debug_messenger_create_info.messageType = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + debug_messenger_create_info.pfnUserCallback = DebugMessengerCallback; + debug_messenger_create_info.pUserData = this; + ifn_.vkCreateDebugUtilsMessengerEXT( + instance_, &debug_messenger_create_info, nullptr, &debug_messenger_); + } + if (debug_messenger_ != VK_NULL_HANDLE) { + XELOGVK("Vulkan debug messenger enabled"); + } else { + XELOGE("Failed to enable the Vulkan debug messenger"); + } + } + debug_names_used_ = + debug_utils_names_requested && instance_extensions_.ext_debug_utils; + + // Get the compatible physical device. + std::vector physical_devices; + for (;;) { + uint32_t physical_device_count = uint32_t(physical_devices.size()); + bool physical_devices_were_empty = !physical_device_count; + VkResult physical_device_enumerate_result = ifn_.vkEnumeratePhysicalDevices( + instance_, &physical_device_count, + physical_devices_were_empty ? nullptr : physical_devices.data()); + // If the original device count was 0 (first call), SUCCESS is returned, not + // INCOMPLETE. + if (physical_device_enumerate_result == VK_SUCCESS || + physical_device_enumerate_result == VK_INCOMPLETE) { + physical_devices.resize(physical_device_count); + if (physical_device_enumerate_result == VK_SUCCESS && + (!physical_devices_were_empty || !physical_device_count)) { + break; + } + } else { + XELOGE("Failed to enumerate Vulkan physical devices"); + return false; + } + } + if (physical_devices.empty()) { + XELOGE("No Vulkan physical devices are available"); return false; } - size_t device_index = - std::min(available_devices.size(), cvars::vulkan_device_index); - auto& device_info = available_devices[device_index]; + size_t physical_device_index_first, physical_device_index_last; + if (cvars::vulkan_device >= 0) { + physical_device_index_first = uint32_t(cvars::vulkan_device); + physical_device_index_last = physical_device_index_first; + if (physical_device_index_first >= physical_devices.size()) { + XELOGE( + "vulkan_device config variable is out of range, {} devices are " + "available", + physical_devices.size()); + return false; + } + } else { + physical_device_index_first = 0; + physical_device_index_last = physical_devices.size() - 1; + } + physical_device_ = VK_NULL_HANDLE; + std::vector queue_families_properties; + std::vector device_extension_properties; + std::vector device_extensions_enabled; + for (size_t i = physical_device_index_first; i <= physical_device_index_last; + ++i) { + VkPhysicalDevice physical_device_current = physical_devices[i]; + + // Get physical device features and check if the needed ones are supported. + // Need this before obtaining the queues as sparse binding is an optional + // feature. + ifn_.vkGetPhysicalDeviceFeatures(physical_device_current, + &device_features_); + // Passing indices directly from guest memory, where they are big-endian; a + // workaround using fetch from shared memory for 32-bit indices that need + // swapping isn't implemented yet. Not supported only Qualcomm Adreno 4xx. + if (!device_features_.fullDrawIndexUint32) { + continue; + } + // TODO(Triang3l): Make geometry shaders optional by providing compute + // shader fallback (though that would require vertex shader stores). + if (!device_features_.geometryShader) { + continue; + } + + // Get the needed queues: + // - Graphics and compute. + // - Sparse binding if used (preferably the same as the graphics and compute + // one for the lowest latency as Xenia submits sparse binding commands + // right before graphics commands anyway). + // - Additional queues for presentation as VulkanProvider may be used with + // different surfaces, and they may have varying support of presentation + // from different queue families. + uint32_t queue_family_count = 0; + ifn_.vkGetPhysicalDeviceQueueFamilyProperties(physical_device_current, + &queue_family_count, nullptr); + queue_families_properties.resize(queue_family_count); + ifn_.vkGetPhysicalDeviceQueueFamilyProperties( + physical_device_current, &queue_family_count, + queue_families_properties.data()); + assert_true(queue_family_count == queue_families_properties.size()); + // Initialize all queue families to unused. + queue_families_.clear(); + queue_families_.resize(queue_family_count); + // First, try to obtain a graphics and compute queue. Preferably find a + // queue with sparse binding support as well. + // The family indices here are listed from the best to the worst. + uint32_t queue_family_graphics_compute_sparse_binding = UINT32_MAX; + uint32_t queue_family_graphics_compute_only = UINT32_MAX; + for (uint32_t j = 0; j < queue_family_count; ++j) { + const VkQueueFamilyProperties& queue_family_properties = + queue_families_properties[j]; + if ((queue_family_properties.queueFlags & + (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) != + (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) { + continue; + } + uint32_t* queue_family_ptr; + if (device_features_.sparseBinding && + (queue_family_properties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)) { + queue_family_ptr = &queue_family_graphics_compute_sparse_binding; + } else { + queue_family_ptr = &queue_family_graphics_compute_only; + } + if (*queue_family_ptr == UINT32_MAX) { + *queue_family_ptr = j; + } + } + if (queue_family_graphics_compute_sparse_binding != UINT32_MAX) { + assert_true(device_features_.sparseBinding); + queue_family_graphics_compute_ = + queue_family_graphics_compute_sparse_binding; + } else if (queue_family_graphics_compute_only != UINT32_MAX) { + queue_family_graphics_compute_ = queue_family_graphics_compute_only; + } else { + // No graphics and compute queue family. + continue; + } + // Mark the graphics and compute queue as requested. + queue_families_[queue_family_graphics_compute_].queue_count = + std::max(queue_families_[queue_family_graphics_compute_].queue_count, + uint32_t(1)); + // Request a separate sparse binding queue if needed. + queue_family_sparse_binding_ = UINT32_MAX; + if (device_features_.sparseBinding) { + if (queue_families_properties[queue_family_graphics_compute_].queueFlags & + VK_QUEUE_SPARSE_BINDING_BIT) { + queue_family_sparse_binding_ = queue_family_graphics_compute_; + } else { + for (uint32_t j = 0; j < queue_family_count; ++j) { + if (!(queue_families_properties[j].queueFlags & + VK_QUEUE_SPARSE_BINDING_BIT)) { + continue; + } + queue_family_sparse_binding_ = j; + queue_families_[j].queue_count = + std::max(queue_families_[j].queue_count, uint32_t(1)); + break; + } + } + // Don't expose, and disable during logical device creature, the sparse + // binding feature if failed to obtain a queue supporting it. + if (queue_family_sparse_binding_ == UINT32_MAX) { + device_features_.sparseBinding = VK_FALSE; + } + } + bool any_queue_potentially_supports_present = false; + if (instance_extensions_.khr_surface) { + // Request possible presentation queues. + for (uint32_t j = 0; j < queue_family_count; ++j) { +#if XE_PLATFORM_WIN32 + if (instance_extensions_.khr_win32_surface && + !ifn_.vkGetPhysicalDeviceWin32PresentationSupportKHR( + physical_device_current, j)) { + continue; + } +#endif + any_queue_potentially_supports_present = true; + QueueFamily& queue_family = queue_families_[j]; + queue_family.queue_count = + std::max(queue_families_[j].queue_count, uint32_t(1)); + queue_family.potentially_supports_present = true; + } + } + if (!any_queue_potentially_supports_present && is_surface_required_) { + continue; + } + + // Get device properties, will be needed to check if extensions have been + // promoted to core. + ifn_.vkGetPhysicalDeviceProperties(physical_device_current, + &device_properties_); + + // Get the extensions, check if swapchain is supported. + device_extension_properties.clear(); + VkResult device_extensions_enumerate_result; + for (;;) { + uint32_t device_extension_count = + uint32_t(device_extension_properties.size()); + bool device_extensions_were_empty = !device_extension_count; + device_extensions_enumerate_result = + ifn_.vkEnumerateDeviceExtensionProperties( + physical_device_current, nullptr, &device_extension_count, + device_extensions_were_empty + ? nullptr + : device_extension_properties.data()); + // If the original extension count was 0 (first call), SUCCESS is + // returned, not INCOMPLETE. + if (device_extensions_enumerate_result == VK_SUCCESS || + device_extensions_enumerate_result == VK_INCOMPLETE) { + device_extension_properties.resize(device_extension_count); + if (device_extensions_enumerate_result == VK_SUCCESS && + (!device_extensions_were_empty || !device_extension_count)) { + break; + } + } else { + break; + } + } + if (device_extensions_enumerate_result != VK_SUCCESS) { + continue; + } + std::memset(&device_extensions_, 0, sizeof(device_extensions_)); + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { + device_extensions_.khr_dedicated_allocation = true; + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)) { + device_extensions_.khr_image_format_list = true; + device_extensions_.khr_shader_float_controls = true; + device_extensions_.khr_spirv_1_4 = true; + } + } + device_extensions_enabled.clear(); + for (const VkExtensionProperties& device_extension : + device_extension_properties) { + const char* device_extension_name = device_extension.extensionName; + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons, as well as to skip adding extensions promoted to + // the core to device_extensions_enabled. Adding literals to + // device_extensions_enabled for the most C string lifetime safety. + if (!device_extensions_.amd_shader_info && + !std::strcmp(device_extension_name, "VK_AMD_shader_info")) { + device_extensions_enabled.push_back("VK_AMD_shader_info"); + device_extensions_.amd_shader_info = true; + } else if (!device_extensions_.ext_fragment_shader_interlock && + !std::strcmp(device_extension_name, + "VK_EXT_fragment_shader_interlock")) { + device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock"); + device_extensions_.ext_fragment_shader_interlock = true; + } else if (!device_extensions_.khr_dedicated_allocation && + !std::strcmp(device_extension_name, + "VK_KHR_dedicated_allocation")) { + device_extensions_enabled.push_back("VK_KHR_dedicated_allocation"); + device_extensions_.khr_dedicated_allocation = true; + } else if (!device_extensions_.khr_image_format_list && + !std::strcmp(device_extension_name, + "VK_KHR_image_format_list")) { + device_extensions_enabled.push_back("VK_KHR_image_format_list"); + device_extensions_.khr_image_format_list = true; + } else if (!device_extensions_.khr_shader_float_controls && + !std::strcmp(device_extension_name, + "VK_KHR_shader_float_controls")) { + device_extensions_enabled.push_back("VK_KHR_shader_float_controls"); + device_extensions_.khr_shader_float_controls = true; + } else if (!device_extensions_.khr_spirv_1_4 && + !std::strcmp(device_extension_name, "VK_KHR_spirv_1_4")) { + device_extensions_enabled.push_back("VK_KHR_spirv_1_4"); + device_extensions_.khr_spirv_1_4 = true; + } else if (!device_extensions_.khr_swapchain && + !std::strcmp(device_extension_name, "VK_KHR_swapchain")) { + device_extensions_enabled.push_back("VK_KHR_swapchain"); + device_extensions_.khr_swapchain = true; + } + } + if (is_surface_required_ && !device_extensions_.khr_swapchain) { + continue; + } + + // Get the memory types. + VkPhysicalDeviceMemoryProperties memory_properties; + ifn_.vkGetPhysicalDeviceMemoryProperties(physical_device_current, + &memory_properties); + memory_types_device_local_ = 0; + memory_types_host_visible_ = 0; + memory_types_host_coherent_ = 0; + memory_types_host_cached_ = 0; + for (uint32_t j = 0; j < memory_properties.memoryTypeCount; ++j) { + VkMemoryPropertyFlags memory_property_flags = + memory_properties.memoryTypes[j].propertyFlags; + uint32_t memory_type_bit = uint32_t(1) << j; + if (memory_property_flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { + memory_types_device_local_ |= memory_type_bit; + } + if (memory_property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + memory_types_host_visible_ |= memory_type_bit; + } + if (memory_property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { + memory_types_host_coherent_ |= memory_type_bit; + } + if (memory_property_flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) { + memory_types_host_cached_ |= memory_type_bit; + } + } + if (!memory_types_device_local_ && !memory_types_host_visible_) { + // Shouldn't happen according to the specification. + continue; + } + + physical_device_ = physical_device_current; + break; + } + if (physical_device_ == VK_NULL_HANDLE) { + XELOGE( + "Failed to get a compatible Vulkan physical device with swapchain " + "support"); + return false; + } + + // Get additional device properties. + std::memset(&device_float_controls_properties_, 0, + sizeof(device_float_controls_properties_)); + if (instance_extensions_.khr_get_physical_device_properties2) { + VkPhysicalDeviceProperties2KHR device_properties_2; + device_properties_2.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; + device_properties_2.pNext = nullptr; + VkPhysicalDeviceProperties2KHR* device_properties_2_last = + &device_properties_2; + if (device_extensions_.khr_shader_float_controls) { + device_float_controls_properties_.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR; + device_float_controls_properties_.pNext = nullptr; + device_properties_2_last->pNext = &device_float_controls_properties_; + device_properties_2_last = + reinterpret_cast( + &device_float_controls_properties_); + } + if (device_properties_2_last != &device_properties_2) { + ifn_.vkGetPhysicalDeviceProperties2KHR(physical_device_, + &device_properties_2); + } + } // 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"); + std::vector queue_create_infos; + queue_create_infos.reserve(queue_families_.size()); + uint32_t used_queue_count = 0; + uint32_t max_queue_count_per_family = 0; + for (size_t i = 0; i < queue_families_.size(); ++i) { + QueueFamily& queue_family = queue_families_[i]; + queue_family.queue_first_index = used_queue_count; + if (!queue_family.queue_count) { + continue; + } + VkDeviceQueueCreateInfo& queue_create_info = + queue_create_infos.emplace_back(); + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.pNext = nullptr; + queue_create_info.flags = 0; + queue_create_info.queueFamilyIndex = uint32_t(i); + queue_create_info.queueCount = queue_family.queue_count; + // pQueuePriorities will be set later based on max_queue_count_per_family. + max_queue_count_per_family = + std::max(max_queue_count_per_family, queue_family.queue_count); + used_queue_count += queue_family.queue_count; + } + std::vector queue_priorities; + queue_priorities.resize(max_queue_count_per_family, 1.0f); + for (VkDeviceQueueCreateInfo& queue_create_info : queue_create_infos) { + queue_create_info.pQueuePriorities = queue_priorities.data(); + } + VkDeviceCreateInfo device_create_info; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.pNext = nullptr; + device_create_info.flags = 0; + device_create_info.queueCreateInfoCount = uint32_t(queue_create_infos.size()); + device_create_info.pQueueCreateInfos = queue_create_infos.data(); + // Device layers are deprecated - using validation layer on the instance. + device_create_info.enabledLayerCount = 0; + device_create_info.ppEnabledLayerNames = nullptr; + device_create_info.enabledExtensionCount = + uint32_t(device_extensions_enabled.size()); + device_create_info.ppEnabledExtensionNames = device_extensions_enabled.data(); + // TODO(Triang3l): Enable only needed features. + device_create_info.pEnabledFeatures = &device_features_; + if (ifn_.vkCreateDevice(physical_device_, &device_create_info, nullptr, + &device_) != VK_SUCCESS) { + XELOGE("Failed to create a Vulkan device"); + return false; + } + + // Get device functions. + std::memset(&dfn_, 0, sizeof(ifn_)); + bool device_functions_loaded = true; +#define XE_UI_VULKAN_FUNCTION(name) \ + functions_loaded &= \ + (dfn_.name = PFN_##name(ifn_.vkGetDeviceProcAddr(device_, #name))) != \ + nullptr; +#define XE_UI_VULKAN_FUNCTION_DONT_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (dfn_.extension_name = PFN_##extension_name( \ + ifn_.vkGetDeviceProcAddr(device_, #extension_name))) != nullptr; +#define XE_UI_VULKAN_FUNCTION_PROMOTE(extension_name, core_name) \ + functions_loaded &= \ + (dfn_.extension_name = PFN_##extension_name( \ + ifn_.vkGetDeviceProcAddr(device_, #core_name))) != nullptr; + // Core - require unconditionally. + { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/device_1_0.inc" + if (!functions_loaded) { + XELOGE("Failed to get Vulkan device function pointers"); + return false; + } + } + // Extensions - disable the specific extension if failed to get its functions. + if (device_extensions_.amd_shader_info) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/device_amd_shader_info.inc" + device_extensions_.amd_shader_info = functions_loaded; + } + if (device_extensions_.khr_swapchain) { + bool functions_loaded = true; +#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" + if (!functions_loaded) { + // Outside the physical device selection loop, so can't just skip the + // device anymore, but this shouldn't really happen anyway. + XELOGE( + "Failed to get Vulkan swapchain function pointers while swapchain " + "support is required"); + return false; + } + device_extensions_.khr_swapchain = functions_loaded; + } +#undef XE_UI_VULKAN_FUNCTION_PROMOTE +#undef XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#undef XE_UI_VULKAN_FUNCTION + if (!device_functions_loaded) { + XELOGE("Failed to get Vulkan device function pointers"); + return false; + } + + // Report device information after verifying that extension function pointers + // could be obtained. + XELOGVK( + "Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API " + "{}.{}.{})", + device_properties_.deviceName, device_properties_.vendorID, + device_properties_.deviceID, device_properties_.driverVersion, + VK_VERSION_MAJOR(device_properties_.apiVersion), + VK_VERSION_MINOR(device_properties_.apiVersion), + VK_VERSION_PATCH(device_properties_.apiVersion)); + XELOGVK("Vulkan device extensions:"); + XELOGVK("* VK_AMD_shader_info: {}", + device_extensions_.amd_shader_info ? "yes" : "no"); + XELOGVK("* VK_EXT_fragment_shader_interlock: {}", + device_extensions_.ext_fragment_shader_interlock ? "yes" : "no"); + XELOGVK("* VK_KHR_dedicated_allocation: {}", + device_extensions_.khr_dedicated_allocation ? "yes" : "no"); + XELOGVK("* VK_KHR_image_format_list: {}", + device_extensions_.khr_image_format_list ? "yes" : "no"); + XELOGVK("* VK_KHR_shader_float_controls: {}", + device_extensions_.khr_shader_float_controls ? "yes" : "no"); + if (device_extensions_.khr_shader_float_controls) { + XELOGVK( + " * Signed zero, inf, nan preserve for float32: {}", + device_float_controls_properties_.shaderSignedZeroInfNanPreserveFloat32 + ? "yes" + : "no"); + XELOGVK(" * Denorm flush to zero for float32: {}", + device_float_controls_properties_.shaderDenormFlushToZeroFloat32 + ? "yes" + : "no"); + XELOGVK("* VK_KHR_spirv_1_4: {}", + device_extensions_.khr_spirv_1_4 ? "yes" : "no"); + XELOGVK("* VK_KHR_swapchain: {}", + device_extensions_.khr_swapchain ? "yes" : "no"); + } + // TODO(Triang3l): Report properties, features. + + // Get the queues. + queues_.reset(); + queues_ = std::make_unique(used_queue_count); + uint32_t queue_index = 0; + for (size_t i = 0; i < queue_families_.size(); ++i) { + const QueueFamily& queue_family = queue_families_[i]; + if (!queue_family.queue_count) { + continue; + } + assert_true(queue_index == queue_family.queue_first_index); + for (uint32_t j = 0; j < queue_family.queue_count; ++j) { + VkQueue queue; + dfn_.vkGetDeviceQueue(device_, uint32_t(i), j, &queue); + queues_[queue_index++].queue = queue; + } + } + + // Create host-side samplers. + VkSamplerCreateInfo sampler_create_info = {}; + sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_create_info.magFilter = VK_FILTER_NEAREST; + sampler_create_info.minFilter = VK_FILTER_NEAREST; + sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.maxLod = FLT_MAX; + if (dfn_.vkCreateSampler( + device_, &sampler_create_info, nullptr, + &host_samplers_[size_t(HostSampler::kNearestClamp)]) != VK_SUCCESS) { + XELOGE("Failed to create the nearest-neighbor clamping Vulkan sampler"); + return false; + } + sampler_create_info.magFilter = VK_FILTER_LINEAR; + sampler_create_info.minFilter = VK_FILTER_LINEAR; + sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + if (dfn_.vkCreateSampler( + device_, &sampler_create_info, nullptr, + &host_samplers_[size_t(HostSampler::kLinearClamp)]) != VK_SUCCESS) { + XELOGE("Failed to create the bilinear-filtering clamping Vulkan sampler"); + return false; + } + sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + if (dfn_.vkCreateSampler( + device_, &sampler_create_info, nullptr, + &host_samplers_[size_t(HostSampler::kLinearRepeat)]) != VK_SUCCESS) { + XELOGE("Failed to create the bilinear-filtering repeating Vulkan sampler"); + return false; + } + sampler_create_info.magFilter = VK_FILTER_NEAREST; + sampler_create_info.minFilter = VK_FILTER_NEAREST; + sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + if (dfn_.vkCreateSampler( + device_, &sampler_create_info, nullptr, + &host_samplers_[size_t(HostSampler::kNearestRepeat)]) != VK_SUCCESS) { + XELOGE("Failed to create the nearest-neighbor repeating Vulkan sampler"); return false; } return true; } -std::unique_ptr VulkanProvider::CreateContext( - Window* target_window) { - auto new_context = - std::unique_ptr(new VulkanContext(this, target_window)); - if (!new_context->Initialize()) { - return nullptr; - } - return std::unique_ptr(new_context.release()); +std::unique_ptr VulkanProvider::CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback) { + return VulkanPresenter::Create(host_gpu_loss_callback, *this); } -std::unique_ptr VulkanProvider::CreateOffscreenContext() { - auto new_context = - std::unique_ptr(new VulkanContext(this, nullptr)); - if (!new_context->Initialize()) { - return nullptr; +std::unique_ptr VulkanProvider::CreateImmediateDrawer() { + return VulkanImmediateDrawer::Create(*this); +} + +void VulkanProvider::SetDeviceObjectName(VkObjectType type, uint64_t handle, + const char* name) const { + if (!debug_names_used_) { + return; } - return std::unique_ptr(new_context.release()); + VkDebugUtilsObjectNameInfoEXT name_info; + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.pNext = nullptr; + name_info.objectType = type; + name_info.objectHandle = handle; + name_info.pObjectName = name; + ifn_.vkSetDebugUtilsObjectNameEXT(device_, &name_info); +} + +void VulkanProvider::AccumulateInstanceExtensions( + size_t properties_count, const VkExtensionProperties* properties, + bool request_debug_utils, InstanceExtensions& instance_extensions, + std::vector& instance_extensions_enabled) { + for (size_t i = 0; i < properties_count; ++i) { + const char* instance_extension_name = properties[i].extensionName; + // Checking if already enabled as an optimization to do fewer and fewer + // string comparisons, as well as to skip adding extensions promoted to the + // core to instance_extensions_enabled. Adding literals to + // instance_extensions_enabled for the most C string lifetime safety. + if (request_debug_utils && !instance_extensions.ext_debug_utils && + !std::strcmp(instance_extension_name, "VK_EXT_debug_utils")) { + // Debug utilities are only enabled when needed. Overhead in Xenia not + // profiled, but better to avoid unless enabled by the user. + instance_extensions_enabled.push_back("VK_EXT_debug_utils"); + instance_extensions.ext_debug_utils = true; + } else if (!instance_extensions.khr_get_physical_device_properties2 && + !std::strcmp(instance_extension_name, + "VK_KHR_get_physical_device_properties2")) { + instance_extensions_enabled.push_back( + "VK_KHR_get_physical_device_properties2"); + instance_extensions.khr_get_physical_device_properties2 = true; + } else if (!instance_extensions.khr_surface && + !std::strcmp(instance_extension_name, "VK_KHR_surface")) { + instance_extensions_enabled.push_back("VK_KHR_surface"); + instance_extensions.khr_surface = true; + } else { +#if XE_PLATFORM_ANDROID + if (!instance_extensions.khr_android_surface && + !std::strcmp(instance_extension_name, "VK_KHR_android_surface")) { + instance_extensions_enabled.push_back("VK_KHR_android_surface"); + instance_extensions.khr_android_surface = true; + } +#elif XE_PLATFORM_GNU_LINUX + if (!instance_extensions.khr_xcb_surface && + !std::strcmp(instance_extension_name, "VK_KHR_xcb_surface")) { + instance_extensions_enabled.push_back("VK_KHR_xcb_surface"); + instance_extensions.khr_xcb_surface = true; + } +#elif XE_PLATFORM_WIN32 + if (!instance_extensions.khr_win32_surface && + !std::strcmp(instance_extension_name, "VK_KHR_win32_surface")) { + instance_extensions_enabled.push_back("VK_KHR_win32_surface"); + instance_extensions.khr_win32_surface = true; + } +#endif + } + } +} + +VkBool32 VKAPI_CALL VulkanProvider::DebugMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_types, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data) { + const char* severity_string; + switch (message_severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + severity_string = "verbose output"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + severity_string = "info"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + severity_string = "warning"; + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + severity_string = "error"; + break; + default: + switch (xe::bit_count(uint32_t(message_severity))) { + case 0: + severity_string = "no-severity"; + break; + case 1: + severity_string = "unknown-severity"; + break; + default: + severity_string = "multi-severity"; + } + } + const char* type_string; + switch (message_types) { + case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: + type_string = "general"; + break; + case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: + type_string = "validation"; + break; + case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: + type_string = "performance"; + break; + default: + switch (xe::bit_count(uint32_t(message_types))) { + case 0: + type_string = "no-type"; + break; + case 1: + type_string = "unknown-type"; + break; + default: + type_string = "multi-type"; + } + } + XELOGVK("Vulkan {} {}: {}", type_string, severity_string, + callback_data->pMessage); + return VK_FALSE; } } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_provider.h b/src/xenia/ui/vulkan/vulkan_provider.h index 12c303785..15884c93e 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 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,37 +10,282 @@ #ifndef XENIA_UI_VULKAN_VULKAN_PROVIDER_H_ #define XENIA_UI_VULKAN_VULKAN_PROVIDER_H_ +#include +#include #include +#include +#include +#include +#include "xenia/base/assert.h" +#include "xenia/base/platform.h" #include "xenia/ui/graphics_provider.h" +#include "xenia/ui/renderdoc_api.h" + +#if XE_PLATFORM_ANDROID +#ifndef VK_USE_PLATFORM_ANDROID_KHR +#define VK_USE_PLATFORM_ANDROID_KHR 1 +#endif +#elif XE_PLATFORM_GNU_LINUX +#ifndef VK_USE_PLATFORM_XCB_KHR +#define VK_USE_PLATFORM_XCB_KHR 1 +#endif +#elif XE_PLATFORM_WIN32 +// Must be included before vulkan.h with VK_USE_PLATFORM_WIN32_KHR because it +// includes Windows.h too. +#include "xenia/base/platform_win.h" +#ifndef VK_USE_PLATFORM_WIN32_KHR +#define VK_USE_PLATFORM_WIN32_KHR 1 +#endif +#endif + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES 1 +#endif +#include "third_party/vulkan/vulkan.h" + +#define XELOGVK XELOGI + +#define XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES 1 namespace xe { namespace ui { namespace vulkan { -class VulkanDevice; -class VulkanInstance; - class VulkanProvider : public GraphicsProvider { public: - ~VulkanProvider() override; + ~VulkanProvider(); - static std::unique_ptr Create(); + static std::unique_ptr Create(bool is_surface_required); - VulkanInstance* instance() const { return instance_.get(); } - VulkanDevice* device() const { return device_.get(); } + std::unique_ptr CreatePresenter( + Presenter::HostGpuLossCallback host_gpu_loss_callback = + Presenter::FatalErrorHostGpuLossCallback) override; - std::unique_ptr CreateContext( - Window* target_window) override; - std::unique_ptr CreateOffscreenContext() override; + std::unique_ptr CreateImmediateDrawer() override; - protected: - VulkanProvider() = default; + const RenderdocApi& renderdoc_api() const { return renderdoc_api_; } + + struct LibraryFunctions { + // From the module. + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkDestroyInstance vkDestroyInstance; + // From vkGetInstanceProcAddr. + PFN_vkCreateInstance vkCreateInstance; + PFN_vkEnumerateInstanceExtensionProperties + vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; + struct { + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion; + } v_1_1; + }; + const LibraryFunctions& lfn() const { return lfn_; } + + struct InstanceExtensions { + bool ext_debug_utils; + // Core since 1.1.0. + bool khr_get_physical_device_properties2; + + // Surface extensions. + bool khr_surface; +#if XE_PLATFORM_ANDROID + bool khr_android_surface; +#elif XE_PLATFORM_GNU_LINUX + bool khr_xcb_surface; +#elif XE_PLATFORM_WIN32 + bool khr_win32_surface; +#endif + }; + const InstanceExtensions& instance_extensions() const { + return instance_extensions_; + } + VkInstance instance() const { return instance_; } + struct InstanceFunctions { +#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; +#define XE_UI_VULKAN_FUNCTION_PROMOTED(extension_name, core_name) \ + PFN_##extension_name extension_name; +#include "xenia/ui/vulkan/functions/instance_1_0.inc" +#include "xenia/ui/vulkan/functions/instance_ext_debug_utils.inc" +#include "xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc" +#include "xenia/ui/vulkan/functions/instance_khr_surface.inc" +#if XE_PLATFORM_ANDROID +#include "xenia/ui/vulkan/functions/instance_khr_android_surface.inc" +#elif XE_PLATFORM_GNU_LINUX +#include "xenia/ui/vulkan/functions/instance_khr_xcb_surface.inc" +#elif XE_PLATFORM_WIN32 +#include "xenia/ui/vulkan/functions/instance_khr_win32_surface.inc" +#endif +#undef XE_UI_VULKAN_FUNCTION_PROMOTED +#undef XE_UI_VULKAN_FUNCTION + }; + const InstanceFunctions& ifn() const { return ifn_; } + + VkPhysicalDevice physical_device() const { return physical_device_; } + const VkPhysicalDeviceProperties& device_properties() const { + return device_properties_; + } + const VkPhysicalDeviceFeatures& device_features() const { + return device_features_; + } + struct DeviceExtensions { + bool amd_shader_info; + bool ext_fragment_shader_interlock; + // Core since 1.1.0. + bool khr_dedicated_allocation; + // Core since 1.2.0. + bool khr_image_format_list; + // Core since 1.2.0. + bool khr_shader_float_controls; + // Core since 1.2.0. + bool khr_spirv_1_4; + bool khr_swapchain; + }; + const DeviceExtensions& device_extensions() const { + return device_extensions_; + } + uint32_t memory_types_device_local() const { + return memory_types_device_local_; + } + uint32_t memory_types_host_visible() const { + return memory_types_host_visible_; + } + uint32_t memory_types_host_coherent() const { + return memory_types_host_coherent_; + } + uint32_t memory_types_host_cached() const { + return memory_types_host_cached_; + } + struct QueueFamily { + uint32_t queue_first_index = 0; + uint32_t queue_count = 0; + bool potentially_supports_present = false; + }; + const std::vector& queue_families() const { + return queue_families_; + } + // Required. + uint32_t queue_family_graphics_compute() const { + return queue_family_graphics_compute_; + } + // Optional, if sparse binding is supported (UINT32_MAX otherwise). May be the + // same as queue_family_graphics_compute_. + uint32_t queue_family_sparse_binding() const { + return queue_family_sparse_binding_; + } + const VkPhysicalDeviceFloatControlsPropertiesKHR& + device_float_controls_properties() const { + return device_float_controls_properties_; + } + + struct Queue { + VkQueue queue = VK_NULL_HANDLE; + std::recursive_mutex mutex; + }; + struct QueueAcquisition { + QueueAcquisition(std::unique_lock&& lock, + VkQueue queue) + : lock(std::move(lock)), queue(queue) {} + std::unique_lock lock; + VkQueue queue; + }; + QueueAcquisition AcquireQueue(uint32_t index) { + Queue& queue = queues_[index]; + return QueueAcquisition(std::unique_lock(queue.mutex), + queue.queue); + } + QueueAcquisition AcquireQueue(uint32_t family_index, uint32_t index) { + assert_true(family_index != UINT32_MAX); + return AcquireQueue(queue_families_[family_index].queue_first_index + + index); + } + + VkDevice device() const { return device_; } + struct DeviceFunctions { +#define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; +#include "xenia/ui/vulkan/functions/device_1_0.inc" +#include "xenia/ui/vulkan/functions/device_amd_shader_info.inc" +#include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" +#undef XE_UI_VULKAN_FUNCTION + }; + const DeviceFunctions& dfn() const { return dfn_; } + + void SetDeviceObjectName(VkObjectType type, uint64_t handle, + const char* name) const; + + bool IsSparseBindingSupported() const { + return queue_family_sparse_binding_ != UINT32_MAX; + } + + // Samplers that may be useful for host needs. Only these samplers should be + // used in host, non-emulation contexts, because the total number of samplers + // is heavily limited (4000) on Nvidia GPUs - the rest of samplers are + // allocated for emulation. + enum class HostSampler { + kNearestClamp, + kLinearClamp, + kNearestRepeat, + kLinearRepeat, + + kCount, + }; + VkSampler GetHostSampler(HostSampler sampler) const { + return host_samplers_[size_t(sampler)]; + } + + private: + explicit VulkanProvider(bool is_surface_required) + : is_surface_required_(is_surface_required) {} bool Initialize(); - std::unique_ptr instance_; - std::unique_ptr device_; + static void AccumulateInstanceExtensions( + size_t properties_count, const VkExtensionProperties* properties, + bool request_debug_utils, InstanceExtensions& instance_extensions, + std::vector& instance_extensions_enabled); + + static VkBool32 VKAPI_CALL DebugMessengerCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_types, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, + void* user_data); + + bool is_surface_required_; + + RenderdocApi renderdoc_api_; + +#if XE_PLATFORM_LINUX + void* library_ = nullptr; +#elif XE_PLATFORM_WIN32 + HMODULE library_ = nullptr; +#endif + + LibraryFunctions lfn_ = {}; + + InstanceExtensions instance_extensions_; + VkInstance instance_ = VK_NULL_HANDLE; + InstanceFunctions ifn_; + VkDebugUtilsMessengerEXT debug_messenger_ = VK_NULL_HANDLE; + bool debug_names_used_ = false; + + VkPhysicalDevice physical_device_ = VK_NULL_HANDLE; + VkPhysicalDeviceProperties device_properties_; + VkPhysicalDeviceFeatures device_features_; + DeviceExtensions device_extensions_; + uint32_t memory_types_device_local_; + uint32_t memory_types_host_visible_; + uint32_t memory_types_host_coherent_; + uint32_t memory_types_host_cached_; + std::vector queue_families_; + uint32_t queue_family_graphics_compute_; + uint32_t queue_family_sparse_binding_; + VkPhysicalDeviceFloatControlsPropertiesKHR device_float_controls_properties_; + + VkDevice device_ = VK_NULL_HANDLE; + DeviceFunctions dfn_ = {}; + // Queues contain a mutex, can't use std::vector. + std::unique_ptr queues_; + + VkSampler host_samplers_[size_t(HostSampler::kCount)] = {}; }; } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_submission_tracker.cc b/src/xenia/ui/vulkan/vulkan_submission_tracker.cc new file mode 100644 index 000000000..f6ebe60bb --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_submission_tracker.cc @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/vulkan/vulkan_submission_tracker.h" + +#include + +#include "xenia/base/assert.h" +#include "xenia/ui/vulkan/vulkan_util.h" + +namespace xe { +namespace ui { +namespace vulkan { + +VulkanSubmissionTracker::FenceAcquisition::~FenceAcquisition() { + if (!submission_tracker_) { + // Dropped submission or left after std::move. + return; + } + assert_true(submission_tracker_->fence_acquired_ == fence_); + if (fence_ != VK_NULL_HANDLE) { + if (signal_failed_) { + // Left in the unsignaled state. + submission_tracker_->fences_reclaimed_.push_back(fence_); + } else { + // Left in the pending state. + submission_tracker_->fences_pending_.emplace_back( + submission_tracker_->submission_current_, fence_); + } + submission_tracker_->fence_acquired_ = VK_NULL_HANDLE; + } + ++submission_tracker_->submission_current_; +} + +void VulkanSubmissionTracker::Shutdown() { + AwaitAllSubmissionsCompletion(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + for (VkFence fence : fences_reclaimed_) { + dfn.vkDestroyFence(device, fence, nullptr); + } + fences_reclaimed_.clear(); + for (const std::pair& fence_pair : fences_pending_) { + dfn.vkDestroyFence(device, fence_pair.second, nullptr); + } + fences_pending_.clear(); + assert_true(fence_acquired_ == VK_NULL_HANDLE); + util::DestroyAndNullHandle(dfn.vkDestroyFence, device, fence_acquired_); +} + +void VulkanSubmissionTracker::FenceAcquisition::SubmissionFailedOrDropped() { + if (!submission_tracker_) { + return; + } + assert_true(submission_tracker_->fence_acquired_ == fence_); + if (fence_ != VK_NULL_HANDLE) { + submission_tracker_->fences_reclaimed_.push_back(fence_); + } + submission_tracker_->fence_acquired_ = VK_NULL_HANDLE; + fence_ = VK_NULL_HANDLE; + // No submission acquisition from now on, don't increment the current + // submission index as well. + submission_tracker_ = VK_NULL_HANDLE; +} + +uint64_t VulkanSubmissionTracker::UpdateAndGetCompletedSubmission() { + if (!fences_pending_.empty()) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + while (!fences_pending_.empty()) { + const std::pair& pending_pair = + fences_pending_.front(); + assert_true(pending_pair.first > submission_completed_on_gpu_); + if (dfn.vkGetFenceStatus(device, pending_pair.second) != VK_SUCCESS) { + break; + } + fences_reclaimed_.push_back(pending_pair.second); + submission_completed_on_gpu_ = pending_pair.first; + fences_pending_.pop_front(); + } + } + return submission_completed_on_gpu_; +} + +bool VulkanSubmissionTracker::AwaitSubmissionCompletion( + uint64_t submission_index) { + // The tracker itself can't give a submission index for a submission that + // hasn't even started being recorded yet, the client has provided a + // completely invalid value or has done overly optimistic math if such an + // index has been obtained somehow. + assert_true(submission_index <= submission_current_); + // Waiting for the current submission is fine if there was a failure or a + // refusal to submit, and the submission index wasn't incremented, but still + // need to release objects referenced in the dropped submission (while + // shutting down, for instance - in this case, waiting for the last successful + // submission, which could have also referenced the objects from the new + // submission - we can't know since the client has already overwritten its + // last usage index, would correctly ensure that GPU usage of the objects is + // not pending). Waiting for successful submissions, but failed signals, will + // result in a true race condition, however, but waiting for the closest + // successful signal is the best approximation - also retrying to signal in + // this case. + // Go from the most recent to wait only for one fence, which includes all the + // preceding ones. + // "Fence signal operations that are defined by vkQueueSubmit additionally + // include in the first synchronization scope all commands that occur earlier + // in submission order." + size_t reclaim_end = fences_pending_.size(); + if (reclaim_end) { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + while (reclaim_end) { + const std::pair& pending_pair = + fences_pending_[reclaim_end - 1]; + assert_true(pending_pair.first > submission_completed_on_gpu_); + if (pending_pair.first <= submission_index) { + // Wait if requested. + if (dfn.vkWaitForFences(device, 1, &pending_pair.second, VK_TRUE, + UINT64_MAX) == VK_SUCCESS) { + break; + } + } + // Just refresh the completed submission. + if (dfn.vkGetFenceStatus(device, pending_pair.second) == VK_SUCCESS) { + break; + } + --reclaim_end; + } + if (reclaim_end) { + submission_completed_on_gpu_ = fences_pending_[reclaim_end - 1].first; + for (; reclaim_end; --reclaim_end) { + fences_reclaimed_.push_back(fences_pending_.front().second); + fences_pending_.pop_front(); + } + } + } + return submission_completed_on_gpu_ == submission_index; +} + +VulkanSubmissionTracker::FenceAcquisition +VulkanSubmissionTracker::AcquireFenceToAdvanceSubmission() { + assert_true(fence_acquired_ == VK_NULL_HANDLE); + // Reclaim fences if the client only gets the completed submission index or + // awaits in special cases such as shutdown. + UpdateAndGetCompletedSubmission(); + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + if (!fences_reclaimed_.empty()) { + VkFence reclaimed_fence = fences_reclaimed_.back(); + if (dfn.vkResetFences(device, 1, &reclaimed_fence) == VK_SUCCESS) { + fence_acquired_ = fences_reclaimed_.back(); + fences_reclaimed_.pop_back(); + } + } + if (fence_acquired_ == VK_NULL_HANDLE) { + VkFenceCreateInfo fence_create_info; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.pNext = nullptr; + fence_create_info.flags = 0; + // May fail, a null fence is handled in FenceAcquisition. + dfn.vkCreateFence(device, &fence_create_info, nullptr, &fence_acquired_); + } + return FenceAcquisition(*this, fence_acquired_); +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_submission_tracker.h b/src/xenia/ui/vulkan/vulkan_submission_tracker.h new file mode 100644 index 000000000..c1f055c87 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_submission_tracker.h @@ -0,0 +1,135 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ +#define XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ + +#include +#include +#include +#include + +#include "xenia/ui/vulkan/vulkan_provider.h" + +namespace xe { +namespace ui { +namespace vulkan { + +// Fence wrapper, safely handling cases when the fence has not been initialized +// yet or has already been shut down, and failed or dropped submissions. +// +// The current submission index can be associated with the usage of objects to +// release them when the GPU isn't potentially referencing them anymore, and +// should be incremented only +// +// 0 can be used as a "never referenced" submission index. +// +// The submission index timeline survives Shutdown, so submission indices can be +// given to clients that are not aware of the lifetime of the tracker. +// +// To transfer the tracker to another queue (to make sure the first signal on +// the new queue does not happen before the last signal on the old one), call +// AwaitAllSubmissionsCompletion before doing the first submission on the new +// one. +class VulkanSubmissionTracker { + public: + class FenceAcquisition { + public: + FenceAcquisition() : submission_tracker_(nullptr), fence_(VK_NULL_HANDLE) {} + FenceAcquisition(VulkanSubmissionTracker& submission_tracker, VkFence fence) + : submission_tracker_(&submission_tracker), fence_(fence) {} + FenceAcquisition(const FenceAcquisition& fence_acquisition) = delete; + FenceAcquisition& operator=(const FenceAcquisition& fence_acquisition) = + delete; + FenceAcquisition(FenceAcquisition&& fence_acquisition) { + *this = std::move(fence_acquisition); + } + FenceAcquisition& operator=(FenceAcquisition&& fence_acquisition) { + if (this == &fence_acquisition) { + return *this; + } + submission_tracker_ = fence_acquisition.submission_tracker_; + fence_acquisition.submission_tracker_ = nullptr; + fence_ = fence_acquisition.fence_; + fence_acquisition.fence_ = VK_NULL_HANDLE; + return *this; + } + ~FenceAcquisition(); + + // In unsignaled state. May be null if failed to create or to reset a fence. + VkFence fence() { return fence_; } + + // Call if vkQueueSubmit has failed (or it was decided not to commit the + // submission), and the submission index shouldn't be incremented by + // releasing this submission (for instance, to retry commands with long-term + // effects like copying or image layout changes later if in the attempt the + // submission index stays the same). + void SubmissionFailedOrDropped(); + // Call if for some reason (like signaling multiple fences) the fence + // signaling was done in a separate submission than the command buffer, and + // the command buffer vkQueueSubmit succeeded (so commands with long-term + // effects will be executed), but the fence-only vkQueueSubmit has failed, + // thus the tracker shouldn't attempt to wait for that fence (it will be in + // the unsignaled state). + void SubmissionSucceededSignalFailed() { signal_failed_ = true; } + + private: + // If nullptr, has been moved to another FenceAcquisition - not holding a + // fence from now on. + VulkanSubmissionTracker* submission_tracker_; + VkFence fence_; + bool signal_failed_ = false; + }; + + VulkanSubmissionTracker(VulkanProvider& provider) : provider_(provider) {} + VulkanSubmissionTracker(const VulkanSubmissionTracker& submission_tracker) = + delete; + VulkanSubmissionTracker& operator=( + const VulkanSubmissionTracker& submission_tracker) = delete; + ~VulkanSubmissionTracker() { Shutdown(); } + + void Shutdown(); + + uint64_t GetCurrentSubmission() const { return submission_current_; } + uint64_t UpdateAndGetCompletedSubmission(); + + // Returns whether the expected GPU signal has actually been reached (rather + // than some fallback condition) for cases when stronger completeness + // guarantees as needed (when downloading, as opposed to just destroying). + // If false is returned, it's also not guaranteed that GetCompletedSubmission + // will return a value >= submission_index. + bool AwaitSubmissionCompletion(uint64_t submission_index); + bool AwaitAllSubmissionsCompletion() { + return AwaitSubmissionCompletion(submission_current_ - 1); + } + + [[nodiscard]] FenceAcquisition AcquireFenceToAdvanceSubmission(); + + private: + VulkanProvider& provider_; + uint64_t submission_current_ = 1; + // Last submission with a successful fence signal as well as a successful + // fence wait / query. + uint64_t submission_completed_on_gpu_ = 0; + // The flow is: + // Reclaimed (or create if empty) > acquired > pending > reclaimed. + // Or, if dropped the submission while acquired: + // Reclaimed (or create if empty) > acquired > reclaimed. + VkFence fence_acquired_ = VK_NULL_HANDLE; + // Ordered by the submission index (the first pair member). + std::deque> fences_pending_; + // Fences are reclaimed when awaiting or when refreshing the completed value. + std::vector fences_reclaimed_; +}; + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_VULKAN_VULKAN_SUBMISSION_TRACKER_H_ 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 79f74a782..000000000 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.cc +++ /dev/null @@ -1,824 +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; - const VulkanInstance::InstanceFunctions& ifn = instance_->ifn(); - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = ifn.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 = ifn.vkGetPhysicalDeviceSurfaceFormatsKHR(*device_, surface_, &count, - nullptr); - CheckResult(status, "vkGetPhysicalDeviceSurfaceFormatsKHR"); - std::vector surface_formats; - surface_formats.resize(count); - status = ifn.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 = ifn.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 = ifn.vkGetPhysicalDeviceSurfacePresentModesKHR(*device_, surface_, - &count, nullptr); - CheckResult(status, "vkGetPhysicalDeviceSurfacePresentModesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - present_modes.resize(count); - status = ifn.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 = dfn.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 = - dfn.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 = - dfn.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 = - dfn.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 = dfn.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 = dfn.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 = dfn.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 = dfn.vkGetSwapchainImagesKHR(*device_, handle, &actual_image_count, - nullptr); - CheckResult(status, "vkGetSwapchainImagesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - images.resize(actual_image_count); - status = dfn.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 = dfn.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; - - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - 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 = dfn.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 = dfn.vkCreateFramebuffer(*device_, &framebuffer_info, nullptr, - &buffer->framebuffer); - CheckResult(status, "vkCreateFramebuffer"); - if (status != VK_SUCCESS) { - return status; - } - - return VK_SUCCESS; -} - -void VulkanSwapChain::DestroyBuffer(Buffer* buffer) { - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - if (buffer->framebuffer) { - dfn.vkDestroyFramebuffer(*device_, buffer->framebuffer, nullptr); - buffer->framebuffer = nullptr; - } - if (buffer->image_view) { - dfn.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(); - - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - - DestroyAndNullHandle(dfn.vkDestroySemaphore, *device_, - image_available_semaphore_); - DestroyAndNullHandle(dfn.vkDestroyRenderPass, *device_, render_pass_); - - if (copy_cmd_buffer_) { - dfn.vkFreeCommandBuffers(*device_, cmd_pool_, 1, ©_cmd_buffer_); - copy_cmd_buffer_ = nullptr; - } - if (render_cmd_buffer_) { - dfn.vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_); - render_cmd_buffer_ = nullptr; - } - DestroyAndNullHandle(dfn.vkDestroyCommandPool, *device_, cmd_pool_); - - 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; - } - - DestroyAndNullHandle(dfn.vkDestroyFence, *device_, synchronization_fence_); - - // images_ doesn't need to be cleaned up as the swapchain does it implicitly. - DestroyAndNullHandle(dfn.vkDestroySwapchainKHR, *device_, handle); - const VulkanInstance::InstanceFunctions& ifn = instance_->ifn(); - DestroyAndNullHandle(ifn.vkDestroySurfaceKHR, *instance_, surface_); -} - -VkResult VulkanSwapChain::Begin() { - wait_semaphores_.clear(); - - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - VkResult status; - - // Wait for the last swap to finish. - status = - dfn.vkWaitForFences(*device_, 1, &synchronization_fence_, VK_TRUE, -1); - if (status != VK_SUCCESS) { - return status; - } - - status = dfn.vkResetFences(*device_, 1, &synchronization_fence_); - if (status != VK_SUCCESS) { - return status; - } - - // Get the index of the next available swapchain image. - status = - dfn.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 = - dfn.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. - dfn.vkResetCommandBuffer(render_cmd_buffer_, 0); - dfn.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 = dfn.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 = dfn.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; - } - dfn.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_]; - const VulkanDevice::DeviceFunctions& dfn = device_->dfn(); - VkResult status; - - status = dfn.vkEndCommandBuffer(render_cmd_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - status = dfn.vkEndCommandBuffer(copy_cmd_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Build primary command buffer. - status = dfn.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 = dfn.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}; - dfn.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 - dfn.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; - dfn.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; - dfn.vkCmdBeginRenderPass(cmd_buffer_, &render_pass_begin_info, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - // Render commands. - dfn.vkCmdExecuteCommands(cmd_buffer_, 1, &render_cmd_buffer_); - - // End render pass. - dfn.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; - dfn.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 = dfn.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 = dfn.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 = dfn.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_upload_buffer_pool.cc b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc new file mode 100644 index 000000000..2e0a054c7 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.cc @@ -0,0 +1,199 @@ +/** + ****************************************************************************** + * 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_upload_buffer_pool.h" + +#include + +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/ui/vulkan/vulkan_util.h" + +namespace xe { +namespace ui { +namespace vulkan { + +// Host-visible memory sizes are likely to be internally rounded to +// nonCoherentAtomSize (it's the memory mapping granularity, though as the map +// or flush range must be clamped to the actual allocation size as a special +// case, but it's still unlikely that the allocation won't be aligned to it), so +// try not to waste that padding. +VulkanUploadBufferPool::VulkanUploadBufferPool(const VulkanProvider& provider, + VkBufferUsageFlags usage, + size_t page_size) + : GraphicsUploadBufferPool(size_t( + util::GetMappableMemorySize(provider, VkDeviceSize(page_size)))), + provider_(provider), + usage_(usage) {} + +uint8_t* VulkanUploadBufferPool::Request(uint64_t submission_index, size_t size, + size_t alignment, VkBuffer& buffer_out, + VkDeviceSize& offset_out) { + size_t offset; + const VulkanPage* page = + static_cast(GraphicsUploadBufferPool::Request( + submission_index, size, alignment, offset)); + if (!page) { + return nullptr; + } + buffer_out = page->buffer_; + offset_out = VkDeviceSize(offset); + return reinterpret_cast(page->mapping_) + offset; +} + +uint8_t* VulkanUploadBufferPool::RequestPartial(uint64_t submission_index, + size_t size, size_t alignment, + VkBuffer& buffer_out, + VkDeviceSize& offset_out, + VkDeviceSize& size_out) { + size_t offset, size_obtained; + const VulkanPage* page = + static_cast(GraphicsUploadBufferPool::RequestPartial( + submission_index, size, alignment, offset, size_obtained)); + if (!page) { + return nullptr; + } + buffer_out = page->buffer_; + offset_out = VkDeviceSize(offset); + size_out = VkDeviceSize(size_obtained); + return reinterpret_cast(page->mapping_) + offset; +} + +GraphicsUploadBufferPool::Page* +VulkanUploadBufferPool::CreatePageImplementation() { + if (memory_type_ == kMemoryTypeUnavailable) { + // Don't try to create everything again and again if totally broken. + return nullptr; + } + + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + + VkBufferCreateInfo buffer_create_info; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.pNext = nullptr; + buffer_create_info.flags = 0; + buffer_create_info.size = VkDeviceSize(page_size_); + buffer_create_info.usage = usage_; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_create_info.queueFamilyIndexCount = 0; + buffer_create_info.pQueueFamilyIndices = nullptr; + VkBuffer buffer; + if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer) != + VK_SUCCESS) { + XELOGE("Failed to create a Vulkan upload buffer with {} bytes", page_size_); + return nullptr; + } + + if (memory_type_ == kMemoryTypeUnknown) { + VkMemoryRequirements memory_requirements; + dfn.vkGetBufferMemoryRequirements(device, buffer, &memory_requirements); + memory_type_ = util::ChooseHostMemoryType( + provider_, memory_requirements.memoryTypeBits, false); + if (memory_type_ == UINT32_MAX) { + XELOGE( + "No host-visible memory types can store an Vulkan upload buffer with " + "{} bytes", + page_size_); + memory_type_ = kMemoryTypeUnavailable; + dfn.vkDestroyBuffer(device, buffer, nullptr); + return nullptr; + } + allocation_size_ = memory_requirements.size; + if (allocation_size_ > page_size_) { + // Try to occupy the allocation padding. If that's going to require even + // more memory for some reason, don't. + buffer_create_info.size = allocation_size_; + VkBuffer buffer_expanded; + if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, + &buffer_expanded) == VK_SUCCESS) { + VkMemoryRequirements memory_requirements_expanded; + dfn.vkGetBufferMemoryRequirements(device, buffer_expanded, + &memory_requirements_expanded); + uint32_t memory_type_expanded = util::ChooseHostMemoryType( + provider_, memory_requirements.memoryTypeBits, false); + if (memory_requirements_expanded.size <= allocation_size_ && + memory_type_expanded != UINT32_MAX) { + page_size_ = size_t(allocation_size_); + allocation_size_ = memory_requirements_expanded.size; + memory_type_ = memory_type_expanded; + dfn.vkDestroyBuffer(device, buffer, nullptr); + buffer = buffer_expanded; + } else { + dfn.vkDestroyBuffer(device, buffer_expanded, nullptr); + } + } + } + } + + VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = allocation_size_; + memory_allocate_info.memoryTypeIndex = memory_type_; + VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; + if (provider_.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); + memory_dedicated_allocate_info.sType = + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; + memory_dedicated_allocate_info.pNext = nullptr; + memory_dedicated_allocate_info.image = VK_NULL_HANDLE; + memory_dedicated_allocate_info.buffer = buffer; + } + VkDeviceMemory memory; + if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != + VK_SUCCESS) { + XELOGE("Failed to allocate {} bytes of Vulkan upload buffer memory", + allocation_size_); + dfn.vkDestroyBuffer(device, buffer, nullptr); + return nullptr; + } + + if (dfn.vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) { + XELOGE("Failed to bind memory to a Vulkan upload buffer with {} bytes", + page_size_); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, memory, nullptr); + return nullptr; + } + + void* mapping; + if (dfn.vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, &mapping) != + VK_SUCCESS) { + XELOGE("Failed to map {} bytes of Vulkan upload buffer memory", + allocation_size_); + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, memory, nullptr); + return nullptr; + } + + return new VulkanPage(provider_, buffer, memory, mapping); +} + +void VulkanUploadBufferPool::FlushPageWrites(Page* page, size_t offset, + size_t size) { + util::FlushMappedMemoryRange( + provider_, static_cast(page)->memory_, memory_type_, + VkDeviceSize(offset), allocation_size_, VkDeviceSize(size)); +} + +VulkanUploadBufferPool::VulkanPage::~VulkanPage() { + const VulkanProvider::DeviceFunctions& dfn = provider_.dfn(); + VkDevice device = provider_.device(); + dfn.vkDestroyBuffer(device, buffer_, nullptr); + // Unmapping is done implicitly when the memory is freed. + dfn.vkFreeMemory(device, memory_, nullptr); +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.h b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.h new file mode 100644 index 000000000..309c44ff1 --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_upload_buffer_pool.h @@ -0,0 +1,67 @@ +/** + ****************************************************************************** + * 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_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_ +#define XENIA_UI_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_ + +#include "xenia/ui/graphics_upload_buffer_pool.h" +#include "xenia/ui/vulkan/vulkan_provider.h" + +namespace xe { +namespace ui { +namespace vulkan { + +class VulkanUploadBufferPool : public GraphicsUploadBufferPool { + public: + VulkanUploadBufferPool(const VulkanProvider& provider, + VkBufferUsageFlags usage, + size_t page_size = kDefaultPageSize); + + uint8_t* Request(uint64_t submission_index, size_t size, size_t alignment, + VkBuffer& buffer_out, VkDeviceSize& offset_out); + uint8_t* RequestPartial(uint64_t submission_index, size_t size, + size_t alignment, VkBuffer& buffer_out, + VkDeviceSize& offset_out, VkDeviceSize& size_out); + + protected: + Page* CreatePageImplementation() override; + + void FlushPageWrites(Page* page, size_t offset, size_t size) override; + + private: + struct VulkanPage : public Page { + // Takes ownership of the buffer and its memory and mapping. + VulkanPage(const VulkanProvider& provider, VkBuffer buffer, + VkDeviceMemory memory, void* mapping) + : provider_(provider), + buffer_(buffer), + memory_(memory), + mapping_(mapping) {} + ~VulkanPage() override; + const VulkanProvider& provider_; + VkBuffer buffer_; + VkDeviceMemory memory_; + void* mapping_; + }; + + const VulkanProvider& provider_; + + VkDeviceSize allocation_size_; + static constexpr uint32_t kMemoryTypeUnknown = UINT32_MAX; + static constexpr uint32_t kMemoryTypeUnavailable = kMemoryTypeUnknown - 1; + uint32_t memory_type_ = UINT32_MAX; + + VkBufferUsageFlags usage_; +}; + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_ diff --git a/src/xenia/ui/vulkan/vulkan_util.cc b/src/xenia/ui/vulkan/vulkan_util.cc index a237b45d1..f8dd5846e 100644 --- a/src/xenia/ui/vulkan/vulkan_util.cc +++ b/src/xenia/ui/vulkan/vulkan_util.cc @@ -9,496 +9,187 @@ #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" +#include -// Implement AMD's VMA here. -#define VMA_IMPLEMENTATION -#include "xenia/ui/vulkan/vulkan_mem_alloc.h" +#include "xenia/base/assert.h" +#include "xenia/base/math.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace ui { namespace vulkan { +namespace util { -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"; +void FlushMappedMemoryRange(const VulkanProvider& provider, + VkDeviceMemory memory, uint32_t memory_type, + VkDeviceSize offset, VkDeviceSize memory_size, + VkDeviceSize size) { + assert_false(size != VK_WHOLE_SIZE && memory_size == VK_WHOLE_SIZE); + assert_true(memory_size == VK_WHOLE_SIZE || offset <= memory_size); + assert_true(memory_size == VK_WHOLE_SIZE || size <= memory_size - offset); + if (!size || + (provider.memory_types_host_coherent() & (uint32_t(1) << memory_type))) { + return; } -} - -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; - } + VkMappedMemoryRange range; + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.pNext = nullptr; + range.memory = memory; + range.offset = offset; + range.size = size; + VkDeviceSize non_coherent_atom_size = + provider.device_properties().limits.nonCoherentAtomSize; + // On some Android implementations, nonCoherentAtomSize is 0, not 1. + if (non_coherent_atom_size > 1) { + range.offset = offset / non_coherent_atom_size * non_coherent_atom_size; + if (size != VK_WHOLE_SIZE) { + range.size = std::min(xe::round_up(offset + size, non_coherent_atom_size), + memory_size) - + range.offset; } } - return {!any_missing, enabled_layers}; + provider.dfn().vkFlushMappedMemoryRanges(provider.device(), 1, &range); } -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; - } - } +bool CreateDedicatedAllocationBuffer( + const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage, + MemoryPurpose memory_purpose, VkBuffer& buffer_out, + VkDeviceMemory& memory_out, uint32_t* memory_type_out, + VkDeviceSize* memory_size_out) { + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + VkBufferCreateInfo buffer_create_info; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.pNext = nullptr; + buffer_create_info.flags = 0; + buffer_create_info.size = size; + buffer_create_info.usage = usage; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_create_info.queueFamilyIndexCount = 0; + buffer_create_info.pQueueFamilyIndices = nullptr; + VkBuffer buffer; + if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer) != + VK_SUCCESS) { + return false; } - return {!any_missing, enabled_extensions}; + + VkMemoryRequirements memory_requirements; + dfn.vkGetBufferMemoryRequirements(device, buffer, &memory_requirements); + uint32_t memory_type = ChooseMemoryType( + provider, memory_requirements.memoryTypeBits, memory_purpose); + if (memory_type == UINT32_MAX) { + dfn.vkDestroyBuffer(device, buffer, nullptr); + return false; + } + + VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_allocate_info.memoryTypeIndex = memory_type; + VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; + if (provider.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); + memory_dedicated_allocate_info.sType = + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; + memory_dedicated_allocate_info.pNext = nullptr; + memory_dedicated_allocate_info.image = VK_NULL_HANDLE; + memory_dedicated_allocate_info.buffer = buffer; + } + VkDeviceMemory memory; + if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != + VK_SUCCESS) { + dfn.vkDestroyBuffer(device, buffer, nullptr); + return false; + } + + if (dfn.vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) { + dfn.vkDestroyBuffer(device, buffer, nullptr); + dfn.vkFreeMemory(device, memory, nullptr); + return false; + } + + buffer_out = buffer; + memory_out = memory; + if (memory_type_out) { + *memory_type_out = memory_type; + } + if (memory_size_out) { + *memory_size_out = memory_allocate_info.allocationSize; + } + return true; } +bool CreateDedicatedAllocationImage(const VulkanProvider& provider, + const VkImageCreateInfo& create_info, + MemoryPurpose memory_purpose, + VkImage& image_out, + VkDeviceMemory& memory_out, + uint32_t* memory_type_out, + VkDeviceSize* memory_size_out) { + const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + VkDevice device = provider.device(); + + VkImage image; + if (dfn.vkCreateImage(device, &create_info, nullptr, &image) != VK_SUCCESS) { + return false; + } + + VkMemoryRequirements memory_requirements; + dfn.vkGetImageMemoryRequirements(device, image, &memory_requirements); + uint32_t memory_type = ChooseMemoryType( + provider, memory_requirements.memoryTypeBits, memory_purpose); + if (memory_type == UINT32_MAX) { + dfn.vkDestroyImage(device, image, nullptr); + return false; + } + + VkMemoryAllocateInfo memory_allocate_info; + VkMemoryAllocateInfo* memory_allocate_info_last = &memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = nullptr; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_allocate_info.memoryTypeIndex = memory_type; + VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info; + if (provider.device_extensions().khr_dedicated_allocation) { + memory_allocate_info_last->pNext = &memory_dedicated_allocate_info; + memory_allocate_info_last = reinterpret_cast( + &memory_dedicated_allocate_info); + memory_dedicated_allocate_info.sType = + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR; + memory_dedicated_allocate_info.pNext = nullptr; + memory_dedicated_allocate_info.image = image; + memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; + } + VkDeviceMemory memory; + if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) != + VK_SUCCESS) { + dfn.vkDestroyImage(device, image, nullptr); + return false; + } + + if (dfn.vkBindImageMemory(device, image, memory, 0) != VK_SUCCESS) { + dfn.vkDestroyImage(device, image, nullptr); + dfn.vkFreeMemory(device, memory, nullptr); + return false; + } + + image_out = image; + memory_out = memory; + if (memory_type_out) { + *memory_type_out = memory_type; + } + if (memory_size_out) { + *memory_size_out = memory_allocate_info.allocationSize; + } + return true; +} + +} // namespace util } // namespace vulkan } // namespace ui } // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_util.h b/src/xenia/ui/vulkan/vulkan_util.h index d57c6c0fa..653c66e2c 100644 --- a/src/xenia/ui/vulkan/vulkan_util.h +++ b/src/xenia/ui/vulkan/vulkan_util.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,21 +10,24 @@ #ifndef XENIA_UI_VULKAN_VULKAN_UTIL_H_ #define XENIA_UI_VULKAN_VULKAN_UTIL_H_ -#include -#include -#include +#include +#include -#include "xenia/ui/vulkan/vulkan.h" - -namespace xe { -namespace ui { -class Window; -} // namespace ui -} // namespace xe +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace ui { namespace vulkan { +namespace util { + +inline void CheckResult(VkResult result, const char* action) { + if (result != VK_SUCCESS) { + XELOGE("Vulkan check: {} returned 0x{:X}", action, uint32_t(result)); + } + assert_true(result == VK_SUCCESS, action); +} template inline bool DestroyAndNullHandle(F* destroy_function, T& handle) { @@ -36,9 +39,8 @@ inline bool DestroyAndNullHandle(F* destroy_function, T& handle) { return false; } -template -inline bool DestroyAndNullHandle(F* destroy_function, VkInstance parent, - T& handle) { +template +inline bool DestroyAndNullHandle(F* destroy_function, P parent, T& handle) { if (handle != VK_NULL_HANDLE) { destroy_function(parent, handle, nullptr); handle = VK_NULL_HANDLE; @@ -47,86 +49,128 @@ inline bool DestroyAndNullHandle(F* destroy_function, VkInstance parent, return false; } -template -inline bool DestroyAndNullHandle(F* destroy_function, VkDevice parent, - T& handle) { - if (handle != VK_NULL_HANDLE) { - destroy_function(parent, handle, nullptr); - handle = VK_NULL_HANDLE; - return true; +enum class MemoryPurpose { + kDeviceLocal, + kUpload, + kReadback, +}; + +inline VkDeviceSize GetMappableMemorySize(const VulkanProvider& provider, + VkDeviceSize size) { + VkDeviceSize non_coherent_atom_size = + provider.device_properties().limits.nonCoherentAtomSize; + // On some Android implementations, nonCoherentAtomSize is 0, not 1. + if (non_coherent_atom_size > 1) { + size = xe::round_up(size, non_coherent_atom_size, false); } - return false; + return size; } -struct Version { - uint32_t major; - uint32_t minor; - uint32_t patch; - std::string pretty_string; +inline uint32_t ChooseHostMemoryType(const VulkanProvider& provider, + uint32_t supported_types, + bool is_readback) { + supported_types &= provider.memory_types_host_visible(); + uint32_t host_cached = provider.memory_types_host_cached(); + uint32_t memory_type; + // For upload, uncached is preferred so writes do not pollute the CPU cache. + // For readback, cached is preferred so multiple CPU reads are fast. + // If the preferred caching behavior is not available, pick any host-visible. + if (xe::bit_scan_forward( + supported_types & (is_readback ? host_cached : ~host_cached), + &memory_type) || + xe::bit_scan_forward(supported_types, &memory_type)) { + return memory_type; + } + return UINT32_MAX; +} - static uint32_t Make(uint32_t major, uint32_t minor, uint32_t patch); +inline uint32_t ChooseMemoryType(const VulkanProvider& provider, + uint32_t supported_types, + MemoryPurpose purpose) { + switch (purpose) { + case MemoryPurpose::kDeviceLocal: { + uint32_t memory_type; + return xe::bit_scan_forward(supported_types, &memory_type) ? memory_type + : UINT32_MAX; + } break; + case MemoryPurpose::kUpload: + case MemoryPurpose::kReadback: + return ChooseHostMemoryType(provider, supported_types, + purpose == MemoryPurpose::kReadback); + default: + assert_unhandled_case(purpose); + return UINT32_MAX; + } +} - static Version Parse(uint32_t value); -}; +// Actual memory size is required if explicit size is specified for clamping to +// the actual memory allocation size while rounding to the non-coherent atom +// size (offset + size passed to vkFlushMappedMemoryRanges inside this function +// must be either a multiple of nonCoherentAtomSize (but not exceeding the +// memory size) or equal to the memory size). +void FlushMappedMemoryRange(const VulkanProvider& provider, + VkDeviceMemory memory, uint32_t memory_type, + VkDeviceSize offset = 0, + VkDeviceSize memory_size = VK_WHOLE_SIZE, + VkDeviceSize size = VK_WHOLE_SIZE); -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); +inline VkExtent2D GetMax2DFramebufferExtent(const VulkanProvider& provider) { + const VkPhysicalDeviceLimits& limits = provider.device_properties().limits; + VkExtent2D max_extent; + max_extent.width = + std::min(limits.maxFramebufferWidth, limits.maxImageDimension2D); + max_extent.height = + std::min(limits.maxFramebufferHeight, limits.maxImageDimension2D); + return max_extent; +} -std::string to_flags_string(VkImageUsageFlagBits flags); -std::string to_flags_string(VkFormatFeatureFlagBits flags); -std::string to_flags_string(VkSurfaceTransformFlagBitsKHR flags); +inline void InitializeSubresourceRange( + VkImageSubresourceRange& range, + VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT, + uint32_t base_mip_level = 0, uint32_t level_count = VK_REMAINING_MIP_LEVELS, + uint32_t base_array_layer = 0, + uint32_t layer_count = VK_REMAINING_ARRAY_LAYERS) { + range.aspectMask = aspect_mask; + range.baseMipLevel = base_mip_level; + range.levelCount = level_count; + range.baseArrayLayer = base_array_layer; + range.layerCount = layer_count; +} -const char* to_string(VkColorSpaceKHR color_space); -const char* to_string(VkPresentModeKHR present_mode); +// Creates a buffer backed by a dedicated allocation. The allocation size will +// NOT be aligned to nonCoherentAtomSize - if mapping or flushing not the whole +// size, memory_size_out must be used for clamping the range. +bool CreateDedicatedAllocationBuffer( + const VulkanProvider& provider, VkDeviceSize size, VkBufferUsageFlags usage, + MemoryPurpose memory_purpose, VkBuffer& buffer_out, + VkDeviceMemory& memory_out, uint32_t* memory_type_out = nullptr, + VkDeviceSize* memory_size_out = nullptr); -// Throws a fatal error with some Vulkan help text. -void FatalVulkanError(std::string error); +bool CreateDedicatedAllocationImage(const VulkanProvider& provider, + const VkImageCreateInfo& create_info, + MemoryPurpose memory_purpose, + VkImage& image_out, + VkDeviceMemory& memory_out, + uint32_t* memory_type_out = nullptr, + VkDeviceSize* memory_size_out = nullptr); -// 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); +inline VkShaderModule CreateShaderModule(const VulkanProvider& provider, + const void* code, size_t code_size) { + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0; + shader_module_create_info.codeSize = code_size; + shader_module_create_info.pCode = reinterpret_cast(code); + VkShaderModule shader_module; + return provider.dfn().vkCreateShaderModule( + provider.device(), &shader_module_create_info, nullptr, + &shader_module) == VK_SUCCESS + ? shader_module + : VK_NULL_HANDLE; +} +} // namespace util } // namespace vulkan } // namespace ui } // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_window_demo.cc b/src/xenia/ui/vulkan/vulkan_window_demo.cc index f2e0fcff8..f4ba6a669 100644 --- a/src/xenia/ui/vulkan/vulkan_window_demo.cc +++ b/src/xenia/ui/vulkan/vulkan_window_demo.cc @@ -34,7 +34,7 @@ class VulkanWindowDemoApp final : public WindowDemoApp { std::unique_ptr VulkanWindowDemoApp::CreateGraphicsProvider() const { - return VulkanProvider::Create(); + return VulkanProvider::Create(true); } } // namespace vulkan diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index 74b81ae21..ad6129307 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,347 +10,719 @@ #include "xenia/ui/window.h" #include +#include #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" #include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/presenter.h" namespace xe { namespace ui { -constexpr bool kContinuousRepaint = false; -constexpr bool kShowPresentFps = kContinuousRepaint; - -// Enables long press behaviors (context menu, etc). -constexpr bool kTouch = false; - -constexpr uint64_t kDoubleClickDelayMillis = 600; -constexpr double kDoubleClickDistance = 5; - -constexpr int32_t kMouseWheelDetent = 120; - -Window::Window(WindowedAppContext& app_context, const std::string& title) - : app_context_(app_context), title_(title) {} +Window::Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height) + : app_context_(app_context), + title_(title), + desired_logical_width_(desired_logical_width), + desired_logical_height_(desired_logical_height) {} Window::~Window() { - // Context must have been cleaned up already in OnDestroy. - assert_null(context_.get()); + // In case the implementation didn't need to call EnterDestructor. Though + // that was likely a mistake, so placing an assertion. + assert_true(phase_ == Phase::kDeleting); + EnterDestructor(); + + if (presenter_) { + Presenter* old_presenter = presenter_; + // Null the pointer to prevent an infinite loop between + // SetWindowSurfaceFromUIThread and SetPresenter calling each other. + presenter_ = nullptr; + old_presenter->SetWindowSurfaceFromUIThread(nullptr, nullptr); + presenter_surface_.reset(); + } + + // Right before destruction has finished, after which no interaction with + // *this can be done, notify the destruction receivers that the window is + // being destroyed and that *this is not accessible anymore. + while (innermost_destruction_receiver_) { + innermost_destruction_receiver_->window_ = nullptr; + innermost_destruction_receiver_ = + innermost_destruction_receiver_->outer_receiver_; + } } -void Window::AttachListener(WindowListener* listener) { - if (in_listener_loop_) { - pending_listener_attaches_.push_back(listener); - return; - } - auto it = std::find(listeners_.begin(), listeners_.end(), listener); - if (it != listeners_.end()) { +void Window::AddListener(WindowListener* listener) { + assert_not_null(listener); + // Check if already added. + if (std::find(listeners_.cbegin(), listeners_.cend(), listener) != + listeners_.cend()) { return; } listeners_.push_back(listener); - Invalidate(); } -void Window::DetachListener(WindowListener* listener) { - if (in_listener_loop_) { - pending_listener_detaches_.push_back(listener); +void Window::RemoveListener(WindowListener* listener) { + assert_not_null(listener); + auto it = std::find(listeners_.cbegin(), listeners_.cend(), listener); + if (it == listeners_.cend()) { return; } - auto it = std::find(listeners_.begin(), listeners_.end(), listener); - if (it == listeners_.end()) { - return; + // Actualize the next listener indices after the erasure from the vector. + ListenerIterationContext* iteration_context = + innermost_listener_iteration_context_; + if (iteration_context) { + size_t existing_index = size_t(std::distance(listeners_.cbegin(), it)); + while (iteration_context) { + if (iteration_context->next_index > existing_index) { + --iteration_context->next_index; + } + iteration_context = iteration_context->outer_context; + } } listeners_.erase(it); } -void Window::ForEachListener(std::function fn) { - assert_false(in_listener_loop_); - in_listener_loop_ = true; - for (auto listener : listeners_) { - fn(listener); +void Window::AddInputListener(WindowInputListener* listener, size_t z_order) { + assert_not_null(listener); + // Check if already added. + for (auto it_existing = input_listeners_.rbegin(); + it_existing != input_listeners_.rend(); ++it_existing) { + if (it_existing->second != listener) { + continue; + } + if (it_existing->first == z_order) { + return; + } + // If removing the listener that is the next in a current listener loop, + // skip it (in a multimap, only one element iterator is invalidated). + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (iteration_context->next_iterator == it_existing) { + ++iteration_context->next_iterator; + } + iteration_context = iteration_context->outer_context; + } + input_listeners_.erase(std::prev(it_existing.base())); + // FIXME(Triang3l): Changing the Z order of an existing listener while + // already executing the listeners may cause listeners to be called twice if + // the Z order is lowered from one that has already been processed to one + // below the current one. Because nested listener calls are supported, a + // single last call index can't be associated with a listener to skip it if + // calling twice for the same event (a "not equal to" comparison of the call + // indices will result in the skipping being cancelled in the outer loop if + // an inner one is done, a "greater than" comparison will cause the inner + // loop to effectively terminate all outer ones). } - in_listener_loop_ = false; - while (!pending_listener_attaches_.empty()) { - auto listener = pending_listener_attaches_.back(); - pending_listener_attaches_.pop_back(); - AttachListener(listener); - } - while (!pending_listener_detaches_.empty()) { - auto listener = pending_listener_detaches_.back(); - pending_listener_detaches_.pop_back(); - DetachListener(listener); - } -} - -void Window::TryForEachListener(std::function fn) { - assert_false(in_listener_loop_); - in_listener_loop_ = true; - for (auto listener : listeners_) { - if (fn(listener)) { - break; + auto it_new = std::prev( + std::make_reverse_iterator(input_listeners_.emplace(z_order, listener))); + // If adding to layers in between the currently being processed ones (from + // highest to lowest) and the previously next, make sure the new listener is + // executed too. Execution within one layer, however, happens in the reverse + // order of addition, so if adding to the Z layer currently being processed, + // the new listener must not be executed within the loop. But, if adding to + // the next Z layer after the current one, it must be executed immediately. + { + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (z_order < iteration_context->current_z_order && + (iteration_context->next_iterator == input_listeners_.crend() || + z_order >= iteration_context->next_iterator->first)) { + iteration_context->next_iterator = it_new; + } + iteration_context = iteration_context->outer_context; } } - in_listener_loop_ = false; - while (!pending_listener_attaches_.empty()) { - auto listener = pending_listener_attaches_.back(); - pending_listener_attaches_.pop_back(); - AttachListener(listener); - } - while (!pending_listener_detaches_.empty()) { - auto listener = pending_listener_detaches_.back(); - pending_listener_detaches_.pop_back(); - DetachListener(listener); - } } -void Window::set_imgui_input_enabled(bool value) { - if (value == is_imgui_input_enabled_) { +void Window::RemoveInputListener(WindowInputListener* listener) { + assert_not_null(listener); + for (auto it_existing = input_listeners_.rbegin(); + it_existing != input_listeners_.rend(); ++it_existing) { + if (it_existing->second != listener) { + continue; + } + // If removing the listener that is the next in a current listener loop, + // skip it (in a multimap, only one element iterator is invalidated). + InputListenerIterationContext* iteration_context = + innermost_input_listener_iteration_context_; + while (iteration_context) { + if (iteration_context->next_iterator == it_existing) { + ++iteration_context->next_iterator; + } + iteration_context = iteration_context->outer_context; + } + input_listeners_.erase(std::prev(it_existing.base())); return; } - is_imgui_input_enabled_ = value; - if (!value) { - DetachListener(imgui_drawer_.get()); - } else { - AttachListener(imgui_drawer_.get()); - } } -bool Window::OnCreate() { return true; } +bool Window::Open() { + if (phase_ != Phase::kClosedOpenable) { + return true; + } -bool Window::MakeReady() { - imgui_drawer_ = std::make_unique(this); + // For consistency of the behavior of OpenImpl and the initial On*Update + // that should be called as a result of it, reset the actual state to its + // defaults for a closed window. + // Note that this is performed in Open, not after closing, because there's + // only one entry point for opening a window, while closing may be done + // different ways - by actually closing, by destroying, or by failing to call + // OpenImpl - instead of performing this reset in every possible close case, + // just returning these defaults from the actual state getters if + // HasActualState is false. + actual_physical_width_ = 0; + actual_physical_height_ = 0; + has_focus_ = false; + phase_ = Phase::kOpening; + bool platform_open_result = OpenImpl(); + if (!platform_open_result) { + phase_ = Phase::kClosedOpenable; + return false; + } + if (phase_ != Phase::kOpening) { + // The window was closed mid-opening. + return true; + } + phase_ = Phase::kOpen; + + // Call the listeners (OnOpened with all the new state so the listeners are + // aware that they can start interacting with the open Window, and after that, + // in case certain listeners don't handle OnOpened, but rather, only need the + // more granular callbacks, make sure those callbacks receive the new state + // too) for the actual state of the new window (that may be different than the + // desired, depending on how the platform has interpreted the desired state). + { + MonitorUpdateEvent e(this, true, true); + OnMonitorUpdate(e); + } + { + UISetupEvent e(this, true); + WindowDestructionReceiver destruction_receiver(this); + SendEventToListeners([&e](auto listener) { listener->OnOpened(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + SendEventToListeners([&e](auto listener) { listener->OnDpiChanged(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + SendEventToListeners([&e](auto listener) { listener->OnResize(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + if (HasFocus()) { + SendEventToListeners([&e](auto listener) { listener->OnGotFocus(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrListenersUncallable()) { + return true; + } + } + } + + // May now try to create a valid surface (though the window may be in a + // minimized state without the possibility of creating a surface, but that + // will be resolved by the implementation), after OnDpiChanged and OnResize so + // nothing related to painting will be making wrong assumptions about the + // size. + OnSurfaceChanged(true); return true; } -void Window::OnMainMenuChange() { - ForEachListener([](auto listener) { listener->OnMainMenuChange(); }); +void Window::SetFullscreen(bool new_fullscreen) { + if (fullscreen_ == new_fullscreen) { + return; + } + fullscreen_ = new_fullscreen; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewFullscreen(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } } -void Window::OnClose() { - UIEvent e(this); - ForEachListener([&e](auto listener) { listener->OnClosing(&e); }); - on_closing(&e); - ForEachListener([&e](auto listener) { listener->OnClosed(&e); }); - on_closed(&e); +void Window::SetTitle(const std::string_view new_title) { + if (title_ == new_title) { + return; + } + title_ = new_title; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewTitle(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } } -void Window::OnDestroy() { - if (!context_) { +void Window::SetIcon(const void* buffer, size_t size) { + bool reset = !buffer || !size; + WindowDestructionReceiver destruction_receiver(this); + LoadAndApplyIcon(reset ? nullptr : buffer, reset ? 0 : size, CanApplyState()); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetMainMenu(std::unique_ptr new_main_menu) { + // The primary reason for this comparison (of two unique pointers) is + // nullptr == nullptr. + if (main_menu_ == new_main_menu) { + return; + } + // Keep the old menu object existing while it's still being detached from + // the platform window. + std::unique_ptr old_main_menu = std::move(main_menu_); + main_menu_ = std::move(new_main_menu); + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewMainMenu(old_main_menu.get()); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::CompleteMainMenuItemsUpdate() { + if (!main_menu_ || !CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + CompleteMainMenuItemsUpdateImpl(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetMainMenuEnabled(bool enabled) { + if (!main_menu_) { + return; + } + // Not comparing to the actual enabled state, it's a part of the MenuItem, not + // the Window. + // In case enabling (or even disabling) causes menu-related events (like + // pressing) that may execute callbacks potentially destroying the Window via + // the outer architecture. + WindowDestructionReceiver destruction_receiver(this); + main_menu_->SetEnabled(enabled); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + // Modifying the state of the items, notify the implementation so it makes the + // displaying of the main menu consistent. + CompleteMainMenuItemsUpdate(); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::CaptureMouse() { + ++mouse_capture_request_count_; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + // Call even if capturing while the mouse is already assumed to be captured, + // in case something has released it in the OS. + ApplyNewMouseCapture(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::ReleaseMouse() { + assert_not_zero(mouse_capture_request_count_); + if (!mouse_capture_request_count_) { + return; + } + if (--mouse_capture_request_count_) { + return; + } + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewMouseRelease(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetCursorVisibility(CursorVisibility new_cursor_visibility) { + if (cursor_visibility_ == new_cursor_visibility) { + return; + } + CursorVisibility old_cursor_visibility = cursor_visibility_; + cursor_visibility_ = new_cursor_visibility; + if (!CanApplyState()) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ApplyNewCursorVisibility(old_cursor_visibility); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::Focus() { + if (!CanApplyState() || has_focus_) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + FocusImpl(); + if (destruction_receiver.IsWindowDestroyedOrStateInapplicable()) { + return; + } +} + +void Window::SetPresenter(Presenter* presenter) { + if (presenter_ == presenter) { + return; + } + if (presenter_) { + presenter_->SetWindowSurfaceFromUIThread(nullptr, nullptr); + presenter_surface_.reset(); + } + presenter_ = presenter; + if (presenter_) { + presenter_surface_ = CreateSurface(presenter_->GetSupportedSurfaceTypes()); + presenter_->SetWindowSurfaceFromUIThread(this, presenter_surface_.get()); + } +} + +void Window::OnSurfaceChanged(bool new_surface_potentially_exists) { + if (!presenter_) { return; } - imgui_drawer_.reset(); + // Detach the presenter from the old surface before attaching to the new one. + if (presenter_surface_) { + presenter_->SetWindowSurfaceFromUIThread(this, nullptr); + presenter_surface_.reset(); + } - // Context must go last. - context_.reset(); -} - -void Window::Layout() { - UIEvent e(this); - OnLayout(&e); -} - -void Window::Invalidate() {} - -void Window::OnDpiChanged(UIEvent* e) { - // TODO(DrChat): Notify listeners. -} - -void Window::OnResize(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnResize(e); }); -} - -void Window::OnLayout(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnLayout(e); }); -} - -void Window::OnPaint(UIEvent* e) { - if (!context_) { + if (!new_surface_potentially_exists) { return; } - ++frame_count_; - ++fps_frame_count_; - static auto tick_frequency = Clock::QueryHostTickFrequency(); - auto now_ticks = Clock::QueryHostTickCount(); - // Average fps over 1 second. - if (now_ticks > fps_update_time_ticks_ + tick_frequency * 1) { - fps_ = static_cast( - fps_frame_count_ / - (static_cast(now_ticks - fps_update_time_ticks_) / - tick_frequency)); - fps_update_time_ticks_ = now_ticks; - fps_frame_count_ = 0; + presenter_surface_ = CreateSurface(presenter_->GetSupportedSurfaceTypes()); + if (presenter_surface_) { + presenter_->SetWindowSurfaceFromUIThread(this, presenter_surface_.get()); + } +} + +void Window::OnBeforeClose(WindowDestructionReceiver& destruction_receiver) { + // Because events are not sent from closed windows, and to make sure the + // window isn't closed while its surface is still attached to the presenter, + // this must be called before doing what constitutes closing in the platform + // implementation, not after. + + bool was_open = phase_ == Phase::kOpen; + bool was_open_or_opening = was_open || phase_ == Phase::kOpening; + assert_true(was_open_or_opening); + if (!was_open_or_opening) { + return; } - GraphicsContextLock context_lock(context_.get()); + if (was_open) { + phase_ = Phase::kOpenBeforeClosing; - // Prepare ImGui for use this frame. - auto& io = imgui_drawer_->GetIO(); - if (!last_paint_time_ticks_) { - io.DeltaTime = 0.0f; - last_paint_time_ticks_ = now_ticks; + // If the window was focused, notify the listeners that focus is being lost + // because the window is being closed (the implementation usually wouldn't + // be sending any events to the listeners after OnClosing even if the OS + // actually sends the focus loss event as part of the closing process). + OnFocusUpdate(false, destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + + { + UIEvent e(this); + SendEventToListeners([&e](auto listener) { listener->OnClosing(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + + // Disconnect from the surface without connecting to the new one (after the + // listeners so they don't try to reconnect afterwards). + OnSurfaceChanged(false); + } + + phase_ = Phase::kClosing; +} + +void Window::OnAfterClose() { + assert_true(phase_ == Phase::kClosing); + if (phase_ != Phase::kClosing) { + return; + } + phase_ = (innermost_listener_iteration_context_ || + innermost_input_listener_iteration_context_) + ? Phase::kClosedLeavingListeners + : Phase::kClosedOpenable; +} + +void Window::OnDpiChanged(UISetupEvent& e, + WindowDestructionReceiver& destruction_receiver) { + SendEventToListeners([&e](auto listener) { listener->OnDpiChanged(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::OnMonitorUpdate(MonitorUpdateEvent& e) { + if (presenter_surface_) { + presenter_->OnSurfaceMonitorUpdateFromUIThread( + e.old_monitor_potentially_disconnected()); + } +} + +bool Window::OnActualSizeUpdate( + uint32_t new_physical_width, uint32_t new_physical_height, + WindowDestructionReceiver& destruction_receiver) { + if (actual_physical_width_ == new_physical_width && + actual_physical_height_ == new_physical_height) { + return false; + } + actual_physical_width_ = new_physical_width; + actual_physical_height_ = new_physical_height; + // The listeners may reference the presenter, update the presenter first. + if (presenter_surface_) { + presenter_->OnSurfaceResizeFromUIThread(); + } + UISetupEvent e(this); + SendEventToListeners([&e](auto listener) { listener->OnResize(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return true; + } + return true; +} + +void Window::OnFocusUpdate(bool new_has_focus, + WindowDestructionReceiver& destruction_receiver) { + if (has_focus_ == new_has_focus) { + return; + } + has_focus_ = new_has_focus; + UISetupEvent e(this); + if (has_focus_) { + SendEventToListeners([&e](auto listener) { listener->OnGotFocus(e); }, + destruction_receiver); } else { - io.DeltaTime = (now_ticks - last_paint_time_ticks_) / - static_cast(tick_frequency); - last_paint_time_ticks_ = now_ticks; + SendEventToListeners([&e](auto listener) { listener->OnLostFocus(e); }, + destruction_receiver); } - io.DisplaySize = ImVec2(static_cast(scaled_width()), - static_cast(scaled_height())); - - bool can_swap = context_->BeginSwap(); - if (context_->WasLost()) { - on_context_lost(e); + if (destruction_receiver.IsWindowDestroyed()) { return; } - if (!can_swap) { - // Surface not available. +} + +void Window::OnPaint(bool force_paint) { + if (is_painting_) { return; } + is_painting_ = true; + if (presenter_surface_) { + presenter_->PaintFromUIThread(force_paint); + } + is_painting_ = false; +} - ImGui::NewFrame(); - - ForEachListener([e](auto listener) { listener->OnPainting(e); }); - on_painting(e); - ForEachListener([e](auto listener) { listener->OnPaint(e); }); - on_paint(e); - - // Flush ImGui buffers before we swap. - ImGui::Render(); - imgui_drawer_->RenderDrawLists(); - - ForEachListener([e](auto listener) { listener->OnPainted(e); }); - on_painted(e); - - context_->EndSwap(); - - // If animations are running, reinvalidate immediately. - if (kContinuousRepaint) { - Invalidate(); +void Window::OnFileDrop(FileDropEvent& e, + WindowDestructionReceiver& destruction_receiver) { + SendEventToListeners([&e](auto listener) { listener->OnFileDrop(e); }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; } } -void Window::OnFileDrop(FileDropEvent* e) { - on_file_drop(e); - ForEachListener([e](auto listener) { listener->OnFileDrop(e); }); +void Window::OnKeyDown(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyDown(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnVisible(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnVisible(e); }); +void Window::OnKeyUp(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyUp(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnHidden(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnHidden(e); }); +void Window::OnKeyChar(KeyEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnKeyChar(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnGotFocus(UIEvent* e) { - ForEachListener([e](auto listener) { listener->OnGotFocus(e); }); +void Window::OnMouseDown(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseDown(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnLostFocus(UIEvent* e) { - modifier_shift_pressed_ = false; - modifier_cntrl_pressed_ = false; - modifier_alt_pressed_ = false; - modifier_super_pressed_ = false; - ForEachListener([e](auto listener) { listener->OnLostFocus(e); }); +void Window::OnMouseMove(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseMove(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } } -void Window::OnKeyPress(KeyEvent* e, bool is_down, bool is_char) { - if (!is_char) { - switch (e->virtual_key()) { - case VirtualKey::kShift: - modifier_shift_pressed_ = is_down; - break; - case VirtualKey::kControl: - modifier_cntrl_pressed_ = is_down; - break; - case VirtualKey::kMenu: - modifier_alt_pressed_ = is_down; - break; - case VirtualKey::kLWin: - modifier_super_pressed_ = is_down; - break; - default: - break; +void Window::OnMouseUp(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseUp(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::OnMouseWheel(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver) { + PropagateEventThroughInputListeners( + [&e](auto listener) { + listener->OnMouseWheel(e); + return e.is_handled(); + }, + destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } +} + +void Window::SendEventToListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver) { + if (!CanSendEventsToListeners()) { + return; + } + ListenerIterationContext iteration_context( + innermost_listener_iteration_context_); + innermost_listener_iteration_context_ = &iteration_context; + while (iteration_context.next_index < listeners_.size()) { + // iteration_context.next_index may be changed during the execution of the + // listener if the list of the listeners is modified by it - don't assume + // that after the call iteration_context.next_index will be the same as + // iteration_context.next_index + 1 before it. + fn(listeners_[iteration_context.next_index++]); + if (destruction_receiver.IsWindowDestroyed()) { + // The window was destroyed by the listener, can't access anything in + // *this anymore, including innermost_listener_iteration_context_ which + // has to be left in an indeterminate state. + return; + } + if (!CanSendEventsToListeners()) { + // The listener has put the window in a state in which the window can't + // send events anymore. + break; } } + assert_true(innermost_listener_iteration_context_ == &iteration_context); + innermost_listener_iteration_context_ = + innermost_listener_iteration_context_->outer_context; + if (phase_ == Phase::kClosedLeavingListeners && + !innermost_listener_iteration_context_ && + !innermost_input_listener_iteration_context_) { + phase_ = Phase::kClosedOpenable; + } } -void Window::OnKeyDown(KeyEvent* e) { - on_key_down(e); - if (e->is_handled()) { +void Window::PropagateEventThroughInputListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver) { + if (!CanSendEventsToListeners()) { return; } - TryForEachListener([e](auto listener) { - listener->OnKeyDown(e); - return e->is_handled(); - }); - OnKeyPress(e, true, false); -} - -void Window::OnKeyUp(KeyEvent* e) { - on_key_up(e); - if (e->is_handled()) { - return; + InputListenerIterationContext iteration_context( + innermost_input_listener_iteration_context_, input_listeners_.crbegin()); + innermost_input_listener_iteration_context_ = &iteration_context; + while (iteration_context.next_iterator != input_listeners_.crend()) { + // The current iterator may be invalidated, and + // iteration_context.next_iterator may be changed, during the execution of + // the listener if the list of the listeners is modified by it - don't + // assume that after the call iteration_context.next_iterator will be the + // same as std::next(iteration_context.next_iterator) before it. + iteration_context.current_z_order = iteration_context.next_iterator->first; + bool event_handled = fn((iteration_context.next_iterator++)->second); + if (destruction_receiver.IsWindowDestroyed()) { + // The window was destroyed by the listener, can't access anything in + // *this anymore, including innermost_listener_iteration_context_ which + // has to be left in an indeterminate state. + return; + } + if (event_handled) { + break; + } + if (!CanSendEventsToListeners()) { + // The listener has put the window in a state in which the window can't + // send events anymore. + break; + } } - TryForEachListener([e](auto listener) { - listener->OnKeyUp(e); - return e->is_handled(); - }); - OnKeyPress(e, false, false); -} - -void Window::OnKeyChar(KeyEvent* e) { - OnKeyPress(e, true, true); - on_key_char(e); - ForEachListener([e](auto listener) { listener->OnKeyChar(e); }); - OnKeyPress(e, false, true); -} - -void Window::OnMouseDown(MouseEvent* e) { - on_mouse_down(e); - if (e->is_handled()) { - return; + assert_true(innermost_input_listener_iteration_context_ == + &iteration_context); + innermost_input_listener_iteration_context_ = + innermost_input_listener_iteration_context_->outer_context; + if (phase_ == Phase::kClosedLeavingListeners && + !innermost_listener_iteration_context_ && + !innermost_input_listener_iteration_context_) { + phase_ = Phase::kClosedOpenable; } - TryForEachListener([e](auto listener) { - listener->OnMouseDown(e); - return e->is_handled(); - }); -} - -void Window::OnMouseMove(MouseEvent* e) { - on_mouse_move(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseMove(e); - return e->is_handled(); - }); -} - -void Window::OnMouseUp(MouseEvent* e) { - on_mouse_up(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseUp(e); - return e->is_handled(); - }); -} - -void Window::OnMouseWheel(MouseEvent* e) { - on_mouse_wheel(e); - if (e->is_handled()) { - return; - } - TryForEachListener([e](auto listener) { - listener->OnMouseWheel(e); - return e->is_handled(); - }); } } // namespace ui diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index 2627c7ca0..564eaeaea 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,209 +10,711 @@ #ifndef XENIA_UI_WINDOW_H_ #define XENIA_UI_WINDOW_H_ +#include +#include +#include #include #include +#include -#include "xenia/base/delegate.h" #include "xenia/base/platform.h" -#include "xenia/ui/graphics_context.h" #include "xenia/ui/menu_item.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/surface.h" #include "xenia/ui/ui_event.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app_context.h" namespace xe { namespace ui { -typedef void* NativePlatformHandle; -typedef void* NativeWindowHandle; - -class ImGuiDrawer; - class Window { public: - static std::unique_ptr Create(WindowedAppContext& app_context_, - const std::string& title); + // Transitions between these phases is sequential and looped (and >= and <= + // can be used for openness checks, for closedness checks ! of >= and <= is + // needed due to looping), with the exception of kDeleting that may be entered + // from any other state (with an assertion for that not being done during + // kOpening though as that's extremely dangerous and would require a lot of + // handling in OpenImpl on all platforms) as the Window object may be deleted + // externally at any moment, and the Window will have no control anymore when + // that happens. Another exception is that the window may be closed in the + // platform during kOpening - in this case, it will skip kOpenBeforeClosing + // and go directly to kClosing and beyond. + enum class Phase { + // The window hasn't been opened yet, or has been fully closed and can be + // reopened. + // No native window - external state updates change only the desired state, + // don't go to the implementation immediately. + // No actual state. + // Listeners are not called. + kClosedOpenable, + // OpenImpl is being invoked, the implementation is performing initial + // setup. + // External state changes are functionally near-impossible as OpenImpl + // mostly isn't able to communicate with external Xenia code that may have + // any effect on the Window, to avoid interference during the native window + // setup which may be pretty complex - and also, this is the phase in which + // the native window is being created, so there's no guarantee that the + // native window exists throughout this phase. + // However, it's still not strictly enforceable that OpenImpl will not cause + // any interaction with the Window - it may happen, for instance, if + // OpenImpl causes the OS to execute the pending functions in the + // WindowedAppContext that might have been, for example, left over from when + // the window was still open last time. Therefore, for the reason of state + // consistency within OpenImpl, all external state changes are simply + // dropped in this phase. + // However, the desired state may be updated by the implementation during + // OpenImpl still, but via the Update functions (if the implementation or + // the OS, for instance, clamps the size of the window during creation, or + // refuses to enter fullscreen). + // Actual state is first populated during this phase, and it's readable + // (with its level of completeness at the specific point in time) for the + // internal purposes of the implementation. + // Listeners are not called so the implementation can perform all the setup + // without outer interference (the common code calls some to let the + // listeners be aware of the initial state when the window enters kOpen + // anyway). + // Note: Closing may occur in the platform during kOpening - skip + // kOpenBeforeClosing in this case while closing. + kOpening, + // Fully interactive. + // The native window exists, external state changes are applied immediately + // (or at least immediately requested to be applied shortly after, but the + // implementation must make sure that, for instance, if SetFullscreen is + // successfully called, but the window will actually enter fullscreen only + // at the next platform event loop tick, IsFullscreen will start returning + // true immediately). + // The desired state can be updated as feedback from the implementation. + // Actual state can be retrieved. + // Listeners are called. + // The only state in which a non-null Surface can be created (it's destroyed + // after entering kClosing). + kOpen, + // OnBeforeClose is being invoked. + // The native window still exists, this is mostly like kOpen, but with no + // way of creating a Surface (it's becoming destroyed in this state so the + // native window can be destroyed safely in the next phase) or recursively + // requesting closing - for consistency during closing within the platform, + // state changes also behave like in kOpen. + // Listeners are still called as normal, primarily because this is where the + // OnClosing listener function is invoked, but reopening the window from a + // listener is not possible for state consistency during closing. + kOpenBeforeClosing, + // OnBeforeClose has completed, but OnAfterClose hasn't been called yet for + // the implementation to confirm that it has finished destroying the native + // window being closed. This state exists to prevent the situation in which + // the Window is somehow reopened in the middle of the implementation's + // internal work in closing. + // The implementation must detach from the native window and destroy it in + // this phase. + // The native window is being destroyed - external state updates change only + // the desired state, don't go to the implementation immediately. + // Actual state is still queryable for internal purposes of the + // implementation. + // Listeners are not called. + kClosing, + // OnBeforeClose has completed, but the close has occurred from a listener, + // and the call stack of listeners still hasn't been exited. + // This state exists to prevent the situation in which the Window is being + // closed and then reopened in the middle of the implementation's internal + // work in event handlers. For example, let's assume putting a window (HWND) + // in the fullscreen state requires removing window decorations + // (SetWindowLong) and resizing the window (SetWindowPos), both being able + // to invoke the resize handler (WM_SIZE) and thus the resize listener. In + // this case, consider the following situation: + // - SetWindowLong called for HWND. + // - WM_SIZE arrives. + // - Listener's OnResize called. + // - Listener's OnResize does RequestClose, destroying the current HWND. + // - Listener's OnResize does Open, creating a new HWND. + // - SetWindowPos called for HWND, which is different now. + // Here, SetWindowLong will be called for one native window, but then it + // will be replaced, and SetWindowPos will be called for a different one. + // No native window - external state updates change only the desired state, + // don't go to the implementation immediately. + // No actual state. + // Listeners are not called. + kClosedLeavingListeners, + // The destructor has been called - should transition into this before doing + // anything not only in the common, but in the implementation's destructor + // as well. The transition must be done regardless of the previous phase as + // there's no way the Window can stop its destruction from now on. This is + // mostly similar to kClosedLeavingListeners, except there's no way to leave + // this phase. + kDeleting, + }; + + enum class CursorVisibility { + kVisible, + // Temporarily revealed, hidden if not interacting with the mouse. + kAutoHidden, + kHidden, + }; + + static std::unique_ptr Create(WindowedAppContext& app_context, + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height); virtual ~Window(); WindowedAppContext& app_context() const { return app_context_; } - virtual NativePlatformHandle native_platform_handle() const = 0; - virtual NativeWindowHandle native_handle() const = 0; - - MenuItem* main_menu() const { return main_menu_.get(); } - void set_main_menu(std::unique_ptr main_menu) { - main_menu_ = std::move(main_menu); - OnMainMenuChange(); + Phase phase() const { return phase_; } + bool HasActualState() const { + // kOpening - for internal use by the implementation. + // kOpen, kOpenBeforeClosing - for both external and internal use. + // kClosing - for internal use by the implementation. + return phase_ >= Phase::kOpening && phase_ <= Phase::kClosing; } - virtual void EnableMainMenu() = 0; - virtual void DisableMainMenu() = 0; + void AddListener(WindowListener* listener); + void RemoveListener(WindowListener* listener); + void AddInputListener(WindowInputListener* listener, size_t z_order); + void RemoveInputListener(WindowInputListener* listener); - const std::string& title() const { return title_; } - virtual bool set_title(const std::string_view title) { - if (title == title_) { - return false; + // `false` is returned only in case of an error while trying to perform the + // platform window opening. If the window is already open, or just can't be + // reopened in the current phase (as in this case it's assumed that the outer + // will handle this situation properly and won't, for instance, leave a + // process without windows - it will quit the application in OnBeforeClose of + // the window closing of which was initiated before or even during opening, + // for instance), `true` is returned. The functions of WindowListeners will be + // called only for a newly opened platform window - and the listeners may + // close or even destroy the window, in which case this function will still + // return `true` to differentiate from an actual error - if it's really + // necessary that the platform window is open after the call, check phase() + // after calling. + bool Open(); + // The call may or may not close the window immediately, depending on the + // platform (phase() may still return an open phase, and events may still be + // sent after the call). Use phase() to check if closing has actually + // happened immediately. + void RequestClose() { + // Don't allow external close requests during opening for state consistency + // inside OpenImpl (if an internal close happens during OpenImpl, the + // implementation will be aware of that at least), and don't allow closing + // twice. + if (phase_ != Phase::kOpen) { + return; } - title_ = title; - return true; + RequestCloseImpl(); + // Must not doing anything else with *this as callbacks might have been + // triggered during closing (if it has actually even happened), and the + // Window might have been deleted. } - virtual bool SetIcon(const void* buffer, size_t size) = 0; + // The `public` state setters are for calling from outside. + // The implementation must use the public getters to obtain the desired state + // while applying, but for updating the actual state, or for overriding the + // desired state, the `protected` On*Update functions must be used (overall + // the On* functions are for the implementation's feedback). + + virtual uint32_t GetMediumDpi() const { return 96; } + uint32_t GetDpi() const { + uint32_t dpi = GetLatestDpiImpl(); + return dpi ? dpi : GetMediumDpi(); + } + + // Round trips are not guaranteed to return the same results. + static constexpr uint32_t ConvertSizeDpi(uint32_t size, uint32_t new_dpi, + uint32_t old_dpi) { + // Always rounding up to prevent zero sizes (unless the input is zero) as + // well as gaps at the edge. + return uint32_t((uint64_t(size) * new_dpi + (old_dpi - 1)) / old_dpi); + } + uint32_t SizeToLogical(uint32_t size) const { + return ConvertSizeDpi(size, GetMediumDpi(), GetDpi()); + } + uint32_t SizeToPhysical(uint32_t size) const { + return ConvertSizeDpi(size, GetDpi(), GetMediumDpi()); + } + static constexpr int32_t ConvertPositionDpi(int32_t position, + uint32_t new_dpi, + uint32_t old_dpi) { + // Rounding to the nearest mostly similar to Windows MulDiv. + // Plus old_dpi / 2 for positive values, minus old_dpi / 2 for negative + // values for consistent rounding for both positive and negative values (as + // the `/` operator rounds towards zero). + // Example: + // (-3 - 1) / 3 == -1 + // (-2 - 1) / 3 == -1 + // (-1 - 1) / 3 == 0 + // --- + // (0 + 1) / 3 == 0 + // (1 + 1) / 3 == 0 + // (2 + 1) / 3 == 1 + return int32_t((int64_t(position) * new_dpi + + int32_t(old_dpi >> 1) * (position < 0 ? -1 : 1)) / + old_dpi); + } + int32_t PositionToLogical(int32_t position) const { + return ConvertPositionDpi(position, GetMediumDpi(), GetDpi()); + } + int32_t PositionToPhysical(int32_t position) const { + return ConvertPositionDpi(position, GetDpi(), GetMediumDpi()); + } + + // The desired logical size of the window when it's not maximized, regardless + // of the current state of the window (maximized, fullscreen, etc.) + // The implementation may update it, for instance, to clamp it, or when the + // user resizes a non-maximized window. + uint32_t GetDesiredLogicalWidth() const { return desired_logical_width_; } + uint32_t GetDesiredLogicalHeight() const { return desired_logical_height_; } + + // 0 width or height may be returned even in case of an open window with a + // valid non-zero-area surface depending on the platform. + uint32_t GetActualPhysicalWidth() const { + return HasActualState() ? actual_physical_width_ : 0; + } + uint32_t GetActualPhysicalHeight() const { + return HasActualState() ? actual_physical_height_ : 0; + } + uint32_t GetActualLogicalWidth() const { + return SizeToLogical(GetActualPhysicalWidth()); + } + uint32_t GetActualLogicalHeight() const { + return SizeToLogical(GetActualPhysicalHeight()); + } + + // Desired state stored by the common Window, modifiable both externally and + // by the implementation (including from SetFullscreen itself). + virtual bool IsFullscreen() const { return fullscreen_; } + void SetFullscreen(bool new_fullscreen); + + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + const std::string& GetTitle() const { return title_; } + void SetTitle(const std::string_view new_title); + + // Desired state stored in a platform-dependent way in the implementation, + // externally modifiable, read-only by the implementation unless from the + // LoadAndApplyIcon implementation. The icon is in Windows .ico format. + // Provide null buffer and / or zero size to reset the icon. + void SetIcon(const void* buffer, size_t size); void ResetIcon() { SetIcon(nullptr, 0); } - virtual bool CaptureMouse() = 0; - virtual bool ReleaseMouse() = 0; + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + void SetMainMenu(std::unique_ptr new_main_menu); + void CompleteMainMenuItemsUpdate(); + void SetMainMenuEnabled(bool enabled); - virtual bool is_fullscreen() const { return false; } - virtual void ToggleFullscreen(bool fullscreen) {} - - virtual bool is_bordered() const { return false; } - virtual void set_bordered(bool enabled) {} - - virtual int get_medium_dpi() const { return 96; } - virtual int get_dpi() const { return get_medium_dpi(); } - virtual float get_dpi_scale() const { - return float(get_dpi()) / float(get_medium_dpi()); + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + bool IsMouseCaptureRequested() const { + return mouse_capture_request_count_ != 0; } + void CaptureMouse(); + void ReleaseMouse(); - bool has_focus() const { return has_focus_; } - virtual void set_focus(bool value) { has_focus_ = value; } + // Desired state stored by the common Window, externally modifiable, read-only + // in the implementation. + CursorVisibility GetCursorVisibility() const { return cursor_visibility_; } + // Setting this to kAutoHidden from any _other_ visibility should hide the + // cursor immediately - for instance, if the external code wants to auto-hide + // the cursor in fullscreen, to allow going into the fullscreen mode to hide + // the cursor instantly. + void SetCursorVisibility(CursorVisibility new_cursor_visibility); - bool is_cursor_visible() const { return is_cursor_visible_; } - virtual void set_cursor_visible(bool value) { is_cursor_visible_ = value; } + bool HasFocus() const { return HasActualState() ? has_focus_ : false; } + // May be applied in a delayed way or dropped at all, HasFocus will not + // necessarily be true immediately. + void Focus(); - // TODO(Triang3l): Don't scale for guest output - use physical pixels. Use - // logical pixels only for the immediate drawer. - int32_t width() const { return width_; } - int32_t height() const { return height_; } - int32_t scaled_width() const { return int32_t(width_ * get_dpi_scale()); } - int32_t scaled_height() const { return int32_t(height_ * get_dpi_scale()); } + // TODO(Triang3l): A resize function, primarily for snapping externally to + // 1280x720, 1920x1080, and other 1:1 resolutions. It will need to resize the + // window (to a desired logical size - the actual physical size is entirely + // the feedback of the implementation) in the normal state, and possibly also + // un-maximize (and possibly un-fullscreen) it (but this choice will possibly + // need to be exposed to the caller). Because it's currently not needed, it's + // not implemented to avoid platform-specific complexities regarding + // maximization, DPI, etc. - virtual void Resize(int32_t width, int32_t height) { - width_ = width; - height_ = height; + void SetPresenter(Presenter* presenter); + + // Request repainting of the surface. Can be called from non-UI threads as + // long as they know the Surface exists and isn't in the middle of being + // changed to another (the synchronization of this fact between the UI thread + // and the caller thread must be done externally through OnSurfaceChanged). + void RequestPaint() { + if (presenter_surface_) { + RequestPaintImpl(); + } } - virtual void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - width_ = right - left; - height_ = bottom - top; - } - - GraphicsContext* context() const { return context_.get(); } - ImGuiDrawer* imgui_drawer() const { return imgui_drawer_.get(); } - bool is_imgui_input_enabled() const { return is_imgui_input_enabled_; } - void set_imgui_input_enabled(bool value); - - void AttachListener(WindowListener* listener); - void DetachListener(WindowListener* listener); - - virtual bool Initialize() { return true; } - void set_context(std::unique_ptr context) { - context_ = std::move(context); - if (context_) { - MakeReady(); + void RequestPresenterUIPaintFromUIThread() { + if (presenter_) { + presenter_->RequestUIPaintFromUIThread(); } } - void Layout(); - virtual void Invalidate(); - - virtual void Close() = 0; - - public: - Delegate on_closing; - Delegate on_closed; - - Delegate on_painting; - Delegate on_paint; - Delegate on_painted; - Delegate on_context_lost; - - Delegate on_file_drop; - - Delegate on_key_down; - Delegate on_key_up; - Delegate on_key_char; - - Delegate on_mouse_down; - Delegate on_mouse_move; - Delegate on_mouse_up; - Delegate on_mouse_wheel; - protected: - Window(WindowedAppContext& app_context, const std::string& title); + // The receiver, which must never be instantiated in the Window object itself + // (rather, usually it should be created as a local variable, because only + // LIFO-ordered creation and deletion of these is supported), that allows + // deletion of the Window from within an event handler (which may invoke a + // WindowListener, and window listeners are allowed to destroy windows; also + // they may execute, for instance, the functions requested to be executed in + // the UI thread in the WindowedAppContext, which are also allowed to destroy + // windows - because if the former wasn't allowed, the latter would be + // required to destroy windows as a result of UI interaction) to be caught by + // functions inside the Window in order to stop interacting with `*this` and + // returning after this happens. + // Note that the receivers are signaled in the *end* of the destruction of the + // common Window, when truly nothing can be done with it anymore, so it's safe + // to assume that right after the creation of the WindowDestructionReceiver, + // it will still be in an unsignaled state even if it's used somewhere in the + // destructor. The reason is that the users of the WindowDestructionReceiver + // are expected to stop accessing the Window *immediately* once + // IsWindowDestroyed becomes `true`, and to leave it in a potentially + // indeterminate state - but the code executed subsequently in the destructor + // may still use that state meaningfully. + class WindowDestructionReceiver { + public: + explicit WindowDestructionReceiver(Window* window) : window_(window) { + if (window_) { + outer_receiver_ = window_->innermost_destruction_receiver_; + window_->innermost_destruction_receiver_ = this; + } + } - void ForEachListener(std::function fn); - void TryForEachListener(std::function fn); + ~WindowDestructionReceiver() { + // If the window is not null, removal from the stack must happen + // regardless of `phase_ == Phase::kDeleting`, because the window + // destructor iterates the receivers after EnterDestructor(), and if the + // receiver is not removed in this case, the destructor will do + // use-after-free. + if (window_) { + // Only LIFO order is supported (normally through RAII). + assert_true(window_->innermost_destruction_receiver_ == this); + window_->innermost_destruction_receiver_ = outer_receiver_; + } + } - virtual bool MakeReady(); + bool IsWindowDestroyed() const { return window_ == nullptr; } - virtual bool OnCreate(); - virtual void OnMainMenuChange(); - virtual void OnClose(); - virtual void OnDestroy(); + // Helper functions for common usages of the receiver. Unlike + // IsWindowDestroyed, these, however, may return false immediately on + // creation. + // Primarily for the implementation (most importantly its native event + // handler), to stop interacting with the native window given that it was + // possible before the function call it's guarded with. + bool IsWindowDestroyedOrClosed() const { + return IsWindowDestroyed() || window_->IsClosed(); + } + // For guarding Apply* calls if one state setter needs to make multiple of + // them (or just detecting if it's okay to call Apply*). + bool IsWindowDestroyedOrStateInapplicable() const { + return IsWindowDestroyed() || !window_->CanApplyState(); + } + bool IsWindowDestroyedOrListenersUncallable() const { + return IsWindowDestroyed() || !window_->CanSendEventsToListeners(); + } - virtual void OnDpiChanged(UIEvent* e); - virtual void OnResize(UIEvent* e); - virtual void OnLayout(UIEvent* e); - virtual void OnPaint(UIEvent* e); - virtual void OnFileDrop(FileDropEvent* e); + private: + // The Window must set window_ to nullptr in its destructor. + friend Window; + Window* window_; + WindowDestructionReceiver* outer_receiver_ = nullptr; + }; - virtual void OnVisible(UIEvent* e); - virtual void OnHidden(UIEvent* e); + // Like in the Windows Media Player. + // A more modern Windows example, Movies & TV in Windows 11 21H2, has 5000, + // but it's too long especially for highly dynamic games. + // Implementations may use different values according to the platform's UX + // conventions. + static constexpr uint32_t kDefaultCursorAutoHideMilliseconds = 3333; - virtual void OnGotFocus(UIEvent* e); - virtual void OnLostFocus(UIEvent* e); + Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); - virtual void OnKeyDown(KeyEvent* e); - virtual void OnKeyUp(KeyEvent* e); - virtual void OnKeyChar(KeyEvent* e); + // If implementation-specific destruction happens, should be called in the + // beginning of the implementation's destructor so the implementation can + // destroy the platform window without doing something unsafe in destruction. + void EnterDestructor() { + phase_ = Phase::kDeleting; + // Disconnect from the surface before destroying the window behind it. + OnSurfaceChanged(false); + } - virtual void OnMouseDown(MouseEvent* e); - virtual void OnMouseMove(MouseEvent* e); - virtual void OnMouseUp(MouseEvent* e); - virtual void OnMouseWheel(MouseEvent* e); + // For an open window, the implementation should return the current DPI for + // the window. For a non-open one, it should be the closest approximation, + // such as the last DPI from an existing window, the system DPI, or just the + // medium DPI (0 returned from it will also be treated as medium DPI). + virtual uint32_t GetLatestDpiImpl() const { return GetMediumDpi(); } - void OnKeyPress(KeyEvent* e, bool is_down, bool is_char); + // Deletion of the window may (and must) not happen in OpenImpl, the listeners + // are deferred, so there's no need to use WindowDestructionReceiver in it. + // In case of failure, the implementation must not leave itself in an + // indeterminate state, so another attempt to open the window can be made. + // The implementation must apply the following desired state if it needs it, + // directly (not via Set* methods as they will be dropped during OpenImpl + // since the window is not fully open yet): + // - Title (GetTitle()). + // - Icon (from the last LoadAndApplyIcon call). + // - Main menu (GetMainMenu()) and its enablement. + // - Desired logical size (GetDesiredLogicalWidth() / Height(), taking into + // account that the main menu, during the initial opening, should not be + // included in this size - it specifies the client area that painting will + // be done to), within the capabilities of the platform (may be clamped by + // the OS, for instance - in this case, OnDesiredLogicalSizeUpdate may be + // called from within OpenImpl to store the clamped size for later). + // - Fullscreen (GetFullscreen()) - however, if possible, the calculations + // that would normally be done for a non-fullscreen window in OpenImpl + // should also be done if entering fullscreen, including the menu-related + // ones - first, the usual windowed geometry calculations should be done, + // and then fullscreen should be entered; but preferably still entering + // fullscreen before actually showing a visible window to the user for a + // seamless transition. + // - Mouse capture (IsMouseCaptureRequested()). + // - Cursor visibility (GetCursorVisibility()). + // Also, as a result of the OpenImpl call, these function should be called + // (immediately from within OpenImpl directly or indirectly through the native + // event handling, or shortly after during the UI main loop) to provide the + // initial actual state to the common Window code so it returns the correct + // values: + // - OnActualSizeUpdate, at least if the window isn't opened as not yet + // visible on screen (otherwise the size will be assumed to be 0x0 until the + // next size update caused by something likely requiring user interaction). + // - OnFocusUpdate, at least if the focus has been obtained (otherwise the + // window will be assumed to be not in focus until it goes into the focus + // again). + // Also, if some of the desired state that may be updated by the + // implementation could not be applied (such as the fullscreen mode), and + // certain values of the implementation state are either normally + // differentiated within the implementation or are just meaningful considering + // the platform's defaults (for instance, the platform inherently supports + // only fullscreen, possibly doesn't have a concept of windows at all), it's + // recommended to call the appropriate On*Update functions to update the + // desired state to the actual one. + virtual bool OpenImpl() = 0; + virtual void RequestCloseImpl() = 0; + + // Apply* are called only if CanApplyState() is true (unless the function + // should do more than just applying, such as also updating the desired state + // in a platform-dependent way - see each individual function). + // ApplyNew* means that the value has actually been changed to something + // different than it was previously. + virtual void ApplyNewFullscreen() {} + virtual void ApplyNewTitle() {} + // can_apply_state_in_current_phase whether the window is in a life cycle + // phase that would normally accept Apply calls (the native window surely + // exists), since this function may be called in closed states too to update + // the desired icon (since it's stored in the implementation) - the + // implementation may, however, ignore it and use a more granular check of the + // existence of the native window and the safety of updating the icon for + // better internal state consistency. The icon is in Windows .ico format. If + // the buffer is null or the size is 0, the icon should be reset to the + // default one. Returns whether the icon has been updated successfully. + virtual void LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) {} + MenuItem* GetMainMenu() const { return main_menu_.get(); } + // May be called to add, replace or remove the main menu. + virtual void ApplyNewMainMenu(MenuItem* old_main_menu) {} + // If there's main menu, and state can be applied, will be called to make the + // implementation's state consistent with the new state of the MenuItems of + // the main menu after changes have been made to them. + virtual void CompleteMainMenuItemsUpdateImpl() {} + // Will be called even if capturing while the mouse is already assumed to be + // captured, in case something has released it in the OS. + virtual void ApplyNewMouseCapture() {} + virtual void ApplyNewMouseRelease() {} + virtual void ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) {} + // If state can be applied, this is called to request bringing the window into + // focus (and once that's done by the OS, update the actual focus state). Does + // nothing otherwise (focus can't be requested before the window is open, a + // closed window is always assumed to be not in focus). + virtual void FocusImpl() {} + + Presenter* presenter() const { return presenter_; } + bool HasSurface() const { return presenter_surface_ != nullptr; } + // If new_surface_potentially_exists is false, creation of the new surface for + // the window won't be updated, and it may be called from the destructor (via + // EnterDestructor to destroy the surface before destroying what it depends + // on) as no virtual functions (including CreateSurface) will be called. + // This function is nonvirtual itself for this reason as well. + void OnSurfaceChanged(bool new_surface_potentially_exists); + // Called only for an open window. + virtual std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) = 0; + // Called only if the Surface exists. + virtual void RequestPaintImpl() = 0; + + // Will also disconnect the surface if needed. + void OnBeforeClose(WindowDestructionReceiver& destruction_receiver); + void OnAfterClose(); + + // These functions may usually also be called as part of the opening process + // from within OpenImpl (directly or through the platform event handler + // invoked during it) to actualize the state for the newly createad window, + // especially if it's different than the desired one. + void OnDpiChanged(UISetupEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMonitorUpdate(MonitorUpdateEvent& e); + // For calling when the platform changes something in the non-maximized, + // non-fullscreen size of the window. + void OnDesiredLogicalSizeUpdate(uint32_t new_desired_logical_width, + uint32_t new_desired_logical_height) { + desired_logical_width_ = new_desired_logical_width; + desired_logical_height_ = new_desired_logical_height; + } + // If the size of the client area is the same as the currently assumed one + // (the desired / last size for a newly opened / reopened window, the last + // actual size for an already open window), does nothing and returns false. + // Otherwise, updates the size, notifies what depends on the size about the + // change, and returns true. Not storing the new size in the UISetupEvent + // because a resize listener may request another resize, in which case it will + // be outdated - listeners must query the new physical size from the window + // explicitly. + bool OnActualSizeUpdate(uint32_t new_physical_width, + uint32_t new_physical_height, + WindowDestructionReceiver& destruction_receiver); + void OnDesiredFullscreenUpdate(bool new_fullscreen) { + fullscreen_ = new_fullscreen; + } + void OnFocusUpdate(bool new_has_focus, + WindowDestructionReceiver& destruction_receiver); + + // Pass true as force_paint in case the platform can't retain the image from + // the previous paint so it won't be skipped if there are no content updates. + void OnPaint(bool force_paint = false); + + void OnFileDrop(FileDropEvent& e, + WindowDestructionReceiver& destruction_receiver); + + void OnKeyDown(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + void OnKeyUp(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + void OnKeyChar(KeyEvent& e, WindowDestructionReceiver& destruction_receiver); + + void OnMouseDown(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseMove(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseUp(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + void OnMouseWheel(MouseEvent& e, + WindowDestructionReceiver& destruction_receiver); + + private: + struct ListenerIterationContext { + explicit ListenerIterationContext(ListenerIterationContext* outer_context, + size_t first_index = 0) + : outer_context(outer_context), next_index(first_index) {} + // To support nested listener calls, in case a listener does some + // interaction with the window that results in more events being triggered + // (such as calling Windows API functions that return a result from a + // message handled by a window, rather that simply enqueueing the message). + ListenerIterationContext* outer_context; + // Using indices, not iterators, because after the erasure, the adjustment + // must be done for the vector element indices that would be in the iterator + // range that would be invalidated. + size_t next_index; + }; + + struct InputListenerIterationContext { + explicit InputListenerIterationContext( + InputListenerIterationContext* outer_context, + std::multimap::const_reverse_iterator + first_iterator, + size_t first_z_order = SIZE_MAX) + : outer_context(outer_context), + next_iterator(first_iterator), + current_z_order(first_z_order) {} + // To support nested listener calls. + InputListenerIterationContext* outer_context; + // Reverse iterator because input handlers with a higher Z order index may + // correspond to what's displayed on top of what has a lower Z order index, + // so what's higher may consum the event. + std::multimap::const_reverse_iterator + next_iterator; + size_t current_z_order; + }; + + // If the window is closed, the platform native window is either being + // destroyed, or doesn't exist anymore, and thus it's in a non-interactive + // state. + bool IsClosed() const { + return phase_ < Phase::kOpening && phase_ > Phase::kOpenBeforeClosing; + } + + bool CanApplyState() const { + // In kOpening, OpenImpl itself pulls the desired state itself and applies + // it, the Apply* functions can't be called and are unsafe to call because + // the implementation is an incomplete state, with the platform window + // potentially not existing. In kOpenBeforeClosing, as the native window + // still hasn't been destroyed and it can receive new state, still allowing + // applying new state for more consistency between the desired and the + // actual state during the final listener invocation. + return phase_ >= Phase::kOpen && phase_ <= Phase::kOpenBeforeClosing; + } + + bool CanSendEventsToListeners() const { + return phase_ >= Phase::kOpen && phase_ <= Phase::kOpenBeforeClosing; + } + // The listeners may delete the Window - check the destruction receiver after + // calling and stop doing anything accessing *this if that happens. + void SendEventToListeners(std::function fn, + WindowDestructionReceiver& destruction_receiver); + void PropagateEventThroughInputListeners( + std::function fn, + WindowDestructionReceiver& destruction_receiver); + + std::unique_ptr CreateSurface(Surface::TypeFlags allowed_types) { + // If opening, surface creation is deferred until all the initial setup has + // completed. Destruction of the surface is also a part of the closing + // process in OnBeforeClose. + if (phase_ != Phase::kOpen) { + return nullptr; + } + return CreateSurfaceImpl(allowed_types); + } WindowedAppContext& app_context_; - std::unique_ptr main_menu_; - std::string title_; -#ifdef XE_PLATFORM_GNU_LINUX - // GTK must have a default value here that isn't 0 - // TODO(Triang3l): Cleanup and unify this. May need to get the first resize - // message on various platforms. - int32_t width_ = 1280; - int32_t height_ = 720; -#else - int32_t width_ = 0; - int32_t height_ = 0; -#endif - bool has_focus_ = true; - bool is_cursor_visible_ = true; - bool is_imgui_input_enabled_ = false; - std::unique_ptr context_; - std::unique_ptr imgui_drawer_; - - uint32_t frame_count_ = 0; - uint32_t fps_ = 0; - uint64_t fps_update_time_ticks_ = 0; - uint64_t fps_frame_count_ = 0; - uint64_t last_paint_time_ticks_ = 0; - - bool modifier_shift_pressed_ = false; - bool modifier_cntrl_pressed_ = false; - bool modifier_alt_pressed_ = false; - bool modifier_super_pressed_ = false; + Phase phase_ = Phase::kClosedOpenable; + WindowDestructionReceiver* innermost_destruction_receiver_ = nullptr; // All currently-attached listeners that get event notifications. - bool in_listener_loop_ = false; std::vector listeners_; - std::vector pending_listener_attaches_; - std::vector pending_listener_detaches_; + // Ordered by the Z order, and then by the time of addition (but executed in + // reverse order). + // Note: All the iteration logic involving this Z ordering must be the same as + // in drawing (in the UI drawers in the Presenter), but in reverse. + std::multimap input_listeners_; + // Linked list-based stacks of the contexts of the listener iterations + // currently being done, usually allocated on the stack. + ListenerIterationContext* innermost_listener_iteration_context_ = nullptr; + InputListenerIterationContext* innermost_input_listener_iteration_context_ = + nullptr; + + uint32_t desired_logical_width_ = 0; + uint32_t desired_logical_height_ = 0; + // Set by the implementation via OnActualSizeUpdate (from OpenImpl or from the + // platform resize handler). + uint32_t actual_physical_width_ = 0; + uint32_t actual_physical_height_ = 0; + + bool fullscreen_ = false; + + std::string title_; + + std::unique_ptr main_menu_; + + uint32_t mouse_capture_request_count_ = 0; + + CursorVisibility cursor_visibility_ = CursorVisibility::kVisible; + + bool has_focus_ = false; + + Presenter* presenter_ = nullptr; + std::unique_ptr presenter_surface_; + // Whether currently in InPaint to prevent recursive painting in case it's + // triggered somehow from within painting again, because painting is much more + // complex than just a small state update, and recursive painting is + // completely unsupported by the Presenter. + bool is_painting_ = false; }; } // namespace ui diff --git a/src/xenia/ui/window_android.cc b/src/xenia/ui/window_android.cc index cd5aaba80..c653df217 100644 --- a/src/xenia/ui/window_android.cc +++ b/src/xenia/ui/window_android.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,29 +13,22 @@ #include #include "xenia/base/assert.h" +#include "xenia/ui/surface_android.h" #include "xenia/ui/windowed_app_context_android.h" namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - // The window is a proxy between the main activity and Xenia, so there can be - // only one for an activity. - AndroidWindowedAppContext& android_app_context = - static_cast(app_context); - AndroidWindow* current_activity_window = - android_app_context.GetActivityWindow(); - assert_null(current_activity_window); - if (current_activity_window) { - return nullptr; - } - auto window = std::make_unique(app_context, title); - android_app_context.SetActivityWindow(window.get()); - return std::move(window); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique( + app_context, title, desired_logical_width, desired_logical_height); } AndroidWindow::~AndroidWindow() { + EnterDestructor(); AndroidWindowedAppContext& android_app_context = static_cast(app_context()); if (android_app_context.GetActivityWindow() == this) { @@ -43,6 +36,57 @@ AndroidWindow::~AndroidWindow() { } } +bool AndroidWindow::OpenImpl() { + // The window is a proxy between the main activity and Xenia, so there can be + // only one for an activity. + AndroidWindowedAppContext& android_app_context = + static_cast(app_context()); + AndroidWindow* previous_activity_window = + android_app_context.GetActivityWindow(); + assert_null(previous_activity_window); + if (previous_activity_window) { + // Don't detach the old window as it's assuming it's still attached while + // it's in an open phase. + return false; + } + android_app_context.SetActivityWindow(this); + return true; +} + +void AndroidWindow::RequestCloseImpl() { + // Finishing the Activity would cause the entire WindowedAppContext to quit, + // which is not the same behavior as on other platforms - the + // WindowedAppContext quit is done explicitly by the listeners during + // OnClosing if needed (the main Window is potentially being changed to a + // different one, for instance). Therefore, only detach the window from the + // app context. + + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + OnAfterClose(); + + AndroidWindowedAppContext& android_app_context = + static_cast(app_context()); + if (android_app_context.GetActivityWindow() == this) { + android_app_context.SetActivityWindow(nullptr); + } +} + +std::unique_ptr AndroidWindow::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + if (allowed_types & Surface::kTypeFlag_AndroidNativeWindow) { + // TODO(Triang3l): AndroidNativeWindowSurface for the ANativeWindow. + } + return nullptr; +} + +void AndroidWindow::RequestPaintImpl() { + // TODO(Triang3l): postInvalidate. +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, diff --git a/src/xenia/ui/window_android.h b/src/xenia/ui/window_android.h index 780c1d77d..74832576d 100644 --- a/src/xenia/ui/window_android.h +++ b/src/xenia/ui/window_android.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,31 +18,24 @@ namespace ui { class AndroidWindow : public Window { public: - // Many functions are left unimplemented because the layout is configured from - // XML and Java. + // Several state-related functions are left unimplemented because the layout + // is configured from XML and Java. - AndroidWindow(WindowedAppContext& app_context, const std::string& title) - : Window(app_context, title) {} + AndroidWindow(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, + desired_logical_height) {} ~AndroidWindow(); - NativePlatformHandle native_platform_handle() const override { - return nullptr; - } - // TODO(Triang3l): ANativeWindow for Vulkan surface creation. - NativeWindowHandle native_handle() const override { return nullptr; } + uint32_t GetMediumDpi() const override { return 160; } - void EnableMainMenu() override {} - void DisableMainMenu() override {} + protected: + bool OpenImpl() override; + void RequestCloseImpl() override; - bool SetIcon(const void* buffer, size_t size) override { return false; } - - bool CaptureMouse() override { return false; } - bool ReleaseMouse() override { return false; } - - int get_medium_dpi() const override { return 160; } - - // TODO(Triang3l): Call the close event, which may finish the activity. - void Close() override {} + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; }; // Dummy for the menu item - menus are controlled by the layout. @@ -53,9 +46,6 @@ class AndroidMenuItem final : public MenuItem { AndroidMenuItem(Type type, const std::string& text, const std::string& hotkey, std::function callback) : MenuItem(type, text, hotkey, callback) {} - - void EnableMenuItem(Window& window) override {} - void DisableMenuItem(Window& window) override {} }; } // namespace ui diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index 05d61611d..0d1e97a9a 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -17,6 +17,8 @@ #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/presenter.h" +#include "xenia/ui/ui_event.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #include "xenia/ui/window_demo.h" @@ -30,26 +32,31 @@ bool WindowDemoApp::OnInitialize() { Profiler::Initialize(); Profiler::ThreadEnter("Main"); - // Create graphics provider that provides the context for the window. + // Create the graphics provider that provides the presenter for the window. graphics_provider_ = CreateGraphicsProvider(); if (!graphics_provider_) { + XELOGE("Failed to initialize the graphics provider"); return false; } + enum : size_t { + kZOrderImGui, + kZOrderProfiler, + kZOrderWindowDemoInput, + }; + // Create the window. - window_ = xe::ui::Window::Create(app_context(), GetName()); - if (!window_->Initialize()) { - XELOGE("Failed to initialize main window"); - return false; - } + window_ = xe::ui::Window::Create(app_context(), GetName(), 1920, 1200); + window_->AddListener(&window_listener_); + window_->AddInputListener(&window_listener_, kZOrderWindowDemoInput); // Main menu. auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File"); { - file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "&Close", - "Alt+F4", - [this]() { window_->Close(); })); + file_menu->AddChild( + MenuItem::Create(MenuItem::Type::kString, "&Close", "Alt+F4", + [this]() { window_->RequestClose(); })); } main_menu->AddChild(std::move(file_menu)); auto debug_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Debug"); @@ -62,51 +69,61 @@ bool WindowDemoApp::OnInitialize() { []() { Profiler::TogglePause(); })); } main_menu->AddChild(std::move(debug_menu)); - window_->set_main_menu(std::move(main_menu)); + window_->SetMainMenu(std::move(main_menu)); - // Initial size setting, done here so that it knows the menu exists. - window_->Resize(1920, 1200); + // Open the window once it's configured. + if (!window_->Open()) { + XELOGE("Failed to open the main window"); + return false; + } - // Create the graphics context for the window. The window will finish - // initialization with the context (loading resources, etc). - window_->set_context(graphics_provider_->CreateContext(window_.get())); + // Setup drawing to the window. - // Setup the profiler display. - GraphicsContextLock context_lock(window_->context()); - Profiler::set_window(window_.get()); + presenter_ = graphics_provider_->CreatePresenter(); + if (!presenter_) { + XELOGE("Failed to initialize the presenter"); + return false; + } - // Enable imgui input. - window_->set_imgui_input_enabled(true); + immediate_drawer_ = graphics_provider_->CreateImmediateDrawer(); + if (!immediate_drawer_) { + XELOGE("Failed to initialize the immediate drawer"); + return false; + } + immediate_drawer_->SetPresenter(presenter_.get()); - window_->on_closed.AddListener([this](xe::ui::UIEvent* e) { - XELOGI("User-initiated death!"); - app_context().QuitFromUIThread(); - }); + imgui_drawer_ = std::make_unique(window_.get(), kZOrderImGui); + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + immediate_drawer_.get()); + demo_dialog_ = std::make_unique(imgui_drawer_.get()); - window_->on_key_down.AddListener([](xe::ui::KeyEvent* e) { - switch (e->virtual_key()) { - case VirtualKey::kF3: - Profiler::ToggleDisplay(); - break; - default: - break; - } - }); + Profiler::SetUserIO(kZOrderProfiler, window_.get(), presenter_.get(), + immediate_drawer_.get()); - window_->on_painting.AddListener([this](xe::ui::UIEvent* e) { - auto& io = window_->imgui_drawer()->GetIO(); - - ImGui::ShowDemoWindow(); - ImGui::ShowMetricsWindow(); - - Profiler::Flip(); - - // Continuous paint. - window_->Invalidate(); - }); + window_->SetPresenter(presenter_.get()); return true; } +void WindowDemoApp::WindowDemoWindowListener::OnClosing(UIEvent& e) { + app_context_.QuitFromUIThread(); +} + +void WindowDemoApp::WindowDemoWindowListener::OnKeyDown(KeyEvent& e) { + switch (e.virtual_key()) { + case VirtualKey::kF3: + Profiler::ToggleDisplay(); + break; + default: + return; + } + e.set_handled(true); +} + +void WindowDemoApp::WindowDemoDialog::OnDraw(ImGuiIO& io) { + ImGui::ShowDemoWindow(); + ImGui::ShowMetricsWindow(); +} + } // namespace ui } // namespace xe diff --git a/src/xenia/ui/window_demo.h b/src/xenia/ui/window_demo.h index 29b6bc1fa..f3942ea7c 100644 --- a/src/xenia/ui/window_demo.h +++ b/src/xenia/ui/window_demo.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -14,7 +14,12 @@ #include #include "xenia/ui/graphics_provider.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/immediate_drawer.h" +#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" +#include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" namespace xe { @@ -29,13 +34,41 @@ class WindowDemoApp : public WindowedApp { protected: explicit WindowDemoApp(WindowedAppContext& app_context, const std::string_view name) - : WindowedApp(app_context, name) {} + : WindowedApp(app_context, name), window_listener_(app_context) {} virtual std::unique_ptr CreateGraphicsProvider() const = 0; private: + class WindowDemoWindowListener final : public WindowListener, + public WindowInputListener { + public: + explicit WindowDemoWindowListener(WindowedAppContext& app_context) + : app_context_(app_context) {} + + void OnClosing(UIEvent& e) override; + + void OnKeyDown(KeyEvent& e) override; + + private: + WindowedAppContext& app_context_; + }; + + class WindowDemoDialog final : public ImGuiDialog { + public: + explicit WindowDemoDialog(ImGuiDrawer* imgui_drawer) + : ImGuiDialog(imgui_drawer) {} + + protected: + void OnDraw(ImGuiIO& io) override; + }; + + WindowDemoWindowListener window_listener_; std::unique_ptr graphics_provider_; std::unique_ptr window_; + std::unique_ptr presenter_; + std::unique_ptr immediate_drawer_; + std::unique_ptr imgui_drawer_; + std::unique_ptr demo_dialog_; }; } // namespace ui diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index b35f91305..6eb563667 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -11,11 +11,13 @@ #include #include +#include +#include #include "xenia/base/assert.h" -#include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/platform_linux.h" +#include "xenia/ui/surface_gnulinux.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/window_gtk.h" @@ -23,384 +25,407 @@ namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - return std::make_unique(app_context, title); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique(app_context, title, desired_logical_width, + desired_logical_height); } -GTKWindow::GTKWindow(WindowedAppContext& app_context, const std::string& title) - : Window(app_context, title) {} +GTKWindow::GTKWindow(WindowedAppContext& app_context, + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, + desired_logical_height) {} GTKWindow::~GTKWindow() { - OnDestroy(); + EnterDestructor(); if (window_) { - if (GTK_IS_WIDGET(window_)) { - gtk_widget_destroy(window_); - } + // Set window_ to null to ignore events from now on since this ui::GTKWindow + // is entering an indeterminate state. + GtkWidget* window = window_; window_ = nullptr; + // Destroying the top-level window also destroys its children. + drawing_area_ = nullptr; + box_ = nullptr; + gtk_widget_destroy(window); } } -bool GTKWindow::Initialize() { return OnCreate(); } - -gboolean gtk_event_handler(GtkWidget* widget, GdkEvent* event, gpointer data) { - GTKWindow* window = reinterpret_cast(data); - switch (event->type) { - case GDK_OWNER_CHANGE: - window->HandleWindowOwnerChange(&(event->owner_change)); - break; - case GDK_VISIBILITY_NOTIFY: - window->HandleWindowVisibility(&(event->visibility)); - break; - case GDK_KEY_PRESS: - case GDK_KEY_RELEASE: - window->HandleKeyboard(&(event->key)); - break; - case GDK_SCROLL: - case GDK_MOTION_NOTIFY: - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - window->HandleMouse(&(event->any)); - break; - case GDK_FOCUS_CHANGE: - window->HandleWindowFocus(&(event->focus_change)); - break; - case GDK_CONFIGURE: - // Only handle the event for the drawing area so we don't save - // a width and height that includes the menu bar on the full window - if (event->configure.window == - gtk_widget_get_window(window->drawing_area_)) { - window->HandleWindowResize(&(event->configure)); - } - break; - default: - // Do nothing - break; - } - // Propagate the event to other handlers - return GDK_EVENT_PROPAGATE; -} - -gboolean draw_callback(GtkWidget* widget, GdkFrameClock* frame_clock, - gpointer data) { - GTKWindow* window = reinterpret_cast(data); - window->HandleWindowPaint(); - return G_SOURCE_CONTINUE; -} - -gboolean close_callback(GtkWidget* widget, gpointer data) { - GTKWindow* window = reinterpret_cast(data); - window->Close(); - return G_SOURCE_CONTINUE; -} - -bool GTKWindow::OnCreate() { - // GTK optionally allows passing argv and argc here for parsing gtk specific - // options. We won't bother +bool GTKWindow::OpenImpl() { window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_resizable(GTK_WINDOW(window_), true); - gtk_window_set_title(GTK_WINDOW(window_), title_.c_str()); - gtk_window_set_default_size(GTK_WINDOW(window_), width_, height_); - // Drawing area is where we will attach our vulkan/gl context - drawing_area_ = gtk_drawing_area_new(); - // tick callback is for the refresh rate of the window - gtk_widget_add_tick_callback(drawing_area_, draw_callback, - reinterpret_cast(this), nullptr); - // Attach our event handler to both the main window (for keystrokes) and the - // drawing area (for mouse input, resize event, etc) - g_signal_connect(G_OBJECT(drawing_area_), "event", - G_CALLBACK(gtk_event_handler), - reinterpret_cast(this)); - GdkDisplay* gdk_display = gtk_widget_get_display(window_); - assert(GDK_IS_X11_DISPLAY(gdk_display)); - connection_ = XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); + gtk_window_set_title(GTK_WINDOW(window_), GetTitle().c_str()); - g_signal_connect(G_OBJECT(window_), "event", G_CALLBACK(gtk_event_handler), - reinterpret_cast(this)); - // When the window manager kills the window (ie, the user hits X) - g_signal_connect(G_OBJECT(window_), "destroy", G_CALLBACK(close_callback), - reinterpret_cast(this)); - // Enable only keyboard events (so no mouse) for the top window - gtk_widget_set_events(window_, GDK_KEY_PRESS | GDK_KEY_RELEASE); - // Enable all events for the drawing area - gtk_widget_add_events(drawing_area_, GDK_ALL_EVENTS_MASK); - // Place the drawing area in a container (which later will hold the menu) - // then let it fill the whole area + // Create the vertical box container for the main menu and the drawing area. box_ = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_end(GTK_BOX(box_), drawing_area_, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(window_), box_); + + // Add the main menu (even if fullscreen was requested, for the initial layout + // calculation). + const GTKMenuItem* main_menu = static_cast(GetMainMenu()); + GtkWidget* main_menu_widget = main_menu ? main_menu->handle() : nullptr; + if (main_menu_widget) { + gtk_box_pack_start(GTK_BOX(box_), main_menu_widget, FALSE, FALSE, 0); + } + + // Create the drawing area for creating the surface for, which will be the + // client area of the window occupying all the window space not taken by the + // main menu. + drawing_area_ = gtk_drawing_area_new(); + gtk_box_pack_end(GTK_BOX(box_), drawing_area_, TRUE, TRUE, 0); + // The desired size is the client (drawing) area size. Let GTK auto-size the + // entire window around it (as well as the width of the menu actually if it + // happens to be bigger - the desired size in the Window will be updated later + // to reflect that). + gtk_widget_set_size_request(drawing_area_, GetDesiredLogicalWidth(), + GetDesiredLogicalHeight()); + + // Attach the event handlers. + // Keyboard events are processed by the window, mouse events are processed + // within, and by, the drawing (client) area. + gtk_widget_set_events(window_, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | + GDK_FOCUS_CHANGE_MASK); + gtk_widget_set_events(drawing_area_, + GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_SCROLL_MASK); + g_signal_connect(G_OBJECT(window_), "event", + G_CALLBACK(WindowEventHandlerThunk), + reinterpret_cast(this)); + g_signal_connect(G_OBJECT(drawing_area_), "event", + G_CALLBACK(DrawingAreaEventHandlerThunk), + reinterpret_cast(this)); + g_signal_connect(G_OBJECT(drawing_area_), "draw", G_CALLBACK(DrawHandler), + reinterpret_cast(this)); + + // Finally show all the widgets in the window, including the main menu. gtk_widget_show_all(window_); - return super::OnCreate(); -} + // Remove the size request after finishing the initial layout because it makes + // it impossible to make the window smaller. + gtk_widget_set_size_request(drawing_area_, -1, -1); -void GTKWindow::OnDestroy() { super::OnDestroy(); } - -void GTKWindow::OnClose() { - if (!closing_ && window_) { - closing_ = true; + // After setting up the initial layout for non-fullscreen, enter fullscreen if + // requested. + if (IsFullscreen()) { + if (main_menu_widget) { + gtk_container_remove(GTK_CONTAINER(box_), main_menu_widget); + } + gtk_window_fullscreen(GTK_WINDOW(window_)); } - super::OnClose(); -} -bool GTKWindow::set_title(const std::string_view title) { - if (!super::set_title(title)) { - return false; + // Make sure the initial state after opening is reported to the common Window + // class no matter how GTK sends the events. + { + WindowDestructionReceiver destruction_receiver(this); + + // TODO(Triang3l): Report the desired client area size. + + GtkAllocation drawing_area_allocation; + gtk_widget_get_allocation(drawing_area_, &drawing_area_allocation); + OnActualSizeUpdate(uint32_t(drawing_area_allocation.width), + uint32_t(drawing_area_allocation.height), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + + if (gtk_window_has_toplevel_focus(GTK_WINDOW(window_))) { + OnFocusUpdate(true, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } } - std::string titlez(title); - gtk_window_set_title(GTK_WINDOW(window_), (gchar*)titlez.c_str()); + return true; } -bool GTKWindow::SetIcon(const void* buffer, size_t size) { - // TODO(dougvj) Set icon after changin buffer to the correct format. (the - // call is gtk_window_set_icon) - return false; -} +void GTKWindow::RequestCloseImpl() { gtk_window_close(GTK_WINDOW(window_)); } -bool GTKWindow::is_fullscreen() const { return fullscreen_; } +void GTKWindow::ApplyNewFullscreen() { + // Various functions here may trigger events that may result in the listeners + // being invoked, and potentially cause the destruction of the window or + // fullscreen being toggled from inside this function. + WindowDestructionReceiver destruction_receiver(this); -void GTKWindow::ToggleFullscreen(bool fullscreen) { - if (fullscreen == is_fullscreen()) { - return; - } + const GTKMenuItem* main_menu = static_cast(GetMainMenu()); + GtkWidget* main_menu_widget = main_menu ? main_menu->handle() : nullptr; - fullscreen_ = fullscreen; - if (fullscreen) { + // Changing the menu and the fullscreen state may change the size of the + // drawing area too, don't handle the resize multiple times (also potentially + // with the listeners changing the desired fullscreen if called from the + // handling of some event like GDK_CONFIGURE). + BeginBatchedSizeUpdate(); + + if (IsFullscreen()) { + if (main_menu_widget) { + gtk_container_remove(GTK_CONTAINER(box_), main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + } gtk_window_fullscreen(GTK_WINDOW(window_)); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } } else { gtk_window_unfullscreen(GTK_WINDOW(window_)); - } -} - -bool GTKWindow::is_bordered() const { - return gtk_window_get_decorated(GTK_WINDOW(window_)); -} - -void GTKWindow::set_bordered(bool enabled) { - if (is_fullscreen()) { - // Don't screw with the borders if we're fullscreen. - return; - } - gtk_window_set_decorated(GTK_WINDOW(window_), enabled); -} - -void GTKWindow::set_cursor_visible(bool value) { - if (is_cursor_visible_ == value) { - return; - } - if (value) { - // TODO(dougvj) Show and hide cursor - } else { - } -} - -void GTKWindow::set_focus(bool value) { - if (has_focus_ == value) { - return; - } - if (window_) { - if (value) { - gtk_window_activate_focus(GTK_WINDOW(window_)); - } else { - // TODO(dougvj) Check to see if we need to do something here to unset - // the focus. + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - } else { - has_focus_ = value; - } -} - -void GTKWindow::Resize(int32_t width, int32_t height) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - gtk_window_resize(GTK_WINDOW(window_), width, height); - super::Resize(width, height); -} - -void GTKWindow::Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - gtk_window_move(GTK_WINDOW(window_), left, top); - gtk_window_resize(GTK_WINDOW(window_), right - left, bottom - top); - super::Resize(left, top, right, bottom); -} - -void GTKWindow::OnResize(UIEvent* e) { super::OnResize(e); } - -void GTKWindow::Invalidate() { - // gtk_widget_queue_draw(drawing_area_); - super::Invalidate(); -} - -void GTKWindow::Close() { - if (closing_) { - return; - } - closing_ = true; - OnClose(); - gtk_widget_destroy(window_); - window_ = nullptr; -} - -void GTKWindow::OnMainMenuChange() { - // We need to store the old handle for detachment - static int count = 0; - auto main_menu = reinterpret_cast(main_menu_.get()); - if (main_menu && main_menu->handle()) { - if (!is_fullscreen()) { - gtk_box_pack_start(GTK_BOX(box_), main_menu->handle(), FALSE, FALSE, 0); - gtk_widget_show_all(window_); - } else { - gtk_container_remove(GTK_CONTAINER(box_), main_menu->handle()); + if (main_menu_widget) { + gtk_box_pack_start(GTK_BOX(box_), main_menu_widget, FALSE, FALSE, 0); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + // If the new menu is used for the first time, it will be in the hidden + // state initially. The menu might have been changed while in fullscreen + // without having shown it. + gtk_widget_show_all(main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } } } -} -bool GTKWindow::HandleWindowOwnerChange(GdkEventOwnerChange* event) { - if (event->type == GDK_OWNER_CHANGE) { - if (event->reason == GDK_OWNER_CHANGE_DESTROY) { - OnDestroy(); - } else if (event->reason == GDK_OWNER_CHANGE_CLOSE) { - closing_ = true; - Close(); - OnClose(); - } - return true; + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } - return false; } -bool GTKWindow::HandleWindowPaint() { - auto e = UIEvent(this); - OnPaint(&e); - return true; +void GTKWindow::ApplyNewTitle() { + gtk_window_set_title(GTK_WINDOW(window_), GetTitle().c_str()); } -bool GTKWindow::HandleWindowResize(GdkEventConfigure* event) { - if (event->type == GDK_CONFIGURE) { - int32_t width = event->width; - int32_t height = event->height; - auto e = UIEvent(this); - if (width != width_ || height != height_) { - width_ = width; - height_ = height; - Layout(); - } - OnResize(&e); - return true; +void GTKWindow::ApplyNewMainMenu(MenuItem* old_main_menu) { + if (IsFullscreen()) { + // The menu will be set when exiting fullscreen. + return; } - return false; -} + // The fullscreen state may have been changed by some callback invoked, such + // as the configure (resize) one, recheck it after making changes also. -bool GTKWindow::HandleWindowVisibility(GdkEventVisibility* event) { - // TODO(dougvj) The gdk docs say that this is deprecated because modern window - // managers composite everything and nothing is truly hidden. - if (event->type == GDK_VISIBILITY_NOTIFY) { - if (event->state == GDK_VISIBILITY_UNOBSCURED) { - auto e = UIEvent(this); - OnVisible(&e); - } else { - auto e = UIEvent(this); - OnHidden(&e); + WindowDestructionReceiver destruction_receiver(this); + + // Changing the menu may change the size of the drawing area too, and here the + // menu may be changed twice (to detach the old one and to attach the new), + // don't handle the resize multiple times. + BeginBatchedSizeUpdate(); + + if (old_main_menu) { + const GTKMenuItem& old_gtk_main_menu = + *static_cast(old_main_menu); + gtk_container_remove(GTK_CONTAINER(box_), old_gtk_main_menu.handle()); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - return true; } - return false; -} -bool GTKWindow::HandleWindowFocus(GdkEventFocus* event) { - if (event->type == GDK_FOCUS_CHANGE) { - if (!event->in) { - has_focus_ = false; - auto e = UIEvent(this); - OnLostFocus(&e); - } else { - has_focus_ = true; - auto e = UIEvent(this); - OnGotFocus(&e); + const GTKMenuItem* new_main_menu = + static_cast(GetMainMenu()); + if (!new_main_menu) { + EndBatchedSizeUpdate(destruction_receiver); + return; + } + GtkWidget* new_main_menu_widget = new_main_menu->handle(); + gtk_box_pack_start(GTK_BOX(box_), new_main_menu_widget, FALSE, FALSE, 0); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); } - return true; + return; + } + // If the new menu is used for the first time, it will be in the hidden state + // initially. + gtk_widget_show_all(new_main_menu_widget); + if (destruction_receiver.IsWindowDestroyedOrClosed() || IsFullscreen()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } - return false; } -bool GTKWindow::HandleMouse(GdkEventAny* event) { +void GTKWindow::FocusImpl() { gtk_window_activate_focus(GTK_WINDOW(window_)); } + +std::unique_ptr GTKWindow::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + GdkDisplay* display = gtk_widget_get_display(window_); + GdkWindow* drawing_area_window = gtk_widget_get_window(drawing_area_); + bool type_known = false; + bool type_supported_by_display = false; + if (allowed_types & Surface::kTypeFlag_XcbWindow) { + type_known = true; + if (GDK_IS_X11_DISPLAY(display)) { + type_supported_by_display = true; + return std::make_unique( + XGetXCBConnection(gdk_x11_display_get_xdisplay(display)), + gdk_x11_window_get_xid(drawing_area_window)); + } + } + // TODO(Triang3l): Wayland surface. + if (type_known && !type_supported_by_display) { + XELOGE( + "GTKWindow: The window system of the GTK window is not supported by " + "Xenia"); + } + return nullptr; +} + +void GTKWindow::RequestPaintImpl() { gtk_widget_queue_draw(drawing_area_); } + +void GTKWindow::HandleSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + if (!drawing_area_) { + // Batched size update ended when the window has already been closed, for + // instance. + return; + } + + // TODO(Triang3l): Report the desired client area size. + + GtkAllocation drawing_area_allocation; + gtk_widget_get_allocation(drawing_area_, &drawing_area_allocation); + OnActualSizeUpdate(uint32_t(drawing_area_allocation.width), + uint32_t(drawing_area_allocation.height), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void GTKWindow::BeginBatchedSizeUpdate() { + // It's okay if batched_size_update_contained_* are not false when beginning + // a batched update, in case the new batched update was started by a window + // listener called from within EndBatchedSizeUpdate. + ++batched_size_update_depth_; +} + +void GTKWindow::EndBatchedSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + assert_not_zero(batched_size_update_depth_); + if (--batched_size_update_depth_) { + return; + } + // Resetting batched_size_update_contained_* in closing, not opening, because + // a listener may start a new batch, and finish it, and there won't be need to + // handle the deferred messages twice. + if (batched_size_update_contained_configure_) { + batched_size_update_contained_configure_ = false; + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + if (batched_size_update_contained_draw_) { + batched_size_update_contained_draw_ = false; + RequestPaint(); + } +} + +bool GTKWindow::HandleMouse(GdkEvent* event, + WindowDestructionReceiver& destruction_receiver) { MouseEvent::Button button = MouseEvent::Button::kNone; - int32_t dx = 0; - int32_t dy = 0; int32_t x = 0; int32_t y = 0; + int32_t scroll_x = 0; + int32_t scroll_y = 0; switch (event->type) { - default: - // Double click/etc? - return true; + case GDK_MOTION_NOTIFY: { + auto motion_event = reinterpret_cast(event); + x = motion_event->x; + y = motion_event->y; + } break; case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: { - GdkEventButton* e = reinterpret_cast(event); - switch (e->button) { + auto button_event = reinterpret_cast(event); + switch (button_event->button) { case 1: button = MouseEvent::Button::kLeft; break; - case 3: - button = MouseEvent::Button::kRight; - break; case 2: button = MouseEvent::Button::kMiddle; break; + case 3: + button = MouseEvent::Button::kRight; + break; case 4: button = MouseEvent::Button::kX1; break; case 5: button = MouseEvent::Button::kX2; break; + default: + // Still handle the movement. + break; } - x = e->x; - y = e->y; - break; - } - case GDK_MOTION_NOTIFY: { - GdkEventMotion* e = reinterpret_cast(event); - x = e->x; - y = e->y; - break; - } + x = button_event->x; + y = button_event->y; + } break; case GDK_SCROLL: { - GdkEventScroll* e = reinterpret_cast(event); - x = e->x; - y = e->y; - dx = e->delta_x; - dy = e->delta_y; - break; - } - } - - auto e = MouseEvent(this, button, x, y, dx, dy); - switch (event->type) { - case GDK_BUTTON_PRESS: - OnMouseDown(&e); - break; - case GDK_BUTTON_RELEASE: - OnMouseUp(&e); - break; - case GDK_MOTION_NOTIFY: - OnMouseMove(&e); - break; - case GDK_SCROLL: - OnMouseWheel(&e); - break; + auto scroll_event = reinterpret_cast(event); + x = scroll_event->x; + y = scroll_event->y; + scroll_x = scroll_event->delta_x * MouseEvent::kScrollPerDetent; + // In GDK, positive is towards the bottom of the screen, not forward from + // the user. + scroll_y = -scroll_event->delta_y * MouseEvent::kScrollPerDetent; + } break; default: return false; } + + MouseEvent e(this, button, x, y, scroll_x, scroll_y); + switch (event->type) { + case GDK_MOTION_NOTIFY: + OnMouseMove(e, destruction_receiver); + break; + case GDK_BUTTON_PRESS: + OnMouseDown(e, destruction_receiver); + break; + case GDK_BUTTON_RELEASE: + OnMouseUp(e, destruction_receiver); + break; + case GDK_SCROLL: + OnMouseWheel(e, destruction_receiver); + break; + default: + break; + } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } -bool GTKWindow::HandleKeyboard(GdkEventKey* event) { +bool GTKWindow::HandleKeyboard( + GdkEventKey* event, WindowDestructionReceiver& destruction_receiver) { unsigned int modifiers = event->state; bool shift_pressed = modifiers & GDK_SHIFT_MASK; bool ctrl_pressed = modifiers & GDK_CONTROL_MASK; @@ -408,25 +433,154 @@ bool GTKWindow::HandleKeyboard(GdkEventKey* event) { bool super_pressed = modifiers & GDK_SUPER_MASK; uint32_t key_char = gdk_keyval_to_unicode(event->keyval); // TODO(Triang3l): event->hardware_keycode to VirtualKey translation. - auto e = KeyEvent(this, VirtualKey(event->hardware_keycode), 1, - event->type == GDK_KEY_RELEASE, shift_pressed, ctrl_pressed, - alt_pressed, super_pressed); + KeyEvent e(this, VirtualKey(event->hardware_keycode), 1, + event->type == GDK_KEY_RELEASE, shift_pressed, ctrl_pressed, + alt_pressed, super_pressed); switch (event->type) { case GDK_KEY_PRESS: - OnKeyDown(&e); + OnKeyDown(e, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return e.is_handled(); + } if (key_char > 0) { - OnKeyChar(&e); + OnKeyChar(e, destruction_receiver); } break; case GDK_KEY_RELEASE: - OnKeyUp(&e); + OnKeyUp(e, destruction_receiver); break; default: - return false; + break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } +gboolean GTKWindow::WindowEventHandler(GdkEvent* event) { + switch (event->type) { + case GDK_DELETE: + // In case the widget was somehow forcibly destroyed without GDK_DELETE. + case GDK_DESTROY: { + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + // Set window_ to null to ignore events from now on since this + // ui::GTKWindow is entering an indeterminate state - this should be done + // at some point in closing anyway. + GtkWidget* window = window_; + window_ = nullptr; + // Destroying the top-level window also destroys its children. + drawing_area_ = nullptr; + box_ = nullptr; + if (event->type != GDK_DESTROY) { + gtk_widget_destroy(window); + } + OnAfterClose(); + } break; + + case GDK_FOCUS_CHANGE: { + auto focus_event = reinterpret_cast(event); + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(bool(focus_event->in), destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: { + WindowDestructionReceiver destruction_receiver(this); + HandleKeyboard(reinterpret_cast(event), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + default: + break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + return GDK_EVENT_PROPAGATE; +} + +gboolean GTKWindow::WindowEventHandlerThunk(GtkWidget* widget, GdkEvent* event, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->window_ || + reinterpret_cast(event)->window != + gtk_widget_get_window(window->window_)) { + return GDK_EVENT_PROPAGATE; + } + return window->WindowEventHandler(event); +} + +gboolean GTKWindow::DrawingAreaEventHandler(GdkEvent* event) { + switch (event->type) { + case GDK_MOTION_NOTIFY: + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_SCROLL: { + WindowDestructionReceiver destruction_receiver(this); + HandleMouse(event, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case GDK_CONFIGURE: { + if (batched_size_update_depth_) { + batched_size_update_contained_configure_ = true; + } else { + WindowDestructionReceiver destruction_receiver(this); + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + default: + break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + return GDK_EVENT_PROPAGATE; +} + +gboolean GTKWindow::DrawingAreaEventHandlerThunk(GtkWidget* widget, + GdkEvent* event, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->drawing_area_ || + reinterpret_cast(event)->window != + gtk_widget_get_window(window->drawing_area_)) { + return GDK_EVENT_PROPAGATE; + } + return window->DrawingAreaEventHandler(event); +} + +gboolean GTKWindow::DrawHandler(GtkWidget* widget, cairo_t* cr, + gpointer user_data) { + GTKWindow* window = reinterpret_cast(user_data); + if (!window || widget != window->drawing_area_) { + return FALSE; + } + if (window->batched_size_update_depth_) { + window->batched_size_update_contained_draw_ = true; + } else { + window->OnPaint(); + } + return TRUE; +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, @@ -434,17 +588,10 @@ std::unique_ptr MenuItem::Create(Type type, return std::make_unique(type, text, hotkey, callback); } -static void _menu_activate_callback(GtkWidget* gtk_menu, gpointer data) { - GTKMenuItem* menu = reinterpret_cast(data); - menu->Activate(); -} - -void GTKMenuItem::Activate() { - try { - callback_(); - } catch (const std::bad_function_call& e) { - // Ignore - } +void GTKMenuItem::ActivateHandler(GtkWidget* menu_item, gpointer user_data) { + static_cast(user_data)->OnSelected(); + // The menu item might have been destroyed by its OnSelected, don't do + // anything with it here from now on. } GTKMenuItem::GTKMenuItem(Type type, const std::string& text, @@ -475,13 +622,20 @@ GTKMenuItem::GTKMenuItem(Type type, const std::string& text, menu_ = gtk_menu_item_new_with_mnemonic(gtk_label); break; } - if (GTK_IS_MENU_ITEM(menu_)) - g_signal_connect(menu_, "activate", G_CALLBACK(_menu_activate_callback), - (gpointer)this); + if (menu_) { + // Own the object because it may be detached from and re-attached to a + // Window. + g_object_ref_sink(menu_); + if (GTK_IS_MENU_ITEM(menu_)) { + g_signal_connect(menu_, "activate", G_CALLBACK(ActivateHandler), + reinterpret_cast(this)); + } + } } GTKMenuItem::~GTKMenuItem() { if (menu_) { + g_object_unref(menu_); } } diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h index 6677f2fc7..a78cae29f 100644 --- a/src/xenia/ui/window_gtk.h +++ b/src/xenia/ui/window_gtk.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -28,72 +28,61 @@ class GTKWindow : public Window { using super = Window; public: - GTKWindow(WindowedAppContext& app_context, const std::string& title); + GTKWindow(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); ~GTKWindow() override; - NativePlatformHandle native_platform_handle() const override { - return connection_; - } - NativeWindowHandle native_handle() const override { return window_; } - GtkWidget* native_window_handle() const { return drawing_area_; } - - void EnableMainMenu() override {} - void DisableMainMenu() override {} - - bool set_title(const std::string_view title) override; - - bool SetIcon(const void* buffer, size_t size) override; - - // This seems to happen implicitly compared to Windows. - bool CaptureMouse() override { return true; }; - bool ReleaseMouse() override { return true; }; - - bool is_fullscreen() const override; - void ToggleFullscreen(bool fullscreen) override; - - bool is_bordered() const override; - void set_bordered(bool enabled) override; - - void set_cursor_visible(bool value) override; - void set_focus(bool value) override; - - void Resize(int32_t width, int32_t height) override; - void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) override; - - bool Initialize() override; - void Invalidate() override; - void Close() override; + // Will be null if the window hasn't been successfully opened yet, or has been + // closed. + GtkWidget* window() const { return window_; } protected: - bool OnCreate() override; - void OnMainMenuChange() override; - void OnDestroy() override; - void OnClose() override; + bool OpenImpl() override; + void RequestCloseImpl() override; - void OnResize(UIEvent* e) override; + void ApplyNewFullscreen() override; + void ApplyNewTitle() override; + void ApplyNewMainMenu(MenuItem* old_main_menu) override; + // Mouse capture seems to happen implicitly compared to Windows. + void FocusImpl() override; + + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; private: - GtkWidget* window_; - GtkWidget* box_; - GtkWidget* drawing_area_; - xcb_connection_t* connection_; + void HandleSizeUpdate(WindowDestructionReceiver& destruction_receiver); + // For updating multiple factors that may influence the window size at once, + // without handling the configure event multiple times (that may not only + // result in wasted handling, but also in the state potentially changed to an + // inconsistent one in the middle of a size update by the listeners). + void BeginBatchedSizeUpdate(); + void EndBatchedSizeUpdate(WindowDestructionReceiver& destruction_receiver); - // C Callback shims for GTK - friend gboolean gtk_event_handler(GtkWidget*, GdkEvent*, gpointer); - friend gboolean close_callback(GtkWidget*, gpointer); - friend gboolean draw_callback(GtkWidget*, GdkFrameClock*, gpointer); + // Handling events related to the whole window. + bool HandleMouse(GdkEvent* event, + WindowDestructionReceiver& destruction_receiver); + bool HandleKeyboard(GdkEventKey* event, + WindowDestructionReceiver& destruction_receiver); + gboolean WindowEventHandler(GdkEvent* event); + static gboolean WindowEventHandlerThunk(GtkWidget* widget, GdkEvent* event, + gpointer user_data); - bool HandleMouse(GdkEventAny* event); - bool HandleKeyboard(GdkEventKey* event); - bool HandleWindowResize(GdkEventConfigure* event); - bool HandleWindowFocus(GdkEventFocus* event); - bool HandleWindowVisibility(GdkEventVisibility* event); - bool HandleWindowOwnerChange(GdkEventOwnerChange* event); - bool HandleWindowPaint(); + // Handling events related specifically to the drawing (client) area. + gboolean DrawingAreaEventHandler(GdkEvent* event); + static gboolean DrawingAreaEventHandlerThunk(GtkWidget* widget, + GdkEvent* event, + gpointer user_data); + static gboolean DrawHandler(GtkWidget* widget, cairo_t* cr, gpointer data); - bool closing_ = false; - bool fullscreen_ = false; + // Non-owning (initially floating) references to the widgets. + GtkWidget* window_ = nullptr; + GtkWidget* box_ = nullptr; + GtkWidget* drawing_area_ = nullptr; + + uint32_t batched_size_update_depth_ = 0; + bool batched_size_update_contained_configure_ = false; + bool batched_size_update_contained_draw_ = false; }; class GTKMenuItem : public MenuItem { @@ -102,20 +91,16 @@ class GTKMenuItem : public MenuItem { std::function callback); ~GTKMenuItem() override; - GtkWidget* handle() { return menu_; } - using MenuItem::OnSelected; - void Activate(); - - void EnableMenuItem(Window& window) override {} - void DisableMenuItem(Window& window) override {} + GtkWidget* handle() const { return menu_; } protected: void OnChildAdded(MenuItem* child_item) override; void OnChildRemoved(MenuItem* child_item) override; - GTKMenuItem* parent_ = nullptr; - GTKMenuItem* child_ = nullptr; private: + static void ActivateHandler(GtkWidget* menu_item, gpointer user_data); + + // An owning reference because a menu may be transferred between windows. GtkWidget* menu_ = nullptr; }; diff --git a/src/xenia/ui/window_listener.h b/src/xenia/ui/window_listener.h index 08f7a5c7e..6dbf36c77 100644 --- a/src/xenia/ui/window_listener.h +++ b/src/xenia/ui/window_listener.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,38 +15,39 @@ namespace xe { namespace ui { -// Virtual interface for types that want to listen for Window events. -// Use Window::AttachListener and Window::DetachListener to manage active -// listeners. +// Virtual interfaces for types that want to listen for Window events. +// Use Window::Add[Input]Listener and Window::Remove[Input]Listener to manage +// active listeners. + class WindowListener { public: virtual ~WindowListener() = default; - virtual void OnMainMenuChange() {} - virtual void OnClosing(UIEvent* e) {} - virtual void OnClosed(UIEvent* e) {} + // OnOpened will be followed by various initial setup listeners. + virtual void OnOpened(UISetupEvent& e) {} + virtual void OnClosing(UIEvent& e) {} - virtual void OnResize(UIEvent* e) {} - virtual void OnLayout(UIEvent* e) {} - virtual void OnPainting(UIEvent* e) {} - virtual void OnPaint(UIEvent* e) {} - virtual void OnPainted(UIEvent* e) {} - virtual void OnFileDrop(UIEvent* e) {} + virtual void OnDpiChanged(UISetupEvent& e) {} + virtual void OnResize(UISetupEvent& e) {} - virtual void OnVisible(UIEvent* e) {} - virtual void OnHidden(UIEvent* e) {} + virtual void OnGotFocus(UISetupEvent& e) {} + virtual void OnLostFocus(UISetupEvent& e) {} - virtual void OnGotFocus(UIEvent* e) {} - virtual void OnLostFocus(UIEvent* e) {} + virtual void OnFileDrop(FileDropEvent& e) {} +}; - virtual void OnKeyDown(KeyEvent* e) {} - virtual void OnKeyUp(KeyEvent* e) {} - virtual void OnKeyChar(KeyEvent* e) {} +class WindowInputListener { + public: + virtual ~WindowInputListener() = default; - virtual void OnMouseDown(MouseEvent* e) {} - virtual void OnMouseMove(MouseEvent* e) {} - virtual void OnMouseUp(MouseEvent* e) {} - virtual void OnMouseWheel(MouseEvent* e) {} + virtual void OnKeyDown(KeyEvent& e) {} + virtual void OnKeyUp(KeyEvent& e) {} + virtual void OnKeyChar(KeyEvent& e) {} + + virtual void OnMouseDown(MouseEvent& e) {} + virtual void OnMouseMove(MouseEvent& e) {} + virtual void OnMouseUp(MouseEvent& e) {} + virtual void OnMouseWheel(MouseEvent& e) {} }; } // namespace ui diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index a6d2c68ae..39ea5b3da 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -2,71 +2,74 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/window_win.h" -#include - +#include #include #include "xenia/base/assert.h" #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" +#include "xenia/ui/surface_win.h" + +// Must be included before Windows headers for things like NOMINMAX. #include "xenia/base/platform_win.h" #include "xenia/ui/virtual_key.h" #include "xenia/ui/windowed_app_context_win.h" +// For per-monitor DPI awareness v1. +#include + namespace xe { namespace ui { std::unique_ptr Window::Create(WindowedAppContext& app_context, - const std::string& title) { - return std::make_unique(app_context, title); + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) { + return std::make_unique( + app_context, title, desired_logical_width, desired_logical_height); } Win32Window::Win32Window(WindowedAppContext& app_context, - const std::string& title) - : Window(app_context, title) {} + const std::string_view title, + uint32_t desired_logical_width, + uint32_t desired_logical_height) + : Window(app_context, title, desired_logical_width, desired_logical_height), + arrow_cursor_(LoadCursor(nullptr, IDC_ARROW)) { + dpi_ = GetCurrentSystemDpi(); +} Win32Window::~Win32Window() { - OnDestroy(); + EnterDestructor(); + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } if (hwnd_) { - SetWindowLongPtr(hwnd_, GWLP_USERDATA, 0); - CloseWindow(hwnd_); + // Set hwnd_ to null to ignore events from now on since this Win32Window is + // entering an indeterminate state. + HWND hwnd = hwnd_; hwnd_ = nullptr; + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + DestroyWindow(hwnd); } if (icon_) { DestroyIcon(icon_); - icon_ = nullptr; } } -NativePlatformHandle Win32Window::native_platform_handle() const { - return static_cast(app_context()).hinstance(); -} +uint32_t Win32Window::GetMediumDpi() const { return USER_DEFAULT_SCREEN_DPI; } -bool Win32Window::Initialize() { return OnCreate(); } - -bool Win32Window::OnCreate() { - HINSTANCE hInstance = - static_cast(app_context()).hinstance(); - - // Per-monitor DPI awareness is expected to be enabled via the manifest, as - // that's the recommended way, which also doesn't require calling - // SetProcessDpiAwareness before doing anything that may depend on DPI - // awareness (so it's safe to use any Windows APIs before this code). - // TODO(Triang3l): Safe handling of per-monitor DPI awareness v2, with - // automatic scaling on DPI change. - if (!GetDpiForMonitor_) { - auto shcore = GetModuleHandleW(L"shcore.dll"); - if (shcore) { - GetDpiForMonitor_ = GetProcAddress(shcore, "GetDpiForMonitor"); - } - } +bool Win32Window::OpenImpl() { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + HINSTANCE hinstance = win32_app_context.hinstance(); static bool has_registered_class = false; if (!has_registered_class) { @@ -76,11 +79,12 @@ bool Win32Window::OnCreate() { wcex.lpfnWndProc = Win32Window::WndProcThunk; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIconW(hInstance, L"MAINICON"); - wcex.hIconSm = NULL; // LoadIconW(hInstance, L"MAINICON"); - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.hInstance = hinstance; + wcex.hIcon = LoadIconW(hinstance, L"MAINICON"); + wcex.hIconSm = nullptr; // LoadIconW(hinstance, L"MAINICON"); + wcex.hCursor = arrow_cursor_; + // Matches the black background color of the presenter's painting. + wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.lpszMenuName = nullptr; wcex.lpszClassName = L"XeniaWindowClass"; if (!RegisterClassExW(&wcex)) { @@ -90,22 +94,92 @@ bool Win32Window::OnCreate() { has_registered_class = true; } - // Setup initial size. + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); + + // Setup the initial size for the non-fullscreen window. With per-monitor DPI, + // this is also done to be able to obtain the initial window rectangle (with + // CW_USEDEFAULT) to get the monitor for the window position, and then to + // adjust the normal window size to the new DPI. + // Save the initial desired size since it may be modified by the handler of + // the WM_SIZE sent during window creation - it's needed for the initial + // per-monitor DPI scaling. + uint32_t initial_desired_logical_width = GetDesiredLogicalWidth(); + uint32_t initial_desired_logical_height = GetDesiredLogicalHeight(); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + const Win32WindowedAppContext::PerMonitorDpiV1Api* per_monitor_dpi_v1_api = + win32_app_context.per_monitor_dpi_v1_api(); + // Even with per-monitor DPI, take the closest approximation (system DPI) to + // potentially more accurately determine the initial monitor. + dpi_ = GetCurrentSystemDpi(); DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD window_ex_style = WS_EX_APPWINDOW | WS_EX_CONTROLPARENT; - RECT rc = {0, 0, width_, height_}; - AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); - - // Create window. - hwnd_ = - CreateWindowExW(window_ex_style, L"XeniaWindowClass", - reinterpret_cast(xe::to_utf16(title_).c_str()), - window_style, rc.left, rc.top, rc.right - rc.left, - rc.bottom - rc.top, nullptr, nullptr, hInstance, this); + RECT window_size_rect; + window_size_rect.left = 0; + window_size_rect.top = 0; + window_size_rect.right = LONG(ConvertSizeDpi(initial_desired_logical_width, + dpi_, USER_DEFAULT_SCREEN_DPI)); + window_size_rect.bottom = LONG(ConvertSizeDpi(initial_desired_logical_height, + dpi_, USER_DEFAULT_SCREEN_DPI)); + AdjustWindowRectangle(window_size_rect, window_style, + BOOL(main_menu != nullptr), window_ex_style, dpi_); + // Create the window. Though WM_NCCREATE will assign to `hwnd_` too, still do + // the assignment here to handle the case of a failure after WM_NCCREATE, for + // instance. + hwnd_ = CreateWindowExW( + window_ex_style, L"XeniaWindowClass", + reinterpret_cast(xe::to_utf16(GetTitle()).c_str()), window_style, + CW_USEDEFAULT, CW_USEDEFAULT, + window_size_rect.right - window_size_rect.left, + window_size_rect.bottom - window_size_rect.top, nullptr, nullptr, + hinstance, this); if (!hwnd_) { - XELOGE("CreateWindow failed"); + XELOGE("CreateWindowExW failed"); return false; } + // For per-monitor DPI, obtain the DPI of the monitor the window was created + // on, and adjust the initial normal size for it. If as a result of this + // resizing, the window is moved to a different monitor, the WM_DPICHANGED + // handler will do the needed correction. + uint32_t initial_monitor_dpi = dpi_; + if (per_monitor_dpi_v2_api) { + initial_monitor_dpi = per_monitor_dpi_v2_api->get_dpi_for_window(hwnd_); + } else if (per_monitor_dpi_v1_api) { + HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST); + UINT monitor_dpi_x, monitor_dpi_y; + if (monitor && SUCCEEDED(per_monitor_dpi_v1_api->get_dpi_for_monitor( + monitor, MDT_DEFAULT, &monitor_dpi_x, &monitor_dpi_y))) { + initial_monitor_dpi = monitor_dpi_x; + } + } + if (dpi_ != initial_monitor_dpi) { + dpi_ = initial_monitor_dpi; + WINDOWPLACEMENT initial_dpi_placement; + // Note that WINDOWPLACEMENT contains workspace coordinates, which are + // adjusted to exclude toolbars such as the taskbar - the positions and + // rectangle origins there can't be mixed with origins of rectangles in + // virtual screen coordinates such as those involved in functions like + // GetWindowRect. + initial_dpi_placement.length = sizeof(initial_dpi_placement); + if (GetWindowPlacement(hwnd_, &initial_dpi_placement)) { + window_size_rect.left = 0; + window_size_rect.top = 0; + window_size_rect.right = LONG(ConvertSizeDpi( + initial_desired_logical_width, dpi_, USER_DEFAULT_SCREEN_DPI)); + window_size_rect.bottom = LONG(ConvertSizeDpi( + initial_desired_logical_height, dpi_, USER_DEFAULT_SCREEN_DPI)); + AdjustWindowRectangle(window_size_rect, window_style, + BOOL(main_menu != nullptr), window_ex_style, dpi_); + initial_dpi_placement.rcNormalPosition.right = + initial_dpi_placement.rcNormalPosition.left + + (window_size_rect.right - window_size_rect.left); + initial_dpi_placement.rcNormalPosition.bottom = + initial_dpi_placement.rcNormalPosition.top + + (window_size_rect.bottom - window_size_rect.top); + SetWindowPlacement(hwnd_, &initial_dpi_placement); + } + } // Disable flicks. ATOM atom = GlobalAddAtomW(L"MicrosoftTabletPenServiceProperty"); @@ -123,533 +197,617 @@ bool Win32Window::OnCreate() { reinterpret_cast(dwHwndTabletProperty)); GlobalDeleteAtom(atom); - // Enable DWM elevation. - EnableMMCSS(); // Enable file dragging from external sources DragAcceptFiles(hwnd_, true); - ShowWindow(hwnd_, SW_SHOWNORMAL); - UpdateWindow(hwnd_); + // Apply the initial state from the Window that the window shouldn't be + // visibly transitioned to. - arrow_cursor_ = LoadCursor(nullptr, IDC_ARROW); - - // Initial state. - if (!is_cursor_visible_) { - ShowCursor(FALSE); - } - if (has_focus_) { - SetFocus(hwnd_); - } - - return super::OnCreate(); -} - -void Win32Window::EnableMMCSS() { - HMODULE hLibrary = LoadLibraryW(L"DWMAPI.DLL"); - if (!hLibrary) { - return; - } - - typedef HRESULT(__stdcall * PDwmEnableMMCSS)(BOOL); - PDwmEnableMMCSS pDwmEnableMMCSS = - (PDwmEnableMMCSS)GetProcAddress(hLibrary, "DwmEnableMMCSS"); - if (pDwmEnableMMCSS) { - pDwmEnableMMCSS(TRUE); - } - - typedef HRESULT(__stdcall * PDwmSetPresentParameters)( - HWND, DWM_PRESENT_PARAMETERS*); - PDwmSetPresentParameters pDwmSetPresentParameters = - (PDwmSetPresentParameters)GetProcAddress(hLibrary, - "DwmSetPresentParameters"); - if (pDwmSetPresentParameters) { - DWM_PRESENT_PARAMETERS pp; - std::memset(&pp, 0, sizeof(DWM_PRESENT_PARAMETERS)); - pp.cbSize = sizeof(DWM_PRESENT_PARAMETERS); - pp.fQueue = FALSE; - pp.cBuffer = 2; - pp.fUseSourceRate = FALSE; - pp.cRefreshesPerFrame = 1; - pp.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT; - pDwmSetPresentParameters(hwnd_, &pp); - } - - FreeLibrary(hLibrary); -} - -void Win32Window::OnDestroy() { super::OnDestroy(); } - -void Win32Window::OnClose() { - if (!closing_ && hwnd_) { - closing_ = true; - } - super::OnClose(); -} - -void Win32Window::EnableMainMenu() { - if (main_menu_) { - main_menu_->EnableMenuItem(*this); - } -} - -void Win32Window::DisableMainMenu() { - if (main_menu_) { - main_menu_->DisableMenuItem(*this); - } -} - -bool Win32Window::set_title(const std::string_view title) { - if (!super::set_title(title)) { - return false; - } - auto wide_title = xe::to_utf16(title); - SetWindowTextW(hwnd_, reinterpret_cast(wide_title.c_str())); - return true; -} - -bool Win32Window::SetIcon(const void* buffer, size_t size) { - if (icon_ != nullptr) { - DestroyIcon(icon_); - icon_ = nullptr; - } - - // Reset icon to default. - auto default_icon = LoadIconW( - static_cast(app_context()).hinstance(), - L"MAINICON"); - SendMessageW(hwnd_, WM_SETICON, ICON_BIG, - reinterpret_cast(default_icon)); - SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, - reinterpret_cast(default_icon)); - if (!buffer || !size) { - return true; - } - - // Create icon and set on window (if it's valid). - icon_ = CreateIconFromResourceEx( - reinterpret_cast(const_cast(buffer)), - static_cast(size), TRUE, 0x00030000, 0, 0, - LR_DEFAULTCOLOR | LR_DEFAULTSIZE); if (icon_) { SendMessageW(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon_)); SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon_)); } - return false; -} - -bool Win32Window::CaptureMouse() { - if (GetCapture() != nullptr) { - return false; + if (IsFullscreen()) { + // Go fullscreen after setting up everything related to the placement of the + // non-fullscreen window. + WindowDestructionReceiver destruction_receiver(this); + ApplyFullscreenEntry(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return true; + } + } else { + if (main_menu) { + SetMenu(hwnd_, main_menu->handle()); + } } - SetCapture(hwnd_); + + // Finally show the window. + ShowWindow(hwnd_, SW_SHOWNORMAL); + + // Report the initial actual state after opening, messages for which might + // have missed if they were processed during CreateWindowExW when the HWND was + // not yet attached to the Win32Window. + { + WindowDestructionReceiver destruction_receiver(this); + + // Report the desired logical size of the client area in the non-maximized + // state after the initial layout setup in Windows. + WINDOWPLACEMENT shown_placement; + shown_placement.length = sizeof(shown_placement); + if (GetWindowPlacement(hwnd_, &shown_placement)) { + // Get the size of the non-client area to subtract it from the size of the + // entire window in its non-maximized state, to get the client area. + RECT non_client_area_rect = {}; + AdjustWindowRectangle(non_client_area_rect); + OnDesiredLogicalSizeUpdate( + SizeToLogical(uint32_t( + (shown_placement.rcNormalPosition.right - + shown_placement.rcNormalPosition.left) - + (non_client_area_rect.right - non_client_area_rect.left))), + SizeToLogical(uint32_t( + (shown_placement.rcNormalPosition.bottom - + shown_placement.rcNormalPosition.top) - + (non_client_area_rect.bottom - non_client_area_rect.top)))); + } + + // Report the actual physical size in the current state. + RECT shown_client_rect; + if (GetClientRect(hwnd_, &shown_client_rect)) { + OnActualSizeUpdate( + uint32_t(shown_client_rect.right - shown_client_rect.left), + uint32_t(shown_client_rect.bottom - shown_client_rect.top), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } + + OnFocusUpdate(GetFocus() == hwnd_, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return true; + } + } + + // Apply the initial state from the Window that involves interaction with the + // user. + + if (IsMouseCaptureRequested()) { + SetCapture(hwnd_); + } + + cursor_currently_auto_hidden_ = false; + CursorVisibility cursor_visibility = GetCursorVisibility(); + if (cursor_visibility != CursorVisibility::kVisible) { + if (cursor_visibility == CursorVisibility::kAutoHidden) { + if (!GetCursorPos(&cursor_auto_hide_last_screen_pos_)) { + cursor_auto_hide_last_screen_pos_.x = LONG_MAX; + cursor_auto_hide_last_screen_pos_.y = LONG_MAX; + } + cursor_currently_auto_hidden_ = true; + } + // OnFocusUpdate needs to be done before this. + SetCursorIfFocusedOnClientArea(nullptr); + } + return true; } -bool Win32Window::ReleaseMouse() { - if (GetCapture() != hwnd_) { - return false; - } - return ReleaseCapture() != 0; +void Win32Window::RequestCloseImpl() { + // Note that CloseWindow doesn't close the window, rather, it only minimizes + // it - need to send WM_CLOSE to let the Win32Window WndProc perform all the + // shutdown. + SendMessageW(hwnd_, WM_CLOSE, 0, 0); + // The window might have been deleted by the close handler, don't do anything + // with *this anymore (if that's needed, use a WindowDestructionReceiver). } -bool Win32Window::is_fullscreen() const { return fullscreen_; } +uint32_t Win32Window::GetLatestDpiImpl() const { + // hwnd_ may be null in this function, but the latest DPI is stored in a + // variable anyway. + return dpi_; +} -void Win32Window::ToggleFullscreen(bool fullscreen) { - if (fullscreen == is_fullscreen()) { - return; - } - - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - if (fullscreen) { - // https://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx - MONITORINFO mi = {sizeof(mi)}; - if (GetWindowPlacement(hwnd_, &windowed_pos_) && - GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY), - &mi)) { - // Remove the menubar and borders. - SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - ::SetMenu(hwnd_, NULL); - - // Resize the window to fullscreen. - auto& rc = mi.rcMonitor; - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), false); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); +void Win32Window::ApplyNewFullscreen() { + // Various functions here may send messages that may result in the + // listeners being invoked, and potentially cause the destruction of the + // window or fullscreen being toggled from inside this function. + WindowDestructionReceiver destruction_receiver(this); + if (IsFullscreen()) { + ApplyFullscreenEntry(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; } } else { - // Reinstate borders, resize to 1280x720 - SetWindowLong(hwnd_, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - SetWindowPlacement(hwnd_, &windowed_pos_); + // Changing the style and the menu may change the size too, don't handle + // the resize multiple times (also potentially with the listeners changing + // the desired fullscreen if called from the handling of some message like + // WM_SIZE). + BeginBatchedSizeUpdate(); - auto main_menu = reinterpret_cast(main_menu_.get()); + // Reinstate the non-client area. + SetWindowLong(hwnd_, GWL_STYLE, + GetWindowLong(hwnd_, GWL_STYLE) | WS_OVERLAPPEDWINDOW); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); if (main_menu) { - ::SetMenu(hwnd_, main_menu->handle()); - } - } - - fullscreen_ = fullscreen; - - // width_ and height_ will be updated by the WM_SIZE handler - - // windowed_pos_.rcNormalPosition is also not the correct source for them when - // switching from fullscreen to maximized. -} - -bool Win32Window::is_bordered() const { - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - return (style & WS_OVERLAPPEDWINDOW) == WS_OVERLAPPEDWINDOW; -} - -void Win32Window::set_bordered(bool enabled) { - if (is_fullscreen()) { - // Don't screw with the borders if we're fullscreen. - return; - } - - DWORD style = GetWindowLong(hwnd_, GWL_STYLE); - if (enabled) { - SetWindowLong(hwnd_, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); - } else { - SetWindowLong(hwnd_, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - } -} - -int Win32Window::get_dpi() const { - // TODO(Triang3l): Cache until WM_DPICHANGED is received (which, with - // per-monitor awareness v2 will also receive the new suggested window size). - // According to MSDN, x and y are identical. - - if (!GetDpiForMonitor_) { - HDC screen_hdc = GetDC(nullptr); - if (!screen_hdc) { - return get_medium_dpi(); - } - int logical_pixels_x = GetDeviceCaps(screen_hdc, LOGPIXELSX); - ReleaseDC(nullptr, screen_hdc); - return logical_pixels_x; - } - - HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTOPRIMARY); - - UINT dpi_x, dpi_y; - auto gdfm = (decltype(&GetDpiForMonitor))GetDpiForMonitor_; - gdfm(monitor, MDT_DEFAULT, &dpi_x, &dpi_y); - return dpi_x; -} - -void Win32Window::set_cursor_visible(bool value) { - if (is_cursor_visible_ == value) { - return; - } - is_cursor_visible_ = value; - - if (value) { - ShowCursor(TRUE); - } else { - ShowCursor(FALSE); - } -} - -void Win32Window::set_focus(bool value) { - if (has_focus_ == value) { - return; - } - if (hwnd_) { - if (value) { - SetFocus(hwnd_); - } else { - SetFocus(nullptr); - } - } else { - has_focus_ = value; - } -} - -void Win32Window::Resize(int32_t width, int32_t height) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - - // Scale width and height - int32_t scaled_width, scaled_height; - float dpi_scale = get_dpi_scale(); - scaled_width = int32_t(width * dpi_scale); - scaled_height = int32_t(height * dpi_scale); - - RECT rc = {0, 0, 0, 0}; - GetWindowRect(hwnd_, &rc); - if (rc.top < 0) { - rc.top = 100; - } - if (rc.left < 0) { - rc.left = 100; - } - - rc.right = rc.left + scaled_width; - rc.bottom = rc.top + scaled_height; - - bool has_menu = !is_fullscreen() && (main_menu_ ? true : false); - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); - - super::Resize(width, height); -} - -void Win32Window::Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) { - if (is_fullscreen()) { - // Cannot resize while in fullscreen. - return; - } - - RECT rc = {left, top, right, bottom}; - - // Scale width and height - float dpi_scale = get_dpi_scale(); - rc.right = int32_t((right - left) * dpi_scale) + left; - rc.bottom = int32_t((bottom - top) * dpi_scale) + top; - - bool has_menu = !is_fullscreen() && (main_menu_ ? true : false); - AdjustWindowRect(&rc, GetWindowLong(hwnd_, GWL_STYLE), has_menu); - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); - - super::Resize(left, top, right, bottom); -} - -void Win32Window::RawReposition(const RECT& rc) { - MoveWindow(hwnd_, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - TRUE); -} - -void Win32Window::OnResize(UIEvent* e) { - RECT client_rect; - GetClientRect(hwnd_, &client_rect); - int32_t width = client_rect.right - client_rect.left; - int32_t height = client_rect.bottom - client_rect.top; - - // Rescale to base DPI. - float dpi_scale = get_dpi_scale(); - width = int32_t(width / dpi_scale); - height = int32_t(height / dpi_scale); - - if (width != width_ || height != height_) { - width_ = width; - height_ = height; - Layout(); - } - super::OnResize(e); -} - -void Win32Window::Invalidate() { - super::Invalidate(); - InvalidateRect(hwnd_, nullptr, FALSE); -} - -void Win32Window::Close() { - if (closing_) { - return; - } - closing_ = true; - OnClose(); - DestroyWindow(hwnd_); - hwnd_ = nullptr; -} - -void Win32Window::OnMainMenuChange() { - auto main_menu = reinterpret_cast(main_menu_.get()); - // Don't actually set the menu if we're fullscreen. We'll do that later. - if (main_menu && !is_fullscreen()) { - ::SetMenu(hwnd_, main_menu->handle()); - } -} - -LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam) { - Win32Window* window = nullptr; - if (message == WM_NCCREATE) { - auto create_struct = reinterpret_cast(lParam); - window = reinterpret_cast(create_struct->lpCreateParams); - SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window); - } else { - window = - reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - } - if (window) { - return window->WndProc(hWnd, message, wParam, lParam); - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } -} - -LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, - LPARAM lParam) { - if (hwnd_ != nullptr && hWnd != hwnd_) { - return DefWindowProc(hWnd, message, wParam, lParam); - } - - if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) { - if (HandleMouse(message, wParam, lParam)) { - return 0; - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } - } else if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { - if (HandleKeyboard(message, wParam, lParam)) { - return 0; - } else { - return DefWindowProc(hWnd, message, wParam, lParam); - } - } - - switch (message) { - case WM_DROPFILES: { - HDROP drop_handle = reinterpret_cast(wParam); - auto drop_count = DragQueryFileW(drop_handle, 0xFFFFFFFFu, nullptr, 0); - if (drop_count > 0) { - // Get required buffer size - UINT path_size = DragQueryFileW(drop_handle, 0, nullptr, 0); - if (path_size > 0 && path_size < 0xFFFFFFFFu) { - std::u16string path; - ++path_size; // Ensure space for the null terminator - path.resize(path_size); // Reserve space - // Only getting first file dropped (other files ignored) - path_size = - DragQueryFileW(drop_handle, 0, (LPWSTR)&path[0], path_size); - if (path_size > 0) { - path.resize(path_size); // Will drop the null terminator - auto e = FileDropEvent(this, xe::to_path(path)); - OnFileDrop(&e); - } + SetMenu(hwnd_, main_menu->handle()); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); } + return; } - DragFinish(drop_handle); - } break; - case WM_NCCREATE: { - // Tell Windows to automatically scale non-client areas on different DPIs. - auto en = (BOOL(WINAPI*)(HWND hwnd))GetProcAddress( - GetModuleHandleW(L"user32.dll"), "EnableNonClientDpiScaling"); - if (en) { - en(hWnd); - } - } break; - case WM_CREATE: - break; - case WM_DESTROY: - OnDestroy(); - break; - case WM_CLOSE: - OnClose(); - break; - - case WM_MOVING: - break; - case WM_MOVE: - break; - case WM_SIZING: - break; - case WM_SIZE: { - auto e = UIEvent(this); - OnResize(&e); - } break; - - case WM_PAINT: { - ValidateRect(hwnd_, nullptr); - static bool in_paint = false; - if (!in_paint) { - in_paint = true; - auto e = UIEvent(this); - OnPaint(&e); - in_paint = false; - } - return 0; // Ignored because of custom paint. - } - case WM_ERASEBKGND: - return 0; // Ignored because of custom paint. - case WM_DISPLAYCHANGE: - break; - case WM_DPICHANGED: { - LPRECT rect = (LPRECT)lParam; - if (rect) { - RawReposition(*rect); - } - - auto e = UIEvent(this); - OnDpiChanged(&e); - } break; - - case WM_ACTIVATEAPP: - case WM_SHOWWINDOW: { - if (wParam == TRUE) { - auto e = UIEvent(this); - OnVisible(&e); - } else { - auto e = UIEvent(this); - OnHidden(&e); - } - break; } - case WM_KILLFOCUS: { - has_focus_ = false; - auto e = UIEvent(this); - OnLostFocus(&e); - break; + // For some reason, WM_DPICHANGED is not sent when the window is borderless + // fullscreen with per-monitor DPI awareness v1 (on Windows versions since + // Windows 8.1 before Windows 10 1703) - refresh the current DPI explicitly. + dpi_ = GetCurrentDpi(); + if (dpi_ != pre_fullscreen_dpi_) { + // Rescale the pre-fullscreen non-maximized window size to the new DPI as + // WM_DPICHANGED with the new rectangle was received for the fullscreen + // window size, not the windowed one. Simulating the behavior of the + // automatic resizing when changing the scale in the Windows settings (as + // of Windows 11 21H2 at least), which keeps the physical top-left origin + // of the entire window including the non-client area, but rescales the + // size. + // Note that WINDOWPLACEMENT contains workspace coordinates, which are + // adjusted to exclude toolbars such as the taskbar - the positions and + // rectangle origins there can't be mixed with origins of rectangles in + // virtual screen coordinates such as those involved in functions like + // GetWindowRect. + RECT new_dpi_rect; + new_dpi_rect.left = 0; + new_dpi_rect.top = 0; + new_dpi_rect.right = LONG(ConvertSizeDpi( + pre_fullscreen_normal_client_width_, dpi_, pre_fullscreen_dpi_)); + new_dpi_rect.bottom = LONG(ConvertSizeDpi( + pre_fullscreen_normal_client_height_, dpi_, pre_fullscreen_dpi_)); + AdjustWindowRectangle(new_dpi_rect); + pre_fullscreen_placement_.rcNormalPosition.right = + pre_fullscreen_placement_.rcNormalPosition.left + + (new_dpi_rect.right - new_dpi_rect.left); + pre_fullscreen_placement_.rcNormalPosition.bottom = + pre_fullscreen_placement_.rcNormalPosition.top + + (new_dpi_rect.bottom - new_dpi_rect.top); } - case WM_SETFOCUS: { - has_focus_ = true; - auto e = UIEvent(this); - OnGotFocus(&e); - break; + SetWindowPlacement(hwnd_, &pre_fullscreen_placement_); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; } - case WM_TABLET_QUERYSYSTEMGESTURESTATUS: - return - // disables press and hold (right-click) gesture - TABLET_DISABLE_PRESSANDHOLD | - // disables UI feedback on pen up (waves) - TABLET_DISABLE_PENTAPFEEDBACK | - // disables UI feedback on pen button down (circle) - TABLET_DISABLE_PENBARRELFEEDBACK | - // disables pen flicks (back, forward, drag down, drag up) - TABLET_DISABLE_FLICKS | TABLET_DISABLE_TOUCHSWITCH | - TABLET_DISABLE_SMOOTHSCROLLING | TABLET_DISABLE_TOUCHUIFORCEON | - TABLET_ENABLE_MULTITOUCHDATA; + // https://devblogs.microsoft.com/oldnewthing/20131017-00/?p=2903 + SetWindowPos(hwnd_, nullptr, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | + SWP_FRAMECHANGED); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } - case WM_MENUCOMMAND: { - // TODO(benvanik): Redirect this to MenuItem's on_selected delegate. - MENUINFO menu_info = {0}; - menu_info.cbSize = sizeof(menu_info); - menu_info.fMask = MIM_MENUDATA; - GetMenuInfo(HMENU(lParam), &menu_info); - auto parent_item = reinterpret_cast(menu_info.dwMenuData); - auto child_item = - reinterpret_cast(parent_item->child(wParam)); - assert_not_null(child_item); - UIEvent e(this); - child_item->OnSelected(&e); - } break; + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } } - - return DefWindowProc(hWnd, message, wParam, lParam); } -bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { - int32_t x = GET_X_LPARAM(lParam); - int32_t y = GET_Y_LPARAM(lParam); - if (message == WM_MOUSEWHEEL) { - POINT pt = {x, y}; - ScreenToClient(hwnd_, &pt); - x = pt.x; - y = pt.y; +void Win32Window::ApplyNewTitle() { + SetWindowTextW(hwnd_, + reinterpret_cast(xe::to_utf16(GetTitle()).c_str())); +} + +void Win32Window::LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) { + bool reset = !buffer || !size; + + HICON new_icon, new_icon_small; + if (reset) { + if (!icon_) { + // The icon is already the default one. + return; + } + if (!hwnd_) { + // Don't need to get the actual icon from the class if there's nothing to + // set it for yet (and there's no HWND to get it from, and the class may + // have not been registered yet also). + DestroyIcon(icon_); + icon_ = nullptr; + return; + } + new_icon = reinterpret_cast(GetClassLongPtrW(hwnd_, GCLP_HICON)); + new_icon_small = + reinterpret_cast(GetClassLongPtrW(hwnd_, GCLP_HICONSM)); + // Not caring if it's null in the class, accepting anything the class + // specifies. + } else { + new_icon = CreateIconFromResourceEx( + static_cast(const_cast(buffer)), DWORD(size), TRUE, + 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + if (!new_icon) { + return; + } + new_icon_small = new_icon; + } + + if (hwnd_) { + SendMessageW(hwnd_, WM_SETICON, ICON_BIG, + reinterpret_cast(new_icon)); + SendMessageW(hwnd_, WM_SETICON, ICON_SMALL, + reinterpret_cast(new_icon_small)); + } + + // The old icon is not in use anymore, safe to destroy it now. + if (icon_) { + DestroyIcon(icon_); + icon_ = nullptr; + } + + if (!reset) { + assert_true(new_icon_small == new_icon); + icon_ = new_icon; + } +} + +void Win32Window::ApplyNewMainMenu(MenuItem* old_main_menu) { + if (IsFullscreen()) { + // The menu will be set when exiting fullscreen. + return; + } + const Win32MenuItem* main_menu = + static_cast(GetMainMenu()); + WindowDestructionReceiver destruction_receiver(this); + SetMenu(hwnd_, main_menu ? main_menu->handle() : nullptr); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::CompleteMainMenuItemsUpdateImpl() { + if (IsFullscreen()) { + return; + } + DrawMenuBar(hwnd_); +} + +void Win32Window::ApplyNewMouseCapture() { + WindowDestructionReceiver destruction_receiver(this); + SetCapture(hwnd_); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::ApplyNewMouseRelease() { + if (GetCapture() != hwnd_) { + return; + } + WindowDestructionReceiver destruction_receiver(this); + ReleaseCapture(); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) { + CursorVisibility new_cursor_visibility = GetCursorVisibility(); + cursor_currently_auto_hidden_ = false; + if (new_cursor_visibility == CursorVisibility::kAutoHidden) { + if (!GetCursorPos(&cursor_auto_hide_last_screen_pos_)) { + cursor_auto_hide_last_screen_pos_.x = LONG_MAX; + cursor_auto_hide_last_screen_pos_.y = LONG_MAX; + } + cursor_currently_auto_hidden_ = true; + } else if (old_cursor_visibility == CursorVisibility::kAutoHidden) { + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + } + SetCursorIfFocusedOnClientArea( + new_cursor_visibility == CursorVisibility::kVisible ? arrow_cursor_ + : nullptr); +} + +void Win32Window::FocusImpl() { SetFocus(hwnd_); } + +std::unique_ptr Win32Window::CreateSurfaceImpl( + Surface::TypeFlags allowed_types) { + HINSTANCE hInstance = + static_cast(app_context()).hinstance(); + if (allowed_types & Surface::kTypeFlag_Win32Hwnd) { + return std::make_unique(hInstance, hwnd_); + } + return nullptr; +} + +void Win32Window::RequestPaintImpl() { InvalidateRect(hwnd_, nullptr, FALSE); } + +BOOL Win32Window::AdjustWindowRectangle(RECT& rect, DWORD style, BOOL menu, + DWORD ex_style, UINT dpi) const { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->adjust_window_rect_ex_for_dpi( + &rect, style, menu, ex_style, dpi); + } + // Before per-monitor DPI v2, there was no rescaling of the non-client + // area at runtime at all, so throughout the execution of the process it will + // behave the same regardless of the DPI. + return AdjustWindowRectEx(&rect, style, menu, ex_style); +} + +BOOL Win32Window::AdjustWindowRectangle(RECT& rect) const { + if (!hwnd_) { + return FALSE; + } + return AdjustWindowRectangle(rect, GetWindowLong(hwnd_, GWL_STYLE), + BOOL(GetMainMenu() != nullptr), + GetWindowLong(hwnd_, GWL_EXSTYLE), dpi_); +} + +uint32_t Win32Window::GetCurrentSystemDpi() const { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->get_dpi_for_system(); + } + + HDC screen_hdc = GetDC(nullptr); + if (!screen_hdc) { + return USER_DEFAULT_SCREEN_DPI; + } + // According to MSDN, x and y are identical. + int logical_pixels_x = GetDeviceCaps(screen_hdc, LOGPIXELSX); + ReleaseDC(nullptr, screen_hdc); + return uint32_t(logical_pixels_x); +} + +uint32_t Win32Window::GetCurrentDpi() const { + if (hwnd_) { + const Win32WindowedAppContext& win32_app_context = + static_cast(app_context()); + + const Win32WindowedAppContext::PerMonitorDpiV2Api* per_monitor_dpi_v2_api = + win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + return per_monitor_dpi_v2_api->get_dpi_for_window(hwnd_); + } + + const Win32WindowedAppContext::PerMonitorDpiV1Api* per_monitor_dpi_v1_api = + win32_app_context.per_monitor_dpi_v1_api(); + if (per_monitor_dpi_v1_api) { + HMONITOR monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST); + UINT monitor_dpi_x, monitor_dpi_y; + if (monitor && + SUCCEEDED(per_monitor_dpi_v1_api->get_dpi_for_monitor( + monitor, MDT_DEFAULT, &monitor_dpi_x, &monitor_dpi_y))) { + // According to MSDN, x and y are identical. + return monitor_dpi_x; + } + } + } + + return GetCurrentSystemDpi(); +} + +void Win32Window::ApplyFullscreenEntry( + WindowDestructionReceiver& destruction_receiver) { + if (!IsFullscreen()) { + return; + } + + // https://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx + // No reason to use MONITOR_DEFAULTTOPRIMARY instead of + // MONITOR_DEFAULTTONEAREST, however. + pre_fullscreen_dpi_ = dpi_; + pre_fullscreen_placement_.length = sizeof(pre_fullscreen_placement_); + HMONITOR monitor; + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + if (!GetWindowPlacement(hwnd_, &pre_fullscreen_placement_) || + !(monitor = MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST)) || + !GetMonitorInfo(monitor, &monitor_info)) { + OnDesiredFullscreenUpdate(false); + return; + } + // Preserve values for DPI rescaling of the window in the non-maximized state + // if DPI is changed mid-fullscreen. + // Get the size of the non-client area to subtract it from the size of the + // entire window in its non-maximized state, to get the client area. + RECT non_client_area_rect = {}; + AdjustWindowRectangle(non_client_area_rect); + pre_fullscreen_normal_client_width_ = + uint32_t((pre_fullscreen_placement_.rcNormalPosition.right - + pre_fullscreen_placement_.rcNormalPosition.left) - + (non_client_area_rect.right - non_client_area_rect.left)); + pre_fullscreen_normal_client_height_ = + uint32_t((pre_fullscreen_placement_.rcNormalPosition.bottom - + pre_fullscreen_placement_.rcNormalPosition.top) - + (non_client_area_rect.bottom - non_client_area_rect.top)); + + // Changing the style and the menu may change the size too, don't handle the + // resize multiple times (also potentially with the listeners changing the + // desired fullscreen if called from the handling of some message like + // WM_SIZE). + BeginBatchedSizeUpdate(); + + // Remove the non-client area. + if (GetMainMenu()) { + SetMenu(hwnd_, nullptr); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + } + SetWindowLong(hwnd_, GWL_STYLE, + GetWindowLong(hwnd_, GWL_STYLE) & ~DWORD(WS_OVERLAPPEDWINDOW)); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + // Resize the window to fullscreen. It is important that this is done _after_ + // disabling the decorations and the menu, to make sure that composition will + // not have to be done for the new size of the window at all, so independent, + // low-latency presentation is possible immediately - if the window was + // involved in composition, it may stay composed persistently until some other + // state change that sometimes helps, sometimes doesn't, even if it becomes + // borderless fullscreen again - this occurs sometimes at least on Windows 11 + // 21H2 on Nvidia GeForce GTX 1070 on driver version 472.12. + SetWindowPos(hwnd_, HWND_TOP, monitor_info.rcMonitor.left, + monitor_info.rcMonitor.top, + monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, + monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + if (!destruction_receiver.IsWindowDestroyed()) { + EndBatchedSizeUpdate(destruction_receiver); + } + return; + } + + EndBatchedSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } +} + +void Win32Window::HandleSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + if (!hwnd_) { + // Batched size update ended when the window has already been closed, for + // instance. + return; + } + + { + MonitorUpdateEvent e(this, false); + OnMonitorUpdate(e); + } + + // For the desired size in the normal, not maximized and not fullscreen state. + if (!IsFullscreen()) { + WINDOWPLACEMENT window_placement; + window_placement.length = sizeof(window_placement); + if (GetWindowPlacement(hwnd_, &window_placement)) { + // window_placement.rcNormalPosition is the entire window's rectangle, not + // only the client area - convert to client. + // https://devblogs.microsoft.com/oldnewthing/20131017-00/?p=2903 + RECT non_client_rect = {}; + if (AdjustWindowRectangle(non_client_rect)) { + OnDesiredLogicalSizeUpdate( + SizeToLogical(uint32_t((window_placement.rcNormalPosition.right - + non_client_rect.right) - + (window_placement.rcNormalPosition.left - + non_client_rect.left))), + SizeToLogical(uint32_t((window_placement.rcNormalPosition.bottom - + non_client_rect.bottom) - + (window_placement.rcNormalPosition.top - + non_client_rect.top)))); + } + } + } + + // For the actual state. + RECT client_rect; + if (GetClientRect(hwnd_, &client_rect)) { + OnActualSizeUpdate(uint32_t(client_rect.right - client_rect.left), + uint32_t(client_rect.bottom - client_rect.top), + destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + return; + } + } +} + +void Win32Window::BeginBatchedSizeUpdate() { + // It's okay if batched_size_update_contained_* are not false when beginning + // a batched update, in case the new batched update was started by a window + // listener called from within EndBatchedSizeUpdate. + ++batched_size_update_depth_; +} + +void Win32Window::EndBatchedSizeUpdate( + WindowDestructionReceiver& destruction_receiver) { + assert_not_zero(batched_size_update_depth_); + if (--batched_size_update_depth_) { + return; + } + // Resetting batched_size_update_contained_* in closing, not opening, because + // a listener may start a new batch, and finish it, and there won't be need to + // handle the deferred messages twice. + if (batched_size_update_contained_wm_size_) { + batched_size_update_contained_wm_size_ = false; + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + return; + } + } + if (batched_size_update_contained_wm_paint_) { + batched_size_update_contained_wm_paint_ = false; + RequestPaint(); + } +} + +bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver) { + // Mouse messages usually contain the position in the client area in lParam, + // but WM_MOUSEWHEEL is an exception, it passes the screen position. + int32_t message_x = GET_X_LPARAM(lParam); + int32_t message_y = GET_Y_LPARAM(lParam); + bool message_pos_is_screen = message == WM_MOUSEWHEEL; + + POINT client_pos = {message_x, message_y}; + if (message_pos_is_screen) { + ScreenToClient(hwnd_, &client_pos); + } + + if (GetCursorVisibility() == CursorVisibility::kAutoHidden) { + POINT screen_pos = {message_x, message_y}; + if (message_pos_is_screen || ClientToScreen(hwnd_, &screen_pos)) { + if (screen_pos.x != cursor_auto_hide_last_screen_pos_.x || + screen_pos.y != cursor_auto_hide_last_screen_pos_.y) { + // WM_MOUSEMOVE messages followed by WM_SETCURSOR may be sent for + // reasons not always involving actual mouse movement performed by the + // user. They're sent when the position of the cursor relative to the + // client area has been changed, as well as other events related to + // window management (including when creating the window), even when not + // interacting with the OS. These should not be revealing the cursor. + // Only revealing it if the mouse has actually been moved. + cursor_currently_auto_hidden_ = false; + SetCursorAutoHideTimer(); + // There's no need to SetCursor here, mouse messages relevant to the + // cursor within the window are always followed by WM_SETCURSOR. + cursor_auto_hide_last_screen_pos_ = screen_pos; + } + } } MouseEvent::Button button = MouseEvent::Button::kNone; - int32_t dx = x - last_mouse_pos_.x; - int32_t dy = y - last_mouse_pos_.y; + int32_t scroll_y = 0; switch (message) { case WM_LBUTTONDOWN: case WM_LBUTTONUP: @@ -673,7 +831,8 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { button = MouseEvent::Button::kX2; break; default: - return false; + // Still handle the movement. + break; } break; case WM_MOUSEMOVE: @@ -681,59 +840,412 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { break; case WM_MOUSEWHEEL: button = MouseEvent::Button::kNone; - dx = 0; // ? - dy = GET_WHEEL_DELTA_WPARAM(wParam); + static_assert( + MouseEvent::kScrollPerDetent == WHEEL_DELTA, + "Assuming the Windows scroll amount can be passed directly to " + "MouseEvent"); + scroll_y = GET_WHEEL_DELTA_WPARAM(wParam); break; default: - // Double click/etc? - return true; + return false; } - last_mouse_pos_ = {x, y}; - - auto e = MouseEvent(this, button, x, y, dx, dy); + MouseEvent e(this, button, client_pos.x, client_pos.y, 0, scroll_y); switch (message) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: - OnMouseDown(&e); + OnMouseDown(e, destruction_receiver); break; case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: - OnMouseUp(&e); + OnMouseUp(e, destruction_receiver); break; case WM_MOUSEMOVE: - OnMouseMove(&e); + OnMouseMove(e, destruction_receiver); break; case WM_MOUSEWHEEL: - OnMouseWheel(&e); + OnMouseWheel(e, destruction_receiver); + break; + default: break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } -bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) { - auto e = KeyEvent( - this, VirtualKey(wParam), lParam & 0xFFFF0000, !!(lParam & 0x2), - !!(GetKeyState(VK_SHIFT) & 0x80), !!(GetKeyState(VK_CONTROL) & 0x80), - !!(GetKeyState(VK_MENU) & 0x80), !!(GetKeyState(VK_LWIN) & 0x80)); +bool Win32Window::HandleKeyboard( + UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver) { + KeyEvent e(this, VirtualKey(wParam), lParam & 0xFFFF, + !!(lParam & (LPARAM(1) << 30)), !!(GetKeyState(VK_SHIFT) & 0x80), + !!(GetKeyState(VK_CONTROL) & 0x80), + !!(GetKeyState(VK_MENU) & 0x80), !!(GetKeyState(VK_LWIN) & 0x80)); switch (message) { case WM_KEYDOWN: - OnKeyDown(&e); + OnKeyDown(e, destruction_receiver); break; case WM_KEYUP: - OnKeyUp(&e); + OnKeyUp(e, destruction_receiver); break; case WM_CHAR: - OnKeyChar(&e); + OnKeyChar(e, destruction_receiver); + break; + default: break; } + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed(). return e.is_handled(); } +void Win32Window::SetCursorIfFocusedOnClientArea(HCURSOR cursor) const { + if (!HasFocus()) { + return; + } + POINT cursor_pos; + if (!GetCursorPos(&cursor_pos)) { + return; + } + if (WindowFromPoint(cursor_pos) == hwnd_ && + SendMessage(hwnd_, WM_NCHITTEST, 0, + MAKELONG(cursor_pos.x, cursor_pos.y)) == HTCLIENT) { + SetCursor(cursor); + } +} + +void Win32Window::SetCursorAutoHideTimer() { + // Reset the timer by deleting the old timer and creating the new one. + // ChangeTimerQueueTimer doesn't work if the timer has already expired. + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + // After making sure that the callback is not callable anymore + // (DeleteTimerQueueTimer waits for the completion of the callback if it has + // been called already, or cancels it if it's hasn't), update the most recent + // message revision. + last_cursor_auto_hide_queued = last_cursor_auto_hide_signaled + 1; + CreateTimerQueueTimer(&cursor_auto_hide_timer_, nullptr, + AutoHideCursorTimerCallback, this, + kDefaultCursorAutoHideMilliseconds, 0, + WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE); +} + +void Win32Window::AutoHideCursorTimerCallback(void* parameter, + BOOLEAN timer_or_wait_fired) { + if (!timer_or_wait_fired) { + // Not a timer callback. + return; + } + Win32Window& window = *static_cast(parameter); + window.last_cursor_auto_hide_signaled = window.last_cursor_auto_hide_queued; + SendMessage(window.hwnd_, kUserMessageAutoHideCursor, + window.last_cursor_auto_hide_signaled, 0); +} + +LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, + LPARAM lParam) { + if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) { + WindowDestructionReceiver destruction_receiver(this); + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed() afterwards. + return HandleMouse(message, wParam, lParam, destruction_receiver) + ? 0 + : DefWindowProc(hWnd, message, wParam, lParam); + } + if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { + WindowDestructionReceiver destruction_receiver(this); + // Returning immediately anyway - no need to check + // destruction_receiver.IsWindowDestroyed() afterwards. + return HandleKeyboard(message, wParam, lParam, destruction_receiver) + ? 0 + : DefWindowProc(hWnd, message, wParam, lParam); + } + + switch (message) { + case WM_CLOSE: + // In case the Windows window was somehow forcibly destroyed without + // WM_CLOSE. + case WM_DESTROY: { + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + { + WindowDestructionReceiver destruction_receiver(this); + OnBeforeClose(destruction_receiver); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + } + // Set hwnd_ to null to ignore events from now on since this Win32Window + // is entering an indeterminate state - this should be done at some point + // in closing anyway. + hwnd_ = nullptr; + SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); + if (message != WM_DESTROY) { + DestroyWindow(hWnd); + } + OnAfterClose(); + } break; + + case WM_DROPFILES: { + HDROP drop_handle = reinterpret_cast(wParam); + auto drop_count = DragQueryFileW(drop_handle, 0xFFFFFFFFu, nullptr, 0); + if (drop_count > 0) { + // Get required buffer size + UINT path_size = DragQueryFileW(drop_handle, 0, nullptr, 0); + if (path_size > 0 && path_size < 0xFFFFFFFFu) { + std::u16string path; + ++path_size; // Ensure space for the null terminator + path.resize(path_size); // Reserve space + // Only getting first file dropped (other files ignored) + path_size = + DragQueryFileW(drop_handle, 0, (LPWSTR)&path[0], path_size); + if (path_size > 0) { + path.resize(path_size); // Will drop the null terminator + FileDropEvent e(this, xe::to_path(path)); + WindowDestructionReceiver destruction_receiver(this); + OnFileDrop(e, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + DragFinish(drop_handle); + break; + } + } + } + } + DragFinish(drop_handle); + } break; + + case WM_MOVE: { + OnMonitorUpdate(MonitorUpdateEvent(this, false)); + } break; + + case WM_SIZE: { + if (batched_size_update_depth_) { + batched_size_update_contained_wm_size_ = true; + } else { + WindowDestructionReceiver destruction_receiver(this); + HandleSizeUpdate(destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + + case WM_PAINT: { + if (batched_size_update_depth_) { + // Avoid painting an outdated surface during a batched size update when + // WM_SIZE handling is deferred. + batched_size_update_contained_wm_paint_ = true; + } else { + ValidateRect(hwnd_, nullptr); + OnPaint(); + } + // Custom painting via OnPaint - don't pass to DefWindowProc. + return 0; + } break; + + case WM_ERASEBKGND: { + if (HasSurface()) { + // Don't erase between paints because painting may be dropped if nothing + // has changed since the last one. + return 0; + } + } break; + + case WM_DISPLAYCHANGE: { + OnMonitorUpdate(MonitorUpdateEvent(this, true)); + } break; + + case WM_DPICHANGED: { + // Note that for some reason, WM_DPICHANGED is not sent when the window is + // borderless fullscreen with per-monitor DPI awareness v1. + + dpi_ = GetCurrentDpi(); + + WindowDestructionReceiver destruction_receiver(this); + + { + UISetupEvent e(this); + OnDpiChanged(e, destruction_receiver); + // The window might have been closed by the handler, check hwnd_ too + // since it's needed below. + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + + auto rect = reinterpret_cast(lParam); + if (rect) { + // SetWindowPos arguments according to WM_DPICHANGED MSDN documentation. + // https://docs.microsoft.com/en-us/windows/win32/hidpi/wm-dpichanged + // There's no need to handle the maximized state any special way (by + // updating the window placement instead of the window position in this + // case, for instance), as Windows (by design) restores the window when + // changing the DPI to a new one. + SetWindowPos(hwnd_, nullptr, int(rect->left), int(rect->top), + int(rect->right - rect->left), + int(rect->bottom - rect->top), + SWP_NOZORDER | SWP_NOACTIVATE); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } + } break; + + case WM_KILLFOCUS: { + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(false, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case WM_SETFOCUS: { + WindowDestructionReceiver destruction_receiver(this); + OnFocusUpdate(true, destruction_receiver); + if (destruction_receiver.IsWindowDestroyedOrClosed()) { + break; + } + } break; + + case WM_SETCURSOR: { + if (reinterpret_cast(wParam) == hwnd_ && HasFocus() && + LOWORD(lParam) == HTCLIENT) { + switch (GetCursorVisibility()) { + case CursorVisibility::kAutoHidden: { + // Always revealing the cursor in case of events like clicking, but + // WM_MOUSEMOVE messages may be sent for reasons not always + // involving actual mouse movement performed by the user. Revealing + // the cursor in case of movement is done in HandleMouse instead. + if (HIWORD(lParam) != WM_MOUSEMOVE) { + cursor_currently_auto_hidden_ = false; + SetCursorAutoHideTimer(); + } + if (cursor_currently_auto_hidden_) { + SetCursor(nullptr); + return TRUE; + } + } break; + case CursorVisibility::kHidden: + SetCursor(nullptr); + return TRUE; + default: + break; + } + } + // For the non-client area, and for visible cursor, letting normal + // processing happen, setting the cursor to an arrow or to something + // specific to non-client parts of the window. + } break; + + case kUserMessageAutoHideCursor: { + // Recheck the cursor visibility - the callback might have been called + // before or while the timer is deleted. Also ignore messages from + // outdated mouse interactions. + if (GetCursorVisibility() == CursorVisibility::kAutoHidden && + wParam == last_cursor_auto_hide_queued) { + // The timer object is not needed anymore. + if (cursor_auto_hide_timer_) { + DeleteTimerQueueTimer(nullptr, cursor_auto_hide_timer_, nullptr); + cursor_auto_hide_timer_ = nullptr; + } + cursor_currently_auto_hidden_ = true; + SetCursorIfFocusedOnClientArea(nullptr); + } + return 0; + } break; + + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: + return + // disables press and hold (right-click) gesture + TABLET_DISABLE_PRESSANDHOLD | + // disables UI feedback on pen up (waves) + TABLET_DISABLE_PENTAPFEEDBACK | + // disables UI feedback on pen button down (circle) + TABLET_DISABLE_PENBARRELFEEDBACK | + // disables pen flicks (back, forward, drag down, drag up) + TABLET_DISABLE_FLICKS | TABLET_DISABLE_TOUCHSWITCH | + TABLET_DISABLE_SMOOTHSCROLLING | TABLET_DISABLE_TOUCHUIFORCEON | + TABLET_ENABLE_MULTITOUCHDATA; + + case WM_MENUCOMMAND: { + MENUINFO menu_info = {0}; + menu_info.cbSize = sizeof(menu_info); + menu_info.fMask = MIM_MENUDATA; + GetMenuInfo(HMENU(lParam), &menu_info); + auto parent_item = reinterpret_cast(menu_info.dwMenuData); + auto child_item = + reinterpret_cast(parent_item->child(wParam)); + assert_not_null(child_item); + WindowDestructionReceiver destruction_receiver(this); + child_item->OnSelected(); + if (destruction_receiver.IsWindowDestroyed()) { + break; + } + // The menu item might have been destroyed by its OnSelected, don't do + // anything with it here from now on. + } break; + } + + // The window might have been destroyed by the handlers, don't interact with + // *this in this function from now on. + + // Passing the original hWnd argument rather than hwnd_ as the window might + // have been closed or destroyed by a handler, making hwnd_ null even though + // DefWindowProc still needs to be called to propagate the closing-related + // messages needed by Windows, or inaccessible (due to use-after-free) at all. + return DefWindowProc(hWnd, message, wParam, lParam); +} + +LRESULT CALLBACK Win32Window::WndProcThunk(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) { + if (hWnd) { + Win32Window* window = nullptr; + if (message == WM_NCCREATE) { + auto create_struct = reinterpret_cast(lParam); + window = reinterpret_cast(create_struct->lpCreateParams); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window); + // Don't miss any messages (as they may have effect on the actual state + // stored in Win32Window) sent before the completion of CreateWindowExW + // dropped because `window->hwnd_ != hWnd`, when the result of + // CreateWindowExW still hasn't been assigned to `hwnd_` (however, don't + // reattach this window to a closed window if WM_NCCREATE was somehow sent + // to a window being closed). + if (window->phase() == Phase::kOpening) { + assert_true(!window->hwnd_ || window->hwnd_ == hWnd); + window->hwnd_ = hWnd; + } + // Enable non-client area DPI scaling for AdjustWindowRectExForDpi to work + // correctly between Windows 10 1607 (when AdjustWindowRectExForDpi and + // EnableNonClientDpiScaling were added) and 1703 (when per-monitor + // awareness version 2 was added with automatically enabled non-client + // area DPI scaling). + const Win32WindowedAppContext& win32_app_context = + static_cast(window->app_context()); + const Win32WindowedAppContext::PerMonitorDpiV2Api* + per_monitor_dpi_v2_api = win32_app_context.per_monitor_dpi_v2_api(); + if (per_monitor_dpi_v2_api) { + per_monitor_dpi_v2_api->enable_non_client_dpi_scaling(hWnd); + } + // Already fully handled, no need to call Win32Window::WndProc. + } else { + window = + reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (window && window->hwnd_ == hWnd) { + return window->WndProc(hWnd, message, wParam, lParam); + } + } + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + std::unique_ptr MenuItem::Create(Type type, const std::string& text, const std::string& hotkey, @@ -772,20 +1284,12 @@ Win32MenuItem::~Win32MenuItem() { } } -void Win32MenuItem::EnableMenuItem(Window& window) { - int i = 0; - for (auto iter = children_.begin(); iter != children_.end(); ++iter, i++) { - ::EnableMenuItem(handle_, i, MF_BYPOSITION | MF_ENABLED); +void Win32MenuItem::SetEnabled(bool enabled) { + UINT enable_flags = MF_BYPOSITION | (enabled ? MF_ENABLED : MF_GRAYED); + UINT i = 0; + for (auto iter = children_.begin(); iter != children_.end(); ++iter, ++i) { + EnableMenuItem(handle_, i, enable_flags); } - DrawMenuBar((HWND)window.native_handle()); -} - -void Win32MenuItem::DisableMenuItem(Window& window) { - int i = 0; - for (auto iter = children_.begin(); iter != children_.end(); ++iter, i++) { - ::EnableMenuItem(handle_, i, MF_BYPOSITION | MF_GRAYED); - } - DrawMenuBar((HWND)window.native_handle()); } void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) { diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index f4dceaeac..dd5d8b978 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,10 +13,15 @@ #include #include -#include "xenia/base/platform_win.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/window.h" +// Must be included before Windows headers for things like NOMINMAX. +#include "xenia/base/platform_win.h" + +#include +#include + namespace xe { namespace ui { @@ -24,73 +29,127 @@ class Win32Window : public Window { using super = Window; public: - Win32Window(WindowedAppContext& app_context, const std::string& title); + Win32Window(WindowedAppContext& app_context, const std::string_view title, + uint32_t desired_logical_width, uint32_t desired_logical_height); ~Win32Window() override; - NativePlatformHandle native_platform_handle() const override; - NativeWindowHandle native_handle() const override { return hwnd_; } + // Will be null if the window hasn't been successfully opened yet, or has been + // closed. HWND hwnd() const { return hwnd_; } - void EnableMainMenu() override; - void DisableMainMenu() override; - - bool set_title(const std::string_view title) override; - - bool SetIcon(const void* buffer, size_t size) override; - - bool CaptureMouse() override; - bool ReleaseMouse() override; - - bool is_fullscreen() const override; - void ToggleFullscreen(bool fullscreen) override; - - bool is_bordered() const override; - void set_bordered(bool enabled) override; - - int get_dpi() const override; - - void set_cursor_visible(bool value) override; - void set_focus(bool value) override; - - void Resize(int32_t width, int32_t height) override; - void Resize(int32_t left, int32_t top, int32_t right, - int32_t bottom) override; - - // (raw) Resize the window, no DPI scaling applied. - void RawReposition(const RECT& rc); - - bool Initialize() override; - void Invalidate() override; - void Close() override; + uint32_t GetMediumDpi() const override; protected: - bool OnCreate() override; - void OnMainMenuChange() override; - void OnDestroy() override; - void OnClose() override; + bool OpenImpl() override; + void RequestCloseImpl() override; - void OnResize(UIEvent* e) override; + uint32_t GetLatestDpiImpl() const override; + + void ApplyNewFullscreen() override; + void ApplyNewTitle() override; + void LoadAndApplyIcon(const void* buffer, size_t size, + bool can_apply_state_in_current_phase) override; + void ApplyNewMainMenu(MenuItem* old_main_menu) override; + void CompleteMainMenuItemsUpdateImpl() override; + void ApplyNewMouseCapture() override; + void ApplyNewMouseRelease() override; + void ApplyNewCursorVisibility( + CursorVisibility old_cursor_visibility) override; + void FocusImpl() override; + + std::unique_ptr CreateSurfaceImpl( + Surface::TypeFlags allowed_types) override; + void RequestPaintImpl() override; + + private: + enum : UINT { + kUserMessageAutoHideCursor = WM_USER, + }; + + BOOL AdjustWindowRectangle(RECT& rect, DWORD style, BOOL menu, DWORD ex_style, + UINT dpi) const; + BOOL AdjustWindowRectangle(RECT& rect) const; + + uint32_t GetCurrentSystemDpi() const; + uint32_t GetCurrentDpi() const; + + void ApplyFullscreenEntry(WindowDestructionReceiver& destruction_receiver); + + void HandleSizeUpdate(WindowDestructionReceiver& destruction_receiver); + // For updating multiple factors that may influence the window size at once, + // without handling WM_SIZE multiple times (that may not only result in wasted + // handling, but also in the state potentially changed to an inconsistent one + // in the middle of a size update by the listeners). + void BeginBatchedSizeUpdate(); + void EndBatchedSizeUpdate(WindowDestructionReceiver& destruction_receiver); + + bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver); + bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam, + WindowDestructionReceiver& destruction_receiver); + + void SetCursorIfFocusedOnClientArea(HCURSOR cursor) const; + void SetCursorAutoHideTimer(); + static void NTAPI AutoHideCursorTimerCallback(void* parameter, + BOOLEAN timer_or_wait_fired); static LRESULT CALLBACK WndProcThunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + // This can't handle messages sent during CreateWindow (hwnd_ still not + // assigned to) or after nulling hwnd_ in closing / deleting. virtual LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - private: - void EnableMMCSS(); - bool HandleMouse(UINT message, WPARAM wParam, LPARAM lParam); - bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam); - - HWND hwnd_ = nullptr; - HICON icon_ = nullptr; - bool closing_ = false; - bool fullscreen_ = false; HCURSOR arrow_cursor_ = nullptr; - WINDOWPLACEMENT windowed_pos_ = {0}; - POINT last_mouse_pos_ = {0}; + HICON icon_ = nullptr; - void* GetDpiForMonitor_ = nullptr; + uint32_t dpi_ = USER_DEFAULT_SCREEN_DPI; + + // hwnd_ may be accessed by the cursor hiding timer callback from a separate + // thread, but the timer can be active only with a valid window anyway. + HWND hwnd_ = nullptr; + + uint32_t batched_size_update_depth_ = 0; + bool batched_size_update_contained_wm_size_ = false; + bool batched_size_update_contained_wm_paint_ = false; + + uint32_t pre_fullscreen_dpi_; + WINDOWPLACEMENT pre_fullscreen_placement_; + // The client area part of pre_fullscreen_placement_.rcNormalPosition, saved + // in case something effecting the behavior of AdjustWindowRectEx for the + // non-fullscreen state is changed mid-fullscreen (for instance, the menu is + // toggled), so a new AdjustWindowRectExForDpi call for the old DPI, but with + // the other state different than the old one, while exiting fullscreen, won't + // cause anomalies like negative size. + uint32_t pre_fullscreen_normal_client_width_; + uint32_t pre_fullscreen_normal_client_height_; + + // Must be the screen position, not the client position, so it's possible to + // immediately hide the cursor, for instance, when switching to fullscreen + // (and thus changing the client area top-left corner, resulting in + // WM_MOUSEMOVE being sent, which would instantly reveal the cursor because of + // that relative position change). + POINT cursor_auto_hide_last_screen_pos_ = {LONG_MAX, LONG_MAX}; + // Using a timer queue timer for hiding the cursor rather than WM_TIMER + // because the latter is a very low-priority message which is never received + // if WM_PAINT messages are sent continuously (invalidating the window right + // after painting). + HANDLE cursor_auto_hide_timer_ = nullptr; + // Last hiding case numbers for skipping of obsolete cursor hiding messages + // (both WM_MOUSEMOVE and the hiding message have been sent, for instance, and + // WM_MOUSEMOVE hasn't been handled yet, or the cursor visibility state has + // been changed). The queued index is read, and the signaled index is written, + // by the timer callback, which is executed outside the message thread, so + // before modifying the queued number, or reading the signaled number, in the + // message thread, delete the timer (deleting the timer awaits cancels the + // callback if it hasn't been invoked yet, or awaits it if it has). Use + // equality comparison for safe rollover handling. + WPARAM last_cursor_auto_hide_queued = 0; + WPARAM last_cursor_auto_hide_signaled = 0; + // Whether the cursor has been hidden after the expiration of the timer, and + // hasn't been revealed yet. + bool cursor_currently_auto_hidden_ = false; }; class Win32MenuItem : public MenuItem { @@ -99,10 +158,9 @@ class Win32MenuItem : public MenuItem { std::function callback); ~Win32MenuItem() override; - HMENU handle() { return handle_; } + HMENU handle() const { return handle_; } - void EnableMenuItem(Window& window) override; - void DisableMenuItem(Window& window) override; + void SetEnabled(bool enabled) override; using MenuItem::OnSelected; diff --git a/src/xenia/ui/windowed_app_context_android.h b/src/xenia/ui/windowed_app_context_android.h index 91cd10427..bc7583109 100644 --- a/src/xenia/ui/windowed_app_context_android.h +++ b/src/xenia/ui/windowed_app_context_android.h @@ -36,7 +36,8 @@ class AndroidWindowedAppContext final : public WindowedAppContext { // The single Window instance that will be receiving window callbacks. // Multiple windows cannot be created as one activity or fragment can have // only one layout. This window acts purely as a proxy between the activity - // and the Xenia logic. + // and the Xenia logic. May be done during Window destruction, so must not + // interact with it. AndroidWindow* GetActivityWindow() const { return activity_window_; } void SetActivityWindow(AndroidWindow* window) { activity_window_ = window; } diff --git a/src/xenia/ui/windowed_app_context_win.cc b/src/xenia/ui/windowed_app_context_win.cc index 399a2afd4..f9371304a 100644 --- a/src/xenia/ui/windowed_app_context_win.cc +++ b/src/xenia/ui/windowed_app_context_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -22,10 +22,43 @@ Win32WindowedAppContext::~Win32WindowedAppContext() { if (pending_functions_hwnd_) { DestroyWindow(pending_functions_hwnd_); } + if (shcore_module_) { + FreeLibrary(shcore_module_); + } } bool Win32WindowedAppContext::Initialize() { // Logging possibly not initialized in this function yet. + + // Obtain function pointers that may be used for windows if available. + shcore_module_ = LoadLibraryW(L"SHCore.dll"); + if (shcore_module_) { + per_monitor_dpi_v1_api_available_ = true; + per_monitor_dpi_v1_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v1_api_.get_dpi_for_monitor) = + GetProcAddress(shcore_module_, "GetDpiForMonitor")) != nullptr; + per_monitor_dpi_v2_api_available_ = true; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.adjust_window_rect_ex_for_dpi) = + GetProcAddress(shcore_module_, "AdjustWindowRectExForDpi")) != + nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.enable_non_client_dpi_scaling) = + GetProcAddress(shcore_module_, "EnableNonClientDpiScaling")) != + nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.get_dpi_for_system) = + GetProcAddress(shcore_module_, "GetDpiForSystem")) != nullptr; + per_monitor_dpi_v2_api_available_ &= + (*reinterpret_cast( + &per_monitor_dpi_v2_api_.get_dpi_for_window) = + GetProcAddress(shcore_module_, "GetDpiForWindow")) != nullptr; + } + // Create the message-only window for executing pending functions - using a // window instead of executing them between iterations so non-main message // loops, such as Windows modals, can execute pending functions too. @@ -51,6 +84,7 @@ bool Win32WindowedAppContext::Initialize() { if (!pending_functions_hwnd_) { return false; } + return true; } @@ -117,7 +151,7 @@ LRESULT CALLBACK Win32WindowedAppContext::PendingFunctionsWndProc( break; case kPendingFunctionsWindowClassMessageExecute: app_context->ExecutePendingFunctionsFromUIThread(); - break; + return 0; default: break; } diff --git a/src/xenia/ui/windowed_app_context_win.h b/src/xenia/ui/windowed_app_context_win.h index 1c01961ac..08e70e662 100644 --- a/src/xenia/ui/windowed_app_context_win.h +++ b/src/xenia/ui/windowed_app_context_win.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2021 Ben Vanik. All rights reserved. * + * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,11 +15,42 @@ #include "xenia/base/platform_win.h" #include "xenia/ui/windowed_app_context.h" +// For per-monitor DPI awareness v1. +#include + namespace xe { namespace ui { class Win32WindowedAppContext final : public WindowedAppContext { public: + // clang-format off + struct PerMonitorDpiV1Api { + HRESULT (STDAPICALLTYPE* get_dpi_for_monitor)( + HMONITOR hmonitor, MONITOR_DPI_TYPE dpi_type, UINT* dpi_x, UINT* dpi_y); + }; + struct PerMonitorDpiV2Api { + // Important note: Even though per-monitor DPI awareness version 2 + // inherently has automatic non-client area DPI scaling, PMv2 was added in + // Windows 10 1703. However, these functions were added earlier, in 1607. + // While we haven't tested the actual behavior on 1607 and this is just a + // guess, still, before using AdjustWindowRectExForDpi for the window DPI, + // make sure that EnableNonClientDpiScaling is called for the window in its + // WM_NCCREATE handler to enable automatic non-client DPI scaling on PMv1 on + // 1607, so AdjustWindowRectExForDpi (which doesn't have a window argument + // so it can't know whether automatic scaling is enabled for it) will likely + // return values that reflect the actual size of the non-client area of the + // window (otherwise, for instance, "un-adjusting" the actual window + // rectangle using AdjustWindowRectExForDpi may result in a negative client + // area size if the DPI passed to it is larger than the DPI actually used + // for the non-client area). + BOOL (WINAPI* adjust_window_rect_ex_for_dpi)( + LPRECT rect, DWORD style, BOOL menu, DWORD ex_style, UINT dpi); + BOOL (WINAPI* enable_non_client_dpi_scaling)(HWND hwnd); + UINT (WINAPI* get_dpi_for_system)(); + UINT (WINAPI* get_dpi_for_window)(HWND hwnd); + }; + // clang-format on + // Must call Initialize and check its result after creating to be able to // perform pending function calls. explicit Win32WindowedAppContext(HINSTANCE hinstance, int show_cmd) @@ -37,6 +68,23 @@ class Win32WindowedAppContext final : public WindowedAppContext { int RunMainMessageLoop(); + // Per-monitor DPI awareness version 2 is expected to be enabled via the + // manifest, as that's the recommended way, which also doesn't require calling + // SetProcessDpiAwareness before doing anything that may depend on DPI + // awareness (so it's safe to use any Windows APIs before what would be + // supposed to initialize it). + // Windows 8.1 per-monitor DPI awareness version 1. + const PerMonitorDpiV1Api* per_monitor_dpi_v1_api() const { + return per_monitor_dpi_v1_api_available_ ? &per_monitor_dpi_v1_api_ + : nullptr; + } + // Windows 10 1607 per-monitor DPI awareness API, also heavily used for + // per-monitor DPI awareness version 2 functionality added in Windows 10 1703. + const PerMonitorDpiV2Api* per_monitor_dpi_v2_api() const { + return per_monitor_dpi_v2_api_available_ ? &per_monitor_dpi_v2_api_ + : nullptr; + } + private: enum : UINT { kPendingFunctionsWindowClassMessageExecute = WM_USER, @@ -47,9 +95,15 @@ class Win32WindowedAppContext final : public WindowedAppContext { HINSTANCE hinstance_; int show_cmd_; - HWND pending_functions_hwnd_ = nullptr; + + HMODULE shcore_module_ = nullptr; + PerMonitorDpiV1Api per_monitor_dpi_v1_api_ = {}; + PerMonitorDpiV2Api per_monitor_dpi_v2_api_ = {}; + bool per_monitor_dpi_v1_api_available_ = false; + bool per_monitor_dpi_v2_api_available_ = false; static bool pending_functions_window_class_registered_; + HWND pending_functions_hwnd_ = nullptr; }; } // namespace ui diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index d27d37661..574501788 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -312,7 +312,8 @@ struct X_OBJECT_ATTRIBUTES { // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082.aspx typedef struct { - xe::be exception_code; + // Renamed due to a collision with exception_code from Windows excpt.h. + xe::be code; xe::be exception_flags; xe::be exception_record; xe::be exception_address; diff --git a/third_party/.clang-format b/third_party/.clang-format new file mode 100644 index 000000000..9d159247d --- /dev/null +++ b/third_party/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false diff --git a/third_party/FidelityFX-CAS b/third_party/FidelityFX-CAS new file mode 160000 index 000000000..9fabcc9a2 --- /dev/null +++ b/third_party/FidelityFX-CAS @@ -0,0 +1 @@ +Subproject commit 9fabcc9a2c45f958aff55ddfda337e74ef894b7f diff --git a/third_party/FidelityFX-FSR b/third_party/FidelityFX-FSR new file mode 160000 index 000000000..a21ffb8f6 --- /dev/null +++ b/third_party/FidelityFX-FSR @@ -0,0 +1 @@ +Subproject commit a21ffb8f6c13233ba336352bdff293894c706575 diff --git a/third_party/fxaa/FXAA3_11.h b/third_party/fxaa/FXAA3_11.h new file mode 100644 index 000000000..993966d10 --- /dev/null +++ b/third_party/fxaa/FXAA3_11.h @@ -0,0 +1,2065 @@ +//---------------------------------------------------------------------------------- +// File: es3-kepler\FXAA/FXAA3_11.h +// SDK Version: v2.11 +// Email: gameworks@nvidia.com +// Site: http://developer.nvidia.com/ +// +// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//---------------------------------------------------------------------------------- +/*============================================================================ + + + NVIDIA FXAA 3.11 by TIMOTHY LOTTES + +------------------------------------------------------------------------------ + INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + + #define FXAA_PC 1 + #define FXAA_HLSL_5 1 + #define FXAA_QUALITY__PRESET 12 + +Or, + + #define FXAA_360 1 + +Or, + + #define FXAA_PS3 1 + +Etc. + +(2.) +Then include this file, + + #include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + + return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + + #define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + + // {xy} = center of pixel + FxaaFloat2 pos, + + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ + INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + + #define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.rgb = sqrt(color.rgb); // gamma 2.0 color output + color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma + return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + + color.rgb = ToneMap(color.rgb); // linear color output + return color; + +To use FXAA, + + color.rgb = ToneMap(color.rgb); // linear color output + color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma + return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ + BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ + COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, + have the pass write out luma into alpha. + Then blend into RGB only. + FXAA should be able to run ok + assuming the blending pass did not any add aliasing. + This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + + INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 + #define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 + #define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT + #define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC + // + // FXAA Quality + // The high quality PC algorithm. + // + #define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT + // + // Controls algorithm's early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don't need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don't need AA. + // + #define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif +#endif + +/*============================================================================ + FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS + // + // Consoles the sharpness of edges on PS3 only. + // Non-PS3 tuning is done with shader input. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 8.0 is sharper + // 4.0 is softer + // 2.0 is really soft (good for vector graphics inputs) + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 + #endif + #if 0 + #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 + #endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD + // + // Only effects PS3. + // Non-PS3 tuning is done with shader input. + // + // The minimum amount of local contrast required to apply algorithm. + // The console setting has a different mapping than the quality setting. + // + // This only applies when FXAA_EARLY_EXIT is 1. + // + // Due to the PS3 being ALU bound, + // there are only two safe values here: 0.25 and 0.125. + // These options use the shaders ability to a free *|/ by 2|4|8. + // + // 0.125 leaves less aliasing, but is softer + // 0.25 leaves more aliasing, and is sharper + // + #if 1 + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 + #else + #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 + #endif +#endif + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + + API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +#else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + + +/*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x___} = 8.0/screenWidthInPixels + // {_y__} = 8.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immedates. + // Immedates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif +/*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + + FXAA3 CONSOLE - PC VERSION + +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with + #define FXAA_QUALITY__PRESET 10 +Or + #define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat lumaM = rgbyM.w; + #else + FxaaFloat lumaM = rgbyM.y; + #endif +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); + #else + FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); + #endif + if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ + float4 lumaNwNeSwSe; + #if (FXAA_GREEN_AS_LUMA == 0) + asm { + tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #else + asm { + tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false + tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false + }; + #endif +/*--------------------------------------------------------------------------*/ + lumaNwNeSwSe.y += 1.0/384.0; + float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); + float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); + float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ + float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + float lumaMinM = min(lumaMin, rgbyM.w); + float lumaMaxM = max(lumaMax, rgbyM.w); + #else + float lumaMinM = min(lumaMin, rgbyM.y); + float lumaMaxM = max(lumaMax, rgbyM.y); + #endif + if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ + float2 dir; + dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); + dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); + dir = normalize(dir); +/*--------------------------------------------------------------------------*/ + float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ + float4 dir2; + float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; + dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); + dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ + float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); + float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); + float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); + float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ + float4 rgbyA = rgbyN1 + rgbyP1; + float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ + float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; + rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; + return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h0.w(TRUE), v5.xwxx, #0 + 6: addh h0.z(TRUE), -h2, h0.w + 7: texpkb h1.w(TRUE), v5, #0 + 9: addh h0.x(TRUE), h0.z, -h1.w + 10: addh h3.w(TRUE), h0.z, h1 + 11: texpkb h2.w(TRUE), v5.zwzz, #0 + 13: addh h0.z(TRUE), h3.w, -h2.w + 14: addh h0.x(TRUE), h2.w, h0 + 15: nrmh h1.xz(TRUE), h0_n + 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| + 17: maxh h4.w(TRUE), h0, h1 + 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n + 19: movr r1.zw(TRUE), v4.xxxy + 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww + 22: minh h5.w(TRUE), h0, h1 + 23: texpkb h0(TRUE), r2.xzxx, #0 + 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 + 27: maxh h4.x(TRUE), h2.z, h2.w + 28: texpkb h1(TRUE), r0.zwzz, #0 + 30: addh_d2 h1(TRUE), h0, h1 + 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 33: texpkb h0(TRUE), r0, #0 + 35: minh h4.z(TRUE), h2, h2.w + 36: fenct TRUE + 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 39: texpkb h2(TRUE), r1, #0 + 41: addh_d2 h0(TRUE), h0, h2 + 42: maxh h2.w(TRUE), h4, h4.x + 43: minh h2.x(TRUE), h5.w, h4.z + 44: addh_d2 h0(TRUE), h0, h1 + 45: slth h2.x(TRUE), h0.w, h2 + 46: sgth h2.w(TRUE), h0, h2 + 47: movh h0(TRUE), h0 + 48: addx.c0 rc(TRUE), h2, h2.w + 49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; + | | | + 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; + | | | + 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; + | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; + | | | + 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; + | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; + | | | + 5 | SCT1 | mov | 15: NRMh h1.xz, h0; + | SRB | nrm | 15: NRMh h1.xz, h0; + | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; + | SCB1 | max | 17: MAXh h4.w, h0, h1; + | | | + 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; + | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; + | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; + | SCB1 | min | 22: MINh h5.w, h0, h1; + | | | + 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; + | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; + | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; + | | | + 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; + | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; + | | | + 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; + | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; + | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; + | | | + 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; + | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; + | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; + | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; + | | | + 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; + | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; + | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; + | | | + 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; + | SCT1 | set | 46: SGTh h2.w, h0, h2; + | SCB0/1 | mul | 47: MOVh h0, h0; + | | | + 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; + | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 0% 0% 50% + 6: 100% 0% 75% + 7: 0% 100% 75% + 8: 0% 100% 100% + 9: 0% 100% 25% + 10: 0% 100% 100% + 11: 50% 0% 100% + 12: 50% 0% 100% + 13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 0% 100% + 2: 0% 0% 100% 0% 100% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 0% 0% 0% 100% 100% + 6: 100% 100% 0% 100% 100% + 7: 0% 0% 100% 100% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 0% 100% + 10: 0% 0% 100% 100% 100% + 11: 100% 100% 0% 100% 100% + 12: 100% 100% 0% 100% 100% + 13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O3 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 dir; + half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + lumaNe.w += half(1.0/512.0); + dir.x = -lumaNe.w; + dir.z = -lumaNe.w; + #else + lumaNe.y += half(1.0/512.0); + dir.x = -lumaNe.y; + dir.z = -lumaNe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSw.w; + dir.z += lumaSw.w; + #else + dir.x += lumaSw.y; + dir.z += lumaSw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x -= lumaNw.w; + dir.z += lumaNw.w; + #else + dir.x -= lumaNw.y; + dir.z += lumaNw.y; + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x += lumaSe.w; + dir.z -= lumaSe.w; + #else + dir.x += lumaSe.y; + dir.z -= lumaSe.y; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half4 dir1_pos; + dir1_pos.xy = normalize(dir.xyz).xz; + half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) + // compilier moves these scalar ops up to other cycles + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); + half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); + #else + half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); + half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); + #endif + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif +/*--------------------------------------------------------------------------*/ +// (13) + if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + + FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + + --fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ + NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: + 0: texpkb h0.w(TRUE), v5.zyxx, #0 + 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x + 4: texpkb h1.w(TRUE), v5.xwxx, #0 + 6: addh h0.x(TRUE), h1.w, -h2.y + 7: texpkb h2.w(TRUE), v5.zwzz, #0 + 9: minh h4.w(TRUE), h2.y, h2 + 10: maxh h5.x(TRUE), h2.y, h2.w + 11: texpkb h0.w(TRUE), v5, #0 + 13: addh h3.w(TRUE), -h0, h0.x + 14: addh h0.x(TRUE), h0.w, h0 + 15: addh h0.z(TRUE), -h2.w, h0.x + 16: addh h0.x(TRUE), h2.w, h3.w + 17: minh h5.y(TRUE), h0.w, h1.w + 18: nrmh h2.xz(TRUE), h0_n + 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| + 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w + 21: movr r1.zw(TRUE), v4.xxxy + 22: maxh h2.w(TRUE), h0, h1 + 23: fenct TRUE + 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 26: texpkb h0(TRUE), r0, #0 + 28: maxh h5.x(TRUE), h2.w, h5 + 29: minh h5.w(TRUE), h5.y, h4 + 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz + 32: texpkb h2(TRUE), r1, #0 + 34: addh_d2 h2(TRUE), h0, h2 + 35: texpkb h1(TRUE), v4, #0 + 37: maxh h5.y(TRUE), h5.x, h1.w + 38: minh h4.w(TRUE), h1, h5 + 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 41: texpkb h0(TRUE), r0, #0 + 43: addh_m8 h5.z(TRUE), h5.y, -h4.w + 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz + 46: texpkb h3(TRUE), r2, #0 + 48: addh_d2 h0(TRUE), h0, h3 + 49: addh_d2 h3(TRUE), h0, h2 + 50: movh h0(TRUE), h3 + 51: slth h3.x(TRUE), h3.w, h5.w + 52: sgth h3.w(TRUE), h3, h5.x + 53: addx.c0 rc(TRUE), h3.x, h3 + 54: slth.c0 rc(TRUE), h5.z, h5 + 55: movh h0(c0.NE.w), h2 + 56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- + 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; + | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; + | | | + 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; + | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; + | | | + 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; + | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; + | SCB1 | min | 9: MINh h4.w, h2.---y, h2; + | | | + 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; + | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; + | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; + | | | + 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; + | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; + | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; + | | | + 6 | SCT1 | mov | 18: NRMh h2.xz, h0; + | SRB | nrm | 18: NRMh h2.xz, h0; + | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; + | | | + 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; + | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; + | SCB1 | max | 22: MAXh h2.w, h0, h1; + | | | + 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; + | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; + | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; + | SCB1 | min | 29: MINh h5.w, h5.---y, h4; + | | | + 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; + | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; + | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; + | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; + | | | + 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; + | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; + | SCB1 | min | 38: MINh h4.w, h1, h5; + | | | + 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; + | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; + | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; + | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; + | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; + | | | + 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; + | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; + | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; + | | | + 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; + | SCB0/1 | mul | 50: MOVh h0, h3; + | | | + 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; + | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; + | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; + | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; + | | | + 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; + | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; + +Pass SCT TEX SCB + 1: 0% 100% 25% + 2: 0% 100% 25% + 3: 0% 100% 50% + 4: 0% 100% 50% + 5: 50% 0% 25% + 6: 0% 0% 25% + 7: 100% 0% 25% + 8: 0% 100% 50% + 9: 0% 100% 100% + 10: 0% 100% 50% + 11: 0% 100% 75% + 12: 0% 100% 100% + 13: 100% 0% 100% + 14: 50% 0% 50% + 15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 + 1: 0% 0% 100% 100% 0% + 2: 0% 0% 100% 100% 0% + 3: 0% 0% 100% 100% 100% + 4: 0% 0% 100% 100% 100% + 5: 100% 100% 0% 100% 0% + 6: 0% 0% 0% 0% 100% + 7: 100% 100% 0% 0% 100% + 8: 0% 0% 100% 100% 100% + 9: 0% 0% 100% 100% 100% + 10: 0% 0% 100% 100% 100% + 11: 0% 0% 100% 100% 100% + 12: 0% 0% 100% 100% 100% + 13: 100% 100% 0% 100% 100% + 14: 100% 100% 0% 100% 100% + 15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +#pragma option O2 +#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + FxaaFloat2 pos, + FxaaFloat4 fxaaConsolePosPos, + FxaaTex tex, + FxaaTex fxaaConsole360TexExpBiasNegOne, + FxaaTex fxaaConsole360TexExpBiasNegTwo, + FxaaFloat2 fxaaQualityRcpFrame, + FxaaFloat4 fxaaConsoleRcpFrameOpt, + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + FxaaFloat fxaaQualitySubpix, + FxaaFloat fxaaQualityEdgeThreshold, + FxaaFloat fxaaQualityEdgeThresholdMin, + FxaaFloat fxaaConsoleEdgeSharpness, + FxaaFloat fxaaConsoleEdgeThreshold, + FxaaFloat fxaaConsoleEdgeThresholdMin, + FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) + half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaNe = rgbyNe.w + half(1.0/512.0); + #else + half lumaNe = rgbyNe.y + half(1.0/512.0); + #endif +/*--------------------------------------------------------------------------*/ +// (2) + half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaSwNegNe = lumaSw.w - lumaNe; + #else + half lumaSwNegNe = lumaSw.y - lumaNe; + #endif +/*--------------------------------------------------------------------------*/ +// (3) + half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); + half lumaMinNwSw = min(lumaNw.w, lumaSw.w); + #else + half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); + half lumaMinNwSw = min(lumaNw.y, lumaSw.y); + #endif +/*--------------------------------------------------------------------------*/ +// (4) + half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half dirZ = lumaNw.w + lumaSwNegNe; + half dirX = -lumaNw.w + lumaSwNegNe; + #else + half dirZ = lumaNw.y + lumaSwNegNe; + half dirX = -lumaNw.y + lumaSwNegNe; + #endif +/*--------------------------------------------------------------------------*/ +// (5) + half3 dir; + dir.y = 0.0; + #if (FXAA_GREEN_AS_LUMA == 0) + dir.x = lumaSe.w + dirX; + dir.z = -lumaSe.w + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.w); + #else + dir.x = lumaSe.y + dirX; + dir.z = -lumaSe.y + dirZ; + half lumaMinNeSe = min(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (6) + half4 dir1_pos; + dir1_pos.xy = normalize(dir).xz; + half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) + half4 dir2_pos; + dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); + dir1_pos.zw = pos.xy; + dir2_pos.zw = pos.xy; + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxNeSe = max(lumaNe, lumaSe.w); + #else + half lumaMaxNeSe = max(lumaNe, lumaSe.y); + #endif +/*--------------------------------------------------------------------------*/ +// (8) + half4 temp1N; + temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); + half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); + half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) + half4 rgby1; + rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; + rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); + rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) + half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); + #if (FXAA_GREEN_AS_LUMA == 0) + half lumaMaxM = max(lumaMax, rgbyM.w); + half lumaMinM = min(lumaMin, rgbyM.w); + #else + half lumaMaxM = max(lumaMax, rgbyM.y); + half lumaMinM = min(lumaMin, rgbyM.y); + #endif +/*--------------------------------------------------------------------------*/ +// (11) + half4 temp2N; + temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); + half4 rgby2; + rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; + half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) + rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); + rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) + rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) + #if (FXAA_GREEN_AS_LUMA == 0) + bool twoTapLt = rgby2.w < lumaMin; + bool twoTapGt = rgby2.w > lumaMax; + #else + bool twoTapLt = rgby2.y < lumaMin; + bool twoTapGt = rgby2.y > lumaMax; + #endif + bool earlyExit = lumaRangeM < lumaMax; + bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) + if(twoTap) rgby2 = rgby1; + if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ + return rgby2; } +/*==========================================================================*/ +#endif diff --git a/third_party/vulkan/vk_mem_alloc.h b/third_party/vulkan/vk_mem_alloc.h index 71d78b795..cb3ff6070 100644 --- a/third_party/vulkan/vk_mem_alloc.h +++ b/third_party/vulkan/vk_mem_alloc.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. +// Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,701 +23,301 @@ #ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H #define AMD_VULKAN_MEMORY_ALLOCATOR_H +/** \mainpage Vulkan Memory Allocator + +Version 3.0.0-development + +Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved. \n +License: MIT + +API documentation divided into groups: [Modules](modules.html) + +\section main_table_of_contents Table of contents + +- User guide + - \subpage quick_start + - [Project setup](@ref quick_start_project_setup) + - [Initialization](@ref quick_start_initialization) + - [Resource allocation](@ref quick_start_resource_allocation) + - \subpage choosing_memory_type + - [Usage](@ref choosing_memory_type_usage) + - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags) + - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types) + - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools) + - [Dedicated allocations](@ref choosing_memory_type_dedicated_allocations) + - \subpage memory_mapping + - [Mapping functions](@ref memory_mapping_mapping_functions) + - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory) + - [Cache flush and invalidate](@ref memory_mapping_cache_control) + - [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable) + - \subpage staying_within_budget + - [Querying for budget](@ref staying_within_budget_querying_for_budget) + - [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage) + - \subpage resource_aliasing + - \subpage custom_memory_pools + - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex) + - [Linear allocation algorithm](@ref linear_algorithm) + - [Free-at-once](@ref linear_algorithm_free_at_once) + - [Stack](@ref linear_algorithm_stack) + - [Double stack](@ref linear_algorithm_double_stack) + - [Ring buffer](@ref linear_algorithm_ring_buffer) + - [Buddy allocation algorithm](@ref buddy_algorithm) + - \subpage defragmentation + - [Defragmenting CPU memory](@ref defragmentation_cpu) + - [Defragmenting GPU memory](@ref defragmentation_gpu) + - [Additional notes](@ref defragmentation_additional_notes) + - [Writing custom allocation algorithm](@ref defragmentation_custom_algorithm) + - \subpage statistics + - [Numeric statistics](@ref statistics_numeric_statistics) + - [JSON dump](@ref statistics_json_dump) + - \subpage allocation_annotation + - [Allocation user data](@ref allocation_user_data) + - [Allocation names](@ref allocation_names) + - \subpage virtual_allocator + - \subpage debugging_memory_usage + - [Memory initialization](@ref debugging_memory_usage_initialization) + - [Margins](@ref debugging_memory_usage_margins) + - [Corruption detection](@ref debugging_memory_usage_corruption_detection) + - \subpage opengl_interop +- \subpage usage_patterns + - [Common mistakes](@ref usage_patterns_common_mistakes) + - [Simple patterns](@ref usage_patterns_simple) + - [Advanced patterns](@ref usage_patterns_advanced) +- \subpage configuration + - [Pointers to Vulkan functions](@ref config_Vulkan_functions) + - [Custom host memory allocator](@ref custom_memory_allocator) + - [Device memory allocation callbacks](@ref allocation_callbacks) + - [Device heap memory limit](@ref heap_memory_limit) + - \subpage vk_khr_dedicated_allocation + - \subpage enabling_buffer_device_address + - \subpage vk_amd_device_coherent_memory +- \subpage general_considerations + - [Thread safety](@ref general_considerations_thread_safety) + - [Validation layer warnings](@ref general_considerations_validation_layer_warnings) + - [Allocation algorithm](@ref general_considerations_allocation_algorithm) + - [Features not supported](@ref general_considerations_features_not_supported) + +\section main_see_also See also + +- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/) +- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) + +\defgroup group_init Library initialization + +\brief API elements related to the initialization and management of the entire library, especially #VmaAllocator object. + +\defgroup group_alloc Memory allocation + +\brief API elements related to the allocation, deallocation, and management of Vulkan memory, buffers, images. +Most basic ones being: vmaCreateBuffer(), vmaCreateImage(). + +\defgroup group_virtual Virtual allocator + +\brief API elements related to the mechanism of \ref virtual_allocator - using the core allocation algorithm +for user-defined purpose without allocating any real GPU memory. + +\defgroup group_stats Statistics + +\brief API elements that query current status of the allocator, from memory usage, budget, to full dump of the internal state in JSON format. +*/ + + #ifdef __cplusplus extern "C" { #endif -/** \mainpage Vulkan Memory Allocator - -Version 2.0.0-alpha.6 (2017-11-13) - -Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. \n -License: MIT - -Documentation of all members: vk_mem_alloc.h - -Table of contents: - -- User guide - - \subpage quick_start - - \subpage choosing_memory_type - - \subpage memory_mapping - - \subpage custom_memory_pools - - \subpage defragmentation - - \subpage lost_allocations - - \subpage allocation_annotation -- \subpage configuration - - \subpage vk_khr_dedicated_allocation -- \subpage thread_safety - -See also: - -- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) -- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/) - - - - -\page quick_start Quick start - -\section project_setup Project setup - -In your project code: - --# Include "vk_mem_alloc.h" file wherever you want to use the library. --# In exacly one C++ file define following macro before include to build library - implementation. - -\code -#define VMA_IMPLEMENTATION -#include "vk_mem_alloc.h" -\endcode - -\section initialization Initialization - -At program startup: - --# Initialize Vulkan to have `VkPhysicalDevice` and `VkDevice` object. --# Fill VmaAllocatorCreateInfo structure and create `VmaAllocator` object by - calling vmaCreateAllocator(). - -\code -VmaAllocatorCreateInfo allocatorInfo = {}; -allocatorInfo.physicalDevice = physicalDevice; -allocatorInfo.device = device; - -VmaAllocator allocator; -vmaCreateAllocator(&allocatorInfo, &allocator); -\endcode - -\section resource_allocation Resource allocation - -When you want to create a buffer or image: - --# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure. --# Fill VmaAllocationCreateInfo structure. --# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory - already allocated and bound to it. - -\code -VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; -bufferInfo.size = 65536; -bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - -VmaAllocationCreateInfo allocInfo = {}; -allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - -VkBuffer buffer; -VmaAllocation allocation; -vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); -\endcode - -Don't forget to destroy your objects when no longer needed: - -\code -vmaDestroyBuffer(allocator, buffer, allocation); -vmaDestroyAllocator(allocator); -\endcode - - -\page choosing_memory_type Choosing memory type - -Physical devices in Vulkan support various combinations of memory heaps and -types. Help with choosing correct and optimal memory type for your specific -resource is one of the key features of this library. You can use it by filling -appropriate members of VmaAllocationCreateInfo structure, as described below. -You can also combine multiple methods. - --# If you just want to find memory type index that meets your requirements, you - can use function vmaFindMemoryTypeIndex(). --# If you want to allocate a region of device memory without association with any - specific image or buffer, you can use function vmaAllocateMemory(). Usage of - this function is not recommended and usually not needed. --# If you already have a buffer or an image created, you want to allocate memory - for it and then you will bind it yourself, you can use function - vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(). --# If you want to create a buffer or an image, allocate memory for it and bind - them together, all in one call, you can use function vmaCreateBuffer(), - vmaCreateImage(). This is the recommended way to use this library. - -When using 3. or 4., the library internally queries Vulkan for memory types -supported for that buffer or image (function `vkGetBufferMemoryRequirements()`) -and uses only one of these types. - -If no memory type can be found that meets all the requirements, these functions -return `VK_ERROR_FEATURE_NOT_PRESENT`. - -You can leave VmaAllocationCreateInfo structure completely filled with zeros. -It means no requirements are specified for memory type. -It is valid, although not very useful. - -\section choosing_memory_type_usage Usage - -The easiest way to specify memory requirements is to fill member -VmaAllocationCreateInfo::usage using one of the values of enum `VmaMemoryUsage`. -It defines high level, common usage types. - -For example, if you want to create a uniform buffer that will be filled using -transfer only once or infrequently and used for rendering every frame, you can -do it using following code: - -\code -VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; -bufferInfo.size = 65536; -bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - -VmaAllocationCreateInfo allocInfo = {}; -allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - -VkBuffer buffer; -VmaAllocation allocation; -vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); -\endcode - -\section choosing_memory_type_required_preferred_flags Required and preferred flags - -You can specify more detailed requirements by filling members -VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags -with a combination of bits from enum `VkMemoryPropertyFlags`. For example, -if you want to create a buffer that will be persistently mapped on host (so it -must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`, -use following code: - -\code -VmaAllocationCreateInfo allocInfo = {}; -allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; -allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; -allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; - -VkBuffer buffer; -VmaAllocation allocation; -vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); -\endcode - -A memory type is chosen that has all the required flags and as many preferred -flags set as possible. - -If you use VmaAllocationCreateInfo::usage, it is just internally converted to -a set of required and preferred flags. - -\section choosing_memory_type_explicit_memory_types Explicit memory types - -If you inspected memory types available on the physical device and you have -a preference for memory types that you want to use, you can fill member -VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set -means that a memory type with that index is allowed to be used for the -allocation. Special value 0, just like UINT32_MAX, means there are no -restrictions to memory type index. - -Please note that this member is NOT just a memory type index. -Still you can use it to choose just one, specific memory type. -For example, if you already determined that your buffer should be created in -memory type 2, use following code: - -\code -uint32_t memoryTypeIndex = 2; - -VmaAllocationCreateInfo allocInfo = {}; -allocInfo.memoryTypeBits = 1u << memoryTypeIndex; - -VkBuffer buffer; -VmaAllocation allocation; -vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); -\endcode - -\section choosing_memory_type_custom_memory_pools Custom memory pools - -If you allocate from custom memory pool, all the ways of specifying memory -requirements described above are not applicable and the aforementioned members -of VmaAllocationCreateInfo structure are ignored. Memory type is selected -explicitly when creating the pool and then used to make all the allocations from -that pool. For further details, see \ref custom_memory_pools. - - -\page memory_mapping Memory mapping - -\section persistently_mapped_memory Persistently mapped memory - -If you need to map memory on host, it may happen that two allocations are -assigned to the same `VkDeviceMemory` block, so if you map them both at the same -time, it will cause error because mapping single memory block multiple times is -illegal in Vulkan. - -TODO update this... - -It is safer, more convenient and more efficient to use special feature designed -for that: persistently mapped memory. Allocations made with -`VMA_ALLOCATION_CREATE_MAPPED_BIT` flag set in -VmaAllocationCreateInfo::flags are returned from device memory -blocks that stay mapped all the time, so you can just access CPU pointer to it. -VmaAllocationInfo::pMappedData pointer is already offseted to the beginning of -particular allocation. Example: - -\code -VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; -bufCreateInfo.size = 1024; -bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - -VmaAllocationCreateInfo allocCreateInfo = {}; -allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; -allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; - -VkBuffer buf; -VmaAllocation alloc; -VmaAllocationInfo allocInfo; -vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); - -// Buffer is immediately mapped. You can access its memory. -memcpy(allocInfo.pMappedData, myData, 1024); -\endcode - -Memory in Vulkan doesn't need to be unmapped before using it e.g. for transfers, -but if you are not sure whether it's `HOST_COHERENT` (here is surely is because -it's created with `VMA_MEMORY_USAGE_CPU_ONLY`), you should check it. If it's -not, you should call `vkInvalidateMappedMemoryRanges()` before reading and -`vkFlushMappedMemoryRanges()` after writing to mapped memory on CPU. Example: - -\code -VkMemoryPropertyFlags memFlags; -vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags); -if((memFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) -{ - VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; - memRange.memory = allocInfo.deviceMemory; - memRange.offset = allocInfo.offset; - memRange.size = allocInfo.size; - vkFlushMappedMemoryRanges(device, 1, &memRange); -} -\endcode - -\section amd_perf_note Note on performance - -There is a situation that you should be careful about. It happens only if all of -following conditions are met: - --# You use AMD GPU. --# You use the memory type that is both `DEVICE_LOCAL` and `HOST_VISIBLE` - (used when you specify `VMA_MEMORY_USAGE_CPU_TO_GPU`). --# Operating system is Windows 7 or 8.x (Windows 10 is not affected because it - uses WDDM2). - -Then whenever a `VkDeviceMemory` block allocated from this memory type is mapped -for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this -block is migrated by WDDM to system RAM, which degrades performance. It doesn't -matter if that particular memory block is actually used by the command buffer -being submitted. - -To avoid this problem, either make sure to unmap all allocations made from this -memory type before your Submit and Present, or use `VMA_MEMORY_USAGE_GPU_ONLY` -and transfer from a staging buffer in `VMA_MEMORY_USAGE_CPU_ONLY`, which can -safely stay mapped all the time. - -\page custom_memory_pools Custom memory pools - -The library automatically creates and manages default memory pool for each -memory type available on the device. A pool contains a number of -`VkDeviceMemory` blocks. You can create custom pool and allocate memory out of -it. It can be useful if you want to: - -- Keep certain kind of allocations separate from others. -- Enforce particular size of Vulkan memory blocks. -- Limit maximum amount of Vulkan memory allocated for that pool. - -To use custom memory pools: - --# Fill VmaPoolCreateInfo structure. --# Call vmaCreatePool() to obtain `VmaPool` handle. --# When making an allocation, set VmaAllocationCreateInfo::pool to this handle. - You don't need to specify any other parameters of this structure, like usage. - -Example: - -\code -// Create a pool that could have at most 2 blocks, 128 MB each. -VmaPoolCreateInfo poolCreateInfo = {}; -poolCreateInfo.memoryTypeIndex = ... -poolCreateInfo.blockSize = 128ull * 1024 * 1024; -poolCreateInfo.maxBlockCount = 2; - -VmaPool pool; -vmaCreatePool(allocator, &poolCreateInfo, &pool); - -// Allocate a buffer out of it. -VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; -bufCreateInfo.size = 1024; -bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - -VmaAllocationCreateInfo allocCreateInfo = {}; -allocCreateInfo.pool = pool; - -VkBuffer buf; -VmaAllocation alloc; -VmaAllocationInfo allocInfo; -vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); -\endcode - -You have to free all allocations made from this pool before destroying it. - -\code -vmaDestroyBuffer(allocator, buf, alloc); -vmaDestroyPool(allocator, pool); -\endcode - -\page defragmentation Defragmentation - -Interleaved allocations and deallocations of many objects of varying size can -cause fragmentation, which can lead to a situation where the library is unable -to find a continuous range of free memory for a new allocation despite there is -enough free space, just scattered across many small free ranges between existing -allocations. - -To mitigate this problem, you can use vmaDefragment(). Given set of allocations, -this function can move them to compact used memory, ensure more continuous free -space and possibly also free some `VkDeviceMemory`. It can work only on -allocations made from memory type that is `HOST_VISIBLE`. Allocations are -modified to point to the new `VkDeviceMemory` and offset. Data in this memory is -also `memmove`-ed to the new place. However, if you have images or buffers bound -to these allocations (and you certainly do), you need to destroy, recreate, and -bind them to the new place in memory. - -For further details and example code, see documentation of function -vmaDefragment(). - -\page lost_allocations Lost allocations - -If your game oversubscribes video memory, if may work OK in previous-generation -graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically -paged to system RAM. In Vulkan you can't do it because when you run out of -memory, an allocation just fails. If you have more data (e.g. textures) that can -fit into VRAM and you don't need it all at once, you may want to upload them to -GPU on demand and "push out" ones that are not used for a long time to make room -for the new ones, effectively using VRAM (or a cartain memory pool) as a form of -cache. Vulkan Memory Allocator can help you with that by supporting a concept of -"lost allocations". - -To create an allocation that can become lost, include `VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` -flag in VmaAllocationCreateInfo::flags. Before using a buffer or image bound to -such allocation in every new frame, you need to query it if it's not lost. To -check it: call vmaGetAllocationInfo() and see if VmaAllocationInfo::deviceMemory -is not `VK_NULL_HANDLE`. If the allocation is lost, you should not use it or -buffer/image bound to it. You mustn't forget to destroy this allocation and this -buffer/image. - -To create an allocation that can make some other allocations lost to make room -for it, use `VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` flag. You will -usually use both flags `VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` and -`VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` at the same time. - -Warning! Current implementation uses quite naive, brute force algorithm, -which can make allocation calls that use `VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` -flag quite slow. A new, more optimal algorithm and data structure to speed this -up is planned for the future. - -When interleaving creation of new allocations with usage of existing ones, -how do you make sure that an allocation won't become lost while it's used in the -current frame? - -It is ensured because vmaGetAllocationInfo() not only returns allocation -parameters and checks whether it's not lost, but when it's not, it also -atomically marks it as used in the current frame, which makes it impossible to -become lost in that frame. It uses lockless algorithm, so it works fast and -doesn't involve locking any internal mutex. - -What if my allocation may still be in use by the GPU when it's rendering a -previous frame while I already submit new frame on the CPU? - -You can make sure that allocations "touched" by vmaGetAllocationInfo() will not -become lost for a number of additional frames back from the current one by -specifying this number as VmaAllocatorCreateInfo::frameInUseCount (for default -memory pool) and VmaPoolCreateInfo::frameInUseCount (for custom pool). - -How do you inform the library when new frame starts? - -You need to call function vmaSetCurrentFrameIndex(). - -Example code: - -\code -struct MyBuffer -{ - VkBuffer m_Buf = nullptr; - VmaAllocation m_Alloc = nullptr; - - // Called when the buffer is really needed in the current frame. - void EnsureBuffer(); -}; - -void MyBuffer::EnsureBuffer() -{ - // Buffer has been created. - if(m_Buf != VK_NULL_HANDLE) - { - // Check if its allocation is not lost + mark it as used in current frame. - VmaAllocationInfo allocInfo; - vmaGetAllocationInfo(allocator, m_Alloc, &allocInfo); - if(allocInfo.deviceMemory != VK_NULL_HANDLE) - { - // It's all OK - safe to use m_Buf. - return; - } - } - - // Buffer not yet exists or lost - destroy and recreate it. - - vmaDestroyBuffer(allocator, m_Buf, m_Alloc); - - VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - bufCreateInfo.size = 1024; - bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - - VmaAllocationCreateInfo allocCreateInfo = {}; - allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT | - VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT; - - vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &m_Buf, &m_Alloc, nullptr); -} -\endcode - -When using lost allocations, you may see some Vulkan validation layer warnings -about overlapping regions of memory bound to different kinds of buffers and -images. This is still valid as long as you implement proper handling of lost -allocations (like in the example above) and don't use them. - -The library uses following algorithm for allocation, in order: - --# Try to find free range of memory in existing blocks. --# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size. --# If failed, try to create such block with size/2 and size/4. --# If failed and `VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` flag was - specified, try to find space in existing blocks, possilby making some other - allocations lost. --# If failed, try to allocate separate `VkDeviceMemory` for this allocation, - just like when you use `VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT`. --# If failed, choose other memory type that meets the requirements specified in - VmaAllocationCreateInfo and go to point 1. --# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. - - -\page allocation_annotation Allocation names and user data - -\section allocation_user_data Allocation user data - -You can annotate allocations with your own information, e.g. for debugging purposes. -To do that, fill VmaAllocationCreateInfo::pUserData field when creating -an allocation. It's an opaque `void*` pointer. You can use it e.g. as a pointer, -some handle, index, key, ordinal number or any other value that would associate -the allocation with your custom metadata. - -\code -VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; -// Fill bufferInfo... - -MyBufferMetadata* pMetadata = CreateBufferMetadata(); - -VmaAllocationCreateInfo allocCreateInfo = {}; -allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; -allocCreateInfo.pUserData = pMetadata; - -VkBuffer buffer; -VmaAllocation allocation; -vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr); -\endcode - -The pointer may be later retrieved as VmaAllocationInfo::pUserData: - -\code -VmaAllocationInfo allocInfo; -vmaGetAllocationInfo(allocator, allocation, &allocInfo); -MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData; -\endcode - -It can also be changed using function vmaSetAllocationUserData(). - -Values of (non-zero) allocations' `pUserData` are printed in JSON report created by -vmaBuildStatsString(), in hexadecimal form. - -\section allocation_names Allocation names - -There is alternative mode available where `pUserData` pointer is used to point to -a null-terminated string, giving a name to the allocation. To use this mode, -set `VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT` flag in VmaAllocationCreateInfo::flags. -Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to -vmaSetAllocationUserData() must be either null or pointer to a null-terminated string. -The library creates internal copy of the string, so the pointer you pass doesn't need -to be valid for whole lifetime of the allocation. You can free it after the call. - -\code -VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; -// Fill imageInfo... - -std::string imageName = "Texture: "; -imageName += fileName; - -VmaAllocationCreateInfo allocCreateInfo = {}; -allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; -allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT; -allocCreateInfo.pUserData = imageName.c_str(); - -VkImage image; -VmaAllocation allocation; -vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr); -\endcode - -The value of `pUserData` pointer of the allocation will be different than the one -you passed when setting allocation's name - pointing to a buffer managed -internally that holds copy of the string. - -\code -VmaAllocationInfo allocInfo; -vmaGetAllocationInfo(allocator, allocation, &allocInfo); -const char* imageName = (const char*)allocInfo.pUserData; -printf("Image name: %s\n", imageName); -\endcode - -That string is also printed in JSON report created by vmaBuildStatsString(). - -\page configuration Configuration - -Please check "CONFIGURATION SECTION" in the code to find macros that you can define -before each include of this file or change directly in this file to provide -your own implementation of basic facilities like assert, `min()` and `max()` functions, -mutex etc. C++ STL is used by default, but changing these allows you to get rid -of any STL usage if you want, as many game developers tend to do. - -\section config_Vulkan_functions Pointers to Vulkan functions - -The library uses Vulkan functions straight from the `vulkan.h` header by default. -If you want to provide your own pointers to these functions, e.g. fetched using -`vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`: - --# Define `VMA_STATIC_VULKAN_FUNCTIONS 0`. --# Provide valid pointers through VmaAllocatorCreateInfo::pVulkanFunctions. - -\section custom_memory_allocator Custom host memory allocator - -If you use custom allocator for CPU memory rather than default operator `new` -and `delete` from C++, you can make this library using your allocator as well -by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These -functions will be passed to Vulkan, as well as used by the library itself to -make any CPU-side allocations. - -\section allocation_callbacks Device memory allocation callbacks - -The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally. -You can setup callbacks to be informed about these calls, e.g. for the purpose -of gathering some statistics. To do it, fill optional member -VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. - -\section heap_memory_limit Device heap memory limit - -If you want to test how your program behaves with limited amount of Vulkan device -memory available without switching your graphics card to one that really has -smaller VRAM, you can use a feature of this library intended for this purpose. -To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit. - - - -\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation - -VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve -performance on some GPUs. It augments Vulkan API with possibility to query -driver whether it prefers particular buffer or image to have its own, dedicated -allocation (separate `VkDeviceMemory` block) for better efficiency - to be able -to do some internal optimizations. - -The extension is supported by this library. It will be used automatically when -enabled. To enable it: - -1 . When creating Vulkan device, check if following 2 device extensions are -supported (call `vkEnumerateDeviceExtensionProperties()`). -If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`). - -- VK_KHR_get_memory_requirements2 -- VK_KHR_dedicated_allocation - -If you enabled these extensions: - -2 . Use `VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT` flag when creating -your `VmaAllocator` to inform the library that you enabled required extensions -and you want the library to use them. - -\code -allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; - -vmaCreateAllocator(&allocatorInfo, &allocator); -\endcode - -That's all. The extension will be automatically used whenever you create a -buffer using vmaCreateBuffer() or image using vmaCreateImage(). - -When using the extension together with Vulkan Validation Layer, you will receive -warnings like this: - - vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer. - -It is OK, you should just ignore it. It happens because you use function -`vkGetBufferMemoryRequirements2KHR()` instead of standard -`vkGetBufferMemoryRequirements()`, while the validation layer seems to be -unaware of it. - -To learn more about this extension, see: - -- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_dedicated_allocation) -- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5) - - - -\page thread_safety Thread safety - -- The library has no global state, so separate `VmaAllocator` objects can be used - independently. -- By default, all calls to functions that take `VmaAllocator` as first parameter - are safe to call from multiple threads simultaneously because they are - synchronized internally when needed. -- When the allocator is created with `VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT` - flag, calls to functions that take such `VmaAllocator` object must be - synchronized externally. -- Access to a `VmaAllocation` object must be externally synchronized. For example, - you must not call vmaGetAllocationInfo() and vmaMapMemory() from different - threads at the same time if you pass the same `VmaAllocation` object to these - functions. - +#if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS + extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; + extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; + extern PFN_vkAllocateMemory vkAllocateMemory; + extern PFN_vkFreeMemory vkFreeMemory; + extern PFN_vkMapMemory vkMapMemory; + extern PFN_vkUnmapMemory vkUnmapMemory; + extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; + extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; + extern PFN_vkBindBufferMemory vkBindBufferMemory; + extern PFN_vkBindImageMemory vkBindImageMemory; + extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; + extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; + extern PFN_vkCreateBuffer vkCreateBuffer; + extern PFN_vkDestroyBuffer vkDestroyBuffer; + extern PFN_vkCreateImage vkCreateImage; + extern PFN_vkDestroyImage vkDestroyImage; + extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; + #if VMA_VULKAN_VERSION >= 1001000 + extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; + extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; + extern PFN_vkBindBufferMemory2 vkBindBufferMemory2; + extern PFN_vkBindImageMemory2 vkBindImageMemory2; + extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; + #endif // #if VMA_VULKAN_VERSION >= 1001000 +#endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES + +#ifndef VULKAN_H_ + #include +#endif + +#if !defined(VK_VERSION_1_2) + // This one is tricky. Vulkan specification defines this code as available since + // Vulkan 1.0, but doesn't actually define it in Vulkan SDK earlier than 1.2.131. + // See pull request #207. + #define VK_ERROR_UNKNOWN ((VkResult)-13) +#endif + +// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC, +// where AAA = major, BBB = minor, CCC = patch. +// If you want to use version > 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion. +#if !defined(VMA_VULKAN_VERSION) + #if defined(VK_VERSION_1_2) + #define VMA_VULKAN_VERSION 1002000 + #elif defined(VK_VERSION_1_1) + #define VMA_VULKAN_VERSION 1001000 + #else + #define VMA_VULKAN_VERSION 1000000 + #endif +#endif + +#if !defined(VMA_DEDICATED_ALLOCATION) + #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation + #define VMA_DEDICATED_ALLOCATION 1 + #else + #define VMA_DEDICATED_ALLOCATION 0 + #endif +#endif + +#if !defined(VMA_BIND_MEMORY2) + #if VK_KHR_bind_memory2 + #define VMA_BIND_MEMORY2 1 + #else + #define VMA_BIND_MEMORY2 0 + #endif +#endif + +#if !defined(VMA_MEMORY_BUDGET) + #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) + #define VMA_MEMORY_BUDGET 1 + #else + #define VMA_MEMORY_BUDGET 0 + #endif +#endif + +// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers. +#if !defined(VMA_BUFFER_DEVICE_ADDRESS) + #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000 + #define VMA_BUFFER_DEVICE_ADDRESS 1 + #else + #define VMA_BUFFER_DEVICE_ADDRESS 0 + #endif +#endif + +// Defined to 1 when VK_EXT_memory_priority device extension is defined in Vulkan headers. +#if !defined(VMA_MEMORY_PRIORITY) + #if VK_EXT_memory_priority + #define VMA_MEMORY_PRIORITY 1 + #else + #define VMA_MEMORY_PRIORITY 0 + #endif +#endif + +// Defined to 1 when VK_KHR_external_memory device extension is defined in Vulkan headers. +#if !defined(VMA_EXTERNAL_MEMORY) + #if VK_KHR_external_memory + #define VMA_EXTERNAL_MEMORY 1 + #else + #define VMA_EXTERNAL_MEMORY 0 + #endif +#endif + +// Define these macros to decorate all public functions with additional code, +// before and after returned type, appropriately. This may be useful for +// exporting the functions when compiling VMA as a separate library. Example: +// #define VMA_CALL_PRE __declspec(dllexport) +// #define VMA_CALL_POST __cdecl +#ifndef VMA_CALL_PRE + #define VMA_CALL_PRE +#endif +#ifndef VMA_CALL_POST + #define VMA_CALL_POST +#endif + +// Define this macro to decorate pointers with an attribute specifying the +// length of the array they point to if they are not null. +// +// The length may be one of +// - The name of another parameter in the argument list where the pointer is declared +// - The name of another member in the struct where the pointer is declared +// - The name of a member of a struct type, meaning the value of that member in +// the context of the call. For example +// VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount"), +// this means the number of memory heaps available in the device associated +// with the VmaAllocator being dealt with. +#ifndef VMA_LEN_IF_NOT_NULL + #define VMA_LEN_IF_NOT_NULL(len) +#endif + +// The VMA_NULLABLE macro is defined to be _Nullable when compiling with Clang. +// see: https://clang.llvm.org/docs/AttributeReference.html#nullable +#ifndef VMA_NULLABLE + #ifdef __clang__ + #define VMA_NULLABLE _Nullable + #else + #define VMA_NULLABLE + #endif +#endif + +// The VMA_NOT_NULL macro is defined to be _Nonnull when compiling with Clang. +// see: https://clang.llvm.org/docs/AttributeReference.html#nonnull +#ifndef VMA_NOT_NULL + #ifdef __clang__ + #define VMA_NOT_NULL _Nonnull + #else + #define VMA_NOT_NULL + #endif +#endif + +// If non-dispatchable handles are represented as pointers then we can give +// then nullability annotations +#ifndef VMA_NOT_NULL_NON_DISPATCHABLE + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VMA_NOT_NULL_NON_DISPATCHABLE VMA_NOT_NULL + #else + #define VMA_NOT_NULL_NON_DISPATCHABLE + #endif +#endif + +#ifndef VMA_NULLABLE_NON_DISPATCHABLE + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VMA_NULLABLE_NON_DISPATCHABLE VMA_NULLABLE + #else + #define VMA_NULLABLE_NON_DISPATCHABLE + #endif +#endif + +#ifndef VMA_STATS_STRING_ENABLED + #define VMA_STATS_STRING_ENABLED 1 +#endif + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// INTERFACE +// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// Sections for managing code placement in file, only for development purposes e.g. for convenient folding inside an IDE. +#ifndef _VMA_ENUM_DECLARATIONS + +/** +\addtogroup group_init +@{ */ -#include - -VK_DEFINE_HANDLE(VmaAllocator) - -/// Callback function called after successful vkAllocateMemory. -typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)( - VmaAllocator allocator, - uint32_t memoryType, - VkDeviceMemory memory, - VkDeviceSize size); -/// Callback function called before vkFreeMemory. -typedef void (VKAPI_PTR *PFN_vmaFreeDeviceMemoryFunction)( - VmaAllocator allocator, - uint32_t memoryType, - VkDeviceMemory memory, - VkDeviceSize size); - -/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`. - -Provided for informative purpose, e.g. to gather statistics about number of -allocations or total amount of memory allocated in Vulkan. - -Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. -*/ -typedef struct VmaDeviceMemoryCallbacks { - /// Optional, can be null. - PFN_vmaAllocateDeviceMemoryFunction pfnAllocate; - /// Optional, can be null. - PFN_vmaFreeDeviceMemoryFunction pfnFree; -} VmaDeviceMemoryCallbacks; - -/// Flags for created VmaAllocator. -typedef enum VmaAllocatorCreateFlagBits { +/// Flags for created #VmaAllocator. +typedef enum VmaAllocatorCreateFlagBits +{ /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you. Using this flag may increase performance because internal mutexes are not used. @@ -725,9 +325,12 @@ typedef enum VmaAllocatorCreateFlagBits { VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, /** \brief Enables usage of VK_KHR_dedicated_allocation extension. - Using this extenion will automatically allocate dedicated blocks of memory for + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + + Using this extension will automatically allocate dedicated blocks of memory for some buffers and images instead of suballocating place for them out of bigger - memory blocks (as if you explicitly used VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT + memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag) when it is recommended by the driver. It may improve performance on some GPUs. @@ -736,81 +339,643 @@ typedef enum VmaAllocatorCreateFlagBits { VmaAllocatorCreateInfo::device, and you want them to be used internally by this library: - - VK_KHR_get_memory_requirements2 - - VK_KHR_dedicated_allocation + - VK_KHR_get_memory_requirements2 (device extension) + - VK_KHR_dedicated_allocation (device extension) -When this flag is set, you can experience following warnings reported by Vulkan -validation layer. You can ignore them. + When this flag is set, you can experience following warnings reported by Vulkan + validation layer. You can ignore them. -> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. + > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. */ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002, + /** + Enables usage of VK_KHR_bind_memory2 extension. + + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library. + + The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`, + which allow to pass a chain of `pNext` structures while binding. + This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2(). + */ + VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004, + /** + Enables usage of VK_EXT_memory_budget extension. + + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library, along with another instance extension + VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted). + + The extension provides query for current memory usage and budget, which will probably + be more accurate than an estimation used by the library otherwise. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008, + /** + Enables usage of VK_AMD_device_coherent_memory extension. + + You may set this flag only if you: + + - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device, + - want it to be used internally by this library. + + The extension and accompanying device feature provide access to memory types with + `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags. + They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR. + + When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. + To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type, + returning `VK_ERROR_FEATURE_NOT_PRESENT`. + */ + VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010, + /** + Enables usage of "buffer device address" feature, which allows you to use function + `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader. + + You may set this flag only if you: + + 1. (For Vulkan version < 1.2) Found as available and enabled device extension + VK_KHR_buffer_device_address. + This extension is promoted to core Vulkan 1.2. + 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`. + + When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA. + The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to + allocated memory blocks wherever it might be needed. + + For more information, see documentation chapter \ref enabling_buffer_device_address. + */ + VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020, + /** + Enables usage of VK_EXT_memory_priority extension in the library. + + You may set this flag only if you found available and enabled this device extension, + along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + + When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority + are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored. + + A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + Larger values are higher priority. The granularity of the priorities is implementation-dependent. + It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`. + The value to be used for default priority is 0.5. + For more details, see the documentation of the VK_EXT_memory_priority extension. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 0x00000040, VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VmaAllocatorCreateFlagBits; typedef VkFlags VmaAllocatorCreateFlags; +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/// \brief Intended usage of the allocated memory. +typedef enum VmaMemoryUsage +{ + /** No intended memory usage specified. + Use other members of VmaAllocationCreateInfo to specify your requirements. + */ + VMA_MEMORY_USAGE_UNKNOWN = 0, + /** Memory will be used on device only, so fast access from the device is preferred. + It usually means device-local GPU (video) memory. + No need to be mappable on host. + It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`. + + Usage: + + - Resources written and read by device, e.g. images used as attachments. + - Resources transferred from host once (immutable) or infrequently and read by + device multiple times, e.g. textures to be sampled, vertex buffers, uniform + (constant) buffers, and majority of other types of resources used on GPU. + + Allocation may still end up in `HOST_VISIBLE` memory on some implementations. + In such case, you are free to map it. + You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type. + */ + VMA_MEMORY_USAGE_GPU_ONLY = 1, + /** Memory will be mappable on host. + It usually means CPU (system) memory. + Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`. + CPU access is typically uncached. Writes may be write-combined. + Resources created in this pool may still be accessible to the device, but access to them can be slow. + It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`. + + Usage: Staging copy of resources used as transfer source. + */ + VMA_MEMORY_USAGE_CPU_ONLY = 2, + /** + Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU. + CPU access is typically uncached. Writes may be write-combined. + + Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call. + */ + VMA_MEMORY_USAGE_CPU_TO_GPU = 3, + /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached. + It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`. + + Usage: + + - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping. + - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection. + */ + VMA_MEMORY_USAGE_GPU_TO_CPU = 4, + /** CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`. + + Usage: Staging copy of resources moved from GPU memory to CPU memory as part + of custom paging/residency mechanism, to be moved back to GPU memory when needed. + */ + VMA_MEMORY_USAGE_CPU_COPY = 5, + /** Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`. + Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. + + Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. + + Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + */ + VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, + + VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF +} VmaMemoryUsage; + +/// Flags to be passed as VmaAllocationCreateInfo::flags. +typedef enum VmaAllocationCreateFlagBits +{ + /** \brief Set this flag if the allocation should have its own memory block. + + Use it for special, big resources, like fullscreen images used as attachments. + */ + VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001, + + /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block. + + If new allocation cannot be placed in any of the existing blocks, allocation + fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error. + + You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and + #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense. + + If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */ + VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002, + /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. + + Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData. + + It is valid to use this flag for allocation made from memory type that is not + `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is + useful if you need an allocation that is efficient to use on GPU + (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that + support it (e.g. Intel GPU). + */ + VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004, + /// \deprecated Removed. Do not use. + VMA_ALLOCATION_CREATE_RESERVED_1_BIT = 0x00000008, + /// \deprecated Removed. Do not use. + VMA_ALLOCATION_CREATE_RESERVED_2_BIT = 0x00000010, + /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a + null-terminated string. Instead of copying pointer value, a local copy of the + string is made and stored in allocation's `pUserData`. The string is automatically + freed together with the allocation. It is also used in vmaBuildStatsString(). + */ + VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, + /** Allocation will be created from upper stack in a double stack pool. + + This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040, + /** Create both buffer/image and allocation, but don't bind them together. + It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. + The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage(). + Otherwise it is ignored. + */ + VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080, + /** Create allocation only if additional device memory required for it, if any, won't exceed + memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + */ + VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100, + /** \brief Set this flag if the allocated memory will have aliasing resources. + * + Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. + Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors. + */ + VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200, + + /** Allocation strategy that chooses smallest possible free range for the + allocation. + */ + VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = 0x00010000, + /** Allocation strategy that chooses biggest possible free range for the + allocation. + */ + VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT = 0x00020000, + /** Allocation strategy that chooses first suitable free range for the + allocation. + + "First" doesn't necessarily means the one with smallest offset in memory, + but rather the one that is easiest and fastest to find. + */ + VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = 0x00040000, + + /** Allocation strategy that tries to minimize memory usage. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT, + /** Allocation strategy that tries to minimize allocation time. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT, + /** Allocation strategy that tries to minimize memory fragmentation. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT, + + /** A bit mask to extract only `STRATEGY` bits from entire set of flags. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MASK = + VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT | + VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT | + VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT, + + VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaAllocationCreateFlagBits; +typedef VkFlags VmaAllocationCreateFlags; + +/// Flags to be passed as VmaPoolCreateInfo::flags. +typedef enum VmaPoolCreateFlagBits +{ + /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. + + This is an optional optimization flag. + + If you always allocate using vmaCreateBuffer(), vmaCreateImage(), + vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator + knows exact type of your allocations so it can handle Buffer-Image Granularity + in the optimal way. + + If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(), + exact type of such allocations is not known, so allocator must be conservative + in handling Buffer-Image Granularity, which can lead to suboptimal allocation + (wasted memory). In that case, if you can make sure you always allocate only + buffers and linear images or only optimal images out of this pool, use this flag + to make allocator disregard Buffer-Image Granularity and so make allocations + faster and more optimal. + */ + VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, + + /** \brief Enables alternative, linear allocation algorithm in this pool. + + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. + + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + + When using this flag, you must specify VmaPoolCreateInfo::maxBlockCount == 1 (or 0 for default). + */ + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004, + + /** \brief Enables alternative, buddy allocation algorithm in this pool. + + It operates on a tree of blocks, each having size that is a power of two and + a half of its parent's size. Comparing to default algorithm, this one provides + faster allocation and deallocation and decreased external fragmentation, + at the expense of more memory wasted (internal fragmentation). + For details, see documentation chapter \ref buddy_algorithm. + */ + VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x00000008, + + /** \brief Enables alternative, Two-Level Segregated Fit (TLSF) allocation algorithm in this pool. + + This algorithm is based on 2-level lists dividing address space into smaller + chunks. The first level is aligned to power of two which serves as buckets for requested + memory to fall into, and the second level is lineary subdivided into lists of free memory. + This algorithm aims to achieve bounded response time even in the worst case scenario. + Allocation time can be sometimes slightly longer than compared to other algorithms + but in return the application can avoid stalls in case of fragmentation, giving + predictable results, suitable for real-time use cases. + */ + VMA_POOL_CREATE_TLSF_ALGORITHM_BIT = 0x00000010, + + /** Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_POOL_CREATE_ALGORITHM_MASK = + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT | + VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT | + VMA_POOL_CREATE_TLSF_ALGORITHM_BIT, + + VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaPoolCreateFlagBits; +/// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits. +typedef VkFlags VmaPoolCreateFlags; + +/// Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use. +typedef enum VmaDefragmentationFlagBits +{ + VMA_DEFRAGMENTATION_FLAG_INCREMENTAL = 0x1, + VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaDefragmentationFlagBits; +typedef VkFlags VmaDefragmentationFlags; + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. +typedef enum VmaVirtualBlockCreateFlagBits +{ + /** \brief Enables alternative, linear allocation algorithm in this virtual block. + + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. + + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + */ + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001, + + /** \brief Enables alternative, buddy allocation algorithm in this virtual block. + + It operates on a tree of blocks, each having size that is a power of two and + a half of its parent's size. Comparing to default algorithm, this one provides + faster allocation and deallocation and decreased external fragmentation, + at the expense of more memory wasted (internal fragmentation). + For details, see documentation chapter \ref buddy_algorithm. + */ + VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT = 0x00000002, + + /** \brief Enables alternative, TLSF allocation algorithm in virtual block. + + This algorithm is based on 2-level lists dividing address space into smaller + chunks. The first level is aligned to power of two which serves as buckets for requested + memory to fall into, and the second level is lineary subdivided into lists of free memory. + This algorithm aims to achieve bounded response time even in the worst case scenario. + Allocation time can be sometimes slightly longer than compared to other algorithms + but in return the application can avoid stalls in case of fragmentation, giving + predictable results, suitable for real-time use cases. + */ + VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT = 0x00000004, + + /** \brief Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT | + VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT | + VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT, + + VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaVirtualBlockCreateFlagBits; +/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits. +typedef VkFlags VmaVirtualBlockCreateFlags; + +/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. +typedef enum VmaVirtualAllocationCreateFlagBits +{ + /** \brief Allocation will be created from upper stack in a double stack pool. + + This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT, + /** \brief Allocation strategy that tries to minimize memory usage. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, + /** \brief Allocation strategy that tries to minimize allocation time. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, + /** \brief Allocation strategy that tries to minimize memory fragmentation. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT, + /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags. + + These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK, + + VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaVirtualAllocationCreateFlagBits; +/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits. +typedef VkFlags VmaVirtualAllocationCreateFlags; + +/** @} */ + +#endif // _VMA_ENUM_DECLARATIONS + +#ifndef _VMA_DATA_TYPES_DECLARATIONS + +/** +\addtogroup group_init +@{ */ + +/** \struct VmaAllocator +\brief Represents main object of this library initialized. + +Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it. +Call function vmaDestroyAllocator() to destroy it. + +It is recommended to create just one object of this type per `VkDevice` object, +right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed. +*/ +VK_DEFINE_HANDLE(VmaAllocator) + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** \struct VmaPool +\brief Represents custom memory pool + +Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it. +Call function vmaDestroyPool() to destroy it. + +For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools). +*/ +VK_DEFINE_HANDLE(VmaPool) + +/** \struct VmaAllocation +\brief Represents single memory allocation. + +It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type +plus unique offset. + +There are multiple ways to create such object. +You need to fill structure VmaAllocationCreateInfo. +For more information see [Choosing memory type](@ref choosing_memory_type). + +Although the library provides convenience functions that create Vulkan buffer or image, +allocate memory for it and bind them together, +binding of the allocation to a buffer or an image is out of scope of the allocation itself. +Allocation object can exist without buffer/image bound, +binding can be done manually by the user, and destruction of it can be done +independently of destruction of the allocation. + +The object also remembers its size and some other information. +To retrieve this information, use function vmaGetAllocationInfo() and inspect +returned structure VmaAllocationInfo. +*/ +VK_DEFINE_HANDLE(VmaAllocation) + +/** \struct VmaDefragmentationContext +\brief Represents Opaque object that represents started defragmentation process. + +Fill structure #VmaDefragmentationInfo2 and call function vmaDefragmentationBegin() to create it. +Call function vmaDefragmentationEnd() to destroy it. +*/ +VK_DEFINE_HANDLE(VmaDefragmentationContext) + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \struct VmaVirtualAllocation +\brief Represents single memory allocation done inside VmaVirtualBlock. + +Use it as a unique identifier to virtual allocation within the single block. +*/ +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation); + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \struct VmaVirtualBlock +\brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory. + +Fill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it. +For more information, see documentation chapter \ref virtual_allocator. + +This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally. +*/ +VK_DEFINE_HANDLE(VmaVirtualBlock) + +/** @} */ + +/** +\addtogroup group_init +@{ +*/ + +/// Callback function called after successful vkAllocateMemory. +typedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); + +/// Callback function called before vkFreeMemory. +typedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); + +/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`. + +Provided for informative purpose, e.g. to gather statistics about number of +allocations or total amount of memory allocated in Vulkan. + +Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. +*/ +typedef struct VmaDeviceMemoryCallbacks +{ + /// Optional, can be null. + PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate; + /// Optional, can be null. + PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree; + /// Optional, can be null. + void* VMA_NULLABLE pUserData; +} VmaDeviceMemoryCallbacks; + /** \brief Pointers to some Vulkan functions - a subset used by the library. Used in VmaAllocatorCreateInfo::pVulkanFunctions. */ -typedef struct VmaVulkanFunctions { - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; - PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; - PFN_vkAllocateMemory vkAllocateMemory; - PFN_vkFreeMemory vkFreeMemory; - PFN_vkMapMemory vkMapMemory; - PFN_vkUnmapMemory vkUnmapMemory; - PFN_vkBindBufferMemory vkBindBufferMemory; - PFN_vkBindImageMemory vkBindImageMemory; - PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; - PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; - PFN_vkCreateBuffer vkCreateBuffer; - PFN_vkDestroyBuffer vkDestroyBuffer; - PFN_vkCreateImage vkCreateImage; - PFN_vkDestroyImage vkDestroyImage; - PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; - PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; +typedef struct VmaVulkanFunctions +{ + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr; + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr; + PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties; + PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory; + PFN_vkFreeMemory VMA_NULLABLE vkFreeMemory; + PFN_vkMapMemory VMA_NULLABLE vkMapMemory; + PFN_vkUnmapMemory VMA_NULLABLE vkUnmapMemory; + PFN_vkFlushMappedMemoryRanges VMA_NULLABLE vkFlushMappedMemoryRanges; + PFN_vkInvalidateMappedMemoryRanges VMA_NULLABLE vkInvalidateMappedMemoryRanges; + PFN_vkBindBufferMemory VMA_NULLABLE vkBindBufferMemory; + PFN_vkBindImageMemory VMA_NULLABLE vkBindImageMemory; + PFN_vkGetBufferMemoryRequirements VMA_NULLABLE vkGetBufferMemoryRequirements; + PFN_vkGetImageMemoryRequirements VMA_NULLABLE vkGetImageMemoryRequirements; + PFN_vkCreateBuffer VMA_NULLABLE vkCreateBuffer; + PFN_vkDestroyBuffer VMA_NULLABLE vkDestroyBuffer; + PFN_vkCreateImage VMA_NULLABLE vkCreateImage; + PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage; + PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer; +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + /// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR; + /// Fetch "vkGetImageMemoryRequirements 2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR; +#endif +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + /// Fetch "vkBindBufferMemory2" on Vulkan >= 1.1, fetch "vkBindBufferMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR; + /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; +#endif +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; +#endif } VmaVulkanFunctions; /// Description of a Allocator to be created. typedef struct VmaAllocatorCreateInfo { - /// Flags for created allocator. Use VmaAllocatorCreateFlagBits enum. + /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum. VmaAllocatorCreateFlags flags; /// Vulkan physical device. /** It must be valid throughout whole lifetime of created allocator. */ - VkPhysicalDevice physicalDevice; + VkPhysicalDevice VMA_NOT_NULL physicalDevice; /// Vulkan device. /** It must be valid throughout whole lifetime of created allocator. */ - VkDevice device; - /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps. - /** Set to 0 to use default, which is currently 256 MB. */ + VkDevice VMA_NOT_NULL device; + /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional. + /** Set to 0 to use default, which is currently 256 MiB. */ VkDeviceSize preferredLargeHeapBlockSize; - /// Preferred size of a single `VkDeviceMemory` block to be allocated from small heaps <= 512 MB. - /** Set to 0 to use default, which is currently 64 MB. */ - VkDeviceSize preferredSmallHeapBlockSize; - /// Custom CPU memory allocation callbacks. + /// Custom CPU memory allocation callbacks. Optional. /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */ - const VkAllocationCallbacks* pAllocationCallbacks; - /// Informative callbacks for vkAllocateMemory, vkFreeMemory. + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; + /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional. /** Optional, can be null. */ - const VmaDeviceMemoryCallbacks* pDeviceMemoryCallbacks; - /** \brief Maximum number of additional frames that are in use at the same time as current frame. - - This value is used only when you make allocations with - VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become - lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount. - - For example, if you double-buffer your command buffers, so resources used for - rendering in previous frame may still be in use by the GPU at the moment you - allocate resources needed for the current frame, set this value to 1. - - If you want to allow any allocations other than used in the current frame to - become lost, set this value to 0. - */ - uint32_t frameInUseCount; - /** \brief Either NULL or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. + const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks; + /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on @@ -831,78 +996,77 @@ typedef struct VmaAllocatorCreateInfo smaller amount of memory, because graphics driver doesn't necessary fail new allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is exceeded. It may return success and just silently migrate some device memory - blocks to system RAM. + blocks to system RAM. This driver behavior can also be controlled using + VK_AMD_memory_overallocation_behavior extension. */ - const VkDeviceSize* pHeapSizeLimit; - /** \brief Pointers to Vulkan functions. Can be null if you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1`. + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pHeapSizeLimit; - If you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1` in configuration section, - you can pass null as this member, because the library will fetch pointers to - Vulkan functions internally in a static way, like: + /** \brief Pointers to Vulkan functions. Can be null. - vulkanFunctions.vkAllocateMemory = &vkAllocateMemory; - - Fill this member if you want to provide your own pointers to Vulkan functions, - e.g. fetched using `vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`. + For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions). */ - const VmaVulkanFunctions* pVulkanFunctions; + const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions; + /** \brief Handle to Vulkan instance object. + + Starting from version 3.0.0 this member is no longer optional, it must be set! + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Optional. The highest version of Vulkan that the application is designed to use. + + It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`. + The patch version number specified is ignored. Only the major and minor versions are considered. + It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`. + Only versions 1.0, 1.1, 1.2 are supported by the current implementation. + Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`. + */ + uint32_t vulkanApiVersion; +#if VMA_EXTERNAL_MEMORY + /** \brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type. + + If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount` + elements, defining external memory handle types of particular Vulkan memory type, + to be passed using `VkExportMemoryAllocateInfoKHR`. + + Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type. + This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL. + */ + const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryTypeCount") pTypeExternalMemoryHandleTypes; +#endif // #if VMA_EXTERNAL_MEMORY } VmaAllocatorCreateInfo; -/// Creates Allocator object. -VkResult vmaCreateAllocator( - const VmaAllocatorCreateInfo* pCreateInfo, - VmaAllocator* pAllocator); +/// Information about existing #VmaAllocator object. +typedef struct VmaAllocatorInfo +{ + /** \brief Handle to Vulkan instance object. -/// Destroys allocator object. -void vmaDestroyAllocator( - VmaAllocator allocator); + This is the same value as has been passed through VmaAllocatorCreateInfo::instance. + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Handle to Vulkan physical device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice. + */ + VkPhysicalDevice VMA_NOT_NULL physicalDevice; + /** \brief Handle to Vulkan device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::device. + */ + VkDevice VMA_NOT_NULL device; +} VmaAllocatorInfo; + +/** @} */ /** -PhysicalDeviceProperties are fetched from physicalDevice by the allocator. -You can access it here, without fetching it again on your own. +\addtogroup group_stats +@{ */ -void vmaGetPhysicalDeviceProperties( - VmaAllocator allocator, - const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties); -/** -PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. -You can access it here, without fetching it again on your own. -*/ -void vmaGetMemoryProperties( - VmaAllocator allocator, - const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties); - -/** -\brief Given Memory Type Index, returns Property Flags of this memory type. - -This is just a convenience function. Same information can be obtained using -vmaGetMemoryProperties(). -*/ -void vmaGetMemoryTypeProperties( - VmaAllocator allocator, - uint32_t memoryTypeIndex, - VkMemoryPropertyFlags* pFlags); - -/** \brief Sets index of the current frame. - -This function must be used if you make allocations with -`VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` and -`VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` flags to inform the allocator -when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot -become lost in the current frame. -*/ -void vmaSetCurrentFrameIndex( - VmaAllocator allocator, - uint32_t frameIndex); - -/** \brief Calculated statistics of memory usage in entire allocator. -*/ +/// Calculated statistics of memory usage in entire allocator. typedef struct VmaStatInfo { /// Number of `VkDeviceMemory` Vulkan memory blocks allocated. uint32_t blockCount; - /// Number of `VmaAllocation` allocation objects allocated. + /// Number of #VmaAllocation allocation objects allocated. uint32_t allocationCount; /// Number of free ranges of memory between allocations. uint32_t unusedRangeCount; @@ -922,160 +1086,68 @@ typedef struct VmaStats VmaStatInfo total; } VmaStats; -/// Retrieves statistics from current state of the Allocator. -void vmaCalculateStats( - VmaAllocator allocator, - VmaStats* pStats); - -#define VMA_STATS_STRING_ENABLED 1 - -#if VMA_STATS_STRING_ENABLED - -/// Builds and returns statistics as string in JSON format. -/** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function. -*/ -void vmaBuildStatsString( - VmaAllocator allocator, - char** ppStatsString, - VkBool32 detailedMap); - -void vmaFreeStatsString( - VmaAllocator allocator, - char* pStatsString); - -#endif // #if VMA_STATS_STRING_ENABLED - -VK_DEFINE_HANDLE(VmaPool) - -typedef enum VmaMemoryUsage +/// Statistics of current memory usage and available budget, in bytes, for specific memory heap. +typedef struct VmaBudget { - /** No intended memory usage specified. - Use other members of VmaAllocationCreateInfo to specify your requirements. + /** \brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes. */ - VMA_MEMORY_USAGE_UNKNOWN = 0, - /** Memory will be used on device only, so faster access from the device is preferred. - It usually means device-local GPU memory. - No need to be mappable on host. - Good e.g. for images to be used as attachments, images containing textures to be sampled, - buffers used as vertex buffer, index buffer, uniform buffer and majority of - other types of resources used by device. - You can still do transfers from/to such resource to/from host memory. + VkDeviceSize blockBytes; - The allocation may still end up in `HOST_VISIBLE` memory on some implementations. - In such case, you are free to map it. - You can also use `VMA_ALLOCATION_CREATE_MAPPED_BIT` with this usage type. + /** \brief Sum size of all allocations created in particular heap, in bytes. + + Usually less or equal than `blockBytes`. + Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused - + available for new allocations or wasted due to fragmentation. */ - VMA_MEMORY_USAGE_GPU_ONLY = 1, - /** Memory will be mapped and used on host. - It usually means CPU system memory. - Could be used for transfer to/from device. - Good e.g. for "staging" copy of buffers and images, used as transfer source or destination. - Resources created in this pool may still be accessible to the device, but access to them can be slower. - - Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`. + VkDeviceSize allocationBytes; + + /** \brief Estimated current memory usage of the program, in bytes. + + Fetched from system using `VK_EXT_memory_budget` extension if enabled. + + It might be different than `blockBytes` (usually higher) due to additional implicit objects + also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or + `VkDeviceMemory` blocks allocated outside of this library, if any. */ - VMA_MEMORY_USAGE_CPU_ONLY = 2, - /** Memory will be used for frequent (dynamic) updates from host and reads on device (upload). - Good e.g. for vertex buffers or uniform buffers updated every frame. + VkDeviceSize usage; - Guarantees to be `HOST_VISIBLE`. + /** \brief Estimated amount of memory available to the program, in bytes. + + Fetched from system using `VK_EXT_memory_budget` extension if enabled. + + It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors + external to the program, like other programs also consuming system resources. + Difference `budget - usage` is the amount of additional memory that can probably + be allocated without problems. Exceeding the budget may result in various problems. */ - VMA_MEMORY_USAGE_CPU_TO_GPU = 3, - /** Memory will be used for frequent writing on device and readback on host (download). + VkDeviceSize budget; +} VmaBudget; - Guarantees to be `HOST_VISIBLE`. - */ - VMA_MEMORY_USAGE_GPU_TO_CPU = 4, - VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF -} VmaMemoryUsage; +/** @} */ -/// Flags to be passed as VmaAllocationCreateInfo::flags. -typedef enum VmaAllocationCreateFlagBits { - /** \brief Set this flag if the allocation should have its own memory block. - - Use it for special, big resources, like fullscreen images used as attachments. - - This flag must also be used for host visible resources that you want to map - simultaneously because otherwise they might end up as regions of the same - `VkDeviceMemory`, while mapping same `VkDeviceMemory` multiple times - simultaneously is illegal. - - You should not use this flag if VmaAllocationCreateInfo::pool is not null. - */ - VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001, - - /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block. - - If new allocation cannot be placed in any of the existing blocks, allocation - fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error. - - You should not use `VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT` and - `VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT` at the same time. It makes no sense. - - If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */ - VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002, - /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. - - Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData. - - Is it valid to use this flag for allocation made from memory type that is not - `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is - useful if you need an allocation that is efficient to use on GPU - (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that - support it (e.g. Intel GPU). - - You should not use this flag together with `VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT`. - */ - VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004, - /** Allocation created with this flag can become lost as a result of another - allocation with `VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT` flag, so you - must check it before use. - - To check if allocation is not lost, call vmaGetAllocationInfo() and check if - VmaAllocationInfo::deviceMemory is not `VK_NULL_HANDLE`. - - For details about supporting lost allocations, see Lost Allocations - chapter of User Guide on Main Page. - - You should not use this flag together with `VMA_ALLOCATION_CREATE_MAPPED_BIT`. - */ - VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT = 0x00000008, - /** While creating allocation using this flag, other allocations that were - created with flag `VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` can become lost. - - For details about supporting lost allocations, see Lost Allocations - chapter of User Guide on Main Page. - */ - VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT = 0x00000010, - /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a - null-terminated string. Instead of copying pointer value, a local copy of the - string is made and stored in allocation's pUserData. The string is automatically - freed together with the allocation. It is also used in vmaBuildStatsString(). - */ - VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, - - VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaAllocationCreateFlagBits; -typedef VkFlags VmaAllocationCreateFlags; +/** +\addtogroup group_alloc +@{ +*/ typedef struct VmaAllocationCreateInfo { - /// Use VmaAllocationCreateFlagBits enum. + /// Use #VmaAllocationCreateFlagBits enum. VmaAllocationCreateFlags flags; /** \brief Intended usage of memory. - - You can leave `VMA_MEMORY_USAGE_UNKNOWN` if you specify memory requirements in other way. \n + + You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n If `pool` is not null, this member is ignored. */ VmaMemoryUsage usage; /** \brief Flags that must be set in a Memory Type chosen for an allocation. - + Leave 0 if you specify memory requirements in other way. \n If `pool` is not null, this member is ignored.*/ VkMemoryPropertyFlags requiredFlags; /** \brief Flags that preferably should be set in a memory type chosen for an allocation. - - Set to 0 if no additional flags are prefered. \n + + Set to 0 if no additional flags are preferred. \n If `pool` is not null, this member is ignored. */ VkMemoryPropertyFlags preferredFlags; /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. @@ -1091,17 +1163,468 @@ typedef struct VmaAllocationCreateInfo Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. */ - VmaPool pool; - /** \brief Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). - - If `VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT` is used, it must be either + VmaPool VMA_NULLABLE pool; + /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). + + If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either null or pointer to a null-terminated string. The string will be then copied to internal buffer, so it doesn't need to be valid after allocation call. */ - void* pUserData; + void* VMA_NULLABLE pUserData; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object + and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + Otherwise, it has the priority of a memory block where it is placed and this variable is ignored. + */ + float priority; } VmaAllocationCreateInfo; +/// Describes parameter of created #VmaPool. +typedef struct VmaPoolCreateInfo +{ + /** \brief Vulkan memory type index to allocate this pool from. + */ + uint32_t memoryTypeIndex; + /** \brief Use combination of #VmaPoolCreateFlagBits. + */ + VmaPoolCreateFlags flags; + /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional. + + Specify nonzero to set explicit, constant size of memory blocks used by this + pool. + + Leave 0 to use default and let the library manage block sizes automatically. + Sizes of particular blocks may vary. + In this case, the pool will also support dedicated allocations. + */ + VkDeviceSize blockSize; + /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty. + + Set to 0 to have no preallocated blocks and allow the pool be completely empty. + */ + size_t minBlockCount; + /** \brief Maximum number of blocks that can be allocated in this pool. Optional. + + Set to 0 to use default, which is `SIZE_MAX`, which means no limit. + + Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated + throughout whole lifetime of this pool. + */ + size_t maxBlockCount; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations. + + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object. + Otherwise, this variable is ignored. + */ + float priority; + /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0. + + Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two. + It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough, + e.g. when doing interop with OpenGL. + */ + VkDeviceSize minAllocationAlignment; + /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional. + + Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`. + It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`. + Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool. + + Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`, + can be attached automatically by this library when using other, more convenient of its features. + */ + void* VMA_NULLABLE pMemoryAllocateNext; +} VmaPoolCreateInfo; + +/** @} */ + /** +\addtogroup group_stats +@{ +*/ + +/// Describes parameter of existing #VmaPool. +typedef struct VmaPoolStats +{ + /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes. + */ + VkDeviceSize size; + /** \brief Total number of bytes in the pool not used by any #VmaAllocation. + */ + VkDeviceSize unusedSize; + /** \brief Number of #VmaAllocation objects created from this pool that were not destroyed. + */ + size_t allocationCount; + /** \brief Number of continuous memory ranges in the pool not used by any #VmaAllocation. + */ + size_t unusedRangeCount; + /** \brief Number of `VkDeviceMemory` blocks allocated for this pool. + */ + size_t blockCount; +} VmaPoolStats; + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/// Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo(). +typedef struct VmaAllocationInfo +{ + /** \brief Memory type index that this allocation was allocated from. + + It never changes. + */ + uint32_t memoryType; + /** \brief Handle to Vulkan memory object. + + Same memory object can be shared by multiple allocations. + + It can change after call to vmaDefragment() if this allocation is passed to the function. + */ + VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory; + /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation. + + You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function + vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image, + not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation + and apply this offset automatically. + + It can change after call to vmaDefragment() if this allocation is passed to the function. + */ + VkDeviceSize offset; + /** \brief Size of this allocation, in bytes. + + It never changes. + + \note Allocation size returned in this variable may be greater than the size + requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the + allocation is accessible for operations on memory e.g. using a pointer after + mapping with vmaMapMemory(), but operations on the resource e.g. using + `vkCmdCopyBuffer` must be limited to the size of the resource. + */ + VkDeviceSize size; + /** \brief Pointer to the beginning of this allocation as mapped data. + + If the allocation hasn't been mapped using vmaMapMemory() and hasn't been + created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null. + + It can change after call to vmaMapMemory(), vmaUnmapMemory(). + It can also change after call to vmaDefragment() if this allocation is passed to the function. + */ + void* VMA_NULLABLE pMappedData; + /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). + + It can change after call to vmaSetAllocationUserData() for this allocation. + */ + void* VMA_NULLABLE pUserData; +} VmaAllocationInfo; + +/** \brief Parameters for defragmentation. + +To be used with function vmaDefragmentationBegin(). +*/ +typedef struct VmaDefragmentationInfo2 +{ + /** \brief Reserved for future use. Should be 0. + */ + VmaDefragmentationFlags flags; + /** \brief Number of allocations in `pAllocations` array. + */ + uint32_t allocationCount; + /** \brief Pointer to array of allocations that can be defragmented. + + The array should have `allocationCount` elements. + The array should not contain nulls. + Elements in the array should be unique - same allocation cannot occur twice. + All allocations not present in this array are considered non-moveable during this defragmentation. + */ + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations; + /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation. + + The array should have `allocationCount` elements. + You can pass null if you are not interested in this information. + */ + VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged; + /** \brief Numer of pools in `pPools` array. + */ + uint32_t poolCount; + /** \brief Either null or pointer to array of pools to be defragmented. + + All the allocations in the specified pools can be moved during defragmentation + and there is no way to check if they were really moved as in `pAllocationsChanged`, + so you must query all the allocations in all these pools for new `VkDeviceMemory` + and offset using vmaGetAllocationInfo() if you might need to recreate buffers + and images bound to them. + + The array should have `poolCount` elements. + The array should not contain nulls. + Elements in the array should be unique - same pool cannot occur twice. + + Using this array is equivalent to specifying all allocations from the pools in `pAllocations`. + It might be more efficient. + */ + const VmaPool VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(poolCount) pPools; + /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`. + + `VK_WHOLE_SIZE` means no limit. + */ + VkDeviceSize maxCpuBytesToMove; + /** \brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`. + + `UINT32_MAX` means no limit. + */ + uint32_t maxCpuAllocationsToMove; + /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`. + + `VK_WHOLE_SIZE` means no limit. + */ + VkDeviceSize maxGpuBytesToMove; + /** \brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`. + + `UINT32_MAX` means no limit. + */ + uint32_t maxGpuAllocationsToMove; + /** \brief Optional. Command buffer where GPU copy commands will be posted. + + If not null, it must be a valid command buffer handle that supports Transfer queue type. + It must be in the recording state and outside of a render pass instance. + You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd(). + + Passing null means that only CPU defragmentation will be performed. + */ + VkCommandBuffer VMA_NULLABLE commandBuffer; +} VmaDefragmentationInfo2; + +typedef struct VmaDefragmentationPassMoveInfo +{ + VmaAllocation VMA_NOT_NULL allocation; + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory; + VkDeviceSize offset; +} VmaDefragmentationPassMoveInfo; + +/** \brief Parameters for incremental defragmentation steps. + +To be used with function vmaBeginDefragmentationPass(). +*/ +typedef struct VmaDefragmentationPassInfo +{ + uint32_t moveCount; + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(moveCount) pMoves; +} VmaDefragmentationPassInfo; + +/** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment(). + +\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead. +*/ +typedef struct VmaDefragmentationInfo +{ + /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places. + + Default is `VK_WHOLE_SIZE`, which means no limit. + */ + VkDeviceSize maxBytesToMove; + /** \brief Maximum number of allocations that can be moved to different place. + + Default is `UINT32_MAX`, which means no limit. + */ + uint32_t maxAllocationsToMove; +} VmaDefragmentationInfo; + +/// Statistics returned by function vmaDefragment(). +typedef struct VmaDefragmentationStats +{ + /// Total number of bytes that have been copied while moving allocations to different places. + VkDeviceSize bytesMoved; + /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects. + VkDeviceSize bytesFreed; + /// Number of allocations that have been moved to different places. + uint32_t allocationsMoved; + /// Number of empty `VkDeviceMemory` objects that have been released to the system. + uint32_t deviceMemoryBlocksFreed; +} VmaDefragmentationStats; + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). +typedef struct VmaVirtualBlockCreateInfo +{ + /** \brief Total size of the virtual block. + + Sizes can be expressed in bytes or any units you want as long as you are consistent in using them. + For example, if you allocate from some array of structures, 1 can mean single instance of entire structure. + */ + VkDeviceSize size; + + /** \brief Use combination of #VmaVirtualBlockCreateFlagBits. + */ + VmaVirtualBlockCreateFlagBits flags; + + /** \brief Custom CPU memory allocation callbacks. Optional. + + Optional, can be null. When specified, they will be used for all CPU-side memory allocations. + */ + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; +} VmaVirtualBlockCreateInfo; + +/// Parameters of created virtual allocation to be passed to vmaVirtualAllocate(). +typedef struct VmaVirtualAllocationCreateInfo +{ + /** \brief Size of the allocation. + + Cannot be zero. + */ + VkDeviceSize size; + /** \brief Required alignment of the allocation. Optional. + + Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset. + */ + VkDeviceSize alignment; + /** \brief Use combination of #VmaVirtualAllocationCreateFlagBits. + */ + VmaVirtualAllocationCreateFlags flags; + /** \brief Custom pointer to be associated with the allocation. Optional. + + It can be any value and can be used for user-defined purposes. It can be fetched or changed later. + */ + void* VMA_NULLABLE pUserData; +} VmaVirtualAllocationCreateInfo; + +/// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo(). +typedef struct VmaVirtualAllocationInfo +{ + /** \brief Offset of the allocation. + + Offset at which the allocation was made. + */ + VkDeviceSize offset; + /** \brief Size of the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::size. + */ + VkDeviceSize size; + /** \brief Custom pointer associated with the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData(). + */ + void* VMA_NULLABLE pUserData; +} VmaVirtualAllocationInfo; + +/** @} */ + +#endif // _VMA_DATA_TYPES_DECLARATIONS + +#ifndef _VMA_FUNCTION_HEADERS + +/** +\addtogroup group_init +@{ +*/ + +/// Creates #VmaAllocator object. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( + const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator); + +/// Destroys allocator object. +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( + VmaAllocator VMA_NULLABLE allocator); + +/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc. + +It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to +`VkPhysicalDevice`, `VkDevice` etc. every time using this function. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo); + +/** +PhysicalDeviceProperties are fetched from physicalDevice by the allocator. +You can access it here, without fetching it again on your own. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties); + +/** +PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. +You can access it here, without fetching it again on your own. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); + +/** +\brief Given Memory Type Index, returns Property Flags of this memory type. + +This is just a convenience function. Same information can be obtained using +vmaGetMemoryProperties(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeIndex, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); + +/** \brief Sets index of the current frame. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t frameIndex); + +/** @} */ + +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Retrieves statistics from current state of the Allocator. + +This function is called "calculate" not "get" because it has to traverse all +internal data structures, so it may be quite slow. For faster but more brief statistics +suitable to be called every frame or every allocation, use vmaGetHeapBudgets(). + +Note that when using allocator from multiple threads, returned information may immediately +become outdated. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats( + VmaAllocator VMA_NOT_NULL allocator, + VmaStats* VMA_NOT_NULL pStats); + +/** \brief Retrieves information about current memory budget for all memory heaps. + +\param allocator +\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used. + +This function is called "get" not "calculate" because it is very fast, suitable to be called +every frame or every allocation. For more detailed statistics use vmaCalculateStats(). + +Note that when using allocator from multiple threads, returned information may immediately +become outdated. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( + VmaAllocator VMA_NOT_NULL allocator, + VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pBudgets); + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** +\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo. + This algorithm tries to find a memory type that: - Is allowed by memoryTypeBits. @@ -1115,276 +1638,277 @@ device doesn't support any memory type with requested features for the specific type of resource you want to use it for. Please check parameters of your resource, like image layout (OPTIMAL versus LINEAR) or mip level count. */ -VkResult vmaFindMemoryTypeIndex( - VmaAllocator allocator, +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( + VmaAllocator VMA_NOT_NULL allocator, uint32_t memoryTypeBits, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - uint32_t* pMemoryTypeIndex); + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); -/// Flags to be passed as VmaPoolCreateInfo::flags. -typedef enum VmaPoolCreateFlagBits { - /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. +/** +\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo. - This is na optional optimization flag. +It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. +It internally creates a temporary, dummy buffer that never has memory bound. +It is just a convenience function, equivalent to calling: - If you always allocate using vmaCreateBuffer(), vmaCreateImage(), - vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator - knows exact type of your allocations so it can handle Buffer-Image Granularity - in the optimal way. - - If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(), - exact type of such allocations is not known, so allocator must be conservative - in handling Buffer-Image Granularity, which can lead to suboptimal allocation - (wasted memory). In that case, if you can make sure you always allocate only - buffers and linear images or only optimal images out of this pool, use this flag - to make allocator disregard Buffer-Image Granularity and so make allocations - more optimal. - */ - VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, - - VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VmaPoolCreateFlagBits; -typedef VkFlags VmaPoolCreateFlags; - -/** \brief Describes parameter of created `VmaPool`. +- `vkCreateBuffer` +- `vkGetBufferMemoryRequirements` +- `vmaFindMemoryTypeIndex` +- `vkDestroyBuffer` */ -typedef struct VmaPoolCreateInfo { - /** \brief Vulkan memory type index to allocate this pool from. - */ - uint32_t memoryTypeIndex; - /** \brief Use combination of `VmaPoolCreateFlagBits`. - */ - VmaPoolCreateFlags flags; - /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); - Optional. Leave 0 to use default. - */ - VkDeviceSize blockSize; - /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty. +/** +\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo. - Set to 0 to have no preallocated blocks and let the pool be completely empty. - */ - size_t minBlockCount; - /** \brief Maximum number of blocks that can be allocated in this pool. +It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. +It internally creates a temporary, dummy image that never has memory bound. +It is just a convenience function, equivalent to calling: - Optional. Set to 0 to use `SIZE_MAX`, which means no limit. - - Set to same value as minBlockCount to have fixed amount of memory allocated - throuout whole lifetime of this pool. - */ - size_t maxBlockCount; - /** \brief Maximum number of additional frames that are in use at the same time as current frame. - - This value is used only when you make allocations with - `VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` flag. Such allocation cannot become - lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount. - - For example, if you double-buffer your command buffers, so resources used for - rendering in previous frame may still be in use by the GPU at the moment you - allocate resources needed for the current frame, set this value to 1. - - If you want to allow any allocations other than used in the current frame to - become lost, set this value to 0. - */ - uint32_t frameInUseCount; -} VmaPoolCreateInfo; - -/** \brief Describes parameter of existing `VmaPool`. +- `vkCreateImage` +- `vkGetImageMemoryRequirements` +- `vmaFindMemoryTypeIndex` +- `vkDestroyImage` */ -typedef struct VmaPoolStats { - /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes. - */ - VkDeviceSize size; - /** \brief Total number of bytes in the pool not used by any `VmaAllocation`. - */ - VkDeviceSize unusedSize; - /** \brief Number of VmaAllocation objects created from this pool that were not destroyed or lost. - */ - size_t allocationCount; - /** \brief Number of continuous memory ranges in the pool not used by any `VmaAllocation`. - */ - size_t unusedRangeCount; - /** \brief Size of the largest continuous free memory region. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); - Making a new allocation of that size is not guaranteed to succeed because of - possible additional margin required to respect alignment and buffer/image - granularity. - */ - VkDeviceSize unusedRangeSizeMax; -} VmaPoolStats; +/** \brief Allocates Vulkan device memory and creates #VmaPool object. -/** \brief Allocates Vulkan device memory and creates `VmaPool` object. - -@param allocator Allocator object. -@param pCreateInfo Parameters of pool to create. -@param[out] pPool Handle to created pool. +\param allocator Allocator object. +\param pCreateInfo Parameters of pool to create. +\param[out] pPool Handle to created pool. */ -VkResult vmaCreatePool( - VmaAllocator allocator, - const VmaPoolCreateInfo* pCreateInfo, - VmaPool* pPool); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( + VmaAllocator VMA_NOT_NULL allocator, + const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool); -/** \brief Destroys VmaPool object and frees Vulkan device memory. +/** \brief Destroys #VmaPool object and frees Vulkan device memory. */ -void vmaDestroyPool( - VmaAllocator allocator, - VmaPool pool); +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NULLABLE pool); -/** \brief Retrieves statistics of existing VmaPool object. +/** @} */ -@param allocator Allocator object. -@param pool Pool object. -@param[out] pPoolStats Statistics of specified pool. +/** +\addtogroup group_stats +@{ */ -void vmaGetPoolStats( - VmaAllocator allocator, - VmaPool pool, - VmaPoolStats* pPoolStats); -/** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now. +/** \brief Retrieves statistics of existing #VmaPool object. -@param allocator Allocator object. -@param pool Pool. -@param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information. +\param allocator Allocator object. +\param pool Pool object. +\param[out] pPoolStats Statistics of specified pool. */ -void vmaMakePoolAllocationsLost( - VmaAllocator allocator, - VmaPool pool, - size_t* pLostAllocationCount); +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaPoolStats* VMA_NOT_NULL pPoolStats); -VK_DEFINE_HANDLE(VmaAllocation) +/** @} */ -/** \brief Parameters of `VmaAllocation` objects, that can be retrieved using function vmaGetAllocationInfo(). +/** +\addtogroup group_alloc +@{ */ -typedef struct VmaAllocationInfo { - /** \brief Memory type index that this allocation was allocated from. - - It never changes. - */ - uint32_t memoryType; - /** \brief Handle to Vulkan memory object. - Same memory object can be shared by multiple allocations. - - It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost. +/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions. - If the allocation is lost, it is equal to `VK_NULL_HANDLE`. - */ - VkDeviceMemory deviceMemory; - /** \brief Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation. +Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, +`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is +`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). - It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost. - */ - VkDeviceSize offset; - /** \brief Size of this allocation, in bytes. +Possible return values: - It never changes, unless allocation is lost. - */ - VkDeviceSize size; - /** \brief Pointer to the beginning of this allocation as mapped data. +- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. +- `VK_SUCCESS` - corruption detection has been performed and succeeded. +- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. +- Other value: Error returned by Vulkan, e.g. memory mapping failure. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool); - If the allocation hasn't been mapped using vmaMapMemory() and hasn't been - created with `VMA_ALLOCATION_CREATE_MAPPED_BIT` flag, this value null. +/** \brief Retrieves name of a custom pool. - It can change after call to vmaMapMemory(), vmaUnmapMemory(). - It can also change after call to vmaDefragment() if this allocation is passed to the function. - */ - void* pMappedData; - /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). +After the call `ppName` is either null or points to an internally-owned null-terminated string +containing name of the pool that was previously set. The pointer becomes invalid when the pool is +destroyed or its name is changed using vmaSetPoolName(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE* VMA_NOT_NULL ppName); - It can change after call to vmaSetAllocationUserData() for this allocation. - */ - void* pUserData; -} VmaAllocationInfo; +/** \brief Sets name of a custom pool. + +`pName` can be either null or pointer to a null-terminated string with new name for the pool. +Function makes internal copy of the string, so it can be changed or freed immediately after this call. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE pName); /** \brief General purpose memory allocation. -@param[out] pAllocation Handle to allocated memory. -@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). +\param allocator +\param pVkMemoryRequirements +\param pCreateInfo +\param[out] pAllocation Handle to allocated memory. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). -You should free the memory using vmaFreeMemory(). +You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(), vmaCreateBuffer(), vmaCreateImage() instead whenever possible. */ -VkResult vmaAllocateMemory( - VmaAllocator allocator, - const VkMemoryRequirements* pVkMemoryRequirements, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief General purpose memory allocation for multiple allocation objects at once. + +\param allocator Allocator object. +\param pVkMemoryRequirements Memory requirements for each allocation. +\param pCreateInfo Creation parameters for each allocation. +\param allocationCount Number of allocations to make. +\param[out] pAllocations Pointer to array that will be filled with handles to created allocations. +\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations. + +You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). + +Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. +It is just a general purpose allocation function able to make multiple allocations at once. +It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times. + +All allocations are made using same parameters. All of them are created out of the same memory pool and type. +If any allocation fails, all allocations already made within this function call are also freed, so that when +returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo, + size_t allocationCount, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, + VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo); /** -@param[out] pAllocation Handle to allocated memory. -@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). +\param allocator +\param buffer +\param pCreateInfo +\param[out] pAllocation Handle to allocated memory. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). You should free the memory using vmaFreeMemory(). */ -VkResult vmaAllocateMemoryForBuffer( - VmaAllocator allocator, - VkBuffer buffer, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /// Function similar to vmaAllocateMemoryForBuffer(). -VkResult vmaAllocateMemoryForImage( - VmaAllocator allocator, - VkImage image, - const VmaAllocationCreateInfo* pCreateInfo, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); -/// Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). -void vmaFreeMemory( - VmaAllocator allocator, - VmaAllocation allocation); +/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). -/// Returns current information about specified allocation. -void vmaGetAllocationInfo( - VmaAllocator allocator, - VmaAllocation allocation, - VmaAllocationInfo* pAllocationInfo); +Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( + VmaAllocator VMA_NOT_NULL allocator, + const VmaAllocation VMA_NULLABLE allocation); + +/** \brief Frees memory and destroys multiple allocations. + +Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding. +It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(), +vmaAllocateMemoryPages() and other functions. +It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times. + +Allocations in `pAllocations` array can come from any memory pools and types. +Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + size_t allocationCount, + const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations); + +/** \brief Returns current information about specified allocation. + +Current paramteres of given allocation are returned in `pAllocationInfo`. + +Although this function doesn't lock any mutex, so it should be quite efficient, +you should avoid calling it too often. +You can retrieve same VmaAllocationInfo structure while creating your resource, from function +vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change +(e.g. due to defragmentation). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo); /** \brief Sets pUserData in given allocation to new value. If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT, pUserData must be either null, or pointer to a null-terminated string. The function -makes local copy of the string and sets it as allocation's pUserData. String +makes local copy of the string and sets it as allocation's `pUserData`. String passed as pUserData doesn't need to be valid for whole lifetime of the allocation - you can free it after this call. String previously pointed by allocation's pUserData is freed from memory. -If the flag was not used, the value of pointer pUserData is just copied to -allocation's pUserData. It is opaque, so you can use it however you want - e.g. +If the flag was not used, the value of pointer `pUserData` is just copied to +allocation's `pUserData`. It is opaque, so you can use it however you want - e.g. as a pointer, ordinal number or some handle to you own data. */ -void vmaSetAllocationUserData( - VmaAllocator allocator, - VmaAllocation allocation, - void* pUserData); +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE pUserData); -/** \brief Creates new allocation that is in lost state from the beginning. +/** +\brief Given an allocation, returns Property Flags of its memory type. -It can be useful if you need a dummy, non-null allocation. - -You still need to destroy created object using vmaFreeMemory(). - -Returned allocation is not tied to any specific memory pool or memory type and -not bound to any image or buffer. It has size = 0. It cannot be turned into -a real, non-empty allocation. +This is just a convenience function. Same information can be obtained using +vmaGetAllocationInfo() + vmaGetMemoryProperties(). */ -void vmaCreateLostAllocation( - VmaAllocator allocator, - VmaAllocation* pAllocation); +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); /** \brief Maps memory represented by given allocation and returns pointer to it. Maps memory represented by given allocation to make it accessible to CPU code. When succeeded, `*ppData` contains pointer to first byte of this memory. -If the allocation is part of bigger `VkDeviceMemory` block, the pointer is -correctly offseted to the beginning of region assigned to this particular -allocation. + +\warning +If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is +correctly offsetted to the beginning of region assigned to this particular allocation. +Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block. +You should not add VmaAllocationInfo::offset to it! Mapping is internally reference-counted and synchronized, so despite raw Vulkan function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory` @@ -1400,145 +1924,335 @@ It also safe to call this function multiple times on the same allocation. You must call vmaUnmapMemory() same number of times as you called vmaMapMemory(). It is also safe to call this function on allocation created with -`VMA_ALLOCATION_CREATE_MAPPED_BIT` flag. Its memory stays mapped all the time. +#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time. You must still call vmaUnmapMemory() same number of times as you called vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the -"0-th" mapping made automatically due to `VMA_ALLOCATION_CREATE_MAPPED_BIT` flag. +"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag. This function fails when used on allocation made in memory type that is not `HOST_VISIBLE`. -This function always fails when called for allocation that was created with -`VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT` flag. Such allocations cannot be -mapped. +This function doesn't automatically flush or invalidate caches. +If the allocation is made from a memory types that is not `HOST_COHERENT`, +you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. */ -VkResult vmaMapMemory( - VmaAllocator allocator, - VmaAllocation allocation, - void** ppData); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE* VMA_NOT_NULL ppData); /** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). For details, see description of vmaMapMemory(). + +This function doesn't automatically flush or invalidate caches. +If the allocation is made from a memory types that is not `HOST_COHERENT`, +you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. */ -void vmaUnmapMemory( - VmaAllocator allocator, - VmaAllocation allocation); +VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation); -/** \brief Optional configuration parameters to be passed to function vmaDefragment(). */ -typedef struct VmaDefragmentationInfo { - /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places. - - Default is `VK_WHOLE_SIZE`, which means no limit. - */ - VkDeviceSize maxBytesToMove; - /** \brief Maximum number of allocations that can be moved to different place. +/** \brief Flushes memory of given allocation. - Default is `UINT32_MAX`, which means no limit. - */ - uint32_t maxAllocationsToMove; -} VmaDefragmentationInfo; +Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation. +It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`. +Unmap operation doesn't do that automatically. -/** \brief Statistics returned by function vmaDefragment(). */ -typedef struct VmaDefragmentationStats { - /// Total number of bytes that have been copied while moving allocations to different places. - VkDeviceSize bytesMoved; - /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects. - VkDeviceSize bytesFreed; - /// Number of allocations that have been moved to different places. - uint32_t allocationsMoved; - /// Number of empty `VkDeviceMemory` objects that have been released to the system. - uint32_t deviceMemoryBlocksFreed; -} VmaDefragmentationStats; +- `offset` must be relative to the beginning of allocation. +- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. +- `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. +- If `size` is 0, this call is ignored. +- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. -/** \brief Compacts memory by moving allocations. +Warning! `offset` and `size` are relative to the contents of given `allocation`. +If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. +Do not pass allocation's offset as `offset`!!! -@param pAllocations Array of allocations that can be moved during this compation. -@param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays. -@param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information. -@param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values. -@param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information. -@return VK_SUCCESS if completed, VK_INCOMPLETE if succeeded but didn't make all possible optimizations because limits specified in pDefragmentationInfo have been reached, negative error code in case of error. +This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + +/** \brief Invalidates memory of given allocation. + +Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation. +It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`. +Map operation doesn't do that automatically. + +- `offset` must be relative to the beginning of allocation. +- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. +- `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. +- If `size` is 0, this call is ignored. +- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. + +Warning! `offset` and `size` are relative to the contents of given `allocation`. +If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. +Do not pass allocation's offset as `offset`!!! + +This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if +it is called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + +/** \brief Flushes memory of given set of allocations. + +Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations. +For more information, see documentation of vmaFlushAllocation(). + +\param allocator +\param allocationCount +\param allocations +\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero. +\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + +This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + +/** \brief Invalidates memory of given set of allocations. + +Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations. +For more information, see documentation of vmaInvalidateAllocation(). + +\param allocator +\param allocationCount +\param allocations +\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all ofsets are zero. +\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + +This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + +/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. + +\param allocator +\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked. + +Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, +`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are +`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). + +Possible return values: + +- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types. +- `VK_SUCCESS` - corruption detection has been performed and succeeded. +- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. +- Other value: Error returned by Vulkan, e.g. memory mapping failure. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeBits); + +/** \brief Begins defragmentation process. + +\param allocator Allocator object. +\param pInfo Structure filled with parameters of defragmentation. +\param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information. +\param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation. +\return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error. + +Use this function instead of old, deprecated vmaDefragment(). + +Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd(): + +- You should not use any of allocations passed as `pInfo->pAllocations` or + any allocations that belong to pools passed as `pInfo->pPools`, + including calling vmaGetAllocationInfo(), or access + their data. +- Some mutexes protecting internal data structures may be locked, so trying to + make or free any allocations, bind buffers or images, map memory, or launch + another simultaneous defragmentation in between may cause stall (when done on + another thread) or deadlock (when done on the same thread), unless you are + 100% sure that defragmented allocations are in different pools. +- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined. + They become valid after call to vmaDefragmentationEnd(). +- If `pInfo->commandBuffer` is not null, you must submit that command buffer + and make sure it finished execution before calling vmaDefragmentationEnd(). + +For more information and important limitations regarding defragmentation, see documentation chapter: +[Defragmentation](@ref defragmentation). +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin( + VmaAllocator VMA_NOT_NULL allocator, + const VmaDefragmentationInfo2* VMA_NOT_NULL pInfo, + VmaDefragmentationStats* VMA_NULLABLE pStats, + VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext); + +/** \brief Ends defragmentation process. + +Use this function to finish defragmentation started by vmaDefragmentationBegin(). +It is safe to pass `context == null`. The function then does nothing. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context); + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context, + VmaDefragmentationPassInfo* VMA_NOT_NULL pInfo); + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NULLABLE context); + +/** \brief Deprecated. Compacts memory by moving allocations. + +\param allocator +\param pAllocations Array of allocations that can be moved during this compation. +\param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays. +\param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information. +\param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values. +\param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information. +\return `VK_SUCCESS` if completed, negative error code in case of error. + +\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead. This function works by moving allocations to different places (different `VkDeviceMemory` objects and/or different offsets) in order to optimize memory -usage. Only allocations that are in pAllocations array can be moved. All other +usage. Only allocations that are in `pAllocations` array can be moved. All other allocations are considered nonmovable in this call. Basic rules: - Only allocations made in memory types that have - `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag can be compacted. You may pass other - allocations but it makes no sense - these will never be moved. -- You may pass allocations made with `VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT` but - it makes no sense - they will never be moved. -- Both allocations made with or without `VMA_ALLOCATION_CREATE_MAPPED_BIT` + `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` + flags can be compacted. You may pass other allocations but it makes no sense - + these will never be moved. +- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or + #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations + passed to this function that come from such pools are ignored. +- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or + created as dedicated allocations for any other reason are also ignored. +- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT flag can be compacted. If not persistently mapped, memory will be mapped temporarily inside this function if needed. -- You must not pass same `VmaAllocation` object multiple times in pAllocations array. +- You must not pass same #VmaAllocation object multiple times in `pAllocations` array. The function also frees empty `VkDeviceMemory` blocks. -After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or -VmaAllocationInfo::offset changes. You must query them again using -vmaGetAllocationInfo() if you need them. +Warning: This function may be time-consuming, so you shouldn't call it too often +(like after every resource creation/destruction). +You can call it on special occasions (like when reloading a game level or +when you just destroyed a lot of objects). Calling it every frame may be OK, but +you should measure that on your platform. -If an allocation has been moved, data in memory is copied to new place -automatically, but if it was bound to a buffer or an image, you must destroy -that object yourself, create new one and bind it to the new memory pointed by -the allocation. You must use `vkDestroyBuffer()`, `vkDestroyImage()`, -`vkCreateBuffer()`, `vkCreateImage()` for that purpose and NOT vmaDestroyBuffer(), -vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage()! Example: - -\code -VkDevice device = ...; -VmaAllocator allocator = ...; -std::vector buffers = ...; -std::vector allocations = ...; - -std::vector allocationsChanged(allocations.size()); -vmaDefragment(allocator, allocations.data(), allocations.size(), allocationsChanged.data(), nullptr, nullptr); - -for(size_t i = 0; i < allocations.size(); ++i) -{ - if(allocationsChanged[i]) - { - VmaAllocationInfo allocInfo; - vmaGetAllocationInfo(allocator, allocations[i], &allocInfo); - - vkDestroyBuffer(device, buffers[i], nullptr); - - VkBufferCreateInfo bufferInfo = ...; - vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]); - - // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning. - - vkBindBufferMemory(device, buffers[i], allocInfo.deviceMemory, allocInfo.offset); - } -} -\endcode - -Warning! This function is not correct according to Vulkan specification. Use it -at your own risk. That's becuase Vulkan doesn't guarantee that memory -requirements (size and alignment) for a new buffer or image are consistent. They -may be different even for subsequent calls with the same parameters. It really -does happen on some platforms, especially with images. - -This function may be time-consuming, so you shouldn't call it too often (like -every frame or after every resource creation/destruction), but rater you can -call it on special occasions (like when reloading a game level, when you just -destroyed a lot of objects). +For more information, see [Defragmentation](@ref defragmentation) chapter. */ -VkResult vmaDefragment( - VmaAllocator allocator, - VmaAllocation* pAllocations, +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( + VmaAllocator VMA_NOT_NULL allocator, + const VmaAllocation VMA_NOT_NULL* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, size_t allocationCount, - VkBool32* pAllocationsChanged, - const VmaDefragmentationInfo *pDefragmentationInfo, - VmaDefragmentationStats* pDefragmentationStats); + VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged, + const VmaDefragmentationInfo* VMA_NULLABLE pDefragmentationInfo, + VmaDefragmentationStats* VMA_NULLABLE pDefragmentationStats); + +/** \brief Binds buffer to allocation. + +Binds specified buffer to region of memory represented by specified allocation. +Gets `VkDeviceMemory` handle and offset from the allocation. +If you want to create a buffer, allocate memory for it and bind them together separately, +you should use this function for binding instead of standard `vkBindBufferMemory()`, +because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple +allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously +(which is illegal in Vulkan). + +It is recommended to use function vmaCreateBuffer() instead of this one. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer); + +/** \brief Binds buffer to allocation with additional parameters. + +\param allocator +\param allocation +\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. +\param buffer +\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null. + +This function is similar to vmaBindBufferMemory(), but it provides additional parameters. + +If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag +or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const void* VMA_NULLABLE pNext); + +/** \brief Binds image to allocation. + +Binds specified image to region of memory represented by specified allocation. +Gets `VkDeviceMemory` handle and offset from the allocation. +If you want to create an image, allocate memory for it and bind them together separately, +you should use this function for binding instead of standard `vkBindImageMemory()`, +because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple +allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously +(which is illegal in Vulkan). + +It is recommended to use function vmaCreateImage() instead of this one. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image); + +/** \brief Binds image to allocation with additional parameters. + +\param allocator +\param allocation +\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. +\param image +\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. + +This function is similar to vmaBindImageMemory(), but it provides additional parameters. + +If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag +or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const void* VMA_NULLABLE pNext); /** -@param[out] pBuffer Buffer that was created. -@param[out] pAllocation Allocation that was created. -@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). +\param allocator +\param pBufferCreateInfo +\param pAllocationCreateInfo +\param[out] pBuffer Buffer that was created. +\param[out] pAllocation Allocation that was created. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). This function automatically: @@ -1553,21 +2267,40 @@ If the function succeeded, you must destroy both buffer and allocation when you no longer need them using either convenience function vmaDestroyBuffer() or separately, using `vkDestroyBuffer()` and vmaFreeMemory(). -If VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, +If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, VK_KHR_dedicated_allocation extension is used internally to query driver whether it requires or prefers the new buffer to have dedicated allocation. If yes, and if dedicated allocation is possible (VmaAllocationCreateInfo::pool is null -and VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated +and #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated allocation for this buffer, just like when using -VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + +\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer, +although recommended as a good practice, is out of scope of this library and could be implemented +by the user as a higher-level logic on top of VMA. */ -VkResult vmaCreateBuffer( - VmaAllocator allocator, - const VkBufferCreateInfo* pBufferCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - VkBuffer* pBuffer, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief Creates a buffer with additional minimum alignment. + +Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, +minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. +for interop with OpenGL. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkDeviceSize minAlignment, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan buffer and frees allocated memory. @@ -1580,19 +2313,19 @@ vmaFreeMemory(allocator, allocation); It it safe to pass null as buffer and/or allocation. */ -void vmaDestroyBuffer( - VmaAllocator allocator, - VkBuffer buffer, - VmaAllocation allocation); +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE buffer, + VmaAllocation VMA_NULLABLE allocation); /// Function similar to vmaCreateBuffer(). -VkResult vmaCreateImage( - VmaAllocator allocator, - const VkImageCreateInfo* pImageCreateInfo, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - VkImage* pImage, - VmaAllocation* pAllocation, - VmaAllocationInfo* pAllocationInfo); +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); /** \brief Destroys Vulkan image and frees allocated memory. @@ -1605,10 +2338,142 @@ vmaFreeMemory(allocator, allocation); It it safe to pass null as image and/or allocation. */ -void vmaDestroyImage( - VmaAllocator allocator, - VkImage image, - VmaAllocation allocation); +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NULLABLE_NON_DISPATCHABLE image, + VmaAllocation VMA_NULLABLE allocation); + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \brief Creates new #VmaVirtualBlock object. + +\param pCreateInfo Parameters for creation. +\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( + const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock); + +/** \brief Destroys #VmaVirtualBlock object. + +Please note that you should consciously handle virtual allocations that could remain unfreed in the block. +You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock() +if you are sure this is what you want. If you do neither, an assert is called. + +If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`, +don't forget to free them. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock( + VmaVirtualBlock VMA_NULLABLE virtualBlock); + +/** \brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations. +*/ +VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + +/** \brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo); + +/** \brief Allocates new virtual allocation inside given #VmaVirtualBlock. + +There is no handle type for a virtual allocation. +Virtual allocations within a specific virtual block are uniquely identified by their offsets. + +If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned +(despite the function doesn't ever allocate actual GPU memory). + +\param virtualBlock Virtual block +\param pCreateInfo Parameters for the allocation +\param[out] pAllocation Returned handle of the new allocation +\param[out] pOffset Returned offset of the new allocation. Optional, can be null. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualAllocation* VMA_NOT_NULL pAllocation, + VkDeviceSize* VMA_NULLABLE pOffset); + +/** \brief Frees virtual allocation inside given #VmaVirtualBlock. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NULLABLE allocation); + +/** \brief Frees all virtual allocations inside given #VmaVirtualBlock. + +You must either call this function or free each virtual allocation individually with vmaVirtualFree() +before destroying a virtual block. Otherwise, an assert is called. + +If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`, +don't forget to free it as well. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + +/** \brief Changes custom pointer associated with given virtual allocation. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE pUserData); + +/** \brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStats( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaStatInfo* VMA_NOT_NULL pStatInfo); + +/** @} */ + +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock. +\param virtualBlock Virtual block. +\param[out] ppStatsString Returned string. +\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStats(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces. + +Returned string must be freed using vmaFreeVirtualBlockStatsString(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); + +/// Frees a string returned by vmaBuildVirtualBlockStatsString(). +VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE pStatsString); + +#if VMA_STATS_STRING_ENABLED +/** \brief Builds and returns statistics as a null-terminated string in JSON format. +\param allocator +\param[out] ppStatsString Must be freed using vmaFreeStatsString() function. +\param detailedMap +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE pStatsString); +#endif // VMA_STATS_STRING_ENABLED + +/** @} */ + +#endif // _VMA_FUNCTION_HEADERS #ifdef __cplusplus } @@ -1616,8 +2481,16 @@ void vmaDestroyImage( #endif // AMD_VULKAN_MEMORY_ALLOCATOR_H +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION +// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + // For Visual Studio IntelliSense. -#ifdef __INTELLISENSE__ +#if defined(__cplusplus) && defined(__INTELLISENSE__) #define VMA_IMPLEMENTATION #endif @@ -1627,6 +2500,7 @@ void vmaDestroyImage( #include #include #include +#include /******************************************************************************* CONFIGURATION SECTION @@ -1634,45 +2508,43 @@ CONFIGURATION SECTION Define some of these macros before each #include of this header or change them here if you need other then default behavior depending on your environment. */ +#ifndef _VMA_CONFIGURATION /* Define this macro to 1 to make the library fetch pointers to Vulkan functions internally, like: vulkanFunctions.vkAllocateMemory = &vkAllocateMemory; - -Define to 0 if you are going to provide you own pointers to Vulkan functions via -VmaAllocatorCreateInfo::pVulkanFunctions. */ -#ifndef VMA_STATIC_VULKAN_FUNCTIONS -#define VMA_STATIC_VULKAN_FUNCTIONS 1 +#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES) + #define VMA_STATIC_VULKAN_FUNCTIONS 1 #endif -// Define this macro to 1 to make the library use STL containers instead of its own implementation. -//#define VMA_USE_STL_CONTAINERS 1 +/* +Define this macro to 1 to make the library fetch pointers to Vulkan functions +internally, like: -/* Set this macro to 1 to make the library including and using STL containers: -std::pair, std::vector, std::list, std::unordered_map. + vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(device, "vkAllocateMemory"); -Set it to 0 or undefined to make the library using its own implementation of -the containers. +To use this feature in new versions of VMA you now have to pass +VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as +VmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null. */ -#if VMA_USE_STL_CONTAINERS - #define VMA_USE_STL_VECTOR 1 - #define VMA_USE_STL_UNORDERED_MAP 1 - #define VMA_USE_STL_LIST 1 +#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS) + #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #endif -#if VMA_USE_STL_VECTOR - #include -#endif - -#if VMA_USE_STL_UNORDERED_MAP - #include -#endif - -#if VMA_USE_STL_LIST - #include +#ifndef VMA_USE_STL_SHARED_MUTEX + // Compiler conforms to C++17. + #if __cplusplus >= 201703L + #define VMA_USE_STL_SHARED_MUTEX 1 + // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus + // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2. + #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L + #define VMA_USE_STL_SHARED_MUTEX 1 + #else + #define VMA_USE_STL_SHARED_MUTEX 0 + #endif #endif /* @@ -1681,63 +2553,141 @@ remove them if not needed. */ #include // for assert #include // for min, max -#include // for std::mutex -#include // for std::atomic +#include -#if !defined(_WIN32) - #include // for aligned_alloc() +#ifndef VMA_NULL + // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. + #define VMA_NULL nullptr #endif +#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16) +#include +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + // alignment must be >= sizeof(void*) + if(alignment < sizeof(void*)) + { + alignment = sizeof(void*); + } + + return memalign(alignment, size); +} +#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) && defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)) +#include + +#if defined(__APPLE__) +#include +#endif + +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + // Unfortunately, aligned_alloc causes VMA to crash due to it returning null pointers. (At least under 11.4) + // Therefore, for now disable this specific exception until a proper solution is found. + //#if defined(__APPLE__) && (defined(MAC_OS_X_VERSION_10_16) || defined(__IPHONE_14_0)) + //#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_16 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + // // For C++14, usr/include/malloc/_malloc.h declares aligned_alloc()) only + // // with the MacOSX11.0 SDK in Xcode 12 (which is what adds + // // MAC_OS_X_VERSION_10_16), even though the function is marked + // // availabe for 10.15. That is why the preprocessor checks for 10.16 but + // // the __builtin_available checks for 10.15. + // // People who use C++17 could call aligned_alloc with the 10.15 SDK already. + // if (__builtin_available(macOS 10.15, iOS 13, *)) + // return aligned_alloc(alignment, size); + //#endif + //#endif + + // alignment must be >= sizeof(void*) + if(alignment < sizeof(void*)) + { + alignment = sizeof(void*); + } + + void *pointer; + if(posix_memalign(&pointer, alignment, size) == 0) + return pointer; + return VMA_NULL; +} +#elif defined(_WIN32) +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + return _aligned_malloc(size, alignment); +} +#else +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + return aligned_alloc(alignment, size); +} +#endif + +#if defined(_WIN32) +static void vma_aligned_free(void* ptr) +{ + _aligned_free(ptr); +} +#else +static void vma_aligned_free(void* VMA_NULLABLE ptr) +{ + free(ptr); +} +#endif + +// If your compiler is not compatible with C++11 and definition of +// aligned_alloc() function is missing, uncommeting following line may help: + +//#include + // Normal assert to check for programmer's errors, especially in Debug configuration. #ifndef VMA_ASSERT - #ifdef _DEBUG - #define VMA_ASSERT(expr) assert(expr) - #else + #ifdef NDEBUG #define VMA_ASSERT(expr) + #else + #define VMA_ASSERT(expr) assert(expr) #endif #endif // Assert that will be called very often, like inside data structures e.g. operator[]. // Making it non-empty can make program slow. #ifndef VMA_HEAVY_ASSERT - #ifdef _DEBUG - #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) - #else + #ifdef NDEBUG #define VMA_HEAVY_ASSERT(expr) + #else + #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) #endif #endif -#ifndef VMA_NULL - // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. - #define VMA_NULL nullptr -#endif - #ifndef VMA_ALIGN_OF #define VMA_ALIGN_OF(type) (__alignof(type)) #endif #ifndef VMA_SYSTEM_ALIGNED_MALLOC - #if defined(_WIN32) - #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment))) - #else - #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) )) - #endif + #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) vma_aligned_alloc((alignment), (size)) #endif -#ifndef VMA_SYSTEM_FREE - #if defined(_WIN32) - #define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr) +#ifndef VMA_SYSTEM_ALIGNED_FREE + // VMA_SYSTEM_FREE is the old name, but might have been defined by the user + #if defined(VMA_SYSTEM_FREE) + #define VMA_SYSTEM_ALIGNED_FREE(ptr) VMA_SYSTEM_FREE(ptr) #else - #define VMA_SYSTEM_FREE(ptr) free(ptr) - #endif + #define VMA_SYSTEM_ALIGNED_FREE(ptr) vma_aligned_free(ptr) + #endif +#endif + +#ifndef VMA_BITSCAN_LSB + // Scans integer for index of first nonzero value from the Least Significant Bit (LSB). If mask is 0 then returns UINT8_MAX + #define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask) +#endif + +#ifndef VMA_BITSCAN_MSB + // Scans integer for index of first nonzero value from the Most Significant Bit (MSB). If mask is 0 then returns UINT8_MAX + #define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask) #endif #ifndef VMA_MIN - #define VMA_MIN(v1, v2) (std::min((v1), (v2))) + #define VMA_MIN(v1, v2) ((std::min)((v1), (v2))) #endif #ifndef VMA_MAX - #define VMA_MAX(v1, v2) (std::max((v1), (v2))) + #define VMA_MAX(v1, v2) ((std::max)((v1), (v2))) #endif #ifndef VMA_SWAP @@ -1760,171 +2710,564 @@ remove them if not needed. // Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString. #if VMA_STATS_STRING_ENABLED - static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num) - { - snprintf(outStr, strLen, "%u", static_cast(num)); - } - static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num) - { - snprintf(outStr, strLen, "%llu", static_cast(num)); - } - static inline void VmaPtrToStr(char* outStr, size_t strLen, const void* ptr) - { - snprintf(outStr, strLen, "%p", ptr); - } + static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num) + { + snprintf(outStr, strLen, "%u", static_cast(num)); + } + static inline void VmaUint64ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint64_t num) + { + snprintf(outStr, strLen, "%llu", static_cast(num)); + } + static inline void VmaPtrToStr(char* VMA_NOT_NULL outStr, size_t strLen, const void* ptr) + { + snprintf(outStr, strLen, "%p", ptr); + } #endif #ifndef VMA_MUTEX - class VmaMutex - { - public: - VmaMutex() { } - ~VmaMutex() { } - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } - private: - std::mutex m_Mutex; - }; - #define VMA_MUTEX VmaMutex + class VmaMutex + { + public: + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } + bool TryLock() { return m_Mutex.try_lock(); } + private: + std::mutex m_Mutex; + }; + #define VMA_MUTEX VmaMutex #endif +// Read-write mutex, where "read" is shared access, "write" is exclusive access. +#ifndef VMA_RW_MUTEX + #if VMA_USE_STL_SHARED_MUTEX + // Use std::shared_mutex from C++17. + #include + class VmaRWMutex + { + public: + void LockRead() { m_Mutex.lock_shared(); } + void UnlockRead() { m_Mutex.unlock_shared(); } + bool TryLockRead() { return m_Mutex.try_lock_shared(); } + void LockWrite() { m_Mutex.lock(); } + void UnlockWrite() { m_Mutex.unlock(); } + bool TryLockWrite() { return m_Mutex.try_lock(); } + private: + std::shared_mutex m_Mutex; + }; + #define VMA_RW_MUTEX VmaRWMutex + #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600 + // Use SRWLOCK from WinAPI. + // Minimum supported client = Windows Vista, server = Windows Server 2008. + class VmaRWMutex + { + public: + VmaRWMutex() { InitializeSRWLock(&m_Lock); } + void LockRead() { AcquireSRWLockShared(&m_Lock); } + void UnlockRead() { ReleaseSRWLockShared(&m_Lock); } + bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; } + void LockWrite() { AcquireSRWLockExclusive(&m_Lock); } + void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); } + bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; } + private: + SRWLOCK m_Lock; + }; + #define VMA_RW_MUTEX VmaRWMutex + #else + // Less efficient fallback: Use normal mutex. + class VmaRWMutex + { + public: + void LockRead() { m_Mutex.Lock(); } + void UnlockRead() { m_Mutex.Unlock(); } + bool TryLockRead() { return m_Mutex.TryLock(); } + void LockWrite() { m_Mutex.Lock(); } + void UnlockWrite() { m_Mutex.Unlock(); } + bool TryLockWrite() { return m_Mutex.TryLock(); } + private: + VMA_MUTEX m_Mutex; + }; + #define VMA_RW_MUTEX VmaRWMutex + #endif // #if VMA_USE_STL_SHARED_MUTEX +#endif // #ifndef VMA_RW_MUTEX + /* -If providing your own implementation, you need to implement a subset of std::atomic: - -- Constructor(uint32_t desired) -- uint32_t load() const -- void store(uint32_t desired) -- bool compare_exchange_weak(uint32_t& expected, uint32_t desired) +If providing your own implementation, you need to implement a subset of std::atomic. */ #ifndef VMA_ATOMIC_UINT32 - #define VMA_ATOMIC_UINT32 std::atomic + #include + #define VMA_ATOMIC_UINT32 std::atomic #endif -#ifndef VMA_BEST_FIT - /** - Main parameter for function assessing how good is a free suballocation for a new - allocation request. - - - Set to 1 to use Best-Fit algorithm - prefer smaller blocks, as close to the - size of requested allocations as possible. - - Set to 0 to use Worst-Fit algorithm - prefer larger blocks, as large as - possible. - - Experiments in special testing environment showed that Best-Fit algorithm is - better. - */ - #define VMA_BEST_FIT (1) +#ifndef VMA_ATOMIC_UINT64 + #include + #define VMA_ATOMIC_UINT64 std::atomic #endif #ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY - /** - Every allocation will have its own memory block. - Define to 1 for debugging purposes only. - */ - #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0) + /** + Every allocation will have its own memory block. + Define to 1 for debugging purposes only. + */ + #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0) #endif -#ifndef VMA_DEBUG_ALIGNMENT - /** - Minimum alignment of all suballocations, in bytes. - Set to more than 1 for debugging purposes only. Must be power of two. - */ - #define VMA_DEBUG_ALIGNMENT (1) +#ifndef VMA_MIN_ALIGNMENT + /** + Minimum alignment of all allocations, in bytes. + Set to more than 1 for debugging purposes. Must be power of two. + */ + #ifdef VMA_DEBUG_ALIGNMENT // Old name + #define VMA_MIN_ALIGNMENT VMA_DEBUG_ALIGNMENT + #else + #define VMA_MIN_ALIGNMENT (1) + #endif #endif #ifndef VMA_DEBUG_MARGIN - /** - Minimum margin between suballocations, in bytes. - Set nonzero for debugging purposes only. - */ - #define VMA_DEBUG_MARGIN (0) + /** + Minimum margin before and after every allocation, in bytes. + Set nonzero for debugging purposes only. + */ + #define VMA_DEBUG_MARGIN (0) +#endif + +#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS + /** + Define this macro to 1 to automatically fill new allocations and destroyed + allocations with some bit pattern. + */ + #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0) +#endif + +#ifndef VMA_DEBUG_DETECT_CORRUPTION + /** + Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to + enable writing magic value to the margin before and after every allocation and + validating it, so that memory corruptions (out-of-bounds writes) are detected. + */ + #define VMA_DEBUG_DETECT_CORRUPTION (0) #endif #ifndef VMA_DEBUG_GLOBAL_MUTEX - /** - Set this to 1 for debugging purposes only, to enable single mutex protecting all - entry calls to the library. Can be useful for debugging multithreading issues. - */ - #define VMA_DEBUG_GLOBAL_MUTEX (0) + /** + Set this to 1 for debugging purposes only, to enable single mutex protecting all + entry calls to the library. Can be useful for debugging multithreading issues. + */ + #define VMA_DEBUG_GLOBAL_MUTEX (0) #endif #ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY - /** - Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. - Set to more than 1 for debugging purposes only. Must be power of two. - */ - #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1) + /** + Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. + Set to more than 1 for debugging purposes only. Must be power of two. + */ + #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1) +#endif + +#ifndef VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT + /* + Set this to 1 to make VMA never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount + and return error instead of leaving up to Vulkan implementation what to do in such cases. + */ + #define VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT (0) #endif #ifndef VMA_SMALL_HEAP_MAX_SIZE /// Maximum size of a memory heap in Vulkan to consider it "small". - #define VMA_SMALL_HEAP_MAX_SIZE (512 * 1024 * 1024) + #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024) #endif #ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE /// Default size of a block allocated as single VkDeviceMemory from a "large" heap. - #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256 * 1024 * 1024) + #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024) #endif -#ifndef VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE - /// Default size of a block allocated as single VkDeviceMemory from a "small" heap. - #define VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE (64 * 1024 * 1024) +#ifndef VMA_CLASS_NO_COPY + #define VMA_CLASS_NO_COPY(className) \ + private: \ + className(const className&) = delete; \ + className& operator=(const className&) = delete; #endif -static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX; +#define VMA_VALIDATE(cond) do { if(!(cond)) { \ + VMA_ASSERT(0 && "Validation failed: " #cond); \ + return false; \ + } } while(false) /******************************************************************************* END OF CONFIGURATION */ +#endif // _VMA_CONFIGURATION -static VkAllocationCallbacks VmaEmptyAllocationCallbacks = { - VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL }; +static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC; +static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF; +// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F. +static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666; + +// Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants. +static const uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040; +static const uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080; +static const uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000; +static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u; +static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32; +static const uint32_t VMA_VENDOR_ID_AMD = 4098; + + +#if VMA_STATS_STRING_ENABLED +// Correspond to values of enum VmaSuballocationType. +static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = +{ + "FREE", + "UNKNOWN", + "BUFFER", + "IMAGE_UNKNOWN", + "IMAGE_LINEAR", + "IMAGE_OPTIMAL", +}; +#endif + +static VkAllocationCallbacks VmaEmptyAllocationCallbacks = + { VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL }; + + +#ifndef _VMA_ENUM_DECLARATIONS + +enum VmaSuballocationType +{ + VMA_SUBALLOCATION_TYPE_FREE = 0, + VMA_SUBALLOCATION_TYPE_UNKNOWN = 1, + VMA_SUBALLOCATION_TYPE_BUFFER = 2, + VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3, + VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4, + VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5, + VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF +}; + +enum VMA_CACHE_OPERATION +{ + VMA_CACHE_FLUSH, + VMA_CACHE_INVALIDATE +}; + +enum class VmaAllocationRequestType +{ + Normal, + TLSF, + // Used by "Linear" algorithm. + UpperAddress, + EndOf1st, + EndOf2nd, +}; + +#endif // _VMA_ENUM_DECLARATIONS + +#ifndef _VMA_FORWARD_DECLARATIONS +// Opaque handle used by allocation algorithms to identify single allocation in any conforming way. +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaAllocHandle); + +struct VmaMutexLock; +struct VmaMutexLockRead; +struct VmaMutexLockWrite; + +template +struct AtomicTransactionalIncrement; + +template +struct VmaStlAllocator; + +template +class VmaVector; + +template +class VmaSmallVector; + +template +class VmaPoolAllocator; + +template +struct VmaListItem; + +template +class VmaRawList; + +template +class VmaList; + +template +class VmaIntrusiveLinkedList; + +// Unused in this version +#if 0 +template +struct VmaPair; +template +struct VmaPairFirstLess; + +template +class VmaMap; +#endif + +#if VMA_STATS_STRING_ENABLED +class VmaStringBuilder; +class VmaJsonWriter; +#endif + +class VmaDeviceMemoryBlock; + +struct VmaDedicatedAllocationListItemTraits; +class VmaDedicatedAllocationList; + +struct VmaSuballocation; +struct VmaSuballocationOffsetLess; +struct VmaSuballocationOffsetGreater; +struct VmaSuballocationItemSizeLess; + +typedef VmaList> VmaSuballocationList; + +struct VmaAllocationRequest; + +class VmaBlockMetadata; +class VmaBlockMetadata_Generic; +class VmaBlockMetadata_Linear; +class VmaBlockMetadata_Buddy; +class VmaBlockMetadata_TLSF; + +class VmaBlockVector; + +struct VmaDefragmentationMove; +class VmaDefragmentationAlgorithm; +class VmaDefragmentationAlgorithm_Generic; +class VmaDefragmentationAlgorithm_Fast; + +struct VmaPoolListItemTraits; + +struct VmaBlockDefragmentationContext; +class VmaBlockVectorDefragmentationContext; + +struct VmaCurrentBudgetData; + +class VmaAllocationObjectAllocator; + +#endif // _VMA_FORWARD_DECLARATIONS + + +#ifndef _VMA_FUNCTIONS // Returns number of bits set to 1 in (v). static inline uint32_t VmaCountBitsSet(uint32_t v) { - uint32_t c = v - ((v >> 1) & 0x55555555); - c = ((c >> 2) & 0x33333333) + (c & 0x33333333); - c = ((c >> 4) + c) & 0x0F0F0F0F; - c = ((c >> 8) + c) & 0x00FF00FF; - c = ((c >> 16) + c) & 0x0000FFFF; - return c; + uint32_t c = v - ((v >> 1) & 0x55555555); + c = ((c >> 2) & 0x33333333) + (c & 0x33333333); + c = ((c >> 4) + c) & 0x0F0F0F0F; + c = ((c >> 8) + c) & 0x00FF00FF; + c = ((c >> 16) + c) & 0x0000FFFF; + return c; +} + +static inline uint8_t VmaBitScanLSB(uint64_t mask) +{ +#ifdef _MSC_VER + DWORD pos; + if (_BitScanForward64(&pos, mask)) + return static_cast(pos); +#else + uint8_t pos = 0; + do + { + if (mask & (1ULL << pos)) + return pos; + } while (pos++ < 63); +#endif + return UINT8_MAX; +} + +static inline uint8_t VmaBitScanLSB(uint32_t mask) +{ +#ifdef _MSC_VER + DWORD pos; + if (_BitScanForward(&pos, mask)) + return static_cast(pos); +#else + uint8_t pos = 0; + do + { + if (mask & (1UL << pos)) + return pos; + } while (pos++ < 31); +#endif + return UINT8_MAX; +} + +static inline uint8_t VmaBitScanMSB(uint64_t mask) +{ +#ifdef _MSC_VER + DWORD pos; + if (_BitScanReverse64(&pos, mask)) + return static_cast(pos); +#else + uint8_t pos = 63; + do + { + if (mask & (1ULL << pos)) + return pos; + } while (pos-- > 0); +#endif + return UINT8_MAX; +} + +static inline uint8_t VmaBitScanMSB(uint32_t mask) +{ +#ifdef _MSC_VER + DWORD pos; + if (_BitScanReverse(&pos, mask)) + return static_cast(pos); +#else + uint8_t pos = 31; + do + { + if (mask & (1UL << pos)) + return pos; + } while (pos-- > 0); +#endif + return UINT8_MAX; +} + +/* +Returns true if given number is a power of two. +T must be unsigned integer number or signed integer but always nonnegative. +For 0 returns true. +*/ +template +inline bool VmaIsPow2(T x) +{ + return (x & (x - 1)) == 0; } // Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16. // Use types like uint32_t, uint64_t as T. template -static inline T VmaAlignUp(T val, T align) +static inline T VmaAlignUp(T val, T alignment) { - return (val + align - 1) / align * align; + VMA_HEAVY_ASSERT(VmaIsPow2(alignment)); + return (val + alignment - 1) & ~(alignment - 1); +} + +// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8. +// Use types like uint32_t, uint64_t as T. +template +static inline T VmaAlignDown(T val, T alignment) +{ + VMA_HEAVY_ASSERT(VmaIsPow2(alignment)); + return val & ~(alignment - 1); } // Division with mathematical rounding to nearest number. template -inline T VmaRoundDiv(T x, T y) +static inline T VmaRoundDiv(T x, T y) { - return (x + (y / (T)2)) / y; + return (x + (y / (T)2)) / y; } -#ifndef VMA_SORT +// Divide by 'y' and round up to nearest integer. +template +static inline T VmaDivideRoundingUp(T x, T y) +{ + return (x + y - (T)1) / y; +} +// Returns smallest power of 2 greater or equal to v. +static inline uint32_t VmaNextPow2(uint32_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +static inline uint64_t VmaNextPow2(uint64_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v++; + return v; +} + +// Returns largest power of 2 less or equal to v. +static inline uint32_t VmaPrevPow2(uint32_t v) +{ + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v = v ^ (v >> 1); + return v; +} + +static inline uint64_t VmaPrevPow2(uint64_t v) +{ + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v = v ^ (v >> 1); + return v; +} + +static inline bool VmaStrIsEmpty(const char* pStr) +{ + return pStr == VMA_NULL || *pStr == '\0'; +} + +#if VMA_STATS_STRING_ENABLED +static const char* VmaAlgorithmToStr(uint32_t algorithm) +{ + switch (algorithm) + { + case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT: + return "Linear"; + case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT: + return "Buddy"; + case VMA_POOL_CREATE_TLSF_ALGORITHM_BIT: + return "TLSF"; + case 0: + return "Default"; + default: + VMA_ASSERT(0); + return ""; + } +} +#endif // VMA_STATS_STRING_ENABLED + +#ifndef VMA_SORT template Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp) { Iterator centerValue = end; --centerValue; Iterator insertIndex = beg; - for(Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex) + for (Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex) { - if(cmp(*memTypeIndex, *centerValue)) + if (cmp(*memTypeIndex, *centerValue)) { - if(insertIndex != memTypeIndex) + if (insertIndex != memTypeIndex) { VMA_SWAP(*memTypeIndex, *insertIndex); } ++insertIndex; } } - if(insertIndex != centerValue) + if (insertIndex != centerValue) { VMA_SWAP(*insertIndex, *centerValue); } @@ -1934,7 +3277,7 @@ Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp) template void VmaQuickSort(Iterator beg, Iterator end, Compare cmp) { - if(beg < end) + if (beg < end) { Iterator it = VmaQuickSortPartition(beg, end, cmp); VmaQuickSort(beg, it, cmp); @@ -1943,8 +3286,7 @@ void VmaQuickSort(Iterator beg, Iterator end, Compare cmp) } #define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp) - -#endif // #ifndef VMA_SORT +#endif // VMA_SORT /* Returns true if two memory blocks occupy overlapping pages. @@ -1967,17 +3309,6 @@ static inline bool VmaBlocksOnSamePage( return resourceAEndPage == resourceBStartPage; } -enum VmaSuballocationType -{ - VMA_SUBALLOCATION_TYPE_FREE = 0, - VMA_SUBALLOCATION_TYPE_UNKNOWN = 1, - VMA_SUBALLOCATION_TYPE_BUFFER = 2, - VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3, - VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4, - VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5, - VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF -}; - /* Returns true if given suballocation types could conflict and must respect VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer @@ -1988,12 +3319,12 @@ static inline bool VmaIsBufferImageGranularityConflict( VmaSuballocationType suballocType1, VmaSuballocationType suballocType2) { - if(suballocType1 > suballocType2) + if (suballocType1 > suballocType2) { VMA_SWAP(suballocType1, suballocType2); } - - switch(suballocType1) + + switch (suballocType1) { case VMA_SUBALLOCATION_TYPE_FREE: return false; @@ -2019,40 +3350,48 @@ static inline bool VmaIsBufferImageGranularityConflict( } } -// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope). -struct VmaMutexLock +static void VmaWriteMagicValue(void* pData, VkDeviceSize offset) { -public: - VmaMutexLock(VMA_MUTEX& mutex, bool useMutex) : - m_pMutex(useMutex ? &mutex : VMA_NULL) +#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION + uint32_t* pDst = (uint32_t*)((char*)pData + offset); + const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t); + for (size_t i = 0; i < numberCount; ++i, ++pDst) { - if(m_pMutex) - { - m_pMutex->Lock(); - } + *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE; } - - ~VmaMutexLock() - { - if(m_pMutex) - { - m_pMutex->Unlock(); - } - } - -private: - VMA_MUTEX* m_pMutex; -}; - -#if VMA_DEBUG_GLOBAL_MUTEX - static VMA_MUTEX gDebugGlobalMutex; - #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true); #else - #define VMA_DEBUG_GLOBAL_MUTEX_LOCK + // no-op #endif +} + +static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset) +{ +#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION + const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset); + const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t); + for (size_t i = 0; i < numberCount; ++i, ++pSrc) + { + if (*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE) + { + return false; + } + } +#endif + return true; +} + +/* +Fills structure with parameters of an example buffer to be used for transfers +during GPU memory defragmentation. +*/ +static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo) +{ + memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo)); + outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size. +} -// Minimum size of a free suballocation to register it in the free suballocation collection. -static const VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16; /* Performs binary search and returns iterator to first element that is greater or @@ -2063,23 +3402,69 @@ Cmp should return true if first argument is less than second argument. Returned value is the found element, if present in the collection or place where new element with value (key) should be inserted. */ -template -static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, CmpT cmp) +template +static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp) { - size_t down = 0, up = (end - beg); - while(down < up) - { - const size_t mid = (down + up) / 2; - if(cmp(*(beg+mid), key)) - { - down = mid + 1; - } - else - { - up = mid; - } - } - return beg + down; + size_t down = 0, up = (end - beg); + while (down < up) + { + const size_t mid = down + (up - down) / 2; // Overflow-safe midpoint calculation + if (cmp(*(beg + mid), key)) + { + down = mid + 1; + } + else + { + up = mid; + } + } + return beg + down; +} + +template +IterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value, const CmpLess& cmp) +{ + IterT it = VmaBinaryFindFirstNotLess( + beg, end, value, cmp); + if (it == end || + (!cmp(*it, value) && !cmp(value, *it))) + { + return it; + } + return end; +} + +/* +Returns true if all pointers in the array are not-null and unique. +Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT. +T must be pointer type, e.g. VmaAllocation, VmaPool. +*/ +template +static bool VmaValidatePointerArray(uint32_t count, const T* arr) +{ + for (uint32_t i = 0; i < count; ++i) + { + const T iPtr = arr[i]; + if (iPtr == VMA_NULL) + { + return false; + } + for (uint32_t j = i + 1; j < count; ++j) + { + if (iPtr == arr[j]) + { + return false; + } + } + } + return true; +} + +template +static inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct) +{ + newStruct->pNext = mainStruct->pNext; + mainStruct->pNext = newStruct; } //////////////////////////////////////////////////////////////////////////////// @@ -2087,10 +3472,11 @@ static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, Cm static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment) { - if((pAllocationCallbacks != VMA_NULL) && + void* result = VMA_NULL; + if ((pAllocationCallbacks != VMA_NULL) && (pAllocationCallbacks->pfnAllocation != VMA_NULL)) { - return (*pAllocationCallbacks->pfnAllocation)( + result = (*pAllocationCallbacks->pfnAllocation)( pAllocationCallbacks->pUserData, size, alignment, @@ -2098,20 +3484,22 @@ static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t } else { - return VMA_SYSTEM_ALIGNED_MALLOC(size, alignment); + result = VMA_SYSTEM_ALIGNED_MALLOC(size, alignment); } + VMA_ASSERT(result != VMA_NULL && "CPU memory allocation failed."); + return result; } static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr) { - if((pAllocationCallbacks != VMA_NULL) && + if ((pAllocationCallbacks != VMA_NULL) && (pAllocationCallbacks->pfnFree != VMA_NULL)) { (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr); } else { - VMA_SYSTEM_FREE(ptr); + VMA_SYSTEM_ALIGNED_FREE(ptr); } } @@ -2141,9 +3529,9 @@ static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr template static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count) { - if(ptr != VMA_NULL) + if (ptr != VMA_NULL) { - for(size_t i = count; i--; ) + for (size_t i = count; i--; ) { ptr[i].~T(); } @@ -2151,272 +3539,41 @@ static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, } } -// STL-compatible allocator. -template -class VmaStlAllocator +static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr) { -public: - const VkAllocationCallbacks* const m_pCallbacks; - typedef T value_type; - - VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { } - template VmaStlAllocator(const VmaStlAllocator& src) : m_pCallbacks(src.m_pCallbacks) { } - - T* allocate(size_t n) { return VmaAllocateArray(m_pCallbacks, n); } - void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); } - - template - bool operator==(const VmaStlAllocator& rhs) const + if (srcStr != VMA_NULL) { - return m_pCallbacks == rhs.m_pCallbacks; + const size_t len = strlen(srcStr); + char* const result = vma_new_array(allocs, char, len + 1); + memcpy(result, srcStr, len + 1); + return result; } - template - bool operator!=(const VmaStlAllocator& rhs) const - { - return m_pCallbacks != rhs.m_pCallbacks; - } - - VmaStlAllocator& operator=(const VmaStlAllocator& x) = delete; -}; - -#if VMA_USE_STL_VECTOR - -#define VmaVector std::vector - -template -static void VmaVectorInsert(std::vector& vec, size_t index, const T& item) -{ - vec.insert(vec.begin() + index, item); + return VMA_NULL; } -template -static void VmaVectorRemove(std::vector& vec, size_t index) +#if VMA_STATS_STRING_ENABLED +static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr, size_t strLen) { - vec.erase(vec.begin() + index); + if (srcStr != VMA_NULL) + { + char* const result = vma_new_array(allocs, char, strLen + 1); + memcpy(result, srcStr, strLen); + result[strLen] = '\0'; + return result; + } + return VMA_NULL; } +#endif // VMA_STATS_STRING_ENABLED -#else // #if VMA_USE_STL_VECTOR - -/* Class with interface compatible with subset of std::vector. -T must be POD because constructors and destructors are not called and memcpy is -used for these objects. */ -template -class VmaVector +static void VmaFreeString(const VkAllocationCallbacks* allocs, char* str) { -public: - typedef T value_type; - - VmaVector(const AllocatorT& allocator) : - m_Allocator(allocator), - m_pArray(VMA_NULL), - m_Count(0), - m_Capacity(0) + if (str != VMA_NULL) { + const size_t len = strlen(str); + vma_delete_array(allocs, str, len + 1); } - - VmaVector(size_t count, const AllocatorT& allocator) : - m_Allocator(allocator), - m_pArray(count ? (T*)VmaAllocateArray(allocator.m_pCallbacks, count) : VMA_NULL), - m_Count(count), - m_Capacity(count) - { - } - - VmaVector(const VmaVector& src) : - m_Allocator(src.m_Allocator), - m_pArray(src.m_Count ? (T*)VmaAllocateArray(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL), - m_Count(src.m_Count), - m_Capacity(src.m_Count) - { - if(m_Count != 0) - { - memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T)); - } - } - - ~VmaVector() - { - VmaFree(m_Allocator.m_pCallbacks, m_pArray); - } - - VmaVector& operator=(const VmaVector& rhs) - { - if(&rhs != this) - { - resize(rhs.m_Count); - if(m_Count != 0) - { - memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T)); - } - } - return *this; - } - - bool empty() const { return m_Count == 0; } - size_t size() const { return m_Count; } - T* data() { return m_pArray; } - const T* data() const { return m_pArray; } - - T& operator[](size_t index) - { - VMA_HEAVY_ASSERT(index < m_Count); - return m_pArray[index]; - } - const T& operator[](size_t index) const - { - VMA_HEAVY_ASSERT(index < m_Count); - return m_pArray[index]; - } - - T& front() - { - VMA_HEAVY_ASSERT(m_Count > 0); - return m_pArray[0]; - } - const T& front() const - { - VMA_HEAVY_ASSERT(m_Count > 0); - return m_pArray[0]; - } - T& back() - { - VMA_HEAVY_ASSERT(m_Count > 0); - return m_pArray[m_Count - 1]; - } - const T& back() const - { - VMA_HEAVY_ASSERT(m_Count > 0); - return m_pArray[m_Count - 1]; - } - - void reserve(size_t newCapacity, bool freeMemory = false) - { - newCapacity = VMA_MAX(newCapacity, m_Count); - - if((newCapacity < m_Capacity) && !freeMemory) - { - newCapacity = m_Capacity; - } - - if(newCapacity != m_Capacity) - { - T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator, newCapacity) : VMA_NULL; - if(m_Count != 0) - { - memcpy(newArray, m_pArray, m_Count * sizeof(T)); - } - VmaFree(m_Allocator.m_pCallbacks, m_pArray); - m_Capacity = newCapacity; - m_pArray = newArray; - } - } - - void resize(size_t newCount, bool freeMemory = false) - { - size_t newCapacity = m_Capacity; - if(newCount > m_Capacity) - { - newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8)); - } - else if(freeMemory) - { - newCapacity = newCount; - } - - if(newCapacity != m_Capacity) - { - T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL; - const size_t elementsToCopy = VMA_MIN(m_Count, newCount); - if(elementsToCopy != 0) - { - memcpy(newArray, m_pArray, elementsToCopy * sizeof(T)); - } - VmaFree(m_Allocator.m_pCallbacks, m_pArray); - m_Capacity = newCapacity; - m_pArray = newArray; - } - - m_Count = newCount; - } - - void clear(bool freeMemory = false) - { - resize(0, freeMemory); - } - - void insert(size_t index, const T& src) - { - VMA_HEAVY_ASSERT(index <= m_Count); - const size_t oldCount = size(); - resize(oldCount + 1); - if(index < oldCount) - { - memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T)); - } - m_pArray[index] = src; - } - - void remove(size_t index) - { - VMA_HEAVY_ASSERT(index < m_Count); - const size_t oldCount = size(); - if(index < oldCount - 1) - { - memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T)); - } - resize(oldCount - 1); - } - - void push_back(const T& src) - { - const size_t newIndex = size(); - resize(newIndex + 1); - m_pArray[newIndex] = src; - } - - void pop_back() - { - VMA_HEAVY_ASSERT(m_Count > 0); - resize(size() - 1); - } - - void push_front(const T& src) - { - insert(0, src); - } - - void pop_front() - { - VMA_HEAVY_ASSERT(m_Count > 0); - remove(0); - } - - typedef T* iterator; - - iterator begin() { return m_pArray; } - iterator end() { return m_pArray + m_Count; } - -private: - AllocatorT m_Allocator; - T* m_pArray; - size_t m_Count; - size_t m_Capacity; -}; - -template -static void VmaVectorInsert(VmaVector& vec, size_t index, const T& item) -{ - vec.insert(index, item); } -template -static void VmaVectorRemove(VmaVector& vec, size_t index) -{ - vec.remove(index); -} - -#endif // #if VMA_USE_STL_VECTOR - template size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value) { @@ -2438,7 +3595,7 @@ bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& vector.end(), value, comparator); - if((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it)) + if ((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it)) { size_t indexToRemove = it - vector.begin(); VmaVectorRemove(vector, indexToRemove); @@ -2446,29 +3603,550 @@ bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& } return false; } +#endif // _VMA_FUNCTIONS -template -size_t VmaVectorFindSorted(const VectorT& vector, const typename VectorT::value_type& value) +#ifndef _VMA_STAT_INFO_FUNCTIONS +static void VmaInitStatInfo(VmaStatInfo& outInfo) { - CmpLess comparator; - typename VectorT::iterator it = VmaBinaryFindFirstNotLess( - vector.data(), - vector.data() + vector.size(), - value, - comparator); - if(it != vector.size() && !comparator(*it, value) && !comparator(value, *it)) + memset(&outInfo, 0, sizeof(outInfo)); + outInfo.allocationSizeMin = UINT64_MAX; + outInfo.unusedRangeSizeMin = UINT64_MAX; +} + +// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo. +static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo) +{ + inoutInfo.blockCount += srcInfo.blockCount; + inoutInfo.allocationCount += srcInfo.allocationCount; + inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount; + inoutInfo.usedBytes += srcInfo.usedBytes; + inoutInfo.unusedBytes += srcInfo.unusedBytes; + inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin); + inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax); + inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin); + inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax); +} + +static void VmaAddStatInfoAllocation(VmaStatInfo& inoutInfo, VkDeviceSize size) +{ + ++inoutInfo.allocationCount; + inoutInfo.usedBytes += size; + if (size < inoutInfo.allocationSizeMin) { - return it - vector.begin(); + inoutInfo.allocationSizeMin = size; } - else + if (size > inoutInfo.allocationSizeMax) { - return vector.size(); + inoutInfo.allocationSizeMax = size; } } -//////////////////////////////////////////////////////////////////////////////// -// class VmaPoolAllocator +static void VmaAddStatInfoUnusedRange(VmaStatInfo& inoutInfo, VkDeviceSize size) +{ + ++inoutInfo.unusedRangeCount; + inoutInfo.unusedBytes += size; + if (size < inoutInfo.unusedRangeSizeMin) + { + inoutInfo.unusedRangeSizeMin = size; + } + if (size > inoutInfo.unusedRangeSizeMax) + { + inoutInfo.unusedRangeSizeMax = size; + } +} +static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo) +{ + inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ? + VmaRoundDiv(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0; + inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ? + VmaRoundDiv(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0; +} +#endif // _VMA_STAT_INFO_FUNCTIONS + + +#ifndef _VMA_MUTEX_LOCK +// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope). +struct VmaMutexLock +{ + VMA_CLASS_NO_COPY(VmaMutexLock) +public: + VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) : + m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->Lock(); } + } + ~VmaMutexLock() { if (m_pMutex) { m_pMutex->Unlock(); } } + +private: + VMA_MUTEX* m_pMutex; +}; + +// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading. +struct VmaMutexLockRead +{ + VMA_CLASS_NO_COPY(VmaMutexLockRead) +public: + VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) : + m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->LockRead(); } + } + ~VmaMutexLockRead() { if (m_pMutex) { m_pMutex->UnlockRead(); } } + +private: + VMA_RW_MUTEX* m_pMutex; +}; + +// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing. +struct VmaMutexLockWrite +{ + VMA_CLASS_NO_COPY(VmaMutexLockWrite) +public: + VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) + : m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->LockWrite(); } + } + ~VmaMutexLockWrite() { if (m_pMutex) { m_pMutex->UnlockWrite(); } } + +private: + VMA_RW_MUTEX* m_pMutex; +}; + +#if VMA_DEBUG_GLOBAL_MUTEX + static VMA_MUTEX gDebugGlobalMutex; + #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true); +#else + #define VMA_DEBUG_GLOBAL_MUTEX_LOCK +#endif +#endif // _VMA_MUTEX_LOCK + +#ifndef _VMA_ATOMIC_TRANSACTIONAL_INCREMENT +// An object that increments given atomic but decrements it back in the destructor unless Commit() is called. +template +struct AtomicTransactionalIncrement +{ +public: + typedef std::atomic AtomicT; + + ~AtomicTransactionalIncrement() + { + if(m_Atomic) + --(*m_Atomic); + } + + void Commit() { m_Atomic = nullptr; } + T Increment(AtomicT* atomic) + { + m_Atomic = atomic; + return m_Atomic->fetch_add(1); + } + +private: + AtomicT* m_Atomic = nullptr; +}; +#endif // _VMA_ATOMIC_TRANSACTIONAL_INCREMENT + +#ifndef _VMA_STL_ALLOCATOR +// STL-compatible allocator. +template +struct VmaStlAllocator +{ + const VkAllocationCallbacks* const m_pCallbacks; + typedef T value_type; + + VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) {} + template + VmaStlAllocator(const VmaStlAllocator& src) : m_pCallbacks(src.m_pCallbacks) {} + VmaStlAllocator(const VmaStlAllocator&) = default; + VmaStlAllocator& operator=(const VmaStlAllocator&) = delete; + + T* allocate(size_t n) { return VmaAllocateArray(m_pCallbacks, n); } + void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); } + + template + bool operator==(const VmaStlAllocator& rhs) const + { + return m_pCallbacks == rhs.m_pCallbacks; + } + template + bool operator!=(const VmaStlAllocator& rhs) const + { + return m_pCallbacks != rhs.m_pCallbacks; + } +}; +#endif // _VMA_STL_ALLOCATOR + +#ifndef _VMA_VECTOR +/* Class with interface compatible with subset of std::vector. +T must be POD because constructors and destructors are not called and memcpy is +used for these objects. */ +template +class VmaVector +{ +public: + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + VmaVector(const AllocatorT& allocator); + VmaVector(size_t count, const AllocatorT& allocator); + // This version of the constructor is here for compatibility with pre-C++14 std::vector. + // value is unused. + VmaVector(size_t count, const T& value, const AllocatorT& allocator) : VmaVector(count, allocator) {} + VmaVector(const VmaVector& src); + VmaVector& operator=(const VmaVector& rhs); + ~VmaVector() { VmaFree(m_Allocator.m_pCallbacks, m_pArray); } + + bool empty() const { return m_Count == 0; } + size_t size() const { return m_Count; } + T* data() { return m_pArray; } + T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; } + T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; } + const T* data() const { return m_pArray; } + const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; } + const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; } + + iterator begin() { return m_pArray; } + iterator end() { return m_pArray + m_Count; } + const_iterator cbegin() const { return m_pArray; } + const_iterator cend() const { return m_pArray + m_Count; } + const_iterator begin() const { return cbegin(); } + const_iterator end() const { return cend(); } + + void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); } + void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); } + void push_front(const T& src) { insert(0, src); } + + void push_back(const T& src); + void reserve(size_t newCapacity, bool freeMemory = false); + void resize(size_t newCount); + void clear() { resize(0); } + void shrink_to_fit(); + void insert(size_t index, const T& src); + void remove(size_t index); + + T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; } + const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; } + +private: + AllocatorT m_Allocator; + T* m_pArray; + size_t m_Count; + size_t m_Capacity; +}; + +#ifndef _VMA_VECTOR_FUNCTIONS +template +VmaVector::VmaVector(const AllocatorT& allocator) + : m_Allocator(allocator), + m_pArray(VMA_NULL), + m_Count(0), + m_Capacity(0) {} + +template +VmaVector::VmaVector(size_t count, const AllocatorT& allocator) + : m_Allocator(allocator), + m_pArray(count ? (T*)VmaAllocateArray(allocator.m_pCallbacks, count) : VMA_NULL), + m_Count(count), + m_Capacity(count) {} + +template +VmaVector::VmaVector(const VmaVector& src) + : m_Allocator(src.m_Allocator), + m_pArray(src.m_Count ? (T*)VmaAllocateArray(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL), + m_Count(src.m_Count), + m_Capacity(src.m_Count) +{ + if (m_Count != 0) + { + memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T)); + } +} + +template +VmaVector& VmaVector::operator=(const VmaVector& rhs) +{ + if (&rhs != this) + { + resize(rhs.m_Count); + if (m_Count != 0) + { + memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T)); + } + } + return *this; +} + +template +void VmaVector::push_back(const T& src) +{ + const size_t newIndex = size(); + resize(newIndex + 1); + m_pArray[newIndex] = src; +} + +template +void VmaVector::reserve(size_t newCapacity, bool freeMemory) +{ + newCapacity = VMA_MAX(newCapacity, m_Count); + + if ((newCapacity < m_Capacity) && !freeMemory) + { + newCapacity = m_Capacity; + } + + if (newCapacity != m_Capacity) + { + T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator, newCapacity) : VMA_NULL; + if (m_Count != 0) + { + memcpy(newArray, m_pArray, m_Count * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = newCapacity; + m_pArray = newArray; + } +} + +template +void VmaVector::resize(size_t newCount) +{ + size_t newCapacity = m_Capacity; + if (newCount > m_Capacity) + { + newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8)); + } + + if (newCapacity != m_Capacity) + { + T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL; + const size_t elementsToCopy = VMA_MIN(m_Count, newCount); + if (elementsToCopy != 0) + { + memcpy(newArray, m_pArray, elementsToCopy * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = newCapacity; + m_pArray = newArray; + } + + m_Count = newCount; +} + +template +void VmaVector::shrink_to_fit() +{ + if (m_Capacity > m_Count) + { + T* newArray = VMA_NULL; + if (m_Count > 0) + { + newArray = VmaAllocateArray(m_Allocator.m_pCallbacks, m_Count); + memcpy(newArray, m_pArray, m_Count * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = m_Count; + m_pArray = newArray; + } +} + +template +void VmaVector::insert(size_t index, const T& src) +{ + VMA_HEAVY_ASSERT(index <= m_Count); + const size_t oldCount = size(); + resize(oldCount + 1); + if (index < oldCount) + { + memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T)); + } + m_pArray[index] = src; +} + +template +void VmaVector::remove(size_t index) +{ + VMA_HEAVY_ASSERT(index < m_Count); + const size_t oldCount = size(); + if (index < oldCount - 1) + { + memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T)); + } + resize(oldCount - 1); +} +#endif // _VMA_VECTOR_FUNCTIONS + +template +static void VmaVectorInsert(VmaVector& vec, size_t index, const T& item) +{ + vec.insert(index, item); +} + +template +static void VmaVectorRemove(VmaVector& vec, size_t index) +{ + vec.remove(index); +} +#endif // _VMA_VECTOR + +#ifndef _VMA_SMALL_VECTOR +/* +This is a vector (a variable-sized array), optimized for the case when the array is small. + +It contains some number of elements in-place, which allows it to avoid heap allocation +when the actual number of elements is below that threshold. This allows normal "small" +cases to be fast without losing generality for large inputs. +*/ +template +class VmaSmallVector +{ +public: + typedef T value_type; + typedef T* iterator; + + VmaSmallVector(const AllocatorT& allocator); + VmaSmallVector(size_t count, const AllocatorT& allocator); + template + VmaSmallVector(const VmaSmallVector&) = delete; + template + VmaSmallVector& operator=(const VmaSmallVector&) = delete; + ~VmaSmallVector() = default; + + bool empty() const { return m_Count == 0; } + size_t size() const { return m_Count; } + T* data() { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; } + T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; } + T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; } + const T* data() const { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; } + const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; } + const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; } + + iterator begin() { return data(); } + iterator end() { return data() + m_Count; } + + void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); } + void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); } + void push_front(const T& src) { insert(0, src); } + + void push_back(const T& src); + void resize(size_t newCount, bool freeMemory = false); + void clear(bool freeMemory = false); + void insert(size_t index, const T& src); + void remove(size_t index); + + T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; } + const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; } + +private: + size_t m_Count; + T m_StaticArray[N]; // Used when m_Size <= N + VmaVector m_DynamicArray; // Used when m_Size > N +}; + +#ifndef _VMA_SMALL_VECTOR_FUNCTIONS +template +VmaSmallVector::VmaSmallVector(const AllocatorT& allocator) + : m_Count(0), + m_DynamicArray(allocator) {} + +template +VmaSmallVector::VmaSmallVector(size_t count, const AllocatorT& allocator) + : m_Count(count), + m_DynamicArray(count > N ? count : 0, allocator) {} + +template +void VmaSmallVector::push_back(const T& src) +{ + resize(m_Count + 1); + data()[m_Count] = src; +} + +template +void VmaSmallVector::resize(size_t newCount, bool freeMemory) +{ + if (newCount > N && m_Count > N) + { + // Any direction, staying in m_DynamicArray + m_DynamicArray.resize(newCount); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + } + else if (newCount > N && m_Count <= N) + { + // Growing, moving from m_StaticArray to m_DynamicArray + m_DynamicArray.resize(newCount); + if (m_Count > 0) + { + memcpy(m_DynamicArray.data(), m_StaticArray, m_Count * sizeof(T)); + } + } + else if (newCount <= N && m_Count > N) + { + // Shrinking, moving from m_DynamicArray to m_StaticArray + if (newCount > 0) + { + memcpy(m_StaticArray, m_DynamicArray.data(), newCount * sizeof(T)); + } + m_DynamicArray.resize(0); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + } + else + { + // Any direction, staying in m_StaticArray - nothing to do here + } + m_Count = newCount; +} + +template +void VmaSmallVector::clear(bool freeMemory) +{ + m_DynamicArray.clear(); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + m_Count = 0; +} + +template +void VmaSmallVector::insert(size_t index, const T& src) +{ + VMA_HEAVY_ASSERT(index <= m_Count); + const size_t oldCount = size(); + resize(oldCount + 1); + T* const dataPtr = data(); + if (index < oldCount) + { + // I know, this could be more optimal for case where memmove can be memcpy directly from m_StaticArray to m_DynamicArray. + memmove(dataPtr + (index + 1), dataPtr + index, (oldCount - index) * sizeof(T)); + } + dataPtr[index] = src; +} + +template +void VmaSmallVector::remove(size_t index) +{ + VMA_HEAVY_ASSERT(index < m_Count); + const size_t oldCount = size(); + if (index < oldCount - 1) + { + // I know, this could be more optimal for case where memmove can be memcpy directly from m_DynamicArray to m_StaticArray. + T* const dataPtr = data(); + memmove(dataPtr + index, dataPtr + (index + 1), (oldCount - index - 1) * sizeof(T)); + } + resize(oldCount - 1); +} +#endif // _VMA_SMALL_VECTOR_FUNCTIONS +#endif // _VMA_SMALL_VECTOR + +#ifndef _VMA_POOL_ALLOCATOR /* Allocator for objects of type T using a list of arrays (pools) to speed up allocation. Number of elements that can be allocated is not bounded because @@ -2477,68 +4155,65 @@ allocator can create multiple blocks. template class VmaPoolAllocator { + VMA_CLASS_NO_COPY(VmaPoolAllocator) public: - VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, size_t itemsPerBlock); + VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity); ~VmaPoolAllocator(); - void Clear(); - T* Alloc(); + template T* Alloc(Types&&... args); void Free(T* ptr); private: union Item { uint32_t NextFreeIndex; - T Value; + alignas(T) char Value[sizeof(T)]; }; - struct ItemBlock { Item* pItems; + uint32_t Capacity; uint32_t FirstFreeIndex; }; - + const VkAllocationCallbacks* m_pAllocationCallbacks; - size_t m_ItemsPerBlock; - VmaVector< ItemBlock, VmaStlAllocator > m_ItemBlocks; + const uint32_t m_FirstBlockCapacity; + VmaVector> m_ItemBlocks; ItemBlock& CreateNewBlock(); }; +#ifndef _VMA_POOL_ALLOCATOR_FUNCTIONS template -VmaPoolAllocator::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, size_t itemsPerBlock) : - m_pAllocationCallbacks(pAllocationCallbacks), - m_ItemsPerBlock(itemsPerBlock), +VmaPoolAllocator::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) + : m_pAllocationCallbacks(pAllocationCallbacks), + m_FirstBlockCapacity(firstBlockCapacity), m_ItemBlocks(VmaStlAllocator(pAllocationCallbacks)) { - VMA_ASSERT(itemsPerBlock > 0); + VMA_ASSERT(m_FirstBlockCapacity > 1); } template VmaPoolAllocator::~VmaPoolAllocator() { - Clear(); -} - -template -void VmaPoolAllocator::Clear() -{ - for(size_t i = m_ItemBlocks.size(); i--; ) - vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemsPerBlock); + for (size_t i = m_ItemBlocks.size(); i--;) + vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity); m_ItemBlocks.clear(); } template -T* VmaPoolAllocator::Alloc() +template T* VmaPoolAllocator::Alloc(Types&&... args) { - for(size_t i = m_ItemBlocks.size(); i--; ) + for (size_t i = m_ItemBlocks.size(); i--; ) { ItemBlock& block = m_ItemBlocks[i]; // This block has some free items: Use first one. - if(block.FirstFreeIndex != UINT32_MAX) + if (block.FirstFreeIndex != UINT32_MAX) { Item* const pItem = &block.pItems[block.FirstFreeIndex]; block.FirstFreeIndex = pItem->NextFreeIndex; - return &pItem->Value; + T* result = (T*)&pItem->Value; + new(result)T(std::forward(args)...); // Explicit constructor call. + return result; } } @@ -2546,24 +4221,27 @@ T* VmaPoolAllocator::Alloc() ItemBlock& newBlock = CreateNewBlock(); Item* const pItem = &newBlock.pItems[0]; newBlock.FirstFreeIndex = pItem->NextFreeIndex; - return &pItem->Value; + T* result = (T*)&pItem->Value; + new(result) T(std::forward(args)...); // Explicit constructor call. + return result; } template void VmaPoolAllocator::Free(T* ptr) { // Search all memory blocks to find ptr. - for(size_t i = 0; i < m_ItemBlocks.size(); ++i) + for (size_t i = m_ItemBlocks.size(); i--; ) { ItemBlock& block = m_ItemBlocks[i]; - + // Casting to union. Item* pItemPtr; memcpy(&pItemPtr, &ptr, sizeof(pItemPtr)); - + // Check if pItemPtr is in address range of this block. - if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + m_ItemsPerBlock)) + if ((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity)) { + ptr->~T(); // Explicit destructor call. const uint32_t index = static_cast(pItemPtr - block.pItems); pItemPtr->NextFreeIndex = block.FirstFreeIndex; block.FirstFreeIndex = index; @@ -2576,27 +4254,28 @@ void VmaPoolAllocator::Free(T* ptr) template typename VmaPoolAllocator::ItemBlock& VmaPoolAllocator::CreateNewBlock() { - ItemBlock newBlock = { - vma_new_array(m_pAllocationCallbacks, Item, m_ItemsPerBlock), 0 }; + const uint32_t newBlockCapacity = m_ItemBlocks.empty() ? + m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2; + + const ItemBlock newBlock = + { + vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity), + newBlockCapacity, + 0 + }; m_ItemBlocks.push_back(newBlock); // Setup singly-linked list of all free items in this block. - for(uint32_t i = 0; i < m_ItemsPerBlock - 1; ++i) + for (uint32_t i = 0; i < newBlockCapacity - 1; ++i) newBlock.pItems[i].NextFreeIndex = i + 1; - newBlock.pItems[m_ItemsPerBlock - 1].NextFreeIndex = UINT32_MAX; + newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX; return m_ItemBlocks.back(); } +#endif // _VMA_POOL_ALLOCATOR_FUNCTIONS +#endif // _VMA_POOL_ALLOCATOR -//////////////////////////////////////////////////////////////////////////////// -// class VmaRawList, VmaList - -#if VMA_USE_STL_LIST - -#define VmaList std::list - -#else // #if VMA_USE_STL_LIST - +#ifndef _VMA_RAW_LIST template struct VmaListItem { @@ -2609,36 +4288,38 @@ struct VmaListItem template class VmaRawList { + VMA_CLASS_NO_COPY(VmaRawList) public: typedef VmaListItem ItemType; VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks); - ~VmaRawList(); - void Clear(); + // Intentionally not calling Clear, because that would be unnecessary + // computations to return all items to m_ItemAllocator as free. + ~VmaRawList() = default; size_t GetCount() const { return m_Count; } bool IsEmpty() const { return m_Count == 0; } ItemType* Front() { return m_pFront; } - const ItemType* Front() const { return m_pFront; } ItemType* Back() { return m_pBack; } + const ItemType* Front() const { return m_pFront; } const ItemType* Back() const { return m_pBack; } - ItemType* PushBack(); ItemType* PushFront(); - ItemType* PushBack(const T& value); + ItemType* PushBack(); ItemType* PushFront(const T& value); - void PopBack(); + ItemType* PushBack(const T& value); void PopFront(); - + void PopBack(); + // Item can be null - it means PushBack. ItemType* InsertBefore(ItemType* pItem); // Item can be null - it means PushFront. ItemType* InsertAfter(ItemType* pItem); - ItemType* InsertBefore(ItemType* pItem, const T& value); ItemType* InsertAfter(ItemType* pItem, const T& value); + void Clear(); void Remove(ItemType* pItem); private: @@ -2647,45 +4328,37 @@ private: ItemType* m_pFront; ItemType* m_pBack; size_t m_Count; - - // Declared not defined, to block copy constructor and assignment operator. - VmaRawList(const VmaRawList& src); - VmaRawList& operator=(const VmaRawList& rhs); }; +#ifndef _VMA_RAW_LIST_FUNCTIONS template -VmaRawList::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) : - m_pAllocationCallbacks(pAllocationCallbacks), +VmaRawList::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) + : m_pAllocationCallbacks(pAllocationCallbacks), m_ItemAllocator(pAllocationCallbacks, 128), m_pFront(VMA_NULL), m_pBack(VMA_NULL), - m_Count(0) -{ -} + m_Count(0) {} template -VmaRawList::~VmaRawList() +VmaListItem* VmaRawList::PushFront() { - // Intentionally not calling Clear, because that would be unnecessary - // computations to return all items to m_ItemAllocator as free. -} - -template -void VmaRawList::Clear() -{ - if(IsEmpty() == false) + ItemType* const pNewItem = m_ItemAllocator.Alloc(); + pNewItem->pPrev = VMA_NULL; + if (IsEmpty()) { - ItemType* pItem = m_pBack; - while(pItem != VMA_NULL) - { - ItemType* const pPrevItem = pItem->pPrev; - m_ItemAllocator.Free(pItem); - pItem = pPrevItem; - } - m_pFront = VMA_NULL; - m_pBack = VMA_NULL; - m_Count = 0; + pNewItem->pNext = VMA_NULL; + m_pFront = pNewItem; + m_pBack = pNewItem; + m_Count = 1; } + else + { + pNewItem->pNext = m_pFront; + m_pFront->pPrev = pNewItem; + m_pFront = pNewItem; + ++m_Count; + } + return pNewItem; } template @@ -2711,24 +4384,10 @@ VmaListItem* VmaRawList::PushBack() } template -VmaListItem* VmaRawList::PushFront() +VmaListItem* VmaRawList::PushFront(const T& value) { - ItemType* const pNewItem = m_ItemAllocator.Alloc(); - pNewItem->pPrev = VMA_NULL; - if(IsEmpty()) - { - pNewItem->pNext = VMA_NULL; - m_pFront = pNewItem; - m_pBack = pNewItem; - m_Count = 1; - } - else - { - pNewItem->pNext = m_pFront; - m_pFront->pPrev = pNewItem; - m_pFront = pNewItem; - ++m_Count; - } + ItemType* const pNewItem = PushFront(); + pNewItem->Value = value; return pNewItem; } @@ -2741,11 +4400,18 @@ VmaListItem* VmaRawList::PushBack(const T& value) } template -VmaListItem* VmaRawList::PushFront(const T& value) +void VmaRawList::PopFront() { - ItemType* const pNewItem = PushFront(); - pNewItem->Value = value; - return pNewItem; + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const pFrontItem = m_pFront; + ItemType* const pNextItem = pFrontItem->pNext; + if (pNextItem != VMA_NULL) + { + pNextItem->pPrev = VMA_NULL; + } + m_pFront = pNextItem; + m_ItemAllocator.Free(pFrontItem); + --m_Count; } template @@ -2764,18 +4430,21 @@ void VmaRawList::PopBack() } template -void VmaRawList::PopFront() +void VmaRawList::Clear() { - VMA_HEAVY_ASSERT(m_Count > 0); - ItemType* const pFrontItem = m_pFront; - ItemType* const pNextItem = pFrontItem->pNext; - if(pNextItem != VMA_NULL) + if (IsEmpty() == false) { - pNextItem->pPrev = VMA_NULL; + ItemType* pItem = m_pBack; + while (pItem != VMA_NULL) + { + ItemType* const pPrevItem = pItem->pPrev; + m_ItemAllocator.Free(pItem); + pItem = pPrevItem; + } + m_pFront = VMA_NULL; + m_pBack = VMA_NULL; + m_Count = 0; } - m_pFront = pNextItem; - m_ItemAllocator.Free(pFrontItem); - --m_Count; } template @@ -2875,172 +4544,123 @@ VmaListItem* VmaRawList::InsertAfter(ItemType* pItem, const T& value) newItem->Value = value; return newItem; } +#endif // _VMA_RAW_LIST_FUNCTIONS +#endif // _VMA_RAW_LIST +#ifndef _VMA_LIST template class VmaList { + VMA_CLASS_NO_COPY(VmaList) public: + class reverse_iterator; + class const_iterator; + class const_reverse_iterator; + class iterator { + friend class VmaList; public: - iterator() : - m_pList(VMA_NULL), - m_pItem(VMA_NULL) - { - } + iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} - T& operator*() const - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - return m_pItem->Value; - } - T* operator->() const - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - return &m_pItem->Value; - } + T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } - iterator& operator++() - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - m_pItem = m_pItem->pNext; - return *this; - } - iterator& operator--() - { - if(m_pItem != VMA_NULL) - { - m_pItem = m_pItem->pPrev; - } - else - { - VMA_HEAVY_ASSERT(!m_pList.IsEmpty()); - m_pItem = m_pList->Back(); - } - return *this; - } + bool operator==(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } - iterator operator++(int) - { - iterator result = *this; - ++*this; - return result; - } - iterator operator--(int) - { - iterator result = *this; - --*this; - return result; - } + iterator operator++(int) { iterator result = *this; ++*this; return result; } + iterator operator--(int) { iterator result = *this; --*this; return result; } + + iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; } + iterator& operator--(); - bool operator==(const iterator& rhs) const - { - VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); - return m_pItem == rhs.m_pItem; - } - bool operator!=(const iterator& rhs) const - { - VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); - return m_pItem != rhs.m_pItem; - } - private: VmaRawList* m_pList; VmaListItem* m_pItem; - iterator(VmaRawList* pList, VmaListItem* pItem) : - m_pList(pList), - m_pItem(pItem) - { - } - - friend class VmaList; + iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} }; + class reverse_iterator + { + friend class VmaList; + public: + reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + reverse_iterator operator++(int) { reverse_iterator result = *this; ++* this; return result; } + reverse_iterator operator--(int) { reverse_iterator result = *this; --* this; return result; } + + reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } + reverse_iterator& operator--(); + + private: + VmaRawList* m_pList; + VmaListItem* m_pItem; + + reverse_iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; class const_iterator { + friend class VmaList; public: - const_iterator() : - m_pList(VMA_NULL), - m_pItem(VMA_NULL) - { - } + const_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + const_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + const_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} - const_iterator(const iterator& src) : - m_pList(src.m_pList), - m_pItem(src.m_pItem) - { - } - - const T& operator*() const - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - return m_pItem->Value; - } - const T* operator->() const - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - return &m_pItem->Value; - } + const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } - const_iterator& operator++() - { - VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); - m_pItem = m_pItem->pNext; - return *this; - } - const_iterator& operator--() - { - if(m_pItem != VMA_NULL) - { - m_pItem = m_pItem->pPrev; - } - else - { - VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); - m_pItem = m_pList->Back(); - } - return *this; - } + bool operator==(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } - const_iterator operator++(int) - { - const_iterator result = *this; - ++*this; - return result; - } - const_iterator operator--(int) - { - const_iterator result = *this; - --*this; - return result; - } + const_iterator operator++(int) { const_iterator result = *this; ++* this; return result; } + const_iterator operator--(int) { const_iterator result = *this; --* this; return result; } + + const_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; } + const_iterator& operator--(); - bool operator==(const const_iterator& rhs) const - { - VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); - return m_pItem == rhs.m_pItem; - } - bool operator!=(const const_iterator& rhs) const - { - VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); - return m_pItem != rhs.m_pItem; - } - private: - const_iterator(const VmaRawList* pList, const VmaListItem* pItem) : - m_pList(pList), - m_pItem(pItem) - { - } - const VmaRawList* m_pList; const VmaListItem* m_pItem; + const_iterator(const VmaRawList* pList, const VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; + class const_reverse_iterator + { friend class VmaList; + public: + const_reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + const_reverse_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + const_reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + + const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++* this; return result; } + const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --* this; return result; } + + const_reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } + const_reverse_iterator& operator--(); + + private: + const VmaRawList* m_pList; + const VmaListItem* m_pItem; + + const_reverse_iterator(const VmaRawList* pList, const VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} }; - VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) { } + VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) {} bool empty() const { return m_RawList.IsEmpty(); } size_t size() const { return m_RawList.GetCount(); } @@ -3051,67 +4671,353 @@ public: const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); } const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); } - void clear() { m_RawList.Clear(); } + const_iterator begin() const { return cbegin(); } + const_iterator end() const { return cend(); } + + reverse_iterator rbegin() { return reverse_iterator(&m_RawList, m_RawList.Back()); } + reverse_iterator rend() { return reverse_iterator(&m_RawList, VMA_NULL); } + + const_reverse_iterator crbegin() { return const_reverse_iterator(&m_RawList, m_RawList.Back()); } + const_reverse_iterator crend() { return const_reverse_iterator(&m_RawList, VMA_NULL); } + + const_reverse_iterator rbegin() const { return crbegin(); } + const_reverse_iterator rend() const { return crend(); } + void push_back(const T& value) { m_RawList.PushBack(value); } - void erase(iterator it) { m_RawList.Remove(it.m_pItem); } iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); } + void clear() { m_RawList.Clear(); } + void erase(iterator it) { m_RawList.Remove(it.m_pItem); } + private: VmaRawList m_RawList; }; -#endif // #if VMA_USE_STL_LIST +#ifndef _VMA_LIST_FUNCTIONS +template +typename VmaList::iterator& VmaList::iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pPrev; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} -//////////////////////////////////////////////////////////////////////////////// -// class VmaMap +template +typename VmaList::reverse_iterator& VmaList::reverse_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pNext; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Front(); + } + return *this; +} + +template +typename VmaList::const_iterator& VmaList::const_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pPrev; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} + +template +typename VmaList::const_reverse_iterator& VmaList::const_reverse_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pNext; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} +#endif // _VMA_LIST_FUNCTIONS +#endif // _VMA_LIST + +#ifndef _VMA_INTRUSIVE_LINKED_LIST +/* +Expected interface of ItemTypeTraits: +struct MyItemTypeTraits +{ + typedef MyItem ItemType; + static ItemType* GetPrev(const ItemType* item) { return item->myPrevPtr; } + static ItemType* GetNext(const ItemType* item) { return item->myNextPtr; } + static ItemType*& AccessPrev(ItemType* item) { return item->myPrevPtr; } + static ItemType*& AccessNext(ItemType* item) { return item->myNextPtr; } +}; +*/ +template +class VmaIntrusiveLinkedList +{ +public: + typedef typename ItemTypeTraits::ItemType ItemType; + static ItemType* GetPrev(const ItemType* item) { return ItemTypeTraits::GetPrev(item); } + static ItemType* GetNext(const ItemType* item) { return ItemTypeTraits::GetNext(item); } + + // Movable, not copyable. + VmaIntrusiveLinkedList() = default; + VmaIntrusiveLinkedList(VmaIntrusiveLinkedList && src); + VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList&) = delete; + VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src); + VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete; + ~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); } + + size_t GetCount() const { return m_Count; } + bool IsEmpty() const { return m_Count == 0; } + ItemType* Front() { return m_Front; } + ItemType* Back() { return m_Back; } + const ItemType* Front() const { return m_Front; } + const ItemType* Back() const { return m_Back; } + + void PushBack(ItemType* item); + void PushFront(ItemType* item); + ItemType* PopBack(); + ItemType* PopFront(); + + // MyItem can be null - it means PushBack. + void InsertBefore(ItemType* existingItem, ItemType* newItem); + // MyItem can be null - it means PushFront. + void InsertAfter(ItemType* existingItem, ItemType* newItem); + void Remove(ItemType* item); + void RemoveAll(); + +private: + ItemType* m_Front = VMA_NULL; + ItemType* m_Back = VMA_NULL; + size_t m_Count = 0; +}; + +#ifndef _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS +template +VmaIntrusiveLinkedList::VmaIntrusiveLinkedList(VmaIntrusiveLinkedList&& src) + : m_Front(src.m_Front), m_Back(src.m_Back), m_Count(src.m_Count) +{ + src.m_Front = src.m_Back = VMA_NULL; + src.m_Count = 0; +} + +template +VmaIntrusiveLinkedList& VmaIntrusiveLinkedList::operator=(VmaIntrusiveLinkedList&& src) +{ + if (&src != this) + { + VMA_HEAVY_ASSERT(IsEmpty()); + m_Front = src.m_Front; + m_Back = src.m_Back; + m_Count = src.m_Count; + src.m_Front = src.m_Back = VMA_NULL; + src.m_Count = 0; + } + return *this; +} + +template +void VmaIntrusiveLinkedList::PushBack(ItemType* item) +{ + VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL); + if (IsEmpty()) + { + m_Front = item; + m_Back = item; + m_Count = 1; + } + else + { + ItemTypeTraits::AccessPrev(item) = m_Back; + ItemTypeTraits::AccessNext(m_Back) = item; + m_Back = item; + ++m_Count; + } +} + +template +void VmaIntrusiveLinkedList::PushFront(ItemType* item) +{ + VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL); + if (IsEmpty()) + { + m_Front = item; + m_Back = item; + m_Count = 1; + } + else + { + ItemTypeTraits::AccessNext(item) = m_Front; + ItemTypeTraits::AccessPrev(m_Front) = item; + m_Front = item; + ++m_Count; + } +} + +template +typename VmaIntrusiveLinkedList::ItemType* VmaIntrusiveLinkedList::PopBack() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const backItem = m_Back; + ItemType* const prevItem = ItemTypeTraits::GetPrev(backItem); + if (prevItem != VMA_NULL) + { + ItemTypeTraits::AccessNext(prevItem) = VMA_NULL; + } + m_Back = prevItem; + --m_Count; + ItemTypeTraits::AccessPrev(backItem) = VMA_NULL; + ItemTypeTraits::AccessNext(backItem) = VMA_NULL; + return backItem; +} + +template +typename VmaIntrusiveLinkedList::ItemType* VmaIntrusiveLinkedList::PopFront() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const frontItem = m_Front; + ItemType* const nextItem = ItemTypeTraits::GetNext(frontItem); + if (nextItem != VMA_NULL) + { + ItemTypeTraits::AccessPrev(nextItem) = VMA_NULL; + } + m_Front = nextItem; + --m_Count; + ItemTypeTraits::AccessPrev(frontItem) = VMA_NULL; + ItemTypeTraits::AccessNext(frontItem) = VMA_NULL; + return frontItem; +} + +template +void VmaIntrusiveLinkedList::InsertBefore(ItemType* existingItem, ItemType* newItem) +{ + VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL); + if (existingItem != VMA_NULL) + { + ItemType* const prevItem = ItemTypeTraits::GetPrev(existingItem); + ItemTypeTraits::AccessPrev(newItem) = prevItem; + ItemTypeTraits::AccessNext(newItem) = existingItem; + ItemTypeTraits::AccessPrev(existingItem) = newItem; + if (prevItem != VMA_NULL) + { + ItemTypeTraits::AccessNext(prevItem) = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_Front == existingItem); + m_Front = newItem; + } + ++m_Count; + } + else + PushBack(newItem); +} + +template +void VmaIntrusiveLinkedList::InsertAfter(ItemType* existingItem, ItemType* newItem) +{ + VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL); + if (existingItem != VMA_NULL) + { + ItemType* const nextItem = ItemTypeTraits::GetNext(existingItem); + ItemTypeTraits::AccessNext(newItem) = nextItem; + ItemTypeTraits::AccessPrev(newItem) = existingItem; + ItemTypeTraits::AccessNext(existingItem) = newItem; + if (nextItem != VMA_NULL) + { + ItemTypeTraits::AccessPrev(nextItem) = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_Back == existingItem); + m_Back = newItem; + } + ++m_Count; + } + else + return PushFront(newItem); +} + +template +void VmaIntrusiveLinkedList::Remove(ItemType* item) +{ + VMA_HEAVY_ASSERT(item != VMA_NULL && m_Count > 0); + if (ItemTypeTraits::GetPrev(item) != VMA_NULL) + { + ItemTypeTraits::AccessNext(ItemTypeTraits::AccessPrev(item)) = ItemTypeTraits::GetNext(item); + } + else + { + VMA_HEAVY_ASSERT(m_Front == item); + m_Front = ItemTypeTraits::GetNext(item); + } + + if (ItemTypeTraits::GetNext(item) != VMA_NULL) + { + ItemTypeTraits::AccessPrev(ItemTypeTraits::AccessNext(item)) = ItemTypeTraits::GetPrev(item); + } + else + { + VMA_HEAVY_ASSERT(m_Back == item); + m_Back = ItemTypeTraits::GetPrev(item); + } + ItemTypeTraits::AccessPrev(item) = VMA_NULL; + ItemTypeTraits::AccessNext(item) = VMA_NULL; + --m_Count; +} + +template +void VmaIntrusiveLinkedList::RemoveAll() +{ + if (!IsEmpty()) + { + ItemType* item = m_Back; + while (item != VMA_NULL) + { + ItemType* const prevItem = ItemTypeTraits::AccessPrev(item); + ItemTypeTraits::AccessPrev(item) = VMA_NULL; + ItemTypeTraits::AccessNext(item) = VMA_NULL; + item = prevItem; + } + m_Front = VMA_NULL; + m_Back = VMA_NULL; + m_Count = 0; + } +} +#endif // _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS +#endif // _VMA_INTRUSIVE_LINKED_LIST // Unused in this version. #if 0 -#if VMA_USE_STL_UNORDERED_MAP - -#define VmaPair std::pair - -#define VMA_MAP_TYPE(KeyT, ValueT) \ - std::unordered_map< KeyT, ValueT, std::hash, std::equal_to, VmaStlAllocator< std::pair > > - -#else // #if VMA_USE_STL_UNORDERED_MAP - +#ifndef _VMA_PAIR template struct VmaPair { T1 first; T2 second; - VmaPair() : first(), second() { } - VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) { } + VmaPair() : first(), second() {} + VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) {} }; -/* Class compatible with subset of interface of std::unordered_map. -KeyT, ValueT must be POD because they will be stored in VmaVector. -*/ -template -class VmaMap -{ -public: - typedef VmaPair PairType; - typedef PairType* iterator; - - VmaMap(const VmaStlAllocator& allocator) : m_Vector(allocator) { } - - iterator begin() { return m_Vector.begin(); } - iterator end() { return m_Vector.end(); } - - void insert(const PairType& pair); - iterator find(const KeyT& key); - void erase(iterator it); - -private: - VmaVector< PairType, VmaStlAllocator > m_Vector; -}; - -#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap - template struct VmaPairFirstLess { @@ -3124,7 +5030,33 @@ struct VmaPairFirstLess return lhs.first < rhsFirst; } }; +#endif // _VMA_PAIR +#ifndef _VMA_MAP +/* Class compatible with subset of interface of std::unordered_map. +KeyT, ValueT must be POD because they will be stored in VmaVector. +*/ +template +class VmaMap +{ +public: + typedef VmaPair PairType; + typedef PairType* iterator; + + VmaMap(const VmaStlAllocator& allocator) : m_Vector(allocator) {} + + iterator begin() { return m_Vector.begin(); } + iterator end() { return m_Vector.end(); } + + void insert(const PairType& pair); + iterator find(const KeyT& key); + void erase(iterator it); + +private: + VmaVector< PairType, VmaStlAllocator > m_Vector; +}; + +#ifndef _VMA_MAP_FUNCTIONS template void VmaMap::insert(const PairType& pair) { @@ -3144,7 +5076,7 @@ VmaPair* VmaMap::find(const KeyT& key) m_Vector.data() + m_Vector.size(), key, VmaPairFirstLess()); - if((it != m_Vector.end()) && (it->first == key)) + if ((it != m_Vector.end()) && (it->first == key)) { return it; } @@ -3159,890 +5091,37 @@ void VmaMap::erase(iterator it) { VmaVectorRemove(m_Vector, it - m_Vector.begin()); } - -#endif // #if VMA_USE_STL_UNORDERED_MAP +#endif // _VMA_MAP_FUNCTIONS +#endif // _VMA_MAP #endif // #if 0 -//////////////////////////////////////////////////////////////////////////////// - -class VmaDeviceMemoryBlock; - -struct VmaAllocation_T -{ -private: - static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80; - - enum FLAGS - { - FLAG_USER_DATA_STRING = 0x01, - }; - -public: - enum ALLOCATION_TYPE - { - ALLOCATION_TYPE_NONE, - ALLOCATION_TYPE_BLOCK, - ALLOCATION_TYPE_DEDICATED, - }; - - VmaAllocation_T(uint32_t currentFrameIndex, bool userDataString) : - m_Alignment(1), - m_Size(0), - m_pUserData(VMA_NULL), - m_LastUseFrameIndex(currentFrameIndex), - m_Type((uint8_t)ALLOCATION_TYPE_NONE), - m_SuballocationType((uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN), - m_MapCount(0), - m_Flags(userDataString ? (uint8_t)FLAG_USER_DATA_STRING : 0) - { - } - - ~VmaAllocation_T() - { - VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction."); - - // Check if owned string was freed. - VMA_ASSERT(m_pUserData == VMA_NULL); - } - - void InitBlockAllocation( - VmaPool hPool, - VmaDeviceMemoryBlock* block, - VkDeviceSize offset, - VkDeviceSize alignment, - VkDeviceSize size, - VmaSuballocationType suballocationType, - bool mapped, - bool canBecomeLost) - { - VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); - VMA_ASSERT(block != VMA_NULL); - m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK; - m_Alignment = alignment; - m_Size = size; - m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0; - m_SuballocationType = (uint8_t)suballocationType; - m_BlockAllocation.m_hPool = hPool; - m_BlockAllocation.m_Block = block; - m_BlockAllocation.m_Offset = offset; - m_BlockAllocation.m_CanBecomeLost = canBecomeLost; - } - - void InitLost() - { - VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); - VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST); - m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK; - m_BlockAllocation.m_hPool = VK_NULL_HANDLE; - m_BlockAllocation.m_Block = VMA_NULL; - m_BlockAllocation.m_Offset = 0; - m_BlockAllocation.m_CanBecomeLost = true; - } - - void ChangeBlockAllocation( - VmaDeviceMemoryBlock* block, - VkDeviceSize offset) - { - VMA_ASSERT(block != VMA_NULL); - VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); - m_BlockAllocation.m_Block = block; - m_BlockAllocation.m_Offset = offset; - } - - // pMappedData not null means allocation is created with MAPPED flag. - void InitDedicatedAllocation( - uint32_t memoryTypeIndex, - VkDeviceMemory hMemory, - VmaSuballocationType suballocationType, - void* pMappedData, - VkDeviceSize size) - { - VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); - VMA_ASSERT(hMemory != VK_NULL_HANDLE); - m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED; - m_Alignment = 0; - m_Size = size; - m_SuballocationType = (uint8_t)suballocationType; - m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0; - m_DedicatedAllocation.m_MemoryTypeIndex = memoryTypeIndex; - m_DedicatedAllocation.m_hMemory = hMemory; - m_DedicatedAllocation.m_pMappedData = pMappedData; - } - - ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; } - VkDeviceSize GetAlignment() const { return m_Alignment; } - VkDeviceSize GetSize() const { return m_Size; } - bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; } - void* GetUserData() const { return m_pUserData; } - void SetUserData(VmaAllocator hAllocator, void* pUserData); - VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; } - - VmaDeviceMemoryBlock* GetBlock() const - { - VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); - return m_BlockAllocation.m_Block; - } - VkDeviceSize GetOffset() const; - VkDeviceMemory GetMemory() const; - uint32_t GetMemoryTypeIndex() const; - bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; } - void* GetMappedData() const; - bool CanBecomeLost() const; - VmaPool GetPool() const; - - uint32_t GetLastUseFrameIndex() const - { - return m_LastUseFrameIndex.load(); - } - bool CompareExchangeLastUseFrameIndex(uint32_t& expected, uint32_t desired) - { - return m_LastUseFrameIndex.compare_exchange_weak(expected, desired); - } - /* - - If hAllocation.LastUseFrameIndex + frameInUseCount < allocator.CurrentFrameIndex, - makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true. - - Else, returns false. - - If hAllocation is already lost, assert - you should not call it then. - If hAllocation was not created with CAN_BECOME_LOST_BIT, assert. - */ - bool MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount); - - void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo) - { - VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED); - outInfo.blockCount = 1; - outInfo.allocationCount = 1; - outInfo.unusedRangeCount = 0; - outInfo.usedBytes = m_Size; - outInfo.unusedBytes = 0; - outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size; - outInfo.unusedRangeSizeMin = UINT64_MAX; - outInfo.unusedRangeSizeMax = 0; - } - - void BlockAllocMap(); - void BlockAllocUnmap(); - VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData); - void DedicatedAllocUnmap(VmaAllocator hAllocator); - -private: - VkDeviceSize m_Alignment; - VkDeviceSize m_Size; - void* m_pUserData; - VMA_ATOMIC_UINT32 m_LastUseFrameIndex; - uint8_t m_Type; // ALLOCATION_TYPE - uint8_t m_SuballocationType; // VmaSuballocationType - // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT. - // Bits with mask 0x7F, used only when ALLOCATION_TYPE_DEDICATED, are reference counter for vmaMapMemory()/vmaUnmapMemory(). - uint8_t m_MapCount; - uint8_t m_Flags; // enum FLAGS - - // Allocation out of VmaDeviceMemoryBlock. - struct BlockAllocation - { - VmaPool m_hPool; // Null if belongs to general memory. - VmaDeviceMemoryBlock* m_Block; - VkDeviceSize m_Offset; - bool m_CanBecomeLost; - }; - - // Allocation for an object that has its own private VkDeviceMemory. - struct DedicatedAllocation - { - uint32_t m_MemoryTypeIndex; - VkDeviceMemory m_hMemory; - void* m_pMappedData; // Not null means memory is mapped. - }; - - union - { - // Allocation out of VmaDeviceMemoryBlock. - BlockAllocation m_BlockAllocation; - // Allocation for an object that has its own private VkDeviceMemory. - DedicatedAllocation m_DedicatedAllocation; - }; - - void FreeUserDataString(VmaAllocator hAllocator); -}; - -/* -Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as -allocated memory block or free. -*/ -struct VmaSuballocation -{ - VkDeviceSize offset; - VkDeviceSize size; - VmaAllocation hAllocation; - VmaSuballocationType type; -}; - -typedef VmaList< VmaSuballocation, VmaStlAllocator > VmaSuballocationList; - -// Cost of one additional allocation lost, as equivalent in bytes. -static const VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576; - -/* -Parameters of planned allocation inside a VmaDeviceMemoryBlock. - -If canMakeOtherLost was false: -- item points to a FREE suballocation. -- itemsToMakeLostCount is 0. - -If canMakeOtherLost was true: -- item points to first of sequence of suballocations, which are either FREE, - or point to VmaAllocations that can become lost. -- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for - the requested allocation to succeed. -*/ -struct VmaAllocationRequest -{ - VkDeviceSize offset; - VkDeviceSize sumFreeSize; // Sum size of free items that overlap with proposed allocation. - VkDeviceSize sumItemSize; // Sum size of items to make lost that overlap with proposed allocation. - VmaSuballocationList::iterator item; - size_t itemsToMakeLostCount; - - VkDeviceSize CalcCost() const - { - return sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST; - } -}; - -/* -Data structure used for bookkeeping of allocations and unused ranges of memory -in a single VkDeviceMemory block. -*/ -class VmaBlockMetadata -{ -public: - VmaBlockMetadata(VmaAllocator hAllocator); - ~VmaBlockMetadata(); - void Init(VkDeviceSize size); - - // Validates all data structures inside this object. If not valid, returns false. - bool Validate() const; - VkDeviceSize GetSize() const { return m_Size; } - size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; } - VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; } - VkDeviceSize GetUnusedRangeSizeMax() const; - // Returns true if this block is empty - contains only single free suballocation. - bool IsEmpty() const; - - void CalcAllocationStatInfo(VmaStatInfo& outInfo) const; - void AddPoolStats(VmaPoolStats& inoutStats) const; - -#if VMA_STATS_STRING_ENABLED - void PrintDetailedMap(class VmaJsonWriter& json) const; -#endif - - // Creates trivial request for case when block is empty. - void CreateFirstAllocationRequest(VmaAllocationRequest* pAllocationRequest); - - // Tries to find a place for suballocation with given parameters inside this block. - // If succeeded, fills pAllocationRequest and returns true. - // If failed, returns false. - bool CreateAllocationRequest( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VkDeviceSize bufferImageGranularity, - VkDeviceSize allocSize, - VkDeviceSize allocAlignment, - VmaSuballocationType allocType, - bool canMakeOtherLost, - VmaAllocationRequest* pAllocationRequest); - - bool MakeRequestedAllocationsLost( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VmaAllocationRequest* pAllocationRequest); - - uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount); - - // Makes actual allocation based on request. Request must already be checked and valid. - void Alloc( - const VmaAllocationRequest& request, - VmaSuballocationType type, - VkDeviceSize allocSize, - VmaAllocation hAllocation); - - // Frees suballocation assigned to given memory region. - void Free(const VmaAllocation allocation); - -private: - VkDeviceSize m_Size; - uint32_t m_FreeCount; - VkDeviceSize m_SumFreeSize; - VmaSuballocationList m_Suballocations; - // Suballocations that are free and have size greater than certain threshold. - // Sorted by size, ascending. - VmaVector< VmaSuballocationList::iterator, VmaStlAllocator< VmaSuballocationList::iterator > > m_FreeSuballocationsBySize; - - bool ValidateFreeSuballocationList() const; - - // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem. - // If yes, fills pOffset and returns true. If no, returns false. - bool CheckAllocation( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VkDeviceSize bufferImageGranularity, - VkDeviceSize allocSize, - VkDeviceSize allocAlignment, - VmaSuballocationType allocType, - VmaSuballocationList::const_iterator suballocItem, - bool canMakeOtherLost, - VkDeviceSize* pOffset, - size_t* itemsToMakeLostCount, - VkDeviceSize* pSumFreeSize, - VkDeviceSize* pSumItemSize) const; - // Given free suballocation, it merges it with following one, which must also be free. - void MergeFreeWithNext(VmaSuballocationList::iterator item); - // Releases given suballocation, making it free. - // Merges it with adjacent free suballocations if applicable. - // Returns iterator to new free suballocation at this place. - VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem); - // Given free suballocation, it inserts it into sorted list of - // m_FreeSuballocationsBySize if it's suitable. - void RegisterFreeSuballocation(VmaSuballocationList::iterator item); - // Given free suballocation, it removes it from sorted list of - // m_FreeSuballocationsBySize if it's suitable. - void UnregisterFreeSuballocation(VmaSuballocationList::iterator item); -}; - -// Helper class that represents mapped memory. Synchronized internally. -class VmaDeviceMemoryMapping -{ -public: - VmaDeviceMemoryMapping(); - ~VmaDeviceMemoryMapping(); - - void* GetMappedData() const { return m_pMappedData; } - - // ppData can be null. - VkResult Map(VmaAllocator hAllocator, VkDeviceMemory hMemory, void **ppData); - void Unmap(VmaAllocator hAllocator, VkDeviceMemory hMemory); - -private: - VMA_MUTEX m_Mutex; - uint32_t m_MapCount; - void* m_pMappedData; -}; - -/* -Represents a single block of device memory (`VkDeviceMemory`) with all the -data about its regions (aka suballocations, `VmaAllocation`), assigned and free. - -Thread-safety: This class must be externally synchronized. -*/ -class VmaDeviceMemoryBlock -{ -public: - uint32_t m_MemoryTypeIndex; - VkDeviceMemory m_hMemory; - VmaDeviceMemoryMapping m_Mapping; - VmaBlockMetadata m_Metadata; - - VmaDeviceMemoryBlock(VmaAllocator hAllocator); - - ~VmaDeviceMemoryBlock() - { - VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); - } - - // Always call after construction. - void Init( - uint32_t newMemoryTypeIndex, - VkDeviceMemory newMemory, - VkDeviceSize newSize); - // Always call before destruction. - void Destroy(VmaAllocator allocator); - - // Validates all data structures inside this object. If not valid, returns false. - bool Validate() const; - - // ppData can be null. - VkResult Map(VmaAllocator hAllocator, void** ppData); - void Unmap(VmaAllocator hAllocator); -}; - -struct VmaPointerLess -{ - bool operator()(const void* lhs, const void* rhs) const - { - return lhs < rhs; - } -}; - -class VmaDefragmentator; - -/* -Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific -Vulkan memory type. - -Synchronized internally with a mutex. -*/ -struct VmaBlockVector -{ - VmaBlockVector( - VmaAllocator hAllocator, - uint32_t memoryTypeIndex, - VkDeviceSize preferredBlockSize, - size_t minBlockCount, - size_t maxBlockCount, - VkDeviceSize bufferImageGranularity, - uint32_t frameInUseCount, - bool isCustomPool); - ~VmaBlockVector(); - - VkResult CreateMinBlocks(); - - uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } - VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; } - VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } - uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; } - - void GetPoolStats(VmaPoolStats* pStats); - - bool IsEmpty() const { return m_Blocks.empty(); } - - VkResult Allocate( - VmaPool hCurrentPool, - uint32_t currentFrameIndex, - const VkMemoryRequirements& vkMemReq, - const VmaAllocationCreateInfo& createInfo, - VmaSuballocationType suballocType, - VmaAllocation* pAllocation); - - void Free( - VmaAllocation hAllocation); - - // Adds statistics of this BlockVector to pStats. - void AddStats(VmaStats* pStats); - -#if VMA_STATS_STRING_ENABLED - void PrintDetailedMap(class VmaJsonWriter& json); -#endif - - void MakePoolAllocationsLost( - uint32_t currentFrameIndex, - size_t* pLostAllocationCount); - - VmaDefragmentator* EnsureDefragmentator( - VmaAllocator hAllocator, - uint32_t currentFrameIndex); - - VkResult Defragment( - VmaDefragmentationStats* pDefragmentationStats, - VkDeviceSize& maxBytesToMove, - uint32_t& maxAllocationsToMove); - - void DestroyDefragmentator(); - -private: - friend class VmaDefragmentator; - - const VmaAllocator m_hAllocator; - const uint32_t m_MemoryTypeIndex; - const VkDeviceSize m_PreferredBlockSize; - const size_t m_MinBlockCount; - const size_t m_MaxBlockCount; - const VkDeviceSize m_BufferImageGranularity; - const uint32_t m_FrameInUseCount; - const bool m_IsCustomPool; - VMA_MUTEX m_Mutex; - // Incrementally sorted by sumFreeSize, ascending. - VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator > m_Blocks; - /* There can be at most one allocation that is completely empty - a - hysteresis to avoid pessimistic case of alternating creation and destruction - of a VkDeviceMemory. */ - bool m_HasEmptyBlock; - VmaDefragmentator* m_pDefragmentator; - - // Finds and removes given block from vector. - void Remove(VmaDeviceMemoryBlock* pBlock); - - // Performs single step in sorting m_Blocks. They may not be fully sorted - // after this call. - void IncrementallySortBlocks(); - - VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex); -}; - -struct VmaPool_T -{ -public: - VmaBlockVector m_BlockVector; - - // Takes ownership. - VmaPool_T( - VmaAllocator hAllocator, - const VmaPoolCreateInfo& createInfo); - ~VmaPool_T(); - - VmaBlockVector& GetBlockVector() { return m_BlockVector; } - -#if VMA_STATS_STRING_ENABLED - //void PrintDetailedMap(class VmaStringBuilder& sb); -#endif -}; - -class VmaDefragmentator -{ - const VmaAllocator m_hAllocator; - VmaBlockVector* const m_pBlockVector; - uint32_t m_CurrentFrameIndex; - VkDeviceSize m_BytesMoved; - uint32_t m_AllocationsMoved; - - struct AllocationInfo - { - VmaAllocation m_hAllocation; - VkBool32* m_pChanged; - - AllocationInfo() : - m_hAllocation(VK_NULL_HANDLE), - m_pChanged(VMA_NULL) - { - } - }; - - struct AllocationInfoSizeGreater - { - bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const - { - return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize(); - } - }; - - // Used between AddAllocation and Defragment. - VmaVector< AllocationInfo, VmaStlAllocator > m_Allocations; - - struct BlockInfo - { - VmaDeviceMemoryBlock* m_pBlock; - bool m_HasNonMovableAllocations; - VmaVector< AllocationInfo, VmaStlAllocator > m_Allocations; - - BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) : - m_pBlock(VMA_NULL), - m_HasNonMovableAllocations(true), - m_Allocations(pAllocationCallbacks), - m_pMappedDataForDefragmentation(VMA_NULL) - { - } - - void CalcHasNonMovableAllocations() - { - const size_t blockAllocCount = m_pBlock->m_Metadata.GetAllocationCount(); - const size_t defragmentAllocCount = m_Allocations.size(); - m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount; - } - - void SortAllocationsBySizeDescecnding() - { - VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater()); - } - - VkResult EnsureMapping(VmaAllocator hAllocator, void** ppMappedData); - void Unmap(VmaAllocator hAllocator); - - private: - // Not null if mapped for defragmentation only, not originally mapped. - void* m_pMappedDataForDefragmentation; - }; - - struct BlockPointerLess - { - bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const - { - return pLhsBlockInfo->m_pBlock < pRhsBlock; - } - bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const - { - return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock; - } - }; - - // 1. Blocks with some non-movable allocations go first. - // 2. Blocks with smaller sumFreeSize go first. - struct BlockInfoCompareMoveDestination - { - bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const - { - if(pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations) - { - return true; - } - if(!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations) - { - return false; - } - if(pLhsBlockInfo->m_pBlock->m_Metadata.GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_Metadata.GetSumFreeSize()) - { - return true; - } - return false; - } - }; - - typedef VmaVector< BlockInfo*, VmaStlAllocator > BlockInfoVector; - BlockInfoVector m_Blocks; - - VkResult DefragmentRound( - VkDeviceSize maxBytesToMove, - uint32_t maxAllocationsToMove); - - static bool MoveMakesSense( - size_t dstBlockIndex, VkDeviceSize dstOffset, - size_t srcBlockIndex, VkDeviceSize srcOffset); - -public: - VmaDefragmentator( - VmaAllocator hAllocator, - VmaBlockVector* pBlockVector, - uint32_t currentFrameIndex); - - ~VmaDefragmentator(); - - VkDeviceSize GetBytesMoved() const { return m_BytesMoved; } - uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; } - - void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged); - - VkResult Defragment( - VkDeviceSize maxBytesToMove, - uint32_t maxAllocationsToMove); -}; - -// Main allocator object. -struct VmaAllocator_T -{ - bool m_UseMutex; - bool m_UseKhrDedicatedAllocation; - VkDevice m_hDevice; - bool m_AllocationCallbacksSpecified; - VkAllocationCallbacks m_AllocationCallbacks; - VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks; - - // Number of bytes free out of limit, or VK_WHOLE_SIZE if not limit for that heap. - VkDeviceSize m_HeapSizeLimit[VK_MAX_MEMORY_HEAPS]; - VMA_MUTEX m_HeapSizeLimitMutex; - - VkPhysicalDeviceProperties m_PhysicalDeviceProperties; - VkPhysicalDeviceMemoryProperties m_MemProps; - - // Default pools. - VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES]; - - // Each vector is sorted by memory (handle value). - typedef VmaVector< VmaAllocation, VmaStlAllocator > AllocationVectorType; - AllocationVectorType* m_pDedicatedAllocations[VK_MAX_MEMORY_TYPES]; - VMA_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES]; - - VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo); - ~VmaAllocator_T(); - - const VkAllocationCallbacks* GetAllocationCallbacks() const - { - return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : 0; - } - const VmaVulkanFunctions& GetVulkanFunctions() const - { - return m_VulkanFunctions; - } - - VkDeviceSize GetBufferImageGranularity() const - { - return VMA_MAX( - static_cast(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY), - m_PhysicalDeviceProperties.limits.bufferImageGranularity); - } - - uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; } - uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; } - - uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const - { - VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount); - return m_MemProps.memoryTypes[memTypeIndex].heapIndex; - } - - void GetBufferMemoryRequirements( - VkBuffer hBuffer, - VkMemoryRequirements& memReq, - bool& requiresDedicatedAllocation, - bool& prefersDedicatedAllocation) const; - void GetImageMemoryRequirements( - VkImage hImage, - VkMemoryRequirements& memReq, - bool& requiresDedicatedAllocation, - bool& prefersDedicatedAllocation) const; - - // Main allocation function. - VkResult AllocateMemory( - const VkMemoryRequirements& vkMemReq, - bool requiresDedicatedAllocation, - bool prefersDedicatedAllocation, - VkBuffer dedicatedBuffer, - VkImage dedicatedImage, - const VmaAllocationCreateInfo& createInfo, - VmaSuballocationType suballocType, - VmaAllocation* pAllocation); - - // Main deallocation function. - void FreeMemory(const VmaAllocation allocation); - - void CalculateStats(VmaStats* pStats); - -#if VMA_STATS_STRING_ENABLED - void PrintDetailedMap(class VmaJsonWriter& json); -#endif - - VkResult Defragment( - VmaAllocation* pAllocations, - size_t allocationCount, - VkBool32* pAllocationsChanged, - const VmaDefragmentationInfo* pDefragmentationInfo, - VmaDefragmentationStats* pDefragmentationStats); - - void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo); - - VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool); - void DestroyPool(VmaPool pool); - void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats); - - void SetCurrentFrameIndex(uint32_t frameIndex); - - void MakePoolAllocationsLost( - VmaPool hPool, - size_t* pLostAllocationCount); - - void CreateLostAllocation(VmaAllocation* pAllocation); - - VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory); - void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory); - - VkResult Map(VmaAllocation hAllocation, void** ppData); - void Unmap(VmaAllocation hAllocation); - -private: - VkDeviceSize m_PreferredLargeHeapBlockSize; - VkDeviceSize m_PreferredSmallHeapBlockSize; - - VkPhysicalDevice m_PhysicalDevice; - VMA_ATOMIC_UINT32 m_CurrentFrameIndex; - - VMA_MUTEX m_PoolsMutex; - // Protected by m_PoolsMutex. Sorted by pointer value. - VmaVector > m_Pools; - - VmaVulkanFunctions m_VulkanFunctions; - - void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions); - - VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex); - - VkResult AllocateMemoryOfType( - const VkMemoryRequirements& vkMemReq, - bool dedicatedAllocation, - VkBuffer dedicatedBuffer, - VkImage dedicatedImage, - const VmaAllocationCreateInfo& createInfo, - uint32_t memTypeIndex, - VmaSuballocationType suballocType, - VmaAllocation* pAllocation); - - // Allocates and registers new VkDeviceMemory specifically for single allocation. - VkResult AllocateDedicatedMemory( - VkDeviceSize size, - VmaSuballocationType suballocType, - uint32_t memTypeIndex, - bool map, - bool isUserDataString, - void* pUserData, - VkBuffer dedicatedBuffer, - VkImage dedicatedImage, - VmaAllocation* pAllocation); - - // Tries to free pMemory as Dedicated Memory. Returns true if found and freed. - void FreeDedicatedMemory(VmaAllocation allocation); -}; - -//////////////////////////////////////////////////////////////////////////////// -// Memory allocation #2 after VmaAllocator_T definition - -static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment) -{ - return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment); -} - -static void VmaFree(VmaAllocator hAllocator, void* ptr) -{ - VmaFree(&hAllocator->m_AllocationCallbacks, ptr); -} - -template -static T* VmaAllocate(VmaAllocator hAllocator) -{ - return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T)); -} - -template -static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count) -{ - return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T)); -} - -template -static void vma_delete(VmaAllocator hAllocator, T* ptr) -{ - if(ptr != VMA_NULL) - { - ptr->~T(); - VmaFree(hAllocator, ptr); - } -} - -template -static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count) -{ - if(ptr != VMA_NULL) - { - for(size_t i = count; i--; ) - ptr[i].~T(); - VmaFree(hAllocator, ptr); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// VmaStringBuilder - -#if VMA_STATS_STRING_ENABLED - +#if !defined(_VMA_STRING_BUILDER) && VMA_STATS_STRING_ENABLED class VmaStringBuilder { public: - VmaStringBuilder(VmaAllocator alloc) : m_Data(VmaStlAllocator(alloc->GetAllocationCallbacks())) { } + VmaStringBuilder(const VkAllocationCallbacks* allocationCallbacks) : m_Data(VmaStlAllocator(allocationCallbacks)) {} + ~VmaStringBuilder() = default; + size_t GetLength() const { return m_Data.size(); } const char* GetData() const { return m_Data.data(); } - - void Add(char ch) { m_Data.push_back(ch); } - void Add(const char* pStr); void AddNewLine() { Add('\n'); } + void Add(char ch) { m_Data.push_back(ch); } + + void Add(const char* pStr); void AddNumber(uint32_t num); void AddNumber(uint64_t num); void AddPointer(const void* ptr); private: - VmaVector< char, VmaStlAllocator > m_Data; + VmaVector> m_Data; }; +#ifndef _VMA_STRING_BUILDER_FUNCTIONS void VmaStringBuilder::Add(const char* pStr) { const size_t strLen = strlen(pStr); - if(strLen > 0) + if (strLen > 0) { const size_t oldCount = m_Data.size(); m_Data.resize(oldCount + strLen); @@ -4053,15 +5132,27 @@ void VmaStringBuilder::Add(const char* pStr) void VmaStringBuilder::AddNumber(uint32_t num) { char buf[11]; - VmaUint32ToStr(buf, sizeof(buf), num); - Add(buf); + buf[10] = '\0'; + char* p = &buf[10]; + do + { + *--p = '0' + (num % 10); + num /= 10; + } while (num); + Add(p); } void VmaStringBuilder::AddNumber(uint64_t num) { char buf[21]; - VmaUint64ToStr(buf, sizeof(buf), num); - Add(buf); + buf[20] = '\0'; + char* p = &buf[20]; + do + { + *--p = '0' + (num % 10); + num /= 10; + } while (num); + Add(p); } void VmaStringBuilder::AddPointer(const void* ptr) @@ -4070,42 +5161,65 @@ void VmaStringBuilder::AddPointer(const void* ptr) VmaPtrToStr(buf, sizeof(buf), ptr); Add(buf); } +#endif //_VMA_STRING_BUILDER_FUNCTIONS +#endif // _VMA_STRING_BUILDER -#endif // #if VMA_STATS_STRING_ENABLED - -//////////////////////////////////////////////////////////////////////////////// -// VmaJsonWriter - -#if VMA_STATS_STRING_ENABLED - +#if !defined(_VMA_JSON_WRITER) && VMA_STATS_STRING_ENABLED +/* +Allows to conveniently build a correct JSON document to be written to the +VmaStringBuilder passed to the constructor. +*/ class VmaJsonWriter { + VMA_CLASS_NO_COPY(VmaJsonWriter) public: + // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object. VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb); ~VmaJsonWriter(); + // Begins object by writing "{". + // Inside an object, you must call pairs of WriteString and a value, e.g.: + // j.BeginObject(true); j.WriteString("A"); j.WriteNumber(1); j.WriteString("B"); j.WriteNumber(2); j.EndObject(); + // Will write: { "A": 1, "B": 2 } void BeginObject(bool singleLine = false); + // Ends object by writing "}". void EndObject(); - + + // Begins array by writing "[". + // Inside an array, you can write a sequence of any values. void BeginArray(bool singleLine = false); + // Ends array by writing "[". void EndArray(); - + + // Writes a string value inside "". + // pStr can contain any ANSI characters, including '"', new line etc. - they will be properly escaped. void WriteString(const char* pStr); + + // Begins writing a string value. + // Call BeginString, ContinueString, ContinueString, ..., EndString instead of + // WriteString to conveniently build the string content incrementally, made of + // parts including numbers. void BeginString(const char* pStr = VMA_NULL); + // Posts next part of an open string. void ContinueString(const char* pStr); + // Posts next part of an open string. The number is converted to decimal characters. void ContinueString(uint32_t n); void ContinueString(uint64_t n); + // Posts next part of an open string. Pointer value is converted to characters + // using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00 void ContinueString_Pointer(const void* ptr); + // Ends writing a string value by writing '"'. void EndString(const char* pStr = VMA_NULL); - + + // Writes a number value. void WriteNumber(uint32_t n); void WriteNumber(uint64_t n); + // Writes a boolean value - false or true. void WriteBool(bool b); + // Writes a null value. void WriteNull(); private: - static const char* const INDENT; - enum COLLECTION_TYPE { COLLECTION_TYPE_OBJECT, @@ -4118,6 +5232,8 @@ private: bool singleLineMode; }; + static const char* const INDENT; + VmaStringBuilder& m_SB; VmaVector< StackItem, VmaStlAllocator > m_Stack; bool m_InsideString; @@ -4125,15 +5241,13 @@ private: void BeginValue(bool isString); void WriteIndent(bool oneLess = false); }; - const char* const VmaJsonWriter::INDENT = " "; -VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) : - m_SB(sb), +#ifndef _VMA_JSON_WRITER_FUNCTIONS +VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) + : m_SB(sb), m_Stack(VmaStlAllocator(pAllocationCallbacks)), - m_InsideString(false) -{ -} + m_InsideString(false) {} VmaJsonWriter::~VmaJsonWriter() { @@ -4204,7 +5318,7 @@ void VmaJsonWriter::BeginString(const char* pStr) BeginValue(true); m_SB.Add('"'); m_InsideString = true; - if(pStr != VMA_NULL && pStr[0] != '\0') + if (pStr != VMA_NULL && pStr[0] != '\0') { ContinueString(pStr); } @@ -4215,22 +5329,22 @@ void VmaJsonWriter::ContinueString(const char* pStr) VMA_ASSERT(m_InsideString); const size_t strLen = strlen(pStr); - for(size_t i = 0; i < strLen; ++i) + for (size_t i = 0; i < strLen; ++i) { char ch = pStr[i]; - if(ch == '\'') + if (ch == '\\') { m_SB.Add("\\\\"); } - else if(ch == '"') + else if (ch == '"') { m_SB.Add("\\\""); } - else if(ch >= 32) + else if (ch >= 32) { m_SB.Add(ch); } - else switch(ch) + else switch (ch) { case '\b': m_SB.Add("\\b"); @@ -4275,7 +5389,7 @@ void VmaJsonWriter::ContinueString_Pointer(const void* ptr) void VmaJsonWriter::EndString(const char* pStr) { VMA_ASSERT(m_InsideString); - if(pStr != VMA_NULL && pStr[0] != '\0') + if (pStr != VMA_NULL && pStr[0] != '\0') { ContinueString(pStr); } @@ -4313,21 +5427,21 @@ void VmaJsonWriter::WriteNull() void VmaJsonWriter::BeginValue(bool isString) { - if(!m_Stack.empty()) + if (!m_Stack.empty()) { StackItem& currItem = m_Stack.back(); - if(currItem.type == COLLECTION_TYPE_OBJECT && + if (currItem.type == COLLECTION_TYPE_OBJECT && currItem.valueCount % 2 == 0) { VMA_ASSERT(isString); } - if(currItem.type == COLLECTION_TYPE_OBJECT && + if (currItem.type == COLLECTION_TYPE_OBJECT && currItem.valueCount % 2 != 0) { m_SB.Add(": "); } - else if(currItem.valueCount > 0) + else if (currItem.valueCount > 0) { m_SB.Add(", "); WriteIndent(); @@ -4342,41 +5456,6180 @@ void VmaJsonWriter::BeginValue(bool isString) void VmaJsonWriter::WriteIndent(bool oneLess) { - if(!m_Stack.empty() && !m_Stack.back().singleLineMode) + if (!m_Stack.empty() && !m_Stack.back().singleLineMode) { m_SB.AddNewLine(); - + size_t count = m_Stack.size(); - if(count > 0 && oneLess) + if (count > 0 && oneLess) { --count; } - for(size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { m_SB.Add(INDENT); } } } +#endif // _VMA_JSON_WRITER_FUNCTIONS -#endif // #if VMA_STATS_STRING_ENABLED +static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat) +{ + json.BeginObject(); -//////////////////////////////////////////////////////////////////////////////// + json.WriteString("Blocks"); + json.WriteNumber(stat.blockCount); + + json.WriteString("Allocations"); + json.WriteNumber(stat.allocationCount); + + json.WriteString("UnusedRanges"); + json.WriteNumber(stat.unusedRangeCount); + + json.WriteString("UsedBytes"); + json.WriteNumber(stat.usedBytes); + + json.WriteString("UnusedBytes"); + json.WriteNumber(stat.unusedBytes); + + if (stat.allocationCount > 1) + { + json.WriteString("AllocationSize"); + json.BeginObject(true); + json.WriteString("Min"); + json.WriteNumber(stat.allocationSizeMin); + json.WriteString("Avg"); + json.WriteNumber(stat.allocationSizeAvg); + json.WriteString("Max"); + json.WriteNumber(stat.allocationSizeMax); + json.EndObject(); + } + + if (stat.unusedRangeCount > 1) + { + json.WriteString("UnusedRangeSize"); + json.BeginObject(true); + json.WriteString("Min"); + json.WriteNumber(stat.unusedRangeSizeMin); + json.WriteString("Avg"); + json.WriteNumber(stat.unusedRangeSizeAvg); + json.WriteString("Max"); + json.WriteNumber(stat.unusedRangeSizeMax); + json.EndObject(); + } + + json.EndObject(); +} +#endif // _VMA_JSON_WRITER + +#ifndef _VMA_DEVICE_MEMORY_BLOCK +/* +Represents a single block of device memory (`VkDeviceMemory`) with all the +data about its regions (aka suballocations, #VmaAllocation), assigned and free. + +Thread-safety: This class must be externally synchronized. +*/ +class VmaDeviceMemoryBlock +{ + VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock) +public: + VmaBlockMetadata* m_pMetadata; + + VmaDeviceMemoryBlock(VmaAllocator hAllocator); + ~VmaDeviceMemoryBlock(); + + // Always call after construction. + void Init( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t newMemoryTypeIndex, + VkDeviceMemory newMemory, + VkDeviceSize newSize, + uint32_t id, + uint32_t algorithm, + VkDeviceSize bufferImageGranularity); + // Always call before destruction. + void Destroy(VmaAllocator allocator); + + VmaPool GetParentPool() const { return m_hParentPool; } + VkDeviceMemory GetDeviceMemory() const { return m_hMemory; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + uint32_t GetId() const { return m_Id; } + void* GetMappedData() const { return m_pMappedData; } + + // Validates all data structures inside this object. If not valid, returns false. + bool Validate() const; + VkResult CheckCorruption(VmaAllocator hAllocator); + + // ppData can be null. + VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData); + void Unmap(VmaAllocator hAllocator, uint32_t count); + + VkResult WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize); + VkResult ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize); + + VkResult BindBufferMemory( + const VmaAllocator hAllocator, + const VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext); + VkResult BindImageMemory( + const VmaAllocator hAllocator, + const VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext); + +private: + VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool. + uint32_t m_MemoryTypeIndex; + uint32_t m_Id; + VkDeviceMemory m_hMemory; + + /* + Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory. + Also protects m_MapCount, m_pMappedData. + Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex. + */ + VMA_MUTEX m_Mutex; + uint32_t m_MapCount; + void* m_pMappedData; +}; +#endif // _VMA_DEVICE_MEMORY_BLOCK + +#ifndef _VMA_ALLOCATION_T +struct VmaAllocation_T +{ + friend struct VmaDedicatedAllocationListItemTraits; + + static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80; + + enum FLAGS { FLAG_USER_DATA_STRING = 0x01 }; + +public: + enum ALLOCATION_TYPE + { + ALLOCATION_TYPE_NONE, + ALLOCATION_TYPE_BLOCK, + ALLOCATION_TYPE_DEDICATED, + }; + + // This struct is allocated using VmaPoolAllocator. + VmaAllocation_T(bool userDataString); + ~VmaAllocation_T(); + + void InitBlockAllocation( + VmaDeviceMemoryBlock* block, + VmaAllocHandle allocHandle, + VkDeviceSize alignment, + VkDeviceSize size, + uint32_t memoryTypeIndex, + VmaSuballocationType suballocationType, + bool mapped); + // pMappedData not null means allocation is created with MAPPED flag. + void InitDedicatedAllocation( + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceMemory hMemory, + VmaSuballocationType suballocationType, + void* pMappedData, + VkDeviceSize size); + + ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; } + VkDeviceSize GetAlignment() const { return m_Alignment; } + VkDeviceSize GetSize() const { return m_Size; } + bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; } + void* GetUserData() const { return m_pUserData; } + VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; } + + VmaDeviceMemoryBlock* GetBlock() const { VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); return m_BlockAllocation.m_Block; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; } + + void SetUserData(VmaAllocator hAllocator, void* pUserData); + void ChangeBlockAllocation(VmaAllocator hAllocator, VmaDeviceMemoryBlock* block, VmaAllocHandle allocHandle); + void ChangeAllocHandle(VmaAllocHandle newAllocHandle); + VmaAllocHandle GetAllocHandle() const; + VkDeviceSize GetOffset() const; + VmaPool GetParentPool() const; + VkDeviceMemory GetMemory() const; + void* GetMappedData() const; + + void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo); + + void BlockAllocMap(); + void BlockAllocUnmap(); + VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData); + void DedicatedAllocUnmap(VmaAllocator hAllocator); + +#if VMA_STATS_STRING_ENABLED + uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; } + + void InitBufferImageUsage(uint32_t bufferImageUsage); + void PrintParameters(class VmaJsonWriter& json) const; +#endif + +private: + // Allocation out of VmaDeviceMemoryBlock. + struct BlockAllocation + { + VmaDeviceMemoryBlock* m_Block; + VmaAllocHandle m_AllocHandle; + }; + // Allocation for an object that has its own private VkDeviceMemory. + struct DedicatedAllocation + { + VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool. + VkDeviceMemory m_hMemory; + void* m_pMappedData; // Not null means memory is mapped. + VmaAllocation_T* m_Prev; + VmaAllocation_T* m_Next; + }; + union + { + // Allocation out of VmaDeviceMemoryBlock. + BlockAllocation m_BlockAllocation; + // Allocation for an object that has its own private VkDeviceMemory. + DedicatedAllocation m_DedicatedAllocation; + }; + + VkDeviceSize m_Alignment; + VkDeviceSize m_Size; + void* m_pUserData; + uint32_t m_MemoryTypeIndex; + uint8_t m_Type; // ALLOCATION_TYPE + uint8_t m_SuballocationType; // VmaSuballocationType + // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT. + // Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory(). + uint8_t m_MapCount; + uint8_t m_Flags; // enum FLAGS +#if VMA_STATS_STRING_ENABLED + uint32_t m_BufferImageUsage; // 0 if unknown. +#endif + + void FreeUserDataString(VmaAllocator hAllocator); +}; +#endif // _VMA_ALLOCATION_T + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS +struct VmaDedicatedAllocationListItemTraits +{ + typedef VmaAllocation_T ItemType; + + static ItemType* GetPrev(const ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Prev; + } + static ItemType* GetNext(const ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Next; + } + static ItemType*& AccessPrev(ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Prev; + } + static ItemType*& AccessNext(ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Next; + } +}; +#endif // _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST +/* +Stores linked list of VmaAllocation_T objects. +Thread-safe, synchronized internally. +*/ +class VmaDedicatedAllocationList +{ +public: + VmaDedicatedAllocationList() {} + ~VmaDedicatedAllocationList(); + + void Init(bool useMutex) { m_UseMutex = useMutex; } + bool Validate(); + + void AddStats(VmaStats* stats, uint32_t memTypeIndex, uint32_t memHeapIndex); + void AddPoolStats(VmaPoolStats* stats); +#if VMA_STATS_STRING_ENABLED + // Writes JSON array with the list of allocations. + void BuildStatsString(VmaJsonWriter& json); +#endif + + bool IsEmpty(); + void Register(VmaAllocation alloc); + void Unregister(VmaAllocation alloc); + +private: + typedef VmaIntrusiveLinkedList DedicatedAllocationLinkedList; + + bool m_UseMutex = true; + VMA_RW_MUTEX m_Mutex; + DedicatedAllocationLinkedList m_AllocationList; +}; + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS + +VmaDedicatedAllocationList::~VmaDedicatedAllocationList() +{ + VMA_HEAVY_ASSERT(Validate()); + + if (!m_AllocationList.IsEmpty()) + { + VMA_ASSERT(false && "Unfreed dedicated allocations found!"); + } +} + +bool VmaDedicatedAllocationList::Validate() +{ + const size_t declaredCount = m_AllocationList.GetCount(); + size_t actualCount = 0; + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + for (VmaAllocation alloc = m_AllocationList.Front(); + alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc)) + { + ++actualCount; + } + VMA_VALIDATE(actualCount == declaredCount); + + return true; +} + +void VmaDedicatedAllocationList::AddStats(VmaStats* stats, uint32_t memTypeIndex, uint32_t memHeapIndex) +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + for (VmaAllocation alloc = m_AllocationList.Front(); + alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc)) + { + VmaStatInfo allocationStatInfo; + alloc->DedicatedAllocCalcStatsInfo(allocationStatInfo); + VmaAddStatInfo(stats->total, allocationStatInfo); + VmaAddStatInfo(stats->memoryType[memTypeIndex], allocationStatInfo); + VmaAddStatInfo(stats->memoryHeap[memHeapIndex], allocationStatInfo); + } +} + +void VmaDedicatedAllocationList::AddPoolStats(VmaPoolStats* stats) +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + + const size_t allocCount = m_AllocationList.GetCount(); + stats->allocationCount += allocCount; + stats->blockCount += allocCount; + + for(auto* item = m_AllocationList.Front(); item != nullptr; item = DedicatedAllocationLinkedList::GetNext(item)) + { + stats->size += item->GetSize(); + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaDedicatedAllocationList::BuildStatsString(VmaJsonWriter& json) +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + json.BeginArray(); + for (VmaAllocation alloc = m_AllocationList.Front(); + alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc)) + { + json.BeginObject(true); + alloc->PrintParameters(json); + json.EndObject(); + } + json.EndArray(); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaDedicatedAllocationList::IsEmpty() +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + return m_AllocationList.IsEmpty(); +} + +void VmaDedicatedAllocationList::Register(VmaAllocation alloc) +{ + VmaMutexLockWrite lock(m_Mutex, m_UseMutex); + m_AllocationList.PushBack(alloc); +} + +void VmaDedicatedAllocationList::Unregister(VmaAllocation alloc) +{ + VmaMutexLockWrite lock(m_Mutex, m_UseMutex); + m_AllocationList.Remove(alloc); +} +#endif // _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS +#endif // _VMA_DEDICATED_ALLOCATION_LIST + +#ifndef _VMA_SUBALLOCATION +/* +Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as +allocated memory block or free. +*/ +struct VmaSuballocation +{ + VkDeviceSize offset; + VkDeviceSize size; + void* userData; + VmaSuballocationType type; +}; + +// Comparator for offsets. +struct VmaSuballocationOffsetLess +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset < rhs.offset; + } +}; + +struct VmaSuballocationOffsetGreater +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset > rhs.offset; + } +}; + +struct VmaSuballocationItemSizeLess +{ + bool operator()(const VmaSuballocationList::iterator lhs, + const VmaSuballocationList::iterator rhs) const + { + return lhs->size < rhs->size; + } + + bool operator()(const VmaSuballocationList::iterator lhs, + VkDeviceSize rhsSize) const + { + return lhs->size < rhsSize; + } +}; +#endif // _VMA_SUBALLOCATION + +#ifndef _VMA_ALLOCATION_REQUEST +/* +Parameters of planned allocation inside a VmaDeviceMemoryBlock. +item points to a FREE suballocation. +*/ +struct VmaAllocationRequest +{ + VmaAllocHandle allocHandle; + VkDeviceSize size; + VmaSuballocationList::iterator item; + void* customData; + uint64_t algorithmData; + VmaAllocationRequestType type; +}; +#endif // _VMA_ALLOCATION_REQUEST + +#ifndef _VMA_BLOCK_METADATA +/* +Data structure used for bookkeeping of allocations and unused ranges of memory +in a single VkDeviceMemory block. +*/ +class VmaBlockMetadata +{ +public: + // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object. + VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata() = default; + + virtual void Init(VkDeviceSize size) { m_Size = size; } + bool IsVirtual() const { return m_IsVirtual; } + VkDeviceSize GetSize() const { return m_Size; } + + // Validates all data structures inside this object. If not valid, returns false. + virtual bool Validate() const = 0; + virtual size_t GetAllocationCount() const = 0; + virtual VkDeviceSize GetSumFreeSize() const = 0; + // Returns true if this block is empty - contains only single free suballocation. + virtual bool IsEmpty() const = 0; + virtual void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) = 0; + virtual VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const = 0; + + // Must set blockCount to 1. + virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0; + // Shouldn't modify blockCount. + virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0; + +#if VMA_STATS_STRING_ENABLED + virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0; +#endif + + // Tries to find a place for suballocation with given parameters inside this block. + // If succeeded, fills pAllocationRequest and returns true. + // If failed, returns false. + virtual bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags. + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) = 0; + + virtual VkResult CheckCorruption(const void* pBlockData) = 0; + + // Makes actual allocation based on request. Request must already be checked and valid. + virtual void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) = 0; + + // Frees suballocation assigned to given memory region. + virtual void Free(VmaAllocHandle allocHandle) = 0; + + // Frees all allocations. + // Careful! Don't call it if there are VmaAllocation objects owned by userData of cleared allocations! + virtual void Clear() = 0; + + virtual void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) = 0; + +protected: + const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; } + VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } + VkDeviceSize GetDebugMargin() const { return IsVirtual() ? 0 : VMA_DEBUG_MARGIN; } + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap_Begin(class VmaJsonWriter& json, + VkDeviceSize unusedBytes, + size_t allocationCount, + size_t unusedRangeCount) const; + void PrintDetailedMap_Allocation(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size, void* userData) const; + void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json, + VkDeviceSize offset, + VkDeviceSize size) const; + void PrintDetailedMap_End(class VmaJsonWriter& json) const; +#endif + +private: + VkDeviceSize m_Size; + const VkAllocationCallbacks* m_pAllocationCallbacks; + const VkDeviceSize m_BufferImageGranularity; + const bool m_IsVirtual; +}; + +#ifndef _VMA_BLOCK_METADATA_FUNCTIONS +VmaBlockMetadata::VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : m_Size(0), + m_pAllocationCallbacks(pAllocationCallbacks), + m_BufferImageGranularity(bufferImageGranularity), + m_IsVirtual(isVirtual) {} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json, + VkDeviceSize unusedBytes, size_t allocationCount, size_t unusedRangeCount) const +{ + json.BeginObject(); + + json.WriteString("TotalBytes"); + json.WriteNumber(GetSize()); + + json.WriteString("UnusedBytes"); + json.WriteNumber(unusedBytes); + + json.WriteString("Allocations"); + json.WriteNumber((uint64_t)allocationCount); + + json.WriteString("UnusedRanges"); + json.WriteNumber((uint64_t)unusedRangeCount); + + json.WriteString("Suballocations"); + json.BeginArray(); +} + +void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size, void* userData) const +{ + json.BeginObject(true); + + json.WriteString("Offset"); + json.WriteNumber(offset); + + if (IsVirtual()) + { + json.WriteString("Type"); + json.WriteString("VirtualAllocation"); + + json.WriteString("Size"); + json.WriteNumber(size); + + if (userData != VMA_NULL) + { + json.WriteString("UserData"); + json.BeginString(); + json.ContinueString_Pointer(userData); + json.EndString(); + } + } + else + { + ((VmaAllocation)userData)->PrintParameters(json); + } + + json.EndObject(); +} + +void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size) const +{ + json.BeginObject(true); + + json.WriteString("Offset"); + json.WriteNumber(offset); + + json.WriteString("Type"); + json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]); + + json.WriteString("Size"); + json.WriteNumber(size); + + json.EndObject(); +} + +void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const +{ + json.EndArray(); + json.EndObject(); +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_BLOCK_METADATA_FUNCTIONS +#endif // _VMA_BLOCK_METADATA + +#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY +// Before deleting object of this class remember to call 'Destroy()' +class VmaBlockBufferImageGranularity final +{ +public: + struct ValidationContext + { + const VkAllocationCallbacks* allocCallbacks; + uint16_t* pageAllocs; + }; + + VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity); + ~VmaBlockBufferImageGranularity(); + + bool IsEnabled() const { return m_BufferImageGranularity > MAX_LOW_IMAGE_BUFFER_GRANULARITY; } + + void Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size); + // Before destroying object you must call free it's memory + void Destroy(const VkAllocationCallbacks* pAllocationCallbacks); + + void RoundupAllocRequest(VmaSuballocationType allocType, + VkDeviceSize& inOutAllocSize, + VkDeviceSize& inOutAllocAlignment) const; + + bool IsConflict(VkDeviceSize allocSize, + VkDeviceSize allocOffset, + VkDeviceSize blockSize, + VkDeviceSize blockOffset, + VmaSuballocationType allocType) const; + + void AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size); + void FreePages(VkDeviceSize offset, VkDeviceSize size); + void Clear(); + + ValidationContext StartValidation(const VkAllocationCallbacks* pAllocationCallbacks, + bool isVirutal) const; + bool Validate(ValidationContext& ctx, VkDeviceSize offset, VkDeviceSize size) const; + bool FinishValidation(ValidationContext& ctx) const; + +private: + static const uint16_t MAX_LOW_IMAGE_BUFFER_GRANULARITY = 256; + + struct RegionInfo + { + uint8_t allocType; + uint16_t allocCount; + }; + + VkDeviceSize m_BufferImageGranularity; + uint32_t m_RegionCount; + RegionInfo* m_RegionInfo; + + uint32_t GetStartPage(VkDeviceSize offset) const { return PageToIndex(offset & ~(m_BufferImageGranularity - 1)); } + uint32_t GetEndPage(VkDeviceSize offset, VkDeviceSize size) const { return PageToIndex((offset + size - 1) & ~(m_BufferImageGranularity - 1)); } + + uint32_t PageToIndex(VkDeviceSize offset) const; + void AllocPage(RegionInfo& page, uint8_t allocType); +}; + +#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS +VmaBlockBufferImageGranularity::VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity) + : m_BufferImageGranularity(bufferImageGranularity), + m_RegionCount(0), + m_RegionInfo(VMA_NULL) {} + +VmaBlockBufferImageGranularity::~VmaBlockBufferImageGranularity() +{ + VMA_ASSERT(m_RegionInfo == VMA_NULL && "Free not called before destroying object!"); +} + +void VmaBlockBufferImageGranularity::Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size) +{ + if (IsEnabled()) + { + m_RegionCount = static_cast(VmaDivideRoundingUp(size, m_BufferImageGranularity)); + m_RegionInfo = vma_new_array(pAllocationCallbacks, RegionInfo, m_RegionCount); + memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo)); + } +} + +void VmaBlockBufferImageGranularity::Destroy(const VkAllocationCallbacks* pAllocationCallbacks) +{ + if (m_RegionInfo) + { + vma_delete_array(pAllocationCallbacks, m_RegionInfo, m_RegionCount); + m_RegionInfo = VMA_NULL; + } +} + +void VmaBlockBufferImageGranularity::RoundupAllocRequest(VmaSuballocationType allocType, + VkDeviceSize& inOutAllocSize, + VkDeviceSize& inOutAllocAlignment) const +{ + if (m_BufferImageGranularity > 1 && + m_BufferImageGranularity <= MAX_LOW_IMAGE_BUFFER_GRANULARITY) + { + if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL) + { + inOutAllocAlignment = VMA_MAX(inOutAllocAlignment, m_BufferImageGranularity); + inOutAllocSize = VmaAlignUp(inOutAllocSize, m_BufferImageGranularity); + } + } +} + +bool VmaBlockBufferImageGranularity::IsConflict(VkDeviceSize allocSize, + VkDeviceSize allocOffset, + VkDeviceSize blockSize, + VkDeviceSize blockOffset, + VmaSuballocationType allocType) const +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(allocOffset); + if (m_RegionInfo[startPage].allocCount > 0 && + VmaIsBufferImageGranularityConflict(static_cast(m_RegionInfo[startPage].allocType), allocType)) + { + allocOffset = VmaAlignUp(allocOffset, m_BufferImageGranularity); + if (blockSize < allocSize + allocOffset - blockOffset) + return true; + ++startPage; + } + uint32_t endPage = GetEndPage(allocOffset, allocSize); + if (endPage != startPage && + m_RegionInfo[endPage].allocCount > 0 && + VmaIsBufferImageGranularityConflict(static_cast(m_RegionInfo[endPage].allocType), allocType)) + { + return true; + } + } + return false; +} + +void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size) +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(offset); + AllocPage(m_RegionInfo[startPage], allocType); + + uint32_t endPage = GetEndPage(offset, size); + if (startPage != endPage) + AllocPage(m_RegionInfo[endPage], allocType); + } +} + +void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size) +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(offset); + --m_RegionInfo[startPage].allocCount; + if (m_RegionInfo[startPage].allocCount == 0) + m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE; + uint32_t endPage = GetEndPage(offset, size); + if (startPage != endPage) + { + --m_RegionInfo[endPage].allocCount; + if (m_RegionInfo[endPage].allocCount == 0) + m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE; + } + } +} + +void VmaBlockBufferImageGranularity::Clear() +{ + if (m_RegionInfo) + memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo)); +} + +VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity::StartValidation( + const VkAllocationCallbacks* pAllocationCallbacks, bool isVirutal) const +{ + ValidationContext ctx{ pAllocationCallbacks, VMA_NULL }; + if (!isVirutal && IsEnabled()) + { + ctx.pageAllocs = vma_new_array(pAllocationCallbacks, uint16_t, m_RegionCount); + memset(ctx.pageAllocs, 0, m_RegionCount * sizeof(uint16_t)); + } + return ctx; +} + +bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx, + VkDeviceSize offset, VkDeviceSize size) const +{ + if (IsEnabled()) + { + uint32_t start = GetStartPage(offset); + ++ctx.pageAllocs[start]; + VMA_VALIDATE(m_RegionInfo[start].allocCount > 0); + + uint32_t end = GetEndPage(offset, size); + if (start != end) + { + ++ctx.pageAllocs[end]; + VMA_VALIDATE(m_RegionInfo[end].allocCount > 0); + } + } + return true; +} + +bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const +{ + // Check proper page structure + if (IsEnabled()) + { + VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!"); + + for (uint32_t page = 0; page < m_RegionCount; ++page) + { + VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount); + } + vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount); + ctx.pageAllocs = VMA_NULL; + } + return true; +} + +uint32_t VmaBlockBufferImageGranularity::PageToIndex(VkDeviceSize offset) const +{ + return static_cast(offset >> VMA_BITSCAN_MSB(m_BufferImageGranularity)); +} + +void VmaBlockBufferImageGranularity::AllocPage(RegionInfo& page, uint8_t allocType) +{ + // When current alloc type is free then it can be overriden by new type + if (page.allocCount == 0 || page.allocCount > 0 && page.allocType == VMA_SUBALLOCATION_TYPE_FREE) + page.allocType = allocType; + + ++page.allocCount; +} +#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS +#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY + +#ifndef _VMA_BLOCK_METADATA_GENERIC +class VmaBlockMetadata_Generic : public VmaBlockMetadata +{ + friend class VmaDefragmentationAlgorithm_Generic; + friend class VmaDefragmentationAlgorithm_Fast; + VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic) +public: + VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata_Generic() = default; + + size_t GetAllocationCount() const override { return m_Suballocations.size() - m_FreeCount; } + VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; } + bool IsEmpty() const override { return (m_Suballocations.size() == 1) && (m_FreeCount == 1); } + void Free(VmaAllocHandle allocHandle) override { FreeSuballocation(FindAtOffset((VkDeviceSize)allocHandle)); } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle; }; + + void Init(VkDeviceSize size) override; + bool Validate() const override; + + void CalcAllocationStatInfo(VmaStatInfo& outInfo) const override; + void AddPoolStats(VmaPoolStats& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + VkResult CheckCorruption(const void* pBlockData) override; + + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + + // For defragmentation + bool IsBufferImageGranularityConflictPossible( + VkDeviceSize bufferImageGranularity, + VmaSuballocationType& inOutPrevSuballocType) const; + +private: + uint32_t m_FreeCount; + VkDeviceSize m_SumFreeSize; + VmaSuballocationList m_Suballocations; + // Suballocations that are free. Sorted by size, ascending. + VmaVector> m_FreeSuballocationsBySize; + + VkDeviceSize AlignAllocationSize(VkDeviceSize size) const { return IsVirtual() ? size : VmaAlignUp(size, (VkDeviceSize)16); } + + VmaSuballocationList::iterator FindAtOffset(VkDeviceSize offset); + bool ValidateFreeSuballocationList() const; + + // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem. + // If yes, fills pOffset and returns true. If no, returns false. + bool CheckAllocation( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaSuballocationList::const_iterator suballocItem, + VmaAllocHandle* pAllocHandle) const; + + // Given free suballocation, it merges it with following one, which must also be free. + void MergeFreeWithNext(VmaSuballocationList::iterator item); + // Releases given suballocation, making it free. + // Merges it with adjacent free suballocations if applicable. + // Returns iterator to new free suballocation at this place. + VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem); + // Given free suballocation, it inserts it into sorted list of + // m_FreeSuballocationsBySize if it is suitable. + void RegisterFreeSuballocation(VmaSuballocationList::iterator item); + // Given free suballocation, it removes it from sorted list of + // m_FreeSuballocationsBySize if it is suitable. + void UnregisterFreeSuballocation(VmaSuballocationList::iterator item); +}; + +#ifndef _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS +VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_FreeCount(0), + m_SumFreeSize(0), + m_Suballocations(VmaStlAllocator(pAllocationCallbacks)), + m_FreeSuballocationsBySize(VmaStlAllocator(pAllocationCallbacks)) {} + +void VmaBlockMetadata_Generic::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + + m_FreeCount = 1; + m_SumFreeSize = size; + + VmaSuballocation suballoc = {}; + suballoc.offset = 0; + suballoc.size = size; + suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + + m_Suballocations.push_back(suballoc); + m_FreeSuballocationsBySize.push_back(m_Suballocations.begin()); +} + +bool VmaBlockMetadata_Generic::Validate() const +{ + VMA_VALIDATE(!m_Suballocations.empty()); + + // Expected offset of new suballocation as calculated from previous ones. + VkDeviceSize calculatedOffset = 0; + // Expected number of free suballocations as calculated from traversing their list. + uint32_t calculatedFreeCount = 0; + // Expected sum size of free suballocations as calculated from traversing their list. + VkDeviceSize calculatedSumFreeSize = 0; + // Expected number of free suballocations that should be registered in + // m_FreeSuballocationsBySize calculated from traversing their list. + size_t freeSuballocationsToRegister = 0; + // True if previous visited suballocation was free. + bool prevFree = false; + + const VkDeviceSize debugMargin = GetDebugMargin(); + + for (const auto& subAlloc : m_Suballocations) + { + // Actual offset of this suballocation doesn't match expected one. + VMA_VALIDATE(subAlloc.offset == calculatedOffset); + + const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE); + // Two adjacent free suballocations are invalid. They should be merged. + VMA_VALIDATE(!prevFree || !currFree); + + VmaAllocation alloc = (VmaAllocation)subAlloc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + + if (currFree) + { + calculatedSumFreeSize += subAlloc.size; + ++calculatedFreeCount; + ++freeSuballocationsToRegister; + + // Margin required between allocations - every free space must be at least that large. + VMA_VALIDATE(subAlloc.size >= debugMargin); + } + else + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == subAlloc.offset); + VMA_VALIDATE(alloc->GetSize() == subAlloc.size); + } + + // Margin required between allocations - previous allocation must be free. + VMA_VALIDATE(debugMargin == 0 || prevFree); + } + + calculatedOffset += subAlloc.size; + prevFree = currFree; + } + + // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't + // match expected one. + VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister); + + VkDeviceSize lastSize = 0; + for (size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i) + { + VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i]; + + // Only free suballocations can be registered in m_FreeSuballocationsBySize. + VMA_VALIDATE(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE); + // They must be sorted by size ascending. + VMA_VALIDATE(suballocItem->size >= lastSize); + + lastSize = suballocItem->size; + } + + // Check if totals match calculated values. + VMA_VALIDATE(ValidateFreeSuballocationList()); + VMA_VALIDATE(calculatedOffset == GetSize()); + VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize); + VMA_VALIDATE(calculatedFreeCount == m_FreeCount); + + return true; +} + +void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const +{ + const uint32_t rangeCount = (uint32_t)m_Suballocations.size(); + VmaInitStatInfo(outInfo); + outInfo.blockCount = 1; + + for (const auto& suballoc : m_Suballocations) + { + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + VmaAddStatInfoAllocation(outInfo, suballoc.size); + } + else + { + VmaAddStatInfoUnusedRange(outInfo, suballoc.size); + } + } +} + +void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const +{ + const uint32_t rangeCount = (uint32_t)m_Suballocations.size(); + + inoutStats.size += GetSize(); + inoutStats.unusedSize += m_SumFreeSize; + inoutStats.allocationCount += rangeCount - m_FreeCount; + inoutStats.unusedRangeCount += m_FreeCount; +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const +{ + PrintDetailedMap_Begin(json, + m_SumFreeSize, // unusedBytes + m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount + m_FreeCount); // unusedRangeCount + + for (const auto& suballoc : m_Suballocations) + { + if (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE) + { + PrintDetailedMap_UnusedRange(json, suballoc.offset, suballoc.size); + } + else + { + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + } + } + + PrintDetailedMap_End(json); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaBlockMetadata_Generic::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(allocSize > 0); + VMA_ASSERT(!upperAddress); + VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(pAllocationRequest != VMA_NULL); + VMA_HEAVY_ASSERT(Validate()); + + allocSize = AlignAllocationSize(allocSize); + + pAllocationRequest->type = VmaAllocationRequestType::Normal; + pAllocationRequest->size = allocSize; + + const VkDeviceSize debugMargin = GetDebugMargin(); + + // There is not enough total free space in this block to fulfill the request: Early return. + if (m_SumFreeSize < allocSize + 2 * debugMargin) + { + return false; + } + + // New algorithm, efficiently searching freeSuballocationsBySize. + const size_t freeSuballocCount = m_FreeSuballocationsBySize.size(); + if (freeSuballocCount > 0) + { + if (strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT) + { + // Find first free suballocation with size not less than allocSize + 2 * debugMargin. + VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess( + m_FreeSuballocationsBySize.data(), + m_FreeSuballocationsBySize.data() + freeSuballocCount, + allocSize + 2 * debugMargin, + VmaSuballocationItemSizeLess()); + size_t index = it - m_FreeSuballocationsBySize.data(); + for (; index < freeSuballocCount; ++index) + { + if (CheckAllocation( + allocSize, + allocAlignment, + allocType, + m_FreeSuballocationsBySize[index], + &pAllocationRequest->allocHandle)) + { + pAllocationRequest->item = m_FreeSuballocationsBySize[index]; + return true; + } + } + } + else if (strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET) + { + for (VmaSuballocationList::iterator it = m_Suballocations.begin(); + it != m_Suballocations.end(); + ++it) + { + if (it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation( + allocSize, + allocAlignment, + allocType, + it, + &pAllocationRequest->allocHandle)) + { + pAllocationRequest->item = it; + return true; + } + } + } + else // WORST_FIT, FIRST_FIT + { + // Search staring from biggest suballocations. + for (size_t index = freeSuballocCount; index--; ) + { + if (CheckAllocation( + allocSize, + allocAlignment, + allocType, + m_FreeSuballocationsBySize[index], + &pAllocationRequest->allocHandle)) + { + pAllocationRequest->item = m_FreeSuballocationsBySize[index]; + return true; + } + } + } + } + + return false; +} + +VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData) +{ + for (auto& suballoc : m_Suballocations) + { + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + if (!VmaValidateMagicValue(pBlockData, suballoc.offset - GetDebugMargin())) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + } + } + + return VK_SUCCESS; +} + +void VmaBlockMetadata_Generic::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + VMA_ASSERT(request.type == VmaAllocationRequestType::Normal); + VMA_ASSERT(request.item != m_Suballocations.end()); + VmaSuballocation& suballoc = *request.item; + // Given suballocation is a free block. + VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + // Given offset is inside this suballocation. + VMA_ASSERT((VkDeviceSize)request.allocHandle >= suballoc.offset); + const VkDeviceSize paddingBegin = (VkDeviceSize)request.allocHandle - suballoc.offset; + VMA_ASSERT(suballoc.size >= paddingBegin + request.size); + const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - request.size; + + // Unregister this free suballocation from m_FreeSuballocationsBySize and update + // it to become used. + UnregisterFreeSuballocation(request.item); + + suballoc.offset = (VkDeviceSize)request.allocHandle; + suballoc.size = request.size; + suballoc.type = type; + suballoc.userData = userData; + + // If there are any free bytes remaining at the end, insert new free suballocation after current one. + if (paddingEnd) + { + VmaSuballocation paddingSuballoc = {}; + paddingSuballoc.offset = suballoc.offset + suballoc.size; + paddingSuballoc.size = paddingEnd; + paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + VmaSuballocationList::iterator next = request.item; + ++next; + const VmaSuballocationList::iterator paddingEndItem = + m_Suballocations.insert(next, paddingSuballoc); + RegisterFreeSuballocation(paddingEndItem); + } + + // If there are any free bytes remaining at the beginning, insert new free suballocation before current one. + if (paddingBegin) + { + VmaSuballocation paddingSuballoc = {}; + paddingSuballoc.offset = suballoc.offset - paddingBegin; + paddingSuballoc.size = paddingBegin; + paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + const VmaSuballocationList::iterator paddingBeginItem = + m_Suballocations.insert(request.item, paddingSuballoc); + RegisterFreeSuballocation(paddingBeginItem); + } + + // Update totals. + m_FreeCount = m_FreeCount - 1; + if (paddingBegin > 0) + { + ++m_FreeCount; + } + if (paddingEnd > 0) + { + ++m_FreeCount; + } + m_SumFreeSize -= request.size; +} + +void VmaBlockMetadata_Generic::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + const VmaSuballocation& suballoc = *FindAtOffset((VkDeviceSize)allocHandle); + outInfo.offset = (VkDeviceSize)allocHandle; + outInfo.size = suballoc.size; + outInfo.pUserData = suballoc.userData; +} + +void VmaBlockMetadata_Generic::Clear() +{ + const VkDeviceSize size = GetSize(); + + VMA_ASSERT(IsVirtual()); + m_FreeCount = 1; + m_SumFreeSize = size; + m_Suballocations.clear(); + m_FreeSuballocationsBySize.clear(); + + VmaSuballocation suballoc = {}; + suballoc.offset = 0; + suballoc.size = size; + suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + m_Suballocations.push_back(suballoc); + + m_FreeSuballocationsBySize.push_back(m_Suballocations.begin()); +} + +void VmaBlockMetadata_Generic::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + VmaSuballocation& suballoc = *FindAtOffset((VkDeviceSize)allocHandle); + suballoc.userData = userData; +} + +VmaSuballocationList::iterator VmaBlockMetadata_Generic::FindAtOffset(VkDeviceSize offset) +{ + VMA_HEAVY_ASSERT(!m_Suballocations.empty()); + const VkDeviceSize last = m_Suballocations.rbegin()->offset; + if (last == offset) + return m_Suballocations.rbegin(); + const VkDeviceSize first = m_Suballocations.begin()->offset; + if (first == offset) + return m_Suballocations.begin(); + + const size_t suballocCount = m_Suballocations.size(); + const VkDeviceSize step = (last - first + m_Suballocations.begin()->size) / suballocCount; + auto findSuballocation = [&](auto begin, auto end) -> VmaSuballocationList::iterator + { + for (auto suballocItem = begin; + suballocItem != end; + ++suballocItem) + { + VmaSuballocation& suballoc = *suballocItem; + if (suballoc.offset == offset) + return suballocItem; + } + VMA_ASSERT(false && "Not found!"); + return m_Suballocations.end(); + }; + // If requested offset is closer to the end of range, search from the end + if (offset - first > suballocCount * step / 2) + { + return findSuballocation(m_Suballocations.rbegin(), m_Suballocations.rend()); + } + return findSuballocation(m_Suballocations.begin(), m_Suballocations.end()); +} + +bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const +{ + VkDeviceSize lastSize = 0; + for (size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i) + { + const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i]; + + VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE); + VMA_VALIDATE(it->size >= lastSize); + lastSize = it->size; + } + return true; +} + +bool VmaBlockMetadata_Generic::CheckAllocation( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaSuballocationList::const_iterator suballocItem, + VmaAllocHandle* pAllocHandle) const +{ + VMA_ASSERT(allocSize > 0); + VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(suballocItem != m_Suballocations.cend()); + VMA_ASSERT(pAllocHandle != VMA_NULL); + + const VkDeviceSize debugMargin = GetDebugMargin(); + const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity(); + + const VmaSuballocation& suballoc = *suballocItem; + VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + // Size of this suballocation is too small for this request: Early return. + if (suballoc.size < allocSize) + { + return false; + } + + // Start from offset equal to beginning of this suballocation. + VkDeviceSize offset = suballoc.offset; + + // Apply debugMargin at the beginning. + if (debugMargin > 0) + { + offset += debugMargin; + } + + // Apply alignment. + offset = VmaAlignUp(offset, allocAlignment); + + // Check previous suballocations for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment) + { + bool bufferImageGranularityConflict = false; + VmaSuballocationList::const_iterator prevSuballocItem = suballocItem; + while (prevSuballocItem != m_Suballocations.cbegin()) + { + --prevSuballocItem; + const VmaSuballocation& prevSuballoc = *prevSuballocItem; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + offset = VmaAlignUp(offset, bufferImageGranularity); + } + } + + // Calculate padding at the beginning based on current offset. + const VkDeviceSize paddingBegin = offset - suballoc.offset; + + // Calculate required margin at the end. + const VkDeviceSize requiredEndMargin = debugMargin; + + // Fail if requested size plus margin before and after is bigger than size of this suballocation. + if (paddingBegin + allocSize + requiredEndMargin > suballoc.size) + { + return false; + } + + // Check next suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if (allocSize % bufferImageGranularity || offset % bufferImageGranularity) + { + VmaSuballocationList::const_iterator nextSuballocItem = suballocItem; + ++nextSuballocItem; + while (nextSuballocItem != m_Suballocations.cend()) + { + const VmaSuballocation& nextSuballoc = *nextSuballocItem; + if (VmaBlocksOnSamePage(offset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) + { + return false; + } + } + else + { + // Already on next page. + break; + } + ++nextSuballocItem; + } + } + + *pAllocHandle = (VmaAllocHandle)offset; + // All tests passed: Success. pAllocHandle is already filled. + return true; +} + +void VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item) +{ + VMA_ASSERT(item != m_Suballocations.end()); + VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaSuballocationList::iterator nextItem = item; + ++nextItem; + VMA_ASSERT(nextItem != m_Suballocations.end()); + VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE); + + item->size += nextItem->size; + --m_FreeCount; + m_Suballocations.erase(nextItem); +} + +VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem) +{ + // Change this suballocation to be marked as free. + VmaSuballocation& suballoc = *suballocItem; + suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + suballoc.userData = VMA_NULL; + + // Update totals. + ++m_FreeCount; + m_SumFreeSize += suballoc.size; + + // Merge with previous and/or next suballocation if it's also free. + bool mergeWithNext = false; + bool mergeWithPrev = false; + + VmaSuballocationList::iterator nextItem = suballocItem; + ++nextItem; + if ((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE)) + { + mergeWithNext = true; + } + + VmaSuballocationList::iterator prevItem = suballocItem; + if (suballocItem != m_Suballocations.begin()) + { + --prevItem; + if (prevItem->type == VMA_SUBALLOCATION_TYPE_FREE) + { + mergeWithPrev = true; + } + } + + if (mergeWithNext) + { + UnregisterFreeSuballocation(nextItem); + MergeFreeWithNext(suballocItem); + } + + if (mergeWithPrev) + { + UnregisterFreeSuballocation(prevItem); + MergeFreeWithNext(prevItem); + RegisterFreeSuballocation(prevItem); + return prevItem; + } + else + { + RegisterFreeSuballocation(suballocItem); + return suballocItem; + } +} + +void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item) +{ + VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(item->size > 0); + + // You may want to enable this validation at the beginning or at the end of + // this function, depending on what do you want to check. + VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); + + if (m_FreeSuballocationsBySize.empty()) + { + m_FreeSuballocationsBySize.push_back(item); + } + else + { + VmaVectorInsertSorted(m_FreeSuballocationsBySize, item); + } + + //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); +} + +void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item) +{ + VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(item->size > 0); + + // You may want to enable this validation at the beginning or at the end of + // this function, depending on what do you want to check. + VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); + + VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess( + m_FreeSuballocationsBySize.data(), + m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(), + item, + VmaSuballocationItemSizeLess()); + for (size_t index = it - m_FreeSuballocationsBySize.data(); + index < m_FreeSuballocationsBySize.size(); + ++index) + { + if (m_FreeSuballocationsBySize[index] == item) + { + VmaVectorRemove(m_FreeSuballocationsBySize, index); + return; + } + VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found."); + } + VMA_ASSERT(0 && "Not found."); + + //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); +} + +bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible( + VkDeviceSize bufferImageGranularity, + VmaSuballocationType& inOutPrevSuballocType) const +{ + if (bufferImageGranularity == 1 || IsEmpty() || IsVirtual()) + { + return false; + } + + VkDeviceSize minAlignment = VK_WHOLE_SIZE; + bool typeConflictFound = false; + for (const auto& suballoc : m_Suballocations) + { + const VmaSuballocationType suballocType = suballoc.type; + if (suballocType != VMA_SUBALLOCATION_TYPE_FREE) + { + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + minAlignment = VMA_MIN(minAlignment, alloc->GetAlignment()); + if (VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType)) + { + typeConflictFound = true; + } + inOutPrevSuballocType = suballocType; + } + } + + return typeConflictFound || minAlignment >= bufferImageGranularity; +} +#endif // _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_GENERIC + +#ifndef _VMA_BLOCK_METADATA_LINEAR +/* +Allocations and their references in internal data structure look like this: + +if(m_2ndVectorMode == SECOND_VECTOR_EMPTY): + + 0 +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | + | | + | | +GetSize() +-------+ + +if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER): + + 0 +-------+ + | Alloc | 2nd[0] + +-------+ + | Alloc | 2nd[1] + +-------+ + | ... | + +-------+ + | Alloc | 2nd[2nd.size() - 1] + +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | +GetSize() +-------+ + +if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK): + + 0 +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | + | | + | | + +-------+ + | Alloc | 2nd[2nd.size() - 1] + +-------+ + | ... | + +-------+ + | Alloc | 2nd[1] + +-------+ + | Alloc | 2nd[0] +GetSize() +-------+ + +*/ +class VmaBlockMetadata_Linear : public VmaBlockMetadata +{ + VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear) +public: + VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata_Linear() = default; + + VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; } + bool IsEmpty() const override { return GetAllocationCount() == 0; } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle; }; + + void Init(VkDeviceSize size) override; + bool Validate() const override; + size_t GetAllocationCount() const override; + + void CalcAllocationStatInfo(VmaStatInfo& outInfo) const override; + void AddPoolStats(VmaPoolStats& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + VkResult CheckCorruption(const void* pBlockData) override; + + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void Free(VmaAllocHandle allocHandle) override; + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + +private: + /* + There are two suballocation vectors, used in ping-pong way. + The one with index m_1stVectorIndex is called 1st. + The one with index (m_1stVectorIndex ^ 1) is called 2nd. + 2nd can be non-empty only when 1st is not empty. + When 2nd is not empty, m_2ndVectorMode indicates its mode of operation. + */ + typedef VmaVector> SuballocationVectorType; + + enum SECOND_VECTOR_MODE + { + SECOND_VECTOR_EMPTY, + /* + Suballocations in 2nd vector are created later than the ones in 1st, but they + all have smaller offset. + */ + SECOND_VECTOR_RING_BUFFER, + /* + Suballocations in 2nd vector are upper side of double stack. + They all have offsets higher than those in 1st vector. + Top of this stack means smaller offsets, but higher indices in this vector. + */ + SECOND_VECTOR_DOUBLE_STACK, + }; + + VkDeviceSize m_SumFreeSize; + SuballocationVectorType m_Suballocations0, m_Suballocations1; + uint32_t m_1stVectorIndex; + SECOND_VECTOR_MODE m_2ndVectorMode; + // Number of items in 1st vector with hAllocation = null at the beginning. + size_t m_1stNullItemsBeginCount; + // Number of other items in 1st vector with hAllocation = null somewhere in the middle. + size_t m_1stNullItemsMiddleCount; + // Number of items in 2nd vector with hAllocation = null. + size_t m_2ndNullItemsCount; + + SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; } + SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; } + const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; } + const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; } + + VmaSuballocation& FindSuballocation(VkDeviceSize offset); + bool ShouldCompact1st() const; + void CleanupAfterFree(); + + bool CreateAllocationRequest_LowerAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest); + bool CreateAllocationRequest_UpperAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest); +}; + +#ifndef _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS +VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_SumFreeSize(0), + m_Suballocations0(VmaStlAllocator(pAllocationCallbacks)), + m_Suballocations1(VmaStlAllocator(pAllocationCallbacks)), + m_1stVectorIndex(0), + m_2ndVectorMode(SECOND_VECTOR_EMPTY), + m_1stNullItemsBeginCount(0), + m_1stNullItemsMiddleCount(0), + m_2ndNullItemsCount(0) {} + +void VmaBlockMetadata_Linear::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + m_SumFreeSize = size; +} + +bool VmaBlockMetadata_Linear::Validate() const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY)); + VMA_VALIDATE(!suballocations1st.empty() || + suballocations2nd.empty() || + m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER); + + if (!suballocations1st.empty()) + { + // Null item at the beginning should be accounted into m_1stNullItemsBeginCount. + VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].type != VMA_SUBALLOCATION_TYPE_FREE); + // Null item at the end should be just pop_back(). + VMA_VALIDATE(suballocations1st.back().type != VMA_SUBALLOCATION_TYPE_FREE); + } + if (!suballocations2nd.empty()) + { + // Null item at the end should be just pop_back(). + VMA_VALIDATE(suballocations2nd.back().type != VMA_SUBALLOCATION_TYPE_FREE); + } + + VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size()); + VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size()); + + VkDeviceSize sumUsedSize = 0; + const size_t suballoc1stCount = suballocations1st.size(); + const VkDeviceSize debugMargin = GetDebugMargin(); + VkDeviceSize offset = debugMargin; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const size_t suballoc2ndCount = suballocations2nd.size(); + size_t nullItem2ndCount = 0; + for (size_t i = 0; i < suballoc2ndCount; ++i) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem2ndCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + + VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount); + } + + for (size_t i = 0; i < m_1stNullItemsBeginCount; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE && + suballoc.userData == VMA_NULL); + } + + size_t nullItem1stCount = m_1stNullItemsBeginCount; + + for (size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem1stCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount); + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + const size_t suballoc2ndCount = suballocations2nd.size(); + size_t nullItem2ndCount = 0; + for (size_t i = suballoc2ndCount; i--; ) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem2ndCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + + VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount); + } + + VMA_VALIDATE(offset <= GetSize()); + VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize); + + return true; +} + +size_t VmaBlockMetadata_Linear::GetAllocationCount() const +{ + return AccessSuballocations1st().size() - m_1stNullItemsBeginCount - m_1stNullItemsMiddleCount + + AccessSuballocations2nd().size() - m_2ndNullItemsCount; +} + +void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const +{ + const VkDeviceSize size = GetSize(); + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + VmaInitStatInfo(outInfo); + outInfo.blockCount = 1; + + VkDeviceSize lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddStatInfoAllocation(outInfo, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + if (lastOffset < freeSpace2ndTo1stEnd) + { + const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddStatInfoAllocation(outInfo, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + if (lastOffset < freeSpace1stTo2ndEnd) + { + const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddStatInfoAllocation(outInfo, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to size. + if (lastOffset < size) + { + const VkDeviceSize unusedRangeSize = size - lastOffset; + VmaAddStatInfoUnusedRange(outInfo, unusedRangeSize); + } + + // End of loop. + lastOffset = size; + } + } + } + + outInfo.unusedBytes = size - outInfo.usedBytes; +} + +void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const VkDeviceSize size = GetSize(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + inoutStats.size += size; + + VkDeviceSize lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace2ndTo1stEnd) + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace1stTo2ndEnd) + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to size. + const VkDeviceSize unusedRangeSize = size - lastOffset; + inoutStats.unusedSize += unusedRangeSize; + ++inoutStats.unusedRangeCount; + } + + // End of loop. + lastOffset = size; + } + } + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const +{ + const VkDeviceSize size = GetSize(); + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + // FIRST PASS + + size_t unusedRangeCount = 0; + VkDeviceSize usedBytes = 0; + + VkDeviceSize lastOffset = 0; + + size_t alloc2ndCount = 0; + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc2ndCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace2ndTo1stEnd) + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + size_t alloc1stCount = 0; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc1stCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc2ndCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to size. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = size; + } + } + } + + const VkDeviceSize unusedBytes = size - usedBytes; + PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount); + + // SECOND PASS + lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace2ndTo1stEnd) + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + nextAlloc1stIndex = m_1stNullItemsBeginCount; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace1stTo2ndEnd) + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to size. + const VkDeviceSize unusedRangeSize = size - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = size; + } + } + } + + PrintDetailedMap_End(json); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaBlockMetadata_Linear::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(allocSize > 0); + VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(pAllocationRequest != VMA_NULL); + VMA_HEAVY_ASSERT(Validate()); + pAllocationRequest->size = allocSize; + return upperAddress ? + CreateAllocationRequest_UpperAddress( + allocSize, allocAlignment, allocType, strategy, pAllocationRequest) : + CreateAllocationRequest_LowerAddress( + allocSize, allocAlignment, allocType, strategy, pAllocationRequest); +} + +VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData) +{ + VMA_ASSERT(!IsVirtual()); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + for (size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + if (!VmaValidateMagicValue(pBlockData, suballoc.offset - GetDebugMargin())) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + } + } + + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + for (size_t i = 0, count = suballocations2nd.size(); i < count; ++i) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + if (!VmaValidateMagicValue(pBlockData, suballoc.offset - GetDebugMargin())) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN; + } + } + } + + return VK_SUCCESS; +} + +void VmaBlockMetadata_Linear::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + const VmaSuballocation newSuballoc = { (VkDeviceSize)request.allocHandle, request.size, userData, type }; + + switch (request.type) + { + case VmaAllocationRequestType::UpperAddress: + { + VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER && + "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer."); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + suballocations2nd.push_back(newSuballoc); + m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK; + } + break; + case VmaAllocationRequestType::EndOf1st: + { + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + + VMA_ASSERT(suballocations1st.empty() || + (VkDeviceSize)request.allocHandle >= suballocations1st.back().offset + suballocations1st.back().size); + // Check if it fits before the end of the block. + VMA_ASSERT((VkDeviceSize)request.allocHandle + request.size <= GetSize()); + + suballocations1st.push_back(newSuballoc); + } + break; + case VmaAllocationRequestType::EndOf2nd: + { + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector. + VMA_ASSERT(!suballocations1st.empty() && + (VkDeviceSize)request.allocHandle + request.size <= suballocations1st[m_1stNullItemsBeginCount].offset); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + switch (m_2ndVectorMode) + { + case SECOND_VECTOR_EMPTY: + // First allocation from second part ring buffer. + VMA_ASSERT(suballocations2nd.empty()); + m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER; + break; + case SECOND_VECTOR_RING_BUFFER: + // 2-part ring buffer is already started. + VMA_ASSERT(!suballocations2nd.empty()); + break; + case SECOND_VECTOR_DOUBLE_STACK: + VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack."); + break; + default: + VMA_ASSERT(0); + } + + suballocations2nd.push_back(newSuballoc); + } + break; + default: + VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR."); + } + + m_SumFreeSize -= newSuballoc.size; +} + +void VmaBlockMetadata_Linear::Free(VmaAllocHandle allocHandle) +{ + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + VkDeviceSize offset = (VkDeviceSize)allocHandle; + + if (!suballocations1st.empty()) + { + // First allocation: Mark it as next empty at the beginning. + VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount]; + if (firstSuballoc.offset == offset) + { + firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + firstSuballoc.userData = VMA_NULL; + m_SumFreeSize += firstSuballoc.size; + ++m_1stNullItemsBeginCount; + CleanupAfterFree(); + return; + } + } + + // Last allocation in 2-part ring buffer or top of upper stack (same logic). + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER || + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + VmaSuballocation& lastSuballoc = suballocations2nd.back(); + if (lastSuballoc.offset == offset) + { + m_SumFreeSize += lastSuballoc.size; + suballocations2nd.pop_back(); + CleanupAfterFree(); + return; + } + } + // Last allocation in 1st vector. + else if (m_2ndVectorMode == SECOND_VECTOR_EMPTY) + { + VmaSuballocation& lastSuballoc = suballocations1st.back(); + if (lastSuballoc.offset == offset) + { + m_SumFreeSize += lastSuballoc.size; + suballocations1st.pop_back(); + CleanupAfterFree(); + return; + } + } + + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + + // Item from the middle of 1st vector. + { + const SuballocationVectorType::iterator it = VmaBinaryFindSorted( + suballocations1st.begin() + m_1stNullItemsBeginCount, + suballocations1st.end(), + refSuballoc, + VmaSuballocationOffsetLess()); + if (it != suballocations1st.end()) + { + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->userData = VMA_NULL; + ++m_1stNullItemsMiddleCount; + m_SumFreeSize += it->size; + CleanupAfterFree(); + return; + } + } + + if (m_2ndVectorMode != SECOND_VECTOR_EMPTY) + { + // Item from the middle of 2nd vector. + const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ? + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) : + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater()); + if (it != suballocations2nd.end()) + { + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->userData = VMA_NULL; + ++m_2ndNullItemsCount; + m_SumFreeSize += it->size; + CleanupAfterFree(); + return; + } + } + + VMA_ASSERT(0 && "Allocation to free not found in linear allocator!"); +} + +void VmaBlockMetadata_Linear::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + VmaSuballocation& suballoc = FindSuballocation((VkDeviceSize)allocHandle); + outInfo.offset = (VkDeviceSize)allocHandle; + outInfo.size = suballoc.size; + outInfo.pUserData = suballoc.userData; +} + +void VmaBlockMetadata_Linear::Clear() +{ + m_SumFreeSize = GetSize(); + m_Suballocations0.clear(); + m_Suballocations1.clear(); + // Leaving m_1stVectorIndex unchanged - it doesn't matter. + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + m_2ndNullItemsCount = 0; +} + +void VmaBlockMetadata_Linear::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + VmaSuballocation& suballoc = FindSuballocation((VkDeviceSize)allocHandle); + suballoc.userData = userData; +} + +VmaSuballocation& VmaBlockMetadata_Linear::FindSuballocation(VkDeviceSize offset) +{ + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + + // Item from the 1st vector. + { + const SuballocationVectorType::iterator it = VmaBinaryFindSorted( + suballocations1st.begin() + m_1stNullItemsBeginCount, + suballocations1st.end(), + refSuballoc, + VmaSuballocationOffsetLess()); + if (it != suballocations1st.end()) + { + return *it; + } + } + + if (m_2ndVectorMode != SECOND_VECTOR_EMPTY) + { + // Rest of members stays uninitialized intentionally for better performance. + const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ? + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) : + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater()); + if (it != suballocations2nd.end()) + { + return *it; + } + } + + VMA_ASSERT(0 && "Allocation not found in linear allocator!"); + return suballocations1st.back(); // Should never occur. +} + +bool VmaBlockMetadata_Linear::ShouldCompact1st() const +{ + const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount; + const size_t suballocCount = AccessSuballocations1st().size(); + return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3; +} + +void VmaBlockMetadata_Linear::CleanupAfterFree() +{ + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (IsEmpty()) + { + suballocations1st.clear(); + suballocations2nd.clear(); + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + m_2ndNullItemsCount = 0; + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + } + else + { + const size_t suballoc1stCount = suballocations1st.size(); + const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount; + VMA_ASSERT(nullItem1stCount <= suballoc1stCount); + + // Find more null items at the beginning of 1st vector. + while (m_1stNullItemsBeginCount < suballoc1stCount && + suballocations1st[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++m_1stNullItemsBeginCount; + --m_1stNullItemsMiddleCount; + } + + // Find more null items at the end of 1st vector. + while (m_1stNullItemsMiddleCount > 0 && + suballocations1st.back().type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_1stNullItemsMiddleCount; + suballocations1st.pop_back(); + } + + // Find more null items at the end of 2nd vector. + while (m_2ndNullItemsCount > 0 && + suballocations2nd.back().type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_2ndNullItemsCount; + suballocations2nd.pop_back(); + } + + // Find more null items at the beginning of 2nd vector. + while (m_2ndNullItemsCount > 0 && + suballocations2nd[0].type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_2ndNullItemsCount; + VmaVectorRemove(suballocations2nd, 0); + } + + if (ShouldCompact1st()) + { + const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount; + size_t srcIndex = m_1stNullItemsBeginCount; + for (size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex) + { + while (suballocations1st[srcIndex].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++srcIndex; + } + if (dstIndex != srcIndex) + { + suballocations1st[dstIndex] = suballocations1st[srcIndex]; + } + ++srcIndex; + } + suballocations1st.resize(nonNullItemCount); + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + } + + // 2nd vector became empty. + if (suballocations2nd.empty()) + { + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + } + + // 1st vector became empty. + if (suballocations1st.size() - m_1stNullItemsBeginCount == 0) + { + suballocations1st.clear(); + m_1stNullItemsBeginCount = 0; + + if (!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + // Swap 1st with 2nd. Now 2nd is empty. + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + m_1stNullItemsMiddleCount = m_2ndNullItemsCount; + while (m_1stNullItemsBeginCount < suballocations2nd.size() && + suballocations2nd[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++m_1stNullItemsBeginCount; + --m_1stNullItemsMiddleCount; + } + m_2ndNullItemsCount = 0; + m_1stVectorIndex ^= 1; + } + } + } + + VMA_HEAVY_ASSERT(Validate()); +} + +bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + const VkDeviceSize blockSize = GetSize(); + const VkDeviceSize debugMargin = GetDebugMargin(); + const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity(); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + // Try to allocate at the end of 1st vector. + + VkDeviceSize resultBaseOffset = 0; + if (!suballocations1st.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations1st.back(); + resultBaseOffset = lastSuballoc.offset + lastSuballoc.size; + } + + // Start from offset equal to beginning of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + // Apply debugMargin at the beginning. + if (debugMargin > 0) + { + resultOffset += debugMargin; + } + + // Apply alignment. + resultOffset = VmaAlignUp(resultOffset, allocAlignment); + + // Check previous suballocations for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations1st.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity); + } + } + + const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? + suballocations2nd.back().offset : blockSize; + + // There is enough free space at the end after alignment. + if (resultOffset + allocSize + debugMargin <= freeSpaceEnd) + { + // Check next suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if ((allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; ) + { + const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) + { + return false; + } + } + else + { + // Already on previous page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)resultOffset; + // pAllocationRequest->item, customData unused. + pAllocationRequest->type = VmaAllocationRequestType::EndOf1st; + return true; + } + } + + // Wrap-around to end of 2nd vector. Try to allocate there, watching for the + // beginning of 1st vector as the end of free space. + if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + VMA_ASSERT(!suballocations1st.empty()); + + VkDeviceSize resultBaseOffset = 0; + if (!suballocations2nd.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations2nd.back(); + resultBaseOffset = lastSuballoc.offset + lastSuballoc.size; + } + + // Start from offset equal to beginning of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + // Apply debugMargin at the beginning. + if (debugMargin > 0) + { + resultOffset += debugMargin; + } + + // Apply alignment. + resultOffset = VmaAlignUp(resultOffset, allocAlignment); + + // Check previous suballocations for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity); + } + } + + size_t index1st = m_1stNullItemsBeginCount; + + // There is enough free space at the end after alignment. + if ((index1st == suballocations1st.size() && resultOffset + allocSize + debugMargin <= blockSize) || + (index1st < suballocations1st.size() && resultOffset + allocSize + debugMargin <= suballocations1st[index1st].offset)) + { + // Check next suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if (allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) + { + for (size_t nextSuballocIndex = index1st; + nextSuballocIndex < suballocations1st.size(); + nextSuballocIndex++) + { + const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) + { + return false; + } + } + else + { + // Already on next page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)resultOffset; + pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd; + // pAllocationRequest->item, customData unused. + return true; + } + } + + return false; +} + +bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + const VkDeviceSize blockSize = GetSize(); + const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity(); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer."); + return false; + } + + // Try to allocate before 2nd.back(), or end of block if 2nd.empty(). + if (allocSize > blockSize) + { + return false; + } + VkDeviceSize resultBaseOffset = blockSize - allocSize; + if (!suballocations2nd.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations2nd.back(); + resultBaseOffset = lastSuballoc.offset - allocSize; + if (allocSize > lastSuballoc.offset) + { + return false; + } + } + + // Start from offset equal to end of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + const VkDeviceSize debugMargin = GetDebugMargin(); + + // Apply debugMargin at the end. + if (debugMargin > 0) + { + if (resultOffset < debugMargin) + { + return false; + } + resultOffset -= debugMargin; + } + + // Apply alignment. + resultOffset = VmaAlignDown(resultOffset, allocAlignment); + + // Check next suballocations from 2nd for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; ) + { + const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity); + } + } + + // There is enough free space. + const VkDeviceSize endOf1st = !suballocations1st.empty() ? + suballocations1st.back().offset + suballocations1st.back().size : + 0; + if (endOf1st + debugMargin <= resultOffset) + { + // Check previous suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if (bufferImageGranularity > 1) + { + for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type)) + { + return false; + } + } + else + { + // Already on next page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)resultOffset; + // pAllocationRequest->item unused. + pAllocationRequest->type = VmaAllocationRequestType::UpperAddress; + return true; + } + + return false; +} +#endif // _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_LINEAR + +#ifndef _VMA_BLOCK_METADATA_BUDDY +/* +- GetSize() is the original size of allocated memory block. +- m_UsableSize is this size aligned down to a power of two. + All allocations and calculations happen relative to m_UsableSize. +- GetUnusableSize() is the difference between them. + It is reported as separate, unused range, not available for allocations. + +Node at level 0 has size = m_UsableSize. +Each next level contains nodes with size 2 times smaller than current level. +m_LevelCount is the maximum number of levels to use in the current object. +*/ +class VmaBlockMetadata_Buddy : public VmaBlockMetadata +{ + VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy) +public: + VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata_Buddy(); + + size_t GetAllocationCount() const override { return m_AllocationCount; } + VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize + GetUnusableSize(); } + bool IsEmpty() const override { return m_Root->type == Node::TYPE_FREE; } + VkResult CheckCorruption(const void* pBlockData) override { return VK_ERROR_FEATURE_NOT_PRESENT; } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle; }; + + void Init(VkDeviceSize size) override; + bool Validate() const override; + + void CalcAllocationStatInfo(VmaStatInfo& outInfo) const override; + void AddPoolStats(VmaPoolStats& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void Free(VmaAllocHandle allocHandle) override; + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + +private: + static const size_t MAX_LEVELS = 48; + + struct ValidationContext + { + size_t calculatedAllocationCount = 0; + size_t calculatedFreeCount = 0; + VkDeviceSize calculatedSumFreeSize = 0; + }; + struct Node + { + VkDeviceSize offset; + enum TYPE + { + TYPE_FREE, + TYPE_ALLOCATION, + TYPE_SPLIT, + TYPE_COUNT + } type; + Node* parent; + Node* buddy; + + union + { + struct + { + Node* prev; + Node* next; + } free; + struct + { + void* userData; + } allocation; + struct + { + Node* leftChild; + } split; + }; + }; + + // Size of the memory block aligned down to a power of two. + VkDeviceSize m_UsableSize; + uint32_t m_LevelCount; + VmaPoolAllocator m_NodeAllocator; + Node* m_Root; + struct + { + Node* front; + Node* back; + } m_FreeList[MAX_LEVELS]; + + // Number of nodes in the tree with type == TYPE_ALLOCATION. + size_t m_AllocationCount; + // Number of nodes in the tree with type == TYPE_FREE. + size_t m_FreeCount; + // Doesn't include space wasted due to internal fragmentation - allocation sizes are just aligned up to node sizes. + // Doesn't include unusable size. + VkDeviceSize m_SumFreeSize; + + VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; } + VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; } + + VkDeviceSize AlignAllocationSize(VkDeviceSize size) const + { + if (!IsVirtual()) + { + size = VmaAlignUp(size, (VkDeviceSize)16); + } + return VmaNextPow2(size); + } + Node* FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel); + void DeleteNodeChildren(Node* node); + bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const; + uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const; + void CalcAllocationStatInfoNode(VmaStatInfo& inoutInfo, const Node* node, VkDeviceSize levelNodeSize) const; + // Adds node to the front of FreeList at given level. + // node->type must be FREE. + // node->free.prev, next can be undefined. + void AddToFreeListFront(uint32_t level, Node* node); + // Removes node from FreeList at given level. + // node->type must be FREE. + // node->free.prev, next stay untouched. + void RemoveFromFreeList(uint32_t level, Node* node); + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const; +#endif +}; + +#ifndef _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS +VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_NodeAllocator(pAllocationCallbacks, 32), // firstBlockCapacity + m_Root(VMA_NULL), + m_AllocationCount(0), + m_FreeCount(1), + m_SumFreeSize(0) +{ + memset(m_FreeList, 0, sizeof(m_FreeList)); +} + +VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy() +{ + DeleteNodeChildren(m_Root); + m_NodeAllocator.Free(m_Root); +} + +void VmaBlockMetadata_Buddy::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + + m_UsableSize = VmaPrevPow2(size); + m_SumFreeSize = m_UsableSize; + + // Calculate m_LevelCount. + const VkDeviceSize minNodeSize = IsVirtual() ? 1 : 16; + m_LevelCount = 1; + while (m_LevelCount < MAX_LEVELS && + LevelToNodeSize(m_LevelCount) >= minNodeSize) + { + ++m_LevelCount; + } + + Node* rootNode = m_NodeAllocator.Alloc(); + rootNode->offset = 0; + rootNode->type = Node::TYPE_FREE; + rootNode->parent = VMA_NULL; + rootNode->buddy = VMA_NULL; + + m_Root = rootNode; + AddToFreeListFront(0, rootNode); +} + +bool VmaBlockMetadata_Buddy::Validate() const +{ + // Validate tree. + ValidationContext ctx; + if (!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0))) + { + VMA_VALIDATE(false && "ValidateNode failed."); + } + VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount); + VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize); + + // Validate free node lists. + for (uint32_t level = 0; level < m_LevelCount; ++level) + { + VMA_VALIDATE(m_FreeList[level].front == VMA_NULL || + m_FreeList[level].front->free.prev == VMA_NULL); + + for (Node* node = m_FreeList[level].front; + node != VMA_NULL; + node = node->free.next) + { + VMA_VALIDATE(node->type == Node::TYPE_FREE); + + if (node->free.next == VMA_NULL) + { + VMA_VALIDATE(m_FreeList[level].back == node); + } + else + { + VMA_VALIDATE(node->free.next->free.prev == node); + } + } + } + + // Validate that free lists ar higher levels are empty. + for (uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level) + { + VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL); + } + + return true; +} + +void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const +{ + VmaInitStatInfo(outInfo); + outInfo.blockCount = 1; + + CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0)); + + const VkDeviceSize unusableSize = GetUnusableSize(); + if (unusableSize > 0) + { + VmaAddStatInfoUnusedRange(outInfo, unusableSize); + } +} + +void VmaBlockMetadata_Buddy::AddPoolStats(VmaPoolStats& inoutStats) const +{ + const VkDeviceSize unusableSize = GetUnusableSize(); + + inoutStats.size += GetSize(); + inoutStats.unusedSize += m_SumFreeSize + unusableSize; + inoutStats.allocationCount += m_AllocationCount; + inoutStats.unusedRangeCount += m_FreeCount; + + if (unusableSize > 0) + { + ++inoutStats.unusedRangeCount; + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const +{ + VmaStatInfo stat; + CalcAllocationStatInfo(stat); + + PrintDetailedMap_Begin( + json, + stat.unusedBytes, + stat.allocationCount, + stat.unusedRangeCount); + + PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0)); + + const VkDeviceSize unusableSize = GetUnusableSize(); + if (unusableSize > 0) + { + PrintDetailedMap_UnusedRange(json, + m_UsableSize, // offset + unusableSize); // size + } + + PrintDetailedMap_End(json); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaBlockMetadata_Buddy::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm."); + + allocSize = AlignAllocationSize(allocSize); + + // Simple way to respect bufferImageGranularity. May be optimized some day. + // Whenever it might be an OPTIMAL image... + if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL) + { + allocAlignment = VMA_MAX(allocAlignment, GetBufferImageGranularity()); + allocSize = VmaAlignUp(allocSize, GetBufferImageGranularity()); + } + + if (allocSize > m_UsableSize) + { + return false; + } + + const uint32_t targetLevel = AllocSizeToLevel(allocSize); + for (uint32_t level = targetLevel; level--; ) + { + for (Node* freeNode = m_FreeList[level].front; + freeNode != VMA_NULL; + freeNode = freeNode->free.next) + { + if (freeNode->offset % allocAlignment == 0) + { + pAllocationRequest->type = VmaAllocationRequestType::Normal; + pAllocationRequest->allocHandle = (VmaAllocHandle)freeNode->offset; + pAllocationRequest->size = allocSize; + pAllocationRequest->customData = (void*)(uintptr_t)level; + return true; + } + } + } + + return false; +} + +void VmaBlockMetadata_Buddy::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + VMA_ASSERT(request.type == VmaAllocationRequestType::Normal); + + const uint32_t targetLevel = AllocSizeToLevel(request.size); + uint32_t currLevel = (uint32_t)(uintptr_t)request.customData; + + Node* currNode = m_FreeList[currLevel].front; + VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE); + while (currNode->offset != (VkDeviceSize)request.allocHandle) + { + currNode = currNode->free.next; + VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE); + } + + // Go down, splitting free nodes. + while (currLevel < targetLevel) + { + // currNode is already first free node at currLevel. + // Remove it from list of free nodes at this currLevel. + RemoveFromFreeList(currLevel, currNode); + + const uint32_t childrenLevel = currLevel + 1; + + // Create two free sub-nodes. + Node* leftChild = m_NodeAllocator.Alloc(); + Node* rightChild = m_NodeAllocator.Alloc(); + + leftChild->offset = currNode->offset; + leftChild->type = Node::TYPE_FREE; + leftChild->parent = currNode; + leftChild->buddy = rightChild; + + rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel); + rightChild->type = Node::TYPE_FREE; + rightChild->parent = currNode; + rightChild->buddy = leftChild; + + // Convert current currNode to split type. + currNode->type = Node::TYPE_SPLIT; + currNode->split.leftChild = leftChild; + + // Add child nodes to free list. Order is important! + AddToFreeListFront(childrenLevel, rightChild); + AddToFreeListFront(childrenLevel, leftChild); + + ++m_FreeCount; + ++currLevel; + currNode = m_FreeList[currLevel].front; + + /* + We can be sure that currNode, as left child of node previously split, + also fulfills the alignment requirement. + */ + } + + // Remove from free list. + VMA_ASSERT(currLevel == targetLevel && + currNode != VMA_NULL && + currNode->type == Node::TYPE_FREE); + RemoveFromFreeList(currLevel, currNode); + + // Convert to allocation node. + currNode->type = Node::TYPE_ALLOCATION; + currNode->allocation.userData = userData; + + ++m_AllocationCount; + --m_FreeCount; + m_SumFreeSize -= request.size; +} + +void VmaBlockMetadata_Buddy::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + uint32_t level = 0; + const Node* const node = FindAllocationNode((VkDeviceSize)allocHandle, level); + outInfo.offset = (VkDeviceSize)allocHandle; + outInfo.size = LevelToNodeSize(level); + outInfo.pUserData = node->allocation.userData; +} + +void VmaBlockMetadata_Buddy::DeleteNodeChildren(Node* node) +{ + if (node->type == Node::TYPE_SPLIT) + { + DeleteNodeChildren(node->split.leftChild->buddy); + DeleteNodeChildren(node->split.leftChild); + const VkAllocationCallbacks* allocationCallbacks = GetAllocationCallbacks(); + m_NodeAllocator.Free(node->split.leftChild->buddy); + m_NodeAllocator.Free(node->split.leftChild); + } +} + +void VmaBlockMetadata_Buddy::Clear() +{ + DeleteNodeChildren(m_Root); + m_Root->type = Node::TYPE_FREE; + m_AllocationCount = 0; + m_FreeCount = 1; + m_SumFreeSize = m_UsableSize; +} + +void VmaBlockMetadata_Buddy::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + uint32_t level = 0; + Node* const node = FindAllocationNode((VkDeviceSize)allocHandle, level); + node->allocation.userData = userData; +} + +VmaBlockMetadata_Buddy::Node* VmaBlockMetadata_Buddy::FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel) +{ + Node* node = m_Root; + VkDeviceSize nodeOffset = 0; + outLevel = 0; + VkDeviceSize levelNodeSize = LevelToNodeSize(0); + while (node->type == Node::TYPE_SPLIT) + { + const VkDeviceSize nextLevelNodeSize = levelNodeSize >> 1; + if (offset < nodeOffset + nextLevelNodeSize) + { + node = node->split.leftChild; + } + else + { + node = node->split.leftChild->buddy; + nodeOffset += nextLevelNodeSize; + } + ++outLevel; + levelNodeSize = nextLevelNodeSize; + } + + VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION); + return node; +} + +bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const +{ + VMA_VALIDATE(level < m_LevelCount); + VMA_VALIDATE(curr->parent == parent); + VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL)); + VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr); + switch (curr->type) + { + case Node::TYPE_FREE: + // curr->free.prev, next are validated separately. + ctx.calculatedSumFreeSize += levelNodeSize; + ++ctx.calculatedFreeCount; + break; + case Node::TYPE_ALLOCATION: + ++ctx.calculatedAllocationCount; + if (!IsVirtual()) + { + VMA_VALIDATE(curr->allocation.userData != VMA_NULL); + } + break; + case Node::TYPE_SPLIT: + { + const uint32_t childrenLevel = level + 1; + const VkDeviceSize childrenLevelNodeSize = levelNodeSize >> 1; + const Node* const leftChild = curr->split.leftChild; + VMA_VALIDATE(leftChild != VMA_NULL); + VMA_VALIDATE(leftChild->offset == curr->offset); + if (!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize)) + { + VMA_VALIDATE(false && "ValidateNode for left child failed."); + } + const Node* const rightChild = leftChild->buddy; + VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize); + if (!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize)) + { + VMA_VALIDATE(false && "ValidateNode for right child failed."); + } + } + break; + default: + return false; + } + + return true; +} + +uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const +{ + // I know this could be optimized somehow e.g. by using std::log2p1 from C++20. + uint32_t level = 0; + VkDeviceSize currLevelNodeSize = m_UsableSize; + VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1; + while (allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount) + { + ++level; + currLevelNodeSize >>= 1; + nextLevelNodeSize >>= 1; + } + return level; +} + +void VmaBlockMetadata_Buddy::Free(VmaAllocHandle allocHandle) +{ + uint32_t level = 0; + Node* node = FindAllocationNode((VkDeviceSize)allocHandle, level); + + ++m_FreeCount; + --m_AllocationCount; + m_SumFreeSize += LevelToNodeSize(level); + + node->type = Node::TYPE_FREE; + + // Join free nodes if possible. + while (level > 0 && node->buddy->type == Node::TYPE_FREE) + { + RemoveFromFreeList(level, node->buddy); + Node* const parent = node->parent; + + m_NodeAllocator.Free(node->buddy); + m_NodeAllocator.Free(node); + parent->type = Node::TYPE_FREE; + + node = parent; + --level; + --m_FreeCount; + } + + AddToFreeListFront(level, node); +} + +void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& inoutInfo, const Node* node, VkDeviceSize levelNodeSize) const +{ + switch (node->type) + { + case Node::TYPE_FREE: + VmaAddStatInfoUnusedRange(inoutInfo, levelNodeSize); + break; + case Node::TYPE_ALLOCATION: + VmaAddStatInfoAllocation(inoutInfo, levelNodeSize); + break; + case Node::TYPE_SPLIT: + { + const VkDeviceSize childrenNodeSize = levelNodeSize / 2; + const Node* const leftChild = node->split.leftChild; + CalcAllocationStatInfoNode(inoutInfo, leftChild, childrenNodeSize); + const Node* const rightChild = leftChild->buddy; + CalcAllocationStatInfoNode(inoutInfo, rightChild, childrenNodeSize); + } + break; + default: + VMA_ASSERT(0); + } +} + +void VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node) +{ + VMA_ASSERT(node->type == Node::TYPE_FREE); + + // List is empty. + Node* const frontNode = m_FreeList[level].front; + if (frontNode == VMA_NULL) + { + VMA_ASSERT(m_FreeList[level].back == VMA_NULL); + node->free.prev = node->free.next = VMA_NULL; + m_FreeList[level].front = m_FreeList[level].back = node; + } + else + { + VMA_ASSERT(frontNode->free.prev == VMA_NULL); + node->free.prev = VMA_NULL; + node->free.next = frontNode; + frontNode->free.prev = node; + m_FreeList[level].front = node; + } +} + +void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node) +{ + VMA_ASSERT(m_FreeList[level].front != VMA_NULL); + + // It is at the front. + if (node->free.prev == VMA_NULL) + { + VMA_ASSERT(m_FreeList[level].front == node); + m_FreeList[level].front = node->free.next; + } + else + { + Node* const prevFreeNode = node->free.prev; + VMA_ASSERT(prevFreeNode->free.next == node); + prevFreeNode->free.next = node->free.next; + } + + // It is at the back. + if (node->free.next == VMA_NULL) + { + VMA_ASSERT(m_FreeList[level].back == node); + m_FreeList[level].back = node->free.prev; + } + else + { + Node* const nextFreeNode = node->free.next; + VMA_ASSERT(nextFreeNode->free.prev == node); + nextFreeNode->free.prev = node->free.prev; + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const +{ + switch (node->type) + { + case Node::TYPE_FREE: + PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize); + break; + case Node::TYPE_ALLOCATION: + PrintDetailedMap_Allocation(json, node->offset, levelNodeSize, node->allocation.userData); + break; + case Node::TYPE_SPLIT: + { + const VkDeviceSize childrenNodeSize = levelNodeSize / 2; + const Node* const leftChild = node->split.leftChild; + PrintDetailedMapNode(json, leftChild, childrenNodeSize); + const Node* const rightChild = leftChild->buddy; + PrintDetailedMapNode(json, rightChild, childrenNodeSize); + } + break; + default: + VMA_ASSERT(0); + } +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_BUDDY + +#ifndef _VMA_BLOCK_METADATA_TLSF +// To not search current larger region if first allocation won't succeed and skip to smaller range +// use with VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT as strategy in CreateAllocationRequest() +class VmaBlockMetadata_TLSF : public VmaBlockMetadata +{ + VMA_CLASS_NO_COPY(VmaBlockMetadata_TLSF) +public: + VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata_TLSF(); + + size_t GetAllocationCount() const override { return m_AllocCount; } + VkDeviceSize GetSumFreeSize() const override { return m_BlocksFreeSize + m_NullBlock->size; } + bool IsEmpty() const override { return m_NullBlock->offset == 0; } + VkResult CheckCorruption(const void* pBlockData) override { return VK_ERROR_FEATURE_NOT_PRESENT; } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return ((Block*)allocHandle)->offset; }; + + void Init(VkDeviceSize size) override; + bool Validate() const override; + + void CalcAllocationStatInfo(VmaStatInfo& outInfo) const override; + void AddPoolStats(VmaPoolStats& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void Free(VmaAllocHandle allocHandle) override; + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + +private: + // According to original paper it should be preferable 4 or 5: + // M. Masmano, I. Ripoll, A. Crespo, and J. Real "TLSF: a New Dynamic Memory Allocator for Real-Time Systems" + // http://www.gii.upv.es/tlsf/files/ecrts04_tlsf.pdf + static const uint8_t SECOND_LEVEL_INDEX = 5; + static const uint16_t SMALL_BUFFER_SIZE = 256; + static const uint32_t INITIAL_BLOCK_ALLOC_COUNT = 16; + static const uint8_t MEMORY_CLASS_SHIFT = 7; + + struct RegionInfo + { + uint8_t allocType; + uint16_t allocCount; + }; + class Block + { + public: + VkDeviceSize offset; + VkDeviceSize size; + Block* prevPhysical; + Block* nextPhysical; + + void MarkFree() { prevFree = VMA_NULL; } + void MarkTaken() { prevFree = this; } + bool IsFree() const { return prevFree != this; } + void*& UserData() { VMA_HEAVY_ASSERT(!IsFree()); return userData; } + Block*& PrevFree() { return prevFree; } + Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; } + + private: + Block* prevFree; // Address of the same block here indicates that block is taken + union + { + Block* nextFree; + void* userData; + }; + }; + + size_t m_AllocCount; + // Total number of free blocks besides null block + size_t m_BlocksFreeCount; + // Total size of free blocks excluding null block + VkDeviceSize m_BlocksFreeSize; + uint32_t m_IsFree; + uint8_t m_MemoryClasses; + uint16_t* m_InnerIsFree; + uint32_t m_ListsCount; + /* + * 0: 0-3 lists for small buffers + * 1+: 0-(2^SLI-1) lists for normal buffers + */ + Block** m_FreeList; + VmaPoolAllocator m_BlockAllocator; + Block* m_NullBlock; + VmaBlockBufferImageGranularity m_GranularityHandler; + + uint8_t SizeToMemoryClass(VkDeviceSize size) const; + uint16_t SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const; + uint32_t GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const; + uint32_t GetListIndex(VkDeviceSize size) const; + + void RemoveFreeBlock(Block* block); + void InsertFreeBlock(Block* block); + void MergeBlock(Block* block, Block* prev); + + Block* FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const; + bool CheckBlock( + Block& block, + uint32_t listIndex, + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaAllocationRequest* pAllocationRequest); +}; + +#ifndef _VMA_BLOCK_METADATA_TLSF_FUNCTIONS +VmaBlockMetadata_TLSF::VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_AllocCount(0), + m_BlocksFreeCount(0), + m_BlocksFreeSize(0), + m_IsFree(0), + m_MemoryClasses(0), + m_InnerIsFree(VMA_NULL), + m_ListsCount(0), + m_FreeList(VMA_NULL), + m_BlockAllocator(pAllocationCallbacks, INITIAL_BLOCK_ALLOC_COUNT * sizeof(Block)), + m_NullBlock(VMA_NULL), + m_GranularityHandler(bufferImageGranularity) {} + +VmaBlockMetadata_TLSF::~VmaBlockMetadata_TLSF() +{ + if (m_InnerIsFree) + vma_delete_array(GetAllocationCallbacks(), m_InnerIsFree, m_MemoryClasses); + if (m_FreeList) + vma_delete_array(GetAllocationCallbacks(), m_FreeList, m_ListsCount); + m_GranularityHandler.Destroy(GetAllocationCallbacks()); +} + +void VmaBlockMetadata_TLSF::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + + if (!IsVirtual()) + m_GranularityHandler.Init(GetAllocationCallbacks(), size); + + m_NullBlock = m_BlockAllocator.Alloc(); + m_NullBlock->size = size; + m_NullBlock->offset = 0; + m_NullBlock->prevPhysical = VMA_NULL; + m_NullBlock->nextPhysical = VMA_NULL; + m_NullBlock->MarkFree(); + m_NullBlock->NextFree() = VMA_NULL; + m_NullBlock->PrevFree() = VMA_NULL; + uint8_t memoryClass = SizeToMemoryClass(size); + uint16_t sli = SizeToSecondIndex(size, memoryClass); + m_ListsCount = (memoryClass == 0 ? 0 : (memoryClass - 1) * (1UL << SECOND_LEVEL_INDEX) + sli) + 5; + + m_MemoryClasses = memoryClass + 2; + m_InnerIsFree = vma_new_array(GetAllocationCallbacks(), uint16_t, m_MemoryClasses); + memset(m_InnerIsFree, 0, m_MemoryClasses * sizeof(uint16_t)); + + m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount); + memset(m_FreeList, 0, m_ListsCount * sizeof(Block*)); +} + +bool VmaBlockMetadata_TLSF::Validate() const +{ + VMA_VALIDATE(GetSumFreeSize() <= GetSize()); + + VkDeviceSize calculatedSize = m_NullBlock->size; + VkDeviceSize calculatedFreeSize = m_NullBlock->size; + size_t allocCount = 0; + size_t freeCount = 0; + + // Check integrity of free lists + for (uint32_t list = 0; list < m_ListsCount; ++list) + { + Block* block = m_FreeList[list]; + if (block != VMA_NULL) + { + VMA_VALIDATE(block->IsFree()); + VMA_VALIDATE(block->PrevFree() == VMA_NULL); + while (block->NextFree()) + { + VMA_VALIDATE(block->NextFree()->IsFree()); + VMA_VALIDATE(block->NextFree()->PrevFree() == block); + block = block->NextFree(); + } + } + } + + VkDeviceSize nextOffset = m_NullBlock->offset; + auto validateCtx = m_GranularityHandler.StartValidation(GetAllocationCallbacks(), IsVirtual()); + + VMA_VALIDATE(m_NullBlock->nextPhysical == VMA_NULL); + if (m_NullBlock->prevPhysical) + { + VMA_VALIDATE(m_NullBlock->prevPhysical->nextPhysical == m_NullBlock); + } + // Check all blocks + for (Block* prev = m_NullBlock->prevPhysical; prev != VMA_NULL; prev = prev->prevPhysical) + { + VMA_VALIDATE(prev->offset + prev->size == nextOffset); + nextOffset = prev->offset; + calculatedSize += prev->size; + + uint32_t listIndex = GetListIndex(prev->size); + if (prev->IsFree()) + { + ++freeCount; + // Check if free block belongs to free list + Block* freeBlock = m_FreeList[listIndex]; + VMA_VALIDATE(freeBlock != VMA_NULL); + + bool found = false; + do + { + if (freeBlock == prev) + found = true; + + freeBlock = freeBlock->NextFree(); + } while (!found && freeBlock != VMA_NULL); + + VMA_VALIDATE(found); + calculatedFreeSize += prev->size; + } + else + { + ++allocCount; + // Check if taken block is not on a free list + Block* freeBlock = m_FreeList[listIndex]; + while (freeBlock) + { + VMA_VALIDATE(freeBlock != prev); + freeBlock = freeBlock->NextFree(); + } + + if (!IsVirtual()) + { + VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size)); + } + } + + if (prev->prevPhysical) + { + VMA_VALIDATE(prev->prevPhysical->nextPhysical == prev); + } + } + + if (!IsVirtual()) + { + VMA_VALIDATE(m_GranularityHandler.FinishValidation(validateCtx)); + } + + VMA_VALIDATE(nextOffset == 0); + VMA_VALIDATE(calculatedSize == GetSize()); + VMA_VALIDATE(calculatedFreeSize == GetSumFreeSize()); + VMA_VALIDATE(allocCount == m_AllocCount); + VMA_VALIDATE(freeCount == m_BlocksFreeCount); + + return true; +} + +void VmaBlockMetadata_TLSF::CalcAllocationStatInfo(VmaStatInfo& outInfo) const +{ + VmaInitStatInfo(outInfo); + outInfo.blockCount = 1; + if (m_NullBlock->size > 0) + VmaAddStatInfoUnusedRange(outInfo, m_NullBlock->size); + + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + if (block->IsFree()) + VmaAddStatInfoUnusedRange(outInfo, block->size); + else + VmaAddStatInfoAllocation(outInfo, block->size); + } +} + +void VmaBlockMetadata_TLSF::AddPoolStats(VmaPoolStats& inoutStats) const +{ + inoutStats.size += GetSize(); + inoutStats.unusedSize += GetSumFreeSize(); + inoutStats.allocationCount += m_AllocCount; + inoutStats.unusedRangeCount += m_BlocksFreeCount; + if(m_NullBlock->size > 0) + ++inoutStats.unusedRangeCount; +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_TLSF::PrintDetailedMap(class VmaJsonWriter& json) const +{ + size_t blockCount = m_AllocCount + m_BlocksFreeCount; + VmaStlAllocator allocator(GetAllocationCallbacks()); + VmaVector> blockList(blockCount, allocator); + + size_t i = blockCount; + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + blockList[--i] = block; + } + VMA_ASSERT(i == 0); + + VmaStatInfo stat; + CalcAllocationStatInfo(stat); + + PrintDetailedMap_Begin(json, + stat.unusedBytes, + stat.allocationCount, + stat.unusedRangeCount); + + for (; i < blockCount; ++i) + { + Block* block = blockList[i]; + if (block->IsFree()) + PrintDetailedMap_UnusedRange(json, block->offset, block->size); + else + PrintDetailedMap_Allocation(json, block->offset, block->size, block->PrevFree()); + } + if (m_NullBlock->size > 0) + PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size); + + PrintDetailedMap_End(json); +} +#endif + +bool VmaBlockMetadata_TLSF::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(allocSize > 0 && "Cannot allocate empty block!"); + VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm."); + + // For small granularity round up + if (!IsVirtual()) + m_GranularityHandler.RoundupAllocRequest(allocType, allocSize, allocAlignment); + + // Quick check for too small pool + if (allocSize > GetSumFreeSize()) + return false; + + // If no free blocks in pool then check only null block + if (m_BlocksFreeCount == 0) + return CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest); + + VkDeviceSize roundedSize = allocSize; + if (allocSize >= (1 << SECOND_LEVEL_INDEX)) + { + // Round up to the next block + roundedSize += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX)) - 1; + } + + uint32_t listIndex = 0; + Block* block = FindFreeBlock(roundedSize, listIndex); + while (block) + { + if (CheckBlock(*block, listIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + block = block->NextFree(); + // Region does not meet requirements + if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT) + break; + } + + if ((strategy & VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT) == 0) + { + // No region in previous bucket, check null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + } + + // No other region found, check previous bucket + uint32_t prevListIndex = 0; + Block* prevListBlock = FindFreeBlock(allocSize, prevListIndex); + while (prevListBlock) + { + if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + prevListBlock = prevListBlock->NextFree(); + } + + if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT) + { + // No region in previous bucket, check null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + } + + // If all searches failed and first bucket still have some free regions then check it fully + while (block) + { + if (CheckBlock(*block, listIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + block = block->NextFree(); + } + + // Worst case, if bufferImageGranularity is causing free blocks to become not suitable then full search has to be done + if (!IsVirtual() && m_GranularityHandler.IsEnabled()) + { + while (++listIndex < m_ListsCount) + { + block = m_FreeList[listIndex]; + while (block) + { + if (CheckBlock(*block, listIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + block = block->NextFree(); + } + } + } + + // No more memory sadly + return false; +} + +void VmaBlockMetadata_TLSF::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + VMA_ASSERT(request.type == VmaAllocationRequestType::TLSF); + + // Get block and pop it from the free list + Block* currentBlock = (Block*)request.allocHandle; + VMA_ASSERT(currentBlock != VMA_NULL); + + if (currentBlock != m_NullBlock) + RemoveFreeBlock(currentBlock); + + // Append missing alignment to prev block or create new one + VMA_ASSERT(currentBlock->offset <= request.algorithmData); + VkDeviceSize misssingAlignment = request.algorithmData - currentBlock->offset; + if (misssingAlignment) + { + Block* prevBlock = currentBlock->prevPhysical; + VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!"); + + if (prevBlock->IsFree()) + { + uint32_t oldList = GetListIndex(prevBlock->size); + prevBlock->size += misssingAlignment; + // Check if new size crosses list bucket + if (oldList != GetListIndex(prevBlock->size)) + { + prevBlock->size -= misssingAlignment; + RemoveFreeBlock(prevBlock); + prevBlock->size += misssingAlignment; + InsertFreeBlock(prevBlock); + } + else + m_BlocksFreeSize += misssingAlignment; + } + else + { + Block* newBlock = m_BlockAllocator.Alloc(); + currentBlock->prevPhysical = newBlock; + prevBlock->nextPhysical = newBlock; + newBlock->prevPhysical = prevBlock; + newBlock->nextPhysical = currentBlock; + newBlock->size = misssingAlignment; + newBlock->offset = currentBlock->offset; + newBlock->MarkTaken(); + + InsertFreeBlock(newBlock); + } + + currentBlock->size -= misssingAlignment; + currentBlock->offset += misssingAlignment; + } + + if (currentBlock->size == request.size) + { + if (currentBlock == m_NullBlock) + { + // Setup new null block + m_NullBlock = m_BlockAllocator.Alloc(); + m_NullBlock->size = 0; + m_NullBlock->offset = currentBlock->offset + request.size; + m_NullBlock->prevPhysical = currentBlock; + m_NullBlock->nextPhysical = VMA_NULL; + m_NullBlock->MarkFree(); + m_NullBlock->PrevFree() = VMA_NULL; + m_NullBlock->NextFree() = VMA_NULL; + currentBlock->nextPhysical = m_NullBlock; + currentBlock->MarkTaken(); + } + } + else + { + VMA_ASSERT(currentBlock->size > request.size && "Proper block already found, shouldn't find smaller one!"); + + // Create new free block + Block* newBlock = m_BlockAllocator.Alloc(); + newBlock->size = currentBlock->size - request.size; + newBlock->offset = currentBlock->offset + request.size; + newBlock->prevPhysical = currentBlock; + newBlock->nextPhysical = currentBlock->nextPhysical; + currentBlock->nextPhysical = newBlock; + currentBlock->size = request.size; + + if (currentBlock == m_NullBlock) + { + m_NullBlock = newBlock; + m_NullBlock->MarkFree(); + m_NullBlock->NextFree() = VMA_NULL; + m_NullBlock->PrevFree() = VMA_NULL; + currentBlock->MarkTaken(); + } + else + { + newBlock->nextPhysical->prevPhysical = newBlock; + newBlock->MarkTaken(); + InsertFreeBlock(newBlock); + } + } + currentBlock->UserData() = userData; + + if (!IsVirtual()) + m_GranularityHandler.AllocPages((uint8_t)(uintptr_t)request.customData, + currentBlock->offset, currentBlock->size); + ++m_AllocCount; +} + +void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle) +{ + Block* block = (Block*)allocHandle; + Block* next = block->nextPhysical; + VMA_ASSERT(!block->IsFree() && "Block is already free!"); + + if (!IsVirtual()) + m_GranularityHandler.FreePages(block->offset, block->size); + --m_AllocCount; + + // Try merging + Block* prev = block->prevPhysical; + if (prev != VMA_NULL && prev->IsFree()) + { + RemoveFreeBlock(prev); + MergeBlock(block, prev); + } + + if (!next->IsFree()) + InsertFreeBlock(block); + else if (next == m_NullBlock) + MergeBlock(m_NullBlock, block); + else + { + RemoveFreeBlock(next); + MergeBlock(next, block); + InsertFreeBlock(next); + } +} + +void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + Block* block = (Block*)allocHandle; + VMA_ASSERT(!block->IsFree() && "Cannot get allocation info for free block!"); + outInfo.offset = block->offset; + outInfo.size = block->size; + outInfo.pUserData = block->UserData(); +} + +void VmaBlockMetadata_TLSF::Clear() +{ + m_AllocCount = 0; + m_BlocksFreeCount = 0; + m_BlocksFreeSize = 0; + m_IsFree = 0; + m_NullBlock->offset = 0; + m_NullBlock->size = GetSize(); + Block* block = m_NullBlock->prevPhysical; + m_NullBlock->prevPhysical = VMA_NULL; + while (block) + { + Block* prev = block->prevPhysical; + m_BlockAllocator.Free(block); + block = prev; + } + memset(m_FreeList, 0, m_ListsCount * sizeof(Block*)); + memset(m_InnerIsFree, 0, m_MemoryClasses * sizeof(uint16_t)); + m_GranularityHandler.Clear(); +} + +void VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + Block* block = (Block*)allocHandle; + VMA_ASSERT(!block->IsFree() && "Trying to set user data for not allocated block!"); + block->UserData() = userData; +} + +uint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) const +{ + if (size > SMALL_BUFFER_SIZE) + return VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT; + return 0; +} + +uint16_t VmaBlockMetadata_TLSF::SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const +{ + if (memoryClass == 0) + return static_cast((size - 1) / 64); + return static_cast((size >> (memoryClass + MEMORY_CLASS_SHIFT - SECOND_LEVEL_INDEX)) ^ (1U << SECOND_LEVEL_INDEX)); +} + +uint32_t VmaBlockMetadata_TLSF::GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const +{ + if (memoryClass == 0) + return secondIndex; + return static_cast(memoryClass - 1) * (1 << SECOND_LEVEL_INDEX) + secondIndex + 4; +} + +uint32_t VmaBlockMetadata_TLSF::GetListIndex(VkDeviceSize size) const +{ + uint8_t memoryClass = SizeToMemoryClass(size); + return GetListIndex(memoryClass, SizeToSecondIndex(size, memoryClass)); +} + +void VmaBlockMetadata_TLSF::RemoveFreeBlock(Block* block) +{ + VMA_ASSERT(block != m_NullBlock); + VMA_ASSERT(block->IsFree()); + + if (block->NextFree() != VMA_NULL) + block->NextFree()->PrevFree() = block->PrevFree(); + if (block->PrevFree() != VMA_NULL) + block->PrevFree()->NextFree() = block->NextFree(); + else + { + uint8_t memClass = SizeToMemoryClass(block->size); + uint16_t secondIndex = SizeToSecondIndex(block->size, memClass); + uint32_t index = GetListIndex(memClass, secondIndex); + m_FreeList[index] = block->NextFree(); + if (block->NextFree() == VMA_NULL) + { + m_InnerIsFree[memClass] &= ~(1U << secondIndex); + if (m_InnerIsFree[memClass] == 0) + m_IsFree &= ~(1UL << memClass); + } + } + block->MarkTaken(); + block->UserData() = VMA_NULL; + --m_BlocksFreeCount; + m_BlocksFreeSize -= block->size; +} + +void VmaBlockMetadata_TLSF::InsertFreeBlock(Block* block) +{ + VMA_ASSERT(block != m_NullBlock); + VMA_ASSERT(!block->IsFree() && "Cannot insert block twice!"); + + uint8_t memClass = SizeToMemoryClass(block->size); + uint16_t secondIndex = SizeToSecondIndex(block->size, memClass); + uint32_t index = GetListIndex(memClass, secondIndex); + block->PrevFree() = VMA_NULL; + block->NextFree() = m_FreeList[index]; + m_FreeList[index] = block; + if (block->NextFree() != VMA_NULL) + block->NextFree()->PrevFree() = block; + else + { + m_InnerIsFree[memClass] |= 1U << secondIndex; + m_IsFree |= 1UL << memClass; + } + ++m_BlocksFreeCount; + m_BlocksFreeSize += block->size; +} + +void VmaBlockMetadata_TLSF::MergeBlock(Block* block, Block* prev) +{ + VMA_ASSERT(block->prevPhysical == prev && "Cannot merge seperate physical regions!"); + VMA_ASSERT(!prev->IsFree() && "Cannot merge block that belongs to free list!"); + + block->offset = prev->offset; + block->size += prev->size; + block->prevPhysical = prev->prevPhysical; + if (block->prevPhysical) + block->prevPhysical->nextPhysical = block; + m_BlockAllocator.Free(prev); +} + +VmaBlockMetadata_TLSF::Block* VmaBlockMetadata_TLSF::FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const +{ + uint8_t memoryClass = SizeToMemoryClass(size); + uint16_t innerFreeMap = m_InnerIsFree[memoryClass] & (~0U << SizeToSecondIndex(size, memoryClass)); + if (!innerFreeMap) + { + // Check higher levels for avaiable blocks + uint32_t freeMap = m_IsFree & (~0UL << (memoryClass + 1)); + if (!freeMap) + return VMA_NULL; // No more memory avaible + + // Find lowest free region + innerFreeMap = m_InnerIsFree[VMA_BITSCAN_LSB(freeMap)]; + } + // Find lowest free subregion + listIndex = GetListIndex(memoryClass, VMA_BITSCAN_LSB(static_cast(innerFreeMap))); + return m_FreeList[listIndex]; +} + +bool VmaBlockMetadata_TLSF::CheckBlock( + Block& block, + uint32_t listIndex, + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(block.IsFree() && "Block is already taken!"); + + VkDeviceSize alignedOffset = VmaAlignUp(block.offset, allocAlignment); + if (block.size < allocSize + alignedOffset - block.offset) + return false; + + // Check for granularity conflicts + if (!IsVirtual() && + m_GranularityHandler.IsConflict(allocSize, alignedOffset, block.size, block.offset, allocType)) + return false; + + // Alloc successful + pAllocationRequest->type = VmaAllocationRequestType::TLSF; + pAllocationRequest->allocHandle = (VmaAllocHandle)█ + pAllocationRequest->size = allocSize; + pAllocationRequest->customData = (void*)allocType; + pAllocationRequest->algorithmData = alignedOffset; + + // Place block at the start of list if it's normal block + if (listIndex != m_ListsCount && block.PrevFree()) + { + block.PrevFree()->NextFree() = block.NextFree(); + if (block.NextFree()) + block.NextFree()->PrevFree() = block.PrevFree(); + block.PrevFree() = VMA_NULL; + block.NextFree() = m_FreeList[listIndex]; + m_FreeList[listIndex] = █ + if (block.NextFree()) + block.NextFree()->PrevFree() = █ + } + + return true; +} +#endif // _VMA_BLOCK_METADATA_TLSF_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_TLSF + +#ifndef _VMA_BLOCK_VECTOR +/* +Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific +Vulkan memory type. + +Synchronized internally with a mutex. +*/ +class VmaBlockVector +{ + friend class VmaDefragmentationAlgorithm_Generic; + VMA_CLASS_NO_COPY(VmaBlockVector) +public: + VmaBlockVector( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceSize preferredBlockSize, + size_t minBlockCount, + size_t maxBlockCount, + VkDeviceSize bufferImageGranularity, + bool explicitBlockSize, + uint32_t algorithm, + float priority, + VkDeviceSize minAllocationAlignment, + void* pMemoryAllocateNext); + ~VmaBlockVector(); + + VmaAllocator GetAllocator() const { return m_hAllocator; } + VmaPool GetParentPool() const { return m_hParentPool; } + bool IsCustomPool() const { return m_hParentPool != VMA_NULL; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; } + VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } + uint32_t GetAlgorithm() const { return m_Algorithm; } + bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; } + float GetPriority() const { return m_Priority; } + void* const GetAllocationNextPtr() const { return m_pMemoryAllocateNext; } + + VkResult CreateMinBlocks(); + void AddPoolStats(VmaPoolStats* pStats); + bool IsEmpty(); + bool IsCorruptionDetectionEnabled() const; + + VkResult Allocate( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations); + + void Free(const VmaAllocation hAllocation); + // Adds statistics of this BlockVector to pStats. + void AddStats(VmaStats* pStats); + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json); +#endif + + VkResult CheckCorruption(); + + // Saves results in pCtx->res. + void Defragment( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags, + VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove, + VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove, + VkCommandBuffer commandBuffer); + void DefragmentationEnd( + class VmaBlockVectorDefragmentationContext* pCtx, + uint32_t flags, + VmaDefragmentationStats* pStats); + + uint32_t ProcessDefragmentations( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves); + + void CommitDefragmentations( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationStats* pStats); + + //////////////////////////////////////////////////////////////////////////////// + // To be used only while the m_Mutex is locked. Used during defragmentation. + + size_t GetBlockCount() const { return m_Blocks.size(); } + VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; } + size_t CalcAllocationCount() const; + bool IsBufferImageGranularityConflictPossible() const; + +private: + const VmaAllocator m_hAllocator; + const VmaPool m_hParentPool; + const uint32_t m_MemoryTypeIndex; + const VkDeviceSize m_PreferredBlockSize; + const size_t m_MinBlockCount; + const size_t m_MaxBlockCount; + const VkDeviceSize m_BufferImageGranularity; + const bool m_ExplicitBlockSize; + const uint32_t m_Algorithm; + const float m_Priority; + const VkDeviceSize m_MinAllocationAlignment; + + void* const m_pMemoryAllocateNext; + VMA_RW_MUTEX m_Mutex; + /* There can be at most one allocation that is completely empty (except when minBlockCount > 0) - + a hysteresis to avoid pessimistic case of alternating creation and destruction of a VkDeviceMemory. */ + bool m_HasEmptyBlock; + // Incrementally sorted by sumFreeSize, ascending. + VmaVector> m_Blocks; + uint32_t m_NextBlockId; + + VkDeviceSize CalcMaxBlockSize() const; + // Finds and removes given block from vector. + void Remove(VmaDeviceMemoryBlock* pBlock); + // Performs single step in sorting m_Blocks. They may not be fully sorted + // after this call. + void IncrementallySortBlocks(); + + VkResult AllocatePage( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + VmaAllocation* pAllocation); + + VkResult AllocateFromBlock( + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize size, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + uint32_t strategy, + VmaAllocation* pAllocation); + + VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex); + // Saves result to pCtx->res. + void ApplyDefragmentationMovesCpu( + VmaBlockVectorDefragmentationContext* pDefragCtx, + const VmaVector>& moves); + // Saves result to pCtx->res. + void ApplyDefragmentationMovesGpu( + VmaBlockVectorDefragmentationContext* pDefragCtx, + VmaVector>& moves, + VkCommandBuffer commandBuffer); + + /* + Used during defragmentation. pDefragmentationStats is optional. It is in/out + - updated with new data. + */ + void FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats); + void UpdateHasEmptyBlock(); +}; +#endif // _VMA_BLOCK_VECTOR + +#ifndef _VMA_DEFRAGMENTATION_ALGORITHM +struct VmaDefragmentationMove +{ + size_t srcBlockIndex; + size_t dstBlockIndex; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VmaAllocHandle dstHandle; + VkDeviceSize size; + VmaAllocation hAllocation; + VmaDeviceMemoryBlock* pSrcBlock; + VmaDeviceMemoryBlock* pDstBlock; +}; + +/* +Performs defragmentation: + +- Updates `pBlockVector->m_pMetadata`. +- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset(). +- Does not move actual data, only returns requested moves as `moves`. +*/ +class VmaDefragmentationAlgorithm +{ + VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm) +public: + VmaDefragmentationAlgorithm( + VmaAllocator hAllocator, + VmaBlockVector* pBlockVector) + : m_hAllocator(hAllocator), + m_pBlockVector(pBlockVector) {} + virtual ~VmaDefragmentationAlgorithm() = default; + + virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) = 0; + virtual void AddAll() = 0; + + virtual VkResult Defragment( + VmaVector>& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + VmaDefragmentationFlags flags) = 0; + + virtual VkDeviceSize GetBytesMoved() const = 0; + virtual uint32_t GetAllocationsMoved() const = 0; + +protected: + struct AllocationInfo + { + VmaAllocation m_hAllocation; + VkBool32* m_pChanged; + + AllocationInfo() : m_hAllocation(VK_NULL_HANDLE), m_pChanged(VMA_NULL) {} + AllocationInfo(VmaAllocation hAlloc, VkBool32* pChanged) : m_hAllocation(hAlloc), m_pChanged(pChanged) {} + }; + + VmaAllocator const m_hAllocator; + VmaBlockVector* const m_pBlockVector; +}; + +#endif // _VMA_DEFRAGMENTATION_ALGORITHM + +#ifndef _VMA_DEFRAGMENTATION_ALGORITHM_GENERIC +class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm +{ + VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic) +public: + VmaDefragmentationAlgorithm_Generic( + VmaAllocator hAllocator, + VmaBlockVector* pBlockVector, + bool overlappingMoveSupported); + virtual ~VmaDefragmentationAlgorithm_Generic(); + + virtual void AddAll() { m_AllAllocations = true; } + virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; } + virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; } + + virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged); + virtual VkResult Defragment( + VmaVector>& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + VmaDefragmentationFlags flags); + +private: + struct AllocationInfoSizeGreater + { + bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const; + }; + struct AllocationInfoOffsetGreater + { + bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const; + }; + struct BlockInfo + { + size_t m_OriginalBlockIndex; + VmaDeviceMemoryBlock* m_pBlock; + bool m_HasNonMovableAllocations; + VmaVector> m_Allocations; + + BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks); + + void CalcHasNonMovableAllocations(); + void SortAllocationsBySizeDescending(); + void SortAllocationsByOffsetDescending(); + }; + struct BlockPointerLess + { + bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const; + bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const; + }; + // 1. Blocks with some non-movable allocations go first. + // 2. Blocks with smaller sumFreeSize go first. + struct BlockInfoCompareMoveDestination + { + bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const; + }; + typedef VmaVector> BlockInfoVector; + + BlockInfoVector m_Blocks; + uint32_t m_AllocationCount; + bool m_AllAllocations; + VkDeviceSize m_BytesMoved; + uint32_t m_AllocationsMoved; + + static bool MoveMakesSense( + size_t dstBlockIndex, VkDeviceSize dstOffset, + size_t srcBlockIndex, VkDeviceSize srcOffset); + + size_t CalcBlocksWithNonMovableCount() const; + VkResult DefragmentRound( + VmaVector>& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + bool freeOldAllocations); +}; +#endif // _VMA_DEFRAGMENTATION_ALGORITHM_GENERIC + +#ifndef _VMA_DEFRAGMENTATION_ALGORITHM_FAST +class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm +{ + VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast) +public: + VmaDefragmentationAlgorithm_Fast( + VmaAllocator hAllocator, + VmaBlockVector* pBlockVector, + bool overlappingMoveSupported); + virtual ~VmaDefragmentationAlgorithm_Fast() = default; + + virtual void AddAll() { m_AllAllocations = true; } + virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; } + virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; } + virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; } + + virtual VkResult Defragment( + VmaVector< VmaDefragmentationMove, VmaStlAllocator >& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + VmaDefragmentationFlags flags); + +private: + struct BlockInfo + { + size_t origBlockIndex; + }; + class FreeSpaceDatabase + { + public: + FreeSpaceDatabase(); + + void Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size); + bool Fetch(VkDeviceSize alignment, VkDeviceSize size, + size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset); + + private: + static const size_t MAX_COUNT = 4; + + struct FreeSpace + { + size_t blockInfoIndex; // SIZE_MAX means this structure is invalid. + VkDeviceSize offset; + VkDeviceSize size; + } m_FreeSpaces[MAX_COUNT]; + }; + + const bool m_OverlappingMoveSupported; + + uint32_t m_AllocationCount; + bool m_AllAllocations; + VkDeviceSize m_BytesMoved; + uint32_t m_AllocationsMoved; + + VmaVector> m_BlockInfos; + + void PreprocessMetadata(); + void PostprocessMetadata(); + void InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc); +}; +#endif // _VMA_DEFRAGMENTATION_ALGORITHM_FAST + +#ifndef _VMA_BLOCK_VECTOR_DEFRAGMENTATION_CONTEXT +struct VmaBlockDefragmentationContext +{ + enum BLOCK_FLAG + { + BLOCK_FLAG_USED = 0x00000001, + }; + uint32_t flags; + VkBuffer hBuffer; +}; + +class VmaBlockVectorDefragmentationContext +{ + VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext) +public: + VkResult res; + bool mutexLocked; + VmaVector> blockContexts; + VmaVector> defragmentationMoves; + uint32_t defragmentationMovesProcessed; + uint32_t defragmentationMovesCommitted; + bool hasDefragmentationPlan; + + VmaBlockVectorDefragmentationContext( + VmaAllocator hAllocator, + VmaPool hCustomPool, // Optional. + VmaBlockVector* pBlockVector); + ~VmaBlockVectorDefragmentationContext(); + + VmaPool GetCustomPool() const { return m_hCustomPool; } + VmaBlockVector* GetBlockVector() const { return m_pBlockVector; } + VmaDefragmentationAlgorithm* GetAlgorithm() const { return m_pAlgorithm; } + void AddAll() { m_AllAllocations = true; } + + void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged); + void Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags); + +private: + struct AllocInfo + { + VmaAllocation hAlloc; + VkBool32* pChanged; + }; + + const VmaAllocator m_hAllocator; + // Null if not from custom pool. + const VmaPool m_hCustomPool; + // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors. + VmaBlockVector* const m_pBlockVector; + // Owner of this object. + VmaDefragmentationAlgorithm* m_pAlgorithm; + // Used between constructor and Begin. + VmaVector> m_Allocations; + bool m_AllAllocations; +}; +#endif // _VMA_BLOCK_VECTOR_DEFRAGMENTATION_CONTEXT + +#ifndef _VMA_DEFRAGMENTATION_CONTEXT +struct VmaDefragmentationContext_T +{ +private: + VMA_CLASS_NO_COPY(VmaDefragmentationContext_T) +public: + VmaDefragmentationContext_T( + VmaAllocator hAllocator, + uint32_t flags, + VmaDefragmentationStats* pStats); + ~VmaDefragmentationContext_T(); + + void AddPools(uint32_t poolCount, const VmaPool* pPools); + void AddAllocations( + uint32_t allocationCount, + const VmaAllocation* pAllocations, + VkBool32* pAllocationsChanged); + + /* + Returns: + - `VK_SUCCESS` if succeeded and object can be destroyed immediately. + - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd(). + - Negative value if error occurred and object can be destroyed immediately. + */ + VkResult Defragment( + VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove, + VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove, + VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags); + + VkResult DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo); + VkResult DefragmentPassEnd(); + +private: + const VmaAllocator m_hAllocator; + const uint32_t m_Flags; + VmaDefragmentationStats* const m_pStats; + + VkDeviceSize m_MaxCpuBytesToMove; + uint32_t m_MaxCpuAllocationsToMove; + VkDeviceSize m_MaxGpuBytesToMove; + uint32_t m_MaxGpuAllocationsToMove; + + // Owner of these objects. + VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES]; + // Owner of these objects. + VmaVector> m_CustomPoolContexts; +}; +#endif // _VMA_DEFRAGMENTATION_CONTEXT + +#ifndef _VMA_POOL_T +struct VmaPool_T +{ + friend struct VmaPoolListItemTraits; + VMA_CLASS_NO_COPY(VmaPool_T) +public: + VmaBlockVector m_BlockVector; + VmaDedicatedAllocationList m_DedicatedAllocations; + + VmaPool_T( + VmaAllocator hAllocator, + const VmaPoolCreateInfo& createInfo, + VkDeviceSize preferredBlockSize); + ~VmaPool_T(); + + uint32_t GetId() const { return m_Id; } + void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; } + + const char* GetName() const { return m_Name; } + void SetName(const char* pName); + +#if VMA_STATS_STRING_ENABLED + //void PrintDetailedMap(class VmaStringBuilder& sb); +#endif + +private: + uint32_t m_Id; + char* m_Name; + VmaPool_T* m_PrevPool = VMA_NULL; + VmaPool_T* m_NextPool = VMA_NULL; +}; + +struct VmaPoolListItemTraits +{ + typedef VmaPool_T ItemType; + + static ItemType* GetPrev(const ItemType* item) { return item->m_PrevPool; } + static ItemType* GetNext(const ItemType* item) { return item->m_NextPool; } + static ItemType*& AccessPrev(ItemType* item) { return item->m_PrevPool; } + static ItemType*& AccessNext(ItemType* item) { return item->m_NextPool; } +}; +#endif // _VMA_POOL_T + +#ifndef _VMA_CURRENT_BUDGET_DATA +struct VmaCurrentBudgetData +{ + VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS]; + VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS]; + +#if VMA_MEMORY_BUDGET + VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch; + VMA_RW_MUTEX m_BudgetMutex; + uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS]; + uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS]; + uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS]; +#endif // VMA_MEMORY_BUDGET + + VmaCurrentBudgetData(); + + void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize); + void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize); +}; + +#ifndef _VMA_CURRENT_BUDGET_DATA_FUNCTIONS +VmaCurrentBudgetData::VmaCurrentBudgetData() +{ + for (uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex) + { + m_BlockBytes[heapIndex] = 0; + m_AllocationBytes[heapIndex] = 0; +#if VMA_MEMORY_BUDGET + m_VulkanUsage[heapIndex] = 0; + m_VulkanBudget[heapIndex] = 0; + m_BlockBytesAtBudgetFetch[heapIndex] = 0; +#endif + } + +#if VMA_MEMORY_BUDGET + m_OperationsSinceBudgetFetch = 0; +#endif +} + +void VmaCurrentBudgetData::AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize) +{ + m_AllocationBytes[heapIndex] += allocationSize; +#if VMA_MEMORY_BUDGET + ++m_OperationsSinceBudgetFetch; +#endif +} + +void VmaCurrentBudgetData::RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize) +{ + VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize); + m_AllocationBytes[heapIndex] -= allocationSize; +#if VMA_MEMORY_BUDGET + ++m_OperationsSinceBudgetFetch; +#endif +} +#endif // _VMA_CURRENT_BUDGET_DATA_FUNCTIONS +#endif // _VMA_CURRENT_BUDGET_DATA + +#ifndef _VMA_ALLOCATION_OBJECT_ALLOCATOR +/* +Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects. +*/ +class VmaAllocationObjectAllocator +{ + VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator) +public: + VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) + : m_Allocator(pAllocationCallbacks, 1024) {} + + template VmaAllocation Allocate(Types&&... args); + void Free(VmaAllocation hAlloc); + +private: + VMA_MUTEX m_Mutex; + VmaPoolAllocator m_Allocator; +}; + +template +VmaAllocation VmaAllocationObjectAllocator::Allocate(Types&&... args) +{ + VmaMutexLock mutexLock(m_Mutex); + return m_Allocator.Alloc(std::forward(args)...); +} + +void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc) +{ + VmaMutexLock mutexLock(m_Mutex); + m_Allocator.Free(hAlloc); +} +#endif // _VMA_ALLOCATION_OBJECT_ALLOCATOR + +#ifndef _VMA_VIRTUAL_BLOCK_T +struct VmaVirtualBlock_T +{ + VMA_CLASS_NO_COPY(VmaVirtualBlock_T) +public: + const bool m_AllocationCallbacksSpecified; + const VkAllocationCallbacks m_AllocationCallbacks; + + VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo); + ~VmaVirtualBlock_T(); + + VkResult Init() { return VK_SUCCESS; } + bool IsEmpty() const { return m_Metadata->IsEmpty(); } + void Free(VmaVirtualAllocation allocation) { m_Metadata->Free((VmaAllocHandle)allocation); } + void SetAllocationUserData(VmaVirtualAllocation allocation, void* userData) { m_Metadata->SetAllocationUserData((VmaAllocHandle)allocation, userData); } + void Clear() { m_Metadata->Clear(); } + + const VkAllocationCallbacks* GetAllocationCallbacks() const; + void GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo); + VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation, + VkDeviceSize* outOffset); + void CalculateStats(VmaStatInfo& outStatInfo) const; +#if VMA_STATS_STRING_ENABLED + void BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const; +#endif + +private: + VmaBlockMetadata* m_Metadata; +}; + +#ifndef _VMA_VIRTUAL_BLOCK_T_FUNCTIONS +VmaVirtualBlock_T::VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo) + : m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL), + m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks) +{ + const uint32_t algorithm = createInfo.flags & VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK; + switch (algorithm) + { + case 0: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Generic)(VK_NULL_HANDLE, 1, true); + break; + case VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Buddy)(VK_NULL_HANDLE, 1, true); + break; + case VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Linear)(VK_NULL_HANDLE, 1, true); + break; + case VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_TLSF)(VK_NULL_HANDLE, 1, true); + break; + default: + VMA_ASSERT(0); + } + + m_Metadata->Init(createInfo.size); +} + +VmaVirtualBlock_T::~VmaVirtualBlock_T() +{ + // This is an important assert!!! + // Hitting it means you have some memory leak - unreleased virtual allocations. + VMA_ASSERT(m_Metadata->IsEmpty() && "Some virtual allocations were not freed before destruction of this virtual block!"); + + vma_delete(GetAllocationCallbacks(), m_Metadata); +} + +const VkAllocationCallbacks* VmaVirtualBlock_T::GetAllocationCallbacks() const +{ + return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL; +} + +void VmaVirtualBlock_T::GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo) +{ + m_Metadata->GetAllocationInfo((VmaAllocHandle)allocation, outInfo); +} + +VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation, + VkDeviceSize* outOffset) +{ + VmaAllocationRequest request = {}; + if (m_Metadata->CreateAllocationRequest( + createInfo.size, // allocSize + VMA_MAX(createInfo.alignment, (VkDeviceSize)1), // allocAlignment + (createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0, // upperAddress + VMA_SUBALLOCATION_TYPE_UNKNOWN, // allocType - unimportant + createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK, // strategy + &request)) + { + m_Metadata->Alloc(request, + VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant + createInfo.pUserData); + outAllocation = (VmaVirtualAllocation)request.allocHandle; + if(outOffset) + *outOffset = m_Metadata->GetAllocationOffset(request.allocHandle); + return VK_SUCCESS; + } + outAllocation = (VmaVirtualAllocation)VK_WHOLE_SIZE; + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + +void VmaVirtualBlock_T::CalculateStats(VmaStatInfo& outStatInfo) const +{ + m_Metadata->CalcAllocationStatInfo(outStatInfo); + VmaPostprocessCalcStatInfo(outStatInfo); +} + +#if VMA_STATS_STRING_ENABLED +void VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const +{ + VmaJsonWriter json(GetAllocationCallbacks(), sb); + json.BeginObject(); + + VmaStatInfo stat = {}; + CalculateStats(stat); + + json.WriteString("Stats"); + VmaPrintStatInfo(json, stat); + + if (detailedMap) + { + json.WriteString("Details"); + m_Metadata->PrintDetailedMap(json); + } + + json.EndObject(); +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS +#endif // _VMA_VIRTUAL_BLOCK_T + +// Main allocator object. +struct VmaAllocator_T +{ + VMA_CLASS_NO_COPY(VmaAllocator_T) +public: + bool m_UseMutex; + uint32_t m_VulkanApiVersion; + bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0). + bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0). + bool m_UseExtMemoryBudget; + bool m_UseAmdDeviceCoherentMemory; + bool m_UseKhrBufferDeviceAddress; + bool m_UseExtMemoryPriority; + VkDevice m_hDevice; + VkInstance m_hInstance; + bool m_AllocationCallbacksSpecified; + VkAllocationCallbacks m_AllocationCallbacks; + VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks; + VmaAllocationObjectAllocator m_AllocationObjectAllocator; + + // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size. + uint32_t m_HeapSizeLimitMask; + + VkPhysicalDeviceProperties m_PhysicalDeviceProperties; + VkPhysicalDeviceMemoryProperties m_MemProps; + + // Default pools. + VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES]; + VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES]; + + VmaCurrentBudgetData m_Budget; + VMA_ATOMIC_UINT32 m_DeviceMemoryCount; // Total number of VkDeviceMemory objects. + + VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo); + VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo); + ~VmaAllocator_T(); + + const VkAllocationCallbacks* GetAllocationCallbacks() const + { + return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL; + } + const VmaVulkanFunctions& GetVulkanFunctions() const + { + return m_VulkanFunctions; + } + + VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; } + + VkDeviceSize GetBufferImageGranularity() const + { + return VMA_MAX( + static_cast(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY), + m_PhysicalDeviceProperties.limits.bufferImageGranularity); + } + + uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; } + uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; } + + uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const + { + VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount); + return m_MemProps.memoryTypes[memTypeIndex].heapIndex; + } + // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT. + bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const + { + return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + } + // Minimum alignment for all allocations in specific memory type. + VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const + { + return IsMemoryTypeNonCoherent(memTypeIndex) ? + VMA_MAX((VkDeviceSize)VMA_MIN_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) : + (VkDeviceSize)VMA_MIN_ALIGNMENT; + } + + bool IsIntegratedGpu() const + { + return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + } + + uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; } + + void GetBufferMemoryRequirements( + VkBuffer hBuffer, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const; + void GetImageMemoryRequirements( + VkImage hImage, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const; + + // Main allocation function. + VkResult AllocateMemory( + const VkMemoryRequirements& vkMemReq, + bool requiresDedicatedAllocation, + bool prefersDedicatedAllocation, + VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, // UINT32_MAX when unknown. + VkImage dedicatedImage, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations); + + // Main deallocation function. + void FreeMemory( + size_t allocationCount, + const VmaAllocation* pAllocations); + + void CalculateStats(VmaStats* pStats); + + void GetHeapBudgets( + VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount); + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json); +#endif + + VkResult DefragmentationBegin( + const VmaDefragmentationInfo2& info, + VmaDefragmentationStats* pStats, + VmaDefragmentationContext* pContext); + VkResult DefragmentationEnd( + VmaDefragmentationContext context); + + VkResult DefragmentationPassBegin( + VmaDefragmentationPassInfo* pInfo, + VmaDefragmentationContext context); + VkResult DefragmentationPassEnd( + VmaDefragmentationContext context); + + void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo); + + VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool); + void DestroyPool(VmaPool pool); + void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats); + + void SetCurrentFrameIndex(uint32_t frameIndex); + uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); } + + VkResult CheckPoolCorruption(VmaPool hPool); + VkResult CheckCorruption(uint32_t memoryTypeBits); + + // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping. + VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory); + // Call to Vulkan function vkFreeMemory with accompanying bookkeeping. + void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory); + // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR. + VkResult BindVulkanBuffer( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkBuffer buffer, + const void* pNext); + // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR. + VkResult BindVulkanImage( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkImage image, + const void* pNext); + + VkResult Map(VmaAllocation hAllocation, void** ppData); + void Unmap(VmaAllocation hAllocation); + + VkResult BindBufferMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext); + VkResult BindImageMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext); + + VkResult FlushOrInvalidateAllocation( + VmaAllocation hAllocation, + VkDeviceSize offset, VkDeviceSize size, + VMA_CACHE_OPERATION op); + VkResult FlushOrInvalidateAllocations( + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, const VkDeviceSize* sizes, + VMA_CACHE_OPERATION op); + + void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern); + + /* + Returns bit mask of memory types that can support defragmentation on GPU as + they support creation of required buffer for copy operations. + */ + uint32_t GetGpuDefragmentationMemoryTypeBits(); + +#if VMA_EXTERNAL_MEMORY + VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const + { + return m_TypeExternalMemoryHandleTypes[memTypeIndex]; + } +#endif // #if VMA_EXTERNAL_MEMORY + +private: + VkDeviceSize m_PreferredLargeHeapBlockSize; + + VkPhysicalDevice m_PhysicalDevice; + VMA_ATOMIC_UINT32 m_CurrentFrameIndex; + VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized. +#if VMA_EXTERNAL_MEMORY + VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES]; +#endif // #if VMA_EXTERNAL_MEMORY + + VMA_RW_MUTEX m_PoolsMutex; + typedef VmaIntrusiveLinkedList PoolList; + // Protected by m_PoolsMutex. + PoolList m_Pools; + uint32_t m_NextPoolId; + + VmaVulkanFunctions m_VulkanFunctions; + + // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types. + uint32_t m_GlobalMemoryTypeBits; + + void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions); + +#if VMA_STATIC_VULKAN_FUNCTIONS == 1 + void ImportVulkanFunctions_Static(); +#endif + + void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions); + +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + void ImportVulkanFunctions_Dynamic(); +#endif + + void ValidateVulkanFunctions(); + + VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex); + + VkResult AllocateMemoryOfType( + VmaPool pool, + VkDeviceSize size, + VkDeviceSize alignment, + bool dedicatedPreferred, + VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, + VkImage dedicatedImage, + const VmaAllocationCreateInfo& createInfo, + uint32_t memTypeIndex, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + VmaBlockVector& blockVector, + size_t allocationCount, + VmaAllocation* pAllocations); + + // Helper function only to be used inside AllocateDedicatedMemory. + VkResult AllocateDedicatedMemoryPage( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + uint32_t memTypeIndex, + const VkMemoryAllocateInfo& allocInfo, + bool map, + bool isUserDataString, + void* pUserData, + VmaAllocation* pAllocation); + + // Allocates and registers new VkDeviceMemory specifically for dedicated allocations. + VkResult AllocateDedicatedMemory( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + uint32_t memTypeIndex, + bool map, + bool isUserDataString, + bool canAliasMemory, + void* pUserData, + float priority, + VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, + VkImage dedicatedImage, + size_t allocationCount, + VmaAllocation* pAllocations, + const void* pNextChain = nullptr); + + void FreeDedicatedMemory(const VmaAllocation allocation); + + VkResult CalcMemTypeParams( + VmaAllocationCreateInfo& outCreateInfo, + uint32_t memTypeIndex, + VkDeviceSize size, + size_t allocationCount); + VkResult CalcAllocationParams( + VmaAllocationCreateInfo& outCreateInfo, + bool dedicatedRequired, + bool dedicatedPreferred); + + /* + Calculates and returns bit mask of memory types that can support defragmentation + on GPU as they support creation of required buffer for copy operations. + */ + uint32_t CalculateGpuDefragmentationMemoryTypeBits() const; + uint32_t CalculateGlobalMemoryTypeBits() const; + + bool GetFlushOrInvalidateRange( + VmaAllocation allocation, + VkDeviceSize offset, VkDeviceSize size, + VkMappedMemoryRange& outRange) const; + +#if VMA_MEMORY_BUDGET + void UpdateVulkanBudget(); +#endif // #if VMA_MEMORY_BUDGET +}; + + +#ifndef _VMA_MEMORY_FUNCTIONS +static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment) +{ + return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment); +} + +static void VmaFree(VmaAllocator hAllocator, void* ptr) +{ + VmaFree(&hAllocator->m_AllocationCallbacks, ptr); +} + +template +static T* VmaAllocate(VmaAllocator hAllocator) +{ + return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T)); +} + +template +static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count) +{ + return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T)); +} + +template +static void vma_delete(VmaAllocator hAllocator, T* ptr) +{ + if(ptr != VMA_NULL) + { + ptr->~T(); + VmaFree(hAllocator, ptr); + } +} + +template +static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count) +{ + if(ptr != VMA_NULL) + { + for(size_t i = count; i--; ) + ptr[i].~T(); + VmaFree(hAllocator, ptr); + } +} +#endif // _VMA_MEMORY_FUNCTIONS + +#ifndef _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS +VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) + : m_pMetadata(VMA_NULL), + m_MemoryTypeIndex(UINT32_MAX), + m_Id(0), + m_hMemory(VK_NULL_HANDLE), + m_MapCount(0), + m_pMappedData(VMA_NULL) {} + +VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock() +{ + VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped."); + VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); +} + +void VmaDeviceMemoryBlock::Init( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t newMemoryTypeIndex, + VkDeviceMemory newMemory, + VkDeviceSize newSize, + uint32_t id, + uint32_t algorithm, + VkDeviceSize bufferImageGranularity) +{ + VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); + + m_hParentPool = hParentPool; + m_MemoryTypeIndex = newMemoryTypeIndex; + m_Id = id; + m_hMemory = newMemory; + + switch (algorithm) + { + case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + break; + case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + break; + case VMA_POOL_CREATE_TLSF_ALGORITHM_BIT: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_TLSF)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + break; + default: + VMA_ASSERT(0); + // Fall-through. + case 0: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + } + m_pMetadata->Init(newSize); +} + +void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator) +{ + // This is the most important assert in the entire library. + // Hitting it means you have some memory leak - unreleased VmaAllocation objects. + VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!"); + + VMA_ASSERT(m_hMemory != VK_NULL_HANDLE); + allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory); + m_hMemory = VK_NULL_HANDLE; + + vma_delete(allocator, m_pMetadata); + m_pMetadata = VMA_NULL; +} + +bool VmaDeviceMemoryBlock::Validate() const +{ + VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) && + (m_pMetadata->GetSize() != 0)); + + return m_pMetadata->Validate(); +} + +VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator) +{ + void* pData = nullptr; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + res = m_pMetadata->CheckCorruption(pData); + + Unmap(hAllocator, 1); + + return res; +} + +VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData) +{ + if (count == 0) + { + return VK_SUCCESS; + } + + VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); + if (m_MapCount != 0) + { + m_MapCount += count; + VMA_ASSERT(m_pMappedData != VMA_NULL); + if (ppData != VMA_NULL) + { + *ppData = m_pMappedData; + } + return VK_SUCCESS; + } + else + { + VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)( + hAllocator->m_hDevice, + m_hMemory, + 0, // offset + VK_WHOLE_SIZE, + 0, // flags + &m_pMappedData); + if (result == VK_SUCCESS) + { + if (ppData != VMA_NULL) + { + *ppData = m_pMappedData; + } + m_MapCount = count; + } + return result; + } +} + +void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count) +{ + if (count == 0) + { + return; + } + + VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); + if (m_MapCount >= count) + { + m_MapCount -= count; + if (m_MapCount == 0) + { + m_pMappedData = VMA_NULL; + (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); + } + } + else + { + VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped."); + } +} + +VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize) +{ + VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION); + VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN); + + void* pData; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN); + VmaWriteMagicValue(pData, allocOffset + allocSize); + + Unmap(hAllocator, 1); + return VK_SUCCESS; +} + +VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize) +{ + VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION); + VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN); + + void* pData; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + if (!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!"); + } + else if (!VmaValidateMagicValue(pData, allocOffset + allocSize)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!"); + } + + Unmap(hAllocator, 1); + return VK_SUCCESS; +} + +VkResult VmaDeviceMemoryBlock::BindBufferMemory( + const VmaAllocator hAllocator, + const VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext) +{ + VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK && + hAllocation->GetBlock() == this); + VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() && + "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?"); + const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset; + // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads. + VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); + return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext); +} + +VkResult VmaDeviceMemoryBlock::BindImageMemory( + const VmaAllocator hAllocator, + const VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext) +{ + VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK && + hAllocation->GetBlock() == this); + VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() && + "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?"); + const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset; + // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads. + VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); + return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext); +} +#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS + +#ifndef _VMA_ALLOCATION_T_FUNCTIONS +VmaAllocation_T::VmaAllocation_T(bool userDataString) + : m_Alignment{ 1 }, + m_Size{ 0 }, + m_pUserData{ VMA_NULL }, + m_MemoryTypeIndex{ 0 }, + m_Type{ (uint8_t)ALLOCATION_TYPE_NONE }, + m_SuballocationType{ (uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN }, + m_MapCount{ 0 }, + m_Flags{ userDataString ? (uint8_t)FLAG_USER_DATA_STRING : (uint8_t)0 } +{ +#if VMA_STATS_STRING_ENABLED + m_BufferImageUsage = 0; +#endif +} + +VmaAllocation_T::~VmaAllocation_T() +{ + VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction."); + + // Check if owned string was freed. + VMA_ASSERT(m_pUserData == VMA_NULL); +} + +void VmaAllocation_T::InitBlockAllocation( + VmaDeviceMemoryBlock* block, + VmaAllocHandle allocHandle, + VkDeviceSize alignment, + VkDeviceSize size, + uint32_t memoryTypeIndex, + VmaSuballocationType suballocationType, + bool mapped) +{ + VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); + VMA_ASSERT(block != VMA_NULL); + m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK; + m_Alignment = alignment; + m_Size = size; + m_MemoryTypeIndex = memoryTypeIndex; + m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0; + m_SuballocationType = (uint8_t)suballocationType; + m_BlockAllocation.m_Block = block; + m_BlockAllocation.m_AllocHandle = allocHandle; +} + +void VmaAllocation_T::InitDedicatedAllocation( + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceMemory hMemory, + VmaSuballocationType suballocationType, + void* pMappedData, + VkDeviceSize size) +{ + VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); + VMA_ASSERT(hMemory != VK_NULL_HANDLE); + m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED; + m_Alignment = 0; + m_Size = size; + m_MemoryTypeIndex = memoryTypeIndex; + m_SuballocationType = (uint8_t)suballocationType; + m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0; + m_DedicatedAllocation.m_hParentPool = hParentPool; + m_DedicatedAllocation.m_hMemory = hMemory; + m_DedicatedAllocation.m_pMappedData = pMappedData; + m_DedicatedAllocation.m_Prev = VMA_NULL; + m_DedicatedAllocation.m_Next = VMA_NULL; +} void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData) { - if(IsUserDataString()) + if (IsUserDataString()) { VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData); FreeUserDataString(hAllocator); - if(pUserData != VMA_NULL) + if (pUserData != VMA_NULL) { - const char* const newStrSrc = (char*)pUserData; - const size_t newStrLen = strlen(newStrSrc); - char* const newStrDst = vma_new_array(hAllocator, char, newStrLen + 1); - memcpy(newStrDst, newStrSrc, newStrLen + 1); - m_pUserData = newStrDst; + m_pUserData = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), (const char*)pUserData); } } else @@ -4385,12 +11638,54 @@ void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData) } } -VkDeviceSize VmaAllocation_T::GetOffset() const +void VmaAllocation_T::ChangeBlockAllocation( + VmaAllocator hAllocator, + VmaDeviceMemoryBlock* block, + VmaAllocHandle allocHandle) { - switch(m_Type) + VMA_ASSERT(block != VMA_NULL); + VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); + + // Move mapping reference counter from old block to new block. + if (block != m_BlockAllocation.m_Block) + { + uint32_t mapRefCount = m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP; + if (IsPersistentMap()) + ++mapRefCount; + m_BlockAllocation.m_Block->Unmap(hAllocator, mapRefCount); + block->Map(hAllocator, mapRefCount, VMA_NULL); + } + + m_BlockAllocation.m_Block = block; + m_BlockAllocation.m_AllocHandle = allocHandle; +} + +void VmaAllocation_T::ChangeAllocHandle(VmaAllocHandle newAllocHandle) +{ + VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); + m_BlockAllocation.m_AllocHandle = newAllocHandle; +} + +VmaAllocHandle VmaAllocation_T::GetAllocHandle() const +{ + switch (m_Type) { case ALLOCATION_TYPE_BLOCK: - return m_BlockAllocation.m_Offset; + return m_BlockAllocation.m_AllocHandle; + case ALLOCATION_TYPE_DEDICATED: + return VMA_NULL; + default: + VMA_ASSERT(0); + return VMA_NULL; + } +} + +VkDeviceSize VmaAllocation_T::GetOffset() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->m_pMetadata->GetAllocationOffset(m_BlockAllocation.m_AllocHandle); case ALLOCATION_TYPE_DEDICATED: return 0; default: @@ -4399,12 +11694,26 @@ VkDeviceSize VmaAllocation_T::GetOffset() const } } -VkDeviceMemory VmaAllocation_T::GetMemory() const +VmaPool VmaAllocation_T::GetParentPool() const { - switch(m_Type) + switch (m_Type) { case ALLOCATION_TYPE_BLOCK: - return m_BlockAllocation.m_Block->m_hMemory; + return m_BlockAllocation.m_Block->GetParentPool(); + case ALLOCATION_TYPE_DEDICATED: + return m_DedicatedAllocation.m_hParentPool; + default: + VMA_ASSERT(0); + return VK_NULL_HANDLE; + } +} + +VkDeviceMemory VmaAllocation_T::GetMemory() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->GetDeviceMemory(); case ALLOCATION_TYPE_DEDICATED: return m_DedicatedAllocation.m_hMemory; default: @@ -4413,30 +11722,16 @@ VkDeviceMemory VmaAllocation_T::GetMemory() const } } -uint32_t VmaAllocation_T::GetMemoryTypeIndex() const -{ - switch(m_Type) - { - case ALLOCATION_TYPE_BLOCK: - return m_BlockAllocation.m_Block->m_MemoryTypeIndex; - case ALLOCATION_TYPE_DEDICATED: - return m_DedicatedAllocation.m_MemoryTypeIndex; - default: - VMA_ASSERT(0); - return UINT32_MAX; - } -} - void* VmaAllocation_T::GetMappedData() const { - switch(m_Type) + switch (m_Type) { case ALLOCATION_TYPE_BLOCK: - if(m_MapCount != 0) + if (m_MapCount != 0) { - void* pBlockData = m_BlockAllocation.m_Block->m_Mapping.GetMappedData(); + void* pBlockData = m_BlockAllocation.m_Block->GetMappedData(); VMA_ASSERT(pBlockData != VMA_NULL); - return (char*)pBlockData + m_BlockAllocation.m_Offset; + return (char*)pBlockData + GetOffset(); } else { @@ -4452,75 +11747,24 @@ void* VmaAllocation_T::GetMappedData() const } } -bool VmaAllocation_T::CanBecomeLost() const +void VmaAllocation_T::DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo) { - switch(m_Type) - { - case ALLOCATION_TYPE_BLOCK: - return m_BlockAllocation.m_CanBecomeLost; - case ALLOCATION_TYPE_DEDICATED: - return false; - default: - VMA_ASSERT(0); - return false; - } -} - -VmaPool VmaAllocation_T::GetPool() const -{ - VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); - return m_BlockAllocation.m_hPool; -} - -bool VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) -{ - VMA_ASSERT(CanBecomeLost()); - - /* - Warning: This is a carefully designed algorithm. - Do not modify unless you really know what you're doing :) - */ - uint32_t localLastUseFrameIndex = GetLastUseFrameIndex(); - for(;;) - { - if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST) - { - VMA_ASSERT(0); - return false; - } - else if(localLastUseFrameIndex + frameInUseCount >= currentFrameIndex) - { - return false; - } - else // Last use time earlier than current time. - { - if(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST)) - { - // Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST. - // Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock. - return true; - } - } - } -} - -void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator) -{ - VMA_ASSERT(IsUserDataString()); - if(m_pUserData != VMA_NULL) - { - char* const oldStr = (char*)m_pUserData; - const size_t oldStrLen = strlen(oldStr); - vma_delete_array(hAllocator, oldStr, oldStrLen + 1); - m_pUserData = VMA_NULL; - } + VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED); + outInfo.blockCount = 1; + outInfo.allocationCount = 1; + outInfo.unusedRangeCount = 0; + outInfo.usedBytes = m_Size; + outInfo.unusedBytes = 0; + outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size; + outInfo.unusedRangeSizeMin = UINT64_MAX; + outInfo.unusedRangeSizeMax = 0; } void VmaAllocation_T::BlockAllocMap() { VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK); - if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F) + if ((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F) { ++m_MapCount; } @@ -4534,7 +11778,7 @@ void VmaAllocation_T::BlockAllocUnmap() { VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK); - if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0) + if ((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0) { --m_MapCount; } @@ -4548,9 +11792,9 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa { VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED); - if(m_MapCount != 0) + if (m_MapCount != 0) { - if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F) + if ((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F) { VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL); *ppData = m_DedicatedAllocation.m_pMappedData; @@ -4572,7 +11816,7 @@ VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppDa VK_WHOLE_SIZE, 0, // flags ppData); - if(result == VK_SUCCESS) + if (result == VK_SUCCESS) { m_DedicatedAllocation.m_pMappedData = *ppData; m_MapCount = 1; @@ -4585,10 +11829,10 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator) { VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED); - if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0) + if ((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0) { --m_MapCount; - if(m_MapCount == 0) + if (m_MapCount == 0) { m_DedicatedAllocation.m_pMappedData = VMA_NULL; (*hAllocator->GetVulkanFunctions().vkUnmapMemory)( @@ -4603,1249 +11847,84 @@ void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator) } #if VMA_STATS_STRING_ENABLED - -// Correspond to values of enum VmaSuballocationType. -static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = { - "FREE", - "UNKNOWN", - "BUFFER", - "IMAGE_UNKNOWN", - "IMAGE_LINEAR", - "IMAGE_OPTIMAL", -}; - -static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat) +void VmaAllocation_T::InitBufferImageUsage(uint32_t bufferImageUsage) { - json.BeginObject(); - - json.WriteString("Blocks"); - json.WriteNumber(stat.blockCount); - - json.WriteString("Allocations"); - json.WriteNumber(stat.allocationCount); - - json.WriteString("UnusedRanges"); - json.WriteNumber(stat.unusedRangeCount); - - json.WriteString("UsedBytes"); - json.WriteNumber(stat.usedBytes); - - json.WriteString("UnusedBytes"); - json.WriteNumber(stat.unusedBytes); - - if(stat.allocationCount > 1) - { - json.WriteString("AllocationSize"); - json.BeginObject(true); - json.WriteString("Min"); - json.WriteNumber(stat.allocationSizeMin); - json.WriteString("Avg"); - json.WriteNumber(stat.allocationSizeAvg); - json.WriteString("Max"); - json.WriteNumber(stat.allocationSizeMax); - json.EndObject(); - } - - if(stat.unusedRangeCount > 1) - { - json.WriteString("UnusedRangeSize"); - json.BeginObject(true); - json.WriteString("Min"); - json.WriteNumber(stat.unusedRangeSizeMin); - json.WriteString("Avg"); - json.WriteNumber(stat.unusedRangeSizeAvg); - json.WriteString("Max"); - json.WriteNumber(stat.unusedRangeSizeMax); - json.EndObject(); - } - - json.EndObject(); + VMA_ASSERT(m_BufferImageUsage == 0); + m_BufferImageUsage = bufferImageUsage; } -#endif // #if VMA_STATS_STRING_ENABLED - -struct VmaSuballocationItemSizeLess +void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const { - bool operator()( - const VmaSuballocationList::iterator lhs, - const VmaSuballocationList::iterator rhs) const - { - return lhs->size < rhs->size; - } - bool operator()( - const VmaSuballocationList::iterator lhs, - VkDeviceSize rhsSize) const - { - return lhs->size < rhsSize; - } -}; + json.WriteString("Type"); + json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]); -//////////////////////////////////////////////////////////////////////////////// -// class VmaBlockMetadata - -VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) : - m_Size(0), - m_FreeCount(0), - m_SumFreeSize(0), - m_Suballocations(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), - m_FreeSuballocationsBySize(VmaStlAllocator(hAllocator->GetAllocationCallbacks())) -{ -} - -VmaBlockMetadata::~VmaBlockMetadata() -{ -} - -void VmaBlockMetadata::Init(VkDeviceSize size) -{ - m_Size = size; - m_FreeCount = 1; - m_SumFreeSize = size; - - VmaSuballocation suballoc = {}; - suballoc.offset = 0; - suballoc.size = size; - suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; - - m_Suballocations.push_back(suballoc); - VmaSuballocationList::iterator suballocItem = m_Suballocations.end(); - --suballocItem; - m_FreeSuballocationsBySize.push_back(suballocItem); -} - -bool VmaBlockMetadata::Validate() const -{ - if(m_Suballocations.empty()) - { - return false; - } - - // Expected offset of new suballocation as calculates from previous ones. - VkDeviceSize calculatedOffset = 0; - // Expected number of free suballocations as calculated from traversing their list. - uint32_t calculatedFreeCount = 0; - // Expected sum size of free suballocations as calculated from traversing their list. - VkDeviceSize calculatedSumFreeSize = 0; - // Expected number of free suballocations that should be registered in - // m_FreeSuballocationsBySize calculated from traversing their list. - size_t freeSuballocationsToRegister = 0; - // True if previous visisted suballocation was free. - bool prevFree = false; - - for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin(); - suballocItem != m_Suballocations.cend(); - ++suballocItem) - { - const VmaSuballocation& subAlloc = *suballocItem; - - // Actual offset of this suballocation doesn't match expected one. - if(subAlloc.offset != calculatedOffset) - { - return false; - } - - const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE); - // Two adjacent free suballocations are invalid. They should be merged. - if(prevFree && currFree) - { - return false; - } - prevFree = currFree; - - if(currFree != (subAlloc.hAllocation == VK_NULL_HANDLE)) - { - return false; - } - - if(currFree) - { - calculatedSumFreeSize += subAlloc.size; - ++calculatedFreeCount; - if(subAlloc.size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER) - { - ++freeSuballocationsToRegister; - } - } - - calculatedOffset += subAlloc.size; - } - - // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't - // match expected one. - if(m_FreeSuballocationsBySize.size() != freeSuballocationsToRegister) - { - return false; - } - - VkDeviceSize lastSize = 0; - for(size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i) - { - VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i]; - - // Only free suballocations can be registered in m_FreeSuballocationsBySize. - if(suballocItem->type != VMA_SUBALLOCATION_TYPE_FREE) - { - return false; - } - // They must be sorted by size ascending. - if(suballocItem->size < lastSize) - { - return false; - } - - lastSize = suballocItem->size; - } - - // Check if totals match calculacted values. - return - ValidateFreeSuballocationList() && - (calculatedOffset == m_Size) && - (calculatedSumFreeSize == m_SumFreeSize) && - (calculatedFreeCount == m_FreeCount); -} - -VkDeviceSize VmaBlockMetadata::GetUnusedRangeSizeMax() const -{ - if(!m_FreeSuballocationsBySize.empty()) - { - return m_FreeSuballocationsBySize.back()->size; - } - else - { - return 0; - } -} - -bool VmaBlockMetadata::IsEmpty() const -{ - return (m_Suballocations.size() == 1) && (m_FreeCount == 1); -} - -void VmaBlockMetadata::CalcAllocationStatInfo(VmaStatInfo& outInfo) const -{ - outInfo.blockCount = 1; - - const uint32_t rangeCount = (uint32_t)m_Suballocations.size(); - outInfo.allocationCount = rangeCount - m_FreeCount; - outInfo.unusedRangeCount = m_FreeCount; - - outInfo.unusedBytes = m_SumFreeSize; - outInfo.usedBytes = m_Size - outInfo.unusedBytes; - - outInfo.allocationSizeMin = UINT64_MAX; - outInfo.allocationSizeMax = 0; - outInfo.unusedRangeSizeMin = UINT64_MAX; - outInfo.unusedRangeSizeMax = 0; - - for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin(); - suballocItem != m_Suballocations.cend(); - ++suballocItem) - { - const VmaSuballocation& suballoc = *suballocItem; - if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) - { - outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size); - outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size); - } - else - { - outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size); - outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size); - } - } -} - -void VmaBlockMetadata::AddPoolStats(VmaPoolStats& inoutStats) const -{ - const uint32_t rangeCount = (uint32_t)m_Suballocations.size(); - - inoutStats.size += m_Size; - inoutStats.unusedSize += m_SumFreeSize; - inoutStats.allocationCount += rangeCount - m_FreeCount; - inoutStats.unusedRangeCount += m_FreeCount; - inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax()); -} - -#if VMA_STATS_STRING_ENABLED - -void VmaBlockMetadata::PrintDetailedMap(class VmaJsonWriter& json) const -{ - json.BeginObject(); - - json.WriteString("TotalBytes"); + json.WriteString("Size"); json.WriteNumber(m_Size); - json.WriteString("UnusedBytes"); - json.WriteNumber(m_SumFreeSize); - - json.WriteString("Allocations"); - json.WriteNumber(m_Suballocations.size() - m_FreeCount); - - json.WriteString("UnusedRanges"); - json.WriteNumber(m_FreeCount); - - json.WriteString("Suballocations"); - json.BeginArray(); - size_t i = 0; - for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin(); - suballocItem != m_Suballocations.cend(); - ++suballocItem, ++i) + if (m_pUserData != VMA_NULL) { - json.BeginObject(true); - - json.WriteString("Type"); - json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[suballocItem->type]); - - json.WriteString("Size"); - json.WriteNumber(suballocItem->size); - - json.WriteString("Offset"); - json.WriteNumber(suballocItem->offset); - - if(suballocItem->type != VMA_SUBALLOCATION_TYPE_FREE) + json.WriteString("UserData"); + if (IsUserDataString()) { - const void* pUserData = suballocItem->hAllocation->GetUserData(); - if(pUserData != VMA_NULL) - { - json.WriteString("UserData"); - if(suballocItem->hAllocation->IsUserDataString()) - { - json.WriteString((const char*)pUserData); - } - else - { - json.BeginString(); - json.ContinueString_Pointer(pUserData); - json.EndString(); - } - } - } - - json.EndObject(); - } - json.EndArray(); - - json.EndObject(); -} - -#endif // #if VMA_STATS_STRING_ENABLED - -/* -How many suitable free suballocations to analyze before choosing best one. -- Set to 1 to use First-Fit algorithm - first suitable free suballocation will - be chosen. -- Set to UINT32_MAX to use Best-Fit/Worst-Fit algorithm - all suitable free - suballocations will be analized and best one will be chosen. -- Any other value is also acceptable. -*/ -//static const uint32_t MAX_SUITABLE_SUBALLOCATIONS_TO_CHECK = 8; - -void VmaBlockMetadata::CreateFirstAllocationRequest(VmaAllocationRequest* pAllocationRequest) -{ - VMA_ASSERT(IsEmpty()); - pAllocationRequest->offset = 0; - pAllocationRequest->sumFreeSize = m_SumFreeSize; - pAllocationRequest->sumItemSize = 0; - pAllocationRequest->item = m_Suballocations.begin(); - pAllocationRequest->itemsToMakeLostCount = 0; -} - -bool VmaBlockMetadata::CreateAllocationRequest( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VkDeviceSize bufferImageGranularity, - VkDeviceSize allocSize, - VkDeviceSize allocAlignment, - VmaSuballocationType allocType, - bool canMakeOtherLost, - VmaAllocationRequest* pAllocationRequest) -{ - VMA_ASSERT(allocSize > 0); - VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); - VMA_ASSERT(pAllocationRequest != VMA_NULL); - VMA_HEAVY_ASSERT(Validate()); - - // There is not enough total free space in this block to fullfill the request: Early return. - if(canMakeOtherLost == false && m_SumFreeSize < allocSize) - { - return false; - } - - // New algorithm, efficiently searching freeSuballocationsBySize. - const size_t freeSuballocCount = m_FreeSuballocationsBySize.size(); - if(freeSuballocCount > 0) - { - if(VMA_BEST_FIT) - { - // Find first free suballocation with size not less than allocSize. - VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess( - m_FreeSuballocationsBySize.data(), - m_FreeSuballocationsBySize.data() + freeSuballocCount, - allocSize, - VmaSuballocationItemSizeLess()); - size_t index = it - m_FreeSuballocationsBySize.data(); - for(; index < freeSuballocCount; ++index) - { - if(CheckAllocation( - currentFrameIndex, - frameInUseCount, - bufferImageGranularity, - allocSize, - allocAlignment, - allocType, - m_FreeSuballocationsBySize[index], - false, // canMakeOtherLost - &pAllocationRequest->offset, - &pAllocationRequest->itemsToMakeLostCount, - &pAllocationRequest->sumFreeSize, - &pAllocationRequest->sumItemSize)) - { - pAllocationRequest->item = m_FreeSuballocationsBySize[index]; - return true; - } - } + json.WriteString((const char*)m_pUserData); } else { - // Search staring from biggest suballocations. - for(size_t index = freeSuballocCount; index--; ) - { - if(CheckAllocation( - currentFrameIndex, - frameInUseCount, - bufferImageGranularity, - allocSize, - allocAlignment, - allocType, - m_FreeSuballocationsBySize[index], - false, // canMakeOtherLost - &pAllocationRequest->offset, - &pAllocationRequest->itemsToMakeLostCount, - &pAllocationRequest->sumFreeSize, - &pAllocationRequest->sumItemSize)) - { - pAllocationRequest->item = m_FreeSuballocationsBySize[index]; - return true; - } - } + json.BeginString(); + json.ContinueString_Pointer(m_pUserData); + json.EndString(); } } - if(canMakeOtherLost) + if (m_BufferImageUsage != 0) { - // Brute-force algorithm. TODO: Come up with something better. - - pAllocationRequest->sumFreeSize = VK_WHOLE_SIZE; - pAllocationRequest->sumItemSize = VK_WHOLE_SIZE; - - VmaAllocationRequest tmpAllocRequest = {}; - for(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin(); - suballocIt != m_Suballocations.end(); - ++suballocIt) - { - if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE || - suballocIt->hAllocation->CanBecomeLost()) - { - if(CheckAllocation( - currentFrameIndex, - frameInUseCount, - bufferImageGranularity, - allocSize, - allocAlignment, - allocType, - suballocIt, - canMakeOtherLost, - &tmpAllocRequest.offset, - &tmpAllocRequest.itemsToMakeLostCount, - &tmpAllocRequest.sumFreeSize, - &tmpAllocRequest.sumItemSize)) - { - tmpAllocRequest.item = suballocIt; - - if(tmpAllocRequest.CalcCost() < pAllocationRequest->CalcCost()) - { - *pAllocationRequest = tmpAllocRequest; - } - } - } - } - - if(pAllocationRequest->sumItemSize != VK_WHOLE_SIZE) - { - return true; - } - } - - return false; -} - -bool VmaBlockMetadata::MakeRequestedAllocationsLost( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VmaAllocationRequest* pAllocationRequest) -{ - while(pAllocationRequest->itemsToMakeLostCount > 0) - { - if(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE) - { - ++pAllocationRequest->item; - } - VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end()); - VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE); - VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost()); - if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) - { - pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item); - --pAllocationRequest->itemsToMakeLostCount; - } - else - { - return false; - } - } - - VMA_HEAVY_ASSERT(Validate()); - VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end()); - VMA_ASSERT(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE); - - return true; -} - -uint32_t VmaBlockMetadata::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) -{ - uint32_t lostAllocationCount = 0; - for(VmaSuballocationList::iterator it = m_Suballocations.begin(); - it != m_Suballocations.end(); - ++it) - { - if(it->type != VMA_SUBALLOCATION_TYPE_FREE && - it->hAllocation->CanBecomeLost() && - it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount)) - { - it = FreeSuballocation(it); - ++lostAllocationCount; - } - } - return lostAllocationCount; -} - -void VmaBlockMetadata::Alloc( - const VmaAllocationRequest& request, - VmaSuballocationType type, - VkDeviceSize allocSize, - VmaAllocation hAllocation) -{ - VMA_ASSERT(request.item != m_Suballocations.end()); - VmaSuballocation& suballoc = *request.item; - // Given suballocation is a free block. - VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); - // Given offset is inside this suballocation. - VMA_ASSERT(request.offset >= suballoc.offset); - const VkDeviceSize paddingBegin = request.offset - suballoc.offset; - VMA_ASSERT(suballoc.size >= paddingBegin + allocSize); - const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize; - - // Unregister this free suballocation from m_FreeSuballocationsBySize and update - // it to become used. - UnregisterFreeSuballocation(request.item); - - suballoc.offset = request.offset; - suballoc.size = allocSize; - suballoc.type = type; - suballoc.hAllocation = hAllocation; - - // If there are any free bytes remaining at the end, insert new free suballocation after current one. - if(paddingEnd) - { - VmaSuballocation paddingSuballoc = {}; - paddingSuballoc.offset = request.offset + allocSize; - paddingSuballoc.size = paddingEnd; - paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - VmaSuballocationList::iterator next = request.item; - ++next; - const VmaSuballocationList::iterator paddingEndItem = - m_Suballocations.insert(next, paddingSuballoc); - RegisterFreeSuballocation(paddingEndItem); - } - - // If there are any free bytes remaining at the beginning, insert new free suballocation before current one. - if(paddingBegin) - { - VmaSuballocation paddingSuballoc = {}; - paddingSuballoc.offset = request.offset - paddingBegin; - paddingSuballoc.size = paddingBegin; - paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - const VmaSuballocationList::iterator paddingBeginItem = - m_Suballocations.insert(request.item, paddingSuballoc); - RegisterFreeSuballocation(paddingBeginItem); - } - - // Update totals. - m_FreeCount = m_FreeCount - 1; - if(paddingBegin > 0) - { - ++m_FreeCount; - } - if(paddingEnd > 0) - { - ++m_FreeCount; - } - m_SumFreeSize -= allocSize; -} - -void VmaBlockMetadata::Free(const VmaAllocation allocation) -{ - for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin(); - suballocItem != m_Suballocations.end(); - ++suballocItem) - { - VmaSuballocation& suballoc = *suballocItem; - if(suballoc.hAllocation == allocation) - { - FreeSuballocation(suballocItem); - VMA_HEAVY_ASSERT(Validate()); - return; - } - } - VMA_ASSERT(0 && "Not found!"); -} - -bool VmaBlockMetadata::ValidateFreeSuballocationList() const -{ - VkDeviceSize lastSize = 0; - for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i) - { - const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i]; - - if(it->type != VMA_SUBALLOCATION_TYPE_FREE) - { - VMA_ASSERT(0); - return false; - } - if(it->size < VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER) - { - VMA_ASSERT(0); - return false; - } - if(it->size < lastSize) - { - VMA_ASSERT(0); - return false; - } - - lastSize = it->size; - } - return true; -} - -bool VmaBlockMetadata::CheckAllocation( - uint32_t currentFrameIndex, - uint32_t frameInUseCount, - VkDeviceSize bufferImageGranularity, - VkDeviceSize allocSize, - VkDeviceSize allocAlignment, - VmaSuballocationType allocType, - VmaSuballocationList::const_iterator suballocItem, - bool canMakeOtherLost, - VkDeviceSize* pOffset, - size_t* itemsToMakeLostCount, - VkDeviceSize* pSumFreeSize, - VkDeviceSize* pSumItemSize) const -{ - VMA_ASSERT(allocSize > 0); - VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); - VMA_ASSERT(suballocItem != m_Suballocations.cend()); - VMA_ASSERT(pOffset != VMA_NULL); - - *itemsToMakeLostCount = 0; - *pSumFreeSize = 0; - *pSumItemSize = 0; - - if(canMakeOtherLost) - { - if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE) - { - *pSumFreeSize = suballocItem->size; - } - else - { - if(suballocItem->hAllocation->CanBecomeLost() && - suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) - { - ++*itemsToMakeLostCount; - *pSumItemSize = suballocItem->size; - } - else - { - return false; - } - } - - // Remaining size is too small for this request: Early return. - if(m_Size - suballocItem->offset < allocSize) - { - return false; - } - - // Start from offset equal to beginning of this suballocation. - *pOffset = suballocItem->offset; - - // Apply VMA_DEBUG_MARGIN at the beginning. - if((VMA_DEBUG_MARGIN > 0) && suballocItem != m_Suballocations.cbegin()) - { - *pOffset += VMA_DEBUG_MARGIN; - } - - // Apply alignment. - const VkDeviceSize alignment = VMA_MAX(allocAlignment, static_cast(VMA_DEBUG_ALIGNMENT)); - *pOffset = VmaAlignUp(*pOffset, alignment); - - // Check previous suballocations for BufferImageGranularity conflicts. - // Make bigger alignment if necessary. - if(bufferImageGranularity > 1) - { - bool bufferImageGranularityConflict = false; - VmaSuballocationList::const_iterator prevSuballocItem = suballocItem; - while(prevSuballocItem != m_Suballocations.cbegin()) - { - --prevSuballocItem; - const VmaSuballocation& prevSuballoc = *prevSuballocItem; - if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity)) - { - if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) - { - bufferImageGranularityConflict = true; - break; - } - } - else - // Already on previous page. - break; - } - if(bufferImageGranularityConflict) - { - *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity); - } - } - - // Now that we have final *pOffset, check if we are past suballocItem. - // If yes, return false - this function should be called for another suballocItem as starting point. - if(*pOffset >= suballocItem->offset + suballocItem->size) - { - return false; - } - - // Calculate padding at the beginning based on current offset. - const VkDeviceSize paddingBegin = *pOffset - suballocItem->offset; - - // Calculate required margin at the end if this is not last suballocation. - VmaSuballocationList::const_iterator next = suballocItem; - ++next; - const VkDeviceSize requiredEndMargin = - (next != m_Suballocations.cend()) ? VMA_DEBUG_MARGIN : 0; - - const VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin; - // Another early return check. - if(suballocItem->offset + totalSize > m_Size) - { - return false; - } - - // Advance lastSuballocItem until desired size is reached. - // Update itemsToMakeLostCount. - VmaSuballocationList::const_iterator lastSuballocItem = suballocItem; - if(totalSize > suballocItem->size) - { - VkDeviceSize remainingSize = totalSize - suballocItem->size; - while(remainingSize > 0) - { - ++lastSuballocItem; - if(lastSuballocItem == m_Suballocations.cend()) - { - return false; - } - if(lastSuballocItem->type == VMA_SUBALLOCATION_TYPE_FREE) - { - *pSumFreeSize += lastSuballocItem->size; - } - else - { - VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE); - if(lastSuballocItem->hAllocation->CanBecomeLost() && - lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) - { - ++*itemsToMakeLostCount; - *pSumItemSize += lastSuballocItem->size; - } - else - { - return false; - } - } - remainingSize = (lastSuballocItem->size < remainingSize) ? - remainingSize - lastSuballocItem->size : 0; - } - } - - // Check next suballocations for BufferImageGranularity conflicts. - // If conflict exists, we must mark more allocations lost or fail. - if(bufferImageGranularity > 1) - { - VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem; - ++nextSuballocItem; - while(nextSuballocItem != m_Suballocations.cend()) - { - const VmaSuballocation& nextSuballoc = *nextSuballocItem; - if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) - { - if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) - { - VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE); - if(nextSuballoc.hAllocation->CanBecomeLost() && - nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex) - { - ++*itemsToMakeLostCount; - } - else - { - return false; - } - } - } - else - { - // Already on next page. - break; - } - ++nextSuballocItem; - } - } - } - else - { - const VmaSuballocation& suballoc = *suballocItem; - VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); - - *pSumFreeSize = suballoc.size; - - // Size of this suballocation is too small for this request: Early return. - if(suballoc.size < allocSize) - { - return false; - } - - // Start from offset equal to beginning of this suballocation. - *pOffset = suballoc.offset; - - // Apply VMA_DEBUG_MARGIN at the beginning. - if((VMA_DEBUG_MARGIN > 0) && suballocItem != m_Suballocations.cbegin()) - { - *pOffset += VMA_DEBUG_MARGIN; - } - - // Apply alignment. - const VkDeviceSize alignment = VMA_MAX(allocAlignment, static_cast(VMA_DEBUG_ALIGNMENT)); - *pOffset = VmaAlignUp(*pOffset, alignment); - - // Check previous suballocations for BufferImageGranularity conflicts. - // Make bigger alignment if necessary. - if(bufferImageGranularity > 1) - { - bool bufferImageGranularityConflict = false; - VmaSuballocationList::const_iterator prevSuballocItem = suballocItem; - while(prevSuballocItem != m_Suballocations.cbegin()) - { - --prevSuballocItem; - const VmaSuballocation& prevSuballoc = *prevSuballocItem; - if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity)) - { - if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) - { - bufferImageGranularityConflict = true; - break; - } - } - else - // Already on previous page. - break; - } - if(bufferImageGranularityConflict) - { - *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity); - } - } - - // Calculate padding at the beginning based on current offset. - const VkDeviceSize paddingBegin = *pOffset - suballoc.offset; - - // Calculate required margin at the end if this is not last suballocation. - VmaSuballocationList::const_iterator next = suballocItem; - ++next; - const VkDeviceSize requiredEndMargin = - (next != m_Suballocations.cend()) ? VMA_DEBUG_MARGIN : 0; - - // Fail if requested size plus margin before and after is bigger than size of this suballocation. - if(paddingBegin + allocSize + requiredEndMargin > suballoc.size) - { - return false; - } - - // Check next suballocations for BufferImageGranularity conflicts. - // If conflict exists, allocation cannot be made here. - if(bufferImageGranularity > 1) - { - VmaSuballocationList::const_iterator nextSuballocItem = suballocItem; - ++nextSuballocItem; - while(nextSuballocItem != m_Suballocations.cend()) - { - const VmaSuballocation& nextSuballoc = *nextSuballocItem; - if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) - { - if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) - { - return false; - } - } - else - { - // Already on next page. - break; - } - ++nextSuballocItem; - } - } - } - - // All tests passed: Success. pOffset is already filled. - return true; -} - -void VmaBlockMetadata::MergeFreeWithNext(VmaSuballocationList::iterator item) -{ - VMA_ASSERT(item != m_Suballocations.end()); - VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); - - VmaSuballocationList::iterator nextItem = item; - ++nextItem; - VMA_ASSERT(nextItem != m_Suballocations.end()); - VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE); - - item->size += nextItem->size; - --m_FreeCount; - m_Suballocations.erase(nextItem); -} - -VmaSuballocationList::iterator VmaBlockMetadata::FreeSuballocation(VmaSuballocationList::iterator suballocItem) -{ - // Change this suballocation to be marked as free. - VmaSuballocation& suballoc = *suballocItem; - suballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - suballoc.hAllocation = VK_NULL_HANDLE; - - // Update totals. - ++m_FreeCount; - m_SumFreeSize += suballoc.size; - - // Merge with previous and/or next suballocation if it's also free. - bool mergeWithNext = false; - bool mergeWithPrev = false; - - VmaSuballocationList::iterator nextItem = suballocItem; - ++nextItem; - if((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE)) - { - mergeWithNext = true; - } - - VmaSuballocationList::iterator prevItem = suballocItem; - if(suballocItem != m_Suballocations.begin()) - { - --prevItem; - if(prevItem->type == VMA_SUBALLOCATION_TYPE_FREE) - { - mergeWithPrev = true; - } - } - - if(mergeWithNext) - { - UnregisterFreeSuballocation(nextItem); - MergeFreeWithNext(suballocItem); - } - - if(mergeWithPrev) - { - UnregisterFreeSuballocation(prevItem); - MergeFreeWithNext(prevItem); - RegisterFreeSuballocation(prevItem); - return prevItem; - } - else - { - RegisterFreeSuballocation(suballocItem); - return suballocItem; + json.WriteString("Usage"); + json.WriteNumber(m_BufferImageUsage); } } +#endif // VMA_STATS_STRING_ENABLED -void VmaBlockMetadata::RegisterFreeSuballocation(VmaSuballocationList::iterator item) +void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator) { - VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); - VMA_ASSERT(item->size > 0); - - // You may want to enable this validation at the beginning or at the end of - // this function, depending on what do you want to check. - VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); - - if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER) - { - if(m_FreeSuballocationsBySize.empty()) - { - m_FreeSuballocationsBySize.push_back(item); - } - else - { - VmaVectorInsertSorted(m_FreeSuballocationsBySize, item); - } - } - - //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); + VMA_ASSERT(IsUserDataString()); + VmaFreeString(hAllocator->GetAllocationCallbacks(), (char*)m_pUserData); + m_pUserData = VMA_NULL; } +#endif // _VMA_ALLOCATION_T_FUNCTIONS - -void VmaBlockMetadata::UnregisterFreeSuballocation(VmaSuballocationList::iterator item) -{ - VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE); - VMA_ASSERT(item->size > 0); - - // You may want to enable this validation at the beginning or at the end of - // this function, depending on what do you want to check. - VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); - - if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER) - { - VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess( - m_FreeSuballocationsBySize.data(), - m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(), - item, - VmaSuballocationItemSizeLess()); - for(size_t index = it - m_FreeSuballocationsBySize.data(); - index < m_FreeSuballocationsBySize.size(); - ++index) - { - if(m_FreeSuballocationsBySize[index] == item) - { - VmaVectorRemove(m_FreeSuballocationsBySize, index); - return; - } - VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found."); - } - VMA_ASSERT(0 && "Not found."); - } - - //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList()); -} - -//////////////////////////////////////////////////////////////////////////////// -// class VmaDeviceMemoryMapping - -VmaDeviceMemoryMapping::VmaDeviceMemoryMapping() : - m_MapCount(0), - m_pMappedData(VMA_NULL) -{ -} - -VmaDeviceMemoryMapping::~VmaDeviceMemoryMapping() -{ - VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped."); -} - -VkResult VmaDeviceMemoryMapping::Map(VmaAllocator hAllocator, VkDeviceMemory hMemory, void **ppData) -{ - VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); - if(m_MapCount != 0) - { - ++m_MapCount; - VMA_ASSERT(m_pMappedData != VMA_NULL); - if(ppData != VMA_NULL) - { - *ppData = m_pMappedData; - } - return VK_SUCCESS; - } - else - { - VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)( - hAllocator->m_hDevice, - hMemory, - 0, // offset - VK_WHOLE_SIZE, - 0, // flags - &m_pMappedData); - if(result == VK_SUCCESS) - { - if(ppData != VMA_NULL) - { - *ppData = m_pMappedData; - } - m_MapCount = 1; - } - return result; - } -} - -void VmaDeviceMemoryMapping::Unmap(VmaAllocator hAllocator, VkDeviceMemory hMemory) -{ - VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex); - if(m_MapCount != 0) - { - if(--m_MapCount == 0) - { - m_pMappedData = VMA_NULL; - (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, hMemory); - } - } - else - { - VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped."); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// class VmaDeviceMemoryBlock - -VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) : - m_MemoryTypeIndex(UINT32_MAX), - m_hMemory(VK_NULL_HANDLE), - m_Metadata(hAllocator) -{ -} - -void VmaDeviceMemoryBlock::Init( - uint32_t newMemoryTypeIndex, - VkDeviceMemory newMemory, - VkDeviceSize newSize) -{ - VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); - - m_MemoryTypeIndex = newMemoryTypeIndex; - m_hMemory = newMemory; - - m_Metadata.Init(newSize); -} - -void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator) -{ - // This is the most important assert in the entire library. - // Hitting it means you have some memory leak - unreleased VmaAllocation objects. - VMA_ASSERT(m_Metadata.IsEmpty() && "Some allocations were not freed before destruction of this memory block!"); - - VMA_ASSERT(m_hMemory != VK_NULL_HANDLE); - allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_Metadata.GetSize(), m_hMemory); - m_hMemory = VK_NULL_HANDLE; -} - -bool VmaDeviceMemoryBlock::Validate() const -{ - if((m_hMemory == VK_NULL_HANDLE) || - (m_Metadata.GetSize() == 0)) - { - return false; - } - - return m_Metadata.Validate(); -} - -VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, void** ppData) -{ - return m_Mapping.Map(hAllocator, m_hMemory, ppData); -} - -void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator) -{ - m_Mapping.Unmap(hAllocator, m_hMemory); -} - -static void InitStatInfo(VmaStatInfo& outInfo) -{ - memset(&outInfo, 0, sizeof(outInfo)); - outInfo.allocationSizeMin = UINT64_MAX; - outInfo.unusedRangeSizeMin = UINT64_MAX; -} - -// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo. -static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo) -{ - inoutInfo.blockCount += srcInfo.blockCount; - inoutInfo.allocationCount += srcInfo.allocationCount; - inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount; - inoutInfo.usedBytes += srcInfo.usedBytes; - inoutInfo.unusedBytes += srcInfo.unusedBytes; - inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin); - inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax); - inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin); - inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax); -} - -static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo) -{ - inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ? - VmaRoundDiv(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0; - inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ? - VmaRoundDiv(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0; -} - -VmaPool_T::VmaPool_T( - VmaAllocator hAllocator, - const VmaPoolCreateInfo& createInfo) : - m_BlockVector( - hAllocator, - createInfo.memoryTypeIndex, - createInfo.blockSize, - createInfo.minBlockCount, - createInfo.maxBlockCount, - (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), - createInfo.frameInUseCount, - true) // isCustomPool -{ -} - -VmaPool_T::~VmaPool_T() -{ -} - -#if VMA_STATS_STRING_ENABLED - -#endif // #if VMA_STATS_STRING_ENABLED - +#ifndef _VMA_BLOCK_VECTOR_FUNCTIONS VmaBlockVector::VmaBlockVector( VmaAllocator hAllocator, + VmaPool hParentPool, uint32_t memoryTypeIndex, VkDeviceSize preferredBlockSize, size_t minBlockCount, size_t maxBlockCount, VkDeviceSize bufferImageGranularity, - uint32_t frameInUseCount, - bool isCustomPool) : - m_hAllocator(hAllocator), + bool explicitBlockSize, + uint32_t algorithm, + float priority, + VkDeviceSize minAllocationAlignment, + void* pMemoryAllocateNext) + : m_hAllocator(hAllocator), + m_hParentPool(hParentPool), m_MemoryTypeIndex(memoryTypeIndex), m_PreferredBlockSize(preferredBlockSize), m_MinBlockCount(minBlockCount), m_MaxBlockCount(maxBlockCount), m_BufferImageGranularity(bufferImageGranularity), - m_FrameInUseCount(frameInUseCount), - m_IsCustomPool(isCustomPool), - m_Blocks(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + m_ExplicitBlockSize(explicitBlockSize), + m_Algorithm(algorithm), + m_Priority(priority), + m_MinAllocationAlignment(minAllocationAlignment), + m_pMemoryAllocateNext(pMemoryAllocateNext), m_HasEmptyBlock(false), - m_pDefragmentator(VMA_NULL) -{ -} + m_Blocks(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + m_NextBlockId(0) {} VmaBlockVector::~VmaBlockVector() { - VMA_ASSERT(m_pDefragmentator == VMA_NULL); - - for(size_t i = m_Blocks.size(); i--; ) + for (size_t i = m_Blocks.size(); i--; ) { m_Blocks[i]->Destroy(m_hAllocator); vma_delete(m_hAllocator, m_Blocks[i]); @@ -5854,10 +11933,10 @@ VmaBlockVector::~VmaBlockVector() VkResult VmaBlockVector::CreateMinBlocks() { - for(size_t i = 0; i < m_MinBlockCount; ++i) + for (size_t i = 0; i < m_MinBlockCount; ++i) { VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL); - if(res != VK_SUCCESS) + if (res != VK_SUCCESS) { return res; } @@ -5865,329 +11944,389 @@ VkResult VmaBlockVector::CreateMinBlocks() return VK_SUCCESS; } -void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats) +void VmaBlockVector::AddPoolStats(VmaPoolStats* pStats) { - pStats->size = 0; - pStats->unusedSize = 0; - pStats->allocationCount = 0; - pStats->unusedRangeCount = 0; - pStats->unusedRangeSizeMax = 0; + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + const size_t blockCount = m_Blocks.size(); + pStats->blockCount += blockCount; - for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) { const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; VMA_ASSERT(pBlock); VMA_HEAVY_ASSERT(pBlock->Validate()); - pBlock->m_Metadata.AddPoolStats(*pStats); + pBlock->m_pMetadata->AddPoolStats(*pStats); } } -static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32; +bool VmaBlockVector::IsEmpty() +{ + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + return m_Blocks.empty(); +} + +bool VmaBlockVector::IsCorruptionDetectionEnabled() const +{ + const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + return (VMA_DEBUG_DETECT_CORRUPTION != 0) && + (VMA_DEBUG_MARGIN > 0) && + (m_Algorithm == 0 || m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) && + (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags; +} VkResult VmaBlockVector::Allocate( - VmaPool hCurrentPool, - uint32_t currentFrameIndex, - const VkMemoryRequirements& vkMemReq, + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations) +{ + size_t allocIndex; + VkResult res = VK_SUCCESS; + + alignment = VMA_MAX(alignment, m_MinAllocationAlignment); + + if (IsCorruptionDetectionEnabled()) + { + size = VmaAlignUp(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE)); + alignment = VmaAlignUp(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE)); + } + + { + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); + for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + res = AllocatePage( + size, + alignment, + createInfo, + suballocType, + pAllocations + allocIndex); + if (res != VK_SUCCESS) + { + break; + } + } + } + + if (res != VK_SUCCESS) + { + // Free all already created allocations. + const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex); + while (allocIndex--) + { + VmaAllocation_T* const alloc = pAllocations[allocIndex]; + const VkDeviceSize allocSize = alloc->GetSize(); + Free(alloc); + m_hAllocator->m_Budget.RemoveAllocation(heapIndex, allocSize); + } + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + } + + return res; +} + +VkResult VmaBlockVector::AllocatePage( + VkDeviceSize size, + VkDeviceSize alignment, const VmaAllocationCreateInfo& createInfo, VmaSuballocationType suballocType, VmaAllocation* pAllocation) { + const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0; const bool mapped = (createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0; const bool isUserDataString = (createInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0; - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); - - // 1. Search existing allocations. Try to allocate without making other allocations lost. - // Forward order in m_Blocks - prefer blocks with smallest amount of free space. - for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex ) + VkDeviceSize freeMemory; { - VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; - VMA_ASSERT(pCurrBlock); - VmaAllocationRequest currRequest = {}; - if(pCurrBlock->m_Metadata.CreateAllocationRequest( - currentFrameIndex, - m_FrameInUseCount, - m_BufferImageGranularity, - vkMemReq.size, - vkMemReq.alignment, - suballocType, - false, // canMakeOtherLost - &currRequest)) - { - // Allocate from pCurrBlock. - VMA_ASSERT(currRequest.itemsToMakeLostCount == 0); - - if(mapped) - { - VkResult res = pCurrBlock->Map(m_hAllocator, nullptr); - if(res != VK_SUCCESS) - { - return res; - } - } - - // We no longer have an empty Allocation. - if(pCurrBlock->m_Metadata.IsEmpty()) - { - m_HasEmptyBlock = false; - } - - *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); - pCurrBlock->m_Metadata.Alloc(currRequest, suballocType, vkMemReq.size, *pAllocation); - (*pAllocation)->InitBlockAllocation( - hCurrentPool, - pCurrBlock, - currRequest.offset, - vkMemReq.alignment, - vkMemReq.size, - suballocType, - mapped, - (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0); - VMA_HEAVY_ASSERT(pCurrBlock->Validate()); - VMA_DEBUG_LOG(" Returned from existing allocation #%u", (uint32_t)blockIndex); - (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData); - return VK_SUCCESS; - } + const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex); + VmaBudget heapBudget = {}; + m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1); + freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0; } + const bool canFallbackToDedicated = !IsCustomPool(); const bool canCreateNewBlock = ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) && - (m_Blocks.size() < m_MaxBlockCount); + (m_Blocks.size() < m_MaxBlockCount) && + (freeMemory >= size || !canFallbackToDedicated); + uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK; - // 2. Try to create new block. - if(canCreateNewBlock) + // Upper address can only be used with linear allocator and within single memory block. + if (isUpperAddress && + (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1)) { - // 2.1. Start with full preferredBlockSize. - VkDeviceSize blockSize = m_PreferredBlockSize; - size_t newBlockIndex = 0; - VkResult res = CreateBlock(blockSize, &newBlockIndex); - // Allocating blocks of other sizes is allowed only in default pools. - // In custom pools block size is fixed. - if(res < 0 && m_IsCustomPool == false) - { - // 2.2. Try half the size. - blockSize /= 2; - if(blockSize >= vkMemReq.size) - { - res = CreateBlock(blockSize, &newBlockIndex); - if(res < 0) - { - // 2.3. Try quarter the size. - blockSize /= 2; - if(blockSize >= vkMemReq.size) - { - res = CreateBlock(blockSize, &newBlockIndex); - } - } - } - } - if(res == VK_SUCCESS) - { - VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex]; - VMA_ASSERT(pBlock->m_Metadata.GetSize() >= vkMemReq.size); - - if(mapped) - { - res = pBlock->Map(m_hAllocator, nullptr); - if(res != VK_SUCCESS) - { - return res; - } - } - - // Allocate from pBlock. Because it is empty, dstAllocRequest can be trivially filled. - VmaAllocationRequest allocRequest; - pBlock->m_Metadata.CreateFirstAllocationRequest(&allocRequest); - *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); - pBlock->m_Metadata.Alloc(allocRequest, suballocType, vkMemReq.size, *pAllocation); - (*pAllocation)->InitBlockAllocation( - hCurrentPool, - pBlock, - allocRequest.offset, - vkMemReq.alignment, - vkMemReq.size, - suballocType, - mapped, - (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0); - VMA_HEAVY_ASSERT(pBlock->Validate()); - VMA_DEBUG_LOG(" Created new allocation Size=%llu", allocInfo.allocationSize); - (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData); - return VK_SUCCESS; - } + return VK_ERROR_FEATURE_NOT_PRESENT; } - const bool canMakeOtherLost = (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) != 0; - - // 3. Try to allocate from existing blocks with making other allocations lost. - if(canMakeOtherLost) + // Validate strategy. + switch (strategy) { - uint32_t tryIndex = 0; - for(; tryIndex < VMA_ALLOCATION_TRY_COUNT; ++tryIndex) - { - VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL; - VmaAllocationRequest bestRequest = {}; - VkDeviceSize bestRequestCost = VK_WHOLE_SIZE; + case 0: + strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT; + break; + case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT: + case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT: + case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT: + break; + default: + return VK_ERROR_FEATURE_NOT_PRESENT; + } - // 1. Search existing allocations. + // Early reject: requested allocation size is larger that maximum block size for this block vector. + if (size + 2 * VMA_DEBUG_MARGIN > m_PreferredBlockSize) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + + // 1. Search existing allocations. Try to allocate. + if (m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) + { + // Use only last block. + if (!m_Blocks.empty()) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back(); + VMA_ASSERT(pCurrBlock); + VkResult res = AllocateFromBlock( + pCurrBlock, + size, + alignment, + createInfo.flags, + createInfo.pUserData, + suballocType, + strategy, + pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG(" Returned from last block #%u", pCurrBlock->GetId()); + return VK_SUCCESS; + } + } + } + else + { + if (strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT) + { // Forward order in m_Blocks - prefer blocks with smallest amount of free space. - for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex ) + for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) { VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; VMA_ASSERT(pCurrBlock); - VmaAllocationRequest currRequest = {}; - if(pCurrBlock->m_Metadata.CreateAllocationRequest( - currentFrameIndex, - m_FrameInUseCount, - m_BufferImageGranularity, - vkMemReq.size, - vkMemReq.alignment, + VkResult res = AllocateFromBlock( + pCurrBlock, + size, + alignment, + createInfo.flags, + createInfo.pUserData, suballocType, - canMakeOtherLost, - &currRequest)) + strategy, + pAllocation); + if (res == VK_SUCCESS) { - const VkDeviceSize currRequestCost = currRequest.CalcCost(); - if(pBestRequestBlock == VMA_NULL || - currRequestCost < bestRequestCost) - { - pBestRequestBlock = pCurrBlock; - bestRequest = currRequest; - bestRequestCost = currRequestCost; - - if(bestRequestCost == 0) - { - break; - } - } - } - } - - if(pBestRequestBlock != VMA_NULL) - { - if(mapped) - { - VkResult res = pBestRequestBlock->Map(m_hAllocator, nullptr); - if(res != VK_SUCCESS) - { - return res; - } - } - - if(pBestRequestBlock->m_Metadata.MakeRequestedAllocationsLost( - currentFrameIndex, - m_FrameInUseCount, - &bestRequest)) - { - // We no longer have an empty Allocation. - if(pBestRequestBlock->m_Metadata.IsEmpty()) - { - m_HasEmptyBlock = false; - } - // Allocate from this pBlock. - *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString); - pBestRequestBlock->m_Metadata.Alloc(bestRequest, suballocType, vkMemReq.size, *pAllocation); - (*pAllocation)->InitBlockAllocation( - hCurrentPool, - pBestRequestBlock, - bestRequest.offset, - vkMemReq.alignment, - vkMemReq.size, - suballocType, - mapped, - (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0); - VMA_HEAVY_ASSERT(pBlock->Validate()); - VMA_DEBUG_LOG(" Returned from existing allocation #%u", (uint32_t)blockIndex); - (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData); + VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId()); return VK_SUCCESS; } - // else: Some allocations must have been touched while we are here. Next try. + } + } + else // WORST_FIT, FIRST_FIT + { + // Backward order in m_Blocks - prefer blocks with largest amount of free space. + for (size_t blockIndex = m_Blocks.size(); blockIndex--; ) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pCurrBlock); + VkResult res = AllocateFromBlock( + pCurrBlock, + size, + alignment, + createInfo.flags, + createInfo.pUserData, + suballocType, + strategy, + pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId()); + return VK_SUCCESS; + } + } + } + } + + // 2. Try to create new block. + if (canCreateNewBlock) + { + // Calculate optimal size for new block. + VkDeviceSize newBlockSize = m_PreferredBlockSize; + uint32_t newBlockSizeShift = 0; + const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3; + + if (!m_ExplicitBlockSize) + { + // Allocate 1/8, 1/4, 1/2 as first blocks. + const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize(); + for (uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i) + { + const VkDeviceSize smallerNewBlockSize = newBlockSize / 2; + if (smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2) + { + newBlockSize = smallerNewBlockSize; + ++newBlockSizeShift; + } + else + { + break; + } + } + } + + size_t newBlockIndex = 0; + VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ? + CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY; + // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize. + if (!m_ExplicitBlockSize) + { + while (res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX) + { + const VkDeviceSize smallerNewBlockSize = newBlockSize / 2; + if (smallerNewBlockSize >= size) + { + newBlockSize = smallerNewBlockSize; + ++newBlockSizeShift; + res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ? + CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + else + { + break; + } + } + } + + if (res == VK_SUCCESS) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex]; + VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size); + + res = AllocateFromBlock( + pBlock, + size, + alignment, + createInfo.flags, + createInfo.pUserData, + suballocType, + strategy, + pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG(" Created new block #%u Size=%llu", pBlock->GetId(), newBlockSize); + return VK_SUCCESS; } else { - // Could not find place in any of the blocks - break outer loop. - break; + // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment. + return VK_ERROR_OUT_OF_DEVICE_MEMORY; } } - /* Maximum number of tries exceeded - a very unlike event when many other - threads are simultaneously touching allocations making it impossible to make - lost at the same time as we try to allocate. */ - if(tryIndex == VMA_ALLOCATION_TRY_COUNT) - { - return VK_ERROR_TOO_MANY_OBJECTS; - } } return VK_ERROR_OUT_OF_DEVICE_MEMORY; } void VmaBlockVector::Free( - VmaAllocation hAllocation) + const VmaAllocation hAllocation) { VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL; + bool budgetExceeded = false; + { + const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex); + VmaBudget heapBudget = {}; + m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1); + budgetExceeded = heapBudget.usage >= heapBudget.budget; + } + // Scope for lock. { - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock(); - if(hAllocation->IsPersistentMap()) + if (IsCorruptionDetectionEnabled()) { - pBlock->m_Mapping.Unmap(m_hAllocator, pBlock->m_hMemory); + VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize()); + VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value."); } - pBlock->m_Metadata.Free(hAllocation); + if (hAllocation->IsPersistentMap()) + { + pBlock->Unmap(m_hAllocator, 1); + } + + pBlock->m_pMetadata->Free(hAllocation->GetAllocHandle()); VMA_HEAVY_ASSERT(pBlock->Validate()); - VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", memTypeIndex); + VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex); + const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount; // pBlock became empty after this deallocation. - if(pBlock->m_Metadata.IsEmpty()) + if (pBlock->m_pMetadata->IsEmpty()) { - // Already has empty Allocation. We don't want to have two, so delete this one. - if(m_HasEmptyBlock && m_Blocks.size() > m_MinBlockCount) + // Already has empty block. We don't want to have two, so delete this one. + if ((m_HasEmptyBlock || budgetExceeded) && canDeleteBlock) { pBlockToDelete = pBlock; Remove(pBlock); } - // We now have first empty Allocation. - else - { - m_HasEmptyBlock = true; - } + // else: We now have an empty block - leave it. } // pBlock didn't become empty, but we have another empty block - find and free that one. // (This is optional, heuristics.) - else if(m_HasEmptyBlock) + else if (m_HasEmptyBlock && canDeleteBlock) { VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back(); - if(pLastBlock->m_Metadata.IsEmpty() && m_Blocks.size() > m_MinBlockCount) + if (pLastBlock->m_pMetadata->IsEmpty()) { pBlockToDelete = pLastBlock; m_Blocks.pop_back(); - m_HasEmptyBlock = false; } } + UpdateHasEmptyBlock(); IncrementallySortBlocks(); } - // Destruction of a free Allocation. Deferred until this point, outside of mutex + // Destruction of a free block. Deferred until this point, outside of mutex // lock, for performance reason. - if(pBlockToDelete != VMA_NULL) + if (pBlockToDelete != VMA_NULL) { - VMA_DEBUG_LOG(" Deleted empty allocation"); + VMA_DEBUG_LOG(" Deleted empty block #%u", pBlockToDelete->GetId()); pBlockToDelete->Destroy(m_hAllocator); vma_delete(m_hAllocator, pBlockToDelete); } } +VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const +{ + VkDeviceSize result = 0; + for (size_t i = m_Blocks.size(); i--; ) + { + result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize()); + if (result >= m_PreferredBlockSize) + { + break; + } + } + return result; +} + void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock) { - for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) { - if(m_Blocks[blockIndex] == pBlock) + if (m_Blocks[blockIndex] == pBlock) { VmaVectorRemove(m_Blocks, blockIndex); return; @@ -6198,25 +12337,120 @@ void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock) void VmaBlockVector::IncrementallySortBlocks() { - // Bubble sort only until first swap. - for(size_t i = 1; i < m_Blocks.size(); ++i) + if (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) { - if(m_Blocks[i - 1]->m_Metadata.GetSumFreeSize() > m_Blocks[i]->m_Metadata.GetSumFreeSize()) + // Bubble sort only until first swap. + for (size_t i = 1; i < m_Blocks.size(); ++i) { - VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]); - return; + if (m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize()) + { + VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]); + return; + } } } } +VkResult VmaBlockVector::AllocateFromBlock( + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize size, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + uint32_t strategy, + VmaAllocation* pAllocation) +{ + const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0; + const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0; + const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0; + + VmaAllocationRequest currRequest = {}; + if (pBlock->m_pMetadata->CreateAllocationRequest( + size, + alignment, + isUpperAddress, + suballocType, + strategy, + &currRequest)) + { + // Allocate from pCurrBlock. + if (mapped) + { + VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL); + if (res != VK_SUCCESS) + { + return res; + } + } + + *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(isUserDataString); + pBlock->m_pMetadata->Alloc(currRequest, suballocType, *pAllocation); + UpdateHasEmptyBlock(); + (*pAllocation)->InitBlockAllocation( + pBlock, + currRequest.allocHandle, + alignment, + currRequest.size, // Not size, as actual allocation size may be larger than requested! + m_MemoryTypeIndex, + suballocType, + mapped); + VMA_HEAVY_ASSERT(pBlock->Validate()); + (*pAllocation)->SetUserData(m_hAllocator, pUserData); + m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), currRequest.size); + if (VMA_DEBUG_INITIALIZE_ALLOCATIONS) + { + m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED); + } + if (IsCorruptionDetectionEnabled()) + { + VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, (*pAllocation)->GetOffset(), currRequest.size); + VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value."); + } + return VK_SUCCESS; + } + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex) { VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + allocInfo.pNext = m_pMemoryAllocateNext; allocInfo.memoryTypeIndex = m_MemoryTypeIndex; allocInfo.allocationSize = blockSize; + +#if VMA_BUFFER_DEVICE_ADDRESS + // Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature. + VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR }; + if (m_hAllocator->m_UseKhrBufferDeviceAddress) + { + allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo); + } +#endif // VMA_BUFFER_DEVICE_ADDRESS + +#if VMA_MEMORY_PRIORITY + VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; + if (m_hAllocator->m_UseExtMemoryPriority) + { + priorityInfo.priority = m_Priority; + VmaPnextChainPushFront(&allocInfo, &priorityInfo); + } +#endif // VMA_MEMORY_PRIORITY + +#if VMA_EXTERNAL_MEMORY + // Attach VkExportMemoryAllocateInfoKHR if necessary. + VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; + exportMemoryAllocInfo.handleTypes = m_hAllocator->GetExternalMemoryHandleTypeFlags(m_MemoryTypeIndex); + if (exportMemoryAllocInfo.handleTypes != 0) + { + VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo); + } +#endif // VMA_EXTERNAL_MEMORY + VkDeviceMemory mem = VK_NULL_HANDLE; VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem); - if(res < 0) + if (res < 0) { return res; } @@ -6226,12 +12460,17 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn // Create new Allocation for it. VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator); pBlock->Init( + m_hAllocator, + m_hParentPool, m_MemoryTypeIndex, mem, - allocInfo.allocationSize); + allocInfo.allocationSize, + m_NextBlockId++, + m_Algorithm, + m_BufferImageGranularity); m_Blocks.push_back(pBlock); - if(pNewBlockIndex != VMA_NULL) + if (pNewBlockIndex != VMA_NULL) { *pNewBlockIndex = m_Blocks.size() - 1; } @@ -6239,16 +12478,258 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn return VK_SUCCESS; } -#if VMA_STATS_STRING_ENABLED +void VmaBlockVector::ApplyDefragmentationMovesCpu( + VmaBlockVectorDefragmentationContext* pDefragCtx, + const VmaVector>& moves) +{ + const size_t blockCount = m_Blocks.size(); + const bool isNonCoherent = m_hAllocator->IsMemoryTypeNonCoherent(m_MemoryTypeIndex); + enum BLOCK_FLAG + { + BLOCK_FLAG_USED = 0x00000001, + BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002, + }; + + struct BlockInfo + { + uint32_t flags; + void* pMappedData; + }; + VmaVector< BlockInfo, VmaStlAllocator > + blockInfo(blockCount, BlockInfo(), VmaStlAllocator(m_hAllocator->GetAllocationCallbacks())); + memset(blockInfo.data(), 0, blockCount * sizeof(BlockInfo)); + + // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED. + const size_t moveCount = moves.size(); + for (size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex) + { + const VmaDefragmentationMove& move = moves[moveIndex]; + blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED; + blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED; + } + + VMA_ASSERT(pDefragCtx->res == VK_SUCCESS); + + // Go over all blocks. Get mapped pointer or map if necessary. + for (size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex) + { + BlockInfo& currBlockInfo = blockInfo[blockIndex]; + VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; + if ((currBlockInfo.flags & BLOCK_FLAG_USED) != 0) + { + currBlockInfo.pMappedData = pBlock->GetMappedData(); + // It is not originally mapped - map it. + if (currBlockInfo.pMappedData == VMA_NULL) + { + pDefragCtx->res = pBlock->Map(m_hAllocator, 1, &currBlockInfo.pMappedData); + if (pDefragCtx->res == VK_SUCCESS) + { + currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION; + } + } + } + } + + // Go over all moves. Do actual data transfer. + if (pDefragCtx->res == VK_SUCCESS) + { + const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize; + VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; + + for (size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex) + { + const VmaDefragmentationMove& move = moves[moveIndex]; + + const BlockInfo& srcBlockInfo = blockInfo[move.srcBlockIndex]; + const BlockInfo& dstBlockInfo = blockInfo[move.dstBlockIndex]; + + VMA_ASSERT(srcBlockInfo.pMappedData && dstBlockInfo.pMappedData); + + // Invalidate source. + if (isNonCoherent) + { + VmaDeviceMemoryBlock* const pSrcBlock = m_Blocks[move.srcBlockIndex]; + memRange.memory = pSrcBlock->GetDeviceMemory(); + memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize); + memRange.size = VMA_MIN( + VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize), + pSrcBlock->m_pMetadata->GetSize() - memRange.offset); + (*m_hAllocator->GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange); + } + + // THE PLACE WHERE ACTUAL DATA COPY HAPPENS. + memmove( + reinterpret_cast(dstBlockInfo.pMappedData) + move.dstOffset, + reinterpret_cast(srcBlockInfo.pMappedData) + move.srcOffset, + static_cast(move.size)); + + if (IsCorruptionDetectionEnabled()) + { + VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN); + VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size); + } + + // Flush destination. + if (isNonCoherent) + { + VmaDeviceMemoryBlock* const pDstBlock = m_Blocks[move.dstBlockIndex]; + memRange.memory = pDstBlock->GetDeviceMemory(); + memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize); + memRange.size = VMA_MIN( + VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize), + pDstBlock->m_pMetadata->GetSize() - memRange.offset); + (*m_hAllocator->GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange); + } + } + } + + // Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation. + // Regardless of pCtx->res == VK_SUCCESS. + for (size_t blockIndex = blockCount; blockIndex--; ) + { + const BlockInfo& currBlockInfo = blockInfo[blockIndex]; + if ((currBlockInfo.flags & BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0) + { + VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; + pBlock->Unmap(m_hAllocator, 1); + } + } +} + +void VmaBlockVector::ApplyDefragmentationMovesGpu( + VmaBlockVectorDefragmentationContext* pDefragCtx, + VmaVector>& moves, + VkCommandBuffer commandBuffer) +{ + const size_t blockCount = m_Blocks.size(); + + pDefragCtx->blockContexts.resize(blockCount); + memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext)); + + // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED. + const size_t moveCount = moves.size(); + for (size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex) + { + const VmaDefragmentationMove& move = moves[moveIndex]; + + //if(move.type == VMA_ALLOCATION_TYPE_UNKNOWN) + { + // Old school move still require us to map the whole block + pDefragCtx->blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED; + pDefragCtx->blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED; + } + } + + VMA_ASSERT(pDefragCtx->res == VK_SUCCESS); + + // Go over all blocks. Create and bind buffer for whole block if necessary. + { + VkBufferCreateInfo bufCreateInfo; + VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo); + + for (size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex) + { + VmaBlockDefragmentationContext& currBlockCtx = pDefragCtx->blockContexts[blockIndex]; + VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; + if ((currBlockCtx.flags & VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0) + { + bufCreateInfo.size = pBlock->m_pMetadata->GetSize(); + pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkCreateBuffer)( + m_hAllocator->m_hDevice, &bufCreateInfo, m_hAllocator->GetAllocationCallbacks(), &currBlockCtx.hBuffer); + if (pDefragCtx->res == VK_SUCCESS) + { + pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkBindBufferMemory)( + m_hAllocator->m_hDevice, currBlockCtx.hBuffer, pBlock->GetDeviceMemory(), 0); + } + } + } + } + + // Go over all moves. Post data transfer commands to command buffer. + if (pDefragCtx->res == VK_SUCCESS) + { + for (size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex) + { + const VmaDefragmentationMove& move = moves[moveIndex]; + + const VmaBlockDefragmentationContext& srcBlockCtx = pDefragCtx->blockContexts[move.srcBlockIndex]; + const VmaBlockDefragmentationContext& dstBlockCtx = pDefragCtx->blockContexts[move.dstBlockIndex]; + + VMA_ASSERT(srcBlockCtx.hBuffer && dstBlockCtx.hBuffer); + + VkBufferCopy region = { + move.srcOffset, + move.dstOffset, + move.size }; + (*m_hAllocator->GetVulkanFunctions().vkCmdCopyBuffer)( + commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, ®ion); + } + } + + // Save buffers to defrag context for later destruction. + if (pDefragCtx->res == VK_SUCCESS && moveCount > 0) + { + pDefragCtx->res = VK_NOT_READY; + } +} + +void VmaBlockVector::FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats) +{ + for (size_t blockIndex = m_Blocks.size(); blockIndex--; ) + { + VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; + if (pBlock->m_pMetadata->IsEmpty()) + { + if (m_Blocks.size() > m_MinBlockCount) + { + if (pDefragmentationStats != VMA_NULL) + { + ++pDefragmentationStats->deviceMemoryBlocksFreed; + pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize(); + } + + VmaVectorRemove(m_Blocks, blockIndex); + pBlock->Destroy(m_hAllocator); + vma_delete(m_hAllocator, pBlock); + } + else + { + break; + } + } + } + UpdateHasEmptyBlock(); +} + +void VmaBlockVector::UpdateHasEmptyBlock() +{ + m_HasEmptyBlock = false; + for (size_t index = 0, count = m_Blocks.size(); index < count; ++index) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[index]; + if (pBlock->m_pMetadata->IsEmpty()) + { + m_HasEmptyBlock = true; + break; + } + } +} + +#if VMA_STATS_STRING_ENABLED void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json) { - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); - json.BeginObject(); - - if(m_IsCustomPool) + if (IsCustomPool()) { + const char* poolName = m_hParentPool->GetName(); + if (poolName != VMA_NULL && poolName[0] != '\0') + { + json.WriteString("Name"); + json.WriteString(poolName); + } + json.WriteString("MemoryTypeIndex"); json.WriteNumber(m_MemoryTypeIndex); @@ -6257,24 +12738,24 @@ void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json) json.WriteString("BlockCount"); json.BeginObject(true); - if(m_MinBlockCount > 0) + if (m_MinBlockCount > 0) { json.WriteString("Min"); - json.WriteNumber(m_MinBlockCount); + json.WriteNumber((uint64_t)m_MinBlockCount); } - if(m_MaxBlockCount < SIZE_MAX) + if (m_MaxBlockCount < SIZE_MAX) { json.WriteString("Max"); - json.WriteNumber(m_MaxBlockCount); + json.WriteNumber((uint64_t)m_MaxBlockCount); } json.WriteString("Cur"); - json.WriteNumber(m_Blocks.size()); + json.WriteNumber((uint64_t)m_Blocks.size()); json.EndObject(); - if(m_FrameInUseCount > 0) + if (m_Algorithm != 0) { - json.WriteString("FrameInUseCount"); - json.WriteNumber(m_FrameInUseCount); + json.WriteString("Algorithm"); + json.WriteString(VmaAlgorithmToStr(m_Algorithm)); } } else @@ -6284,111 +12765,260 @@ void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json) } json.WriteString("Blocks"); - json.BeginArray(); - for(size_t i = 0; i < m_Blocks.size(); ++i) + json.BeginObject(); + for (size_t i = 0; i < m_Blocks.size(); ++i) { - m_Blocks[i]->m_Metadata.PrintDetailedMap(json); - } - json.EndArray(); + json.BeginString(); + json.ContinueString(m_Blocks[i]->GetId()); + json.EndString(); + m_Blocks[i]->m_pMetadata->PrintDetailedMap(json); + } json.EndObject(); } +#endif // VMA_STATS_STRING_ENABLED -#endif // #if VMA_STATS_STRING_ENABLED - -VmaDefragmentator* VmaBlockVector::EnsureDefragmentator( - VmaAllocator hAllocator, - uint32_t currentFrameIndex) +void VmaBlockVector::Defragment( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags, + VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove, + VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove, + VkCommandBuffer commandBuffer) { - if(m_pDefragmentator == VMA_NULL) + pCtx->res = VK_SUCCESS; + + const VkMemoryPropertyFlags memPropFlags = + m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags; + const bool isHostVisible = (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; + + const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 && + isHostVisible; + const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 && + !IsCorruptionDetectionEnabled() && + ((1u << m_MemoryTypeIndex) & m_hAllocator->GetGpuDefragmentationMemoryTypeBits()) != 0; + + // There are options to defragment this memory type. + if (canDefragmentOnCpu || canDefragmentOnGpu) { - m_pDefragmentator = vma_new(m_hAllocator, VmaDefragmentator)( - hAllocator, - this, - currentFrameIndex); - } - - return m_pDefragmentator; -} - -VkResult VmaBlockVector::Defragment( - VmaDefragmentationStats* pDefragmentationStats, - VkDeviceSize& maxBytesToMove, - uint32_t& maxAllocationsToMove) -{ - if(m_pDefragmentator == VMA_NULL) - { - return VK_SUCCESS; - } - - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); - - // Defragment. - VkResult result = m_pDefragmentator->Defragment(maxBytesToMove, maxAllocationsToMove); - - // Accumulate statistics. - if(pDefragmentationStats != VMA_NULL) - { - const VkDeviceSize bytesMoved = m_pDefragmentator->GetBytesMoved(); - const uint32_t allocationsMoved = m_pDefragmentator->GetAllocationsMoved(); - pDefragmentationStats->bytesMoved += bytesMoved; - pDefragmentationStats->allocationsMoved += allocationsMoved; - VMA_ASSERT(bytesMoved <= maxBytesToMove); - VMA_ASSERT(allocationsMoved <= maxAllocationsToMove); - maxBytesToMove -= bytesMoved; - maxAllocationsToMove -= allocationsMoved; - } - - // Free empty blocks. - m_HasEmptyBlock = false; - for(size_t blockIndex = m_Blocks.size(); blockIndex--; ) - { - VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex]; - if(pBlock->m_Metadata.IsEmpty()) + bool defragmentOnGpu; + // There is only one option to defragment this memory type. + if (canDefragmentOnGpu != canDefragmentOnCpu) { - if(m_Blocks.size() > m_MinBlockCount) - { - if(pDefragmentationStats != VMA_NULL) - { - ++pDefragmentationStats->deviceMemoryBlocksFreed; - pDefragmentationStats->bytesFreed += pBlock->m_Metadata.GetSize(); - } + defragmentOnGpu = canDefragmentOnGpu; + } + // Both options are available: Heuristics to choose the best one. + else + { + defragmentOnGpu = (memPropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 || + m_hAllocator->IsIntegratedGpu(); + } - VmaVectorRemove(m_Blocks, blockIndex); - pBlock->Destroy(m_hAllocator); - vma_delete(m_hAllocator, pBlock); + bool overlappingMoveSupported = !defragmentOnGpu; + + if (m_hAllocator->m_UseMutex) + { + if (flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL) + { + if (!m_Mutex.TryLockWrite()) + { + pCtx->res = VK_ERROR_INITIALIZATION_FAILED; + return; + } } else { - m_HasEmptyBlock = true; + m_Mutex.LockWrite(); + pCtx->mutexLocked = true; + } + } + + pCtx->Begin(overlappingMoveSupported, flags); + + // Defragment. + + const VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove; + const uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove; + VmaDefragmentationAlgorithm* algo = pCtx->GetAlgorithm(); + pCtx->res = algo->Defragment(pCtx->defragmentationMoves, maxBytesToMove, maxAllocationsToMove, flags); + + // Accumulate statistics. + if (pStats != VMA_NULL) + { + const VkDeviceSize bytesMoved = algo->GetBytesMoved(); + const uint32_t allocationsMoved = algo->GetAllocationsMoved(); + pStats->bytesMoved += bytesMoved; + pStats->allocationsMoved += allocationsMoved; + VMA_ASSERT(bytesMoved <= maxBytesToMove); + VMA_ASSERT(allocationsMoved <= maxAllocationsToMove); + if (defragmentOnGpu) + { + maxGpuBytesToMove -= bytesMoved; + maxGpuAllocationsToMove -= allocationsMoved; + } + else + { + maxCpuBytesToMove -= bytesMoved; + maxCpuAllocationsToMove -= allocationsMoved; + } + } + + if (flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL) + { + if (m_hAllocator->m_UseMutex) + m_Mutex.UnlockWrite(); + + if (pCtx->res >= VK_SUCCESS && !pCtx->defragmentationMoves.empty()) + pCtx->res = VK_NOT_READY; + + return; + } + + if (pCtx->res >= VK_SUCCESS) + { + if (defragmentOnGpu) + { + ApplyDefragmentationMovesGpu(pCtx, pCtx->defragmentationMoves, commandBuffer); + } + else + { + ApplyDefragmentationMovesCpu(pCtx, pCtx->defragmentationMoves); } } } +} +void VmaBlockVector::DefragmentationEnd( + class VmaBlockVectorDefragmentationContext* pCtx, + uint32_t flags, + VmaDefragmentationStats* pStats) +{ + if (flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL && m_hAllocator->m_UseMutex) + { + VMA_ASSERT(pCtx->mutexLocked == false); + + // Incremental defragmentation doesn't hold the lock, so when we enter here we don't actually have any + // lock protecting us. Since we mutate state here, we have to take the lock out now + m_Mutex.LockWrite(); + pCtx->mutexLocked = true; + } + + // If the mutex isn't locked we didn't do any work and there is nothing to delete. + if (pCtx->mutexLocked || !m_hAllocator->m_UseMutex) + { + // Destroy buffers. + for (size_t blockIndex = pCtx->blockContexts.size(); blockIndex--;) + { + VmaBlockDefragmentationContext& blockCtx = pCtx->blockContexts[blockIndex]; + if (blockCtx.hBuffer) + { + (*m_hAllocator->GetVulkanFunctions().vkDestroyBuffer)(m_hAllocator->m_hDevice, blockCtx.hBuffer, m_hAllocator->GetAllocationCallbacks()); + } + } + + if (pCtx->res >= VK_SUCCESS) + { + FreeEmptyBlocks(pStats); + } + } + + if (pCtx->mutexLocked) + { + VMA_ASSERT(m_hAllocator->m_UseMutex); + m_Mutex.UnlockWrite(); + } +} + +uint32_t VmaBlockVector::ProcessDefragmentations( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves) +{ + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); + + const uint32_t moveCount = VMA_MIN(uint32_t(pCtx->defragmentationMoves.size()) - pCtx->defragmentationMovesProcessed, maxMoves); + + for (uint32_t i = 0; i < moveCount; ++i) + { + VmaDefragmentationMove& move = pCtx->defragmentationMoves[pCtx->defragmentationMovesProcessed + i]; + + pMove->allocation = move.hAllocation; + pMove->memory = move.pDstBlock->GetDeviceMemory(); + pMove->offset = move.dstOffset; + + ++pMove; + } + + pCtx->defragmentationMovesProcessed += moveCount; + + return moveCount; +} + +void VmaBlockVector::CommitDefragmentations( + class VmaBlockVectorDefragmentationContext* pCtx, + VmaDefragmentationStats* pStats) +{ + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); + + for (uint32_t i = pCtx->defragmentationMovesCommitted; i < pCtx->defragmentationMovesProcessed; ++i) + { + const VmaDefragmentationMove& move = pCtx->defragmentationMoves[i]; + + move.pSrcBlock->m_pMetadata->Free(move.hAllocation->GetAllocHandle()); + move.hAllocation->ChangeBlockAllocation(m_hAllocator, move.pDstBlock, move.dstHandle); + } + + pCtx->defragmentationMovesCommitted = pCtx->defragmentationMovesProcessed; + FreeEmptyBlocks(pStats); +} + +size_t VmaBlockVector::CalcAllocationCount() const +{ + size_t result = 0; + for (size_t i = 0; i < m_Blocks.size(); ++i) + { + result += m_Blocks[i]->m_pMetadata->GetAllocationCount(); + } return result; } -void VmaBlockVector::DestroyDefragmentator() +bool VmaBlockVector::IsBufferImageGranularityConflictPossible() const { - if(m_pDefragmentator != VMA_NULL) + if (m_BufferImageGranularity == 1) { - vma_delete(m_hAllocator, m_pDefragmentator); - m_pDefragmentator = VMA_NULL; + return false; } + VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE; + for (size_t i = 0, count = m_Blocks.size(); i < count; ++i) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[i]; + VMA_ASSERT(m_Algorithm == 0); + VmaBlockMetadata_Generic* const pMetadata = (VmaBlockMetadata_Generic*)pBlock->m_pMetadata; + if (pMetadata->IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType)) + { + return true; + } + } + return false; } -void VmaBlockVector::MakePoolAllocationsLost( - uint32_t currentFrameIndex, - size_t* pLostAllocationCount) +VkResult VmaBlockVector::CheckCorruption() { - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + if (!IsCorruptionDetectionEnabled()) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } - for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) { VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; VMA_ASSERT(pBlock); - pBlock->m_Metadata.MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount); + VkResult res = pBlock->CheckCorruption(m_hAllocator); + if (res != VK_SUCCESS) + { + return res; + } } + return VK_SUCCESS; } void VmaBlockVector::AddStats(VmaStats* pStats) @@ -6396,106 +13026,118 @@ void VmaBlockVector::AddStats(VmaStats* pStats) const uint32_t memTypeIndex = m_MemoryTypeIndex; const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex); - VmaMutexLock lock(m_Mutex, m_hAllocator->m_UseMutex); + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); - for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) { const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; VMA_ASSERT(pBlock); VMA_HEAVY_ASSERT(pBlock->Validate()); VmaStatInfo allocationStatInfo; - pBlock->m_Metadata.CalcAllocationStatInfo(allocationStatInfo); + pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo); VmaAddStatInfo(pStats->total, allocationStatInfo); VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo); VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo); } } +#endif // _VMA_BLOCK_VECTOR_FUNCTIONS -//////////////////////////////////////////////////////////////////////////////// -// VmaDefragmentator members definition - -VmaDefragmentator::VmaDefragmentator( +#ifndef _VMA_DEFRAGMENTATION_ALGORITHM_GENERIC_FUNCTIONS +VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic( VmaAllocator hAllocator, VmaBlockVector* pBlockVector, - uint32_t currentFrameIndex) : - m_hAllocator(hAllocator), - m_pBlockVector(pBlockVector), - m_CurrentFrameIndex(currentFrameIndex), + bool overlappingMoveSupported) + : VmaDefragmentationAlgorithm(hAllocator, pBlockVector), + m_AllocationCount(0), + m_AllAllocations(false), m_BytesMoved(0), m_AllocationsMoved(0), - m_Allocations(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), m_Blocks(VmaStlAllocator(hAllocator->GetAllocationCallbacks())) { + // Create block info for each block. + const size_t blockCount = m_pBlockVector->m_Blocks.size(); + for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks()); + pBlockInfo->m_OriginalBlockIndex = blockIndex; + pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex]; + m_Blocks.push_back(pBlockInfo); + } + + // Sort them by m_pBlock pointer value. + VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess()); } -VmaDefragmentator::~VmaDefragmentator() +VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic() { - for(size_t i = m_Blocks.size(); i--; ) + for (size_t i = m_Blocks.size(); i--; ) { vma_delete(m_hAllocator, m_Blocks[i]); } } -void VmaDefragmentator::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) +void VmaDefragmentationAlgorithm_Generic::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { - AllocationInfo allocInfo; - allocInfo.m_hAllocation = hAlloc; - allocInfo.m_pChanged = pChanged; - m_Allocations.push_back(allocInfo); + VmaDeviceMemoryBlock* pBlock = hAlloc->GetBlock(); + BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess()); + if (it != m_Blocks.end() && (*it)->m_pBlock == pBlock) + { + AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged); + (*it)->m_Allocations.push_back(allocInfo); + } + else + { + VMA_ASSERT(0); + } + + ++m_AllocationCount; } -VkResult VmaDefragmentator::BlockInfo::EnsureMapping(VmaAllocator hAllocator, void** ppMappedData) -{ - // It has already been mapped for defragmentation. - if(m_pMappedDataForDefragmentation) - { - *ppMappedData = m_pMappedDataForDefragmentation; - return VK_SUCCESS; - } - - // It is originally mapped. - if(m_pBlock->m_Mapping.GetMappedData()) - { - *ppMappedData = m_pBlock->m_Mapping.GetMappedData(); - return VK_SUCCESS; - } - - // Map on first usage. - VkResult res = m_pBlock->Map(hAllocator, &m_pMappedDataForDefragmentation); - *ppMappedData = m_pMappedDataForDefragmentation; - return res; -} - -void VmaDefragmentator::BlockInfo::Unmap(VmaAllocator hAllocator) -{ - if(m_pMappedDataForDefragmentation != VMA_NULL) - { - m_pBlock->Unmap(hAllocator); - } -} - -VkResult VmaDefragmentator::DefragmentRound( +VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound( + VmaVector< VmaDefragmentationMove, VmaStlAllocator >& moves, VkDeviceSize maxBytesToMove, - uint32_t maxAllocationsToMove) + uint32_t maxAllocationsToMove, + bool freeOldAllocations) { - if(m_Blocks.empty()) + if (m_Blocks.empty()) { return VK_SUCCESS; } + // This is a choice based on research. + // Option 1: + uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; + // Option 2: + //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT; + // Option 3: + //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT; + + size_t srcBlockMinIndex = 0; + // When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations. + /* + if(m_AlgorithmFlags & VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT) + { + const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount(); + if(blocksWithNonMovableCount > 0) + { + srcBlockMinIndex = blocksWithNonMovableCount - 1; + } + } + */ + size_t srcBlockIndex = m_Blocks.size() - 1; size_t srcAllocIndex = SIZE_MAX; - for(;;) + for (;;) { // 1. Find next allocation to move. // 1.1. Start from last to first m_Blocks - they are sorted from most "destination" to most "source". - // 1.2. Then start from last to first m_Allocations - they are sorted from largest to smallest. - while(srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size()) + // 1.2. Then start from last to first m_Allocations. + while (srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size()) { - if(m_Blocks[srcBlockIndex]->m_Allocations.empty()) + if (m_Blocks[srcBlockIndex]->m_Allocations.empty()) { // Finished: no more allocations to process. - if(srcBlockIndex == 0) + if (srcBlockIndex == srcBlockMinIndex) { return VK_SUCCESS; } @@ -6510,7 +13152,7 @@ VkResult VmaDefragmentator::DefragmentRound( srcAllocIndex = m_Blocks[srcBlockIndex]->m_Allocations.size() - 1; } } - + BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex]; AllocationInfo& allocInfo = pSrcBlockInfo->m_Allocations[srcAllocIndex]; @@ -6520,57 +13162,50 @@ VkResult VmaDefragmentator::DefragmentRound( const VmaSuballocationType suballocType = allocInfo.m_hAllocation->GetSuballocationType(); // 2. Try to find new place for this allocation in preceding or current block. - for(size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex) + for (size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex) { BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex]; + VmaBlockMetadata* pMetadata = pDstBlockInfo->m_pBlock->m_pMetadata; VmaAllocationRequest dstAllocRequest; - if(pDstBlockInfo->m_pBlock->m_Metadata.CreateAllocationRequest( - m_CurrentFrameIndex, - m_pBlockVector->GetFrameInUseCount(), - m_pBlockVector->GetBufferImageGranularity(), + if (pMetadata->CreateAllocationRequest( size, alignment, + false, // upperAddress suballocType, - false, // canMakeOtherLost + strategy, &dstAllocRequest) && - MoveMakesSense( - dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset)) + MoveMakesSense( + dstBlockIndex, pMetadata->GetAllocationOffset(dstAllocRequest.allocHandle), srcBlockIndex, srcOffset)) { - VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0); - // Reached limit on number of allocations or bytes to move. - if((m_AllocationsMoved + 1 > maxAllocationsToMove) || + if ((m_AllocationsMoved + 1 > maxAllocationsToMove) || (m_BytesMoved + size > maxBytesToMove)) { - return VK_INCOMPLETE; + return VK_SUCCESS; } - void* pDstMappedData = VMA_NULL; - VkResult res = pDstBlockInfo->EnsureMapping(m_hAllocator, &pDstMappedData); - if(res != VK_SUCCESS) + VmaDefragmentationMove move = {}; + move.srcBlockIndex = pSrcBlockInfo->m_OriginalBlockIndex; + move.dstBlockIndex = pDstBlockInfo->m_OriginalBlockIndex; + move.srcOffset = srcOffset; + move.dstOffset = pMetadata->GetAllocationOffset(dstAllocRequest.allocHandle); + move.size = size; + move.hAllocation = allocInfo.m_hAllocation; + move.pSrcBlock = pSrcBlockInfo->m_pBlock; + move.pDstBlock = pDstBlockInfo->m_pBlock; + move.dstHandle = dstAllocRequest.allocHandle; + + moves.push_back(move); + + pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(dstAllocRequest, suballocType, allocInfo.m_hAllocation); + + if (freeOldAllocations) { - return res; + pSrcBlockInfo->m_pBlock->m_pMetadata->Free(allocInfo.m_hAllocation->GetAllocHandle()); + allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.allocHandle); } - void* pSrcMappedData = VMA_NULL; - res = pSrcBlockInfo->EnsureMapping(m_hAllocator, &pSrcMappedData); - if(res != VK_SUCCESS) - { - return res; - } - - // THE PLACE WHERE ACTUAL DATA COPY HAPPENS. - memcpy( - reinterpret_cast(pDstMappedData) + dstAllocRequest.offset, - reinterpret_cast(pSrcMappedData) + srcOffset, - static_cast(size)); - - pDstBlockInfo->m_pBlock->m_Metadata.Alloc(dstAllocRequest, suballocType, size, allocInfo.m_hAllocation); - pSrcBlockInfo->m_pBlock->m_Metadata.Free(allocInfo.m_hAllocation); - - allocInfo.m_hAllocation->ChangeBlockAllocation(pDstBlockInfo->m_pBlock, dstAllocRequest.offset); - - if(allocInfo.m_pChanged != VMA_NULL) + if (allocInfo.m_pChanged != VMA_NULL) { *allocInfo.m_pChanged = VK_TRUE; } @@ -6586,13 +13221,13 @@ VkResult VmaDefragmentator::DefragmentRound( // If not processed, this allocInfo remains in pBlockInfo->m_Allocations for next round. - if(srcAllocIndex > 0) + if (srcAllocIndex > 0) { --srcAllocIndex; } else { - if(srcBlockIndex > 0) + if (srcBlockIndex > 0) { --srcBlockIndex; srcAllocIndex = SIZE_MAX; @@ -6605,125 +13240,1191 @@ VkResult VmaDefragmentator::DefragmentRound( } } -VkResult VmaDefragmentator::Defragment( - VkDeviceSize maxBytesToMove, - uint32_t maxAllocationsToMove) +bool VmaDefragmentationAlgorithm_Generic::AllocationInfoSizeGreater::operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const { - if(m_Allocations.empty()) - { - return VK_SUCCESS; - } - - // Create block info for each block. - const size_t blockCount = m_pBlockVector->m_Blocks.size(); - for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) - { - BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks()); - pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex]; - m_Blocks.push_back(pBlockInfo); - } - - // Sort them by m_pBlock pointer value. - VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess()); - - // Move allocation infos from m_Allocations to appropriate m_Blocks[memTypeIndex].m_Allocations. - for(size_t blockIndex = 0, allocCount = m_Allocations.size(); blockIndex < allocCount; ++blockIndex) - { - AllocationInfo& allocInfo = m_Allocations[blockIndex]; - // Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost. - if(allocInfo.m_hAllocation->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST) - { - VmaDeviceMemoryBlock* pBlock = allocInfo.m_hAllocation->GetBlock(); - BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess()); - if(it != m_Blocks.end() && (*it)->m_pBlock == pBlock) - { - (*it)->m_Allocations.push_back(allocInfo); - } - else - { - VMA_ASSERT(0); - } - } - } - m_Allocations.clear(); - - for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) - { - BlockInfo* pBlockInfo = m_Blocks[blockIndex]; - pBlockInfo->CalcHasNonMovableAllocations(); - pBlockInfo->SortAllocationsBySizeDescecnding(); - } - - // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks. - VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination()); - - // Execute defragmentation rounds (the main part). - VkResult result = VK_SUCCESS; - for(size_t round = 0; (round < 2) && (result == VK_SUCCESS); ++round) - { - result = DefragmentRound(maxBytesToMove, maxAllocationsToMove); - } - - // Unmap blocks that were mapped for defragmentation. - for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) - { - m_Blocks[blockIndex]->Unmap(m_hAllocator); - } - - return result; + return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize(); } -bool VmaDefragmentator::MoveMakesSense( - size_t dstBlockIndex, VkDeviceSize dstOffset, - size_t srcBlockIndex, VkDeviceSize srcOffset) +bool VmaDefragmentationAlgorithm_Generic::AllocationInfoOffsetGreater::operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const { - if(dstBlockIndex < srcBlockIndex) + return lhs.m_hAllocation->GetOffset() > rhs.m_hAllocation->GetOffset(); +} + +VmaDefragmentationAlgorithm_Generic::BlockInfo::BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) + : m_OriginalBlockIndex(SIZE_MAX), + m_pBlock(VMA_NULL), + m_HasNonMovableAllocations(true), + m_Allocations(pAllocationCallbacks) {} + +void VmaDefragmentationAlgorithm_Generic::BlockInfo::CalcHasNonMovableAllocations() +{ + const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount(); + const size_t defragmentAllocCount = m_Allocations.size(); + m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount; +} + +void VmaDefragmentationAlgorithm_Generic::BlockInfo::SortAllocationsBySizeDescending() +{ + VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater()); +} + +void VmaDefragmentationAlgorithm_Generic::BlockInfo::SortAllocationsByOffsetDescending() +{ + VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater()); +} + +bool VmaDefragmentationAlgorithm_Generic::BlockPointerLess::operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const +{ + return pLhsBlockInfo->m_pBlock < pRhsBlock; +} +bool VmaDefragmentationAlgorithm_Generic::BlockPointerLess::operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const +{ + return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock; +} + +bool VmaDefragmentationAlgorithm_Generic::BlockInfoCompareMoveDestination::operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const +{ + if (pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations) { return true; } - if(dstBlockIndex > srcBlockIndex) + if (!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations) { return false; } - if(dstOffset < srcOffset) + if (pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize()) { return true; } return false; } -//////////////////////////////////////////////////////////////////////////////// -// VmaAllocator_T +bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense( + size_t dstBlockIndex, VkDeviceSize dstOffset, + size_t srcBlockIndex, VkDeviceSize srcOffset) +{ + if (dstBlockIndex < srcBlockIndex) + { + return true; + } + if (dstBlockIndex > srcBlockIndex) + { + return false; + } + if (dstOffset < srcOffset) + { + return true; + } + return false; +} +size_t VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount() const +{ + size_t result = 0; + for (size_t i = 0; i < m_Blocks.size(); ++i) + { + if (m_Blocks[i]->m_HasNonMovableAllocations) + { + ++result; + } + } + return result; +} + +VkResult VmaDefragmentationAlgorithm_Generic::Defragment( + VmaVector< VmaDefragmentationMove, VmaStlAllocator >& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + VmaDefragmentationFlags flags) +{ + if (!m_AllAllocations && m_AllocationCount == 0) + { + return VK_SUCCESS; + } + + const size_t blockCount = m_Blocks.size(); + for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + BlockInfo* pBlockInfo = m_Blocks[blockIndex]; + + if (m_AllAllocations) + { + VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata; + VMA_ASSERT(!pMetadata->IsVirtual()); + for (VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin(); + it != pMetadata->m_Suballocations.end(); + ++it) + { + if (it->type != VMA_SUBALLOCATION_TYPE_FREE) + { + AllocationInfo allocInfo = AllocationInfo((VmaAllocation)it->userData, VMA_NULL); + pBlockInfo->m_Allocations.push_back(allocInfo); + } + } + } + + pBlockInfo->CalcHasNonMovableAllocations(); + + // This is a choice based on research. + // Option 1: + pBlockInfo->SortAllocationsByOffsetDescending(); + // Option 2: + //pBlockInfo->SortAllocationsBySizeDescending(); + } + + // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks. + VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination()); + + // This is a choice based on research. + const uint32_t roundCount = 2; + + // Execute defragmentation rounds (the main part). + VkResult result = VK_SUCCESS; + for (uint32_t round = 0; (round < roundCount) && (result == VK_SUCCESS); ++round) + { + result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove, !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)); + } + + return result; +} +#endif // _VMA_DEFRAGMENTATION_ALGORITHM_GENERIC_FUNCTIONS + +#ifndef _VMA_DEFRAGMENTATION_ALGORITHM_FAST_FUNCTIONS +VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast( + VmaAllocator hAllocator, + VmaBlockVector* pBlockVector, + bool overlappingMoveSupported) + : VmaDefragmentationAlgorithm(hAllocator, pBlockVector), + m_OverlappingMoveSupported(overlappingMoveSupported), + m_AllocationCount(0), + m_AllAllocations(false), + m_BytesMoved(0), + m_AllocationsMoved(0), + m_BlockInfos(VmaStlAllocator(hAllocator->GetAllocationCallbacks())) +{ + VMA_ASSERT(VMA_DEBUG_MARGIN == 0); +} + +VkResult VmaDefragmentationAlgorithm_Fast::Defragment( + VmaVector>& moves, + VkDeviceSize maxBytesToMove, + uint32_t maxAllocationsToMove, + VmaDefragmentationFlags flags) +{ + VMA_ASSERT(m_AllAllocations || m_pBlockVector->CalcAllocationCount() == m_AllocationCount); + + const size_t blockCount = m_pBlockVector->GetBlockCount(); + if (blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0) + { + return VK_SUCCESS; + } + + PreprocessMetadata(); + + // Sort blocks in order from most destination. + + m_BlockInfos.resize(blockCount); + for (size_t i = 0; i < blockCount; ++i) + { + m_BlockInfos[i].origBlockIndex = i; + } + + VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [this](const BlockInfo& lhs, const BlockInfo& rhs) -> bool { + return m_pBlockVector->GetBlock(lhs.origBlockIndex)->m_pMetadata->GetSumFreeSize() < + m_pBlockVector->GetBlock(rhs.origBlockIndex)->m_pMetadata->GetSumFreeSize(); + }); + + // THE MAIN ALGORITHM + + FreeSpaceDatabase freeSpaceDb; + + size_t dstBlockInfoIndex = 0; + size_t dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex; + VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex); + VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata; + VkDeviceSize dstBlockSize = pDstMetadata->GetSize(); + VkDeviceSize dstOffset = 0; + + bool end = false; + for (size_t srcBlockInfoIndex = 0; !end && srcBlockInfoIndex < blockCount; ++srcBlockInfoIndex) + { + const size_t srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex; + VmaDeviceMemoryBlock* const pSrcBlock = m_pBlockVector->GetBlock(srcOrigBlockIndex); + VmaBlockMetadata_Generic* const pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock->m_pMetadata; + for (VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin(); + !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); ) + { + VmaAllocation const pAlloc = (VmaAllocation)srcSuballocIt->userData; + const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment(); + const VkDeviceSize srcAllocSize = srcSuballocIt->size; + if (m_AllocationsMoved == maxAllocationsToMove || + m_BytesMoved + srcAllocSize > maxBytesToMove) + { + end = true; + break; + } + const VkDeviceSize srcAllocOffset = srcSuballocIt->offset; + + VmaDefragmentationMove move = {}; + // Try to place it in one of free spaces from the database. + size_t freeSpaceInfoIndex; + VkDeviceSize dstAllocOffset; + if (freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize, + freeSpaceInfoIndex, dstAllocOffset)) + { + size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex; + VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex); + VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata; + + // Same block + if (freeSpaceInfoIndex == srcBlockInfoIndex) + { + VMA_ASSERT(dstAllocOffset <= srcAllocOffset); + + // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset. + + VmaSuballocation suballoc = *srcSuballocIt; + suballoc.offset = dstAllocOffset; + ((VmaAllocation)(suballoc.userData))->ChangeAllocHandle((VmaAllocHandle)dstAllocOffset); + m_BytesMoved += srcAllocSize; + ++m_AllocationsMoved; + + VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt; + ++nextSuballocIt; + pSrcMetadata->m_Suballocations.erase(srcSuballocIt); + srcSuballocIt = nextSuballocIt; + + InsertSuballoc(pFreeSpaceMetadata, suballoc); + + move.srcBlockIndex = srcOrigBlockIndex; + move.dstBlockIndex = freeSpaceOrigBlockIndex; + move.srcOffset = srcAllocOffset; + move.dstOffset = dstAllocOffset; + move.dstHandle = (VmaAllocHandle)dstAllocOffset; + move.size = srcAllocSize; + + moves.push_back(move); + } + // Different block + else + { + // MOVE OPTION 2: Move the allocation to a different block. + + VMA_ASSERT(freeSpaceInfoIndex < srcBlockInfoIndex); + + VmaSuballocation suballoc = *srcSuballocIt; + suballoc.offset = dstAllocOffset; + ((VmaAllocation)(suballoc.userData))->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, (VmaAllocHandle)dstAllocOffset); + m_BytesMoved += srcAllocSize; + ++m_AllocationsMoved; + + VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt; + ++nextSuballocIt; + pSrcMetadata->m_Suballocations.erase(srcSuballocIt); + srcSuballocIt = nextSuballocIt; + + InsertSuballoc(pFreeSpaceMetadata, suballoc); + + move.srcBlockIndex = srcOrigBlockIndex; + move.dstBlockIndex = freeSpaceOrigBlockIndex; + move.srcOffset = srcAllocOffset; + move.dstOffset = dstAllocOffset; + move.dstHandle = (VmaAllocHandle)dstAllocOffset; + move.size = srcAllocSize; + + moves.push_back(move); + } + } + else + { + dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment); + + // If the allocation doesn't fit before the end of dstBlock, forward to next block. + while (dstBlockInfoIndex < srcBlockInfoIndex && + dstAllocOffset + srcAllocSize > dstBlockSize) + { + // But before that, register remaining free space at the end of dst block. + freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset); + + ++dstBlockInfoIndex; + dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex; + pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex); + pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata; + dstBlockSize = pDstMetadata->GetSize(); + dstOffset = 0; + dstAllocOffset = 0; + } + + // Same block + if (dstBlockInfoIndex == srcBlockInfoIndex) + { + VMA_ASSERT(dstAllocOffset <= srcAllocOffset); + + const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset; + + bool skipOver = overlap; + if (overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset) + { + // If destination and source place overlap, skip if it would move it + // by only < 1/64 of its size. + skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize; + } + + if (skipOver) + { + freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset); + + dstOffset = srcAllocOffset + srcAllocSize; + ++srcSuballocIt; + } + // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset. + else + { + srcSuballocIt->offset = dstAllocOffset; + ((VmaAllocation)(srcSuballocIt->userData))->ChangeAllocHandle((VmaAllocHandle)dstAllocOffset); + dstOffset = dstAllocOffset + srcAllocSize; + m_BytesMoved += srcAllocSize; + ++m_AllocationsMoved; + ++srcSuballocIt; + + move.srcBlockIndex = srcOrigBlockIndex; + move.dstBlockIndex = dstOrigBlockIndex; + move.srcOffset = srcAllocOffset; + move.dstOffset = dstAllocOffset; + move.dstHandle = (VmaAllocHandle)dstAllocOffset; + move.size = srcAllocSize; + + moves.push_back(move); + } + } + // Different block + else + { + // MOVE OPTION 2: Move the allocation to a different block. + + VMA_ASSERT(dstBlockInfoIndex < srcBlockInfoIndex); + VMA_ASSERT(dstAllocOffset + srcAllocSize <= dstBlockSize); + + VmaSuballocation suballoc = *srcSuballocIt; + suballoc.offset = dstAllocOffset; + ((VmaAllocation)(suballoc.userData))->ChangeBlockAllocation(m_hAllocator, pDstBlock, (VmaAllocHandle)dstAllocOffset); + dstOffset = dstAllocOffset + srcAllocSize; + m_BytesMoved += srcAllocSize; + ++m_AllocationsMoved; + + VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt; + ++nextSuballocIt; + pSrcMetadata->m_Suballocations.erase(srcSuballocIt); + srcSuballocIt = nextSuballocIt; + + pDstMetadata->m_Suballocations.push_back(suballoc); + + move.srcBlockIndex = srcOrigBlockIndex; + move.dstBlockIndex = dstOrigBlockIndex; + move.srcOffset = srcAllocOffset; + move.dstOffset = dstAllocOffset; + move.dstHandle = (VmaAllocHandle)dstAllocOffset; + move.size = srcAllocSize; + + moves.push_back(move); + } + } + } + } + + m_BlockInfos.clear(); + + PostprocessMetadata(); + + return VK_SUCCESS; +} + +VmaDefragmentationAlgorithm_Fast::FreeSpaceDatabase::FreeSpaceDatabase() +{ + FreeSpace s = {}; + s.blockInfoIndex = SIZE_MAX; + for (size_t i = 0; i < MAX_COUNT; ++i) + { + m_FreeSpaces[i] = s; + } +} + +void VmaDefragmentationAlgorithm_Fast::FreeSpaceDatabase::Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size) +{ + // Find first invalid or the smallest structure. + size_t bestIndex = SIZE_MAX; + for (size_t i = 0; i < MAX_COUNT; ++i) + { + // Empty structure. + if (m_FreeSpaces[i].blockInfoIndex == SIZE_MAX) + { + bestIndex = i; + break; + } + if (m_FreeSpaces[i].size < size && + (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size > m_FreeSpaces[i].size)) + { + bestIndex = i; + } + } + + if (bestIndex != SIZE_MAX) + { + m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex; + m_FreeSpaces[bestIndex].offset = offset; + m_FreeSpaces[bestIndex].size = size; + } +} + +bool VmaDefragmentationAlgorithm_Fast::FreeSpaceDatabase::Fetch(VkDeviceSize alignment, VkDeviceSize size, + size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset) +{ + size_t bestIndex = SIZE_MAX; + VkDeviceSize bestFreeSpaceAfter = 0; + for (size_t i = 0; i < MAX_COUNT; ++i) + { + // Structure is valid. + if (m_FreeSpaces[i].blockInfoIndex != SIZE_MAX) + { + const VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment); + // Allocation fits into this structure. + if (dstOffset + size <= m_FreeSpaces[i].offset + m_FreeSpaces[i].size) + { + const VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) - + (dstOffset + size); + if (bestIndex == SIZE_MAX || freeSpaceAfter > bestFreeSpaceAfter) + { + bestIndex = i; + bestFreeSpaceAfter = freeSpaceAfter; + } + } + } + } + + if (bestIndex != SIZE_MAX) + { + outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex; + outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment); + + // Leave this structure for remaining empty space. + const VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size; + m_FreeSpaces[bestIndex].offset += alignmentPlusSize; + m_FreeSpaces[bestIndex].size -= alignmentPlusSize; + + return true; + } + + return false; +} + +void VmaDefragmentationAlgorithm_Fast::PreprocessMetadata() +{ + const size_t blockCount = m_pBlockVector->GetBlockCount(); + for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + VmaBlockMetadata_Generic* const pMetadata = + (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata; + pMetadata->m_FreeCount = 0; + pMetadata->m_SumFreeSize = pMetadata->GetSize(); + pMetadata->m_FreeSuballocationsBySize.clear(); + for (VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin(); + it != pMetadata->m_Suballocations.end(); ) + { + if (it->type == VMA_SUBALLOCATION_TYPE_FREE) + { + VmaSuballocationList::iterator nextIt = it; + ++nextIt; + pMetadata->m_Suballocations.erase(it); + it = nextIt; + } + else + { + ++it; + } + } + } +} + +void VmaDefragmentationAlgorithm_Fast::PostprocessMetadata() +{ + const size_t blockCount = m_pBlockVector->GetBlockCount(); + for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + VmaBlockMetadata_Generic* const pMetadata = + (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata; + const VkDeviceSize blockSize = pMetadata->GetSize(); + + // No allocations in this block - entire area is free. + if (pMetadata->m_Suballocations.empty()) + { + pMetadata->m_FreeCount = 1; + //pMetadata->m_SumFreeSize is already set to blockSize. + VmaSuballocation suballoc = { + 0, // offset + blockSize, // size + VMA_NULL, // hAllocation + VMA_SUBALLOCATION_TYPE_FREE }; + pMetadata->m_Suballocations.push_back(suballoc); + pMetadata->RegisterFreeSuballocation(pMetadata->m_Suballocations.begin()); + } + // There are some allocations in this block. + else + { + VkDeviceSize offset = 0; + VmaSuballocationList::iterator it; + for (it = pMetadata->m_Suballocations.begin(); + it != pMetadata->m_Suballocations.end(); + ++it) + { + VMA_ASSERT(it->type != VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(it->offset >= offset); + + // Need to insert preceding free space. + if (it->offset > offset) + { + ++pMetadata->m_FreeCount; + const VkDeviceSize freeSize = it->offset - offset; + VmaSuballocation suballoc = { + offset, // offset + freeSize, // size + VMA_NULL, // hAllocation + VMA_SUBALLOCATION_TYPE_FREE }; + VmaSuballocationList::iterator precedingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc); + pMetadata->m_FreeSuballocationsBySize.push_back(precedingFreeIt); + } + + pMetadata->m_SumFreeSize -= it->size; + offset = it->offset + it->size; + } + + // Need to insert trailing free space. + if (offset < blockSize) + { + ++pMetadata->m_FreeCount; + const VkDeviceSize freeSize = blockSize - offset; + VmaSuballocation suballoc = { + offset, // offset + freeSize, // size + VMA_NULL, // hAllocation + VMA_SUBALLOCATION_TYPE_FREE }; + VMA_ASSERT(it == pMetadata->m_Suballocations.end()); + VmaSuballocationList::iterator trailingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc); + pMetadata->m_FreeSuballocationsBySize.push_back(trailingFreeIt); + } + + VMA_SORT( + pMetadata->m_FreeSuballocationsBySize.begin(), + pMetadata->m_FreeSuballocationsBySize.end(), + VmaSuballocationItemSizeLess()); + } + + VMA_HEAVY_ASSERT(pMetadata->Validate()); + } +} + +void VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc) +{ + VmaSuballocationList& suballocs = pMetadata->m_Suballocations; + VmaSuballocationList::iterator elementAfter; + const VkDeviceSize last = suballocs.rbegin()->offset; + const VkDeviceSize first = suballocs.begin()->offset; + + if (last <= suballoc.offset) + elementAfter = suballocs.end(); + else if (first >= suballoc.offset) + elementAfter = suballocs.begin(); + else + { + const size_t suballocCount = suballocs.size(); + const VkDeviceSize step = (last - first + suballocs.begin()->size) / suballocCount; + // If offset to be inserted is closer to the end of range, search from the end + if ((suballoc.offset - first) / step > suballocCount / 2) + { + elementAfter = suballocs.begin(); + for (VmaSuballocationList::reverse_iterator suballocItem = ++suballocs.rbegin(); + suballocItem != suballocs.rend(); + ++suballocItem) + { + if (suballocItem->offset <= suballoc.offset) + { + elementAfter = --suballocItem; + break; + } + } + } + else + { + elementAfter = suballocs.end(); + for (VmaSuballocationList::iterator suballocItem = ++suballocs.begin(); + suballocItem != suballocs.end(); + ++suballocItem) + { + if (suballocItem->offset >= suballoc.offset) + { + elementAfter = suballocItem; + break; + } + } + } + } + pMetadata->m_Suballocations.insert(elementAfter, suballoc); +} +#endif // _VMA_DEFRAGMENTATION_ALGORITHM_FAST_FUNCTIONS + +#ifndef _VMA_BLOCK_VECTOR_DEFRAGMENTATION_CONTEXT_FUNCTIONS +VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext( + VmaAllocator hAllocator, + VmaPool hCustomPool, + VmaBlockVector* pBlockVector) + : res(VK_SUCCESS), + mutexLocked(false), + blockContexts(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + defragmentationMoves(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + defragmentationMovesProcessed(0), + defragmentationMovesCommitted(0), + hasDefragmentationPlan(0), + m_hAllocator(hAllocator), + m_hCustomPool(hCustomPool), + m_pBlockVector(pBlockVector), + m_pAlgorithm(VMA_NULL), + m_Allocations(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + m_AllAllocations(false) {} + +VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext() +{ + vma_delete(m_hAllocator, m_pAlgorithm); +} + +void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) +{ + AllocInfo info = { hAlloc, pChanged }; + m_Allocations.push_back(info); +} + +void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags) +{ + const bool allAllocations = m_AllAllocations || + m_Allocations.size() == m_pBlockVector->CalcAllocationCount(); + + /******************************** + HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM. + ********************************/ + + /* + Fast algorithm is supported only when certain criteria are met: + - VMA_DEBUG_MARGIN is 0. + - All allocations in this block vector are movable. + - There is no possibility of image/buffer granularity conflict. + - The defragmentation is not incremental + */ + if (VMA_DEBUG_MARGIN == 0 && + allAllocations && + !m_pBlockVector->IsBufferImageGranularityConflictPossible() && + !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)) + { + m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)( + m_hAllocator, m_pBlockVector, overlappingMoveSupported); + } + else + { + m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)( + m_hAllocator, m_pBlockVector, overlappingMoveSupported); + } + + if (allAllocations) + { + m_pAlgorithm->AddAll(); + } + else + { + for (size_t i = 0, count = m_Allocations.size(); i < count; ++i) + { + m_pAlgorithm->AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged); + } + } +} +#endif // _VMA_BLOCK_VECTOR_DEFRAGMENTATION_CONTEXT_FUNCTIONS + +#ifndef _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS +VmaDefragmentationContext_T::VmaDefragmentationContext_T( + VmaAllocator hAllocator, + uint32_t flags, + VmaDefragmentationStats* pStats) + : m_hAllocator(hAllocator), + m_Flags(flags), + m_pStats(pStats), + m_CustomPoolContexts(VmaStlAllocator(hAllocator->GetAllocationCallbacks())) +{ + memset(m_DefaultPoolContexts, 0, sizeof(m_DefaultPoolContexts)); +} + +VmaDefragmentationContext_T::~VmaDefragmentationContext_T() +{ + for (size_t i = m_CustomPoolContexts.size(); i--; ) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i]; + pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats); + vma_delete(m_hAllocator, pBlockVectorCtx); + } + for (size_t i = m_hAllocator->m_MemProps.memoryTypeCount; i--; ) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i]; + if (pBlockVectorCtx) + { + pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats); + vma_delete(m_hAllocator, pBlockVectorCtx); + } + } +} + +void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pPools) +{ + for (uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex) + { + VmaPool pool = pPools[poolIndex]; + VMA_ASSERT(pool); + // Pools with algorithm other than default are not defragmented. + if (pool->m_BlockVector.GetAlgorithm() == 0) + { + VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; + + for (size_t i = m_CustomPoolContexts.size(); i--; ) + { + if (m_CustomPoolContexts[i]->GetCustomPool() == pool) + { + pBlockVectorDefragCtx = m_CustomPoolContexts[i]; + break; + } + } + + if (!pBlockVectorDefragCtx) + { + pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( + m_hAllocator, + pool, + &pool->m_BlockVector); + m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); + } + + pBlockVectorDefragCtx->AddAll(); + } + } +} + +void VmaDefragmentationContext_T::AddAllocations( + uint32_t allocationCount, + const VmaAllocation* pAllocations, + VkBool32* pAllocationsChanged) +{ + // Dispatch pAllocations among defragmentators. Create them when necessary. + for (uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + const VmaAllocation hAlloc = pAllocations[allocIndex]; + VMA_ASSERT(hAlloc); + // DedicatedAlloc cannot be defragmented. + if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) + { + VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL; + + const VmaPool hAllocPool = hAlloc->GetBlock()->GetParentPool(); + // This allocation belongs to custom pool. + if (hAllocPool != VK_NULL_HANDLE) + { + // Pools with algorithm other than default are not defragmented. + if (hAllocPool->m_BlockVector.GetAlgorithm() == 0) + { + for (size_t i = m_CustomPoolContexts.size(); i--; ) + { + if (m_CustomPoolContexts[i]->GetCustomPool() == hAllocPool) + { + pBlockVectorDefragCtx = m_CustomPoolContexts[i]; + break; + } + } + if (!pBlockVectorDefragCtx) + { + pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( + m_hAllocator, + hAllocPool, + &hAllocPool->m_BlockVector); + m_CustomPoolContexts.push_back(pBlockVectorDefragCtx); + } + } + } + // This allocation belongs to default pool. + else + { + const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); + pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex]; + if (!pBlockVectorDefragCtx) + { + VMA_ASSERT(m_hAllocator->m_pBlockVectors[memTypeIndex] && "Trying to use unsupported memory type!"); + + pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)( + m_hAllocator, + VMA_NULL, // hCustomPool + m_hAllocator->m_pBlockVectors[memTypeIndex]); + m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx; + } + } + + if (pBlockVectorDefragCtx) + { + VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ? + &pAllocationsChanged[allocIndex] : VMA_NULL; + pBlockVectorDefragCtx->AddAllocation(hAlloc, pChanged); + } + } + } +} + +VkResult VmaDefragmentationContext_T::Defragment( + VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove, + VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove, + VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags) +{ + if (pStats) + { + memset(pStats, 0, sizeof(VmaDefragmentationStats)); + } + + if (flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL) + { + // For incremental defragmetnations, we just earmark how much we can move + // The real meat is in the defragmentation steps + m_MaxCpuBytesToMove = maxCpuBytesToMove; + m_MaxCpuAllocationsToMove = maxCpuAllocationsToMove; + + m_MaxGpuBytesToMove = maxGpuBytesToMove; + m_MaxGpuAllocationsToMove = maxGpuAllocationsToMove; + + if (m_MaxCpuBytesToMove == 0 && m_MaxCpuAllocationsToMove == 0 && + m_MaxGpuBytesToMove == 0 && m_MaxGpuAllocationsToMove == 0) + return VK_SUCCESS; + + return VK_NOT_READY; + } + + if (commandBuffer == VK_NULL_HANDLE) + { + maxGpuBytesToMove = 0; + maxGpuAllocationsToMove = 0; + } + + VkResult res = VK_SUCCESS; + + // Process default pools. + for (uint32_t memTypeIndex = 0; + memTypeIndex < m_hAllocator->GetMemoryTypeCount() && res >= VK_SUCCESS; + ++memTypeIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex]; + if (pBlockVectorCtx) + { + VMA_ASSERT(pBlockVectorCtx->GetBlockVector()); + pBlockVectorCtx->GetBlockVector()->Defragment( + pBlockVectorCtx, + pStats, flags, + maxCpuBytesToMove, maxCpuAllocationsToMove, + maxGpuBytesToMove, maxGpuAllocationsToMove, + commandBuffer); + if (pBlockVectorCtx->res != VK_SUCCESS) + { + res = pBlockVectorCtx->res; + } + } + } + + // Process custom pools. + for (size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size(); + customCtxIndex < customCtxCount && res >= VK_SUCCESS; + ++customCtxIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex]; + VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector()); + pBlockVectorCtx->GetBlockVector()->Defragment( + pBlockVectorCtx, + pStats, flags, + maxCpuBytesToMove, maxCpuAllocationsToMove, + maxGpuBytesToMove, maxGpuAllocationsToMove, + commandBuffer); + if (pBlockVectorCtx->res != VK_SUCCESS) + { + res = pBlockVectorCtx->res; + } + } + + return res; +} + +VkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo) +{ + VmaDefragmentationPassMoveInfo* pCurrentMove = pInfo->pMoves; + uint32_t movesLeft = pInfo->moveCount; + + // Process default pools. + for (uint32_t memTypeIndex = 0; + memTypeIndex < m_hAllocator->GetMemoryTypeCount(); + ++memTypeIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex]; + if (pBlockVectorCtx) + { + VMA_ASSERT(pBlockVectorCtx->GetBlockVector()); + + if (!pBlockVectorCtx->hasDefragmentationPlan) + { + pBlockVectorCtx->GetBlockVector()->Defragment( + pBlockVectorCtx, + m_pStats, m_Flags, + m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove, + m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove, + VK_NULL_HANDLE); + + if (pBlockVectorCtx->res < VK_SUCCESS) + continue; + + pBlockVectorCtx->hasDefragmentationPlan = true; + } + + const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations( + pBlockVectorCtx, + pCurrentMove, movesLeft); + + movesLeft -= processed; + pCurrentMove += processed; + } + } + + // Process custom pools. + for (size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size(); + customCtxIndex < customCtxCount; + ++customCtxIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex]; + VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector()); + + if (!pBlockVectorCtx->hasDefragmentationPlan) + { + pBlockVectorCtx->GetBlockVector()->Defragment( + pBlockVectorCtx, + m_pStats, m_Flags, + m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove, + m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove, + VK_NULL_HANDLE); + + if (pBlockVectorCtx->res < VK_SUCCESS) + continue; + + pBlockVectorCtx->hasDefragmentationPlan = true; + } + + const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations( + pBlockVectorCtx, + pCurrentMove, movesLeft); + + movesLeft -= processed; + pCurrentMove += processed; + } + + pInfo->moveCount = pInfo->moveCount - movesLeft; + + return VK_SUCCESS; +} + +VkResult VmaDefragmentationContext_T::DefragmentPassEnd() +{ + VkResult res = VK_SUCCESS; + + // Process default pools. + for (uint32_t memTypeIndex = 0; + memTypeIndex < m_hAllocator->GetMemoryTypeCount(); + ++memTypeIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex]; + if (pBlockVectorCtx) + { + VMA_ASSERT(pBlockVectorCtx->GetBlockVector()); + + if (!pBlockVectorCtx->hasDefragmentationPlan) + { + res = VK_NOT_READY; + continue; + } + + pBlockVectorCtx->GetBlockVector()->CommitDefragmentations( + pBlockVectorCtx, m_pStats); + + if (pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted) + res = VK_NOT_READY; + } + } + + // Process custom pools. + for (size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size(); + customCtxIndex < customCtxCount; + ++customCtxIndex) + { + VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex]; + VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector()); + + if (!pBlockVectorCtx->hasDefragmentationPlan) + { + res = VK_NOT_READY; + continue; + } + + pBlockVectorCtx->GetBlockVector()->CommitDefragmentations( + pBlockVectorCtx, m_pStats); + + if (pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted) + res = VK_NOT_READY; + } + + return res; +} +#endif // _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS + +#ifndef _VMA_POOL_T_FUNCTIONS +VmaPool_T::VmaPool_T( + VmaAllocator hAllocator, + const VmaPoolCreateInfo& createInfo, + VkDeviceSize preferredBlockSize) + : m_BlockVector( + hAllocator, + this, // hParentPool + createInfo.memoryTypeIndex, + createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize, + createInfo.minBlockCount, + createInfo.maxBlockCount, + (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), + createInfo.blockSize != 0, // explicitBlockSize + createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm + createInfo.priority, + VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment), + createInfo.pMemoryAllocateNext), + m_Id(0), + m_Name(VMA_NULL) {} + +VmaPool_T::~VmaPool_T() +{ + VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL); +} + +void VmaPool_T::SetName(const char* pName) +{ + const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks(); + VmaFreeString(allocs, m_Name); + + if (pName != VMA_NULL) + { + m_Name = VmaCreateStringCopy(allocs, pName); + } + else + { + m_Name = VMA_NULL; + } +} +#endif // _VMA_POOL_T_FUNCTIONS + +#ifndef _VMA_ALLOCATOR_T_FUNCTIONS VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0), + m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0), m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0), - m_PhysicalDevice(pCreateInfo->physicalDevice), + m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0), + m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0), + m_UseAmdDeviceCoherentMemory((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0), + m_UseKhrBufferDeviceAddress((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0), + m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0), m_hDevice(pCreateInfo->device), + m_hInstance(pCreateInfo->instance), m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL), m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ? *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks), + m_AllocationObjectAllocator(&m_AllocationCallbacks), + m_HeapSizeLimitMask(0), + m_DeviceMemoryCount(0), m_PreferredLargeHeapBlockSize(0), - m_PreferredSmallHeapBlockSize(0), - m_CurrentFrameIndex(0), - m_Pools(VmaStlAllocator(GetAllocationCallbacks())) + m_PhysicalDevice(pCreateInfo->physicalDevice), + m_GpuDefragmentationMemoryTypeBits(UINT32_MAX), + m_NextPoolId(0), + m_GlobalMemoryTypeBits(UINT32_MAX) { - VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device); + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + m_UseKhrDedicatedAllocation = false; + m_UseKhrBindMemory2 = false; + } + + if(VMA_DEBUG_DETECT_CORRUPTION) + { + // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it. + VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0); + } + + VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device && pCreateInfo->instance); + + if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0)) + { +#if !(VMA_DEDICATED_ALLOCATION) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros."); + } +#endif +#if !(VMA_BIND_MEMORY2) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros."); + } +#endif + } +#if !(VMA_MEMORY_BUDGET) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros."); + } +#endif +#if !(VMA_BUFFER_DEVICE_ADDRESS) + if(m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif +#if VMA_VULKAN_VERSION < 1002000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0)) + { + VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros."); + } +#endif +#if VMA_VULKAN_VERSION < 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros."); + } +#endif +#if !(VMA_MEMORY_PRIORITY) + if(m_UseExtMemoryPriority) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks)); - memset(&m_MemProps, 0, sizeof(m_MemProps)); memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties)); - - memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors)); - memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations)); + memset(&m_MemProps, 0, sizeof(m_MemProps)); - for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) - { - m_HeapSizeLimit[i] = VK_WHOLE_SIZE; - } + memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors)); + memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions)); + +#if VMA_EXTERNAL_MEMORY + memset(&m_TypeExternalMemoryHandleTypes, 0, sizeof(m_TypeExternalMemoryHandleTypes)); +#endif // #if VMA_EXTERNAL_MEMORY if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL) { + m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData; m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate; m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree; } @@ -6733,10 +14434,23 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties); (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps); + VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT)); + VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY)); + VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity)); + VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize)); + m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ? pCreateInfo->preferredLargeHeapBlockSize : static_cast(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE); - m_PreferredSmallHeapBlockSize = (pCreateInfo->preferredSmallHeapBlockSize != 0) ? - pCreateInfo->preferredSmallHeapBlockSize : static_cast(VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE); + + m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits(); + +#if VMA_EXTERNAL_MEMORY + if(pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL) + { + memcpy(m_TypeExternalMemoryHandleTypes, pCreateInfo->pTypeExternalMemoryHandleTypes, + sizeof(VkExternalMemoryHandleTypeFlagsKHR) * GetMemoryTypeCount()); + } +#endif // #if VMA_EXTERNAL_MEMORY if(pCreateInfo->pHeapSizeLimit != VMA_NULL) { @@ -6745,7 +14459,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex]; if(limit != VK_WHOLE_SIZE) { - m_HeapSizeLimit[heapIndex] = limit; + m_HeapSizeLimitMask |= 1u << heapIndex; if(limit < m_MemProps.memoryHeaps[heapIndex].size) { m_MemProps.memoryHeaps[heapIndex].size = limit; @@ -6756,93 +14470,241 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex); - - m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)( - this, - memTypeIndex, - preferredBlockSize, - 0, - SIZE_MAX, - GetBufferImageGranularity(), - pCreateInfo->frameInUseCount, - false); // isCustomPool - // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here, - // becase minBlockCount is 0. - m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator(GetAllocationCallbacks())); + // Create only supported types + if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0) + { + const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex); + m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)( + this, + VK_NULL_HANDLE, // hParentPool + memTypeIndex, + preferredBlockSize, + 0, + SIZE_MAX, + GetBufferImageGranularity(), + false, // explicitBlockSize + 0, // algorithm + 0.5f, // priority (0.5 is the default per Vulkan spec) + GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment + VMA_NULL); // // pMemoryAllocateNext + // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here, + // becase minBlockCount is 0. + } } } +VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo) +{ + VkResult res = VK_SUCCESS; + +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + UpdateVulkanBudget(); + } +#endif // #if VMA_MEMORY_BUDGET + + return res; +} + VmaAllocator_T::~VmaAllocator_T() { - VMA_ASSERT(m_Pools.empty()); + VMA_ASSERT(m_Pools.IsEmpty()); - for(size_t i = GetMemoryTypeCount(); i--; ) + for(size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; ) { - vma_delete(this, m_pDedicatedAllocations[i]); - vma_delete(this, m_pBlockVectors[i]); + vma_delete(this, m_pBlockVectors[memTypeIndex]); } } void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions) { #if VMA_STATIC_VULKAN_FUNCTIONS == 1 - m_VulkanFunctions.vkGetPhysicalDeviceProperties = &vkGetPhysicalDeviceProperties; - m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = &vkGetPhysicalDeviceMemoryProperties; - m_VulkanFunctions.vkAllocateMemory = &vkAllocateMemory; - m_VulkanFunctions.vkFreeMemory = &vkFreeMemory; - m_VulkanFunctions.vkMapMemory = &vkMapMemory; - m_VulkanFunctions.vkUnmapMemory = &vkUnmapMemory; - m_VulkanFunctions.vkBindBufferMemory = &vkBindBufferMemory; - m_VulkanFunctions.vkBindImageMemory = &vkBindImageMemory; - m_VulkanFunctions.vkGetBufferMemoryRequirements = &vkGetBufferMemoryRequirements; - m_VulkanFunctions.vkGetImageMemoryRequirements = &vkGetImageMemoryRequirements; - m_VulkanFunctions.vkCreateBuffer = &vkCreateBuffer; - m_VulkanFunctions.vkDestroyBuffer = &vkDestroyBuffer; - m_VulkanFunctions.vkCreateImage = &vkCreateImage; - m_VulkanFunctions.vkDestroyImage = &vkDestroyImage; - if(m_UseKhrDedicatedAllocation) + ImportVulkanFunctions_Static(); +#endif + + if(pVulkanFunctions != VMA_NULL) { - m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = - (PFN_vkGetBufferMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetBufferMemoryRequirements2KHR"); - m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = - (PFN_vkGetImageMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetImageMemoryRequirements2KHR"); + ImportVulkanFunctions_Custom(pVulkanFunctions); } -#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1 + +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + ImportVulkanFunctions_Dynamic(); +#endif + + ValidateVulkanFunctions(); +} + +#if VMA_STATIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Static() +{ + // Vulkan 1.0 + m_VulkanFunctions.vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr; + m_VulkanFunctions.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr; + m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties; + m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties; + m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory; + m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory; + m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory; + m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory; + m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges; + m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges; + m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory; + m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory; + m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements; + m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements; + m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer; + m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer; + m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage; + m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage; + m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer; + + // Vulkan 1.1 +#if VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2; + m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2; + m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2; + m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2; + m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; + } +#endif +} + +#endif // VMA_STATIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions) +{ + VMA_ASSERT(pVulkanFunctions != VMA_NULL); #define VMA_COPY_IF_NOT_NULL(funcName) \ if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName; - if(pVulkanFunctions != VMA_NULL) - { - VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties); - VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties); - VMA_COPY_IF_NOT_NULL(vkAllocateMemory); - VMA_COPY_IF_NOT_NULL(vkFreeMemory); - VMA_COPY_IF_NOT_NULL(vkMapMemory); - VMA_COPY_IF_NOT_NULL(vkUnmapMemory); - VMA_COPY_IF_NOT_NULL(vkBindBufferMemory); - VMA_COPY_IF_NOT_NULL(vkBindImageMemory); - VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements); - VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements); - VMA_COPY_IF_NOT_NULL(vkCreateBuffer); - VMA_COPY_IF_NOT_NULL(vkDestroyBuffer); - VMA_COPY_IF_NOT_NULL(vkCreateImage); - VMA_COPY_IF_NOT_NULL(vkDestroyImage); - VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR); - VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR); - } + VMA_COPY_IF_NOT_NULL(vkGetInstanceProcAddr); + VMA_COPY_IF_NOT_NULL(vkGetDeviceProcAddr); + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties); + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties); + VMA_COPY_IF_NOT_NULL(vkAllocateMemory); + VMA_COPY_IF_NOT_NULL(vkFreeMemory); + VMA_COPY_IF_NOT_NULL(vkMapMemory); + VMA_COPY_IF_NOT_NULL(vkUnmapMemory); + VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges); + VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges); + VMA_COPY_IF_NOT_NULL(vkBindBufferMemory); + VMA_COPY_IF_NOT_NULL(vkBindImageMemory); + VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements); + VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements); + VMA_COPY_IF_NOT_NULL(vkCreateBuffer); + VMA_COPY_IF_NOT_NULL(vkDestroyBuffer); + VMA_COPY_IF_NOT_NULL(vkCreateImage); + VMA_COPY_IF_NOT_NULL(vkDestroyImage); + VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer); + +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR); + VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR); +#endif + +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR); + VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); +#endif + +#if VMA_MEMORY_BUDGET + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); +#endif #undef VMA_COPY_IF_NOT_NULL +} - // If these asserts are hit, you must either #define VMA_STATIC_VULKAN_FUNCTIONS 1 - // or pass valid pointers as VmaAllocatorCreateInfo::pVulkanFunctions. +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Dynamic() +{ + VMA_ASSERT(m_VulkanFunctions.vkGetInstanceProcAddr && m_VulkanFunctions.vkGetDeviceProcAddr && + "To use VMA_DYNAMIC_VULKAN_FUNCTIONS in new versions of VMA you now have to pass " + "VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VmaAllocatorCreateInfo::pVulkanFunctions. " + "Other members can be null."); + +#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \ + if(m_VulkanFunctions.memberName == VMA_NULL) \ + m_VulkanFunctions.memberName = \ + (functionPointerType)m_VulkanFunctions.vkGetInstanceProcAddr(m_hInstance, functionNameString); +#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \ + if(m_VulkanFunctions.memberName == VMA_NULL) \ + m_VulkanFunctions.memberName = \ + (functionPointerType)m_VulkanFunctions.vkGetDeviceProcAddr(m_hDevice, functionNameString); + + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties"); + VMA_FETCH_DEVICE_FUNC(vkAllocateMemory, PFN_vkAllocateMemory, "vkAllocateMemory"); + VMA_FETCH_DEVICE_FUNC(vkFreeMemory, PFN_vkFreeMemory, "vkFreeMemory"); + VMA_FETCH_DEVICE_FUNC(vkMapMemory, PFN_vkMapMemory, "vkMapMemory"); + VMA_FETCH_DEVICE_FUNC(vkUnmapMemory, PFN_vkUnmapMemory, "vkUnmapMemory"); + VMA_FETCH_DEVICE_FUNC(vkFlushMappedMemoryRanges, PFN_vkFlushMappedMemoryRanges, "vkFlushMappedMemoryRanges"); + VMA_FETCH_DEVICE_FUNC(vkInvalidateMappedMemoryRanges, PFN_vkInvalidateMappedMemoryRanges, "vkInvalidateMappedMemoryRanges"); + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory, PFN_vkBindBufferMemory, "vkBindBufferMemory"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory, PFN_vkBindImageMemory, "vkBindImageMemory"); + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements, PFN_vkGetBufferMemoryRequirements, "vkGetBufferMemoryRequirements"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements, PFN_vkGetImageMemoryRequirements, "vkGetImageMemoryRequirements"); + VMA_FETCH_DEVICE_FUNC(vkCreateBuffer, PFN_vkCreateBuffer, "vkCreateBuffer"); + VMA_FETCH_DEVICE_FUNC(vkDestroyBuffer, PFN_vkDestroyBuffer, "vkDestroyBuffer"); + VMA_FETCH_DEVICE_FUNC(vkCreateImage, PFN_vkCreateImage, "vkCreateImage"); + VMA_FETCH_DEVICE_FUNC(vkDestroyImage, PFN_vkDestroyImage, "vkDestroyImage"); + VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, "vkCmdCopyBuffer"); + +#if VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2, "vkGetBufferMemoryRequirements2"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, "vkGetImageMemoryRequirements2"); + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2, "vkBindBufferMemory2"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2, "vkBindImageMemory2"); + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2"); + } +#endif + +#if VMA_DEDICATED_ALLOCATION + if(m_UseKhrDedicatedAllocation) + { + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, "vkGetBufferMemoryRequirements2KHR"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, "vkGetImageMemoryRequirements2KHR"); + } +#endif + +#if VMA_BIND_MEMORY2 + if(m_UseKhrBindMemory2) + { + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, "vkBindBufferMemory2KHR"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, "vkBindImageMemory2KHR"); + } +#endif // #if VMA_BIND_MEMORY2 + +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); + } +#endif // #if VMA_MEMORY_BUDGET + +#undef VMA_FETCH_DEVICE_FUNC +#undef VMA_FETCH_INSTANCE_FUNC +} + +#endif // VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ValidateVulkanFunctions() +{ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL); @@ -6851,161 +14713,336 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL); - if(m_UseKhrDedicatedAllocation) + VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL); + +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation) { VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL); VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL); } +#endif + +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2) + { + VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL); + } +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL); + } +#endif } VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex) { const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size; - return (heapSize <= VMA_SMALL_HEAP_MAX_SIZE) ? - m_PreferredSmallHeapBlockSize : m_PreferredLargeHeapBlockSize; + const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE; + return VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32); } VkResult VmaAllocator_T::AllocateMemoryOfType( - const VkMemoryRequirements& vkMemReq, - bool dedicatedAllocation, + VmaPool pool, + VkDeviceSize size, + VkDeviceSize alignment, + bool dedicatedPreferred, VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, VkImage dedicatedImage, const VmaAllocationCreateInfo& createInfo, uint32_t memTypeIndex, VmaSuballocationType suballocType, - VmaAllocation* pAllocation) + VmaDedicatedAllocationList& dedicatedAllocations, + VmaBlockVector& blockVector, + size_t allocationCount, + VmaAllocation* pAllocations) { - VMA_ASSERT(pAllocation != VMA_NULL); - VMA_DEBUG_LOG(" AllocateMemory: MemoryTypeIndex=%u, Size=%llu", memTypeIndex, vkMemReq.size); + VMA_ASSERT(pAllocations != VMA_NULL); + VMA_DEBUG_LOG(" AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu", memTypeIndex, allocationCount, size); VmaAllocationCreateInfo finalCreateInfo = createInfo; - - // If memory type is not HOST_VISIBLE, disable MAPPED. - if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && - (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) - { - finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT; - } - - VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex]; - VMA_ASSERT(blockVector); - - const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize(); - bool preferDedicatedMemory = - VMA_DEBUG_ALWAYS_DEDICATED_MEMORY || - dedicatedAllocation || - // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size. - vkMemReq.size > preferredBlockSize / 2; - - if(preferDedicatedMemory && - (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 && - finalCreateInfo.pool == VK_NULL_HANDLE) - { - finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } + VkResult res = CalcMemTypeParams( + finalCreateInfo, + memTypeIndex, + size, + allocationCount); + if(res != VK_SUCCESS) + return res; if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) { - if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) - { - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - else - { - return AllocateDedicatedMemory( - vkMemReq.size, - suballocType, - memTypeIndex, - (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, - (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, - finalCreateInfo.pUserData, - dedicatedBuffer, - dedicatedImage, - pAllocation); - } + return AllocateDedicatedMemory( + pool, + size, + suballocType, + dedicatedAllocations, + memTypeIndex, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, + finalCreateInfo.pUserData, + finalCreateInfo.priority, + dedicatedBuffer, + dedicatedBufferUsage, + dedicatedImage, + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); } else { - VkResult res = blockVector->Allocate( - VK_NULL_HANDLE, // hCurrentPool - m_CurrentFrameIndex.load(), - vkMemReq, - finalCreateInfo, - suballocType, - pAllocation); - if(res == VK_SUCCESS) + const bool canAllocateDedicated = + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 && + (pool == VK_NULL_HANDLE || !blockVector.HasExplicitBlockSize()); + + if(canAllocateDedicated) { - return res; + // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size. + if(size > blockVector.GetPreferredBlockSize() / 2) + { + dedicatedPreferred = true; + } + // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget, + // which can quickly deplete maxMemoryAllocationCount: Don't prefer dedicated allocations when above + // 3/4 of the maximum allocation count. + if(m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4) + { + dedicatedPreferred = false; + } + + if(dedicatedPreferred) + { + res = AllocateDedicatedMemory( + pool, + size, + suballocType, + dedicatedAllocations, + memTypeIndex, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, + finalCreateInfo.pUserData, + finalCreateInfo.priority, + dedicatedBuffer, + dedicatedBufferUsage, + dedicatedImage, + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); + if(res == VK_SUCCESS) + { + // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here. + VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); + return VK_SUCCESS; + } + } } - // 5. Try dedicated memory. - if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) - { - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - else + res = blockVector.Allocate( + size, + alignment, + finalCreateInfo, + suballocType, + allocationCount, + pAllocations); + if(res == VK_SUCCESS) + return VK_SUCCESS; + + // Try dedicated memory. + if(canAllocateDedicated && !dedicatedPreferred) { res = AllocateDedicatedMemory( - vkMemReq.size, + pool, + size, suballocType, + dedicatedAllocations, memTypeIndex, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, finalCreateInfo.pUserData, + finalCreateInfo.priority, dedicatedBuffer, + dedicatedBufferUsage, dedicatedImage, - pAllocation); + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); if(res == VK_SUCCESS) { // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here. VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); return VK_SUCCESS; } - else - { - // Everything failed: Return error code. - VMA_DEBUG_LOG(" vkAllocateMemory FAILED"); - return res; - } } + // Everything failed: Return error code. + VMA_DEBUG_LOG(" vkAllocateMemory FAILED"); + return res; } } VkResult VmaAllocator_T::AllocateDedicatedMemory( + VmaPool pool, VkDeviceSize size, VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, uint32_t memTypeIndex, bool map, bool isUserDataString, + bool canAliasMemory, void* pUserData, + float priority, VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, VkImage dedicatedImage, - VmaAllocation* pAllocation) + size_t allocationCount, + VmaAllocation* pAllocations, + const void* pNextChain) { - VMA_ASSERT(pAllocation); + VMA_ASSERT(allocationCount > 0 && pAllocations); VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; allocInfo.memoryTypeIndex = memTypeIndex; allocInfo.allocationSize = size; + allocInfo.pNext = pNextChain; +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR }; - if(m_UseKhrDedicatedAllocation) + if(!canAliasMemory) { + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + if(dedicatedBuffer != VK_NULL_HANDLE) + { + VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE); + dedicatedAllocInfo.buffer = dedicatedBuffer; + VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); + } + else if(dedicatedImage != VK_NULL_HANDLE) + { + dedicatedAllocInfo.image = dedicatedImage; + VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); + } + } + } +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + +#if VMA_BUFFER_DEVICE_ADDRESS + VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR }; + if(m_UseKhrBufferDeviceAddress) + { + bool canContainBufferWithDeviceAddress = true; if(dedicatedBuffer != VK_NULL_HANDLE) { - VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE); - dedicatedAllocInfo.buffer = dedicatedBuffer; - allocInfo.pNext = &dedicatedAllocInfo; + canContainBufferWithDeviceAddress = dedicatedBufferUsage == UINT32_MAX || // Usage flags unknown + (dedicatedBufferUsage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0; } else if(dedicatedImage != VK_NULL_HANDLE) { - dedicatedAllocInfo.image = dedicatedImage; - allocInfo.pNext = &dedicatedAllocInfo; + canContainBufferWithDeviceAddress = false; + } + if(canContainBufferWithDeviceAddress) + { + allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo); + } + } +#endif // #if VMA_BUFFER_DEVICE_ADDRESS + +#if VMA_MEMORY_PRIORITY + VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; + if(m_UseExtMemoryPriority) + { + priorityInfo.priority = priority; + VmaPnextChainPushFront(&allocInfo, &priorityInfo); + } +#endif // #if VMA_MEMORY_PRIORITY + +#if VMA_EXTERNAL_MEMORY + // Attach VkExportMemoryAllocateInfoKHR if necessary. + VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; + exportMemoryAllocInfo.handleTypes = GetExternalMemoryHandleTypeFlags(memTypeIndex); + if(exportMemoryAllocInfo.handleTypes != 0) + { + VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo); + } +#endif // #if VMA_EXTERNAL_MEMORY + + size_t allocIndex; + VkResult res = VK_SUCCESS; + for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + res = AllocateDedicatedMemoryPage( + pool, + size, + suballocType, + memTypeIndex, + allocInfo, + map, + isUserDataString, + pUserData, + pAllocations + allocIndex); + if(res != VK_SUCCESS) + { + break; } } - // Allocate VkDeviceMemory. + if(res == VK_SUCCESS) + { + for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + dedicatedAllocations.Register(pAllocations[allocIndex]); + } + VMA_DEBUG_LOG(" Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u", allocationCount, memTypeIndex); + } + else + { + // Free all already created allocations. + while(allocIndex--) + { + VmaAllocation currAlloc = pAllocations[allocIndex]; + VkDeviceMemory hMemory = currAlloc->GetMemory(); + + /* + There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory + before vkFreeMemory. + + if(currAlloc->GetMappedData() != VMA_NULL) + { + (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory); + } + */ + + FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory); + m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize()); + currAlloc->SetUserData(this, VMA_NULL); + m_AllocationObjectAllocator.Free(currAlloc); + } + + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + } + + return res; +} + +VkResult VmaAllocator_T::AllocateDedicatedMemoryPage( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + uint32_t memTypeIndex, + const VkMemoryAllocateInfo& allocInfo, + bool map, + bool isUserDataString, + void* pUserData, + VmaAllocation* pAllocation) +{ VkDeviceMemory hMemory = VK_NULL_HANDLE; VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory); if(res < 0) @@ -7014,7 +15051,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( return res; } - void* pMappedData = nullptr; + void* pMappedData = VMA_NULL; if(map) { res = (*m_VulkanFunctions.vkMapMemory)( @@ -7032,20 +15069,15 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory( } } - *pAllocation = vma_new(this, VmaAllocation_T)(m_CurrentFrameIndex.load(), isUserDataString); - (*pAllocation)->InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size); + *pAllocation = m_AllocationObjectAllocator.Allocate(isUserDataString); + (*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size); (*pAllocation)->SetUserData(this, pUserData); - - // Register it in m_pDedicatedAllocations. + m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size); + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) { - VmaMutexLock lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex); - AllocationVectorType* pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex]; - VMA_ASSERT(pDedicatedAllocations); - VmaVectorInsertSorted(*pDedicatedAllocations, *pAllocation); + FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED); } - VMA_DEBUG_LOG(" Allocated DedicatedMemory MemoryTypeIndex=#%u", memTypeIndex); - return VK_SUCCESS; } @@ -7055,7 +15087,8 @@ void VmaAllocator_T::GetBufferMemoryRequirements( bool& requiresDedicatedAllocation, bool& prefersDedicatedAllocation) const { - if(m_UseKhrDedicatedAllocation) +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR }; memReqInfo.buffer = hBuffer; @@ -7063,7 +15096,7 @@ void VmaAllocator_T::GetBufferMemoryRequirements( VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR }; VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR }; - memReq2.pNext = &memDedicatedReq; + VmaPnextChainPushFront(&memReq2, &memDedicatedReq); (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2); @@ -7072,6 +15105,7 @@ void VmaAllocator_T::GetBufferMemoryRequirements( prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); } else +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 { (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq); requiresDedicatedAllocation = false; @@ -7085,7 +15119,8 @@ void VmaAllocator_T::GetImageMemoryRequirements( bool& requiresDedicatedAllocation, bool& prefersDedicatedAllocation) const { - if(m_UseKhrDedicatedAllocation) +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) { VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR }; memReqInfo.image = hImage; @@ -7093,7 +15128,7 @@ void VmaAllocator_T::GetImageMemoryRequirements( VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR }; VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR }; - memReq2.pNext = &memDedicatedReq; + VmaPnextChainPushFront(&memReq2, &memDedicatedReq); (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2); @@ -7102,6 +15137,7 @@ void VmaAllocator_T::GetImageMemoryRequirements( prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); } else +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 { (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq); requiresDedicatedAllocation = false; @@ -7109,183 +15145,237 @@ void VmaAllocator_T::GetImageMemoryRequirements( } } +VkResult VmaAllocator_T::CalcMemTypeParams( + VmaAllocationCreateInfo& inoutCreateInfo, + uint32_t memTypeIndex, + VkDeviceSize size, + size_t allocationCount) +{ + // If memory type is not HOST_VISIBLE, disable MAPPED. + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && + (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + inoutCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT; + } + + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0) + { + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + VmaBudget heapBudget = {}; + GetHeapBudgets(&heapBudget, heapIndex, 1); + if(heapBudget.usage + size * allocationCount > heapBudget.budget) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + } + return VK_SUCCESS; +} + +VkResult VmaAllocator_T::CalcAllocationParams( + VmaAllocationCreateInfo& inoutCreateInfo, + bool dedicatedRequired, + bool dedicatedPreferred) +{ + if(dedicatedRequired || + // If memory is lazily allocated, it should be always dedicated. + inoutCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED) + { + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + } + + if(inoutCreateInfo.pool != VK_NULL_HANDLE) + { + if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + { + VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); + return VK_ERROR_FEATURE_NOT_PRESENT; + } + inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority(); + } + + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) + { + VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense."); + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + if(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) + { + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + } + return VK_SUCCESS; +} + VkResult VmaAllocator_T::AllocateMemory( const VkMemoryRequirements& vkMemReq, bool requiresDedicatedAllocation, bool prefersDedicatedAllocation, VkBuffer dedicatedBuffer, + VkBufferUsageFlags dedicatedBufferUsage, VkImage dedicatedImage, const VmaAllocationCreateInfo& createInfo, VmaSuballocationType suballocType, - VmaAllocation* pAllocation) + size_t allocationCount, + VmaAllocation* pAllocations) { - if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && - (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + + VMA_ASSERT(VmaIsPow2(vkMemReq.alignment)); + + if(vkMemReq.size == 0) { - VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense."); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if((createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && - (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0) - { - VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid."); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if(requiresDedicatedAllocation) - { - if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) - { - VMA_ASSERT(0 && "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required."); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - if(createInfo.pool != VK_NULL_HANDLE) - { - VMA_ASSERT(0 && "Pool specified while dedicated allocation is required."); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - } - if((createInfo.pool != VK_NULL_HANDLE) && - ((createInfo.flags & (VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)) != 0)) - { - VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid."); - return VK_ERROR_OUT_OF_DEVICE_MEMORY; + return VK_ERROR_INITIALIZATION_FAILED; } - if(createInfo.pool != VK_NULL_HANDLE) + VmaAllocationCreateInfo createInfoFinal = createInfo; + VkResult res = CalcAllocationParams(createInfoFinal, requiresDedicatedAllocation, prefersDedicatedAllocation); + if(res != VK_SUCCESS) + return res; + + if(createInfoFinal.pool != VK_NULL_HANDLE) { - return createInfo.pool->m_BlockVector.Allocate( - createInfo.pool, - m_CurrentFrameIndex.load(), - vkMemReq, - createInfo, + VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector; + return AllocateMemoryOfType( + createInfoFinal.pool, + vkMemReq.size, + vkMemReq.alignment, + prefersDedicatedAllocation, + dedicatedBuffer, + dedicatedBufferUsage, + dedicatedImage, + createInfoFinal, + blockVector.GetMemoryTypeIndex(), suballocType, - pAllocation); + createInfoFinal.pool->m_DedicatedAllocations, + blockVector, + allocationCount, + pAllocations); } else { // Bit mask of memory Vulkan types acceptable for this allocation. uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; uint32_t memTypeIndex = UINT32_MAX; - VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex); - if(res == VK_SUCCESS) + res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); + // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. + if(res != VK_SUCCESS) + return res; + do { + VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); res = AllocateMemoryOfType( - vkMemReq, + VK_NULL_HANDLE, + vkMemReq.size, + vkMemReq.alignment, requiresDedicatedAllocation || prefersDedicatedAllocation, dedicatedBuffer, + dedicatedBufferUsage, dedicatedImage, - createInfo, + createInfoFinal, memTypeIndex, suballocType, - pAllocation); - // Succeeded on first try. + m_DedicatedAllocations[memTypeIndex], + *blockVector, + allocationCount, + pAllocations); + // Allocation succeeded if(res == VK_SUCCESS) - { - return res; - } - // Allocation from this memory type failed. Try other compatible memory types. - else - { - for(;;) - { - // Remove old memTypeIndex from list of possibilities. - memoryTypeBits &= ~(1u << memTypeIndex); - // Find alternative memTypeIndex. - res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex); - if(res == VK_SUCCESS) - { - res = AllocateMemoryOfType( - vkMemReq, - requiresDedicatedAllocation || prefersDedicatedAllocation, - dedicatedBuffer, - dedicatedImage, - createInfo, - memTypeIndex, - suballocType, - pAllocation); - // Allocation from this alternative memory type succeeded. - if(res == VK_SUCCESS) - { - return res; - } - // else: Allocation from this memory type failed. Try next one - next loop iteration. - } - // No other matching memory type index could be found. - else - { - // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - } - } - } - // Can't find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. - else - return res; + return VK_SUCCESS; + + // Remove old memTypeIndex from list of possibilities. + memoryTypeBits &= ~(1u << memTypeIndex); + // Find alternative memTypeIndex. + res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex); + } while(res == VK_SUCCESS); + + // No other matching memory type index could be found. + // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. + return VK_ERROR_OUT_OF_DEVICE_MEMORY; } } -void VmaAllocator_T::FreeMemory(const VmaAllocation allocation) +void VmaAllocator_T::FreeMemory( + size_t allocationCount, + const VmaAllocation* pAllocations) { - VMA_ASSERT(allocation); + VMA_ASSERT(pAllocations); - if(allocation->CanBecomeLost() == false || - allocation->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST) + for(size_t allocIndex = allocationCount; allocIndex--; ) { - switch(allocation->GetType()) + VmaAllocation allocation = pAllocations[allocIndex]; + + if(allocation != VK_NULL_HANDLE) { - case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) { - VmaBlockVector* pBlockVector = VMA_NULL; - VmaPool hPool = allocation->GetPool(); - if(hPool != VK_NULL_HANDLE) - { - pBlockVector = &hPool->m_BlockVector; - } - else - { - const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); - pBlockVector = m_pBlockVectors[memTypeIndex]; - } - pBlockVector->Free(allocation); + FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED); } - break; - case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: - FreeDedicatedMemory(allocation); - break; - default: - VMA_ASSERT(0); + + switch(allocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaBlockVector* pBlockVector = VMA_NULL; + VmaPool hPool = allocation->GetParentPool(); + if(hPool != VK_NULL_HANDLE) + { + pBlockVector = &hPool->m_BlockVector; + } + else + { + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + pBlockVector = m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); + } + pBlockVector->Free(allocation); + } + break; + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + FreeDedicatedMemory(allocation); + break; + default: + VMA_ASSERT(0); + } + + m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize()); + allocation->SetUserData(this, VMA_NULL); + m_AllocationObjectAllocator.Free(allocation); } } - - allocation->SetUserData(this, VMA_NULL); - vma_delete(this, allocation); } void VmaAllocator_T::CalculateStats(VmaStats* pStats) { // Initialize. - InitStatInfo(pStats->total); + VmaInitStatInfo(pStats->total); for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) - InitStatInfo(pStats->memoryType[i]); + VmaInitStatInfo(pStats->memoryType[i]); for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) - InitStatInfo(pStats->memoryHeap[i]); - + VmaInitStatInfo(pStats->memoryHeap[i]); + // Process default pools. for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; - VMA_ASSERT(pBlockVector); - pBlockVector->AddStats(pStats); + if (pBlockVector != VMA_NULL) + pBlockVector->AddStats(pStats); } // Process custom pools. { - VmaMutexLock lock(m_PoolsMutex, m_UseMutex); - for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex) + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { - m_Pools[poolIndex]->GetBlockVector().AddStats(pStats); + VmaBlockVector& blockVector = pool->m_BlockVector; + blockVector.AddStats(pStats); + const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); + const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + pool->m_DedicatedAllocations.AddStats(pStats, memTypeIndex, memHeapIndex); } } @@ -7293,17 +15383,7 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats) for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); - VmaMutexLock dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex); - AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex]; - VMA_ASSERT(pDedicatedAllocVector); - for(size_t allocIndex = 0, allocCount = pDedicatedAllocVector->size(); allocIndex < allocCount; ++allocIndex) - { - VmaStatInfo allocationStatInfo; - (*pDedicatedAllocVector)[allocIndex]->DedicatedAllocCalcStatsInfo(allocationStatInfo); - VmaAddStatInfo(pStats->total, allocationStatInfo); - VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo); - VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo); - } + m_DedicatedAllocations[memTypeIndex].AddStats(pStats, memTypeIndex, memHeapIndex); } // Postprocess. @@ -7314,189 +15394,153 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats) VmaPostprocessCalcStatInfo(pStats->memoryHeap[i]); } -static const uint32_t VMA_VENDOR_ID_AMD = 4098; - -VkResult VmaAllocator_T::Defragment( - VmaAllocation* pAllocations, - size_t allocationCount, - VkBool32* pAllocationsChanged, - const VmaDefragmentationInfo* pDefragmentationInfo, - VmaDefragmentationStats* pDefragmentationStats) +void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount) { - if(pAllocationsChanged != VMA_NULL) +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) { - memset(pAllocationsChanged, 0, sizeof(*pAllocationsChanged)); - } - if(pDefragmentationStats != VMA_NULL) - { - memset(pDefragmentationStats, 0, sizeof(*pDefragmentationStats)); - } - - const uint32_t currentFrameIndex = m_CurrentFrameIndex.load(); - - VmaMutexLock poolsLock(m_PoolsMutex, m_UseMutex); - - const size_t poolCount = m_Pools.size(); - - // Dispatch pAllocations among defragmentators. Create them in BlockVectors when necessary. - for(size_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) - { - VmaAllocation hAlloc = pAllocations[allocIndex]; - VMA_ASSERT(hAlloc); - const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex(); - // DedicatedAlloc cannot be defragmented. - if((hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) && - // Only HOST_VISIBLE memory types can be defragmented. - ((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) && - // Lost allocation cannot be defragmented. - (hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)) + if(m_Budget.m_OperationsSinceBudgetFetch < 30) { - VmaBlockVector* pAllocBlockVector = nullptr; - - const VmaPool hAllocPool = hAlloc->GetPool(); - // This allocation belongs to custom pool. - if(hAllocPool != VK_NULL_HANDLE) + VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex); + for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) { - pAllocBlockVector = &hAllocPool->GetBlockVector(); + const uint32_t heapIndex = firstHeap + i; + + outBudgets->blockBytes = m_Budget.m_BlockBytes[heapIndex]; + outBudgets->allocationBytes = m_Budget.m_AllocationBytes[heapIndex]; + + if(m_Budget.m_VulkanUsage[heapIndex] + outBudgets->blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]) + { + outBudgets->usage = m_Budget.m_VulkanUsage[heapIndex] + + outBudgets->blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; + } + else + { + outBudgets->usage = 0; + } + + // Have to take MIN with heap size because explicit HeapSizeLimit is included in it. + outBudgets->budget = VMA_MIN( + m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size); } - // This allocation belongs to general pool. - else - { - pAllocBlockVector = m_pBlockVectors[memTypeIndex]; - } - - VmaDefragmentator* const pDefragmentator = pAllocBlockVector->EnsureDefragmentator(this, currentFrameIndex); - - VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ? - &pAllocationsChanged[allocIndex] : VMA_NULL; - pDefragmentator->AddAllocation(hAlloc, pChanged); } - } - - VkResult result = VK_SUCCESS; - - // ======== Main processing. - - VkDeviceSize maxBytesToMove = SIZE_MAX; - uint32_t maxAllocationsToMove = UINT32_MAX; - if(pDefragmentationInfo != VMA_NULL) - { - maxBytesToMove = pDefragmentationInfo->maxBytesToMove; - maxAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove; - } - - // Process standard memory. - for(uint32_t memTypeIndex = 0; - (memTypeIndex < GetMemoryTypeCount()) && (result == VK_SUCCESS); - ++memTypeIndex) - { - // Only HOST_VISIBLE memory types can be defragmented. - if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) + else { - result = m_pBlockVectors[memTypeIndex]->Defragment( - pDefragmentationStats, - maxBytesToMove, - maxAllocationsToMove); + UpdateVulkanBudget(); // Outside of mutex lock + GetHeapBudgets(outBudgets, firstHeap, heapCount); // Recursion } } - - // Process custom pools. - for(size_t poolIndex = 0; (poolIndex < poolCount) && (result == VK_SUCCESS); ++poolIndex) + else +#endif { - result = m_Pools[poolIndex]->GetBlockVector().Defragment( - pDefragmentationStats, - maxBytesToMove, - maxAllocationsToMove); - } - - // ======== Destroy defragmentators. - - // Process custom pools. - for(size_t poolIndex = poolCount; poolIndex--; ) - { - m_Pools[poolIndex]->GetBlockVector().DestroyDefragmentator(); - } - - // Process standard memory. - for(uint32_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; ) - { - if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) + for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) { - m_pBlockVectors[memTypeIndex]->DestroyDefragmentator(); + const uint32_t heapIndex = firstHeap + i; + + outBudgets->blockBytes = m_Budget.m_BlockBytes[heapIndex]; + outBudgets->allocationBytes = m_Budget.m_AllocationBytes[heapIndex]; + + outBudgets->usage = outBudgets->blockBytes; + outBudgets->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics. } } +} - return result; +VkResult VmaAllocator_T::DefragmentationBegin( + const VmaDefragmentationInfo2& info, + VmaDefragmentationStats* pStats, + VmaDefragmentationContext* pContext) +{ + if(info.pAllocationsChanged != VMA_NULL) + { + memset(info.pAllocationsChanged, 0, info.allocationCount * sizeof(VkBool32)); + } + + *pContext = vma_new(this, VmaDefragmentationContext_T)( + this, info.flags, pStats); + + (*pContext)->AddPools(info.poolCount, info.pPools); + (*pContext)->AddAllocations( + info.allocationCount, info.pAllocations, info.pAllocationsChanged); + + VkResult res = (*pContext)->Defragment( + info.maxCpuBytesToMove, info.maxCpuAllocationsToMove, + info.maxGpuBytesToMove, info.maxGpuAllocationsToMove, + info.commandBuffer, pStats, info.flags); + + if(res != VK_NOT_READY) + { + vma_delete(this, *pContext); + *pContext = VMA_NULL; + } + + return res; +} + +VkResult VmaAllocator_T::DefragmentationEnd( + VmaDefragmentationContext context) +{ + vma_delete(this, context); + return VK_SUCCESS; +} + +VkResult VmaAllocator_T::DefragmentationPassBegin( + VmaDefragmentationPassInfo* pInfo, + VmaDefragmentationContext context) +{ + return context->DefragmentPassBegin(pInfo); +} + +VkResult VmaAllocator_T::DefragmentationPassEnd( + VmaDefragmentationContext context) +{ + return context->DefragmentPassEnd(); } void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo) { - if(hAllocation->CanBecomeLost()) - { - /* - Warning: This is a carefully designed algorithm. - Do not modify unless you really know what you're doing :) - */ - uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load(); - uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex(); - for(;;) - { - if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST) - { - pAllocationInfo->memoryType = UINT32_MAX; - pAllocationInfo->deviceMemory = VK_NULL_HANDLE; - pAllocationInfo->offset = 0; - pAllocationInfo->size = hAllocation->GetSize(); - pAllocationInfo->pMappedData = VMA_NULL; - pAllocationInfo->pUserData = hAllocation->GetUserData(); - return; - } - else if(localLastUseFrameIndex == localCurrFrameIndex) - { - pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex(); - pAllocationInfo->deviceMemory = hAllocation->GetMemory(); - pAllocationInfo->offset = hAllocation->GetOffset(); - pAllocationInfo->size = hAllocation->GetSize(); - pAllocationInfo->pMappedData = VMA_NULL; - pAllocationInfo->pUserData = hAllocation->GetUserData(); - return; - } - else // Last use time earlier than current time. - { - if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex)) - { - localLastUseFrameIndex = localCurrFrameIndex; - } - } - } - } - else - { - pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex(); - pAllocationInfo->deviceMemory = hAllocation->GetMemory(); - pAllocationInfo->offset = hAllocation->GetOffset(); - pAllocationInfo->size = hAllocation->GetSize(); - pAllocationInfo->pMappedData = hAllocation->GetMappedData(); - pAllocationInfo->pUserData = hAllocation->GetUserData(); - } + pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex(); + pAllocationInfo->deviceMemory = hAllocation->GetMemory(); + pAllocationInfo->offset = hAllocation->GetOffset(); + pAllocationInfo->size = hAllocation->GetSize(); + pAllocationInfo->pMappedData = hAllocation->GetMappedData(); + pAllocationInfo->pUserData = hAllocation->GetUserData(); } VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool) { - VMA_DEBUG_LOG(" CreatePool: MemoryTypeIndex=%u", pCreateInfo->memoryTypeIndex); + VMA_DEBUG_LOG(" CreatePool: MemoryTypeIndex=%u, flags=%u", pCreateInfo->memoryTypeIndex, pCreateInfo->flags); VmaPoolCreateInfo newCreateInfo = *pCreateInfo; + // Protection against uninitialized new structure member. If garbage data are left there, this pointer dereference would crash. + if(pCreateInfo->pMemoryAllocateNext) + { + VMA_ASSERT(((const VkBaseInStructure*)pCreateInfo->pMemoryAllocateNext)->sType != 0); + } + if(newCreateInfo.maxBlockCount == 0) { newCreateInfo.maxBlockCount = SIZE_MAX; } - if(newCreateInfo.blockSize == 0) + if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount) { - newCreateInfo.blockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex); + return VK_ERROR_INITIALIZATION_FAILED; + } + // Memory type index out of range or forbidden. + if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || + ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + if(newCreateInfo.minAllocationAlignment > 0) + { + VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment)); } - *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo); + const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex); + + *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize); VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks(); if(res != VK_SUCCESS) @@ -7508,8 +15552,9 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo // Add to m_Pools. { - VmaMutexLock lock(m_PoolsMutex, m_UseMutex); - VmaVectorInsertSorted(m_Pools, *pPool); + VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex); + (*pPool)->SetId(m_NextPoolId++); + m_Pools.PushBack(*pPool); } return VK_SUCCESS; @@ -7519,9 +15564,8 @@ void VmaAllocator_T::DestroyPool(VmaPool pool) { // Remove from m_Pools. { - VmaMutexLock lock(m_PoolsMutex, m_UseMutex); - bool success = VmaVectorRemoveSorted(m_Pools, pool); - VMA_ASSERT(success && "Pool not found in Allocator."); + VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex); + m_Pools.Remove(pool); } vma_delete(this, pool); @@ -7529,58 +15573,138 @@ void VmaAllocator_T::DestroyPool(VmaPool pool) void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats) { - pool->m_BlockVector.GetPoolStats(pPoolStats); + pPoolStats->size = 0; + pPoolStats->unusedSize = 0; + pPoolStats->allocationCount = 0; + pPoolStats->unusedRangeCount = 0; + pPoolStats->blockCount = 0; + + pool->m_BlockVector.AddPoolStats(pPoolStats); + pool->m_DedicatedAllocations.AddPoolStats(pPoolStats); } void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) { m_CurrentFrameIndex.store(frameIndex); + +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + UpdateVulkanBudget(); + } +#endif // #if VMA_MEMORY_BUDGET } -void VmaAllocator_T::MakePoolAllocationsLost( - VmaPool hPool, - size_t* pLostAllocationCount) +VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool) { - hPool->m_BlockVector.MakePoolAllocationsLost( - m_CurrentFrameIndex.load(), - pLostAllocationCount); + return hPool->m_BlockVector.CheckCorruption(); } -void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation) +VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) { - *pAllocation = vma_new(this, VmaAllocation_T)(VMA_FRAME_INDEX_LOST, false); - (*pAllocation)->InitLost(); + VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT; + + // Process default pools. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; + if(pBlockVector != VMA_NULL) + { + VkResult localRes = pBlockVector->CheckCorruption(); + switch(localRes) + { + case VK_ERROR_FEATURE_NOT_PRESENT: + break; + case VK_SUCCESS: + finalRes = VK_SUCCESS; + break; + default: + return localRes; + } + } + } + + // Process custom pools. + { + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { + if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) + { + VkResult localRes = pool->m_BlockVector.CheckCorruption(); + switch(localRes) + { + case VK_ERROR_FEATURE_NOT_PRESENT: + break; + case VK_SUCCESS: + finalRes = VK_SUCCESS; + break; + default: + return localRes; + } + } + } + } + + return finalRes; } VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory) { + AtomicTransactionalIncrement deviceMemoryCountIncrement; + const uint64_t prevDeviceMemoryCount = deviceMemoryCountIncrement.Increment(&m_DeviceMemoryCount); +#if VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT + if(prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount) + { + return VK_ERROR_TOO_MANY_OBJECTS; + } +#endif + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex); - VkResult res; - if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE) + // HeapSizeLimit is in effect for this heap. + if((m_HeapSizeLimitMask & (1u << heapIndex)) != 0) { - VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex); - if(m_HeapSizeLimit[heapIndex] >= pAllocateInfo->allocationSize) + const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size; + VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex]; + for(;;) { - res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory); - if(res == VK_SUCCESS) + const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize; + if(blockBytesAfterAllocation > heapSize) { - m_HeapSizeLimit[heapIndex] -= pAllocateInfo->allocationSize; + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation)) + { + break; } - } - else - { - res = VK_ERROR_OUT_OF_DEVICE_MEMORY; } } else { - res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory); + m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize; } - if(res == VK_SUCCESS && m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL) + // VULKAN CALL vkAllocateMemory. + VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory); + + if(res == VK_SUCCESS) { - (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize); +#if VMA_MEMORY_BUDGET + ++m_Budget.m_OperationsSinceBudgetFetch; +#endif + + // Informative callback. + if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL) + { + (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize, m_DeviceMemoryCallbacks.pUserData); + } + + deviceMemoryCountIncrement.Commit(); + } + else + { + m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize; } return res; @@ -7588,35 +15712,91 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory) { + // Informative callback. if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL) { - (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size); + (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size, m_DeviceMemoryCallbacks.pUserData); } + // VULKAN CALL vkFreeMemory. (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks()); - const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType); - if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE) + m_Budget.m_BlockBytes[MemoryTypeIndexToHeapIndex(memoryType)] -= size; + + --m_DeviceMemoryCount; +} + +VkResult VmaAllocator_T::BindVulkanBuffer( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkBuffer buffer, + const void* pNext) +{ + if(pNext != VMA_NULL) { - VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex); - m_HeapSizeLimit[heapIndex] += size; +#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL) + { + VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR }; + bindBufferMemoryInfo.pNext = pNext; + bindBufferMemoryInfo.buffer = buffer; + bindBufferMemoryInfo.memory = memory; + bindBufferMemoryInfo.memoryOffset = memoryOffset; + return (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo); + } + else +#endif // #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + else + { + return (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset); + } +} + +VkResult VmaAllocator_T::BindVulkanImage( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkImage image, + const void* pNext) +{ + if(pNext != VMA_NULL) + { +#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL) + { + VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR }; + bindBufferMemoryInfo.pNext = pNext; + bindBufferMemoryInfo.image = image; + bindBufferMemoryInfo.memory = memory; + bindBufferMemoryInfo.memoryOffset = memoryOffset; + return (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo); + } + else +#endif // #if VMA_BIND_MEMORY2 + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + else + { + return (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset); } } VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData) { - if(hAllocation->CanBecomeLost()) - { - return VK_ERROR_MEMORY_MAP_FAILED; - } - switch(hAllocation->GetType()) { case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: { VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); - char *pBytes = nullptr; - VkResult res = pBlock->Map(this, (void**)&pBytes); + char *pBytes = VMA_NULL; + VkResult res = pBlock->Map(this, 1, (void**)&pBytes); if(res == VK_SUCCESS) { *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset(); @@ -7640,7 +15820,7 @@ void VmaAllocator_T::Unmap(VmaAllocation hAllocation) { VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); hAllocation->BlockAllocUnmap(); - pBlock->Unmap(this); + pBlock->Unmap(this, 1); } break; case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: @@ -7651,42 +15831,346 @@ void VmaAllocator_T::Unmap(VmaAllocation hAllocation) } } -void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation) +VkResult VmaAllocator_T::BindBufferMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext) +{ + VkResult res = VK_SUCCESS; + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext); + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block."); + res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext); + break; + } + default: + VMA_ASSERT(0); + } + return res; +} + +VkResult VmaAllocator_T::BindImageMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext) +{ + VkResult res = VK_SUCCESS; + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext); + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock(); + VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block."); + res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext); + break; + } + default: + VMA_ASSERT(0); + } + return res; +} + +VkResult VmaAllocator_T::FlushOrInvalidateAllocation( + VmaAllocation hAllocation, + VkDeviceSize offset, VkDeviceSize size, + VMA_CACHE_OPERATION op) +{ + VkResult res = VK_SUCCESS; + + VkMappedMemoryRange memRange = {}; + if(GetFlushOrInvalidateRange(hAllocation, offset, size, memRange)) + { + switch(op) + { + case VMA_CACHE_FLUSH: + res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange); + break; + case VMA_CACHE_INVALIDATE: + res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange); + break; + default: + VMA_ASSERT(0); + } + } + // else: Just ignore this call. + return res; +} + +VkResult VmaAllocator_T::FlushOrInvalidateAllocations( + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, const VkDeviceSize* sizes, + VMA_CACHE_OPERATION op) +{ + typedef VmaStlAllocator RangeAllocator; + typedef VmaSmallVector RangeVector; + RangeVector ranges = RangeVector(RangeAllocator(GetAllocationCallbacks())); + + for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + const VmaAllocation alloc = allocations[allocIndex]; + const VkDeviceSize offset = offsets != VMA_NULL ? offsets[allocIndex] : 0; + const VkDeviceSize size = sizes != VMA_NULL ? sizes[allocIndex] : VK_WHOLE_SIZE; + VkMappedMemoryRange newRange; + if(GetFlushOrInvalidateRange(alloc, offset, size, newRange)) + { + ranges.push_back(newRange); + } + } + + VkResult res = VK_SUCCESS; + if(!ranges.empty()) + { + switch(op) + { + case VMA_CACHE_FLUSH: + res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data()); + break; + case VMA_CACHE_INVALIDATE: + res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data()); + break; + default: + VMA_ASSERT(0); + } + } + // else: Just ignore this call. + return res; +} + +void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation) { VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + VmaPool parentPool = allocation->GetParentPool(); + if(parentPool == VK_NULL_HANDLE) { - VmaMutexLock lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex); - AllocationVectorType* const pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex]; - VMA_ASSERT(pDedicatedAllocations); - bool success = VmaVectorRemoveSorted(*pDedicatedAllocations, allocation); - VMA_ASSERT(success); + // Default pool + m_DedicatedAllocations[memTypeIndex].Unregister(allocation); + } + else + { + // Custom pool + parentPool->m_DedicatedAllocations.Unregister(allocation); } VkDeviceMemory hMemory = allocation->GetMemory(); - + + /* + There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory + before vkFreeMemory. + if(allocation->GetMappedData() != VMA_NULL) { (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory); } - + */ + FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory); VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex); } -#if VMA_STATS_STRING_ENABLED +uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const +{ + VkBufferCreateInfo dummyBufCreateInfo; + VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo); + uint32_t memoryTypeBits = 0; + + // Create buffer. + VkBuffer buf = VK_NULL_HANDLE; + VkResult res = (*GetVulkanFunctions().vkCreateBuffer)( + m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf); + if(res == VK_SUCCESS) + { + // Query for supported memory types. + VkMemoryRequirements memReq; + (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq); + memoryTypeBits = memReq.memoryTypeBits; + + // Destroy buffer. + (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks()); + } + + return memoryTypeBits; +} + +uint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits() const +{ + // Make sure memory information is already fetched. + VMA_ASSERT(GetMemoryTypeCount() > 0); + + uint32_t memoryTypeBits = UINT32_MAX; + + if(!m_UseAmdDeviceCoherentMemory) + { + // Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0) + { + memoryTypeBits &= ~(1u << memTypeIndex); + } + } + } + + return memoryTypeBits; +} + +bool VmaAllocator_T::GetFlushOrInvalidateRange( + VmaAllocation allocation, + VkDeviceSize offset, VkDeviceSize size, + VkMappedMemoryRange& outRange) const +{ + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex)) + { + const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize; + const VkDeviceSize allocationSize = allocation->GetSize(); + VMA_ASSERT(offset <= allocationSize); + + outRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + outRange.pNext = VMA_NULL; + outRange.memory = allocation->GetMemory(); + + switch(allocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); + if(size == VK_WHOLE_SIZE) + { + outRange.size = allocationSize - outRange.offset; + } + else + { + VMA_ASSERT(offset + size <= allocationSize); + outRange.size = VMA_MIN( + VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize), + allocationSize - outRange.offset); + } + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + // 1. Still within this allocation. + outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); + if(size == VK_WHOLE_SIZE) + { + size = allocationSize - offset; + } + else + { + VMA_ASSERT(offset + size <= allocationSize); + } + outRange.size = VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize); + + // 2. Adjust to whole block. + const VkDeviceSize allocationOffset = allocation->GetOffset(); + VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0); + const VkDeviceSize blockSize = allocation->GetBlock()->m_pMetadata->GetSize(); + outRange.offset += allocationOffset; + outRange.size = VMA_MIN(outRange.size, blockSize - outRange.offset); + + break; + } + default: + VMA_ASSERT(0); + } + return true; + } + return false; +} + +#if VMA_MEMORY_BUDGET +void VmaAllocator_T::UpdateVulkanBudget() +{ + VMA_ASSERT(m_UseExtMemoryBudget); + + VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR }; + + VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT }; + VmaPnextChainPushFront(&memProps, &budgetProps); + + GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &memProps); + + { + VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex); + + for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) + { + m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex]; + m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex]; + m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load(); + + // Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size. + if(m_Budget.m_VulkanBudget[heapIndex] == 0) + { + m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics. + } + else if(m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size) + { + m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size; + } + if(m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0) + { + m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; + } + } + m_Budget.m_OperationsSinceBudgetFetch = 0; + } +} +#endif // VMA_MEMORY_BUDGET + +void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern) +{ + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS && + (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) + { + void* pData = VMA_NULL; + VkResult res = Map(hAllocation, &pData); + if(res == VK_SUCCESS) + { + memset(pData, (int)pattern, (size_t)hAllocation->GetSize()); + FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH); + Unmap(hAllocation); + } + else + { + VMA_ASSERT(0 && "VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation."); + } + } +} + +uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits() +{ + uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load(); + if(memoryTypeBits == UINT32_MAX) + { + memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits(); + m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits); + } + return memoryTypeBits; +} + +#if VMA_STATS_STRING_ENABLED void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) { bool dedicatedAllocationsStarted = false; for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - VmaMutexLock dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex); - AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex]; - VMA_ASSERT(pDedicatedAllocVector); - if(pDedicatedAllocVector->empty() == false) + VmaDedicatedAllocationList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex]; + if(!dedicatedAllocList.IsEmpty()) { if(dedicatedAllocationsStarted == false) { @@ -7698,40 +16182,8 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) json.BeginString("Type "); json.ContinueString(memTypeIndex); json.EndString(); - - json.BeginArray(); - for(size_t i = 0; i < pDedicatedAllocVector->size(); ++i) - { - const VmaAllocation hAlloc = (*pDedicatedAllocVector)[i]; - json.BeginObject(true); - - json.WriteString("Type"); - json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[hAlloc->GetSuballocationType()]); - - json.WriteString("Size"); - json.WriteNumber(hAlloc->GetSize()); - - const void* pUserData = hAlloc->GetUserData(); - if(pUserData != VMA_NULL) - { - json.WriteString("UserData"); - if(hAlloc->IsUserDataString()) - { - json.WriteString((const char*)pUserData); - } - else - { - json.BeginString(); - json.ContinueString_Pointer(pUserData); - json.EndString(); - } - } - - json.EndObject(); - } - - json.EndArray(); + dedicatedAllocList.BuildStatsString(json); } } if(dedicatedAllocationsStarted) @@ -7743,20 +16195,26 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) bool allocationsStarted = false; for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) { - if(m_pBlockVectors[memTypeIndex]->IsEmpty() == false) + VmaBlockVector* pBlockVector = m_pBlockVectors[memTypeIndex]; + if(pBlockVector != VMA_NULL) { - if(allocationsStarted == false) + if (pBlockVector->IsEmpty() == false) { - allocationsStarted = true; - json.WriteString("DefaultPools"); + if (allocationsStarted == false) + { + allocationsStarted = true; + json.WriteString("DefaultPools"); + json.BeginObject(); + } + + json.BeginString("Type "); + json.ContinueString(memTypeIndex); + json.EndString(); + json.BeginObject(); + pBlockVector->PrintDetailedMap(json); + json.EndObject(); } - - json.BeginString("Type "); - json.ContinueString(memTypeIndex); - json.EndString(); - - m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json); } } if(allocationsStarted) @@ -7765,75 +16223,76 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) } } + // Custom pools { - VmaMutexLock lock(m_PoolsMutex, m_UseMutex); - const size_t poolCount = m_Pools.size(); - if(poolCount > 0) + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + if(!m_Pools.IsEmpty()) { json.WriteString("Pools"); - json.BeginArray(); - for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex) + json.BeginObject(); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) { - m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json); + json.BeginString(); + json.ContinueString(pool->GetId()); + json.EndString(); + + json.BeginObject(); + pool->m_BlockVector.PrintDetailedMap(json); + + if (!pool->m_DedicatedAllocations.IsEmpty()) + { + json.WriteString("DedicatedAllocations"); + pool->m_DedicatedAllocations.BuildStatsString(json); + } + json.EndObject(); } - json.EndArray(); + json.EndObject(); } } } +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_ALLOCATOR_T_FUNCTIONS -#endif // #if VMA_STATS_STRING_ENABLED -static VkResult AllocateMemoryForImage( - VmaAllocator allocator, - VkImage image, - const VmaAllocationCreateInfo* pAllocationCreateInfo, - VmaSuballocationType suballocType, - VmaAllocation* pAllocation) -{ - VMA_ASSERT(allocator && (image != VK_NULL_HANDLE) && pAllocationCreateInfo && pAllocation); - - VkMemoryRequirements vkMemReq = {}; - bool requiresDedicatedAllocation = false; - bool prefersDedicatedAllocation = false; - allocator->GetImageMemoryRequirements(image, vkMemReq, - requiresDedicatedAllocation, prefersDedicatedAllocation); - - return allocator->AllocateMemory( - vkMemReq, - requiresDedicatedAllocation, - prefersDedicatedAllocation, - VK_NULL_HANDLE, // dedicatedBuffer - image, // dedicatedImage - *pAllocationCreateInfo, - suballocType, - pAllocation); -} - -//////////////////////////////////////////////////////////////////////////////// -// Public interface - -VkResult vmaCreateAllocator( +#ifndef _VMA_PUBLIC_INTERFACE +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( const VmaAllocatorCreateInfo* pCreateInfo, VmaAllocator* pAllocator) { VMA_ASSERT(pCreateInfo && pAllocator); + VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 || + (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 2)); VMA_DEBUG_LOG("vmaCreateAllocator"); *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo); - return VK_SUCCESS; + VkResult result = (*pAllocator)->Init(pCreateInfo); + if(result < 0) + { + vma_delete(pCreateInfo->pAllocationCallbacks, *pAllocator); + *pAllocator = VK_NULL_HANDLE; + } + return result; } -void vmaDestroyAllocator( +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( VmaAllocator allocator) { if(allocator != VK_NULL_HANDLE) { VMA_DEBUG_LOG("vmaDestroyAllocator"); - VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; + VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; // Have to copy the callbacks when destroying. vma_delete(&allocationCallbacks, allocator); } } -void vmaGetPhysicalDeviceProperties( +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo* pAllocatorInfo) +{ + VMA_ASSERT(allocator && pAllocatorInfo); + pAllocatorInfo->instance = allocator->m_hInstance; + pAllocatorInfo->physicalDevice = allocator->GetPhysicalDevice(); + pAllocatorInfo->device = allocator->m_hDevice; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( VmaAllocator allocator, const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties) { @@ -7841,7 +16300,7 @@ void vmaGetPhysicalDeviceProperties( *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties; } -void vmaGetMemoryProperties( +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( VmaAllocator allocator, const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties) { @@ -7849,7 +16308,7 @@ void vmaGetMemoryProperties( *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps; } -void vmaGetMemoryTypeProperties( +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( VmaAllocator allocator, uint32_t memoryTypeIndex, VkMemoryPropertyFlags* pFlags) @@ -7859,19 +16318,18 @@ void vmaGetMemoryTypeProperties( *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags; } -void vmaSetCurrentFrameIndex( +VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( VmaAllocator allocator, uint32_t frameIndex) { VMA_ASSERT(allocator); - VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST); VMA_DEBUG_GLOBAL_MUTEX_LOCK allocator->SetCurrentFrameIndex(frameIndex); } -void vmaCalculateStats( +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats( VmaAllocator allocator, VmaStats* pStats) { @@ -7880,9 +16338,18 @@ void vmaCalculateStats( allocator->CalculateStats(pStats); } +VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( + VmaAllocator allocator, + VmaBudget* pBudgets) +{ + VMA_ASSERT(allocator && pBudgets); + VMA_DEBUG_GLOBAL_MUTEX_LOCK + allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount()); +} + #if VMA_STATS_STRING_ENABLED -void vmaBuildStatsString( +VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( VmaAllocator allocator, char** ppStatsString, VkBool32 detailedMap) @@ -7890,17 +16357,20 @@ void vmaBuildStatsString( VMA_ASSERT(allocator && ppStatsString); VMA_DEBUG_GLOBAL_MUTEX_LOCK - VmaStringBuilder sb(allocator); + VmaStringBuilder sb(allocator->GetAllocationCallbacks()); { VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb); json.BeginObject(); + VmaBudget budgets[VK_MAX_MEMORY_HEAPS]; + allocator->GetHeapBudgets(budgets, 0, allocator->GetMemoryHeapCount()); + VmaStats stats; allocator->CalculateStats(&stats); json.WriteString("Total"); VmaPrintStatInfo(json, stats.total); - + for(uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex) { json.BeginString("Heap "); @@ -7919,6 +16389,20 @@ void vmaBuildStatsString( } json.EndArray(); + json.WriteString("Budget"); + json.BeginObject(); + { + json.WriteString("BlockBytes"); + json.WriteNumber(budgets[heapIndex].blockBytes); + json.WriteString("AllocationBytes"); + json.WriteNumber(budgets[heapIndex].allocationBytes); + json.WriteString("Usage"); + json.WriteNumber(budgets[heapIndex].usage); + json.WriteString("Budget"); + json.WriteNumber(budgets[heapIndex].budget); + } + json.EndObject(); + if(stats.memoryHeap[heapIndex].blockCount > 0) { json.WriteString("Stats"); @@ -7958,6 +16442,22 @@ void vmaBuildStatsString( { json.WriteString("LAZILY_ALLOCATED"); } +#if VMA_VULKAN_VERSION >= 1001000 + if((flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0) + { + json.WriteString("PROTECTED"); + } +#endif // #if VMA_VULKAN_VERSION >= 1001000 +#if VK_AMD_device_coherent_memory + if((flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0) + { + json.WriteString("DEVICE_COHERENT"); + } + if((flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) != 0) + { + json.WriteString("DEVICE_UNCACHED"); + } +#endif // #if VK_AMD_device_coherent_memory json.EndArray(); if(stats.memoryType[typeIndex].blockCount > 0) @@ -7980,34 +16480,26 @@ void vmaBuildStatsString( json.EndObject(); } - const size_t len = sb.GetLength(); - char* const pChars = vma_new_array(allocator, char, len + 1); - if(len > 0) - { - memcpy(pChars, sb.GetData(), len); - } - pChars[len] = '\0'; - *ppStatsString = pChars; + *ppStatsString = VmaCreateStringCopy(allocator->GetAllocationCallbacks(), sb.GetData(), sb.GetLength()); } -void vmaFreeStatsString( +VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( VmaAllocator allocator, char* pStatsString) { if(pStatsString != VMA_NULL) { VMA_ASSERT(allocator); - size_t len = strlen(pStatsString); - vma_delete_array(allocator, pStatsString, len + 1); + VmaFreeString(allocator->GetAllocationCallbacks(), pStatsString); } } -#endif // #if VMA_STATS_STRING_ENABLED +#endif // VMA_STATS_STRING_ENABLED /* This function is not protected by any mutex because it just reads immutable data. */ -VkResult vmaFindMemoryTypeIndex( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( VmaAllocator allocator, uint32_t memoryTypeBits, const VmaAllocationCreateInfo* pAllocationCreateInfo, @@ -8017,13 +16509,16 @@ VkResult vmaFindMemoryTypeIndex( VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + memoryTypeBits &= allocator->GetGlobalMemoryTypeBits(); + if(pAllocationCreateInfo->memoryTypeBits != 0) { memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits; } - + uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags; uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags; + uint32_t notPreferredFlags = 0; // Convert usage to requiredFlags and preferredFlags. switch(pAllocationCreateInfo->usage) @@ -8031,23 +16526,43 @@ VkResult vmaFindMemoryTypeIndex( case VMA_MEMORY_USAGE_UNKNOWN: break; case VMA_MEMORY_USAGE_GPU_ONLY: - preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } break; case VMA_MEMORY_USAGE_CPU_ONLY: requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; break; case VMA_MEMORY_USAGE_CPU_TO_GPU: requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } break; case VMA_MEMORY_USAGE_GPU_TO_CPU: requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - preferredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + break; + case VMA_MEMORY_USAGE_CPU_COPY: + notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED: + requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; break; default: + VMA_ASSERT(0); break; } + // Avoid DEVICE_COHERENT unless explicitly requested. + if(((pAllocationCreateInfo->requiredFlags | pAllocationCreateInfo->preferredFlags) & + (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0) + { + notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY; + } + *pMemoryTypeIndex = UINT32_MAX; uint32_t minCost = UINT32_MAX; for(uint32_t memTypeIndex = 0, memTypeBit = 1; @@ -8063,7 +16578,8 @@ VkResult vmaFindMemoryTypeIndex( if((requiredFlags & ~currFlags) == 0) { // Calculate cost as number of bits from preferredFlags not present in this memory type. - uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags); + uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags) + + VmaCountBitsSet(currFlags & notPreferredFlags); // Remember memory type with lowest cost. if(currCost < minCost) { @@ -8080,10 +16596,78 @@ VkResult vmaFindMemoryTypeIndex( return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT; } -VkResult vmaCreatePool( - VmaAllocator allocator, - const VmaPoolCreateInfo* pCreateInfo, - VmaPool* pPool) +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( + VmaAllocator allocator, + const VkBufferCreateInfo* pBufferCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + uint32_t* pMemoryTypeIndex) +{ + VMA_ASSERT(allocator != VK_NULL_HANDLE); + VMA_ASSERT(pBufferCreateInfo != VMA_NULL); + VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); + VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + + const VkDevice hDev = allocator->m_hDevice; + VkBuffer hBuffer = VK_NULL_HANDLE; + const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions(); + VkResult res = funcs->vkCreateBuffer( + hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer); + if(res == VK_SUCCESS) + { + VkMemoryRequirements memReq = {}; + funcs->vkGetBufferMemoryRequirements( + hDev, hBuffer, &memReq); + + res = vmaFindMemoryTypeIndex( + allocator, + memReq.memoryTypeBits, + pAllocationCreateInfo, + pMemoryTypeIndex); + + funcs->vkDestroyBuffer( + hDev, hBuffer, allocator->GetAllocationCallbacks()); + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( + VmaAllocator allocator, + const VkImageCreateInfo* pImageCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + uint32_t* pMemoryTypeIndex) +{ + VMA_ASSERT(allocator != VK_NULL_HANDLE); + VMA_ASSERT(pImageCreateInfo != VMA_NULL); + VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); + VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + + const VkDevice hDev = allocator->m_hDevice; + VkImage hImage = VK_NULL_HANDLE; + const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions(); + VkResult res = funcs->vkCreateImage( + hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage); + if(res == VK_SUCCESS) + { + VkMemoryRequirements memReq = {}; + funcs->vkGetImageMemoryRequirements( + hDev, hImage, &memReq); + + res = vmaFindMemoryTypeIndex( + allocator, + memReq.memoryTypeBits, + pAllocationCreateInfo, + pMemoryTypeIndex); + + funcs->vkDestroyImage( + hDev, hImage, allocator->GetAllocationCallbacks()); + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( + VmaAllocator allocator, + const VmaPoolCreateInfo* pCreateInfo, + VmaPool* pPool) { VMA_ASSERT(allocator && pCreateInfo && pPool); @@ -8094,7 +16678,7 @@ VkResult vmaCreatePool( return allocator->CreatePool(pCreateInfo, pPool); } -void vmaDestroyPool( +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( VmaAllocator allocator, VmaPool pool) { @@ -8112,7 +16696,7 @@ void vmaDestroyPool( allocator->DestroyPool(pool); } -void vmaGetPoolStats( +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats( VmaAllocator allocator, VmaPool pool, VmaPoolStats* pPoolStats) @@ -8124,19 +16708,46 @@ void vmaGetPoolStats( allocator->GetPoolStats(pool, pPoolStats); } -void vmaMakePoolAllocationsLost( - VmaAllocator allocator, - VmaPool pool, - size_t* pLostAllocationCount) +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool) { VMA_ASSERT(allocator && pool); VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->MakePoolAllocationsLost(pool, pLostAllocationCount); + VMA_DEBUG_LOG("vmaCheckPoolCorruption"); + + return allocator->CheckPoolCorruption(pool); } -VkResult vmaAllocateMemory( +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( + VmaAllocator allocator, + VmaPool pool, + const char** ppName) +{ + VMA_ASSERT(allocator && pool && ppName); + + VMA_DEBUG_LOG("vmaGetPoolName"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *ppName = pool->GetName(); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( + VmaAllocator allocator, + VmaPool pool, + const char* pName) +{ + VMA_ASSERT(allocator && pool); + + VMA_DEBUG_LOG("vmaSetPoolName"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + pool->SetName(pName); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( VmaAllocator allocator, const VkMemoryRequirements* pVkMemoryRequirements, const VmaAllocationCreateInfo* pCreateInfo, @@ -8149,25 +16760,69 @@ VkResult vmaAllocateMemory( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkResult result = allocator->AllocateMemory( + VkResult result = allocator->AllocateMemory( *pVkMemoryRequirements, false, // requiresDedicatedAllocation false, // prefersDedicatedAllocation VK_NULL_HANDLE, // dedicatedBuffer + UINT32_MAX, // dedicatedBufferUsage VK_NULL_HANDLE, // dedicatedImage *pCreateInfo, VMA_SUBALLOCATION_TYPE_UNKNOWN, + 1, // allocationCount pAllocation); - if(pAllocationInfo && result == VK_SUCCESS) + if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } - return result; + return result; } -VkResult vmaAllocateMemoryForBuffer( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( + VmaAllocator allocator, + const VkMemoryRequirements* pVkMemoryRequirements, + const VmaAllocationCreateInfo* pCreateInfo, + size_t allocationCount, + VmaAllocation* pAllocations, + VmaAllocationInfo* pAllocationInfo) +{ + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations); + + VMA_DEBUG_LOG("vmaAllocateMemoryPages"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VkResult result = allocator->AllocateMemory( + *pVkMemoryRequirements, + false, // requiresDedicatedAllocation + false, // prefersDedicatedAllocation + VK_NULL_HANDLE, // dedicatedBuffer + UINT32_MAX, // dedicatedBufferUsage + VK_NULL_HANDLE, // dedicatedImage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_UNKNOWN, + allocationCount, + pAllocations); + + if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) + { + for(size_t i = 0; i < allocationCount; ++i) + { + allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i); + } + } + + return result; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( VmaAllocator allocator, VkBuffer buffer, const VmaAllocationCreateInfo* pCreateInfo, @@ -8192,9 +16847,11 @@ VkResult vmaAllocateMemoryForBuffer( requiresDedicatedAllocation, prefersDedicatedAllocation, buffer, // dedicatedBuffer + UINT32_MAX, // dedicatedBufferUsage VK_NULL_HANDLE, // dedicatedImage *pCreateInfo, VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount pAllocation); if(pAllocationInfo && result == VK_SUCCESS) @@ -8202,10 +16859,10 @@ VkResult vmaAllocateMemoryForBuffer( allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } - return result; + return result; } -VkResult vmaAllocateMemoryForImage( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( VmaAllocator allocator, VkImage image, const VmaAllocationCreateInfo* pCreateInfo, @@ -8218,11 +16875,22 @@ VkResult vmaAllocateMemoryForImage( VMA_DEBUG_GLOBAL_MUTEX_LOCK - VkResult result = AllocateMemoryForImage( - allocator, - image, - pCreateInfo, + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetImageMemoryRequirements(image, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + VkResult result = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + VK_NULL_HANDLE, // dedicatedBuffer + UINT32_MAX, // dedicatedBufferUsage + image, // dedicatedImage + *pCreateInfo, VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN, + 1, // allocationCount pAllocation); if(pAllocationInfo && result == VK_SUCCESS) @@ -8230,23 +16898,49 @@ VkResult vmaAllocateMemoryForImage( allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } - return result; + return result; } -void vmaFreeMemory( +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( VmaAllocator allocator, VmaAllocation allocation) { - VMA_ASSERT(allocator && allocation); + VMA_ASSERT(allocator); + + if(allocation == VK_NULL_HANDLE) + { + return; + } VMA_DEBUG_LOG("vmaFreeMemory"); VMA_DEBUG_GLOBAL_MUTEX_LOCK - allocator->FreeMemory(allocation); + allocator->FreeMemory( + 1, // allocationCount + &allocation); } -void vmaGetAllocationInfo( +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( + VmaAllocator allocator, + size_t allocationCount, + const VmaAllocation* pAllocations) +{ + if(allocationCount == 0) + { + return; + } + + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaFreeMemoryPages"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->FreeMemory(allocationCount, pAllocations); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo* pAllocationInfo) @@ -8258,7 +16952,7 @@ void vmaGetAllocationInfo( allocator->GetAllocationInfo(allocation, pAllocationInfo); } -void vmaSetAllocationUserData( +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( VmaAllocator allocator, VmaAllocation allocation, void* pUserData) @@ -8270,18 +16964,17 @@ void vmaSetAllocationUserData( allocation->SetUserData(allocator, pUserData); } -void vmaCreateLostAllocation( - VmaAllocator allocator, - VmaAllocation* pAllocation) +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags) { - VMA_ASSERT(allocator && pAllocation); - - VMA_DEBUG_GLOBAL_MUTEX_LOCK; - - allocator->CreateLostAllocation(pAllocation); + VMA_ASSERT(allocator && allocation && pFlags); + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + *pFlags = allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags; } -VkResult vmaMapMemory( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( VmaAllocator allocator, VmaAllocation allocation, void** ppData) @@ -8293,7 +16986,7 @@ VkResult vmaMapMemory( return allocator->Map(allocation, ppData); } -void vmaUnmapMemory( +VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( VmaAllocator allocator, VmaAllocation allocation) { @@ -8304,24 +16997,282 @@ void vmaUnmapMemory( allocator->Unmap(allocation); } -VkResult vmaDefragment( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( VmaAllocator allocator, - VmaAllocation* pAllocations, + VmaAllocation allocation, + VkDeviceSize offset, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_LOG("vmaFlushAllocation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH); + + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize offset, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_LOG("vmaInvalidateAllocation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE); + + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( + VmaAllocator allocator, + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, + const VkDeviceSize* sizes) +{ + VMA_ASSERT(allocator); + + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocations); + + VMA_DEBUG_LOG("vmaFlushAllocations"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH); + + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( + VmaAllocator allocator, + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, + const VkDeviceSize* sizes) +{ + VMA_ASSERT(allocator); + + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocations); + + VMA_DEBUG_LOG("vmaInvalidateAllocations"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE); + + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( + VmaAllocator allocator, + uint32_t memoryTypeBits) +{ + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaCheckCorruption"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->CheckCorruption(memoryTypeBits); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment( + VmaAllocator allocator, + const VmaAllocation* pAllocations, size_t allocationCount, VkBool32* pAllocationsChanged, const VmaDefragmentationInfo *pDefragmentationInfo, VmaDefragmentationStats* pDefragmentationStats) { - VMA_ASSERT(allocator && pAllocations); + // Deprecated interface, reimplemented using new one. - VMA_DEBUG_LOG("vmaDefragment"); + VmaDefragmentationInfo2 info2 = {}; + info2.allocationCount = (uint32_t)allocationCount; + info2.pAllocations = pAllocations; + info2.pAllocationsChanged = pAllocationsChanged; + if(pDefragmentationInfo != VMA_NULL) + { + info2.maxCpuAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove; + info2.maxCpuBytesToMove = pDefragmentationInfo->maxBytesToMove; + } + else + { + info2.maxCpuAllocationsToMove = UINT32_MAX; + info2.maxCpuBytesToMove = VK_WHOLE_SIZE; + } + // info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero. + + VmaDefragmentationContext ctx; + VkResult res = vmaDefragmentationBegin(allocator, &info2, pDefragmentationStats, &ctx); + if(res == VK_NOT_READY) + { + res = vmaDefragmentationEnd( allocator, ctx); + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin( + VmaAllocator allocator, + const VmaDefragmentationInfo2* pInfo, + VmaDefragmentationStats* pStats, + VmaDefragmentationContext *pContext) +{ + VMA_ASSERT(allocator && pInfo && pContext); + + // Degenerate case: Nothing to defragment. + if(pInfo->allocationCount == 0 && pInfo->poolCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(pInfo->allocationCount == 0 || pInfo->pAllocations != VMA_NULL); + VMA_ASSERT(pInfo->poolCount == 0 || pInfo->pPools != VMA_NULL); + VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->allocationCount, pInfo->pAllocations)); + VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->poolCount, pInfo->pPools)); + + VMA_DEBUG_LOG("vmaDefragmentationBegin"); VMA_DEBUG_GLOBAL_MUTEX_LOCK - return allocator->Defragment(pAllocations, allocationCount, pAllocationsChanged, pDefragmentationInfo, pDefragmentationStats); + VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext); + + return res; } -VkResult vmaCreateBuffer( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd( + VmaAllocator allocator, + VmaDefragmentationContext context) +{ + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaDefragmentationEnd"); + + if(context != VK_NULL_HANDLE) + { + VMA_DEBUG_GLOBAL_MUTEX_LOCK + return allocator->DefragmentationEnd(context); + } + else + { + return VK_SUCCESS; + } +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( + VmaAllocator allocator, + VmaDefragmentationContext context, + VmaDefragmentationPassInfo* pInfo + ) +{ + VMA_ASSERT(allocator); + VMA_ASSERT(pInfo); + + VMA_DEBUG_LOG("vmaBeginDefragmentationPass"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + if(context == VK_NULL_HANDLE) + { + pInfo->moveCount = 0; + return VK_SUCCESS; + } + + return allocator->DefragmentationPassBegin(pInfo, context); +} +VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( + VmaAllocator allocator, + VmaDefragmentationContext context) +{ + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaEndDefragmentationPass"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + if(context == VK_NULL_HANDLE) + return VK_SUCCESS; + + return allocator->DefragmentationPassEnd(context); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( + VmaAllocator allocator, + VmaAllocation allocation, + VkBuffer buffer) +{ + VMA_ASSERT(allocator && allocation && buffer); + + VMA_DEBUG_LOG("vmaBindBufferMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize allocationLocalOffset, + VkBuffer buffer, + const void* pNext) +{ + VMA_ASSERT(allocator && allocation && buffer); + + VMA_DEBUG_LOG("vmaBindBufferMemory2"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( + VmaAllocator allocator, + VmaAllocation allocation, + VkImage image) +{ + VMA_ASSERT(allocator && allocation && image); + + VMA_DEBUG_LOG("vmaBindImageMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindImageMemory(allocation, 0, image, VMA_NULL); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize allocationLocalOffset, + VkImage image, + const void* pNext) +{ + VMA_ASSERT(allocator && allocation && image); + + VMA_DEBUG_LOG("vmaBindImageMemory2"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindImageMemory(allocation, allocationLocalOffset, image, pNext); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( VmaAllocator allocator, const VkBufferCreateInfo* pBufferCreateInfo, const VmaAllocationCreateInfo* pAllocationCreateInfo, @@ -8330,9 +17281,20 @@ VkResult vmaCreateBuffer( VmaAllocationInfo* pAllocationInfo) { VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation); - + + if(pBufferCreateInfo->size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + !allocator->m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); + return VK_ERROR_INITIALIZATION_FAILED; + } + VMA_DEBUG_LOG("vmaCreateBuffer"); - + VMA_DEBUG_GLOBAL_MUTEX_LOCK *pBuffer = VK_NULL_HANDLE; @@ -8353,52 +17315,42 @@ VkResult vmaCreateBuffer( allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation); - // Make sure alignment requirements for specific buffer usages reported - // in Physical Device Properties are included in alignment reported by memory requirements. - if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0) - { - VMA_ASSERT(vkMemReq.alignment % - allocator->m_PhysicalDeviceProperties.limits.minTexelBufferOffsetAlignment == 0); - } - if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0) - { - VMA_ASSERT(vkMemReq.alignment % - allocator->m_PhysicalDeviceProperties.limits.minUniformBufferOffsetAlignment == 0); - } - if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0) - { - VMA_ASSERT(vkMemReq.alignment % - allocator->m_PhysicalDeviceProperties.limits.minStorageBufferOffsetAlignment == 0); - } - // 3. Allocate memory using allocator. res = allocator->AllocateMemory( vkMemReq, requiresDedicatedAllocation, prefersDedicatedAllocation, *pBuffer, // dedicatedBuffer + pBufferCreateInfo->usage, // dedicatedBufferUsage VK_NULL_HANDLE, // dedicatedImage *pAllocationCreateInfo, VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount pAllocation); + if(res >= 0) { // 3. Bind buffer with memory. - res = (*allocator->GetVulkanFunctions().vkBindBufferMemory)( - allocator->m_hDevice, - *pBuffer, - (*pAllocation)->GetMemory(), - (*pAllocation)->GetOffset()); + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); + } if(res >= 0) { // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage); + #endif if(pAllocationInfo != VMA_NULL) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } + return VK_SUCCESS; } - allocator->FreeMemory(*pAllocation); + allocator->FreeMemory( + 1, // allocationCount + pAllocation); *pAllocation = VK_NULL_HANDLE; (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); *pBuffer = VK_NULL_HANDLE; @@ -8411,26 +17363,131 @@ VkResult vmaCreateBuffer( return res; } -void vmaDestroyBuffer( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( + VmaAllocator allocator, + const VkBufferCreateInfo* pBufferCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VkDeviceSize minAlignment, + VkBuffer* pBuffer, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && VmaIsPow2(minAlignment) && pBuffer && pAllocation); + + if(pBufferCreateInfo->size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + !allocator->m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_LOG("vmaCreateBufferWithAlignment"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *pBuffer = VK_NULL_HANDLE; + *pAllocation = VK_NULL_HANDLE; + + // 1. Create VkBuffer. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( + allocator->m_hDevice, + pBufferCreateInfo, + allocator->GetAllocationCallbacks(), + pBuffer); + if(res >= 0) + { + // 2. vkGetBufferMemoryRequirements. + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + // 2a. Include minAlignment + vkMemReq.alignment = VMA_MAX(vkMemReq.alignment, minAlignment); + + // 3. Allocate memory using allocator. + res = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + *pBuffer, // dedicatedBuffer + pBufferCreateInfo->usage, // dedicatedBufferUsage + VK_NULL_HANDLE, // dedicatedImage + *pAllocationCreateInfo, + VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount + pAllocation); + + if(res >= 0) + { + // 3. Bind buffer with memory. + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); + } + if(res >= 0) + { + // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage); + #endif + if(pAllocationInfo != VMA_NULL) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return VK_SUCCESS; + } + allocator->FreeMemory( + 1, // allocationCount + pAllocation); + *pAllocation = VK_NULL_HANDLE; + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + return res; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation) { + VMA_ASSERT(allocator); + + if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaDestroyBuffer"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + if(buffer != VK_NULL_HANDLE) { - VMA_ASSERT(allocator); - - VMA_DEBUG_LOG("vmaDestroyBuffer"); - - VMA_DEBUG_GLOBAL_MUTEX_LOCK - (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks()); - - allocator->FreeMemory(allocation); + } + + if(allocation != VK_NULL_HANDLE) + { + allocator->FreeMemory( + 1, // allocationCount + &allocation); } } -VkResult vmaCreateImage( +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( VmaAllocator allocator, const VkImageCreateInfo* pImageCreateInfo, const VmaAllocationCreateInfo* pAllocationCreateInfo, @@ -8440,6 +17497,15 @@ VkResult vmaCreateImage( { VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation); + if(pImageCreateInfo->extent.width == 0 || + pImageCreateInfo->extent.height == 0 || + pImageCreateInfo->extent.depth == 0 || + pImageCreateInfo->mipLevels == 0 || + pImageCreateInfo->arrayLayers == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + VMA_DEBUG_LOG("vmaCreateImage"); VMA_DEBUG_GLOBAL_MUTEX_LOCK @@ -8458,27 +17524,49 @@ VkResult vmaCreateImage( VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ? VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL : VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR; - + // 2. Allocate memory using allocator. - res = AllocateMemoryForImage(allocator, *pImage, pAllocationCreateInfo, suballocType, pAllocation); + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetImageMemoryRequirements(*pImage, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + res = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + VK_NULL_HANDLE, // dedicatedBuffer + UINT32_MAX, // dedicatedBufferUsage + *pImage, // dedicatedImage + *pAllocationCreateInfo, + suballocType, + 1, // allocationCount + pAllocation); + if(res >= 0) { // 3. Bind image with memory. - res = (*allocator->GetVulkanFunctions().vkBindImageMemory)( - allocator->m_hDevice, - *pImage, - (*pAllocation)->GetMemory(), - (*pAllocation)->GetOffset()); + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL); + } if(res >= 0) { // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferImageUsage(pImageCreateInfo->usage); + #endif if(pAllocationInfo != VMA_NULL) { allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); } + return VK_SUCCESS; } - allocator->FreeMemory(*pAllocation); + allocator->FreeMemory( + 1, // allocationCount + pAllocation); *pAllocation = VK_NULL_HANDLE; (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks()); *pImage = VK_NULL_HANDLE; @@ -8491,23 +17579,2088 @@ VkResult vmaCreateImage( return res; } -void vmaDestroyImage( +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( VmaAllocator allocator, VkImage image, VmaAllocation allocation) { + VMA_ASSERT(allocator); + + if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaDestroyImage"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + if(image != VK_NULL_HANDLE) { - VMA_ASSERT(allocator); - - VMA_DEBUG_LOG("vmaDestroyImage"); - - VMA_DEBUG_GLOBAL_MUTEX_LOCK - (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks()); - - allocator->FreeMemory(allocation); + } + if(allocation != VK_NULL_HANDLE) + { + allocator->FreeMemory( + 1, // allocationCount + &allocation); } } -#endif // #ifdef VMA_IMPLEMENTATION +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( + const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualBlock VMA_NULLABLE * VMA_NOT_NULL pVirtualBlock) +{ + VMA_ASSERT(pCreateInfo && pVirtualBlock); + VMA_ASSERT(pCreateInfo->size > 0); + VMA_DEBUG_LOG("vmaCreateVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + *pVirtualBlock = vma_new(pCreateInfo->pAllocationCallbacks, VmaVirtualBlock_T)(*pCreateInfo); + VkResult res = (*pVirtualBlock)->Init(); + if(res < 0) + { + vma_delete(pCreateInfo->pAllocationCallbacks, *pVirtualBlock); + *pVirtualBlock = VK_NULL_HANDLE; + } + return res; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(VmaVirtualBlock VMA_NULLABLE virtualBlock) +{ + if(virtualBlock != VK_NULL_HANDLE) + { + VMA_DEBUG_LOG("vmaDestroyVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + VkAllocationCallbacks allocationCallbacks = virtualBlock->m_AllocationCallbacks; // Have to copy the callbacks when destroying. + vma_delete(&allocationCallbacks, virtualBlock); + } +} + +VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(VmaVirtualBlock VMA_NOT_NULL virtualBlock) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaIsVirtualBlockEmpty"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + return virtualBlock->IsEmpty() ? VK_TRUE : VK_FALSE; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pVirtualAllocInfo != VMA_NULL); + VMA_DEBUG_LOG("vmaGetVirtualAllocationInfo"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->GetAllocationInfo(allocation, *pVirtualAllocInfo); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, VmaVirtualAllocation* VMA_NOT_NULL pAllocation, + VkDeviceSize* VMA_NULLABLE pOffset) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pCreateInfo != VMA_NULL && pAllocation != VMA_NULL); + VMA_DEBUG_LOG("vmaVirtualAllocate"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + return virtualBlock->Allocate(*pCreateInfo, *pAllocation, pOffset); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(VmaVirtualBlock VMA_NOT_NULL virtualBlock, VmaVirtualAllocation VMA_NULLABLE allocation) +{ + if(virtualBlock != VMA_NULL) + { + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaVirtualFree"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->Free(allocation); + } +} + +VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(VmaVirtualBlock VMA_NOT_NULL virtualBlock) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaClearVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->Clear(); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL allocation, void* VMA_NULLABLE pUserData) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaSetVirtualAllocationUserData"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->SetAllocationUserData(allocation, pUserData); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStats(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaStatInfo* VMA_NOT_NULL pStatInfo) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStatInfo != VMA_NULL); + VMA_DEBUG_LOG("vmaCalculateVirtualBlockStats"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->CalculateStats(*pStatInfo); +} + +#if VMA_STATS_STRING_ENABLED + +VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && ppStatsString != VMA_NULL); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + const VkAllocationCallbacks* allocationCallbacks = virtualBlock->GetAllocationCallbacks(); + VmaStringBuilder sb(allocationCallbacks); + virtualBlock->BuildStatsString(detailedMap != VK_FALSE, sb); + *ppStatsString = VmaCreateStringCopy(allocationCallbacks, sb.GetData(), sb.GetLength()); +} + +#endif // VMA_STATS_STRING_ENABLED + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE pStatsString) +{ + if(pStatsString != VMA_NULL) + { + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString); + } +} +#endif // _VMA_PUBLIC_INTERFACE +#endif // VMA_IMPLEMENTATION + +/** +\page quick_start Quick start + +\section quick_start_project_setup Project setup + +Vulkan Memory Allocator comes in form of a "stb-style" single header file. +You don't need to build it as a separate library project. +You can add this file directly to your project and submit it to code repository next to your other source files. + +"Single header" doesn't mean that everything is contained in C/C++ declarations, +like it tends to be in case of inline functions or C++ templates. +It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro. +If you don't do it properly, you will get linker errors. + +To do it properly: + +-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library. + This includes declarations of all members of the library. +-# In exactly one CPP file define following macro before this include. + It enables also internal definitions. + +\code +#define VMA_IMPLEMENTATION +#include "vk_mem_alloc.h" +\endcode + +It may be a good idea to create dedicated CPP file just for this purpose. + +Note on language: This library is written in C++, but has C-compatible interface. +Thus you can include and use vk_mem_alloc.h in C or C++ code, but full +implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C. + +Please note that this library includes header ``, which in turn +includes `` on Windows. If you need some specific macros defined +before including these headers (like `WIN32_LEAN_AND_MEAN` or +`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define +them before every `#include` of this library. + +You may need to configure the way you import Vulkan functions. + +- By default, VMA assumes you you link statically with Vulkan API. If this is not the case, + `#define VMA_STATIC_VULKAN_FUNCTIONS 0` before `#include` of the VMA implementation and use another way. +- You can `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1` and pass only pointers to `vkGetInstanceProcAddr` and + `vkGetDeviceProcAddr` functions through VmaAllocatorCreateInfo::pVulkanFunctions. + All the remaining Vulkan functions will be fetched automatically. +- Finally, you can provide your own pointers to all Vulkan functions needed by VMA using structure member + VmaAllocatorCreateInfo::pVulkanFunctions, if you fetched them in some custom way e.g. using some loader like [Volk](https://github.com/zeux/volk). + + +\section quick_start_initialization Initialization + +At program startup: + +-# Initialize Vulkan to have `VkPhysicalDevice`, `VkDevice` and `VkInstance` object. +-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by + calling vmaCreateAllocator(). + +\code +VmaAllocatorCreateInfo allocatorInfo = {}; +allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_2; +allocatorInfo.physicalDevice = physicalDevice; +allocatorInfo.device = device; +allocatorInfo.instance = instance; + +VmaAllocator allocator; +vmaCreateAllocator(&allocatorInfo, &allocator); +\endcode + +Only members `physicalDevice`, `device`, `instance` are required. +However, you should inform the library which Vulkan version do you use by setting +VmaAllocatorCreateInfo::vulkanApiVersion and which extensions did you enable +by setting VmaAllocatorCreateInfo::flags (like #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT for VK_KHR_buffer_device_address). +Otherwise, VMA would use only features of Vulkan 1.0 core with no extensions. + + +\section quick_start_resource_allocation Resource allocation + +When you want to create a buffer or image: + +-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure. +-# Fill VmaAllocationCreateInfo structure. +-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory + already allocated and bound to it. + +\code +VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufferInfo.size = 65536; +bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +Don't forget to destroy your objects when no longer needed: + +\code +vmaDestroyBuffer(allocator, buffer, allocation); +vmaDestroyAllocator(allocator); +\endcode + + +\page choosing_memory_type Choosing memory type + +Physical devices in Vulkan support various combinations of memory heaps and +types. Help with choosing correct and optimal memory type for your specific +resource is one of the key features of this library. You can use it by filling +appropriate members of VmaAllocationCreateInfo structure, as described below. +You can also combine multiple methods. + +-# If you just want to find memory type index that meets your requirements, you + can use function: vmaFindMemoryTypeIndex(), vmaFindMemoryTypeIndexForBufferInfo(), + vmaFindMemoryTypeIndexForImageInfo(). +-# If you want to allocate a region of device memory without association with any + specific image or buffer, you can use function vmaAllocateMemory(). Usage of + this function is not recommended and usually not needed. + vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once, + which may be useful for sparse binding. +-# If you already have a buffer or an image created, you want to allocate memory + for it and then you will bind it yourself, you can use function + vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(). + For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory() + or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2(). +-# If you want to create a buffer or an image, allocate memory for it and bind + them together, all in one call, you can use function vmaCreateBuffer(), + vmaCreateImage(). This is the easiest and recommended way to use this library. + +When using 3. or 4., the library internally queries Vulkan for memory types +supported for that buffer or image (function `vkGetBufferMemoryRequirements()`) +and uses only one of these types. + +If no memory type can be found that meets all the requirements, these functions +return `VK_ERROR_FEATURE_NOT_PRESENT`. + +You can leave VmaAllocationCreateInfo structure completely filled with zeros. +It means no requirements are specified for memory type. +It is valid, although not very useful. + +\section choosing_memory_type_usage Usage + +The easiest way to specify memory requirements is to fill member +VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage. +It defines high level, common usage types. +For more details, see description of this enum. + +For example, if you want to create a uniform buffer that will be filled using +transfer only once or infrequently and used for rendering every frame, you can +do it using following code: + +\code +VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufferInfo.size = 65536; +bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +\section choosing_memory_type_required_preferred_flags Required and preferred flags + +You can specify more detailed requirements by filling members +VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags +with a combination of bits from enum `VkMemoryPropertyFlags`. For example, +if you want to create a buffer that will be persistently mapped on host (so it +must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`, +use following code: + +\code +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; +allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; +allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +A memory type is chosen that has all the required flags and as many preferred +flags set as possible. + +If you use VmaAllocationCreateInfo::usage, it is just internally converted to +a set of required and preferred flags. + +\section choosing_memory_type_explicit_memory_types Explicit memory types + +If you inspected memory types available on the physical device and you have +a preference for memory types that you want to use, you can fill member +VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set +means that a memory type with that index is allowed to be used for the +allocation. Special value 0, just like `UINT32_MAX`, means there are no +restrictions to memory type index. + +Please note that this member is NOT just a memory type index. +Still you can use it to choose just one, specific memory type. +For example, if you already determined that your buffer should be created in +memory type 2, use following code: + +\code +uint32_t memoryTypeIndex = 2; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.memoryTypeBits = 1u << memoryTypeIndex; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + + +\section choosing_memory_type_custom_memory_pools Custom memory pools + +If you allocate from custom memory pool, all the ways of specifying memory +requirements described above are not applicable and the aforementioned members +of VmaAllocationCreateInfo structure are ignored. Memory type is selected +explicitly when creating the pool and then used to make all the allocations from +that pool. For further details, see \ref custom_memory_pools. + +\section choosing_memory_type_dedicated_allocations Dedicated allocations + +Memory for allocations is reserved out of larger block of `VkDeviceMemory` +allocated from Vulkan internally. That is the main feature of this whole library. +You can still request a separate memory block to be created for an allocation, +just like you would do in a trivial solution without using any allocator. +In that case, a buffer or image is always bound to that memory at offset 0. +This is called a "dedicated allocation". +You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +The library can also internally decide to use dedicated allocation in some cases, e.g.: + +- When the size of the allocation is large. +- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled + and it reports that dedicated allocation is required or recommended for the resource. +- When allocation of next big memory block fails due to not enough device memory, + but allocation with the exact requested size succeeds. + + +\page memory_mapping Memory mapping + +To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`, +to be able to read from it or write to it in CPU code. +Mapping is possible only of memory allocated from a memory type that has +`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. +Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose. +You can use them directly with memory allocated by this library, +but it is not recommended because of following issue: +Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed. +This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. +Because of this, Vulkan Memory Allocator provides following facilities: + +\section memory_mapping_mapping_functions Mapping functions + +The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory(). +They are safer and more convenient to use than standard Vulkan functions. +You can map an allocation multiple times simultaneously - mapping is reference-counted internally. +You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block. +The way it is implemented is that the library always maps entire memory block, not just region of the allocation. +For further details, see description of vmaMapMemory() function. +Example: + +\code +// Having these objects initialized: + +struct ConstantBuffer +{ + ... +}; +ConstantBuffer constantBufferData; + +VmaAllocator allocator; +VkBuffer constantBuffer; +VmaAllocation constantBufferAllocation; + +// You can map and fill your buffer using following code: + +void* mappedData; +vmaMapMemory(allocator, constantBufferAllocation, &mappedData); +memcpy(mappedData, &constantBufferData, sizeof(constantBufferData)); +vmaUnmapMemory(allocator, constantBufferAllocation); +\endcode + +When mapping, you may see a warning from Vulkan validation layer similar to this one: + +Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used. + +It happens because the library maps entire `VkDeviceMemory` block, where different +types of images and buffers may end up together, especially on GPUs with unified memory like Intel. +You can safely ignore it if you are sure you access only memory of the intended +object that you wanted to map. + + +\section memory_mapping_persistently_mapped_memory Persistently mapped memory + +Kepping your memory persistently mapped is generally OK in Vulkan. +You don't need to unmap it before using its data on the GPU. +The library provides a special feature designed for that: +Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in +VmaAllocationCreateInfo::flags stay mapped all the time, +so you can just access CPU pointer to it any time +without a need to call any "map" or "unmap" function. +Example: + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = sizeof(ConstantBuffer); +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); + +// Buffer is already mapped. You can access its memory. +memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData)); +\endcode + +There are some exceptions though, when you should consider mapping memory only for a short period of time: + +- When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2), + device is discrete AMD GPU, + and memory type is the special 256 MiB pool of `DEVICE_LOCAL + HOST_VISIBLE` memory + (selected when you use #VMA_MEMORY_USAGE_CPU_TO_GPU), + then whenever a memory block allocated from this memory type stays mapped + for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this + block is migrated by WDDM to system RAM, which degrades performance. It doesn't + matter if that particular memory block is actually used by the command buffer + being submitted. +- Keeping many large memory blocks mapped may impact performance or stability of some debugging tools. + +\section memory_mapping_cache_control Cache flush and invalidate + +Memory in Vulkan doesn't need to be unmapped before using it on GPU, +but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set, +you need to manually **invalidate** cache before reading of mapped pointer +and **flush** cache after writing to mapped pointer. +Map/unmap operations don't do that automatically. +Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`, +`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient +functions that refer to given allocation object: vmaFlushAllocation(), +vmaInvalidateAllocation(), +or multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations(). + +Regions of memory specified for flush/invalidate must be aligned to +`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library. +In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations +within blocks are aligned to this value, so their offsets are always multiply of +`nonCoherentAtomSize` and two different allocations never share same "line" of this size. + +Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`. + +Also, Windows drivers from all 3 **PC** GPU vendors (AMD, Intel, NVIDIA) +currently provide `HOST_COHERENT` flag on all memory types that are +`HOST_VISIBLE`, so on this platform you may not need to bother. + +\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable + +It may happen that your allocation ends up in memory that is `HOST_VISIBLE` (available for mapping) +despite it wasn't explicitly requested. +For example, application may work on integrated graphics with unified memory (like Intel) or +allocation from video memory might have failed, so the library chose system memory as fallback. + +You can detect this case and map such allocation to access its memory on CPU directly, +instead of launching a transfer operation. +In order to do that: call vmaGetAllocationMemoryProperties() +and look for `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = sizeof(ConstantBuffer); +bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; +allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + +VkBuffer buf; +VmaAllocation alloc; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr); + +VkMemoryPropertyFlags memFlags; +vmaGetAllocationMemoryProperties(allocator, alloc, &memFlags); +if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) +{ + // Allocation ended up in mappable memory. You can map it and access it directly. + void* mappedData; + vmaMapMemory(allocator, alloc, &mappedData); + memcpy(mappedData, &constantBufferData, sizeof(constantBufferData)); + vmaUnmapMemory(allocator, alloc); +} +else +{ + // Allocation ended up in non-mappable memory. + // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer. +} +\endcode + +You can even use #VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations +that are not necessarily `HOST_VISIBLE` (e.g. using #VMA_MEMORY_USAGE_GPU_ONLY). +If the allocation ends up in memory type that is `HOST_VISIBLE`, it will be persistently mapped and you can use it directly. +If not, the flag is just ignored. +Example: + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = sizeof(ConstantBuffer); +bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); + +if(allocInfo.pMappedData != nullptr) +{ + // Allocation ended up in mappable memory. + // It is persistently mapped. You can access it directly. + memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData)); +} +else +{ + // Allocation ended up in non-mappable memory. + // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer. +} +\endcode + + +\page staying_within_budget Staying within budget + +When developing a graphics-intensive game or program, it is important to avoid allocating +more GPU memory than it is physically available. When the memory is over-committed, +various bad things can happen, depending on the specific GPU, graphics driver, and +operating system: + +- It may just work without any problems. +- The application may slow down because some memory blocks are moved to system RAM + and the GPU has to access them through PCI Express bus. +- A new allocation may take very long time to complete, even few seconds, and possibly + freeze entire system. +- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST` + returned somewhere later. + +\section staying_within_budget_querying_for_budget Querying for budget + +To query for current memory usage and available budget, use function vmaGetHeapBudgets(). +Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap. + +Please note that this function returns different information and works faster than +vmaCalculateStats(). vmaGetHeapBudgets() can be called every frame or even before every +allocation, while vmaCalculateStats() is intended to be used rarely, +only to obtain statistical information, e.g. for debugging purposes. + +It is recommended to use VK_EXT_memory_budget device extension to obtain information +about the budget from Vulkan device. VMA is able to use this extension automatically. +When not enabled, the allocator behaves same way, but then it estimates current usage +and available budget based on its internal information and Vulkan memory heap sizes, +which may be less precise. In order to use this extension: + +1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2 + required by it are available and enable them. Please note that the first is a device + extension and the second is instance extension! +2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object. +3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from + Vulkan inside of it to avoid overhead of querying it with every allocation. + +\section staying_within_budget_controlling_memory_usage Controlling memory usage + +There are many ways in which you can try to stay within the budget. + +First, when making new allocation requires allocating a new memory block, the library +tries not to exceed the budget automatically. If a block with default recommended size +(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even +dedicated memory for just this resource. + +If the size of the requested resource plus current memory usage is more than the +budget, by default the library still tries to create it, leaving it to the Vulkan +implementation whether the allocation succeeds or fails. You can change this behavior +by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is +not made if it would exceed the budget or if the budget is already exceeded. +The allocation then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag +when creating resources that are not essential for the application (e.g. the texture +of a specific object) and not to pass it when creating critically important resources +(e.g. render targets). + +Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure +a new allocation is created only when it fits inside one of the existing memory blocks. +If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +This also ensures that the function call is very fast because it never goes to Vulkan +to obtain a new block. + +Please note that creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount +set to more than 0 will try to allocate memory blocks without checking whether they +fit within budget. + + +\page resource_aliasing Resource aliasing (overlap) + +New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory +management, give an opportunity to alias (overlap) multiple resources in the +same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL). +It can be useful to save video memory, but it must be used with caution. + +For example, if you know the flow of your whole render frame in advance, you +are going to use some intermediate textures or buffers only during a small range of render passes, +and you know these ranges don't overlap in time, you can bind these resources to +the same place in memory, even if they have completely different parameters (width, height, format etc.). + +![Resource aliasing (overlap)](../gfx/Aliasing.png) + +Such scenario is possible using VMA, but you need to create your images manually. +Then you need to calculate parameters of an allocation to be made using formula: + +- allocation size = max(size of each image) +- allocation alignment = max(alignment of each image) +- allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image) + +Following example shows two different images bound to the same place in memory, +allocated to fit largest of them. + +\code +// A 512x512 texture to be sampled. +VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +img1CreateInfo.imageType = VK_IMAGE_TYPE_2D; +img1CreateInfo.extent.width = 512; +img1CreateInfo.extent.height = 512; +img1CreateInfo.extent.depth = 1; +img1CreateInfo.mipLevels = 10; +img1CreateInfo.arrayLayers = 1; +img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB; +img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; +img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +// A full screen texture to be used as color attachment. +VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +img2CreateInfo.imageType = VK_IMAGE_TYPE_2D; +img2CreateInfo.extent.width = 1920; +img2CreateInfo.extent.height = 1080; +img2CreateInfo.extent.depth = 1; +img2CreateInfo.mipLevels = 1; +img2CreateInfo.arrayLayers = 1; +img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; +img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; +img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +VkImage img1; +res = vkCreateImage(device, &img1CreateInfo, nullptr, &img1); +VkImage img2; +res = vkCreateImage(device, &img2CreateInfo, nullptr, &img2); + +VkMemoryRequirements img1MemReq; +vkGetImageMemoryRequirements(device, img1, &img1MemReq); +VkMemoryRequirements img2MemReq; +vkGetImageMemoryRequirements(device, img2, &img2MemReq); + +VkMemoryRequirements finalMemReq = {}; +finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size); +finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment); +finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits; +// Validate if(finalMemReq.memoryTypeBits != 0) + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; + +VmaAllocation alloc; +res = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr); + +res = vmaBindImageMemory(allocator, alloc, img1); +res = vmaBindImageMemory(allocator, alloc, img2); + +// You can use img1, img2 here, but not at the same time! + +vmaFreeMemory(allocator, alloc); +vkDestroyImage(allocator, img2, nullptr); +vkDestroyImage(allocator, img1, nullptr); +\endcode + +Remember that using resources that alias in memory requires proper synchronization. +You need to issue a memory barrier to make sure commands that use `img1` and `img2` +don't overlap on GPU timeline. +You also need to treat a resource after aliasing as uninitialized - containing garbage data. +For example, if you use `img1` and then want to use `img2`, you need to issue +an image memory barrier for `img2` with `oldLayout` = `VK_IMAGE_LAYOUT_UNDEFINED`. + +Additional considerations: + +- Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases. +See chapter 11.8. "Memory Aliasing" of Vulkan specification or `VK_IMAGE_CREATE_ALIAS_BIT` flag. +- You can create more complex layout where different images and buffers are bound +at different offsets inside one large allocation. For example, one can imagine +a big texture used in some render passes, aliasing with a set of many small buffers +used between in some further passes. To bind a resource at non-zero offset of an allocation, +use vmaBindBufferMemory2() / vmaBindImageMemory2(). +- Before allocating memory for the resources you want to alias, check `memoryTypeBits` +returned in memory requirements of each resource to make sure the bits overlap. +Some GPUs may expose multiple memory types suitable e.g. only for buffers or +images with `COLOR_ATTACHMENT` usage, so the sets of memory types supported by your +resources may be disjoint. Aliasing them is not possible in that case. + + +\page custom_memory_pools Custom memory pools + +A memory pool contains a number of `VkDeviceMemory` blocks. +The library automatically creates and manages default pool for each memory type available on the device. +Default memory pool automatically grows in size. +Size of allocated blocks is also variable and managed automatically. + +You can create custom pool and allocate memory out of it. +It can be useful if you want to: + +- Keep certain kind of allocations separate from others. +- Enforce particular, fixed size of Vulkan memory blocks. +- Limit maximum amount of Vulkan memory allocated for that pool. +- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool. +- Use extra parameters for a set of your allocations that are available in #VmaPoolCreateInfo but not in + #VmaAllocationCreateInfo - e.g., custom minimum alignment, custom `pNext` chain. + +To use custom memory pools: + +-# Fill VmaPoolCreateInfo structure. +-# Call vmaCreatePool() to obtain #VmaPool handle. +-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle. + You don't need to specify any other parameters of this structure, like `usage`. + +Example: + +\code +// Create a pool that can have at most 2 blocks, 128 MiB each. +VmaPoolCreateInfo poolCreateInfo = {}; +poolCreateInfo.memoryTypeIndex = ... +poolCreateInfo.blockSize = 128ull * 1024 * 1024; +poolCreateInfo.maxBlockCount = 2; + +VmaPool pool; +vmaCreatePool(allocator, &poolCreateInfo, &pool); + +// Allocate a buffer out of it. +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = 1024; +bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.pool = pool; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); +\endcode + +You have to free all allocations made from this pool before destroying it. + +\code +vmaDestroyBuffer(allocator, buf, alloc); +vmaDestroyPool(allocator, pool); +\endcode + +New versions of this library support creating dedicated allocations in custom pools. +It is supported only when VmaPoolCreateInfo::blockSize = 0. +To use this feature, set VmaAllocationCreateInfo::pool to the pointer to your custom pool and +VmaAllocationCreateInfo::flags to #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + +\section custom_memory_pools_MemTypeIndex Choosing memory type index + +When creating a pool, you must explicitly specify memory type index. +To find the one suitable for your buffers or images, you can use helper functions +vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo(). +You need to provide structures with example parameters of buffers or images +that you are going to create in that pool. + +\code +VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +exampleBufCreateInfo.size = 1024; // Whatever. +exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change if needed. + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; // Change if needed. + +uint32_t memTypeIndex; +vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex); + +VmaPoolCreateInfo poolCreateInfo = {}; +poolCreateInfo.memoryTypeIndex = memTypeIndex; +// ... +\endcode + +When creating buffers/images allocated in that pool, provide following parameters: + +- `VkBufferCreateInfo`: Prefer to pass same parameters as above. + Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior. + Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers + or the other way around. +- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member. + Other members are ignored anyway. + +\section linear_algorithm Linear allocation algorithm + +Each Vulkan memory block managed by this library has accompanying metadata that +keeps track of used and unused regions. By default, the metadata structure and +algorithm tries to find best place for new allocations among free regions to +optimize memory usage. This way you can allocate and free objects in any order. + +![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png) + +Sometimes there is a need to use simpler, linear allocation algorithm. You can +create custom pool that uses such algorithm by adding flag +#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating +#VmaPool object. Then an alternative metadata management is used. It always +creates new allocations after last one and doesn't reuse free regions after +allocations freed in the middle. It results in better allocation performance and +less memory consumed by metadata. + +![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png) + +With this one flag, you can create a custom pool that can be used in many ways: +free-at-once, stack, double stack, and ring buffer. See below for details. +You don't need to specify explicitly which of these options you are going to use - it is detected automatically. + +\subsection linear_algorithm_free_at_once Free-at-once + +In a pool that uses linear algorithm, you still need to free all the allocations +individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free +them in any order. New allocations are always made after last one - free space +in the middle is not reused. However, when you release all the allocation and +the pool becomes empty, allocation starts from the beginning again. This way you +can use linear algorithm to speed up creation of allocations that you are going +to release all at once. + +![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png) + +This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount +value that allows multiple memory blocks. + +\subsection linear_algorithm_stack Stack + +When you free an allocation that was created last, its space can be reused. +Thanks to this, if you always release allocations in the order opposite to their +creation (LIFO - Last In First Out), you can achieve behavior of a stack. + +![Stack](../gfx/Linear_allocator_4_stack.png) + +This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount +value that allows multiple memory blocks. + +\subsection linear_algorithm_double_stack Double stack + +The space reserved by a custom pool with linear algorithm may be used by two +stacks: + +- First, default one, growing up from offset 0. +- Second, "upper" one, growing down from the end towards lower offsets. + +To make allocation from the upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT +to VmaAllocationCreateInfo::flags. + +![Double stack](../gfx/Linear_allocator_7_double_stack.png) + +Double stack is available only in pools with one memory block - +VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined. + +When the two stacks' ends meet so there is not enough space between them for a +new allocation, such allocation fails with usual +`VK_ERROR_OUT_OF_DEVICE_MEMORY` error. + +\subsection linear_algorithm_ring_buffer Ring buffer + +When you free some allocations from the beginning and there is not enough free space +for a new one at the end of a pool, allocator's "cursor" wraps around to the +beginning and starts allocation there. Thanks to this, if you always release +allocations in the same order as you created them (FIFO - First In First Out), +you can achieve behavior of a ring buffer / queue. + +![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png) + +Ring buffer is available only in pools with one memory block - +VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined. + +\section buddy_algorithm Buddy allocation algorithm + +There is another allocation algorithm that can be used with custom pools, called +"buddy". Its internal data structure is based on a binary tree of blocks, each having +size that is a power of two and a half of its parent's size. When you want to +allocate memory of certain size, a free node in the tree is located. If it is too +large, it is recursively split into two halves (called "buddies"). However, if +requested allocation size is not a power of two, the size of the allocation is +aligned up to the nearest power of two and the remaining space is wasted. When +two buddy nodes become free, they are merged back into one larger node. + +![Buddy allocator](../gfx/Buddy_allocator.png) + +The advantage of buddy allocation algorithm over default algorithm is faster +allocation and deallocation, as well as smaller external fragmentation. The +disadvantage is more wasted space (internal fragmentation). +For more information, please search the Internet for "Buddy memory allocation" - +sources that describe this concept in general. + +To use buddy allocation algorithm with a custom pool, add flag +#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating +#VmaPool object. + +Several limitations apply to pools that use buddy algorithm: + +- It is recommended to use VmaPoolCreateInfo::blockSize that is a power of two. + Otherwise, only largest power of two smaller than the size is used for + allocations. The remaining space always stays unused. +- [Margins](@ref debugging_memory_usage_margins) and + [corruption detection](@ref debugging_memory_usage_corruption_detection) + don't work in such pools. +- [Defragmentation](@ref defragmentation) doesn't work with allocations made from + such pool. + +\page defragmentation Defragmentation + +Interleaved allocations and deallocations of many objects of varying size can +cause fragmentation over time, which can lead to a situation where the library is unable +to find a continuous range of free memory for a new allocation despite there is +enough free space, just scattered across many small free ranges between existing +allocations. + +To mitigate this problem, you can use defragmentation feature: +structure #VmaDefragmentationInfo2, function vmaDefragmentationBegin(), vmaDefragmentationEnd(). +Given set of allocations, +this function can move them to compact used memory, ensure more continuous free +space and possibly also free some `VkDeviceMemory` blocks. + +What the defragmentation does is: + +- Updates #VmaAllocation objects to point to new `VkDeviceMemory` and offset. + After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or + VmaAllocationInfo::offset changes. You must query them again using + vmaGetAllocationInfo() if you need them. +- Moves actual data in memory. + +What it doesn't do, so you need to do it yourself: + +- Recreate buffers and images that were bound to allocations that were defragmented and + bind them with their new places in memory. + You must use `vkDestroyBuffer()`, `vkDestroyImage()`, + `vkCreateBuffer()`, `vkCreateImage()`, vmaBindBufferMemory(), vmaBindImageMemory() + for that purpose and NOT vmaDestroyBuffer(), + vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage(), because you don't need to + destroy or create allocation objects! +- Recreate views and update descriptors that point to these buffers and images. + +\section defragmentation_cpu Defragmenting CPU memory + +Following example demonstrates how you can run defragmentation on CPU. +Only allocations created in memory types that are `HOST_VISIBLE` can be defragmented. +Others are ignored. + +The way it works is: + +- It temporarily maps entire memory blocks when necessary. +- It moves data using `memmove()` function. + +\code +// Given following variables already initialized: +VkDevice device; +VmaAllocator allocator; +std::vector buffers; +std::vector allocations; + + +const uint32_t allocCount = (uint32_t)allocations.size(); +std::vector allocationsChanged(allocCount); + +VmaDefragmentationInfo2 defragInfo = {}; +defragInfo.allocationCount = allocCount; +defragInfo.pAllocations = allocations.data(); +defragInfo.pAllocationsChanged = allocationsChanged.data(); +defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE; // No limit. +defragInfo.maxCpuAllocationsToMove = UINT32_MAX; // No limit. + +VmaDefragmentationContext defragCtx; +vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx); +vmaDefragmentationEnd(allocator, defragCtx); + +for(uint32_t i = 0; i < allocCount; ++i) +{ + if(allocationsChanged[i]) + { + // Destroy buffer that is immutably bound to memory region which is no longer valid. + vkDestroyBuffer(device, buffers[i], nullptr); + + // Create new buffer with same parameters. + VkBufferCreateInfo bufferInfo = ...; + vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]); + + // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning. + + // Bind new buffer to new memory region. Data contained in it is already moved. + VmaAllocationInfo allocInfo; + vmaGetAllocationInfo(allocator, allocations[i], &allocInfo); + vmaBindBufferMemory(allocator, allocations[i], buffers[i]); + } +} +\endcode + +Setting VmaDefragmentationInfo2::pAllocationsChanged is optional. +This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index +has been modified during defragmentation. +You can pass null, but you then need to query every allocation passed to defragmentation +for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it. + +If you use [Custom memory pools](@ref choosing_memory_type_custom_memory_pools), +you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools +instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations +to defragment all allocations in given pools. +You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case. +You can also combine both methods. + +\section defragmentation_gpu Defragmenting GPU memory + +It is also possible to defragment allocations created in memory types that are not `HOST_VISIBLE`. +To do that, you need to pass a command buffer that meets requirements as described in +VmaDefragmentationInfo2::commandBuffer. The way it works is: + +- It creates temporary buffers and binds them to entire memory blocks when necessary. +- It issues `vkCmdCopyBuffer()` to passed command buffer. + +Example: + +\code +// Given following variables already initialized: +VkDevice device; +VmaAllocator allocator; +VkCommandBuffer commandBuffer; +std::vector buffers; +std::vector allocations; + + +const uint32_t allocCount = (uint32_t)allocations.size(); +std::vector allocationsChanged(allocCount); + +VkCommandBufferBeginInfo cmdBufBeginInfo = ...; +vkBeginCommandBuffer(commandBuffer, &cmdBufBeginInfo); + +VmaDefragmentationInfo2 defragInfo = {}; +defragInfo.allocationCount = allocCount; +defragInfo.pAllocations = allocations.data(); +defragInfo.pAllocationsChanged = allocationsChanged.data(); +defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE; // Notice it is "GPU" this time. +defragInfo.maxGpuAllocationsToMove = UINT32_MAX; // Notice it is "GPU" this time. +defragInfo.commandBuffer = commandBuffer; + +VmaDefragmentationContext defragCtx; +vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx); + +vkEndCommandBuffer(commandBuffer); + +// Submit commandBuffer. +// Wait for a fence that ensures commandBuffer execution finished. + +vmaDefragmentationEnd(allocator, defragCtx); + +for(uint32_t i = 0; i < allocCount; ++i) +{ + if(allocationsChanged[i]) + { + // Destroy buffer that is immutably bound to memory region which is no longer valid. + vkDestroyBuffer(device, buffers[i], nullptr); + + // Create new buffer with same parameters. + VkBufferCreateInfo bufferInfo = ...; + vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]); + + // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning. + + // Bind new buffer to new memory region. Data contained in it is already moved. + VmaAllocationInfo allocInfo; + vmaGetAllocationInfo(allocator, allocations[i], &allocInfo); + vmaBindBufferMemory(allocator, allocations[i], buffers[i]); + } +} +\endcode + +You can combine these two methods by specifying non-zero `maxGpu*` as well as `maxCpu*` parameters. +The library automatically chooses best method to defragment each memory pool. + +You may try not to block your entire program to wait until defragmentation finishes, +but do it in the background, as long as you carefully fullfill requirements described +in function vmaDefragmentationBegin(). + +\section defragmentation_additional_notes Additional notes + +It is only legal to defragment allocations bound to: + +- buffers +- images created with `VK_IMAGE_CREATE_ALIAS_BIT`, `VK_IMAGE_TILING_LINEAR`, and + being currently in `VK_IMAGE_LAYOUT_GENERAL` or `VK_IMAGE_LAYOUT_PREINITIALIZED`. + +Defragmentation of images created with `VK_IMAGE_TILING_OPTIMAL` or in any other +layout may give undefined results. + +If you defragment allocations bound to images, new images to be bound to new +memory region after defragmentation should be created with `VK_IMAGE_LAYOUT_PREINITIALIZED` +and then transitioned to their original layout from before defragmentation if +needed using an image memory barrier. + +While using defragmentation, you may experience validation layer warnings, which you just need to ignore. +See [Validation layer warnings](@ref general_considerations_validation_layer_warnings). + +Please don't expect memory to be fully compacted after defragmentation. +Algorithms inside are based on some heuristics that try to maximize number of Vulkan +memory blocks to make totally empty to release them, as well as to maximize continuous +empty space inside remaining blocks, while minimizing the number and size of allocations that +need to be moved. Some fragmentation may still remain - this is normal. + +\section defragmentation_custom_algorithm Writing custom defragmentation algorithm + +If you want to implement your own, custom defragmentation algorithm, +there is infrastructure prepared for that, +but it is not exposed through the library API - you need to hack its source code. +Here are steps needed to do this: + +-# Main thing you need to do is to define your own class derived from base abstract + class `VmaDefragmentationAlgorithm` and implement your version of its pure virtual methods. + See definition and comments of this class for details. +-# Your code needs to interact with device memory block metadata. + If you need more access to its data than it is provided by its public interface, + declare your new class as a friend class e.g. in class `VmaBlockMetadata_Generic`. +-# If you want to create a flag that would enable your algorithm or pass some additional + flags to configure it, add them to `VmaDefragmentationFlagBits` and use them in + VmaDefragmentationInfo2::flags. +-# Modify function `VmaBlockVectorDefragmentationContext::Begin` to create object + of your new class whenever needed. + + +\page statistics Statistics + +This library contains functions that return information about its internal state, +especially the amount of memory allocated from Vulkan. +Please keep in mind that these functions need to traverse all internal data structures +to gather these information, so they may be quite time-consuming. +Don't call them too often. + +\section statistics_numeric_statistics Numeric statistics + +You can query for overall statistics of the allocator using function vmaCalculateStats(). +Information are returned using structure #VmaStats. +It contains #VmaStatInfo - number of allocated blocks, number of allocations +(occupied ranges in these blocks), number of unused (free) ranges in these blocks, +number of bytes used and unused (but still allocated from Vulkan) and other information. +They are summed across memory heaps, memory types and total for whole allocator. + +You can query for statistics of a custom pool using function vmaGetPoolStats(). +Information are returned using structure #VmaPoolStats. + +You can query for information about specific allocation using function vmaGetAllocationInfo(). +It fill structure #VmaAllocationInfo. + +\section statistics_json_dump JSON dump + +You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString(). +The result is guaranteed to be correct JSON. +It uses ANSI encoding. +Any strings provided by user (see [Allocation names](@ref allocation_names)) +are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding, +this JSON string can be treated as using this encoding. +It must be freed using function vmaFreeStatsString(). + +The format of this JSON string is not part of official documentation of the library, +but it will not change in backward-incompatible way without increasing library major version number +and appropriate mention in changelog. + +The JSON string contains all the data that can be obtained using vmaCalculateStats(). +It can also contain detailed map of allocated memory blocks and their regions - +free and occupied by allocations. +This allows e.g. to visualize the memory or assess fragmentation. + + +\page allocation_annotation Allocation names and user data + +\section allocation_user_data Allocation user data + +You can annotate allocations with your own information, e.g. for debugging purposes. +To do that, fill VmaAllocationCreateInfo::pUserData field when creating +an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer, +some handle, index, key, ordinal number or any other value that would associate +the allocation with your custom metadata. + +\code +VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +// Fill bufferInfo... + +MyBufferMetadata* pMetadata = CreateBufferMetadata(); + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; +allocCreateInfo.pUserData = pMetadata; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr); +\endcode + +The pointer may be later retrieved as VmaAllocationInfo::pUserData: + +\code +VmaAllocationInfo allocInfo; +vmaGetAllocationInfo(allocator, allocation, &allocInfo); +MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData; +\endcode + +It can also be changed using function vmaSetAllocationUserData(). + +Values of (non-zero) allocations' `pUserData` are printed in JSON report created by +vmaBuildStatsString(), in hexadecimal form. + +\section allocation_names Allocation names + +There is alternative mode available where `pUserData` pointer is used to point to +a null-terminated string, giving a name to the allocation. To use this mode, +set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags. +Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to +vmaSetAllocationUserData() must be either null or pointer to a null-terminated string. +The library creates internal copy of the string, so the pointer you pass doesn't need +to be valid for whole lifetime of the allocation. You can free it after the call. + +\code +VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +// Fill imageInfo... + +std::string imageName = "Texture: "; +imageName += fileName; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT; +allocCreateInfo.pUserData = imageName.c_str(); + +VkImage image; +VmaAllocation allocation; +vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr); +\endcode + +The value of `pUserData` pointer of the allocation will be different than the one +you passed when setting allocation's name - pointing to a buffer managed +internally that holds copy of the string. + +\code +VmaAllocationInfo allocInfo; +vmaGetAllocationInfo(allocator, allocation, &allocInfo); +const char* imageName = (const char*)allocInfo.pUserData; +printf("Image name: %s\n", imageName); +\endcode + +That string is also printed in JSON report created by vmaBuildStatsString(). + +\note Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. +You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library. + + +\page virtual_allocator Virtual allocator + +As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator". +It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block". +You can use it to allocate your own memory or other objects, even completely unrelated to Vulkan. +A common use case is sub-allocation of pieces of one large GPU buffer. + +\section virtual_allocator_creating_virtual_block Creating virtual block + +To use this functionality, there is no main "allocator" object. +You don't need to have #VmaAllocator object created. +All you need to do is to create a separate #VmaVirtualBlock object for each block of memory you want to be managed by the allocator: + +-# Fill in #VmaVirtualBlockCreateInfo structure. +-# Call vmaCreateVirtualBlock(). Get new #VmaVirtualBlock object. + +Example: + +\code +VmaVirtualBlockCreateInfo blockCreateInfo = {}; +blockCreateInfo.size = 1048576; // 1 MB + +VmaVirtualBlock block; +VkResult res = vmaCreateVirtualBlock(&blockCreateInfo, &block); +\endcode + +\section virtual_allocator_making_virtual_allocations Making virtual allocations + +#VmaVirtualBlock object contains internal data structure that keeps track of free and occupied regions +using the same code as the main Vulkan memory allocator. +Similarly to #VmaAllocation for standard GPU allocations, there is #VmaVirtualAllocation type +that represents an opaque handle to an allocation withing the virtual block. + +In order to make such allocation: + +-# Fill in #VmaVirtualAllocationCreateInfo structure. +-# Call vmaVirtualAllocate(). Get new #VmaVirtualAllocation object that represents the allocation. + You can also receive `VkDeviceSize offset` that was assigned to the allocation. + +Example: + +\code +VmaVirtualAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.size = 4096; // 4 KB + +VmaVirtualAllocation alloc; +VkDeviceSize offset; +res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, &offset); +if(res == VK_SUCCESS) +{ + // Use the 4 KB of your memory starting at offset. +} +else +{ + // Allocation failed - no space for it could be found. Handle this error! +} +\endcode + +\section virtual_allocator_deallocation Deallocation + +When no longer needed, an allocation can be freed by calling vmaVirtualFree(). +You can only pass to this function an allocation that was previously returned by vmaVirtualAllocate() +called for the same #VmaVirtualBlock. + +When whole block is no longer needed, the block object can be released by calling vmaDestroyVirtualBlock(). +All allocations must be freed before the block is destroyed, which is checked internally by an assert. +However, if you don't want to call vmaVirtualFree() for each allocation, you can use vmaClearVirtualBlock() to free them all at once - +a feature not available in normal Vulkan memory allocator. Example: + +\code +vmaVirtualFree(block, alloc); +vmaDestroyVirtualBlock(block); +\endcode + +\section virtual_allocator_allocation_parameters Allocation parameters + +You can attach a custom pointer to each allocation by using vmaSetVirtualAllocationUserData(). +Its default value is null. +It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some +larger data structure containing more information. Example: + +\code +struct CustomAllocData +{ + std::string m_AllocName; +}; +CustomAllocData* allocData = new CustomAllocData(); +allocData->m_AllocName = "My allocation 1"; +vmaSetVirtualAllocationUserData(block, alloc, allocData); +\endcode + +The pointer can later be fetched, along with allocation offset and size, by passing the allocation handle to function +vmaGetVirtualAllocationInfo() and inspecting returned structure #VmaVirtualAllocationInfo. +If you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation! +Example: + +\code +VmaVirtualAllocationInfo allocInfo; +vmaGetVirtualAllocationInfo(block, alloc, &allocInfo); +delete (CustomAllocData*)allocInfo.pUserData; + +vmaVirtualFree(block, alloc); +\endcode + +\section virtual_allocator_alignment_and_units Alignment and units + +It feels natural to express sizes and offsets in bytes. +If an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member +VmaVirtualAllocationCreateInfo::alignment to request it. Example: + +\code +VmaVirtualAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.size = 4096; // 4 KB +allocCreateInfo.alignment = 4; // Returned offset must be a multiply of 4 B + +VmaVirtualAllocation alloc; +res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, nullptr); +\endcode + +Alignments of different allocations made from one block may vary. +However, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`, +you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes. +It might be more convenient, but you need to make sure to use this new unit consistently in all the places: + +- VmaVirtualBlockCreateInfo::size +- VmaVirtualAllocationCreateInfo::size and VmaVirtualAllocationCreateInfo::alignment +- Using offset returned by vmaVirtualAllocate() or in VmaVirtualAllocationInfo::offset + +\section virtual_allocator_statistics Statistics + +You can obtain statistics of a virtual block using vmaCalculateVirtualBlockStats(). +The function fills structure #VmaStatInfo - same as used by the normal Vulkan memory allocator. +Example: + +\code +VmaStatInfo statInfo; +vmaCalculateVirtualBlockStats(block, &statInfo); +printf("My virtual block has %llu bytes used by %u virtual allocations\n", + statInfo.usedBytes, statInfo.allocationCount); +\endcode + +You can also request a full list of allocations and free regions as a string in JSON format by calling +vmaBuildVirtualBlockStatsString(). +Returned string must be later freed using vmaFreeVirtualBlockStatsString(). +The format of this string differs from the one returned by the main Vulkan allocator, but it is similar. + +\section virtual_allocator_additional_considerations Additional considerations + +The "virtual allocator" functionality is implemented on a level of individual memory blocks. +Keeping track of a whole collection of blocks, allocating new ones when out of free space, +deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user. + +Alternative allocation algorithms are supported, just like in custom pools of the real GPU memory. +See enum #VmaVirtualBlockCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT). +You can find their description in chapter \ref custom_memory_pools. +Allocation strategies are also supported. +See enum #VmaVirtualAllocationCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT). + +Following features are supported only by the allocator of the real GPU memory and not by virtual allocations: +buffer-image granularity, `VMA_DEBUG_MARGIN`, `VMA_MIN_ALIGNMENT`. + + +\page debugging_memory_usage Debugging incorrect memory usage + +If you suspect a bug with memory usage, like usage of uninitialized memory or +memory being overwritten out of bounds of an allocation, +you can use debug features of this library to verify this. + +\section debugging_memory_usage_initialization Memory initialization + +If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used, +you can enable automatic memory initialization to verify this. +To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1. + +\code +#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1 +#include "vk_mem_alloc.h" +\endcode + +It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`. +Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`. +Memory is automatically mapped and unmapped if necessary. + +If you find these values while debugging your program, good chances are that you incorrectly +read Vulkan memory that is allocated but not initialized, or already freed, respectively. + +Memory initialization works only with memory types that are `HOST_VISIBLE`. +It works also with dedicated allocations. + +\section debugging_memory_usage_margins Margins + +By default, allocations are laid out in memory blocks next to each other if possible +(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`). + +![Allocations without margin](../gfx/Margins_1.png) + +Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified +number of bytes as a margin before and after every allocation. + +\code +#define VMA_DEBUG_MARGIN 16 +#include "vk_mem_alloc.h" +\endcode + +![Allocations with margin](../gfx/Margins_2.png) + +If your bug goes away after enabling margins, it means it may be caused by memory +being overwritten outside of allocation boundaries. It is not 100% certain though. +Change in application behavior may also be caused by different order and distribution +of allocations across memory blocks after margins are applied. + +The margin is applied also before first and after last allocation in a block. +It may occur only once between two adjacent allocations. + +Margins work with all types of memory. + +Margin is applied only to allocations made out of memory blocks and not to dedicated +allocations, which have their own memory block of specific size. +It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag +or those automatically decided to put into dedicated allocations, e.g. due to its +large size or recommended by VK_KHR_dedicated_allocation extension. +Margins are also not active in custom pools created with #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag. + +Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space. + +Note that enabling margins increases memory usage and fragmentation. + +\section debugging_memory_usage_corruption_detection Corruption detection + +You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation +of contents of the margins. + +\code +#define VMA_DEBUG_MARGIN 16 +#define VMA_DEBUG_DETECT_CORRUPTION 1 +#include "vk_mem_alloc.h" +\endcode + +When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN` +(it must be multiply of 4) before and after every allocation is filled with a magic number. +This idea is also know as "canary". +Memory is automatically mapped and unmapped if necessary. + +This number is validated automatically when the allocation is destroyed. +If it is not equal to the expected value, `VMA_ASSERT()` is executed. +It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, +which indicates a serious bug. + +You can also explicitly request checking margins of all allocations in all memory blocks +that belong to specified memory types by using function vmaCheckCorruption(), +or in memory blocks that belong to specified custom pool, by using function +vmaCheckPoolCorruption(). + +Margin validation (corruption detection) works only for memory types that are +`HOST_VISIBLE` and `HOST_COHERENT`. + + +\page opengl_interop OpenGL Interop + +VMA provides some features that help with interoperability with OpenGL. + +\section opengl_interop_exporting_memory Exporting memory + +If you want to attach `VkExportMemoryAllocateInfoKHR` structure to `pNext` chain of memory allocations made by the library: + +It is recommended to create \ref custom_memory_pools for such allocations. +Define and fill in your `VkExportMemoryAllocateInfoKHR` structure and attach it to VmaPoolCreateInfo::pMemoryAllocateNext +while creating the custom pool. +Please note that the structure must remain alive and unchanged for the whole lifetime of the #VmaPool, +not only while creating it, as no copy of the structure is made, +but its original pointer is used for each allocation instead. + +If you want to export all memory allocated by the library from certain memory types, +also dedicated allocations or other allocations made from default pools, +an alternative solution is to fill in VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes. +It should point to an array with `VkExternalMemoryHandleTypeFlagsKHR` to be automatically passed by the library +through `VkExportMemoryAllocateInfoKHR` on each allocation made from a specific memory type. +Please note that new versions of the library also support dedicated allocations created in custom pools. + +You should not mix these two methods in a way that allows to apply both to the same memory type. +Otherwise, `VkExportMemoryAllocateInfoKHR` structure would be attached twice to the `pNext` chain of `VkMemoryAllocateInfo`. + + +\section opengl_interop_custom_alignment Custom alignment + +Buffers or images exported to a different API like OpenGL may require a different alignment, +higher than the one used by the library automatically, queried from functions like `vkGetBufferMemoryRequirements`. +To impose such alignment: + +It is recommended to create \ref custom_memory_pools for such allocations. +Set VmaPoolCreateInfo::minAllocationAlignment member to the minimum alignment required for each allocation +to be made out of this pool. +The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image +from a function like `vkGetBufferMemoryRequirements`, which is called by VMA automatically. + +If you want to create a buffer with a specific minimum alignment out of default pools, +use special function vmaCreateBufferWithAlignment(), which takes additional parameter `minAlignment`. + +Note the problem of alignment affects only resources placed inside bigger `VkDeviceMemory` blocks and not dedicated +allocations, as these, by definition, always have alignment = 0 because the resource is bound to the beginning of its dedicated block. +Contrary to Direct3D 12, Vulkan doesn't have a concept of alignment of the entire memory block passed on its allocation. + + +\page usage_patterns Recommended usage patterns + +See also slides from talk: +[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New) + + +\section usage_patterns_common_mistakes Common mistakes + +Use of CPU_TO_GPU instead of CPU_ONLY memory + +#VMA_MEMORY_USAGE_CPU_TO_GPU is recommended only for resources that will be +mapped and written by the CPU, as well as read directly by the GPU - like some +buffers or textures updated every frame (dynamic). If you create a staging copy +of a resource to be written by CPU and then used as a source of transfer to +another resource placed in the GPU memory, that staging resource should be +created with #VMA_MEMORY_USAGE_CPU_ONLY. Please read the descriptions of these +enums carefully for details. + +Unnecessary use of custom pools + +\ref custom_memory_pools may be useful for special purposes - when you want to +keep certain type of resources separate e.g. to reserve minimum amount of memory +for them or limit maximum amount of memory they can occupy. For most +resources this is not needed and so it is not recommended to create #VmaPool +objects and allocations out of them. Allocating from the default pool is sufficient. + +\section usage_patterns_simple Simple patterns + +\subsection usage_patterns_simple_render_targets Render targets + +When: +Any resources that you frequently write and read on GPU, +e.g. images used as color attachments (aka "render targets"), depth-stencil attachments, +images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)"). + +What to do: +Create them in video memory that is fastest to access from GPU using +#VMA_MEMORY_USAGE_GPU_ONLY. + +Consider using [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension +and/or manually creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, +especially if they are large or if you plan to destroy and recreate them e.g. when +display resolution changes. +Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later. + +\subsection usage_patterns_simple_immutable_resources Immutable resources + +When: +Any resources that you fill on CPU only once (aka "immutable") or infrequently +and then read frequently on GPU, +e.g. textures, vertex and index buffers, constant buffers that don't change often. + +What to do: +Create them in video memory that is fastest to access from GPU using +#VMA_MEMORY_USAGE_GPU_ONLY. + +To initialize content of such resource, create a CPU-side (aka "staging") copy of it +in system memory - #VMA_MEMORY_USAGE_CPU_ONLY, map it, fill it, +and submit a transfer from it to the GPU resource. +You can keep the staging copy if you need it for another upload transfer in the future. +If you don't, you can destroy it or reuse this buffer for uploading different resource +after the transfer finishes. + +Prefer to create just buffers in system memory rather than images, even for uploading textures. +Use `vkCmdCopyBufferToImage()`. +Dont use images with `VK_IMAGE_TILING_LINEAR`. + +\subsection usage_patterns_dynamic_resources Dynamic resources + +When: +Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call, +written on CPU, read on GPU. + +What to do: +Create them using #VMA_MEMORY_USAGE_CPU_TO_GPU. +You can map it and write to it directly on CPU, as well as read from it on GPU. + +This is a more complex situation. Different solutions are possible, +and the best one depends on specific GPU type, but you can use this simple approach for the start. +Prefer to write to such resource sequentially (e.g. using `memcpy`). +Don't perform random access or any reads from it on CPU, as it may be very slow. +Also note that textures written directly from the host through a mapped pointer need to be in LINEAR not OPTIMAL layout. + +\subsection usage_patterns_readback Readback + +When: +Resources that contain data written by GPU that you want to read back on CPU, +e.g. results of some computations. + +What to do: +Create them using #VMA_MEMORY_USAGE_GPU_TO_CPU. +You can write to them directly on GPU, as well as map and read them on CPU. + +\section usage_patterns_advanced Advanced patterns + +\subsection usage_patterns_integrated_graphics Detecting integrated graphics + +You can support integrated graphics (like Intel HD Graphics, AMD APU) better +by detecting it in Vulkan. +To do it, call `vkGetPhysicalDeviceProperties()`, inspect +`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`. +When you find it, you can assume that memory is unified and all memory types are comparably fast +to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + +You can then sum up sizes of all available memory heaps and treat them as useful for +your GPU resources, instead of only `DEVICE_LOCAL` ones. +You can also prefer to create your resources in memory types that are `HOST_VISIBLE` to map them +directly instead of submitting explicit transfer (see below). + +\subsection usage_patterns_direct_vs_transfer Direct access versus transfer + +For resources that you frequently write on CPU and read on GPU, many solutions are possible: + +-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY, + second copy in system memory using #VMA_MEMORY_USAGE_CPU_ONLY and submit explicit transfer each time. +-# Create just a single copy using #VMA_MEMORY_USAGE_CPU_TO_GPU, map it and fill it on CPU, + read it directly on GPU. +-# Create just a single copy using #VMA_MEMORY_USAGE_CPU_ONLY, map it and fill it on CPU, + read it directly on GPU. + +Which solution is the most efficient depends on your resource and especially on the GPU. +It is best to measure it and then make the decision. +Some general recommendations: + +- On integrated graphics use (2) or (3) to avoid unnecessary time and memory overhead + related to using a second copy and making transfer. +- For small resources (e.g. constant buffers) use (2). + Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable. + Even if the resource ends up in system memory, its data may be cached on GPU after first + fetch over PCIe bus. +- For larger resources (e.g. textures), decide between (1) and (2). + You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is + both `DEVICE_LOCAL` and `HOST_VISIBLE`. When you find it, use (2), otherwise use (1). + +Similarly, for resources that you frequently write on GPU and read on CPU, multiple +solutions are possible: + +-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY, + second copy in system memory using #VMA_MEMORY_USAGE_GPU_TO_CPU and submit explicit tranfer each time. +-# Create just single copy using #VMA_MEMORY_USAGE_GPU_TO_CPU, write to it directly on GPU, + map it and read it on CPU. + +You should take some measurements to decide which option is faster in case of your specific +resource. + +Note that textures accessed directly from the host through a mapped pointer need to be in LINEAR layout, +which may slow down their usage on the device. +Textures accessed only by the device and transfer operations can use OPTIMAL layout. + +If you don't want to specialize your code for specific types of GPUs, you can still make +an simple optimization for cases when your resource ends up in mappable memory to use it +directly in this case instead of creating CPU-side staging copy. +For details see [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable). + + +\page configuration Configuration + +Please check "CONFIGURATION SECTION" in the code to find macros that you can define +before each include of this file or change directly in this file to provide +your own implementation of basic facilities like assert, `min()` and `max()` functions, +mutex, atomic etc. +The library uses its own implementation of containers by default, but you can switch to using +STL containers instead. + +For example, define `VMA_ASSERT(expr)` before including the library to provide +custom implementation of the assertion, compatible with your project. +By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration +and empty otherwise. + +\section config_Vulkan_functions Pointers to Vulkan functions + +There are multiple ways to import pointers to Vulkan functions in the library. +In the simplest case you don't need to do anything. +If the compilation or linking of your program or the initialization of the #VmaAllocator +doesn't work for you, you can try to reconfigure it. + +First, the allocator tries to fetch pointers to Vulkan functions linked statically, +like this: + +\code +m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory; +\endcode + +If you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`. + +Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions. +You can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or +by using a helper library like [volk](https://github.com/zeux/volk). + +Third, VMA tries to fetch remaining pointers that are still null by calling +`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own. +If you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`. + +Finally, all the function pointers required by the library (considering selected +Vulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null. + + +\section custom_memory_allocator Custom host memory allocator + +If you use custom allocator for CPU memory rather than default operator `new` +and `delete` from C++, you can make this library using your allocator as well +by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These +functions will be passed to Vulkan, as well as used by the library itself to +make any CPU-side allocations. + +\section allocation_callbacks Device memory allocation callbacks + +The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally. +You can setup callbacks to be informed about these calls, e.g. for the purpose +of gathering some statistics. To do it, fill optional member +VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. + +\section heap_memory_limit Device heap memory limit + +When device memory of certain heap runs out of free space, new allocations may +fail (returning error code) or they may succeed, silently pushing some existing +memory blocks from GPU VRAM to system RAM (which degrades performance). This +behavior is implementation-dependent - it depends on GPU vendor and graphics +driver. + +On AMD cards it can be controlled while creating Vulkan device object by using +VK_AMD_memory_overallocation_behavior extension, if available. + +Alternatively, if you want to test how your program behaves with limited amount of Vulkan device +memory available without switching your graphics card to one that really has +smaller VRAM, you can use a feature of this library intended for this purpose. +To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit. + + + +\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation + +VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve +performance on some GPUs. It augments Vulkan API with possibility to query +driver whether it prefers particular buffer or image to have its own, dedicated +allocation (separate `VkDeviceMemory` block) for better efficiency - to be able +to do some internal optimizations. + +The extension is supported by this library. It will be used automatically when +enabled. To enable it: + +1 . When creating Vulkan device, check if following 2 device extensions are +supported (call `vkEnumerateDeviceExtensionProperties()`). +If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`). + +- VK_KHR_get_memory_requirements2 +- VK_KHR_dedicated_allocation + +If you enabled these extensions: + +2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating +your #VmaAllocator`to inform the library that you enabled required extensions +and you want the library to use them. + +\code +allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + +vmaCreateAllocator(&allocatorInfo, &allocator); +\endcode + +That is all. The extension will be automatically used whenever you create a +buffer using vmaCreateBuffer() or image using vmaCreateImage(). + +When using the extension together with Vulkan Validation Layer, you will receive +warnings like this: + + vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer. + +It is OK, you should just ignore it. It happens because you use function +`vkGetBufferMemoryRequirements2KHR()` instead of standard +`vkGetBufferMemoryRequirements()`, while the validation layer seems to be +unaware of it. + +To learn more about this extension, see: + +- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap50.html#VK_KHR_dedicated_allocation) +- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5) + + + +\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory + +VK_AMD_device_coherent_memory is a device extension that enables access to +additional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and +`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for +allocation of buffers intended for writing "breadcrumb markers" in between passes +or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases. + +When the extension is available but has not been enabled, Vulkan physical device +still exposes those memory types, but their usage is forbidden. VMA automatically +takes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt +to allocate memory of such type is made. + +If you want to use this extension in connection with VMA, follow these steps: + +\section vk_amd_device_coherent_memory_initialization Initialization + +1) Call `vkEnumerateDeviceExtensionProperties` for the physical device. +Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_AMD_device_coherent_memory". + +2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`. +Attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned. +Check if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true. + +3) While creating device with `vkCreateDevice`, enable this extension - add "VK_AMD_device_coherent_memory" +to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`. + +4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`. +Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`. +Enable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to +`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`. + +5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you +have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT +to VmaAllocatorCreateInfo::flags. + +\section vk_amd_device_coherent_memory_usage Usage + +After following steps described above, you can create VMA allocations and custom pools +out of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible +devices. There are multiple ways to do it, for example: + +- You can request or prefer to allocate out of such memory types by adding + `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags + or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with + other ways of \ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage. +- If you manually found memory type index to use for this purpose, force allocation + from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1u << index`. + +\section vk_amd_device_coherent_memory_more_information More information + +To learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_AMD_device_coherent_memory.html) + +Example use of this extension can be found in the code of the sample and test suite +accompanying this library. + + +\page enabling_buffer_device_address Enabling buffer device address + +Device extension VK_KHR_buffer_device_address +allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code. +It is promoted to core Vulkan 1.2. + +If you want to use this feature in connection with VMA, follow these steps: + +\section enabling_buffer_device_address_initialization Initialization + +1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device. +Check if the extension is supported - if returned array of `VkExtensionProperties` contains +"VK_KHR_buffer_device_address". + +2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`. +Attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned. +Check if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress` is true. + +3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add +"VK_KHR_buffer_device_address" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`. + +4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`. +Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`. +Enable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to +`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`. + +5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you +have enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT +to VmaAllocatorCreateInfo::flags. + +\section enabling_buffer_device_address_usage Usage + +After following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA. +The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to +allocated memory blocks wherever it might be needed. + +Please note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`. +The second part of this functionality related to "capture and replay" is not supported, +as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage. + +\section enabling_buffer_device_address_more_information More information + +To learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address) + +Example use of this extension can be found in the code of the sample and test suite +accompanying this library. + +\page general_considerations General considerations + +\section general_considerations_thread_safety Thread safety + +- The library has no global state, so separate #VmaAllocator objects can be used + independently. + There should be no need to create multiple such objects though - one per `VkDevice` is enough. +- By default, all calls to functions that take #VmaAllocator as first parameter + are safe to call from multiple threads simultaneously because they are + synchronized internally when needed. + This includes allocation and deallocation from default memory pool, as well as custom #VmaPool. +- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT + flag, calls to functions that take such #VmaAllocator object must be + synchronized externally. +- Access to a #VmaAllocation object must be externally synchronized. For example, + you must not call vmaGetAllocationInfo() and vmaMapMemory() from different + threads at the same time if you pass the same #VmaAllocation object to these + functions. +- #VmaVirtualBlock is also not safe to be used from multiple threads simultaneously. + +\section general_considerations_validation_layer_warnings Validation layer warnings + +When using this library, you can meet following types of warnings issued by +Vulkan validation layer. They don't necessarily indicate a bug, so you may need +to just ignore them. + +- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.* + - It happens when VK_KHR_dedicated_allocation extension is enabled. + `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it. +- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.* + - It happens when you map a buffer or image, because the library maps entire + `VkDeviceMemory` block, where different types of images and buffers may end + up together, especially on GPUs with unified memory like Intel. +- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.* + - It may happen when you use [defragmentation](@ref defragmentation). + +\section general_considerations_allocation_algorithm Allocation algorithm + +The library uses following algorithm for allocation, in order: + +-# Try to find free range of memory in existing blocks. +-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size. +-# If failed, try to create such block with size/2, size/4, size/8. +-# If failed, try to allocate separate `VkDeviceMemory` for this allocation, + just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +-# If failed, choose other memory type that meets the requirements specified in + VmaAllocationCreateInfo and go to point 1. +-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + +\section general_considerations_features_not_supported Features not supported + +Features deliberately excluded from the scope of this library: + +- **Data transfer.** Uploading (streaming) and downloading data of buffers and images + between CPU and GPU memory and related synchronization is responsibility of the user. + Defining some "texture" object that would automatically stream its data from a + staging copy in CPU memory to GPU memory would rather be a feature of another, + higher-level library implemented on top of VMA. +- **Recreation of buffers and images.** Although the library has functions for + buffer and image creation (vmaCreateBuffer(), vmaCreateImage()), you need to + recreate these objects yourself after defragmentation. That is because the big + structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in + #VmaAllocation object. +- **Handling CPU memory allocation failures.** When dynamically creating small C++ + objects in CPU memory (not Vulkan memory), allocation failures are not checked + and handled gracefully, because that would complicate code significantly and + is usually not needed in desktop PC applications anyway. + Success of an allocation is just checked with an assert. +- **Code free of any compiler warnings.** Maintaining the library to compile and + work correctly on so many different platforms is hard enough. Being free of + any warnings, on any version of any compiler, is simply not feasible. + There are many preprocessor macros that make some variables unused, function parameters unreferenced, + or conditional expressions constant in some configurations. + The code of this library should not be bigger or more complicated just to silence these warnings. + It is recommended to disable such warnings instead. +- This is a C++ library with C interface. **Bindings or ports to any other programming languages** are welcome as external projects but + are not going to be included into this repository. +*/ diff --git a/third_party/vulkan/vk_platform.h b/third_party/vulkan/vk_platform.h index 728929924..18b913abc 100644 --- a/third_party/vulkan/vk_platform.h +++ b/third_party/vulkan/vk_platform.h @@ -2,19 +2,9 @@ // File: vk_platform.h // /* -** Copyright (c) 2014-2017 The Khronos Group Inc. +** Copyright 2014-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ @@ -68,7 +58,9 @@ extern "C" #define VKAPI_PTR #endif -#include +#if !defined(VK_NO_STDDEF_H) + #include +#endif // !defined(VK_NO_STDDEF_H) #if !defined(VK_NO_STDINT_H) #if defined(_MSC_VER) && (_MSC_VER < 1600) diff --git a/third_party/vulkan/vulkan.h b/third_party/vulkan/vulkan.h index d05c8490a..3f7cdba58 100644 --- a/third_party/vulkan/vulkan.h +++ b/third_party/vulkan/vulkan.h @@ -2,19 +2,9 @@ #define VULKAN_H_ 1 /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ #include "vk_platform.h" @@ -24,6 +14,10 @@ #include "vulkan_android.h" #endif +#ifdef VK_USE_PLATFORM_FUCHSIA +#include +#include "vulkan_fuchsia.h" +#endif #ifdef VK_USE_PLATFORM_IOS_MVK #include "vulkan_ios.h" @@ -34,13 +28,10 @@ #include "vulkan_macos.h" #endif - -#ifdef VK_USE_PLATFORM_MIR_KHR -#include -#include "vulkan_mir.h" +#ifdef VK_USE_PLATFORM_METAL_EXT +#include "vulkan_metal.h" #endif - #ifdef VK_USE_PLATFORM_VI_NN #include "vulkan_vi.h" #endif @@ -70,10 +61,32 @@ #endif +#ifdef VK_USE_PLATFORM_DIRECTFB_EXT +#include +#include "vulkan_directfb.h" +#endif + + #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT #include #include #include "vulkan_xlib_xrandr.h" #endif + +#ifdef VK_USE_PLATFORM_GGP +#include +#include "vulkan_ggp.h" +#endif + + +#ifdef VK_USE_PLATFORM_SCREEN_QNX +#include +#include "vulkan_screen.h" +#endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include "vulkan_beta.h" +#endif + #endif // VULKAN_H_ diff --git a/third_party/vulkan/vulkan_android.h b/third_party/vulkan/vulkan_android.h index 07aaeda28..a8a830673 100644 --- a/third_party/vulkan/vulkan_android.h +++ b/third_party/vulkan/vulkan_android.h @@ -1,24 +1,10 @@ #ifndef VULKAN_ANDROID_H_ #define VULKAN_ANDROID_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,14 +13,17 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_KHR_android_surface 1 struct ANativeWindow; - #define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 #define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" - typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; - typedef struct VkAndroidSurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -42,7 +31,6 @@ typedef struct VkAndroidSurfaceCreateInfoKHR { struct ANativeWindow* window; } VkAndroidSurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES @@ -53,12 +41,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR( VkSurfaceKHR* pSurface); #endif + #define VK_ANDROID_external_memory_android_hardware_buffer 1 struct AHardwareBuffer; - -#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3 +#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 4 #define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer" - typedef struct VkAndroidHardwareBufferUsageANDROID { VkStructureType sType; void* pNext; @@ -103,6 +90,18 @@ typedef struct VkExternalFormatANDROID { uint64_t externalFormat; } VkExternalFormatANDROID; +typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID { + VkStructureType sType; + void* pNext; + VkFormat format; + uint64_t externalFormat; + VkFormatFeatureFlags2KHR formatFeatures; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkAndroidHardwareBufferFormatProperties2ANDROID; typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer); diff --git a/third_party/vulkan/vulkan_beta.h b/third_party/vulkan/vulkan_beta.h new file mode 100644 index 000000000..d2f34d1cd --- /dev/null +++ b/third_party/vulkan/vulkan_beta.h @@ -0,0 +1,833 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_KHR_video_queue 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionKHR) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkVideoSessionParametersKHR) +#define VK_KHR_VIDEO_QUEUE_SPEC_VERSION 2 +#define VK_KHR_VIDEO_QUEUE_EXTENSION_NAME "VK_KHR_video_queue" + +typedef enum VkQueryResultStatusKHR { + VK_QUERY_RESULT_STATUS_ERROR_KHR = -1, + VK_QUERY_RESULT_STATUS_NOT_READY_KHR = 0, + VK_QUERY_RESULT_STATUS_COMPLETE_KHR = 1, + VK_QUERY_RESULT_STATUS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkQueryResultStatusKHR; + +typedef enum VkVideoCodecOperationFlagBitsKHR { + VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR = 0, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT = 0x00010000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT = 0x00020000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT = 0x00000001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT = 0x00000002, +#endif + VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodecOperationFlagBitsKHR; +typedef VkFlags VkVideoCodecOperationFlagsKHR; + +typedef enum VkVideoChromaSubsamplingFlagBitsKHR { + VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR = 0, + VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR = 0x00000001, + VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR = 0x00000002, + VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR = 0x00000004, + VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR = 0x00000008, + VK_VIDEO_CHROMA_SUBSAMPLING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoChromaSubsamplingFlagBitsKHR; +typedef VkFlags VkVideoChromaSubsamplingFlagsKHR; + +typedef enum VkVideoComponentBitDepthFlagBitsKHR { + VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR = 0, + VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR = 0x00000001, + VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR = 0x00000004, + VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR = 0x00000010, + VK_VIDEO_COMPONENT_BIT_DEPTH_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoComponentBitDepthFlagBitsKHR; +typedef VkFlags VkVideoComponentBitDepthFlagsKHR; + +typedef enum VkVideoCapabilityFlagBitsKHR { + VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR = 0x00000002, + VK_VIDEO_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCapabilityFlagBitsKHR; +typedef VkFlags VkVideoCapabilityFlagsKHR; + +typedef enum VkVideoSessionCreateFlagBitsKHR { + VK_VIDEO_SESSION_CREATE_DEFAULT_KHR = 0, + VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR = 0x00000001, + VK_VIDEO_SESSION_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoSessionCreateFlagBitsKHR; +typedef VkFlags VkVideoSessionCreateFlagsKHR; +typedef VkFlags VkVideoBeginCodingFlagsKHR; +typedef VkFlags VkVideoEndCodingFlagsKHR; + +typedef enum VkVideoCodingControlFlagBitsKHR { + VK_VIDEO_CODING_CONTROL_DEFAULT_KHR = 0, + VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR = 0x00000001, + VK_VIDEO_CODING_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingControlFlagBitsKHR; +typedef VkFlags VkVideoCodingControlFlagsKHR; + +typedef enum VkVideoCodingQualityPresetFlagBitsKHR { + VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR = 0x00000001, + VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR = 0x00000002, + VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR = 0x00000004, + VK_VIDEO_CODING_QUALITY_PRESET_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoCodingQualityPresetFlagBitsKHR; +typedef VkFlags VkVideoCodingQualityPresetFlagsKHR; +typedef struct VkVideoQueueFamilyProperties2KHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagsKHR videoCodecOperations; +} VkVideoQueueFamilyProperties2KHR; + +typedef struct VkVideoProfileKHR { + VkStructureType sType; + void* pNext; + VkVideoCodecOperationFlagBitsKHR videoCodecOperation; + VkVideoChromaSubsamplingFlagsKHR chromaSubsampling; + VkVideoComponentBitDepthFlagsKHR lumaBitDepth; + VkVideoComponentBitDepthFlagsKHR chromaBitDepth; +} VkVideoProfileKHR; + +typedef struct VkVideoProfilesKHR { + VkStructureType sType; + void* pNext; + uint32_t profileCount; + const VkVideoProfileKHR* pProfiles; +} VkVideoProfilesKHR; + +typedef struct VkVideoCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoCapabilityFlagsKHR capabilityFlags; + VkDeviceSize minBitstreamBufferOffsetAlignment; + VkDeviceSize minBitstreamBufferSizeAlignment; + VkExtent2D videoPictureExtentGranularity; + VkExtent2D minExtent; + VkExtent2D maxExtent; + uint32_t maxReferencePicturesSlotsCount; + uint32_t maxReferencePicturesActiveCount; +} VkVideoCapabilitiesKHR; + +typedef struct VkPhysicalDeviceVideoFormatInfoKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags imageUsage; + const VkVideoProfilesKHR* pVideoProfiles; +} VkPhysicalDeviceVideoFormatInfoKHR; + +typedef struct VkVideoFormatPropertiesKHR { + VkStructureType sType; + void* pNext; + VkFormat format; +} VkVideoFormatPropertiesKHR; + +typedef struct VkVideoPictureResourceKHR { + VkStructureType sType; + const void* pNext; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + uint32_t baseArrayLayer; + VkImageView imageViewBinding; +} VkVideoPictureResourceKHR; + +typedef struct VkVideoReferenceSlotKHR { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const VkVideoPictureResourceKHR* pPictureResource; +} VkVideoReferenceSlotKHR; + +typedef struct VkVideoGetMemoryPropertiesKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryBindIndex; + VkMemoryRequirements2* pMemoryRequirements; +} VkVideoGetMemoryPropertiesKHR; + +typedef struct VkVideoBindMemoryKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryBindIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkDeviceSize memorySize; +} VkVideoBindMemoryKHR; + +typedef struct VkVideoSessionCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkVideoSessionCreateFlagsKHR flags; + const VkVideoProfileKHR* pVideoProfile; + VkFormat pictureFormat; + VkExtent2D maxCodedExtent; + VkFormat referencePicturesFormat; + uint32_t maxReferencePicturesSlotsCount; + uint32_t maxReferencePicturesActiveCount; +} VkVideoSessionCreateInfoKHR; + +typedef struct VkVideoSessionParametersCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoSessionParametersKHR videoSessionParametersTemplate; + VkVideoSessionKHR videoSession; +} VkVideoSessionParametersCreateInfoKHR; + +typedef struct VkVideoSessionParametersUpdateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t updateSequenceCount; +} VkVideoSessionParametersUpdateInfoKHR; + +typedef struct VkVideoBeginCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoBeginCodingFlagsKHR flags; + VkVideoCodingQualityPresetFlagsKHR codecQualityPreset; + VkVideoSessionKHR videoSession; + VkVideoSessionParametersKHR videoSessionParameters; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoBeginCodingInfoKHR; + +typedef struct VkVideoEndCodingInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEndCodingFlagsKHR flags; +} VkVideoEndCodingInfoKHR; + +typedef struct VkVideoCodingControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoCodingControlFlagsKHR flags; +} VkVideoCodingControlInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)(VkPhysicalDevice physicalDevice, const VkVideoProfileKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionKHR)(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionKHR)(VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetVideoSessionMemoryRequirementsKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pVideoSessionMemoryRequirementsCount, VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindVideoSessionMemoryKHR)(VkDevice device, VkVideoSessionKHR videoSession, uint32_t videoSessionBindMemoryCount, const VkVideoBindMemoryKHR* pVideoSessionBindMemories); +typedef VkResult (VKAPI_PTR *PFN_vkCreateVideoSessionParametersKHR)(VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); +typedef VkResult (VKAPI_PTR *PFN_vkUpdateVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyVideoSessionParametersKHR)(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + const VkVideoProfileKHR* pVideoProfile, + VkVideoCapabilitiesKHR* pCapabilities); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, + uint32_t* pVideoFormatPropertyCount, + VkVideoFormatPropertiesKHR* pVideoFormatProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( + VkDevice device, + const VkVideoSessionCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionKHR* pVideoSession); + +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + uint32_t* pVideoSessionMemoryRequirementsCount, + VkVideoGetMemoryPropertiesKHR* pVideoSessionMemoryRequirements); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( + VkDevice device, + VkVideoSessionKHR videoSession, + uint32_t videoSessionBindMemoryCount, + const VkVideoBindMemoryKHR* pVideoSessionBindMemories); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( + VkDevice device, + const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkVideoSessionParametersKHR* pVideoSessionParameters); + +VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); + +VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( + VkDevice device, + VkVideoSessionParametersKHR videoSessionParameters, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoBeginCodingInfoKHR* pBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoEndCodingInfoKHR* pEndCodingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( + VkCommandBuffer commandBuffer, + const VkVideoCodingControlInfoKHR* pCodingControlInfo); +#endif + + +#define VK_KHR_video_decode_queue 1 +#define VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION 2 +#define VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME "VK_KHR_video_decode_queue" + +typedef enum VkVideoDecodeFlagBitsKHR { + VK_VIDEO_DECODE_DEFAULT_KHR = 0, + VK_VIDEO_DECODE_RESERVED_0_BIT_KHR = 0x00000001, + VK_VIDEO_DECODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoDecodeFlagBitsKHR; +typedef VkFlags VkVideoDecodeFlagsKHR; +typedef struct VkVideoDecodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoDecodeFlagsKHR flags; + VkOffset2D codedOffset; + VkExtent2D codedExtent; + VkBuffer srcBuffer; + VkDeviceSize srcBufferOffset; + VkDeviceSize srcBufferRange; + VkVideoPictureResourceKHR dstPictureResource; + const VkVideoReferenceSlotKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoDecodeInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pFrameInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( + VkCommandBuffer commandBuffer, + const VkVideoDecodeInfoKHR* pFrameInfo); +#endif + + +#define VK_KHR_portability_subset 1 +#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 constantAlphaColorBlendFactors; + VkBool32 events; + VkBool32 imageViewFormatReinterpretation; + VkBool32 imageViewFormatSwizzle; + VkBool32 imageView2DOn3DImage; + VkBool32 multisampleArrayImage; + VkBool32 mutableComparisonSamplers; + VkBool32 pointPolygons; + VkBool32 samplerMipLodBias; + VkBool32 separateStencilMaskRef; + VkBool32 shaderSampleRateInterpolationFunctions; + VkBool32 tessellationIsolines; + VkBool32 tessellationPointMode; + VkBool32 triangleFans; + VkBool32 vertexAttributeAccessBeyondStride; +} VkPhysicalDevicePortabilitySubsetFeaturesKHR; + +typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t minVertexInputBindingStrideAlignment; +} VkPhysicalDevicePortabilitySubsetPropertiesKHR; + + + +#define VK_KHR_video_encode_queue 1 +#define VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION 3 +#define VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME "VK_KHR_video_encode_queue" + +typedef enum VkVideoEncodeFlagBitsKHR { + VK_VIDEO_ENCODE_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeFlagBitsKHR; +typedef VkFlags VkVideoEncodeFlagsKHR; + +typedef enum VkVideoEncodeRateControlFlagBitsKHR { + VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_RESET_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_RATE_CONTROL_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeRateControlFlagBitsKHR; +typedef VkFlags VkVideoEncodeRateControlFlagsKHR; + +typedef enum VkVideoEncodeRateControlModeFlagBitsKHR { + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR = 0, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR = 1, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR = 2, + VK_VIDEO_ENCODE_RATE_CONTROL_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeRateControlModeFlagBitsKHR; +typedef VkFlags VkVideoEncodeRateControlModeFlagsKHR; +typedef struct VkVideoEncodeInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeFlagsKHR flags; + uint32_t qualityLevel; + VkExtent2D codedExtent; + VkBuffer dstBitstreamBuffer; + VkDeviceSize dstBitstreamBufferOffset; + VkDeviceSize dstBitstreamBufferMaxRange; + VkVideoPictureResourceKHR srcPictureResource; + const VkVideoReferenceSlotKHR* pSetupReferenceSlot; + uint32_t referenceSlotCount; + const VkVideoReferenceSlotKHR* pReferenceSlots; +} VkVideoEncodeInfoKHR; + +typedef struct VkVideoEncodeRateControlInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeRateControlFlagsKHR flags; + VkVideoEncodeRateControlModeFlagBitsKHR rateControlMode; + uint32_t averageBitrate; + uint16_t peakToAverageBitrateRatio; + uint16_t frameRateNumerator; + uint16_t frameRateDenominator; + uint32_t virtualBufferSizeInMs; +} VkVideoEncodeRateControlInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( + VkCommandBuffer commandBuffer, + const VkVideoEncodeInfoKHR* pEncodeInfo); +#endif + + +#define VK_EXT_video_encode_h264 1 +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_encode.h" +#define VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION 2 +#define VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME "VK_EXT_video_encode_h264" + +typedef enum VkVideoEncodeH264CapabilityFlagBitsEXT { + VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BI_PRED_IMPLICIT_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT = 0x00000010, + VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT = 0x00000020, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT = 0x00000040, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT = 0x00000080, + VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT = 0x00000200, + VK_VIDEO_ENCODE_H264_CAPABILITY_EVENLY_DISTRIBUTED_SLICE_SIZE_BIT_EXT = 0x00000400, + VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264CapabilityFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264CapabilityFlagsEXT; + +typedef enum VkVideoEncodeH264InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264InputModeFlagsEXT; + +typedef enum VkVideoEncodeH264OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264OutputModeFlagsEXT; + +typedef enum VkVideoEncodeH264CreateFlagBitsEXT { + VK_VIDEO_ENCODE_H264_CREATE_DEFAULT_EXT = 0, + VK_VIDEO_ENCODE_H264_CREATE_RESERVED_0_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H264_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH264CreateFlagBitsEXT; +typedef VkFlags VkVideoEncodeH264CreateFlagsEXT; +typedef struct VkVideoEncodeH264CapabilitiesEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264CapabilityFlagsEXT flags; + VkVideoEncodeH264InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH264OutputModeFlagsEXT outputModeFlags; + VkExtent2D minPictureSizeInMbs; + VkExtent2D maxPictureSizeInMbs; + VkExtent2D inputImageDataAlignment; + uint8_t maxNumL0ReferenceForP; + uint8_t maxNumL0ReferenceForB; + uint8_t maxNumL1Reference; + uint8_t qualityLevelCount; + VkExtensionProperties stdExtensionVersion; +} VkVideoEncodeH264CapabilitiesEXT; + +typedef struct VkVideoEncodeH264SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH264CreateFlagsEXT flags; + VkExtent2D maxPictureSizeInMbs; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoEncodeH264SessionCreateInfoEXT; + +typedef struct VkVideoEncodeH264SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH264SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH264PictureParameterSet* pPpsStd; +} VkVideoEncodeH264SessionParametersAddInfoEXT; + +typedef struct VkVideoEncodeH264SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoEncodeH264SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoEncodeH264SessionParametersCreateInfoEXT; + +typedef struct VkVideoEncodeH264DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const StdVideoEncodeH264PictureInfo* pStdPictureInfo; +} VkVideoEncodeH264DpbSlotInfoEXT; + +typedef struct VkVideoEncodeH264NaluSliceEXT { + VkStructureType sType; + const void* pNext; + const StdVideoEncodeH264SliceHeader* pSliceHeaderStd; + uint32_t mbCount; + uint8_t refFinalList0EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList0Entries; + uint8_t refFinalList1EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefFinalList1Entries; + uint32_t precedingNaluBytes; + uint8_t minQp; + uint8_t maxQp; +} VkVideoEncodeH264NaluSliceEXT; + +typedef struct VkVideoEncodeH264VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + uint8_t refDefaultFinalList0EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList0Entries; + uint8_t refDefaultFinalList1EntryCount; + const VkVideoEncodeH264DpbSlotInfoEXT* pRefDefaultFinalList1Entries; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH264NaluSliceEXT* pNaluSliceEntries; + const VkVideoEncodeH264DpbSlotInfoEXT* pCurrentPictureInfo; +} VkVideoEncodeH264VclFrameInfoEXT; + +typedef struct VkVideoEncodeH264EmitPictureParametersEXT { + VkStructureType sType; + const void* pNext; + uint8_t spsId; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH264EmitPictureParametersEXT; + +typedef struct VkVideoEncodeH264ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; +} VkVideoEncodeH264ProfileEXT; + + + +#define VK_EXT_video_encode_h265 1 +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_encode.h" +#define VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION 2 +#define VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME "VK_EXT_video_encode_h265" +typedef VkFlags VkVideoEncodeH265CapabilityFlagsEXT; + +typedef enum VkVideoEncodeH265InputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_INPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265InputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265InputModeFlagsEXT; + +typedef enum VkVideoEncodeH265OutputModeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265OutputModeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265OutputModeFlagsEXT; +typedef VkFlags VkVideoEncodeH265CreateFlagsEXT; + +typedef enum VkVideoEncodeH265CtbSizeFlagBitsEXT { + VK_VIDEO_ENCODE_H265_CTB_SIZE_8_BIT_EXT = 0x00000001, + VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT = 0x00000002, + VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT = 0x00000004, + VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT = 0x00000008, + VK_VIDEO_ENCODE_H265_CTB_SIZE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoEncodeH265CtbSizeFlagBitsEXT; +typedef VkFlags VkVideoEncodeH265CtbSizeFlagsEXT; +typedef struct VkVideoEncodeH265CapabilitiesEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH265CapabilityFlagsEXT flags; + VkVideoEncodeH265InputModeFlagsEXT inputModeFlags; + VkVideoEncodeH265OutputModeFlagsEXT outputModeFlags; + VkVideoEncodeH265CtbSizeFlagsEXT ctbSizes; + VkExtent2D inputImageDataAlignment; + uint8_t maxNumL0ReferenceForP; + uint8_t maxNumL0ReferenceForB; + uint8_t maxNumL1Reference; + uint8_t maxNumSubLayers; + uint8_t qualityLevelCount; + VkExtensionProperties stdExtensionVersion; +} VkVideoEncodeH265CapabilitiesEXT; + +typedef struct VkVideoEncodeH265SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoEncodeH265CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoEncodeH265SessionCreateInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t vpsStdCount; + const StdVideoH265VideoParameterSet* pVpsStd; + uint32_t spsStdCount; + const StdVideoH265SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH265PictureParameterSet* pPpsStd; +} VkVideoEncodeH265SessionParametersAddInfoEXT; + +typedef struct VkVideoEncodeH265SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxVpsStdCount; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoEncodeH265SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoEncodeH265SessionParametersCreateInfoEXT; + +typedef struct VkVideoEncodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + int8_t slotIndex; + const StdVideoEncodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoEncodeH265DpbSlotInfoEXT; + +typedef struct VkVideoEncodeH265ReferenceListsEXT { + VkStructureType sType; + const void* pNext; + uint8_t referenceList0EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList0Entries; + uint8_t referenceList1EntryCount; + const VkVideoEncodeH265DpbSlotInfoEXT* pReferenceList1Entries; + const StdVideoEncodeH265ReferenceModifications* pReferenceModifications; +} VkVideoEncodeH265ReferenceListsEXT; + +typedef struct VkVideoEncodeH265NaluSliceEXT { + VkStructureType sType; + const void* pNext; + uint32_t ctbCount; + const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists; + const StdVideoEncodeH265SliceHeader* pSliceHeaderStd; +} VkVideoEncodeH265NaluSliceEXT; + +typedef struct VkVideoEncodeH265VclFrameInfoEXT { + VkStructureType sType; + const void* pNext; + const VkVideoEncodeH265ReferenceListsEXT* pReferenceFinalLists; + uint32_t naluSliceEntryCount; + const VkVideoEncodeH265NaluSliceEXT* pNaluSliceEntries; + const StdVideoEncodeH265PictureInfo* pCurrentPictureInfo; +} VkVideoEncodeH265VclFrameInfoEXT; + +typedef struct VkVideoEncodeH265EmitPictureParametersEXT { + VkStructureType sType; + const void* pNext; + uint8_t vpsId; + uint8_t spsId; + VkBool32 emitVpsEnable; + VkBool32 emitSpsEnable; + uint32_t ppsIdEntryCount; + const uint8_t* ppsIdEntries; +} VkVideoEncodeH265EmitPictureParametersEXT; + +typedef struct VkVideoEncodeH265ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoEncodeH265ProfileEXT; + + + +#define VK_EXT_video_decode_h264 1 +#include "vk_video/vulkan_video_codec_h264std_decode.h" +#define VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION 3 +#define VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME "VK_EXT_video_decode_h264" + +typedef enum VkVideoDecodeH264PictureLayoutFlagBitsEXT { + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT = 0, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT = 0x00000001, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT = 0x00000002, + VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkVideoDecodeH264PictureLayoutFlagBitsEXT; +typedef VkFlags VkVideoDecodeH264PictureLayoutFlagsEXT; +typedef VkFlags VkVideoDecodeH264CreateFlagsEXT; +typedef struct VkVideoDecodeH264ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH264ProfileIdc stdProfileIdc; + VkVideoDecodeH264PictureLayoutFlagsEXT pictureLayout; +} VkVideoDecodeH264ProfileEXT; + +typedef struct VkVideoDecodeH264CapabilitiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxLevel; + VkOffset2D fieldOffsetGranularity; + VkExtensionProperties stdExtensionVersion; +} VkVideoDecodeH264CapabilitiesEXT; + +typedef struct VkVideoDecodeH264SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoDecodeH264CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoDecodeH264SessionCreateInfoEXT; + +typedef struct VkVideoDecodeH264SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH264SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH264PictureParameterSet* pPpsStd; +} VkVideoDecodeH264SessionParametersAddInfoEXT; + +typedef struct VkVideoDecodeH264SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoDecodeH264SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoDecodeH264SessionParametersCreateInfoEXT; + +typedef struct VkVideoDecodeH264PictureInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264PictureInfo* pStdPictureInfo; + uint32_t slicesCount; + const uint32_t* pSlicesDataOffsets; +} VkVideoDecodeH264PictureInfoEXT; + +typedef struct VkVideoDecodeH264MvcEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264Mvc* pStdMvc; +} VkVideoDecodeH264MvcEXT; + +typedef struct VkVideoDecodeH264DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH264ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH264DpbSlotInfoEXT; + + + +#define VK_EXT_video_decode_h265 1 +#include "vk_video/vulkan_video_codec_h265std_decode.h" +#define VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION 1 +#define VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME "VK_EXT_video_decode_h265" +typedef VkFlags VkVideoDecodeH265CreateFlagsEXT; +typedef struct VkVideoDecodeH265ProfileEXT { + VkStructureType sType; + const void* pNext; + StdVideoH265ProfileIdc stdProfileIdc; +} VkVideoDecodeH265ProfileEXT; + +typedef struct VkVideoDecodeH265CapabilitiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxLevel; + VkExtensionProperties stdExtensionVersion; +} VkVideoDecodeH265CapabilitiesEXT; + +typedef struct VkVideoDecodeH265SessionCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkVideoDecodeH265CreateFlagsEXT flags; + const VkExtensionProperties* pStdExtensionVersion; +} VkVideoDecodeH265SessionCreateInfoEXT; + +typedef struct VkVideoDecodeH265SessionParametersAddInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t spsStdCount; + const StdVideoH265SequenceParameterSet* pSpsStd; + uint32_t ppsStdCount; + const StdVideoH265PictureParameterSet* pPpsStd; +} VkVideoDecodeH265SessionParametersAddInfoEXT; + +typedef struct VkVideoDecodeH265SessionParametersCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxSpsStdCount; + uint32_t maxPpsStdCount; + const VkVideoDecodeH265SessionParametersAddInfoEXT* pParametersAddInfo; +} VkVideoDecodeH265SessionParametersCreateInfoEXT; + +typedef struct VkVideoDecodeH265PictureInfoEXT { + VkStructureType sType; + const void* pNext; + StdVideoDecodeH265PictureInfo* pStdPictureInfo; + uint32_t slicesCount; + const uint32_t* pSlicesDataOffsets; +} VkVideoDecodeH265PictureInfoEXT; + +typedef struct VkVideoDecodeH265DpbSlotInfoEXT { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeH265ReferenceInfo* pStdReferenceInfo; +} VkVideoDecodeH265DpbSlotInfoEXT; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_core.h b/third_party/vulkan/vulkan_core.h index 9fefb4382..2bd3f779e 100644 --- a/third_party/vulkan/vulkan_core.h +++ b/third_party/vulkan/vulkan_core.h @@ -1,24 +1,10 @@ #ifndef VULKAN_CORE_H_ #define VULKAN_CORE_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,47 +13,90 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_VERSION_1_0 1 #include "vk_platform.h" -#define VK_MAKE_VERSION(major, minor, patch) \ - (((major) << 22) | ((minor) << 12) | (patch)) - -// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. -//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 - -// Vulkan 1.0 version number -#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)// Patch version should always be set to 0 - -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) -// Version of this file -#define VK_HEADER_VERSION 74 - - -#define VK_NULL_HANDLE 0 - - - #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; -#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) -#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#ifndef VK_USE_64_BIT_PTR_DEFINES + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_USE_64_BIT_PTR_DEFINES 1 + #else + #define VK_USE_64_BIT_PTR_DEFINES 0 + #endif +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) + #define VK_NULL_HANDLE nullptr + #else + #define VK_NULL_HANDLE ((void*)0) + #endif + #else + #define VK_NULL_HANDLE 0ULL + #endif +#endif +#ifndef VK_NULL_HANDLE + #define VK_NULL_HANDLE 0 +#endif + + +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; -#else + #else #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif #endif -#endif - +// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. +#define VK_MAKE_VERSION(major, minor, patch) \ + ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) -typedef uint32_t VkFlags; +// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. +//#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 + +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) + +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 + +// Version of this file +#define VK_HEADER_VERSION 198 + +// Complete version of this file +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 2, VK_HEADER_VERSION) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. +#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) + +// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) typedef uint32_t VkBool32; +typedef uint64_t VkDeviceAddress; typedef uint64_t VkDeviceSize; +typedef uint32_t VkFlags; typedef uint32_t VkSampleMask; - +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_HANDLE(VkInstance) VK_DEFINE_HANDLE(VkPhysicalDevice) VK_DEFINE_HANDLE(VkDevice) @@ -76,8 +105,6 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) VK_DEFINE_HANDLE(VkCommandBuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) @@ -85,39 +112,29 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) - -#define VK_LOD_CLAMP_NONE 1000.0f -#define VK_REMAINING_MIP_LEVELS (~0U) -#define VK_REMAINING_ARRAY_LAYERS (~0U) -#define VK_WHOLE_SIZE (~0ULL) +#define VK_UUID_SIZE 16U #define VK_ATTACHMENT_UNUSED (~0U) -#define VK_TRUE 1 -#define VK_FALSE 0 +#define VK_FALSE 0U +#define VK_LOD_CLAMP_NONE 1000.0F #define VK_QUEUE_FAMILY_IGNORED (~0U) +#define VK_REMAINING_ARRAY_LAYERS (~0U) +#define VK_REMAINING_MIP_LEVELS (~0U) #define VK_SUBPASS_EXTERNAL (~0U) -#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 -#define VK_UUID_SIZE 16 -#define VK_MAX_MEMORY_TYPES 32 -#define VK_MAX_MEMORY_HEAPS 16 -#define VK_MAX_EXTENSION_NAME_SIZE 256 -#define VK_MAX_DESCRIPTION_SIZE 256 - - -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE, - VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1), - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; +#define VK_TRUE 1U +#define VK_WHOLE_SIZE (~0ULL) +#define VK_MAX_MEMORY_TYPES 32U +#define VK_MAX_MEMORY_HEAPS 16U +#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256U +#define VK_MAX_EXTENSION_NAME_SIZE 256U +#define VK_MAX_DESCRIPTION_SIZE 256U typedef enum VkResult { VK_SUCCESS = 0, @@ -138,8 +155,11 @@ typedef enum VkResult { VK_ERROR_TOO_MANY_OBJECTS = -10, VK_ERROR_FORMAT_NOT_SUPPORTED = -11, VK_ERROR_FRAGMENTED_POOL = -12, + VK_ERROR_UNKNOWN = -13, VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, + VK_ERROR_FRAGMENTATION = -1000161000, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, VK_ERROR_SURFACE_LOST_KHR = -1000000000, VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, VK_SUBOPTIMAL_KHR = 1000001003, @@ -147,13 +167,20 @@ typedef enum VkResult { VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_INVALID_SHADER_NV = -1000012000, - VK_ERROR_FRAGMENTATION_EXT = -1000161000, + VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, VK_ERROR_NOT_PERMITTED_EXT = -1000174001, + VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, + VK_THREAD_IDLE_KHR = 1000268000, + VK_THREAD_DONE_KHR = 1000268001, + VK_OPERATION_DEFERRED_KHR = 1000268002, + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, + VK_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, - VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL, - VK_RESULT_END_RANGE = VK_INCOMPLETE, - VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1), + VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, + VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED_EXT, VK_RESULT_MAX_ENUM = 0x7FFFFFFF } VkResult; @@ -243,7 +270,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = 1000120000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, @@ -271,7 +298,57 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, @@ -286,7 +363,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000, VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, - VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000, VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, @@ -294,10 +370,161 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR = 1000023001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR = 1000023002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR = 1000023003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR = 1000023004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR = 1000023009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR = 1000023011, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000023012, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR = 1000023013, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR = 1000024000, +#endif VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, + VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX = 1000029000, + VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX = 1000029001, + VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX = 1000029002, + VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT = 1000038000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_CREATE_INFO_EXT = 1000038001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000038002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000038003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT = 1000038004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT = 1000038005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT = 1000038006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT = 1000038007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT = 1000038008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT = 1000039000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_CREATE_INFO_EXT = 1000039001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000039002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000039003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT = 1000039004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT = 1000039005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_EXT = 1000039006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT = 1000039007, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT = 1000039008, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT = 1000039009, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT = 1000040000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_CREATE_INFO_EXT = 1000040001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT = 1000040002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT = 1000040003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT = 1000040004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000040005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT = 1000040006, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT = 1000040007, +#endif VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = 1000044004, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, + VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, @@ -305,6 +532,9 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000, VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = 1000066000, + VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, @@ -320,13 +550,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, + VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, - VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000, - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001, - VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002, - VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, @@ -340,6 +567,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000, VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001, VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000, VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, @@ -347,9 +576,21 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000, VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001, + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002, + VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003, + VK_STRUCTURE_TYPE_ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR = 1000116005, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001, VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002, + VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR = 1000121000, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001, + VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR = 1000121003, + VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004, VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, @@ -363,33 +604,312 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000, - VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003, VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004, - VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = 1000147000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, + VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = 1000161000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = 1000161001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, +#endif + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001, + VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003, + VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004, + VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV = 1000165012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000, + VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, + VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000, + VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, + VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT = 1000184000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT = 1000187000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_CREATE_INFO_EXT = 1000187001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT = 1000187002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT = 1000187003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT = 1000187004, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT = 1000187005, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT = 1000187006, +#endif + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002, + VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP = 1000191000, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, + VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, + VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, + VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002, + VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003, + VK_STRUCTURE_TYPE_PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004, + VK_STRUCTURE_TYPE_PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000, + VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, + VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, + VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = 1000215000, + VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = 1000225000, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = 1000225001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = 1000225002, + VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, + VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, + VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = 1000245000, + VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT = 1000247000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, + VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000, + VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002, + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, + VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, + VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = 1000259000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, + VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, + VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, + VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = 1000280001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, + VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PRESENT_ID_KHR = 1000294000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = 1000295000, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = 1000295001, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = 1000295002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = 1000314007, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, + VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = 1000335000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, + VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = 1000351000, + VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = 1000351002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, + VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, + VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = 1000360000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, + VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, + VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, + VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, + VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, + VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, + VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, + VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, + VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, + VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, + VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, + VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = 1000388000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = 1000388001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, + VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = 1000413003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, + VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD, VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, @@ -422,8 +942,22 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR = VK_STRUCTURE_TYPE_SUBPASS_END_INFO, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, @@ -431,14 +965,18 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, @@ -447,31 +985,177 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, - VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO, - VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, - VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1), + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, + VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; +typedef enum VkImageLayout { + VK_IMAGE_LAYOUT_UNDEFINED = 0, + VK_IMAGE_LAYOUT_GENERAL = 1, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, + VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, +#endif + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, +#endif + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = 1000314001, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + +typedef enum VkObjectType { + VK_OBJECT_TYPE_UNKNOWN = 0, + VK_OBJECT_TYPE_INSTANCE = 1, + VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, + VK_OBJECT_TYPE_DEVICE = 3, + VK_OBJECT_TYPE_QUEUE = 4, + VK_OBJECT_TYPE_SEMAPHORE = 5, + VK_OBJECT_TYPE_COMMAND_BUFFER = 6, + VK_OBJECT_TYPE_FENCE = 7, + VK_OBJECT_TYPE_DEVICE_MEMORY = 8, + VK_OBJECT_TYPE_BUFFER = 9, + VK_OBJECT_TYPE_IMAGE = 10, + VK_OBJECT_TYPE_EVENT = 11, + VK_OBJECT_TYPE_QUERY_POOL = 12, + VK_OBJECT_TYPE_BUFFER_VIEW = 13, + VK_OBJECT_TYPE_IMAGE_VIEW = 14, + VK_OBJECT_TYPE_SHADER_MODULE = 15, + VK_OBJECT_TYPE_PIPELINE_CACHE = 16, + VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, + VK_OBJECT_TYPE_RENDER_PASS = 18, + VK_OBJECT_TYPE_PIPELINE = 19, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, + VK_OBJECT_TYPE_SAMPLER = 21, + VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, + VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, + VK_OBJECT_TYPE_FRAMEBUFFER = 24, + VK_OBJECT_TYPE_COMMAND_POOL = 25, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, + VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, + VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, + VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_KHR = 1000023000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR = 1000023001, +#endif + VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000, + VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001, + VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, + VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = 1000295000, + VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, + VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkObjectType; + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + +typedef enum VkVendorId { + VK_VENDOR_ID_VIV = 0x10001, + VK_VENDOR_ID_VSI = 0x10002, + VK_VENDOR_ID_KAZAN = 0x10003, + VK_VENDOR_ID_CODEPLAY = 0x10004, + VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF +} VkVendorId; + typedef enum VkSystemAllocationScope { VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, - VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND, - VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, - VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1), VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF } VkSystemAllocationScope; typedef enum VkInternalAllocationType { VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, - VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1), VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF } VkInternalAllocationType; @@ -703,6 +1387,26 @@ typedef enum VkFormat { VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = 1000066000, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = 1000066001, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = 1000066002, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT = 1000066003, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT = 1000066004, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT = 1000066005, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT = 1000066006, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT = 1000066007, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT = 1000066008, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT = 1000066009, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT = 1000066010, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT = 1000066011, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT = 1000066012, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT = 1000066013, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT = 1000330000, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT = 1000330001, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT = 1000330002, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = 1000330003, + VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = 1000340001, VK_FORMAT_G8B8G8R8_422_UNORM_KHR = VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_B8G8R8G8_422_UNORM_KHR = VK_FORMAT_B8G8R8G8_422_UNORM, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, @@ -737,40 +1441,29 @@ typedef enum VkFormat { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, - VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED, - VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, - VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1), VK_FORMAT_MAX_ENUM = 0x7FFFFFFF } VkFormat; +typedef enum VkImageTiling { + VK_IMAGE_TILING_OPTIMAL = 0, + VK_IMAGE_TILING_LINEAR = 1, + VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000, + VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF +} VkImageTiling; + typedef enum VkImageType { VK_IMAGE_TYPE_1D = 0, VK_IMAGE_TYPE_2D = 1, VK_IMAGE_TYPE_3D = 2, - VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D, - VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D, - VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1), VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkImageType; -typedef enum VkImageTiling { - VK_IMAGE_TILING_OPTIMAL = 0, - VK_IMAGE_TILING_LINEAR = 1, - VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR, - VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1), - VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF -} VkImageTiling; - typedef enum VkPhysicalDeviceType { VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, VK_PHYSICAL_DEVICE_TYPE_CPU = 4, - VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER, - VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU, - VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1), VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkPhysicalDeviceType; @@ -778,57 +1471,27 @@ typedef enum VkQueryType { VK_QUERY_TYPE_OCCLUSION = 0, VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, VK_QUERY_TYPE_TIMESTAMP = 2, - VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, - VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, - VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR = 1000023000, +#endif + VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, + VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, + VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000, +#endif VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } VkQueryType; typedef enum VkSharingMode { VK_SHARING_MODE_EXCLUSIVE = 0, VK_SHARING_MODE_CONCURRENT = 1, - VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE, - VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT, - VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1), VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF } VkSharingMode; -typedef enum VkImageLayout { - VK_IMAGE_LAYOUT_UNDEFINED = 0, - VK_IMAGE_LAYOUT_GENERAL = 1, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, - VK_IMAGE_LAYOUT_PREINITIALIZED = 8, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED, - VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1), - VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF -} VkImageLayout; - -typedef enum VkImageViewType { - VK_IMAGE_VIEW_TYPE_1D = 0, - VK_IMAGE_VIEW_TYPE_2D = 1, - VK_IMAGE_VIEW_TYPE_3D = 2, - VK_IMAGE_VIEW_TYPE_CUBE = 3, - VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, - VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, - VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, - VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D, - VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, - VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1), - VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkImageViewType; - typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_IDENTITY = 0, VK_COMPONENT_SWIZZLE_ZERO = 1, @@ -837,111 +1500,19 @@ typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_G = 4, VK_COMPONENT_SWIZZLE_B = 5, VK_COMPONENT_SWIZZLE_A = 6, - VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A, - VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1), VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF } VkComponentSwizzle; -typedef enum VkVertexInputRate { - VK_VERTEX_INPUT_RATE_VERTEX = 0, - VK_VERTEX_INPUT_RATE_INSTANCE = 1, - VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX, - VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE, - VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1), - VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF -} VkVertexInputRate; - -typedef enum VkPrimitiveTopology { - VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, - VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, - VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, - VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, - VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, - VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1), - VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF -} VkPrimitiveTopology; - -typedef enum VkPolygonMode { - VK_POLYGON_MODE_FILL = 0, - VK_POLYGON_MODE_LINE = 1, - VK_POLYGON_MODE_POINT = 2, - VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, - VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL, - VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT, - VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1), - VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF -} VkPolygonMode; - -typedef enum VkFrontFace { - VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, - VK_FRONT_FACE_CLOCKWISE = 1, - VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE, - VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE, - VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1), - VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF -} VkFrontFace; - -typedef enum VkCompareOp { - VK_COMPARE_OP_NEVER = 0, - VK_COMPARE_OP_LESS = 1, - VK_COMPARE_OP_EQUAL = 2, - VK_COMPARE_OP_LESS_OR_EQUAL = 3, - VK_COMPARE_OP_GREATER = 4, - VK_COMPARE_OP_NOT_EQUAL = 5, - VK_COMPARE_OP_GREATER_OR_EQUAL = 6, - VK_COMPARE_OP_ALWAYS = 7, - VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER, - VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS, - VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1), - VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF -} VkCompareOp; - -typedef enum VkStencilOp { - VK_STENCIL_OP_KEEP = 0, - VK_STENCIL_OP_ZERO = 1, - VK_STENCIL_OP_REPLACE = 2, - VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, - VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, - VK_STENCIL_OP_INVERT = 5, - VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, - VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP, - VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP, - VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1), - VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF -} VkStencilOp; - -typedef enum VkLogicOp { - VK_LOGIC_OP_CLEAR = 0, - VK_LOGIC_OP_AND = 1, - VK_LOGIC_OP_AND_REVERSE = 2, - VK_LOGIC_OP_COPY = 3, - VK_LOGIC_OP_AND_INVERTED = 4, - VK_LOGIC_OP_NO_OP = 5, - VK_LOGIC_OP_XOR = 6, - VK_LOGIC_OP_OR = 7, - VK_LOGIC_OP_NOR = 8, - VK_LOGIC_OP_EQUIVALENT = 9, - VK_LOGIC_OP_INVERT = 10, - VK_LOGIC_OP_OR_REVERSE = 11, - VK_LOGIC_OP_COPY_INVERTED = 12, - VK_LOGIC_OP_OR_INVERTED = 13, - VK_LOGIC_OP_NAND = 14, - VK_LOGIC_OP_SET = 15, - VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR, - VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET, - VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1), - VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF -} VkLogicOp; +typedef enum VkImageViewType { + VK_IMAGE_VIEW_TYPE_1D = 0, + VK_IMAGE_VIEW_TYPE_2D = 1, + VK_IMAGE_VIEW_TYPE_3D = 2, + VK_IMAGE_VIEW_TYPE_CUBE = 3, + VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, + VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkImageViewType; typedef enum VkBlendFactor { VK_BLEND_FACTOR_ZERO = 0, @@ -963,9 +1534,6 @@ typedef enum VkBlendFactor { VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, VK_BLEND_FACTOR_SRC1_ALPHA = 17, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, - VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO, - VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, - VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1), VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF } VkBlendFactor; @@ -1021,12 +1589,21 @@ typedef enum VkBlendOp { VK_BLEND_OP_RED_EXT = 1000148043, VK_BLEND_OP_GREEN_EXT = 1000148044, VK_BLEND_OP_BLUE_EXT = 1000148045, - VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD, - VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX, - VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1), VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF } VkBlendOp; +typedef enum VkCompareOp { + VK_COMPARE_OP_NEVER = 0, + VK_COMPARE_OP_LESS = 1, + VK_COMPARE_OP_EQUAL = 2, + VK_COMPARE_OP_LESS_OR_EQUAL = 3, + VK_COMPARE_OP_GREATER = 4, + VK_COMPARE_OP_NOT_EQUAL = 5, + VK_COMPARE_OP_GREATER_OR_EQUAL = 6, + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT = 0, VK_DYNAMIC_STATE_SCISSOR = 1, @@ -1040,42 +1617,100 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000, - VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE, - VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1), + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR = 1000347000, + VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004, + VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR = 1000226000, + VK_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, + VK_DYNAMIC_STATE_CULL_MODE_EXT = 1000267000, + VK_DYNAMIC_STATE_FRONT_FACE_EXT = 1000267001, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT = 1000267002, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT = 1000267003, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT = 1000267004, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT = 1000267005, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT = 1000267006, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT = 1000267007, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT = 1000267008, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT = 1000267009, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT = 1000267010, + VK_DYNAMIC_STATE_STENCIL_OP_EXT = 1000267011, + VK_DYNAMIC_STATE_VERTEX_INPUT_EXT = 1000352000, + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT = 1000377000, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT = 1000377002, + VK_DYNAMIC_STATE_LOGIC_OP_EXT = 1000377003, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT = 1000377004, + VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT = 1000381000, VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } VkDynamicState; -typedef enum VkFilter { - VK_FILTER_NEAREST = 0, - VK_FILTER_LINEAR = 1, - VK_FILTER_CUBIC_IMG = 1000015000, - VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST, - VK_FILTER_END_RANGE = VK_FILTER_LINEAR, - VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1), - VK_FILTER_MAX_ENUM = 0x7FFFFFFF -} VkFilter; +typedef enum VkFrontFace { + VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF +} VkFrontFace; -typedef enum VkSamplerMipmapMode { - VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, - VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR, - VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1), - VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerMipmapMode; +typedef enum VkVertexInputRate { + VK_VERTEX_INPUT_RATE_VERTEX = 0, + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF +} VkVertexInputRate; -typedef enum VkSamplerAddressMode { - VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, - VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT, - VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1), - VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerAddressMode; +typedef enum VkPrimitiveTopology { + VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5, + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6, + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF +} VkPrimitiveTopology; + +typedef enum VkPolygonMode { + VK_POLYGON_MODE_FILL = 0, + VK_POLYGON_MODE_LINE = 1, + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF +} VkPolygonMode; + +typedef enum VkStencilOp { + VK_STENCIL_OP_KEEP = 0, + VK_STENCIL_OP_ZERO = 1, + VK_STENCIL_OP_REPLACE = 2, + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, + VK_STENCIL_OP_INVERT = 5, + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + +typedef enum VkLogicOp { + VK_LOGIC_OP_CLEAR = 0, + VK_LOGIC_OP_AND = 1, + VK_LOGIC_OP_AND_REVERSE = 2, + VK_LOGIC_OP_COPY = 3, + VK_LOGIC_OP_AND_INVERTED = 4, + VK_LOGIC_OP_NO_OP = 5, + VK_LOGIC_OP_XOR = 6, + VK_LOGIC_OP_OR = 7, + VK_LOGIC_OP_NOR = 8, + VK_LOGIC_OP_EQUIVALENT = 9, + VK_LOGIC_OP_INVERT = 10, + VK_LOGIC_OP_OR_REVERSE = 11, + VK_LOGIC_OP_COPY_INVERTED = 12, + VK_LOGIC_OP_OR_INVERTED = 13, + VK_LOGIC_OP_NAND = 14, + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; typedef enum VkBorderColor { VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, @@ -1084,12 +1719,35 @@ typedef enum VkBorderColor { VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, - VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE, - VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1), + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } VkBorderColor; +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_IMG = 1000015000, + VK_FILTER_CUBIC_EXT = VK_FILTER_CUBIC_IMG, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerAddressMode { + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_SAMPLER = 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, @@ -1102,9 +1760,10 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, - VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, - VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = 1000351000, VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorType; @@ -1112,104 +1771,104 @@ typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, VK_ATTACHMENT_LOAD_OP_CLEAR = 1, VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, - VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1), + VK_ATTACHMENT_LOAD_OP_NONE_EXT = 1000400000, VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentLoadOp; typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, - VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1), + VK_ATTACHMENT_STORE_OP_NONE_KHR = 1000301000, + VK_ATTACHMENT_STORE_OP_NONE_QCOM = VK_ATTACHMENT_STORE_OP_NONE_KHR, + VK_ATTACHMENT_STORE_OP_NONE_EXT = VK_ATTACHMENT_STORE_OP_NONE_KHR, VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, - VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, - VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, - VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF } VkPipelineBindPoint; typedef enum VkCommandBufferLevel { VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, - VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY, - VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1), VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF } VkCommandBufferLevel; typedef enum VkIndexType { VK_INDEX_TYPE_UINT16 = 0, VK_INDEX_TYPE_UINT32 = 1, - VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16, - VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32, - VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1), + VK_INDEX_TYPE_NONE_KHR = 1000165000, + VK_INDEX_TYPE_UINT8_EXT = 1000265000, + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF } VkIndexType; typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, - VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE, - VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, - VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1), VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; -typedef enum VkObjectType { - VK_OBJECT_TYPE_UNKNOWN = 0, - VK_OBJECT_TYPE_INSTANCE = 1, - VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2, - VK_OBJECT_TYPE_DEVICE = 3, - VK_OBJECT_TYPE_QUEUE = 4, - VK_OBJECT_TYPE_SEMAPHORE = 5, - VK_OBJECT_TYPE_COMMAND_BUFFER = 6, - VK_OBJECT_TYPE_FENCE = 7, - VK_OBJECT_TYPE_DEVICE_MEMORY = 8, - VK_OBJECT_TYPE_BUFFER = 9, - VK_OBJECT_TYPE_IMAGE = 10, - VK_OBJECT_TYPE_EVENT = 11, - VK_OBJECT_TYPE_QUERY_POOL = 12, - VK_OBJECT_TYPE_BUFFER_VIEW = 13, - VK_OBJECT_TYPE_IMAGE_VIEW = 14, - VK_OBJECT_TYPE_SHADER_MODULE = 15, - VK_OBJECT_TYPE_PIPELINE_CACHE = 16, - VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17, - VK_OBJECT_TYPE_RENDER_PASS = 18, - VK_OBJECT_TYPE_PIPELINE = 19, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20, - VK_OBJECT_TYPE_SAMPLER = 21, - VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22, - VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, - VK_OBJECT_TYPE_FRAMEBUFFER = 24, - VK_OBJECT_TYPE_COMMAND_POOL = 25, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, - VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, - VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, - VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, - VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, - VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, - VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000, - VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, - VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, - VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, - VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, - VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL, - VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1), - VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkObjectType; +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, + VK_ACCESS_NONE_KHR = 0, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; -typedef VkFlags VkInstanceCreateFlags; +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, @@ -1234,10 +1893,26 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000, VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000, VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, - VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000, +#endif + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, + VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, + VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000, +#endif VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT, VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, @@ -1245,23 +1920,11 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = VK_FORMAT_FEATURE_DISJOINT_BIT, VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG, VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFormatFeatureFlagBits; typedef VkFlags VkFormatFeatureFlags; -typedef enum VkImageUsageFlagBits { - VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, - VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, - VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, - VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, - VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageUsageFlagBits; -typedef VkFlags VkImageUsageFlags; - typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001, VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, @@ -1275,7 +1938,9 @@ typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100, VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, + VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, + VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, @@ -1298,26 +1963,41 @@ typedef enum VkSampleCountFlagBits { } VkSampleCountFlagBits; typedef VkFlags VkSampleCountFlags; -typedef enum VkQueueFlagBits { - VK_QUEUE_GRAPHICS_BIT = 0x00000001, - VK_QUEUE_COMPUTE_BIT = 0x00000002, - VK_QUEUE_TRANSFER_BIT = 0x00000004, - VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, - VK_QUEUE_PROTECTED_BIT = 0x00000010, - VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueueFlagBits; -typedef VkFlags VkQueueFlags; - -typedef enum VkMemoryPropertyFlagBits { - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, - VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, - VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, - VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkMemoryPropertyFlagBits; -typedef VkFlags VkMemoryPropertyFlags; +typedef enum VkImageUsageFlagBits { + VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001, + VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002, + VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004, + VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00000400, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000, +#endif + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200, + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00004000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000, +#endif + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageUsageFlagBits; +typedef VkFlags VkImageUsageFlags; +typedef VkFlags VkInstanceCreateFlags; typedef enum VkMemoryHeapFlagBits { VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, @@ -1326,6 +2006,36 @@ typedef enum VkMemoryHeapFlagBits { VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryHeapFlagBits; typedef VkFlags VkMemoryHeapFlags; + +typedef enum VkMemoryPropertyFlagBits { + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002, + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, + VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, + VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020, + VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040, + VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080, + VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100, + VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkMemoryPropertyFlagBits; +typedef VkFlags VkMemoryPropertyFlags; + +typedef enum VkQueueFlagBits { + VK_QUEUE_GRAPHICS_BIT = 0x00000001, + VK_QUEUE_COMPUTE_BIT = 0x00000002, + VK_QUEUE_TRANSFER_BIT = 0x00000004, + VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + VK_QUEUE_PROTECTED_BIT = 0x00000010, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, +#endif + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueueFlagBits; +typedef VkFlags VkQueueFlags; typedef VkFlags VkDeviceCreateFlags; typedef enum VkDeviceQueueCreateFlagBits { @@ -1352,26 +2062,29 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, - VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, + VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, + VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, + VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, + VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, + VK_PIPELINE_STAGE_NONE_KHR = 0, + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; typedef VkFlags VkMemoryMapFlags; -typedef enum VkImageAspectFlagBits { - VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, - VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, - VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, - VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, - VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, - VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, - VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, - VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, - VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, - VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, - VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageAspectFlagBits; -typedef VkFlags VkImageAspectFlags; +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; typedef enum VkSparseImageFormatFlagBits { VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, @@ -1381,20 +2094,18 @@ typedef enum VkSparseImageFormatFlagBits { } VkSparseImageFormatFlagBits; typedef VkFlags VkSparseImageFormatFlags; -typedef enum VkSparseMemoryBindFlagBits { - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, - VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSparseMemoryBindFlagBits; -typedef VkFlags VkSparseMemoryBindFlags; - typedef enum VkFenceCreateFlagBits { VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFenceCreateFlagBits; typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkSemaphoreCreateFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = 0x00000001, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; typedef VkFlags VkEventCreateFlags; -typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, @@ -1411,12 +2122,16 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; typedef VkFlags VkQueryPipelineStatisticFlags; +typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_64_BIT = 0x00000001, VK_QUERY_RESULT_WAIT_BIT = 0x00000002, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_QUERY_RESULT_WITH_STATUS_BIT_KHR = 0x00000010, +#endif VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryResultFlagBits; typedef VkFlags VkQueryResultFlags; @@ -1426,6 +2141,9 @@ typedef enum VkBufferCreateFlagBits { VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000010, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_EXT = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferCreateFlagBits; typedef VkFlags VkBufferCreateFlags; @@ -1440,25 +2158,91 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 0x00020000, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR = 0x00004000, +#endif + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, + VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000, +#endif + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferUsageFlagBits; typedef VkFlags VkBufferUsageFlags; typedef VkFlags VkBufferViewCreateFlags; + +typedef enum VkImageViewCreateFlagBits { + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, + VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DEFERRED_BIT_EXT = 0x00000002, + VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageViewCreateFlagBits; typedef VkFlags VkImageViewCreateFlags; typedef VkFlags VkShaderModuleCreateFlags; + +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; typedef VkFlags VkPipelineCacheCreateFlags; +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; + typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, - VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010, + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000, + VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, + VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 0x00080000, + VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, + VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200, + VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, + VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineCreateFlagBits; typedef VkFlags VkPipelineCreateFlags; + +typedef enum VkPipelineShaderStageCreateFlagBits { + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000001, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000002, + VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineShaderStageCreateFlagBits; typedef VkFlags VkPipelineShaderStageCreateFlags; typedef enum VkShaderStageFlagBits { @@ -1470,13 +2254,23 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, + VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; -typedef VkFlags VkPipelineVertexInputStateCreateFlags; -typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; -typedef VkFlags VkPipelineTessellationStateCreateFlags; -typedef VkFlags VkPipelineViewportStateCreateFlags; -typedef VkFlags VkPipelineRasterizationStateCreateFlags; typedef enum VkCullModeFlagBits { VK_CULL_MODE_NONE = 0, @@ -1486,39 +2280,43 @@ typedef enum VkCullModeFlagBits { VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCullModeFlagBits; typedef VkFlags VkCullModeFlags; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; typedef VkFlags VkPipelineMultisampleStateCreateFlags; typedef VkFlags VkPipelineDepthStencilStateCreateFlags; typedef VkFlags VkPipelineColorBlendStateCreateFlags; - -typedef enum VkColorComponentFlagBits { - VK_COLOR_COMPONENT_R_BIT = 0x00000001, - VK_COLOR_COMPONENT_G_BIT = 0x00000002, - VK_COLOR_COMPONENT_B_BIT = 0x00000004, - VK_COLOR_COMPONENT_A_BIT = 0x00000008, - VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkColorComponentFlagBits; -typedef VkFlags VkColorComponentFlags; typedef VkFlags VkPipelineDynamicStateCreateFlags; typedef VkFlags VkPipelineLayoutCreateFlags; typedef VkFlags VkShaderStageFlags; -typedef VkFlags VkSamplerCreateFlags; -typedef enum VkDescriptorSetLayoutCreateFlagBits { - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = 0x00000002, - VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorSetLayoutCreateFlagBits; -typedef VkFlags VkDescriptorSetLayoutCreateFlags; +typedef enum VkSamplerCreateFlagBits { + VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, + VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, + VK_SAMPLER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSamplerCreateFlagBits; +typedef VkFlags VkSamplerCreateFlags; typedef enum VkDescriptorPoolCreateFlagBits { VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, - VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002, + VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; typedef VkFlags VkDescriptorPoolCreateFlags; typedef VkFlags VkDescriptorPoolResetFlags; -typedef VkFlags VkFramebufferCreateFlags; -typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = 0x00000004, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef VkFlags VkDescriptorSetLayoutCreateFlags; typedef enum VkAttachmentDescriptionFlagBits { VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, @@ -1526,38 +2324,6 @@ typedef enum VkAttachmentDescriptionFlagBits { } VkAttachmentDescriptionFlagBits; typedef VkFlags VkAttachmentDescriptionFlags; -typedef enum VkSubpassDescriptionFlagBits { - VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, - VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, - VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSubpassDescriptionFlagBits; -typedef VkFlags VkSubpassDescriptionFlags; - -typedef enum VkAccessFlagBits { - VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, - VK_ACCESS_INDEX_READ_BIT = 0x00000002, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, - VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, - VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, - VK_ACCESS_SHADER_READ_BIT = 0x00000020, - VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, - VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, - VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, - VK_ACCESS_HOST_READ_BIT = 0x00002000, - VK_ACCESS_HOST_WRITE_BIT = 0x00004000, - VK_ACCESS_MEMORY_READ_BIT = 0x00008000, - VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, - VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, - VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, - VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, - VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkAccessFlagBits; -typedef VkFlags VkAccessFlags; - typedef enum VkDependencyFlagBits { VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, @@ -1568,6 +2334,28 @@ typedef enum VkDependencyFlagBits { } VkDependencyFlagBits; typedef VkFlags VkDependencyFlags; +typedef enum VkFramebufferCreateFlagBits { + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, + VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFramebufferCreateFlagBits; +typedef VkFlags VkFramebufferCreateFlags; + +typedef enum VkRenderPassCreateFlagBits { + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, + VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderPassCreateFlagBits; +typedef VkFlags VkRenderPassCreateFlags; + +typedef enum VkSubpassDescriptionFlagBits { + VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, + VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0x00000004, + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0x00000008, + VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubpassDescriptionFlagBits; +typedef VkFlags VkSubpassDescriptionFlags; + typedef enum VkCommandPoolCreateFlagBits { VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, @@ -1605,31 +2393,116 @@ typedef VkFlags VkCommandBufferResetFlags; typedef enum VkStencilFaceFlagBits { VK_STENCIL_FACE_FRONT_BIT = 0x00000001, VK_STENCIL_FACE_BACK_BIT = 0x00000002, - VK_STENCIL_FRONT_AND_BACK = 0x00000003, + VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003, + VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkStencilFaceFlagBits; typedef VkFlags VkStencilFaceFlags; +typedef struct VkExtent2D { + uint32_t width; + uint32_t height; +} VkExtent2D; -typedef struct VkApplicationInfo { +typedef struct VkExtent3D { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkExtent3D; + +typedef struct VkOffset2D { + int32_t x; + int32_t y; +} VkOffset2D; + +typedef struct VkOffset3D { + int32_t x; + int32_t y; + int32_t z; +} VkOffset3D; + +typedef struct VkRect2D { + VkOffset2D offset; + VkExtent2D extent; +} VkRect2D; + +typedef struct VkBaseInStructure { + VkStructureType sType; + const struct VkBaseInStructure* pNext; +} VkBaseInStructure; + +typedef struct VkBaseOutStructure { + VkStructureType sType; + struct VkBaseOutStructure* pNext; +} VkBaseOutStructure; + +typedef struct VkBufferMemoryBarrier { VkStructureType sType; const void* pNext; - const char* pApplicationName; - uint32_t applicationVersion; - const char* pEngineName; - uint32_t engineVersion; - uint32_t apiVersion; -} VkApplicationInfo; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; -typedef struct VkInstanceCreateInfo { - VkStructureType sType; - const void* pNext; - VkInstanceCreateFlags flags; - const VkApplicationInfo* pApplicationInfo; - uint32_t enabledLayerCount; - const char* const* ppEnabledLayerNames; - uint32_t enabledExtensionCount; - const char* const* ppEnabledExtensionNames; -} VkInstanceCreateInfo; +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; + +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; +} VkPipelineCacheHeaderVersionOne; typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( void* pUserData, @@ -1637,13 +2510,6 @@ typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( size_t alignment, VkSystemAllocationScope allocationScope); -typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( - void* pUserData, - void* pOriginal, - size_t size, - size_t alignment, - VkSystemAllocationScope allocationScope); - typedef void (VKAPI_PTR *PFN_vkFreeFunction)( void* pUserData, void* pMemory); @@ -1660,6 +2526,14 @@ typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope); +typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( + void* pUserData, + void* pOriginal, + size_t size, + size_t alignment, + VkSystemAllocationScope allocationScope); + +typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); typedef struct VkAllocationCallbacks { void* pUserData; PFN_vkAllocationFunction pfnAllocation; @@ -1669,6 +2543,51 @@ typedef struct VkAllocationCallbacks { PFN_vkInternalFreeNotification pfnInternalFree; } VkAllocationCallbacks; +typedef struct VkApplicationInfo { + VkStructureType sType; + const void* pNext; + const char* pApplicationName; + uint32_t applicationVersion; + const char* pEngineName; + uint32_t engineVersion; + uint32_t apiVersion; +} VkApplicationInfo; + +typedef struct VkFormatProperties { + VkFormatFeatureFlags linearTilingFeatures; + VkFormatFeatureFlags optimalTilingFeatures; + VkFormatFeatureFlags bufferFeatures; +} VkFormatProperties; + +typedef struct VkImageFormatProperties { + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties; + +typedef struct VkInstanceCreateInfo { + VkStructureType sType; + const void* pNext; + VkInstanceCreateFlags flags; + const VkApplicationInfo* pApplicationInfo; + uint32_t enabledLayerCount; + const char* const* ppEnabledLayerNames; + uint32_t enabledExtensionCount; + const char* const* ppEnabledExtensionNames; +} VkInstanceCreateInfo; + +typedef struct VkMemoryHeap { + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap; + +typedef struct VkMemoryType { + VkMemoryPropertyFlags propertyFlags; + uint32_t heapIndex; +} VkMemoryType; + typedef struct VkPhysicalDeviceFeatures { VkBool32 robustBufferAccess; VkBool32 fullDrawIndexUint32; @@ -1727,26 +2646,6 @@ typedef struct VkPhysicalDeviceFeatures { VkBool32 inheritedQueries; } VkPhysicalDeviceFeatures; -typedef struct VkFormatProperties { - VkFormatFeatureFlags linearTilingFeatures; - VkFormatFeatureFlags optimalTilingFeatures; - VkFormatFeatureFlags bufferFeatures; -} VkFormatProperties; - -typedef struct VkExtent3D { - uint32_t width; - uint32_t height; - uint32_t depth; -} VkExtent3D; - -typedef struct VkImageFormatProperties { - VkExtent3D maxExtent; - uint32_t maxMipLevels; - uint32_t maxArrayLayers; - VkSampleCountFlags sampleCounts; - VkDeviceSize maxResourceSize; -} VkImageFormatProperties; - typedef struct VkPhysicalDeviceLimits { uint32_t maxImageDimension1D; uint32_t maxImageDimension2D; @@ -1856,6 +2755,13 @@ typedef struct VkPhysicalDeviceLimits { VkDeviceSize nonCoherentAtomSize; } VkPhysicalDeviceLimits; +typedef struct VkPhysicalDeviceMemoryProperties { + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties; + typedef struct VkPhysicalDeviceSparseProperties { VkBool32 residencyStandard2DBlockShape; VkBool32 residencyStandard2DMultisampleBlockShape; @@ -1883,24 +2789,6 @@ typedef struct VkQueueFamilyProperties { VkExtent3D minImageTransferGranularity; } VkQueueFamilyProperties; -typedef struct VkMemoryType { - VkMemoryPropertyFlags propertyFlags; - uint32_t heapIndex; -} VkMemoryType; - -typedef struct VkMemoryHeap { - VkDeviceSize size; - VkMemoryHeapFlags flags; -} VkMemoryHeap; - -typedef struct VkPhysicalDeviceMemoryProperties { - uint32_t memoryTypeCount; - VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; - uint32_t memoryHeapCount; - VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS]; -} VkPhysicalDeviceMemoryProperties; - -typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); typedef struct VkDeviceQueueCreateInfo { VkStructureType sType; const void* pNext; @@ -1947,13 +2835,6 @@ typedef struct VkSubmitInfo { const VkSemaphore* pSignalSemaphores; } VkSubmitInfo; -typedef struct VkMemoryAllocateInfo { - VkStructureType sType; - const void* pNext; - VkDeviceSize allocationSize; - uint32_t memoryTypeIndex; -} VkMemoryAllocateInfo; - typedef struct VkMappedMemoryRange { VkStructureType sType; const void* pNext; @@ -1962,26 +2843,19 @@ typedef struct VkMappedMemoryRange { VkDeviceSize size; } VkMappedMemoryRange; +typedef struct VkMemoryAllocateInfo { + VkStructureType sType; + const void* pNext; + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; +} VkMemoryAllocateInfo; + typedef struct VkMemoryRequirements { VkDeviceSize size; VkDeviceSize alignment; uint32_t memoryTypeBits; } VkMemoryRequirements; -typedef struct VkSparseImageFormatProperties { - VkImageAspectFlags aspectMask; - VkExtent3D imageGranularity; - VkSparseImageFormatFlags flags; -} VkSparseImageFormatProperties; - -typedef struct VkSparseImageMemoryRequirements { - VkSparseImageFormatProperties formatProperties; - uint32_t imageMipTailFirstLod; - VkDeviceSize imageMipTailSize; - VkDeviceSize imageMipTailOffset; - VkDeviceSize imageMipTailStride; -} VkSparseImageMemoryRequirements; - typedef struct VkSparseMemoryBind { VkDeviceSize resourceOffset; VkDeviceSize size; @@ -2008,12 +2882,6 @@ typedef struct VkImageSubresource { uint32_t arrayLayer; } VkImageSubresource; -typedef struct VkOffset3D { - int32_t x; - int32_t y; - int32_t z; -} VkOffset3D; - typedef struct VkSparseImageMemoryBind { VkImageSubresource subresource; VkOffset3D offset; @@ -2044,6 +2912,20 @@ typedef struct VkBindSparseInfo { const VkSemaphore* pSignalSemaphores; } VkBindSparseInfo; +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + typedef struct VkFenceCreateInfo { VkStructureType sType; const void* pNext; @@ -2125,14 +3007,6 @@ typedef struct VkComponentMapping { VkComponentSwizzle a; } VkComponentMapping; -typedef struct VkImageSubresourceRange { - VkImageAspectFlags aspectMask; - uint32_t baseMipLevel; - uint32_t levelCount; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceRange; - typedef struct VkImageViewCreateInfo { VkStructureType sType; const void* pNext; @@ -2183,6 +3057,16 @@ typedef struct VkPipelineShaderStageCreateInfo { const VkSpecializationInfo* pSpecializationInfo; } VkPipelineShaderStageCreateInfo; +typedef struct VkComputePipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo stage; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkComputePipelineCreateInfo; + typedef struct VkVertexInputBindingDescription { uint32_t binding; uint32_t stride; @@ -2230,21 +3114,6 @@ typedef struct VkViewport { float maxDepth; } VkViewport; -typedef struct VkOffset2D { - int32_t x; - int32_t y; -} VkOffset2D; - -typedef struct VkExtent2D { - uint32_t width; - uint32_t height; -} VkExtent2D; - -typedef struct VkRect2D { - VkOffset2D offset; - VkExtent2D extent; -} VkRect2D; - typedef struct VkPipelineViewportStateCreateInfo { VkStructureType sType; const void* pNext; @@ -2360,16 +3229,6 @@ typedef struct VkGraphicsPipelineCreateInfo { int32_t basePipelineIndex; } VkGraphicsPipelineCreateInfo; -typedef struct VkComputePipelineCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - VkPipelineShaderStageCreateInfo stage; - VkPipelineLayout layout; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkComputePipelineCreateInfo; - typedef struct VkPushConstantRange { VkShaderStageFlags stageFlags; uint32_t offset; @@ -2407,21 +3266,29 @@ typedef struct VkSamplerCreateInfo { VkBool32 unnormalizedCoordinates; } VkSamplerCreateInfo; -typedef struct VkDescriptorSetLayoutBinding { - uint32_t binding; - VkDescriptorType descriptorType; - uint32_t descriptorCount; - VkShaderStageFlags stageFlags; - const VkSampler* pImmutableSamplers; -} VkDescriptorSetLayoutBinding; +typedef struct VkCopyDescriptorSet { + VkStructureType sType; + const void* pNext; + VkDescriptorSet srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + VkDescriptorSet dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; +} VkCopyDescriptorSet; -typedef struct VkDescriptorSetLayoutCreateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorSetLayoutCreateFlags flags; - uint32_t bindingCount; - const VkDescriptorSetLayoutBinding* pBindings; -} VkDescriptorSetLayoutCreateInfo; +typedef struct VkDescriptorBufferInfo { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize range; +} VkDescriptorBufferInfo; + +typedef struct VkDescriptorImageInfo { + VkSampler sampler; + VkImageView imageView; + VkImageLayout imageLayout; +} VkDescriptorImageInfo; typedef struct VkDescriptorPoolSize { VkDescriptorType type; @@ -2445,17 +3312,21 @@ typedef struct VkDescriptorSetAllocateInfo { const VkDescriptorSetLayout* pSetLayouts; } VkDescriptorSetAllocateInfo; -typedef struct VkDescriptorImageInfo { - VkSampler sampler; - VkImageView imageView; - VkImageLayout imageLayout; -} VkDescriptorImageInfo; +typedef struct VkDescriptorSetLayoutBinding { + uint32_t binding; + VkDescriptorType descriptorType; + uint32_t descriptorCount; + VkShaderStageFlags stageFlags; + const VkSampler* pImmutableSamplers; +} VkDescriptorSetLayoutBinding; -typedef struct VkDescriptorBufferInfo { - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize range; -} VkDescriptorBufferInfo; +typedef struct VkDescriptorSetLayoutCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t bindingCount; + const VkDescriptorSetLayoutBinding* pBindings; +} VkDescriptorSetLayoutCreateInfo; typedef struct VkWriteDescriptorSet { VkStructureType sType; @@ -2470,30 +3341,6 @@ typedef struct VkWriteDescriptorSet { const VkBufferView* pTexelBufferView; } VkWriteDescriptorSet; -typedef struct VkCopyDescriptorSet { - VkStructureType sType; - const void* pNext; - VkDescriptorSet srcSet; - uint32_t srcBinding; - uint32_t srcArrayElement; - VkDescriptorSet dstSet; - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; -} VkCopyDescriptorSet; - -typedef struct VkFramebufferCreateInfo { - VkStructureType sType; - const void* pNext; - VkFramebufferCreateFlags flags; - VkRenderPass renderPass; - uint32_t attachmentCount; - const VkImageView* pAttachments; - uint32_t width; - uint32_t height; - uint32_t layers; -} VkFramebufferCreateInfo; - typedef struct VkAttachmentDescription { VkAttachmentDescriptionFlags flags; VkFormat format; @@ -2511,6 +3358,18 @@ typedef struct VkAttachmentReference { VkImageLayout layout; } VkAttachmentReference; +typedef struct VkFramebufferCreateInfo { + VkStructureType sType; + const void* pNext; + VkFramebufferCreateFlags flags; + VkRenderPass renderPass; + uint32_t attachmentCount; + const VkImageView* pAttachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} VkFramebufferCreateInfo; + typedef struct VkSubpassDescription { VkSubpassDescriptionFlags flags; VkPipelineBindPoint pipelineBindPoint; @@ -2592,21 +3451,6 @@ typedef struct VkImageSubresourceLayers { uint32_t layerCount; } VkImageSubresourceLayers; -typedef struct VkImageCopy { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy; - -typedef struct VkImageBlit { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffsets[2]; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffsets[2]; -} VkImageBlit; - typedef struct VkBufferImageCopy { VkDeviceSize bufferOffset; uint32_t bufferRowLength; @@ -2644,6 +3488,21 @@ typedef struct VkClearRect { uint32_t layerCount; } VkClearRect; +typedef struct VkImageBlit { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + typedef struct VkImageResolve { VkImageSubresourceLayers srcSubresource; VkOffset3D srcOffset; @@ -2652,38 +3511,6 @@ typedef struct VkImageResolve { VkExtent3D extent; } VkImageResolve; -typedef struct VkMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; -} VkMemoryBarrier; - -typedef struct VkBufferMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize size; -} VkBufferMemoryBarrier; - -typedef struct VkImageMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier; - typedef struct VkRenderPassBeginInfo { VkStructureType sType; const void* pNext; @@ -2694,28 +3521,6 @@ typedef struct VkRenderPassBeginInfo { const VkClearValue* pClearValues; } VkRenderPassBeginInfo; -typedef struct VkDispatchIndirectCommand { - uint32_t x; - uint32_t y; - uint32_t z; -} VkDispatchIndirectCommand; - -typedef struct VkDrawIndexedIndirectCommand { - uint32_t indexCount; - uint32_t instanceCount; - uint32_t firstIndex; - int32_t vertexOffset; - uint32_t firstInstance; -} VkDrawIndexedIndirectCommand; - -typedef struct VkDrawIndirectCommand { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; -} VkDrawIndirectCommand; - - typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); @@ -3653,27 +4458,22 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( const VkCommandBuffer* pCommandBuffers); #endif + #define VK_VERSION_1_1 1 // Vulkan 1.1 version number -#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0 - +#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) - -#define VK_MAX_DEVICE_GROUP_SIZE 32 -#define VK_LUID_SIZE 8 -#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1) - +#define VK_MAX_DEVICE_GROUP_SIZE 32U +#define VK_LUID_SIZE 8U +#define VK_QUEUE_FAMILY_EXTERNAL (~1U) typedef enum VkPointClippingBehavior { VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, - VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, - VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY, - VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1), VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF } VkPointClippingBehavior; @@ -3682,9 +4482,6 @@ typedef enum VkTessellationDomainOrigin { VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1), VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF } VkTessellationDomainOrigin; @@ -3699,9 +4496,6 @@ typedef enum VkSamplerYcbcrModelConversion { VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1), VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrModelConversion; @@ -3710,9 +4504,6 @@ typedef enum VkSamplerYcbcrRange { VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, - VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL, - VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, - VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1), VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrRange; @@ -3721,9 +4512,6 @@ typedef enum VkChromaLocation { VK_CHROMA_LOCATION_MIDPOINT = 1, VK_CHROMA_LOCATION_COSITED_EVEN_KHR = VK_CHROMA_LOCATION_COSITED_EVEN, VK_CHROMA_LOCATION_MIDPOINT_KHR = VK_CHROMA_LOCATION_MIDPOINT, - VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN, - VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT, - VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1), VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF } VkChromaLocation; @@ -3731,13 +4519,9 @@ typedef enum VkDescriptorUpdateTemplateType { VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1, VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1), VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorUpdateTemplateType; - typedef enum VkSubgroupFeatureFlagBits { VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001, VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002, @@ -3767,7 +4551,11 @@ typedef VkFlags VkPeerMemoryFeatureFlags; typedef enum VkMemoryAllocateFlagBits { VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004, VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryAllocateFlagBits; typedef VkFlags VkMemoryAllocateFlags; @@ -3786,6 +4574,8 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID = 0x00000400, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT = 0x00000080, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -3850,6 +4640,8 @@ typedef enum VkExternalSemaphoreHandleTypeFlagBits { VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA = 0x00000080, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, @@ -3867,7 +4659,6 @@ typedef enum VkExternalSemaphoreFeatureFlagBits { VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalSemaphoreFeatureFlagBits; typedef VkFlags VkExternalSemaphoreFeatureFlags; - typedef struct VkPhysicalDeviceSubgroupProperties { VkStructureType sType; void* pNext; @@ -4135,12 +4926,14 @@ typedef struct VkPhysicalDeviceMultiviewProperties { uint32_t maxMultiviewInstanceIndex; } VkPhysicalDeviceMultiviewProperties; -typedef struct VkPhysicalDeviceVariablePointerFeatures { +typedef struct VkPhysicalDeviceVariablePointersFeatures { VkStructureType sType; void* pNext; VkBool32 variablePointersStorageBuffer; VkBool32 variablePointers; -} VkPhysicalDeviceVariablePointerFeatures; +} VkPhysicalDeviceVariablePointersFeatures; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures; typedef struct VkPhysicalDeviceProtectedMemoryFeatures { VkStructureType sType; @@ -4222,7 +5015,7 @@ typedef struct VkDescriptorUpdateTemplateEntry { typedef struct VkDescriptorUpdateTemplateCreateInfo { VkStructureType sType; - void* pNext; + const void* pNext; VkDescriptorUpdateTemplateCreateFlags flags; uint32_t descriptorUpdateEntryCount; const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; @@ -4346,12 +5139,13 @@ typedef struct VkDescriptorSetLayoutSupport { VkBool32 supported; } VkDescriptorSetLayoutSupport; -typedef struct VkPhysicalDeviceShaderDrawParameterFeatures { +typedef struct VkPhysicalDeviceShaderDrawParametersFeatures { VkStructureType sType; void* pNext; VkBool32 shaderDrawParameters; -} VkPhysicalDeviceShaderDrawParameterFeatures; +} VkPhysicalDeviceShaderDrawParametersFeatures; +typedef VkPhysicalDeviceShaderDrawParametersFeatures VkPhysicalDeviceShaderDrawParameterFeatures; typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion); typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); @@ -4529,19 +5323,776 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( VkDescriptorSetLayoutSupport* pSupport); #endif + +#define VK_VERSION_1_2 1 +// Vulkan 1.2 version number +#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)// Patch version should always be set to 0 + +#define VK_MAX_DRIVER_NAME_SIZE 256U +#define VK_MAX_DRIVER_INFO_SIZE 256U + +typedef enum VkDriverId { + VK_DRIVER_ID_AMD_PROPRIETARY = 1, + VK_DRIVER_ID_AMD_OPEN_SOURCE = 2, + VK_DRIVER_ID_MESA_RADV = 3, + VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8, + VK_DRIVER_ID_ARM_PROPRIETARY = 9, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10, + VK_DRIVER_ID_GGP_PROPRIETARY = 11, + VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12, + VK_DRIVER_ID_MESA_LLVMPIPE = 13, + VK_DRIVER_ID_MOLTENVK = 14, + VK_DRIVER_ID_COREAVI_PROPRIETARY = 15, + VK_DRIVER_ID_JUICE_PROPRIETARY = 16, + VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17, + VK_DRIVER_ID_MESA_TURNIP = 18, + VK_DRIVER_ID_MESA_V3DV = 19, + VK_DRIVER_ID_MESA_PANVK = 20, + VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, + VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, + VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, + VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = VK_DRIVER_ID_NVIDIA_PROPRIETARY, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = VK_DRIVER_ID_IMAGINATION_PROPRIETARY, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = VK_DRIVER_ID_QUALCOMM_PROPRIETARY, + VK_DRIVER_ID_ARM_PROPRIETARY_KHR = VK_DRIVER_ID_ARM_PROPRIETARY, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR = VK_DRIVER_ID_GOOGLE_SWIFTSHADER, + VK_DRIVER_ID_GGP_PROPRIETARY_KHR = VK_DRIVER_ID_GGP_PROPRIETARY, + VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR = VK_DRIVER_ID_BROADCOM_PROPRIETARY, + VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF +} VkDriverId; + +typedef enum VkShaderFloatControlsIndependence { + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF +} VkShaderFloatControlsIndependence; + +typedef enum VkSamplerReductionMode { + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, + VK_SAMPLER_REDUCTION_MODE_MIN = 1, + VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, + VK_SAMPLER_REDUCTION_MODE_MIN_EXT = VK_SAMPLER_REDUCTION_MODE_MIN, + VK_SAMPLER_REDUCTION_MODE_MAX_EXT = VK_SAMPLER_REDUCTION_MODE_MAX, + VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerReductionMode; + +typedef enum VkSemaphoreType { + VK_SEMAPHORE_TYPE_BINARY = 0, + VK_SEMAPHORE_TYPE_TIMELINE = 1, + VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, + VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, + VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreType; + +typedef enum VkResolveModeFlagBits { + VK_RESOLVE_MODE_NONE = 0, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0x00000001, + VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, + VK_RESOLVE_MODE_MIN_BIT = 0x00000004, + VK_RESOLVE_MODE_MAX_BIT = 0x00000008, + VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, + VK_RESOLVE_MODE_MIN_BIT_KHR = VK_RESOLVE_MODE_MIN_BIT, + VK_RESOLVE_MODE_MAX_BIT_KHR = VK_RESOLVE_MODE_MAX_BIT, + VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkResolveModeFlagBits; +typedef VkFlags VkResolveModeFlags; + +typedef enum VkDescriptorBindingFlagBits { + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, + VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorBindingFlagBits; +typedef VkFlags VkDescriptorBindingFlags; + +typedef enum VkSemaphoreWaitFlagBits { + VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001, + VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT, + VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreWaitFlagBits; +typedef VkFlags VkSemaphoreWaitFlags; +typedef struct VkPhysicalDeviceVulkan11Features { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; + VkBool32 protectedMemory; + VkBool32 samplerYcbcrConversion; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceVulkan11Features; + +typedef struct VkPhysicalDeviceVulkan11Properties { + VkStructureType sType; + void* pNext; + uint8_t deviceUUID[VK_UUID_SIZE]; + uint8_t driverUUID[VK_UUID_SIZE]; + uint8_t deviceLUID[VK_LUID_SIZE]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; + uint32_t subgroupSize; + VkShaderStageFlags subgroupSupportedStages; + VkSubgroupFeatureFlags subgroupSupportedOperations; + VkBool32 subgroupQuadOperationsInAllStages; + VkPointClippingBehavior pointClippingBehavior; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; + VkBool32 protectedNoFault; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceVulkan11Properties; + +typedef struct VkPhysicalDeviceVulkan12Features { + VkStructureType sType; + void* pNext; + VkBool32 samplerMirrorClampToEdge; + VkBool32 drawIndirectCount; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; + VkBool32 descriptorIndexing; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; + VkBool32 samplerFilterMinmax; + VkBool32 scalarBlockLayout; + VkBool32 imagelessFramebuffer; + VkBool32 uniformBufferStandardLayout; + VkBool32 shaderSubgroupExtendedTypes; + VkBool32 separateDepthStencilLayouts; + VkBool32 hostQueryReset; + VkBool32 timelineSemaphore; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; + VkBool32 shaderOutputViewportIndex; + VkBool32 shaderOutputLayer; + VkBool32 subgroupBroadcastDynamicId; +} VkPhysicalDeviceVulkan12Features; + +typedef struct VkConformanceVersion { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersion; + +typedef struct VkPhysicalDeviceVulkan12Properties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; + uint64_t maxTimelineSemaphoreValueDifference; + VkSampleCountFlags framebufferIntegerColorSampleCounts; +} VkPhysicalDeviceVulkan12Properties; + +typedef struct VkImageFormatListCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkImageFormatListCreateInfo; + +typedef struct VkAttachmentDescription2 { + VkStructureType sType; + const void* pNext; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription2; + +typedef struct VkAttachmentReference2 { + VkStructureType sType; + const void* pNext; + uint32_t attachment; + VkImageLayout layout; + VkImageAspectFlags aspectMask; +} VkAttachmentReference2; + +typedef struct VkSubpassDescription2 { + VkStructureType sType; + const void* pNext; + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t viewMask; + uint32_t inputAttachmentCount; + const VkAttachmentReference2* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference2* pColorAttachments; + const VkAttachmentReference2* pResolveAttachments; + const VkAttachmentReference2* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription2; + +typedef struct VkSubpassDependency2 { + VkStructureType sType; + const void* pNext; + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; + int32_t viewOffset; +} VkSubpassDependency2; + +typedef struct VkRenderPassCreateInfo2 { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription2* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription2* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency2* pDependencies; + uint32_t correlatedViewMaskCount; + const uint32_t* pCorrelatedViewMasks; +} VkRenderPassCreateInfo2; + +typedef struct VkSubpassBeginInfo { + VkStructureType sType; + const void* pNext; + VkSubpassContents contents; +} VkSubpassBeginInfo; + +typedef struct VkSubpassEndInfo { + VkStructureType sType; + const void* pNext; +} VkSubpassEndInfo; + +typedef struct VkPhysicalDevice8BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; +} VkPhysicalDevice8BitStorageFeatures; + +typedef struct VkPhysicalDeviceDriverProperties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; +} VkPhysicalDeviceDriverProperties; + +typedef struct VkPhysicalDeviceShaderAtomicInt64Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; +} VkPhysicalDeviceShaderAtomicInt64Features; + +typedef struct VkPhysicalDeviceShaderFloat16Int8Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; +} VkPhysicalDeviceShaderFloat16Int8Features; + +typedef struct VkPhysicalDeviceFloatControlsProperties { + VkStructureType sType; + void* pNext; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; +} VkPhysicalDeviceFloatControlsProperties; + +typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t bindingCount; + const VkDescriptorBindingFlags* pBindingFlags; +} VkDescriptorSetLayoutBindingFlagsCreateInfo; + +typedef struct VkPhysicalDeviceDescriptorIndexingFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; +} VkPhysicalDeviceDescriptorIndexingFeatures; + +typedef struct VkPhysicalDeviceDescriptorIndexingProperties { + VkStructureType sType; + void* pNext; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; +} VkPhysicalDeviceDescriptorIndexingProperties; + +typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSetCount; + const uint32_t* pDescriptorCounts; +} VkDescriptorSetVariableDescriptorCountAllocateInfo; + +typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport { + VkStructureType sType; + void* pNext; + uint32_t maxVariableDescriptorCount; +} VkDescriptorSetVariableDescriptorCountLayoutSupport; + +typedef struct VkSubpassDescriptionDepthStencilResolve { + VkStructureType sType; + const void* pNext; + VkResolveModeFlagBits depthResolveMode; + VkResolveModeFlagBits stencilResolveMode; + const VkAttachmentReference2* pDepthStencilResolveAttachment; +} VkSubpassDescriptionDepthStencilResolve; + +typedef struct VkPhysicalDeviceDepthStencilResolveProperties { + VkStructureType sType; + void* pNext; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; +} VkPhysicalDeviceDepthStencilResolveProperties; + +typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 scalarBlockLayout; +} VkPhysicalDeviceScalarBlockLayoutFeatures; + +typedef struct VkImageStencilUsageCreateInfo { + VkStructureType sType; + const void* pNext; + VkImageUsageFlags stencilUsage; +} VkImageStencilUsageCreateInfo; + +typedef struct VkSamplerReductionModeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerReductionMode reductionMode; +} VkSamplerReductionModeCreateInfo; + +typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { + VkStructureType sType; + void* pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxProperties; + +typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; +} VkPhysicalDeviceVulkanMemoryModelFeatures; + +typedef struct VkPhysicalDeviceImagelessFramebufferFeatures { + VkStructureType sType; + void* pNext; + VkBool32 imagelessFramebuffer; +} VkPhysicalDeviceImagelessFramebufferFeatures; + +typedef struct VkFramebufferAttachmentImageInfo { + VkStructureType sType; + const void* pNext; + VkImageCreateFlags flags; + VkImageUsageFlags usage; + uint32_t width; + uint32_t height; + uint32_t layerCount; + uint32_t viewFormatCount; + const VkFormat* pViewFormats; +} VkFramebufferAttachmentImageInfo; + +typedef struct VkFramebufferAttachmentsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentImageInfoCount; + const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos; +} VkFramebufferAttachmentsCreateInfo; + +typedef struct VkRenderPassAttachmentBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkImageView* pAttachments; +} VkRenderPassAttachmentBeginInfo; + +typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 uniformBufferStandardLayout; +} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; + +typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupExtendedTypes; +} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; + +typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures { + VkStructureType sType; + void* pNext; + VkBool32 separateDepthStencilLayouts; +} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures; + +typedef struct VkAttachmentReferenceStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilLayout; +} VkAttachmentReferenceStencilLayout; + +typedef struct VkAttachmentDescriptionStencilLayout { + VkStructureType sType; + void* pNext; + VkImageLayout stencilInitialLayout; + VkImageLayout stencilFinalLayout; +} VkAttachmentDescriptionStencilLayout; + +typedef struct VkPhysicalDeviceHostQueryResetFeatures { + VkStructureType sType; + void* pNext; + VkBool32 hostQueryReset; +} VkPhysicalDeviceHostQueryResetFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { + VkStructureType sType; + void* pNext; + VkBool32 timelineSemaphore; +} VkPhysicalDeviceTimelineSemaphoreFeatures; + +typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { + VkStructureType sType; + void* pNext; + uint64_t maxTimelineSemaphoreValueDifference; +} VkPhysicalDeviceTimelineSemaphoreProperties; + +typedef struct VkSemaphoreTypeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreType semaphoreType; + uint64_t initialValue; +} VkSemaphoreTypeCreateInfo; + +typedef struct VkTimelineSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValueCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValueCount; + const uint64_t* pSignalSemaphoreValues; +} VkTimelineSemaphoreSubmitInfo; + +typedef struct VkSemaphoreWaitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreWaitFlags flags; + uint32_t semaphoreCount; + const VkSemaphore* pSemaphores; + const uint64_t* pValues; +} VkSemaphoreWaitInfo; + +typedef struct VkSemaphoreSignalInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; +} VkSemaphoreSignalInfo; + +typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeatures; + +typedef struct VkBufferDeviceAddressInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferDeviceAddressInfo; + +typedef struct VkBufferOpaqueCaptureAddressCreateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkBufferOpaqueCaptureAddressCreateInfo; + +typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkMemoryOpaqueCaptureAddressAllocateInfo; + +typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkDeviceMemoryOpaqueCaptureAddressInfo; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkResetQueryPool( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif + + #define VK_KHR_surface 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) - #define VK_KHR_SURFACE_SPEC_VERSION 25 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" -#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR +typedef enum VkPresentModeKHR { + VK_PRESENT_MODE_IMMEDIATE_KHR = 0, + VK_PRESENT_MODE_MAILBOX_KHR = 1, + VK_PRESENT_MODE_FIFO_KHR = 2, + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentModeKHR; typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001, VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002, - VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003, + VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104003, VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004, VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005, VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, @@ -4553,26 +6104,12 @@ typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012, VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, - VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1), + VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, + VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF } VkColorSpaceKHR; -typedef enum VkPresentModeKHR { - VK_PRESENT_MODE_IMMEDIATE_KHR = 0, - VK_PRESENT_MODE_MAILBOX_KHR = 1, - VK_PRESENT_MODE_FIFO_KHR = 2, - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, - VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, - VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, - VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR, - VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1), - VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkPresentModeKHR; - - typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001, VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002, @@ -4585,7 +6122,6 @@ typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSurfaceTransformFlagBitsKHR; -typedef VkFlags VkSurfaceTransformFlagsKHR; typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, @@ -4595,7 +6131,7 @@ typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkCompositeAlphaFlagBitsKHR; typedef VkFlags VkCompositeAlphaFlagsKHR; - +typedef VkFlags VkSurfaceTransformFlagsKHR; typedef struct VkSurfaceCapabilitiesKHR { uint32_t minImageCount; uint32_t maxImageCount; @@ -4614,7 +6150,6 @@ typedef struct VkSurfaceFormatKHR { VkColorSpaceKHR colorSpace; } VkSurfaceFormatKHR; - typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); @@ -4651,16 +6186,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( VkPresentModeKHR* pPresentModes); #endif + #define VK_KHR_swapchain 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) - #define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 #define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" - typedef enum VkSwapchainCreateFlagBitsKHR { VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, + VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSwapchainCreateFlagBitsKHR; typedef VkFlags VkSwapchainCreateFlagsKHR; @@ -4673,7 +6208,6 @@ typedef enum VkDeviceGroupPresentModeFlagBitsKHR { VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkDeviceGroupPresentModeFlagBitsKHR; typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; - typedef struct VkSwapchainCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -4731,7 +6265,7 @@ typedef struct VkAcquireNextImageInfoKHR { typedef struct VkDeviceGroupPresentCapabilitiesKHR { VkStructureType sType; - const void* pNext; + void* pNext; uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE]; VkDeviceGroupPresentModeFlagsKHR modes; } VkDeviceGroupPresentCapabilitiesKHR; @@ -4750,7 +6284,6 @@ typedef struct VkDeviceGroupSwapchainCreateInfoKHR { VkDeviceGroupPresentModeFlagsKHR modes; } VkDeviceGroupSwapchainCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); @@ -4812,13 +6345,13 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( uint32_t* pImageIndex); #endif + #define VK_KHR_display 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR) - -#define VK_KHR_DISPLAY_SPEC_VERSION 21 +#define VK_KHR_DISPLAY_SPEC_VERSION 23 #define VK_KHR_DISPLAY_EXTENSION_NAME "VK_KHR_display" - +typedef VkFlags VkDisplayModeCreateFlagsKHR; typedef enum VkDisplayPlaneAlphaFlagBitsKHR { VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, @@ -4828,29 +6361,12 @@ typedef enum VkDisplayPlaneAlphaFlagBitsKHR { VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkDisplayPlaneAlphaFlagBitsKHR; typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; -typedef VkFlags VkDisplayModeCreateFlagsKHR; typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; - -typedef struct VkDisplayPropertiesKHR { - VkDisplayKHR display; - const char* displayName; - VkExtent2D physicalDimensions; - VkExtent2D physicalResolution; - VkSurfaceTransformFlagsKHR supportedTransforms; - VkBool32 planeReorderPossible; - VkBool32 persistentContent; -} VkDisplayPropertiesKHR; - typedef struct VkDisplayModeParametersKHR { VkExtent2D visibleRegion; uint32_t refreshRate; } VkDisplayModeParametersKHR; -typedef struct VkDisplayModePropertiesKHR { - VkDisplayModeKHR displayMode; - VkDisplayModeParametersKHR parameters; -} VkDisplayModePropertiesKHR; - typedef struct VkDisplayModeCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -4858,6 +6374,11 @@ typedef struct VkDisplayModeCreateInfoKHR { VkDisplayModeParametersKHR parameters; } VkDisplayModeCreateInfoKHR; +typedef struct VkDisplayModePropertiesKHR { + VkDisplayModeKHR displayMode; + VkDisplayModeParametersKHR parameters; +} VkDisplayModePropertiesKHR; + typedef struct VkDisplayPlaneCapabilitiesKHR { VkDisplayPlaneAlphaFlagsKHR supportedAlpha; VkOffset2D minSrcPosition; @@ -4875,6 +6396,16 @@ typedef struct VkDisplayPlanePropertiesKHR { uint32_t currentStackIndex; } VkDisplayPlanePropertiesKHR; +typedef struct VkDisplayPropertiesKHR { + VkDisplayKHR display; + const char* displayName; + VkExtent2D physicalDimensions; + VkExtent2D physicalResolution; + VkSurfaceTransformFlagsKHR supportedTransforms; + VkBool32 planeReorderPossible; + VkBool32 persistentContent; +} VkDisplayPropertiesKHR; + typedef struct VkDisplaySurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -4888,7 +6419,6 @@ typedef struct VkDisplaySurfaceCreateInfoKHR { VkExtent2D imageExtent; } VkDisplaySurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); @@ -4940,10 +6470,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( VkSurfaceKHR* pSurface); #endif -#define VK_KHR_display_swapchain 1 -#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 9 -#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" +#define VK_KHR_display_swapchain 1 +#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 10 +#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain" typedef struct VkDisplayPresentInfoKHR { VkStructureType sType; const void* pNext; @@ -4952,7 +6482,6 @@ typedef struct VkDisplayPresentInfoKHR { VkBool32 persistent; } VkDisplayPresentInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); #ifndef VK_NO_PROTOTYPES @@ -4964,15 +6493,125 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( VkSwapchainKHR* pSwapchains); #endif + #define VK_KHR_sampler_mirror_clamp_to_edge 1 -#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1 +#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 3 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge" +#define VK_KHR_dynamic_rendering 1 +#define VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION 1 +#define VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME "VK_KHR_dynamic_rendering" + +typedef enum VkRenderingFlagBitsKHR { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = 0x00000001, + VK_RENDERING_SUSPENDING_BIT_KHR = 0x00000002, + VK_RENDERING_RESUMING_BIT_KHR = 0x00000004, + VK_RENDERING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingFlagBitsKHR; +typedef VkFlags VkRenderingFlagsKHR; +typedef struct VkRenderingAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfoKHR; + +typedef struct VkRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfoKHR* pColorAttachments; + const VkRenderingAttachmentInfoKHR* pDepthAttachment; + const VkRenderingAttachmentInfoKHR* pStencilAttachment; +} VkRenderingInfoKHR; + +typedef struct VkPipelineRenderingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfoKHR; + +typedef struct VkPhysicalDeviceDynamicRenderingFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeaturesKHR; + +typedef struct VkCommandBufferInheritanceRenderingInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingFlagsKHR flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfoKHR; + +typedef struct VkRenderingFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkExtent2D shadingRateAttachmentTexelSize; +} VkRenderingFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkRenderingFragmentDensityMapAttachmentInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkImageLayout imageLayout; +} VkRenderingFragmentDensityMapAttachmentInfoEXT; + +typedef struct VkAttachmentSampleCountInfoAMD { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const VkSampleCountFlagBits* pColorAttachmentSamples; + VkSampleCountFlagBits depthStencilAttachmentSamples; +} VkAttachmentSampleCountInfoAMD; + +typedef VkAttachmentSampleCountInfoAMD VkAttachmentSampleCountInfoNV; + +typedef struct VkMultiviewPerViewAttributesInfoNVX { + VkStructureType sType; + const void* pNext; + VkBool32 perViewAttributes; + VkBool32 perViewAttributesPositionXOnly; +} VkMultiviewPerViewAttributesInfoNVX; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR* pRenderingInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( + VkCommandBuffer commandBuffer, + const VkRenderingInfoKHR* pRenderingInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( + VkCommandBuffer commandBuffer); +#endif + + #define VK_KHR_multiview 1 #define VK_KHR_MULTIVIEW_SPEC_VERSION 1 #define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview" - typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR; typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR; @@ -4982,9 +6621,8 @@ typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesK #define VK_KHR_get_physical_device_properties2 1 -#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 2 #define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2" - typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR; typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR; @@ -5003,7 +6641,6 @@ typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR; typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR; - typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); @@ -5047,10 +6684,10 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( VkSparseImageFormatProperties2* pProperties); #endif -#define VK_KHR_device_group 1 -#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 3 -#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" +#define VK_KHR_device_group 1 +#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 4 +#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group" typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR; typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR; @@ -5059,7 +6696,6 @@ typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR; typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR; - typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR; typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR; @@ -5074,7 +6710,6 @@ typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR; typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR; - typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask); typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); @@ -5101,18 +6736,19 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( uint32_t groupCountZ); #endif + #define VK_KHR_shader_draw_parameters 1 #define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1 #define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters" #define VK_KHR_maintenance1 1 -#define VK_KHR_MAINTENANCE1_SPEC_VERSION 2 -#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1" - +#define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 +#define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" +#define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION +#define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; - typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); #ifndef VK_NO_PROTOTYPES @@ -5122,16 +6758,15 @@ VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( VkCommandPoolTrimFlags flags); #endif + #define VK_KHR_device_group_creation 1 #define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1 #define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation" #define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE - typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR; typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); #ifndef VK_NO_PROTOTYPES @@ -5141,11 +6776,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); #endif + #define VK_KHR_external_memory_capabilities 1 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities" #define VK_LUID_SIZE_KHR VK_LUID_SIZE - typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR; typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR; @@ -5154,7 +6789,6 @@ typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR; typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR; - typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR; typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR; @@ -5167,7 +6801,6 @@ typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR; typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; - typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); #ifndef VK_NO_PROTOTYPES @@ -5177,11 +6810,11 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( VkExternalBufferProperties* pExternalBufferProperties); #endif + #define VK_KHR_external_memory 1 #define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory" #define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL - typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR; typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR; @@ -5193,7 +6826,6 @@ typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR; #define VK_KHR_external_memory_fd 1 #define VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd" - typedef struct VkImportMemoryFdInfoKHR { VkStructureType sType; const void* pNext; @@ -5214,7 +6846,6 @@ typedef struct VkMemoryGetFdInfoKHR { VkExternalMemoryHandleTypeFlagBits handleType; } VkMemoryGetFdInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); @@ -5231,10 +6862,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( VkMemoryFdPropertiesKHR* pMemoryFdProperties); #endif + #define VK_KHR_external_semaphore_capabilities 1 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities" - typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR; typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR; @@ -5243,12 +6874,10 @@ typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR; typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR; - typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR; typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; - typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #ifndef VK_NO_PROTOTYPES @@ -5258,15 +6887,14 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #endif + #define VK_KHR_external_semaphore 1 #define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore" - typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR; typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR; - typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; @@ -5274,7 +6902,6 @@ typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR; #define VK_KHR_external_semaphore_fd 1 #define VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd" - typedef struct VkImportSemaphoreFdInfoKHR { VkStructureType sType; const void* pNext; @@ -5291,7 +6918,6 @@ typedef struct VkSemaphoreGetFdInfoKHR { VkExternalSemaphoreHandleTypeFlagBits handleType; } VkSemaphoreGetFdInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); @@ -5306,17 +6932,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( int* pFd); #endif + #define VK_KHR_push_descriptor 1 #define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2 #define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor" - typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR { VkStructureType sType; void* pNext; uint32_t maxPushDescriptors; } VkPhysicalDevicePushDescriptorPropertiesKHR; - typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); @@ -5337,18 +6962,26 @@ VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( const void* pData); #endif + +#define VK_KHR_shader_float16_int8 1 +#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1 +#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8" +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceShaderFloat16Int8FeaturesKHR; + +typedef VkPhysicalDeviceShaderFloat16Int8Features VkPhysicalDeviceFloat16Int8FeaturesKHR; + + + #define VK_KHR_16bit_storage 1 #define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1 #define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage" - typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR; #define VK_KHR_incremental_present 1 -#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1 +#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 2 #define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present" - typedef struct VkRectLayerKHR { VkOffset2D offset; VkExtent2D extent; @@ -5372,21 +7005,16 @@ typedef struct VkPresentRegionsKHR { #define VK_KHR_descriptor_update_template 1 typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR; - #define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1 #define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template" - typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR; - typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR; - typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR; typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); @@ -5410,17 +7038,74 @@ VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( const void* pData); #endif + +#define VK_KHR_imageless_framebuffer 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION 1 +#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME "VK_KHR_imageless_framebuffer" +typedef VkPhysicalDeviceImagelessFramebufferFeatures VkPhysicalDeviceImagelessFramebufferFeaturesKHR; + +typedef VkFramebufferAttachmentsCreateInfo VkFramebufferAttachmentsCreateInfoKHR; + +typedef VkFramebufferAttachmentImageInfo VkFramebufferAttachmentImageInfoKHR; + +typedef VkRenderPassAttachmentBeginInfo VkRenderPassAttachmentBeginInfoKHR; + + + +#define VK_KHR_create_renderpass2 1 +#define VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION 1 +#define VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME "VK_KHR_create_renderpass2" +typedef VkRenderPassCreateInfo2 VkRenderPassCreateInfo2KHR; + +typedef VkAttachmentDescription2 VkAttachmentDescription2KHR; + +typedef VkAttachmentReference2 VkAttachmentReference2KHR; + +typedef VkSubpassDescription2 VkSubpassDescription2KHR; + +typedef VkSubpassDependency2 VkSubpassDependency2KHR; + +typedef VkSubpassBeginInfo VkSubpassBeginInfoKHR; + +typedef VkSubpassEndInfo VkSubpassEndInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2KHR)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( + VkDevice device, + const VkRenderPassCreateInfo2* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkRenderPass* pRenderPass); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkRenderPassBeginInfo* pRenderPassBegin, + const VkSubpassBeginInfo* pSubpassBeginInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassBeginInfo* pSubpassBeginInfo, + const VkSubpassEndInfo* pSubpassEndInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( + VkCommandBuffer commandBuffer, + const VkSubpassEndInfo* pSubpassEndInfo); +#endif + + #define VK_KHR_shared_presentable_image 1 #define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 #define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" - typedef struct VkSharedPresentSurfaceCapabilitiesKHR { VkStructureType sType; void* pNext; VkImageUsageFlags sharedPresentSupportedUsageFlags; } VkSharedPresentSurfaceCapabilitiesKHR; - typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); #ifndef VK_NO_PROTOTYPES @@ -5429,10 +7114,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( VkSwapchainKHR swapchain); #endif + #define VK_KHR_external_fence_capabilities 1 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities" - typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR; typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR; @@ -5441,12 +7126,10 @@ typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR; typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR; - typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR; typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; - typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); #ifndef VK_NO_PROTOTYPES @@ -5456,15 +7139,14 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( VkExternalFenceProperties* pExternalFenceProperties); #endif + #define VK_KHR_external_fence 1 #define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence" - typedef VkFenceImportFlags VkFenceImportFlagsKHR; typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR; - typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; @@ -5472,7 +7154,6 @@ typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR; #define VK_KHR_external_fence_fd 1 #define VK_KHR_EXTERNAL_FENCE_FD_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd" - typedef struct VkImportFenceFdInfoKHR { VkStructureType sType; const void* pNext; @@ -5489,7 +7170,6 @@ typedef struct VkFenceGetFdInfoKHR { VkExternalFenceHandleTypeFlagBits handleType; } VkFenceGetFdInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); @@ -5504,15 +7184,156 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( int* pFd); #endif -#define VK_KHR_maintenance2 1 -#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_performance_query 1 +#define VK_KHR_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME "VK_KHR_performance_query" + +typedef enum VkPerformanceCounterUnitKHR { + VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR = 0, + VK_PERFORMANCE_COUNTER_UNIT_PERCENTAGE_KHR = 1, + VK_PERFORMANCE_COUNTER_UNIT_NANOSECONDS_KHR = 2, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_KHR = 3, + VK_PERFORMANCE_COUNTER_UNIT_BYTES_PER_SECOND_KHR = 4, + VK_PERFORMANCE_COUNTER_UNIT_KELVIN_KHR = 5, + VK_PERFORMANCE_COUNTER_UNIT_WATTS_KHR = 6, + VK_PERFORMANCE_COUNTER_UNIT_VOLTS_KHR = 7, + VK_PERFORMANCE_COUNTER_UNIT_AMPS_KHR = 8, + VK_PERFORMANCE_COUNTER_UNIT_HERTZ_KHR = 9, + VK_PERFORMANCE_COUNTER_UNIT_CYCLES_KHR = 10, + VK_PERFORMANCE_COUNTER_UNIT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterUnitKHR; + +typedef enum VkPerformanceCounterScopeKHR { + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, + VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, + VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, + VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, + VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, + VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, + VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterScopeKHR; + +typedef enum VkPerformanceCounterStorageKHR { + VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR = 0, + VK_PERFORMANCE_COUNTER_STORAGE_INT64_KHR = 1, + VK_PERFORMANCE_COUNTER_STORAGE_UINT32_KHR = 2, + VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR = 3, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT32_KHR = 4, + VK_PERFORMANCE_COUNTER_STORAGE_FLOAT64_KHR = 5, + VK_PERFORMANCE_COUNTER_STORAGE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterStorageKHR; + +typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, + VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, + VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPerformanceCounterDescriptionFlagBitsKHR; +typedef VkFlags VkPerformanceCounterDescriptionFlagsKHR; + +typedef enum VkAcquireProfilingLockFlagBitsKHR { + VK_ACQUIRE_PROFILING_LOCK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAcquireProfilingLockFlagBitsKHR; +typedef VkFlags VkAcquireProfilingLockFlagsKHR; +typedef struct VkPhysicalDevicePerformanceQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 performanceCounterQueryPools; + VkBool32 performanceCounterMultipleQueryPools; +} VkPhysicalDevicePerformanceQueryFeaturesKHR; + +typedef struct VkPhysicalDevicePerformanceQueryPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 allowCommandBufferQueryCopies; +} VkPhysicalDevicePerformanceQueryPropertiesKHR; + +typedef struct VkPerformanceCounterKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterUnitKHR unit; + VkPerformanceCounterScopeKHR scope; + VkPerformanceCounterStorageKHR storage; + uint8_t uuid[VK_UUID_SIZE]; +} VkPerformanceCounterKHR; + +typedef struct VkPerformanceCounterDescriptionKHR { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsKHR flags; + char name[VK_MAX_DESCRIPTION_SIZE]; + char category[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionKHR; + +typedef struct VkQueryPoolPerformanceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + uint32_t counterIndexCount; + const uint32_t* pCounterIndices; +} VkQueryPoolPerformanceCreateInfoKHR; + +typedef union VkPerformanceCounterResultKHR { + int32_t int32; + int64_t int64; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; +} VkPerformanceCounterResultKHR; + +typedef struct VkAcquireProfilingLockInfoKHR { + VkStructureType sType; + const void* pNext; + VkAcquireProfilingLockFlagsKHR flags; + uint64_t timeout; +} VkAcquireProfilingLockInfoKHR; + +typedef struct VkPerformanceQuerySubmitInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t counterPassIndex; +} VkPerformanceQuerySubmitInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR)(VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterKHR* pCounters, + VkPerformanceCounterDescriptionKHR* pCounterDescriptions); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( + VkPhysicalDevice physicalDevice, + const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, + uint32_t* pNumPasses); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( + VkDevice device, + const VkAcquireProfilingLockInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( + VkDevice device); +#endif + + +#define VK_KHR_maintenance2 1 +#define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" +#define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION +#define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR; - typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR; typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR; @@ -5528,7 +7349,6 @@ typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellation #define VK_KHR_get_surface_capabilities2 1 #define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1 #define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2" - typedef struct VkPhysicalDeviceSurfaceInfo2KHR { VkStructureType sType; const void* pNext; @@ -5547,7 +7367,6 @@ typedef struct VkSurfaceFormat2KHR { VkSurfaceFormatKHR surfaceFormat; } VkSurfaceFormat2KHR; - typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); @@ -5564,18 +7383,82 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( VkSurfaceFormat2KHR* pSurfaceFormats); #endif + #define VK_KHR_variable_pointers 1 #define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1 #define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers" +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; -typedef VkPhysicalDeviceVariablePointerFeatures VkPhysicalDeviceVariablePointerFeaturesKHR; +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointersFeaturesKHR; +#define VK_KHR_get_display_properties2 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION 1 +#define VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_display_properties2" +typedef struct VkDisplayProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPropertiesKHR displayProperties; +} VkDisplayProperties2KHR; + +typedef struct VkDisplayPlaneProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlanePropertiesKHR displayPlaneProperties; +} VkDisplayPlaneProperties2KHR; + +typedef struct VkDisplayModeProperties2KHR { + VkStructureType sType; + void* pNext; + VkDisplayModePropertiesKHR displayModeProperties; +} VkDisplayModeProperties2KHR; + +typedef struct VkDisplayPlaneInfo2KHR { + VkStructureType sType; + const void* pNext; + VkDisplayModeKHR mode; + uint32_t planeIndex; +} VkDisplayPlaneInfo2KHR; + +typedef struct VkDisplayPlaneCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkDisplayPlaneCapabilitiesKHR capabilities; +} VkDisplayPlaneCapabilities2KHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlaneProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkDisplayPlaneProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display, + uint32_t* pPropertyCount, + VkDisplayModeProperties2KHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( + VkPhysicalDevice physicalDevice, + const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, + VkDisplayPlaneCapabilities2KHR* pCapabilities); +#endif + + #define VK_KHR_dedicated_allocation 1 #define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3 #define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation" - typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR; typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; @@ -5595,7 +7478,6 @@ typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; #define VK_KHR_get_memory_requirements2 1 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1 #define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2" - typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR; typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR; @@ -5606,7 +7488,6 @@ typedef VkMemoryRequirements2 VkMemoryRequirements2KHR; typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR; - typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); @@ -5629,33 +7510,25 @@ VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #endif + #define VK_KHR_image_format_list 1 #define VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION 1 #define VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME "VK_KHR_image_format_list" - -typedef struct VkImageFormatListCreateInfoKHR { - VkStructureType sType; - const void* pNext; - uint32_t viewFormatCount; - const VkFormat* pViewFormats; -} VkImageFormatListCreateInfoKHR; +typedef VkImageFormatListCreateInfo VkImageFormatListCreateInfoKHR; #define VK_KHR_sampler_ycbcr_conversion 1 typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR; - -#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1 +#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 14 #define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion" - typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR; typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR; typedef VkChromaLocation VkChromaLocationKHR; - typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR; typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR; @@ -5668,7 +7541,6 @@ typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYc typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); @@ -5685,15 +7557,14 @@ VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( const VkAllocationCallbacks* pAllocator); #endif + #define VK_KHR_bind_memory2 1 #define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1 #define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2" - typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR; typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); @@ -5709,15 +7580,16 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( const VkBindImageMemoryInfo* pBindInfos); #endif -#define VK_KHR_maintenance3 1 -#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1 -#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_maintenance3 1 +#define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" +#define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION +#define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; - typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); #ifndef VK_NO_PROTOTYPES @@ -5727,14 +7599,1104 @@ VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( VkDescriptorSetLayoutSupport* pSupport); #endif + +#define VK_KHR_draw_indirect_count 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 +#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count" +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +#define VK_KHR_shader_subgroup_extended_types 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME "VK_KHR_shader_subgroup_extended_types" +typedef VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR; + + + +#define VK_KHR_8bit_storage 1 +#define VK_KHR_8BIT_STORAGE_SPEC_VERSION 1 +#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME "VK_KHR_8bit_storage" +typedef VkPhysicalDevice8BitStorageFeatures VkPhysicalDevice8BitStorageFeaturesKHR; + + + +#define VK_KHR_shader_atomic_int64 1 +#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64" +typedef VkPhysicalDeviceShaderAtomicInt64Features VkPhysicalDeviceShaderAtomicInt64FeaturesKHR; + + + +#define VK_KHR_shader_clock 1 +#define VK_KHR_SHADER_CLOCK_SPEC_VERSION 1 +#define VK_KHR_SHADER_CLOCK_EXTENSION_NAME "VK_KHR_shader_clock" +typedef struct VkPhysicalDeviceShaderClockFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupClock; + VkBool32 shaderDeviceClock; +} VkPhysicalDeviceShaderClockFeaturesKHR; + + + +#define VK_KHR_driver_properties 1 +#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties" +#define VK_MAX_DRIVER_NAME_SIZE_KHR VK_MAX_DRIVER_NAME_SIZE +#define VK_MAX_DRIVER_INFO_SIZE_KHR VK_MAX_DRIVER_INFO_SIZE +typedef VkDriverId VkDriverIdKHR; + +typedef VkConformanceVersion VkConformanceVersionKHR; + +typedef VkPhysicalDeviceDriverProperties VkPhysicalDeviceDriverPropertiesKHR; + + + +#define VK_KHR_shader_float_controls 1 +#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 4 +#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls" +typedef VkShaderFloatControlsIndependence VkShaderFloatControlsIndependenceKHR; + +typedef VkPhysicalDeviceFloatControlsProperties VkPhysicalDeviceFloatControlsPropertiesKHR; + + + +#define VK_KHR_depth_stencil_resolve 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION 1 +#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME "VK_KHR_depth_stencil_resolve" +typedef VkResolveModeFlagBits VkResolveModeFlagBitsKHR; + +typedef VkResolveModeFlags VkResolveModeFlagsKHR; + +typedef VkSubpassDescriptionDepthStencilResolve VkSubpassDescriptionDepthStencilResolveKHR; + +typedef VkPhysicalDeviceDepthStencilResolveProperties VkPhysicalDeviceDepthStencilResolvePropertiesKHR; + + + +#define VK_KHR_swapchain_mutable_format 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format" + + +#define VK_KHR_timeline_semaphore 1 +#define VK_KHR_TIMELINE_SEMAPHORE_SPEC_VERSION 2 +#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME "VK_KHR_timeline_semaphore" +typedef VkSemaphoreType VkSemaphoreTypeKHR; + +typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR; + +typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreFeatures VkPhysicalDeviceTimelineSemaphoreFeaturesKHR; + +typedef VkPhysicalDeviceTimelineSemaphoreProperties VkPhysicalDeviceTimelineSemaphorePropertiesKHR; + +typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR; + +typedef VkTimelineSemaphoreSubmitInfo VkTimelineSemaphoreSubmitInfoKHR; + +typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR; + +typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValueKHR)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); +#endif + + +#define VK_KHR_vulkan_memory_model 1 +#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 3 +#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model" +typedef VkPhysicalDeviceVulkanMemoryModelFeatures VkPhysicalDeviceVulkanMemoryModelFeaturesKHR; + + + +#define VK_KHR_shader_terminate_invocation 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION 1 +#define VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME "VK_KHR_shader_terminate_invocation" +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR; + + + +#define VK_KHR_fragment_shading_rate 1 +#define VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION 2 +#define VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME "VK_KHR_fragment_shading_rate" + +typedef enum VkFragmentShadingRateCombinerOpKHR { + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4, + VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_ENUM_KHR = 0x7FFFFFFF +} VkFragmentShadingRateCombinerOpKHR; +typedef struct VkFragmentShadingRateAttachmentInfoKHR { + VkStructureType sType; + const void* pNext; + const VkAttachmentReference2* pFragmentShadingRateAttachment; + VkExtent2D shadingRateAttachmentTexelSize; +} VkFragmentShadingRateAttachmentInfoKHR; + +typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkExtent2D fragmentSize; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateStateCreateInfoKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineFragmentShadingRate; + VkBool32 primitiveFragmentShadingRate; + VkBool32 attachmentFragmentShadingRate; +} VkPhysicalDeviceFragmentShadingRateFeaturesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentShadingRateAttachmentTexelSize; + VkExtent2D maxFragmentShadingRateAttachmentTexelSize; + uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio; + VkBool32 primitiveFragmentShadingRateWithMultipleViewports; + VkBool32 layeredShadingRateAttachments; + VkBool32 fragmentShadingRateNonTrivialCombinerOps; + VkExtent2D maxFragmentSize; + uint32_t maxFragmentSizeAspectRatio; + uint32_t maxFragmentShadingRateCoverageSamples; + VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples; + VkBool32 fragmentShadingRateWithShaderDepthStencilWrites; + VkBool32 fragmentShadingRateWithSampleMask; + VkBool32 fragmentShadingRateWithShaderSampleMask; + VkBool32 fragmentShadingRateWithConservativeRasterization; + VkBool32 fragmentShadingRateWithFragmentShaderInterlock; + VkBool32 fragmentShadingRateWithCustomSampleLocations; + VkBool32 fragmentShadingRateStrictMultiplyCombiner; +} VkPhysicalDeviceFragmentShadingRatePropertiesKHR; + +typedef struct VkPhysicalDeviceFragmentShadingRateKHR { + VkStructureType sType; + void* pNext; + VkSampleCountFlags sampleCounts; + VkExtent2D fragmentSize; +} VkPhysicalDeviceFragmentShadingRateKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( + VkPhysicalDevice physicalDevice, + uint32_t* pFragmentShadingRateCount, + VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( + VkCommandBuffer commandBuffer, + const VkExtent2D* pFragmentSize, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_KHR_spirv_1_4 1 +#define VK_KHR_SPIRV_1_4_SPEC_VERSION 1 +#define VK_KHR_SPIRV_1_4_EXTENSION_NAME "VK_KHR_spirv_1_4" + + +#define VK_KHR_surface_protected_capabilities 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION 1 +#define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" +typedef struct VkSurfaceProtectedCapabilitiesKHR { + VkStructureType sType; + const void* pNext; + VkBool32 supportsProtected; +} VkSurfaceProtectedCapabilitiesKHR; + + + +#define VK_KHR_separate_depth_stencil_layouts 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME "VK_KHR_separate_depth_stencil_layouts" +typedef VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR; + +typedef VkAttachmentReferenceStencilLayout VkAttachmentReferenceStencilLayoutKHR; + +typedef VkAttachmentDescriptionStencilLayout VkAttachmentDescriptionStencilLayoutKHR; + + + +#define VK_KHR_present_wait 1 +#define VK_KHR_PRESENT_WAIT_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_EXTENSION_NAME "VK_KHR_present_wait" +typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait; +} VkPhysicalDevicePresentWaitFeaturesKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t presentId, + uint64_t timeout); +#endif + + +#define VK_KHR_uniform_buffer_standard_layout 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME "VK_KHR_uniform_buffer_standard_layout" +typedef VkPhysicalDeviceUniformBufferStandardLayoutFeatures VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR; + + + +#define VK_KHR_buffer_device_address 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 1 +#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_KHR_buffer_device_address" +typedef VkPhysicalDeviceBufferDeviceAddressFeatures VkPhysicalDeviceBufferDeviceAddressFeaturesKHR; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR; + +typedef VkBufferOpaqueCaptureAddressCreateInfo VkBufferOpaqueCaptureAddressCreateInfoKHR; + +typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR; + +typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +#endif + + +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 4 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + + +#define VK_KHR_pipeline_executable_properties 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME "VK_KHR_pipeline_executable_properties" + +typedef enum VkPipelineExecutableStatisticFormatKHR { + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR = 0, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR = 1, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR = 2, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR = 3, + VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPipelineExecutableStatisticFormatKHR; +typedef struct VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 pipelineExecutableInfo; +} VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR; + +typedef struct VkPipelineInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; +} VkPipelineInfoKHR; + +typedef struct VkPipelineExecutablePropertiesKHR { + VkStructureType sType; + void* pNext; + VkShaderStageFlags stages; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + uint32_t subgroupSize; +} VkPipelineExecutablePropertiesKHR; + +typedef struct VkPipelineExecutableInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipeline pipeline; + uint32_t executableIndex; +} VkPipelineExecutableInfoKHR; + +typedef union VkPipelineExecutableStatisticValueKHR { + VkBool32 b32; + int64_t i64; + uint64_t u64; + double f64; +} VkPipelineExecutableStatisticValueKHR; + +typedef struct VkPipelineExecutableStatisticKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkPipelineExecutableStatisticFormatKHR format; + VkPipelineExecutableStatisticValueKHR value; +} VkPipelineExecutableStatisticKHR; + +typedef struct VkPipelineExecutableInternalRepresentationKHR { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkPipelineExecutableInternalRepresentationKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutablePropertiesKHR)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + uint32_t* pExecutableCount, + VkPipelineExecutablePropertiesKHR* pProperties); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pStatisticCount, + VkPipelineExecutableStatisticKHR* pStatistics); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); +#endif + + +#define VK_KHR_shader_integer_dot_product 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME "VK_KHR_shader_integer_dot_product" +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR; + + + +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + +#define VK_KHR_shader_non_semantic_info 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" + + +#define VK_KHR_present_id 1 +#define VK_KHR_PRESENT_ID_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_EXTENSION_NAME "VK_KHR_present_id" +typedef struct VkPresentIdKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentIdKHR; + +typedef struct VkPhysicalDevicePresentIdFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId; +} VkPhysicalDevicePresentIdFeaturesKHR; + + + +#define VK_KHR_synchronization2 1 +typedef uint64_t VkFlags64; +#define VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION 1 +#define VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME "VK_KHR_synchronization2" +typedef VkFlags64 VkPipelineStageFlags2KHR; + +// Flag bits for VkPipelineStageFlagBits2KHR +typedef VkFlags64 VkPipelineStageFlagBits2KHR; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL; +#endif +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; +static const VkPipelineStageFlagBits2KHR VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; + +typedef VkFlags64 VkAccessFlags2KHR; + +// Flag bits for VkAccessFlagBits2KHR +typedef VkFlags64 VkAccessFlagBits2KHR; +static const VkAccessFlagBits2KHR VK_ACCESS_2_NONE_KHR = 0ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkAccessFlagBits2KHR VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +#endif +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL; +static const VkAccessFlagBits2KHR VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL; + + +typedef enum VkSubmitFlagBitsKHR { + VK_SUBMIT_PROTECTED_BIT_KHR = 0x00000001, + VK_SUBMIT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkSubmitFlagBitsKHR; +typedef VkFlags VkSubmitFlagsKHR; +typedef struct VkMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; +} VkMemoryBarrier2KHR; + +typedef struct VkBufferMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2KHR; + +typedef struct VkImageMemoryBarrier2KHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR srcStageMask; + VkAccessFlags2KHR srcAccessMask; + VkPipelineStageFlags2KHR dstStageMask; + VkAccessFlags2KHR dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2KHR; + +typedef struct VkDependencyInfoKHR { + VkStructureType sType; + const void* pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2KHR* pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2KHR* pImageMemoryBarriers; +} VkDependencyInfoKHR; + +typedef struct VkSemaphoreSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2KHR stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfoKHR; + +typedef struct VkCommandBufferSubmitInfoKHR { + VkStructureType sType; + const void* pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfoKHR; + +typedef struct VkSubmitInfo2KHR { + VkStructureType sType; + const void* pNext; + VkSubmitFlagsKHR flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos; +} VkSubmitInfo2KHR; + +typedef struct VkPhysicalDeviceSynchronization2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2FeaturesKHR; + +typedef struct VkQueueFamilyCheckpointProperties2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR checkpointExecutionStageMask; +} VkQueueFamilyCheckpointProperties2NV; + +typedef struct VkCheckpointData2NV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags2KHR stage; + void* pCheckpointMarker; +} VkCheckpointData2NV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfos); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkQueryPool queryPool, uint32_t query); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits, VkFence fence); +typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2KHR stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfoKHR* pDependencyInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( + VkCommandBuffer commandBuffer, + const VkDependencyInfoKHR* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo2KHR* pSubmits, + VkFence fence); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags2KHR stage, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + uint32_t marker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointData2NV* pCheckpointData); +#endif + + +#define VK_KHR_shader_subgroup_uniform_control_flow 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION 1 +#define VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME "VK_KHR_shader_subgroup_uniform_control_flow" +typedef struct VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupUniformControlFlow; +} VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR; + + + +#define VK_KHR_zero_initialize_workgroup_memory 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION 1 +#define VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME "VK_KHR_zero_initialize_workgroup_memory" +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR; + + + +#define VK_KHR_workgroup_memory_explicit_layout 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION 1 +#define VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME "VK_KHR_workgroup_memory_explicit_layout" +typedef struct VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 workgroupMemoryExplicitLayout; + VkBool32 workgroupMemoryExplicitLayoutScalarBlockLayout; + VkBool32 workgroupMemoryExplicitLayout8BitAccess; + VkBool32 workgroupMemoryExplicitLayout16BitAccess; +} VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR; + + + +#define VK_KHR_copy_commands2 1 +#define VK_KHR_COPY_COMMANDS_2_SPEC_VERSION 1 +#define VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME "VK_KHR_copy_commands2" +typedef struct VkBufferCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2KHR; + +typedef struct VkCopyBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2KHR* pRegions; +} VkCopyBufferInfo2KHR; + +typedef struct VkImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2KHR; + +typedef struct VkCopyImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2KHR* pRegions; +} VkCopyImageInfo2KHR; + +typedef struct VkBufferImageCopy2KHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2KHR; + +typedef struct VkCopyBufferToImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyBufferToImageInfo2KHR; + +typedef struct VkCopyImageToBufferInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2KHR* pRegions; +} VkCopyImageToBufferInfo2KHR; + +typedef struct VkImageBlit2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets[2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets[2]; +} VkImageBlit2KHR; + +typedef struct VkBlitImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2KHR* pRegions; + VkFilter filter; +} VkBlitImageInfo2KHR; + +typedef struct VkImageResolve2KHR { + VkStructureType sType; + const void* pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2KHR; + +typedef struct VkResolveImageInfo2KHR { + VkStructureType sType; + const void* pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2KHR* pRegions; +} VkResolveImageInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR* pCopyBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR* pCopyImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2KHR)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2KHR)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR* pBlitImageInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2KHR* pResolveImageInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferInfo2KHR* pCopyBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageInfo2KHR* pCopyImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( + VkCommandBuffer commandBuffer, + const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( + VkCommandBuffer commandBuffer, + const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( + VkCommandBuffer commandBuffer, + const VkBlitImageInfo2KHR* pBlitImageInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2KHR* pResolveImageInfo); +#endif + + +#define VK_KHR_format_feature_flags2 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION 1 +#define VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME "VK_KHR_format_feature_flags2" +typedef VkFlags64 VkFormatFeatureFlags2KHR; + +// Flag bits for VkFormatFeatureFlagBits2KHR +typedef VkFlags64 VkFormatFeatureFlagBits2KHR; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 0x00000020ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 0x00000100ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000200ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 0x00000400ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 0x00000800ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 0x00001000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 0x00002000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 0x00004000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 0x00008000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 0x00010000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 0x00400000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 0x80000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 0x100000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 0x200000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR = 0x02000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x04000000ULL; +#endif +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000ULL; +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkFormatFeatureFlagBits2KHR VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +#endif + +typedef struct VkFormatProperties3KHR { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2KHR linearTilingFeatures; + VkFormatFeatureFlags2KHR optimalTilingFeatures; + VkFormatFeatureFlags2KHR bufferFeatures; +} VkFormatProperties3KHR; + + + +#define VK_KHR_maintenance4 1 +#define VK_KHR_MAINTENANCE_4_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_4_EXTENSION_NAME "VK_KHR_maintenance4" +typedef struct VkPhysicalDeviceMaintenance4FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance4PropertiesKHR { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4PropertiesKHR; + +typedef struct VkDeviceBufferMemoryRequirementsKHR { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirementsKHR; + +typedef struct VkDeviceImageMemoryRequirementsKHR { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirementsKHR; + +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirementsKHR)(VkDevice device, const VkDeviceBufferMemoryRequirementsKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirementsKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirementsKHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( + VkDevice device, + const VkDeviceBufferMemoryRequirementsKHR* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirementsKHR* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( + VkDevice device, + const VkDeviceImageMemoryRequirementsKHR* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +#endif + + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) - -#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" -#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT -#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT - typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, @@ -5768,20 +8730,21 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, - VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31, - VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT = 1000029000, + VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT = 1000029001, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000150000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, + VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1), VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportObjectTypeEXT; - typedef enum VkDebugReportFlagBitsEXT { VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001, VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002, @@ -5791,7 +8754,6 @@ typedef enum VkDebugReportFlagBitsEXT { VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportFlagBitsEXT; typedef VkFlags VkDebugReportFlagsEXT; - typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, @@ -5810,7 +8772,6 @@ typedef struct VkDebugReportCallbackCreateInfoEXT { void* pUserData; } VkDebugReportCallbackCreateInfoEXT; - typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); @@ -5838,6 +8799,7 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( const char* pMessage); #endif + #define VK_NV_glsl_shader 1 #define VK_NV_GLSL_SHADER_SPEC_VERSION 1 #define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader" @@ -5857,16 +8819,11 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( #define VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION 1 #define VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME "VK_AMD_rasterization_order" - typedef enum VkRasterizationOrderAMD { VK_RASTERIZATION_ORDER_STRICT_AMD = 0, VK_RASTERIZATION_ORDER_RELAXED_AMD = 1, - VK_RASTERIZATION_ORDER_BEGIN_RANGE_AMD = VK_RASTERIZATION_ORDER_STRICT_AMD, - VK_RASTERIZATION_ORDER_END_RANGE_AMD = VK_RASTERIZATION_ORDER_RELAXED_AMD, - VK_RASTERIZATION_ORDER_RANGE_SIZE_AMD = (VK_RASTERIZATION_ORDER_RELAXED_AMD - VK_RASTERIZATION_ORDER_STRICT_AMD + 1), VK_RASTERIZATION_ORDER_MAX_ENUM_AMD = 0x7FFFFFFF } VkRasterizationOrderAMD; - typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { VkStructureType sType; const void* pNext; @@ -5888,7 +8845,6 @@ typedef struct VkPipelineRasterizationStateRasterizationOrderAMD { #define VK_EXT_debug_marker 1 #define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4 #define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker" - typedef struct VkDebugMarkerObjectNameInfoEXT { VkStructureType sType; const void* pNext; @@ -5914,7 +8870,6 @@ typedef struct VkDebugMarkerMarkerInfoEXT { float color[4]; } VkDebugMarkerMarkerInfoEXT; - typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectTagEXT)(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); typedef VkResult (VKAPI_PTR *PFN_vkDebugMarkerSetObjectNameEXT)(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerBeginEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); @@ -5942,6 +8897,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); #endif + #define VK_AMD_gcn_shader 1 #define VK_AMD_GCN_SHADER_SPEC_VERSION 1 #define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader" @@ -5950,7 +8906,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( #define VK_NV_dedicated_allocation 1 #define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1 #define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation" - typedef struct VkDedicatedAllocationImageCreateInfoNV { VkStructureType sType; const void* pNext; @@ -5972,10 +8927,200 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV { -#define VK_AMD_draw_indirect_count 1 -#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1 -#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" +#define VK_EXT_transform_feedback 1 +#define VK_EXT_TRANSFORM_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME "VK_EXT_transform_feedback" +typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT; +typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 transformFeedback; + VkBool32 geometryStreams; +} VkPhysicalDeviceTransformFeedbackFeaturesEXT; +typedef struct VkPhysicalDeviceTransformFeedbackPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxTransformFeedbackStreams; + uint32_t maxTransformFeedbackBuffers; + VkDeviceSize maxTransformFeedbackBufferSize; + uint32_t maxTransformFeedbackStreamDataSize; + uint32_t maxTransformFeedbackBufferDataSize; + uint32_t maxTransformFeedbackBufferDataStride; + VkBool32 transformFeedbackQueries; + VkBool32 transformFeedbackStreamsLinesTriangles; + VkBool32 transformFeedbackRasterizationStreamSelect; + VkBool32 transformFeedbackDraw; +} VkPhysicalDeviceTransformFeedbackPropertiesEXT; + +typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateStreamCreateFlagsEXT flags; + uint32_t rasterizationStream; +} VkPipelineRasterizationStateStreamCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffersEXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedbackEXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterBuffer, + uint32_t counterBufferCount, + const VkBuffer* pCounterBuffers, + const VkDeviceSize* pCounterBufferOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + uint32_t index); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, + uint32_t counterOffset, + uint32_t vertexStride); +#endif + + +#define VK_NVX_binary_import 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuModuleNVX) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCuFunctionNVX) +#define VK_NVX_BINARY_IMPORT_SPEC_VERSION 1 +#define VK_NVX_BINARY_IMPORT_EXTENSION_NAME "VK_NVX_binary_import" +typedef struct VkCuModuleCreateInfoNVX { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCuModuleCreateInfoNVX; + +typedef struct VkCuFunctionCreateInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuModuleNVX module; + const char* pName; +} VkCuFunctionCreateInfoNVX; + +typedef struct VkCuLaunchInfoNVX { + VkStructureType sType; + const void* pNext; + VkCuFunctionNVX function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCuLaunchInfoNVX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuModuleNVX)(VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCuFunctionNVX)(VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCuModuleNVX)(VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( + VkDevice device, + const VkCuModuleCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuModuleNVX* pModule); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( + VkDevice device, + const VkCuFunctionCreateInfoNVX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCuFunctionNVX* pFunction); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( + VkDevice device, + VkCuModuleNVX module, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( + VkDevice device, + VkCuFunctionNVX function, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( + VkCommandBuffer commandBuffer, + const VkCuLaunchInfoNVX* pLaunchInfo); +#endif + + +#define VK_NVX_image_view_handle 1 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2 +#define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" +typedef struct VkImageViewHandleInfoNVX { + VkStructureType sType; + const void* pNext; + VkImageView imageView; + VkDescriptorType descriptorType; + VkSampler sampler; +} VkImageViewHandleInfoNVX; + +typedef struct VkImageViewAddressPropertiesNVX { + VkStructureType sType; + void* pNext; + VkDeviceAddress deviceAddress; + VkDeviceSize size; +} VkImageViewAddressPropertiesNVX; + +typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( + VkDevice device, + const VkImageViewHandleInfoNVX* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( + VkDevice device, + VkImageView imageView, + VkImageViewAddressPropertiesNVX* pProperties); +#endif + + +#define VK_AMD_draw_indirect_count 1 +#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 2 +#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count" typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); @@ -5999,13 +9144,14 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( uint32_t stride); #endif + #define VK_AMD_negative_viewport_height 1 #define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1 #define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height" #define VK_AMD_gpu_shader_half_float 1 -#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1 +#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 2 #define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float" @@ -6017,7 +9163,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( #define VK_AMD_texture_gather_bias_lod 1 #define VK_AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION 1 #define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod" - typedef struct VkTextureLODGatherFormatPropertiesAMD { VkStructureType sType; void* pNext; @@ -6030,17 +9175,12 @@ typedef struct VkTextureLODGatherFormatPropertiesAMD { #define VK_AMD_SHADER_INFO_SPEC_VERSION 1 #define VK_AMD_SHADER_INFO_EXTENSION_NAME "VK_AMD_shader_info" - typedef enum VkShaderInfoTypeAMD { VK_SHADER_INFO_TYPE_STATISTICS_AMD = 0, VK_SHADER_INFO_TYPE_BINARY_AMD = 1, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD = 2, - VK_SHADER_INFO_TYPE_BEGIN_RANGE_AMD = VK_SHADER_INFO_TYPE_STATISTICS_AMD, - VK_SHADER_INFO_TYPE_END_RANGE_AMD = VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD, - VK_SHADER_INFO_TYPE_RANGE_SIZE_AMD = (VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD - VK_SHADER_INFO_TYPE_STATISTICS_AMD + 1), VK_SHADER_INFO_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF } VkShaderInfoTypeAMD; - typedef struct VkShaderResourceUsageAMD { uint32_t numUsedVgprs; uint32_t numUsedSgprs; @@ -6059,7 +9199,6 @@ typedef struct VkShaderStatisticsInfoAMD { uint32_t computeWorkGroupSize[3]; } VkShaderStatisticsInfoAMD; - typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); #ifndef VK_NO_PROTOTYPES @@ -6072,11 +9211,23 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( void* pInfo); #endif + #define VK_AMD_shader_image_load_store_lod 1 #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1 #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod" +#define VK_NV_corner_sampled_image 1 +#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2 +#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image" +typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cornerSampledImage; +} VkPhysicalDeviceCornerSampledImageFeaturesNV; + + + #define VK_IMG_format_pvrtc 1 #define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1 #define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc" @@ -6086,7 +9237,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( #define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities" - typedef enum VkExternalMemoryHandleTypeFlagBitsNV { VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002, @@ -6103,7 +9253,6 @@ typedef enum VkExternalMemoryFeatureFlagBitsNV { VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF } VkExternalMemoryFeatureFlagBitsNV; typedef VkFlags VkExternalMemoryFeatureFlagsNV; - typedef struct VkExternalImageFormatPropertiesNV { VkImageFormatProperties imageFormatProperties; VkExternalMemoryFeatureFlagsNV externalMemoryFeatures; @@ -6111,7 +9260,6 @@ typedef struct VkExternalImageFormatPropertiesNV { VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes; } VkExternalImageFormatPropertiesNV; - typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); #ifndef VK_NO_PROTOTYPES @@ -6126,10 +9274,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesN VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); #endif + #define VK_NV_external_memory 1 #define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory" - typedef struct VkExternalMemoryImageCreateInfoNV { VkStructureType sType; const void* pNext; @@ -6145,24 +9293,19 @@ typedef struct VkExportMemoryAllocateInfoNV { #define VK_EXT_validation_flags 1 -#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1 +#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 2 #define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags" - typedef enum VkValidationCheckEXT { VK_VALIDATION_CHECK_ALL_EXT = 0, VK_VALIDATION_CHECK_SHADERS_EXT = 1, - VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT, - VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_SHADERS_EXT, - VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_SHADERS_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1), VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationCheckEXT; - typedef struct VkValidationFlagsEXT { - VkStructureType sType; - const void* pNext; - uint32_t disabledValidationCheckCount; - VkValidationCheckEXT* pDisabledValidationChecks; + VkStructureType sType; + const void* pNext; + uint32_t disabledValidationCheckCount; + const VkValidationCheckEXT* pDisabledValidationChecks; } VkValidationFlagsEXT; @@ -6177,237 +9320,80 @@ typedef struct VkValidationFlagsEXT { #define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote" -#define VK_NVX_device_generated_commands 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX) - -#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 -#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands" +#define VK_EXT_texture_compression_astc_hdr 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME "VK_EXT_texture_compression_astc_hdr" +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT; -typedef enum VkIndirectCommandsTokenTypeNVX { - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1), - VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsTokenTypeNVX; -typedef enum VkObjectEntryTypeNVX { - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0, - VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1, - VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2, - VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3, - VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4, - VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX, - VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX, - VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1), - VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryTypeNVX; - - -typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX { - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsLayoutUsageFlagBitsNVX; -typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX; - -typedef enum VkObjectEntryUsageFlagBitsNVX { - VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001, - VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002, - VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryUsageFlagBitsNVX; -typedef VkFlags VkObjectEntryUsageFlagsNVX; - -typedef struct VkDeviceGeneratedCommandsFeaturesNVX { +#define VK_EXT_astc_decode_mode 1 +#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1 +#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode" +typedef struct VkImageViewASTCDecodeModeEXT { VkStructureType sType; const void* pNext; - VkBool32 computeBindingPointSupport; -} VkDeviceGeneratedCommandsFeaturesNVX; + VkFormat decodeMode; +} VkImageViewASTCDecodeModeEXT; -typedef struct VkDeviceGeneratedCommandsLimitsNVX { +typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT { VkStructureType sType; - const void* pNext; - uint32_t maxIndirectCommandsLayoutTokenCount; - uint32_t maxObjectEntryCounts; - uint32_t minSequenceCountBufferOffsetAlignment; - uint32_t minSequenceIndexBufferOffsetAlignment; - uint32_t minCommandsTokenBufferOffsetAlignment; -} VkDeviceGeneratedCommandsLimitsNVX; + void* pNext; + VkBool32 decodeModeSharedExponent; +} VkPhysicalDeviceASTCDecodeFeaturesEXT; -typedef struct VkIndirectCommandsTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; + + +#define VK_EXT_conditional_rendering 1 +#define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 +#define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" + +typedef enum VkConditionalRenderingFlagBitsEXT { + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, + VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConditionalRenderingFlagBitsEXT; +typedef VkFlags VkConditionalRenderingFlagsEXT; +typedef struct VkConditionalRenderingBeginInfoEXT { + VkStructureType sType; + const void* pNext; VkBuffer buffer; VkDeviceSize offset; -} VkIndirectCommandsTokenNVX; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfoEXT; -typedef struct VkIndirectCommandsLayoutTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - uint32_t bindingUnit; - uint32_t dynamicCount; - uint32_t divisor; -} VkIndirectCommandsLayoutTokenNVX; +typedef struct VkPhysicalDeviceConditionalRenderingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 conditionalRendering; + VkBool32 inheritedConditionalRendering; +} VkPhysicalDeviceConditionalRenderingFeaturesEXT; -typedef struct VkIndirectCommandsLayoutCreateInfoNVX { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkIndirectCommandsLayoutUsageFlagsNVX flags; - uint32_t tokenCount; - const VkIndirectCommandsLayoutTokenNVX* pTokens; -} VkIndirectCommandsLayoutCreateInfoNVX; +typedef struct VkCommandBufferInheritanceConditionalRenderingInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 conditionalRenderingEnable; +} VkCommandBufferInheritanceConditionalRenderingInfoEXT; -typedef struct VkCmdProcessCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t indirectCommandsTokenCount; - const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens; - uint32_t maxSequencesCount; - VkCommandBuffer targetCommandBuffer; - VkBuffer sequencesCountBuffer; - VkDeviceSize sequencesCountOffset; - VkBuffer sequencesIndexBuffer; - VkDeviceSize sequencesIndexOffset; -} VkCmdProcessCommandsInfoNVX; - -typedef struct VkCmdReserveSpaceForCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t maxSequencesCount; -} VkCmdReserveSpaceForCommandsInfoNVX; - -typedef struct VkObjectTableCreateInfoNVX { - VkStructureType sType; - const void* pNext; - uint32_t objectCount; - const VkObjectEntryTypeNVX* pObjectEntryTypes; - const uint32_t* pObjectEntryCounts; - const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags; - uint32_t maxUniformBuffersPerDescriptor; - uint32_t maxStorageBuffersPerDescriptor; - uint32_t maxStorageImagesPerDescriptor; - uint32_t maxSampledImagesPerDescriptor; - uint32_t maxPipelineLayouts; -} VkObjectTableCreateInfoNVX; - -typedef struct VkObjectTableEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; -} VkObjectTableEntryNVX; - -typedef struct VkObjectTablePipelineEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipeline pipeline; -} VkObjectTablePipelineEntryNVX; - -typedef struct VkObjectTableDescriptorSetEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; -} VkObjectTableDescriptorSetEntryNVX; - -typedef struct VkObjectTableVertexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; -} VkObjectTableVertexBufferEntryNVX; - -typedef struct VkObjectTableIndexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; - VkIndexType indexType; -} VkObjectTableIndexBufferEntryNVX; - -typedef struct VkObjectTablePushConstantEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkShaderStageFlags stageFlags; -} VkObjectTablePushConstantEntryNVX; - - -typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable); -typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices); -typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits); +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX( +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( VkCommandBuffer commandBuffer, - const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); + const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); -VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX( - VkDevice device, - const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX( - VkDevice device, - VkIndirectCommandsLayoutNVX indirectCommandsLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX( - VkDevice device, - const VkObjectTableCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkObjectTableNVX* pObjectTable); - -VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX( - VkDevice device, - VkObjectTableNVX objectTable, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectTableEntryNVX* const* ppObjectTableEntries, - const uint32_t* pObjectIndices); - -VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectEntryTypeNVX* pObjectEntryTypes, - const uint32_t* pObjectIndices); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( - VkPhysicalDevice physicalDevice, - VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, - VkDeviceGeneratedCommandsLimitsNVX* pLimits); +VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( + VkCommandBuffer commandBuffer); #endif + #define VK_NV_clip_space_w_scaling 1 #define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 #define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" - typedef struct VkViewportWScalingNV { float xcoeff; float ycoeff; @@ -6421,7 +9407,6 @@ typedef struct VkPipelineViewportWScalingStateCreateInfoNV { const VkViewportWScalingNV* pViewportWScalings; } VkPipelineViewportWScalingStateCreateInfoNV; - typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); #ifndef VK_NO_PROTOTYPES @@ -6432,10 +9417,10 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( const VkViewportWScalingNV* pViewportWScalings); #endif + #define VK_EXT_direct_mode_display 1 #define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1 #define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display" - typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); #ifndef VK_NO_PROTOTYPES @@ -6444,18 +9429,17 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( VkDisplayKHR display); #endif + #define VK_EXT_display_surface_counter 1 #define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1 #define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter" -#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT - typedef enum VkSurfaceCounterFlagBitsEXT { - VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, + VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkSurfaceCounterFlagBitsEXT; typedef VkFlags VkSurfaceCounterFlagsEXT; - typedef struct VkSurfaceCapabilities2EXT { VkStructureType sType; void* pNext; @@ -6472,7 +9456,6 @@ typedef struct VkSurfaceCapabilities2EXT { VkSurfaceCounterFlagsEXT supportedSurfaceCounters; } VkSurfaceCapabilities2EXT; - typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); #ifndef VK_NO_PROTOTYPES @@ -6482,37 +9465,27 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( VkSurfaceCapabilities2EXT* pSurfaceCapabilities); #endif + #define VK_EXT_display_control 1 #define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1 #define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control" - typedef enum VkDisplayPowerStateEXT { VK_DISPLAY_POWER_STATE_OFF_EXT = 0, VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1, VK_DISPLAY_POWER_STATE_ON_EXT = 2, - VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT, - VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT, - VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1), VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDisplayPowerStateEXT; typedef enum VkDeviceEventTypeEXT { VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0, - VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT, - VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1), VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDeviceEventTypeEXT; typedef enum VkDisplayEventTypeEXT { VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0, - VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT, - VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1), VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDisplayEventTypeEXT; - typedef struct VkDisplayPowerInfoEXT { VkStructureType sType; const void* pNext; @@ -6537,7 +9510,6 @@ typedef struct VkSwapchainCounterCreateInfoEXT { VkSurfaceCounterFlagsEXT surfaceCounters; } VkSwapchainCounterCreateInfoEXT; - typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); @@ -6569,10 +9541,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( uint64_t* pCounterValue); #endif + #define VK_GOOGLE_display_timing 1 #define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1 #define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing" - typedef struct VkRefreshCycleDurationGOOGLE { uint64_t refreshDuration; } VkRefreshCycleDurationGOOGLE; @@ -6597,7 +9569,6 @@ typedef struct VkPresentTimesInfoGOOGLE { const VkPresentTimeGOOGLE* pTimes; } VkPresentTimesInfoGOOGLE; - typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); @@ -6614,6 +9585,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( VkPastPresentationTimingGOOGLE* pPresentationTimings); #endif + #define VK_NV_sample_mask_override_coverage 1 #define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1 #define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage" @@ -6625,14 +9597,15 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( #define VK_NV_viewport_array2 1 -#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1 -#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 +#define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" +#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION +#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME #define VK_NVX_multiview_per_view_attributes 1 #define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1 #define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes" - typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { VkStructureType sType; void* pNext; @@ -6645,7 +9618,6 @@ typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX { #define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1 #define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle" - typedef enum VkViewportCoordinateSwizzleNV { VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0, VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1, @@ -6655,14 +9627,9 @@ typedef enum VkViewportCoordinateSwizzleNV { VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6, VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7, - VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV, - VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1), VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF } VkViewportCoordinateSwizzleNV; - typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV; - typedef struct VkViewportSwizzleNV { VkViewportCoordinateSwizzleNV x; VkViewportCoordinateSwizzleNV y; @@ -6684,18 +9651,12 @@ typedef struct VkPipelineViewportSwizzleStateCreateInfoNV { #define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1 #define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles" - typedef enum VkDiscardRectangleModeEXT { VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0, VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1, - VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT, - VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1), VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDiscardRectangleModeEXT; - typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT; - typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT { VkStructureType sType; void* pNext; @@ -6711,7 +9672,6 @@ typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT { const VkRect2D* pDiscardRectangles; } VkPipelineDiscardRectangleStateCreateInfoEXT; - typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); #ifndef VK_NO_PROTOTYPES @@ -6722,23 +9682,18 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( const VkRect2D* pDiscardRectangles); #endif + #define VK_EXT_conservative_rasterization 1 #define VK_EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION 1 #define VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME "VK_EXT_conservative_rasterization" - typedef enum VkConservativeRasterizationModeEXT { VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0, VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1, VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2, - VK_CONSERVATIVE_RASTERIZATION_MODE_BEGIN_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT, - VK_CONSERVATIVE_RASTERIZATION_MODE_END_RANGE_EXT = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT, - VK_CONSERVATIVE_RASTERIZATION_MODE_RANGE_SIZE_EXT = (VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT - VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT + 1), VK_CONSERVATIVE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkConservativeRasterizationModeEXT; - typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT; - typedef struct VkPhysicalDeviceConservativeRasterizationPropertiesEXT { VkStructureType sType; void* pNext; @@ -6763,15 +9718,33 @@ typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT { +#define VK_EXT_depth_clip_enable 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION 1 +#define VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME "VK_EXT_depth_clip_enable" +typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT; +typedef struct VkPhysicalDeviceDepthClipEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 depthClipEnable; +} VkPhysicalDeviceDepthClipEnableFeaturesEXT; + +typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags; + VkBool32 depthClipEnable; +} VkPipelineRasterizationDepthClipStateCreateInfoEXT; + + + #define VK_EXT_swapchain_colorspace 1 -#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 3 +#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 4 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace" #define VK_EXT_hdr_metadata 1 -#define VK_EXT_HDR_METADATA_SPEC_VERSION 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 2 #define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" - typedef struct VkXYColorEXT { float x; float y; @@ -6790,7 +9763,6 @@ typedef struct VkHdrMetadataEXT { float maxFrameAverageLightLevel; } VkHdrMetadataEXT; - typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); #ifndef VK_NO_PROTOTYPES @@ -6801,6 +9773,7 @@ VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( const VkHdrMetadataEXT* pMetadata); #endif + #define VK_EXT_external_memory_dma_buf 1 #define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION 1 #define VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME "VK_EXT_external_memory_dma_buf" @@ -6809,17 +9782,14 @@ VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( #define VK_EXT_queue_family_foreign 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION 1 #define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME "VK_EXT_queue_family_foreign" -#define VK_QUEUE_FAMILY_FOREIGN_EXT (~0U-2) +#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U) #define VK_EXT_debug_utils 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT) - -#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 1 +#define VK_EXT_DEBUG_UTILS_SPEC_VERSION 2 #define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils" - typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT; -typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001, @@ -6828,7 +9798,6 @@ typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000, VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugUtilsMessageSeverityFlagBitsEXT; -typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001, @@ -6837,6 +9806,14 @@ typedef enum VkDebugUtilsMessageTypeFlagBitsEXT { VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugUtilsMessageTypeFlagBitsEXT; typedef VkFlags VkDebugUtilsMessageTypeFlagsEXT; +typedef VkFlags VkDebugUtilsMessageSeverityFlagsEXT; +typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT; +typedef struct VkDebugUtilsLabelEXT { + VkStructureType sType; + const void* pNext; + const char* pLabelName; + float color[4]; +} VkDebugUtilsLabelEXT; typedef struct VkDebugUtilsObjectNameInfoEXT { VkStructureType sType; @@ -6846,23 +9823,6 @@ typedef struct VkDebugUtilsObjectNameInfoEXT { const char* pObjectName; } VkDebugUtilsObjectNameInfoEXT; -typedef struct VkDebugUtilsObjectTagInfoEXT { - VkStructureType sType; - const void* pNext; - VkObjectType objectType; - uint64_t objectHandle; - uint64_t tagName; - size_t tagSize; - const void* pTag; -} VkDebugUtilsObjectTagInfoEXT; - -typedef struct VkDebugUtilsLabelEXT { - VkStructureType sType; - const void* pNext; - const char* pLabelName; - float color[4]; -} VkDebugUtilsLabelEXT; - typedef struct VkDebugUtilsMessengerCallbackDataEXT { VkStructureType sType; const void* pNext; @@ -6871,16 +9831,16 @@ typedef struct VkDebugUtilsMessengerCallbackDataEXT { int32_t messageIdNumber; const char* pMessage; uint32_t queueLabelCount; - VkDebugUtilsLabelEXT* pQueueLabels; + const VkDebugUtilsLabelEXT* pQueueLabels; uint32_t cmdBufLabelCount; - VkDebugUtilsLabelEXT* pCmdBufLabels; + const VkDebugUtilsLabelEXT* pCmdBufLabels; uint32_t objectCount; - VkDebugUtilsObjectNameInfoEXT* pObjects; + const VkDebugUtilsObjectNameInfoEXT* pObjects; } VkDebugUtilsMessengerCallbackDataEXT; typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); @@ -6894,6 +9854,15 @@ typedef struct VkDebugUtilsMessengerCreateInfoEXT { void* pUserData; } VkDebugUtilsMessengerCreateInfoEXT; +typedef struct VkDebugUtilsObjectTagInfoEXT { + VkStructureType sType; + const void* pNext; + VkObjectType objectType; + uint64_t objectHandle; + uint64_t tagName; + size_t tagSize; + const void* pTag; +} VkDebugUtilsObjectTagInfoEXT; typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); @@ -6956,38 +9925,20 @@ VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); #endif + #define VK_EXT_sampler_filter_minmax 1 -#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 1 +#define VK_EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION 2 #define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME "VK_EXT_sampler_filter_minmax" +typedef VkSamplerReductionMode VkSamplerReductionModeEXT; +typedef VkSamplerReductionModeCreateInfo VkSamplerReductionModeCreateInfoEXT; -typedef enum VkSamplerReductionModeEXT { - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT = 0, - VK_SAMPLER_REDUCTION_MODE_MIN_EXT = 1, - VK_SAMPLER_REDUCTION_MODE_MAX_EXT = 2, - VK_SAMPLER_REDUCTION_MODE_BEGIN_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, - VK_SAMPLER_REDUCTION_MODE_END_RANGE_EXT = VK_SAMPLER_REDUCTION_MODE_MAX_EXT, - VK_SAMPLER_REDUCTION_MODE_RANGE_SIZE_EXT = (VK_SAMPLER_REDUCTION_MODE_MAX_EXT - VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT + 1), - VK_SAMPLER_REDUCTION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkSamplerReductionModeEXT; - -typedef struct VkSamplerReductionModeCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkSamplerReductionModeEXT reductionMode; -} VkSamplerReductionModeCreateInfoEXT; - -typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT { - VkStructureType sType; - void* pNext; - VkBool32 filterMinmaxSingleComponentFormats; - VkBool32 filterMinmaxImageComponentMapping; -} VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; +typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT; #define VK_AMD_gpu_shader_int16 1 -#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 1 +#define VK_AMD_GPU_SHADER_INT16_SPEC_VERSION 2 #define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" @@ -7001,6 +9952,41 @@ typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT { #define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask" +#define VK_EXT_inline_uniform_block 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1 +#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block" +typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeaturesEXT; + +typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockPropertiesEXT; + +typedef struct VkWriteDescriptorSetInlineUniformBlockEXT { + VkStructureType sType; + const void* pNext; + uint32_t dataSize; + const void* pData; +} VkWriteDescriptorSetInlineUniformBlockEXT; + +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfoEXT; + + + #define VK_EXT_shader_stencil_export 1 #define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1 #define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export" @@ -7009,7 +9995,6 @@ typedef struct VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT { #define VK_EXT_sample_locations 1 #define VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION 1 #define VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME "VK_EXT_sample_locations" - typedef struct VkSampleLocationEXT { float x; float y; @@ -7066,7 +10051,6 @@ typedef struct VkMultisamplePropertiesEXT { VkExtent2D maxSampleLocationGridSize; } VkMultisamplePropertiesEXT; - typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); @@ -7081,21 +10065,17 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( VkMultisamplePropertiesEXT* pMultisampleProperties); #endif + #define VK_EXT_blend_operation_advanced 1 #define VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION 2 #define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME "VK_EXT_blend_operation_advanced" - typedef enum VkBlendOverlapEXT { VK_BLEND_OVERLAP_UNCORRELATED_EXT = 0, VK_BLEND_OVERLAP_DISJOINT_EXT = 1, VK_BLEND_OVERLAP_CONJOINT_EXT = 2, - VK_BLEND_OVERLAP_BEGIN_RANGE_EXT = VK_BLEND_OVERLAP_UNCORRELATED_EXT, - VK_BLEND_OVERLAP_END_RANGE_EXT = VK_BLEND_OVERLAP_CONJOINT_EXT, - VK_BLEND_OVERLAP_RANGE_SIZE_EXT = (VK_BLEND_OVERLAP_CONJOINT_EXT - VK_BLEND_OVERLAP_UNCORRELATED_EXT + 1), VK_BLEND_OVERLAP_MAX_ENUM_EXT = 0x7FFFFFFF } VkBlendOverlapEXT; - typedef struct VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT { VkStructureType sType; void* pNext; @@ -7126,9 +10106,7 @@ typedef struct VkPipelineColorBlendAdvancedStateCreateInfoEXT { #define VK_NV_fragment_coverage_to_color 1 #define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION 1 #define VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME "VK_NV_fragment_coverage_to_color" - typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV; - typedef struct VkPipelineCoverageToColorStateCreateInfoNV { VkStructureType sType; const void* pNext; @@ -7143,20 +10121,14 @@ typedef struct VkPipelineCoverageToColorStateCreateInfoNV { #define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION 1 #define VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME "VK_NV_framebuffer_mixed_samples" - typedef enum VkCoverageModulationModeNV { VK_COVERAGE_MODULATION_MODE_NONE_NV = 0, VK_COVERAGE_MODULATION_MODE_RGB_NV = 1, VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2, VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3, - VK_COVERAGE_MODULATION_MODE_BEGIN_RANGE_NV = VK_COVERAGE_MODULATION_MODE_NONE_NV, - VK_COVERAGE_MODULATION_MODE_END_RANGE_NV = VK_COVERAGE_MODULATION_MODE_RGBA_NV, - VK_COVERAGE_MODULATION_MODE_RANGE_SIZE_NV = (VK_COVERAGE_MODULATION_MODE_RGBA_NV - VK_COVERAGE_MODULATION_MODE_NONE_NV + 1), VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF } VkCoverageModulationModeNV; - typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV; - typedef struct VkPipelineCoverageModulationStateCreateInfoNV { VkStructureType sType; const void* pNext; @@ -7174,29 +10146,108 @@ typedef struct VkPipelineCoverageModulationStateCreateInfoNV { #define VK_NV_FILL_RECTANGLE_EXTENSION_NAME "VK_NV_fill_rectangle" +#define VK_NV_shader_sm_builtins 1 +#define VK_NV_SHADER_SM_BUILTINS_SPEC_VERSION 1 +#define VK_NV_SHADER_SM_BUILTINS_EXTENSION_NAME "VK_NV_shader_sm_builtins" +typedef struct VkPhysicalDeviceShaderSMBuiltinsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderSMCount; + uint32_t shaderWarpsPerSM; +} VkPhysicalDeviceShaderSMBuiltinsPropertiesNV; + +typedef struct VkPhysicalDeviceShaderSMBuiltinsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shaderSMBuiltins; +} VkPhysicalDeviceShaderSMBuiltinsFeaturesNV; + + + #define VK_EXT_post_depth_coverage 1 #define VK_EXT_POST_DEPTH_COVERAGE_SPEC_VERSION 1 #define VK_EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME "VK_EXT_post_depth_coverage" +#define VK_EXT_image_drm_format_modifier 1 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION 2 +#define VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME "VK_EXT_image_drm_format_modifier" +typedef struct VkDrmFormatModifierPropertiesEXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags drmFormatModifierTilingFeatures; +} VkDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierPropertiesListEXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierPropertiesEXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesListEXT; + +typedef struct VkPhysicalDeviceImageDrmFormatModifierInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkPhysicalDeviceImageDrmFormatModifierInfoEXT; + +typedef struct VkImageDrmFormatModifierListCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t drmFormatModifierCount; + const uint64_t* pDrmFormatModifiers; +} VkImageDrmFormatModifierListCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierExplicitCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + const VkSubresourceLayout* pPlaneLayouts; +} VkImageDrmFormatModifierExplicitCreateInfoEXT; + +typedef struct VkImageDrmFormatModifierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t drmFormatModifier; +} VkImageDrmFormatModifierPropertiesEXT; + +typedef struct VkDrmFormatModifierProperties2EXT { + uint64_t drmFormatModifier; + uint32_t drmFormatModifierPlaneCount; + VkFormatFeatureFlags2KHR drmFormatModifierTilingFeatures; +} VkDrmFormatModifierProperties2EXT; + +typedef struct VkDrmFormatModifierPropertiesList2EXT { + VkStructureType sType; + void* pNext; + uint32_t drmFormatModifierCount; + VkDrmFormatModifierProperties2EXT* pDrmFormatModifierProperties; +} VkDrmFormatModifierPropertiesList2EXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( + VkDevice device, + VkImage image, + VkImageDrmFormatModifierPropertiesEXT* pProperties); +#endif + + #define VK_EXT_validation_cache 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT) - #define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1 #define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache" -#define VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - typedef enum VkValidationCacheHeaderVersionEXT { VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1, - VK_VALIDATION_CACHE_HEADER_VERSION_BEGIN_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_END_RANGE_EXT = VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT, - VK_VALIDATION_CACHE_HEADER_VERSION_RANGE_SIZE_EXT = (VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT - VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT + 1), VK_VALIDATION_CACHE_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationCacheHeaderVersionEXT; - typedef VkFlags VkValidationCacheCreateFlagsEXT; - typedef struct VkValidationCacheCreateInfoEXT { VkStructureType sType; const void* pNext; @@ -7211,7 +10262,6 @@ typedef struct VkShaderModuleValidationCacheCreateInfoEXT { VkValidationCacheEXT validationCache; } VkShaderModuleValidationCacheCreateInfoEXT; - typedef VkResult (VKAPI_PTR *PFN_vkCreateValidationCacheEXT)(VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); typedef void (VKAPI_PTR *PFN_vkDestroyValidationCacheEXT)(VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); @@ -7242,92 +10292,23 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( void* pData); #endif + #define VK_EXT_descriptor_indexing 1 #define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2 #define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing" +typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT; +typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT; -typedef enum VkDescriptorBindingFlagBitsEXT { - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = 0x00000001, - VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = 0x00000002, - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = 0x00000004, - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008, - VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDescriptorBindingFlagBitsEXT; -typedef VkFlags VkDescriptorBindingFlagsEXT; +typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; -typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t bindingCount; - const VkDescriptorBindingFlagsEXT* pBindingFlags; -} VkDescriptorSetLayoutBindingFlagsCreateInfoEXT; +typedef VkPhysicalDeviceDescriptorIndexingFeatures VkPhysicalDeviceDescriptorIndexingFeaturesEXT; -typedef struct VkPhysicalDeviceDescriptorIndexingFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 shaderInputAttachmentArrayDynamicIndexing; - VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; - VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; - VkBool32 shaderUniformBufferArrayNonUniformIndexing; - VkBool32 shaderSampledImageArrayNonUniformIndexing; - VkBool32 shaderStorageBufferArrayNonUniformIndexing; - VkBool32 shaderStorageImageArrayNonUniformIndexing; - VkBool32 shaderInputAttachmentArrayNonUniformIndexing; - VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; - VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; - VkBool32 descriptorBindingUniformBufferUpdateAfterBind; - VkBool32 descriptorBindingSampledImageUpdateAfterBind; - VkBool32 descriptorBindingStorageImageUpdateAfterBind; - VkBool32 descriptorBindingStorageBufferUpdateAfterBind; - VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; - VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; - VkBool32 descriptorBindingUpdateUnusedWhilePending; - VkBool32 descriptorBindingPartiallyBound; - VkBool32 descriptorBindingVariableDescriptorCount; - VkBool32 runtimeDescriptorArray; -} VkPhysicalDeviceDescriptorIndexingFeaturesEXT; +typedef VkPhysicalDeviceDescriptorIndexingProperties VkPhysicalDeviceDescriptorIndexingPropertiesEXT; -typedef struct VkPhysicalDeviceDescriptorIndexingPropertiesEXT { - VkStructureType sType; - void* pNext; - uint32_t maxUpdateAfterBindDescriptorsInAllPools; - VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; - VkBool32 shaderSampledImageArrayNonUniformIndexingNative; - VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; - VkBool32 shaderStorageImageArrayNonUniformIndexingNative; - VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; - VkBool32 robustBufferAccessUpdateAfterBind; - VkBool32 quadDivergentImplicitLod; - uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; - uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; - uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; - uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; - uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; - uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; - uint32_t maxPerStageUpdateAfterBindResources; - uint32_t maxDescriptorSetUpdateAfterBindSamplers; - uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; - uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; - uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; - uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; - uint32_t maxDescriptorSetUpdateAfterBindSampledImages; - uint32_t maxDescriptorSetUpdateAfterBindStorageImages; - uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; -} VkPhysicalDeviceDescriptorIndexingPropertiesEXT; +typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; -typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t descriptorSetCount; - const uint32_t* pDescriptorCounts; -} VkDescriptorSetVariableDescriptorCountAllocateInfoEXT; - -typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT { - VkStructureType sType; - void* pNext; - uint32_t maxVariableDescriptorCount; -} VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; +typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT; @@ -7336,22 +10317,526 @@ typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT { #define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer" +#define VK_NV_shading_rate_image 1 +#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3 +#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image" + +typedef enum VkShadingRatePaletteEntryNV { + VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0, + VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1, + VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2, + VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3, + VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10, + VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11, + VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF +} VkShadingRatePaletteEntryNV; + +typedef enum VkCoarseSampleOrderTypeNV { + VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0, + VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1, + VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2, + VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3, + VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoarseSampleOrderTypeNV; +typedef struct VkShadingRatePaletteNV { + uint32_t shadingRatePaletteEntryCount; + const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries; +} VkShadingRatePaletteNV; + +typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 shadingRateImageEnable; + uint32_t viewportCount; + const VkShadingRatePaletteNV* pShadingRatePalettes; +} VkPipelineViewportShadingRateImageStateCreateInfoNV; + +typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 shadingRateImage; + VkBool32 shadingRateCoarseSampleOrder; +} VkPhysicalDeviceShadingRateImageFeaturesNV; + +typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV { + VkStructureType sType; + void* pNext; + VkExtent2D shadingRateTexelSize; + uint32_t shadingRatePaletteSize; + uint32_t shadingRateMaxCoarseSamples; +} VkPhysicalDeviceShadingRateImagePropertiesNV; + +typedef struct VkCoarseSampleLocationNV { + uint32_t pixelX; + uint32_t pixelY; + uint32_t sample; +} VkCoarseSampleLocationNV; + +typedef struct VkCoarseSampleOrderCustomNV { + VkShadingRatePaletteEntryNV shadingRate; + uint32_t sampleCount; + uint32_t sampleLocationCount; + const VkCoarseSampleLocationNV* pSampleLocations; +} VkCoarseSampleOrderCustomNV; + +typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCoarseSampleOrderTypeNV sampleOrderType; + uint32_t customSampleOrderCount; + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders; +} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( + VkCommandBuffer commandBuffer, + uint32_t firstViewport, + uint32_t viewportCount, + const VkShadingRatePaletteNV* pShadingRatePalettes); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( + VkCommandBuffer commandBuffer, + VkCoarseSampleOrderTypeNV sampleOrderType, + uint32_t customSampleOrderCount, + const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); +#endif + + +#define VK_NV_ray_tracing 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) +#define VK_NV_RAY_TRACING_SPEC_VERSION 3 +#define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR + +typedef enum VkRayTracingShaderGroupTypeKHR { + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; + + +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; + + +typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeNV; + +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; + +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; + +typedef struct VkRayTracingShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; +} VkRayTracingShaderGroupCreateInfoNV; + +typedef struct VkRayTracingPipelineCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoNV* pGroups; + uint32_t maxRecursionDepth; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoNV; + +typedef struct VkGeometryTrianglesNV { + VkStructureType sType; + const void* pNext; + VkBuffer vertexData; + VkDeviceSize vertexOffset; + uint32_t vertexCount; + VkDeviceSize vertexStride; + VkFormat vertexFormat; + VkBuffer indexData; + VkDeviceSize indexOffset; + uint32_t indexCount; + VkIndexType indexType; + VkBuffer transformData; + VkDeviceSize transformOffset; +} VkGeometryTrianglesNV; + +typedef struct VkGeometryAABBNV { + VkStructureType sType; + const void* pNext; + VkBuffer aabbData; + uint32_t numAABBs; + uint32_t stride; + VkDeviceSize offset; +} VkGeometryAABBNV; + +typedef struct VkGeometryDataNV { + VkGeometryTrianglesNV triangles; + VkGeometryAABBNV aabbs; +} VkGeometryDataNV; + +typedef struct VkGeometryNV { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; +} VkGeometryNV; + +typedef struct VkAccelerationStructureInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNV type; + VkBuildAccelerationStructureFlagsNV flags; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNV* pGeometries; +} VkAccelerationStructureInfoNV; + +typedef struct VkAccelerationStructureCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceSize compactedSize; + VkAccelerationStructureInfoNV info; +} VkAccelerationStructureCreateInfoNV; + +typedef struct VkBindAccelerationStructureMemoryInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureNV accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoNV; + +typedef struct VkWriteDescriptorSetAccelerationStructureNV { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureNV* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureNV; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureMemoryRequirementsTypeNV type; + VkAccelerationStructureNV accelerationStructure; +} VkAccelerationStructureMemoryRequirementsInfoNV; + +typedef struct VkPhysicalDeviceRayTracingPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxTriangleCount; + uint32_t maxDescriptorSetAccelerationStructures; +} VkPhysicalDeviceRayTracingPropertiesNV; + +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( + VkDevice device, + const VkAccelerationStructureCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureNV* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2KHR* pMemoryRequirements); + +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( + VkCommandBuffer commandBuffer, + const VkAccelerationStructureInfoNV* pInfo, + VkBuffer instanceData, + VkDeviceSize instanceOffset, + VkBool32 update, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkBuffer scratch, + VkDeviceSize scratchOffset); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( + VkCommandBuffer commandBuffer, + VkAccelerationStructureNV dst, + VkAccelerationStructureNV src, + VkCopyAccelerationStructureModeKHR mode); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( + VkCommandBuffer commandBuffer, + VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, + VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, + VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, + VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, + VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, + VkDeviceSize callableShaderBindingStride, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoNV* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( + VkDevice device, + VkAccelerationStructureNV accelerationStructure, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureNV* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( + VkDevice device, + VkPipeline pipeline, + uint32_t shader); +#endif + + +#define VK_NV_representative_fragment_test 1 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 2 +#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test" +typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 representativeFragmentTest; +} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV; + +typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 representativeFragmentTestEnable; +} VkPipelineRepresentativeFragmentTestStateCreateInfoNV; + + + +#define VK_EXT_filter_cubic 1 +#define VK_EXT_FILTER_CUBIC_SPEC_VERSION 3 +#define VK_EXT_FILTER_CUBIC_EXTENSION_NAME "VK_EXT_filter_cubic" +typedef struct VkPhysicalDeviceImageViewImageFormatInfoEXT { + VkStructureType sType; + void* pNext; + VkImageViewType imageViewType; +} VkPhysicalDeviceImageViewImageFormatInfoEXT; + +typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 filterCubic; + VkBool32 filterCubicMinmax; +} VkFilterCubicImageViewImageFormatPropertiesEXT; + + + +#define VK_QCOM_render_pass_shader_resolve 1 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" + + #define VK_EXT_global_priority 1 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 #define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority" - typedef enum VkQueueGlobalPriorityEXT { VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT = 128, VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT = 256, VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT = 512, VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT = 1024, - VK_QUEUE_GLOBAL_PRIORITY_BEGIN_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT, - VK_QUEUE_GLOBAL_PRIORITY_END_RANGE_EXT = VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT, - VK_QUEUE_GLOBAL_PRIORITY_RANGE_SIZE_EXT = (VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT - VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT + 1), VK_QUEUE_GLOBAL_PRIORITY_MAX_ENUM_EXT = 0x7FFFFFFF } VkQueueGlobalPriorityEXT; - typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT { VkStructureType sType; const void* pNext; @@ -7363,7 +10848,6 @@ typedef struct VkDeviceQueueGlobalPriorityCreateInfoEXT { #define VK_EXT_external_memory_host 1 #define VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION 1 #define VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME "VK_EXT_external_memory_host" - typedef struct VkImportMemoryHostPointerInfoEXT { VkStructureType sType; const void* pNext; @@ -7383,7 +10867,6 @@ typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { VkDeviceSize minImportedHostPointerAlignment; } VkPhysicalDeviceExternalMemoryHostPropertiesEXT; - typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); #ifndef VK_NO_PROTOTYPES @@ -7394,10 +10877,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); #endif + #define VK_AMD_buffer_marker 1 #define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1 #define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker" - typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); #ifndef VK_NO_PROTOTYPES @@ -7409,10 +10892,61 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( uint32_t marker); #endif -#define VK_AMD_shader_core_properties 1 -#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1 -#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" +#define VK_AMD_pipeline_compiler_control 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION 1 +#define VK_AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME "VK_AMD_pipeline_compiler_control" + +typedef enum VkPipelineCompilerControlFlagBitsAMD { + VK_PIPELINE_COMPILER_CONTROL_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkPipelineCompilerControlFlagBitsAMD; +typedef VkFlags VkPipelineCompilerControlFlagsAMD; +typedef struct VkPipelineCompilerControlCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineCompilerControlFlagsAMD compilerControlFlags; +} VkPipelineCompilerControlCreateInfoAMD; + + + +#define VK_EXT_calibrated_timestamps 1 +#define VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION 2 +#define VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME "VK_EXT_calibrated_timestamps" + +typedef enum VkTimeDomainEXT { + VK_TIME_DOMAIN_DEVICE_EXT = 0, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = 1, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = 2, + VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = 3, + VK_TIME_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF +} VkTimeDomainEXT; +typedef struct VkCalibratedTimestampInfoEXT { + VkStructureType sType; + const void* pNext; + VkTimeDomainEXT timeDomain; +} VkCalibratedTimestampInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)(VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains); +typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainEXT* pTimeDomains); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); +#endif + + +#define VK_AMD_shader_core_properties 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 2 +#define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties" typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { VkStructureType sType; void* pNext; @@ -7434,10 +10968,27 @@ typedef struct VkPhysicalDeviceShaderCorePropertiesAMD { -#define VK_EXT_vertex_attribute_divisor 1 -#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 1 -#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" +#define VK_AMD_memory_overallocation_behavior 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION 1 +#define VK_AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME "VK_AMD_memory_overallocation_behavior" +typedef enum VkMemoryOverallocationBehaviorAMD { + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD = 0, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD = 1, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_DISALLOWED_AMD = 2, + VK_MEMORY_OVERALLOCATION_BEHAVIOR_MAX_ENUM_AMD = 0x7FFFFFFF +} VkMemoryOverallocationBehaviorAMD; +typedef struct VkDeviceMemoryOverallocationCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkMemoryOverallocationBehaviorAMD overallocationBehavior; +} VkDeviceMemoryOverallocationCreateInfoAMD; + + + +#define VK_EXT_vertex_attribute_divisor 1 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3 +#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor" typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { VkStructureType sType; void* pNext; @@ -7456,6 +11007,39 @@ typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors; } VkPipelineVertexInputDivisorStateCreateInfoEXT; +typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; +} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT; + + + +#define VK_EXT_pipeline_creation_feedback 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION 1 +#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME "VK_EXT_pipeline_creation_feedback" + +typedef enum VkPipelineCreationFeedbackFlagBitsEXT { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBitsEXT; +typedef VkFlags VkPipelineCreationFeedbackFlagsEXT; +typedef struct VkPipelineCreationFeedbackEXT { + VkPipelineCreationFeedbackFlagsEXT flags; + uint64_t duration; +} VkPipelineCreationFeedbackEXT; + +typedef struct VkPipelineCreationFeedbackCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfoEXT; + #define VK_NV_shader_subgroup_partitioned 1 @@ -7463,6 +11047,2492 @@ typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT { #define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned" +#define VK_NV_compute_shader_derivatives 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1 +#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives" +typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeDerivativeGroupQuads; + VkBool32 computeDerivativeGroupLinear; +} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV; + + + +#define VK_NV_mesh_shader 1 +#define VK_NV_MESH_SHADER_SPEC_VERSION 1 +#define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader" +typedef struct VkPhysicalDeviceMeshShaderFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 taskShader; + VkBool32 meshShader; +} VkPhysicalDeviceMeshShaderFeaturesNV; + +typedef struct VkPhysicalDeviceMeshShaderPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDrawMeshTasksCount; + uint32_t maxTaskWorkGroupInvocations; + uint32_t maxTaskWorkGroupSize[3]; + uint32_t maxTaskTotalMemorySize; + uint32_t maxTaskOutputCount; + uint32_t maxMeshWorkGroupInvocations; + uint32_t maxMeshWorkGroupSize[3]; + uint32_t maxMeshTotalMemorySize; + uint32_t maxMeshOutputVertices; + uint32_t maxMeshOutputPrimitives; + uint32_t maxMeshMultiviewViewCount; + uint32_t meshOutputPerVertexGranularity; + uint32_t meshOutputPerPrimitiveGranularity; +} VkPhysicalDeviceMeshShaderPropertiesNV; + +typedef struct VkDrawMeshTasksIndirectCommandNV { + uint32_t taskCount; + uint32_t firstTask; +} VkDrawMeshTasksIndirectCommandNV; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( + VkCommandBuffer commandBuffer, + uint32_t taskCount, + uint32_t firstTask); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + uint32_t drawCount, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkBuffer countBuffer, + VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, + uint32_t stride); +#endif + + +#define VK_NV_fragment_shader_barycentric 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric" +typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderBarycentric; +} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV; + + + +#define VK_NV_shader_image_footprint 1 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 2 +#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint" +typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 imageFootprint; +} VkPhysicalDeviceShaderImageFootprintFeaturesNV; + + + +#define VK_NV_scissor_exclusive 1 +#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1 +#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive" +typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t exclusiveScissorCount; + const VkRect2D* pExclusiveScissors; +} VkPipelineViewportExclusiveScissorStateCreateInfoNV; + +typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 exclusiveScissor; +} VkPhysicalDeviceExclusiveScissorFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( + VkCommandBuffer commandBuffer, + uint32_t firstExclusiveScissor, + uint32_t exclusiveScissorCount, + const VkRect2D* pExclusiveScissors); +#endif + + +#define VK_NV_device_diagnostic_checkpoints 1 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2 +#define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints" +typedef struct VkQueueFamilyCheckpointPropertiesNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlags checkpointExecutionStageMask; +} VkQueueFamilyCheckpointPropertiesNV; + +typedef struct VkCheckpointDataNV { + VkStructureType sType; + void* pNext; + VkPipelineStageFlagBits stage; + void* pCheckpointMarker; +} VkCheckpointDataNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCheckpointNV)(VkCommandBuffer commandBuffer, const void* pCheckpointMarker); +typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( + VkCommandBuffer commandBuffer, + const void* pCheckpointMarker); + +VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( + VkQueue queue, + uint32_t* pCheckpointDataCount, + VkCheckpointDataNV* pCheckpointData); +#endif + + +#define VK_INTEL_shader_integer_functions2 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION 1 +#define VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME "VK_INTEL_shader_integer_functions2" +typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerFunctions2; +} VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL; + + + +#define VK_INTEL_performance_query 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 +#define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" + +typedef enum VkPerformanceConfigurationTypeINTEL { + VK_PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, + VK_PERFORMANCE_CONFIGURATION_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceConfigurationTypeINTEL; + +typedef enum VkQueryPoolSamplingModeINTEL { + VK_QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, + VK_QUERY_POOL_SAMPLING_MODE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkQueryPoolSamplingModeINTEL; + +typedef enum VkPerformanceOverrideTypeINTEL { + VK_PERFORMANCE_OVERRIDE_TYPE_NULL_HARDWARE_INTEL = 0, + VK_PERFORMANCE_OVERRIDE_TYPE_FLUSH_GPU_CACHES_INTEL = 1, + VK_PERFORMANCE_OVERRIDE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceOverrideTypeINTEL; + +typedef enum VkPerformanceParameterTypeINTEL { + VK_PERFORMANCE_PARAMETER_TYPE_HW_COUNTERS_SUPPORTED_INTEL = 0, + VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL = 1, + VK_PERFORMANCE_PARAMETER_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceParameterTypeINTEL; + +typedef enum VkPerformanceValueTypeINTEL { + VK_PERFORMANCE_VALUE_TYPE_UINT32_INTEL = 0, + VK_PERFORMANCE_VALUE_TYPE_UINT64_INTEL = 1, + VK_PERFORMANCE_VALUE_TYPE_FLOAT_INTEL = 2, + VK_PERFORMANCE_VALUE_TYPE_BOOL_INTEL = 3, + VK_PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, + VK_PERFORMANCE_VALUE_TYPE_MAX_ENUM_INTEL = 0x7FFFFFFF +} VkPerformanceValueTypeINTEL; +typedef union VkPerformanceValueDataINTEL { + uint32_t value32; + uint64_t value64; + float valueFloat; + VkBool32 valueBool; + const char* valueString; +} VkPerformanceValueDataINTEL; + +typedef struct VkPerformanceValueINTEL { + VkPerformanceValueTypeINTEL type; + VkPerformanceValueDataINTEL data; +} VkPerformanceValueINTEL; + +typedef struct VkInitializePerformanceApiInfoINTEL { + VkStructureType sType; + const void* pNext; + void* pUserData; +} VkInitializePerformanceApiInfoINTEL; + +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { + VkStructureType sType; + const void* pNext; + VkQueryPoolSamplingModeINTEL performanceCountersSampling; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; + +typedef struct VkPerformanceMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint64_t marker; +} VkPerformanceMarkerInfoINTEL; + +typedef struct VkPerformanceStreamMarkerInfoINTEL { + VkStructureType sType; + const void* pNext; + uint32_t marker; +} VkPerformanceStreamMarkerInfoINTEL; + +typedef struct VkPerformanceOverrideInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceOverrideTypeINTEL type; + VkBool32 enable; + uint64_t parameter; +} VkPerformanceOverrideInfoINTEL; + +typedef struct VkPerformanceConfigurationAcquireInfoINTEL { + VkStructureType sType; + const void* pNext; + VkPerformanceConfigurationTypeINTEL type; +} VkPerformanceConfigurationAcquireInfoINTEL; + +typedef VkResult (VKAPI_PTR *PFN_vkInitializePerformanceApiINTEL)(VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +typedef void (VKAPI_PTR *PFN_vkUninitializePerformanceApiINTEL)(VkDevice device); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceStreamMarkerINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdSetPerformanceOverrideINTEL)(VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +typedef VkResult (VKAPI_PTR *PFN_vkAcquirePerformanceConfigurationINTEL)(VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); +typedef VkResult (VKAPI_PTR *PFN_vkReleasePerformanceConfigurationINTEL)(VkDevice device, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueue queue, VkPerformanceConfigurationINTEL configuration); +typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( + VkDevice device, + const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); + +VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( + VkDevice device); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( + VkCommandBuffer commandBuffer, + const VkPerformanceOverrideInfoINTEL* pOverrideInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( + VkDevice device, + const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, + VkPerformanceConfigurationINTEL* pConfiguration); + +VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( + VkDevice device, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( + VkQueue queue, + VkPerformanceConfigurationINTEL configuration); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( + VkDevice device, + VkPerformanceParameterTypeINTEL parameter, + VkPerformanceValueINTEL* pValue); +#endif + + +#define VK_EXT_pci_bus_info 1 +#define VK_EXT_PCI_BUS_INFO_SPEC_VERSION 2 +#define VK_EXT_PCI_BUS_INFO_EXTENSION_NAME "VK_EXT_pci_bus_info" +typedef struct VkPhysicalDevicePCIBusInfoPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t pciDomain; + uint32_t pciBus; + uint32_t pciDevice; + uint32_t pciFunction; +} VkPhysicalDevicePCIBusInfoPropertiesEXT; + + + +#define VK_AMD_display_native_hdr 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION 1 +#define VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME "VK_AMD_display_native_hdr" +typedef struct VkDisplayNativeHdrSurfaceCapabilitiesAMD { + VkStructureType sType; + void* pNext; + VkBool32 localDimmingSupport; +} VkDisplayNativeHdrSurfaceCapabilitiesAMD; + +typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkBool32 localDimmingEnable; +} VkSwapchainDisplayNativeHdrCreateInfoAMD; + +typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( + VkDevice device, + VkSwapchainKHR swapChain, + VkBool32 localDimmingEnable); +#endif + + +#define VK_EXT_fragment_density_map 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 +#define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" +typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMap; + VkBool32 fragmentDensityMapDynamic; + VkBool32 fragmentDensityMapNonSubsampledImages; +} VkPhysicalDeviceFragmentDensityMapFeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkExtent2D minFragmentDensityTexelSize; + VkExtent2D maxFragmentDensityTexelSize; + VkBool32 fragmentDensityInvocations; +} VkPhysicalDeviceFragmentDensityMapPropertiesEXT; + +typedef struct VkRenderPassFragmentDensityMapCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkAttachmentReference fragmentDensityMapAttachment; +} VkRenderPassFragmentDensityMapCreateInfoEXT; + + + +#define VK_EXT_scalar_block_layout 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION 1 +#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME "VK_EXT_scalar_block_layout" +typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLayoutFeaturesEXT; + + + +#define VK_GOOGLE_hlsl_functionality1 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 +#define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +#define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME + + +#define VK_GOOGLE_decorate_string 1 +#define VK_GOOGLE_DECORATE_STRING_SPEC_VERSION 1 +#define VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME "VK_GOOGLE_decorate_string" + + +#define VK_EXT_subgroup_size_control 1 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION 2 +#define VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME "VK_EXT_subgroup_size_control" +typedef struct VkPhysicalDeviceSubgroupSizeControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeaturesEXT; + +typedef struct VkPhysicalDeviceSubgroupSizeControlPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlPropertiesEXT; + +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT { + VkStructureType sType; + void* pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT; + + + +#define VK_AMD_shader_core_properties2 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION 1 +#define VK_AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME "VK_AMD_shader_core_properties2" + +typedef enum VkShaderCorePropertiesFlagBitsAMD { + VK_SHADER_CORE_PROPERTIES_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkShaderCorePropertiesFlagBitsAMD; +typedef VkFlags VkShaderCorePropertiesFlagsAMD; +typedef struct VkPhysicalDeviceShaderCoreProperties2AMD { + VkStructureType sType; + void* pNext; + VkShaderCorePropertiesFlagsAMD shaderCoreFeatures; + uint32_t activeComputeUnitCount; +} VkPhysicalDeviceShaderCoreProperties2AMD; + + + +#define VK_AMD_device_coherent_memory 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION 1 +#define VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME "VK_AMD_device_coherent_memory" +typedef struct VkPhysicalDeviceCoherentMemoryFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 deviceCoherentMemory; +} VkPhysicalDeviceCoherentMemoryFeaturesAMD; + + + +#define VK_EXT_shader_image_atomic_int64 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION 1 +#define VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME "VK_EXT_shader_image_atomic_int64" +typedef struct VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderImageInt64Atomics; + VkBool32 sparseImageInt64Atomics; +} VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT; + + + +#define VK_EXT_memory_budget 1 +#define VK_EXT_MEMORY_BUDGET_SPEC_VERSION 1 +#define VK_EXT_MEMORY_BUDGET_EXTENSION_NAME "VK_EXT_memory_budget" +typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize heapBudget[VK_MAX_MEMORY_HEAPS]; + VkDeviceSize heapUsage[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryBudgetPropertiesEXT; + + + +#define VK_EXT_memory_priority 1 +#define VK_EXT_MEMORY_PRIORITY_SPEC_VERSION 1 +#define VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME "VK_EXT_memory_priority" +typedef struct VkPhysicalDeviceMemoryPriorityFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 memoryPriority; +} VkPhysicalDeviceMemoryPriorityFeaturesEXT; + +typedef struct VkMemoryPriorityAllocateInfoEXT { + VkStructureType sType; + const void* pNext; + float priority; +} VkMemoryPriorityAllocateInfoEXT; + + + +#define VK_NV_dedicated_allocation_image_aliasing 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION 1 +#define VK_NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME "VK_NV_dedicated_allocation_image_aliasing" +typedef struct VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 dedicatedAllocationImageAliasing; +} VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV; + + + +#define VK_EXT_buffer_device_address 1 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION 2 +#define VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME "VK_EXT_buffer_device_address" +typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; + +typedef VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkPhysicalDeviceBufferAddressFeaturesEXT; + +typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT; + +typedef struct VkBufferDeviceAddressCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddress deviceAddress; +} VkBufferDeviceAddressCreateInfoEXT; + +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); +#endif + + +#define VK_EXT_tooling_info 1 +#define VK_EXT_TOOLING_INFO_SPEC_VERSION 1 +#define VK_EXT_TOOLING_INFO_EXTENSION_NAME "VK_EXT_tooling_info" + +typedef enum VkToolPurposeFlagBitsEXT { + VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = 0x00000001, + VK_TOOL_PURPOSE_PROFILING_BIT_EXT = 0x00000002, + VK_TOOL_PURPOSE_TRACING_BIT_EXT = 0x00000004, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = 0x00000008, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = 0x00000010, + VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT = 0x00000020, + VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT = 0x00000040, + VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkToolPurposeFlagBitsEXT; +typedef VkFlags VkToolPurposeFlagsEXT; +typedef struct VkPhysicalDeviceToolPropertiesEXT { + VkStructureType sType; + void* pNext; + char name[VK_MAX_EXTENSION_NAME_SIZE]; + char version[VK_MAX_EXTENSION_NAME_SIZE]; + VkToolPurposeFlagsEXT purposes; + char description[VK_MAX_DESCRIPTION_SIZE]; + char layer[VK_MAX_EXTENSION_NAME_SIZE]; +} VkPhysicalDeviceToolPropertiesEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolPropertiesEXT* pToolProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pToolCount, + VkPhysicalDeviceToolPropertiesEXT* pToolProperties); +#endif + + +#define VK_EXT_separate_stencil_usage 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION 1 +#define VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME "VK_EXT_separate_stencil_usage" +typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; + + + +#define VK_EXT_validation_features 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 5 +#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" + +typedef enum VkValidationFeatureEnableEXT { + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, + VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureEnableEXT; + +typedef enum VkValidationFeatureDisableEXT { + VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, + VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, + VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, + VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, + VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, + VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, + VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, + VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT = 7, + VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureDisableEXT; +typedef struct VkValidationFeaturesEXT { + VkStructureType sType; + const void* pNext; + uint32_t enabledValidationFeatureCount; + const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; + uint32_t disabledValidationFeatureCount; + const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; +} VkValidationFeaturesEXT; + + + +#define VK_NV_cooperative_matrix 1 +#define VK_NV_COOPERATIVE_MATRIX_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME "VK_NV_cooperative_matrix" + +typedef enum VkComponentTypeNV { + VK_COMPONENT_TYPE_FLOAT16_NV = 0, + VK_COMPONENT_TYPE_FLOAT32_NV = 1, + VK_COMPONENT_TYPE_FLOAT64_NV = 2, + VK_COMPONENT_TYPE_SINT8_NV = 3, + VK_COMPONENT_TYPE_SINT16_NV = 4, + VK_COMPONENT_TYPE_SINT32_NV = 5, + VK_COMPONENT_TYPE_SINT64_NV = 6, + VK_COMPONENT_TYPE_UINT8_NV = 7, + VK_COMPONENT_TYPE_UINT16_NV = 8, + VK_COMPONENT_TYPE_UINT32_NV = 9, + VK_COMPONENT_TYPE_UINT64_NV = 10, + VK_COMPONENT_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkComponentTypeNV; + +typedef enum VkScopeNV { + VK_SCOPE_DEVICE_NV = 1, + VK_SCOPE_WORKGROUP_NV = 2, + VK_SCOPE_SUBGROUP_NV = 3, + VK_SCOPE_QUEUE_FAMILY_NV = 5, + VK_SCOPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkScopeNV; +typedef struct VkCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t MSize; + uint32_t NSize; + uint32_t KSize; + VkComponentTypeNV AType; + VkComponentTypeNV BType; + VkComponentTypeNV CType; + VkComponentTypeNV DType; + VkScopeNV scope; +} VkCooperativeMatrixPropertiesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrix; + VkBool32 cooperativeMatrixRobustBufferAccess; +} VkPhysicalDeviceCooperativeMatrixFeaturesNV; + +typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { + VkStructureType sType; + void* pNext; + VkShaderStageFlags cooperativeMatrixSupportedStages; +} VkPhysicalDeviceCooperativeMatrixPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( + VkPhysicalDevice physicalDevice, + uint32_t* pPropertyCount, + VkCooperativeMatrixPropertiesNV* pProperties); +#endif + + +#define VK_NV_coverage_reduction_mode 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION 1 +#define VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME "VK_NV_coverage_reduction_mode" + +typedef enum VkCoverageReductionModeNV { + VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0, + VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1, + VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF +} VkCoverageReductionModeNV; +typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV; +typedef struct VkPhysicalDeviceCoverageReductionModeFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 coverageReductionMode; +} VkPhysicalDeviceCoverageReductionModeFeaturesNV; + +typedef struct VkPipelineCoverageReductionStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineCoverageReductionStateCreateFlagsNV flags; + VkCoverageReductionModeNV coverageReductionMode; +} VkPipelineCoverageReductionStateCreateInfoNV; + +typedef struct VkFramebufferMixedSamplesCombinationNV { + VkStructureType sType; + void* pNext; + VkCoverageReductionModeNV coverageReductionMode; + VkSampleCountFlagBits rasterizationSamples; + VkSampleCountFlags depthStencilSamples; + VkSampleCountFlags colorSamples; +} VkFramebufferMixedSamplesCombinationNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( + VkPhysicalDevice physicalDevice, + uint32_t* pCombinationCount, + VkFramebufferMixedSamplesCombinationNV* pCombinations); +#endif + + +#define VK_EXT_fragment_shader_interlock 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME "VK_EXT_fragment_shader_interlock" +typedef struct VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShaderSampleInterlock; + VkBool32 fragmentShaderPixelInterlock; + VkBool32 fragmentShaderShadingRateInterlock; +} VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT; + + + +#define VK_EXT_ycbcr_image_arrays 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME "VK_EXT_ycbcr_image_arrays" +typedef struct VkPhysicalDeviceYcbcrImageArraysFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcrImageArrays; +} VkPhysicalDeviceYcbcrImageArraysFeaturesEXT; + + + +#define VK_EXT_provoking_vertex 1 +#define VK_EXT_PROVOKING_VERTEX_SPEC_VERSION 1 +#define VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME "VK_EXT_provoking_vertex" + +typedef enum VkProvokingVertexModeEXT { + VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0, + VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1, + VK_PROVOKING_VERTEX_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkProvokingVertexModeEXT; +typedef struct VkPhysicalDeviceProvokingVertexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexLast; + VkBool32 transformFeedbackPreservesProvokingVertex; +} VkPhysicalDeviceProvokingVertexFeaturesEXT; + +typedef struct VkPhysicalDeviceProvokingVertexPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 provokingVertexModePerPipeline; + VkBool32 transformFeedbackPreservesTriangleFanProvokingVertex; +} VkPhysicalDeviceProvokingVertexPropertiesEXT; + +typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkProvokingVertexModeEXT provokingVertexMode; +} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT; + + + +#define VK_EXT_headless_surface 1 +#define VK_EXT_HEADLESS_SURFACE_SPEC_VERSION 1 +#define VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME "VK_EXT_headless_surface" +typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; +typedef struct VkHeadlessSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkHeadlessSurfaceCreateFlagsEXT flags; +} VkHeadlessSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( + VkInstance instance, + const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +#define VK_EXT_line_rasterization 1 +#define VK_EXT_LINE_RASTERIZATION_SPEC_VERSION 1 +#define VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME "VK_EXT_line_rasterization" + +typedef enum VkLineRasterizationModeEXT { + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = 0, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = 1, + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = 2, + VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = 3, + VK_LINE_RASTERIZATION_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkLineRasterizationModeEXT; +typedef struct VkPhysicalDeviceLineRasterizationFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; +} VkPhysicalDeviceLineRasterizationFeaturesEXT; + +typedef struct VkPhysicalDeviceLineRasterizationPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; +} VkPhysicalDeviceLineRasterizationPropertiesEXT; + +typedef struct VkPipelineRasterizationLineStateCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkLineRasterizationModeEXT lineRasterizationMode; + VkBool32 stippledLineEnable; + uint32_t lineStippleFactor; + uint16_t lineStipplePattern; +} VkPipelineRasterizationLineStateCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); +#endif + + +#define VK_EXT_shader_atomic_float 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME "VK_EXT_shader_atomic_float" +typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat32Atomics; + VkBool32 shaderBufferFloat32AtomicAdd; + VkBool32 shaderBufferFloat64Atomics; + VkBool32 shaderBufferFloat64AtomicAdd; + VkBool32 shaderSharedFloat32Atomics; + VkBool32 shaderSharedFloat32AtomicAdd; + VkBool32 shaderSharedFloat64Atomics; + VkBool32 shaderSharedFloat64AtomicAdd; + VkBool32 shaderImageFloat32Atomics; + VkBool32 shaderImageFloat32AtomicAdd; + VkBool32 sparseImageFloat32Atomics; + VkBool32 sparseImageFloat32AtomicAdd; +} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT; + + + +#define VK_EXT_host_query_reset 1 +#define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 +#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME "VK_EXT_host_query_reset" +typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); +#endif + + +#define VK_EXT_index_type_uint8 1 +#define VK_EXT_INDEX_TYPE_UINT8_SPEC_VERSION 1 +#define VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME "VK_EXT_index_type_uint8" +typedef struct VkPhysicalDeviceIndexTypeUint8FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 indexTypeUint8; +} VkPhysicalDeviceIndexTypeUint8FeaturesEXT; + + + +#define VK_EXT_extended_dynamic_state 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_extended_dynamic_state" +typedef struct VkPhysicalDeviceExtendedDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState; +} VkPhysicalDeviceExtendedDynamicStateFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetCullModeEXT)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +typedef void (VKAPI_PTR *PFN_vkCmdSetFrontFaceEXT)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveTopologyEXT)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +typedef void (VKAPI_PTR *PFN_vkCmdSetScissorWithCountEXT)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthWriteEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthCompareOpEXT)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBoundsTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( + VkCommandBuffer commandBuffer, + VkCullModeFlags cullMode); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( + VkCommandBuffer commandBuffer, + VkFrontFace frontFace); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t viewportCount, + const VkViewport* pViewports); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( + VkCommandBuffer commandBuffer, + uint32_t scissorCount, + const VkRect2D* pScissors); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer* pBuffers, + const VkDeviceSize* pOffsets, + const VkDeviceSize* pSizes, + const VkDeviceSize* pStrides); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthWriteEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( + VkCommandBuffer commandBuffer, + VkCompareOp depthCompareOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBoundsTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 stencilTestEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( + VkCommandBuffer commandBuffer, + VkStencilFaceFlags faceMask, + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp); +#endif + + +#define VK_EXT_shader_atomic_float2 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 +#define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" +typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderBufferFloat16Atomics; + VkBool32 shaderBufferFloat16AtomicAdd; + VkBool32 shaderBufferFloat16AtomicMinMax; + VkBool32 shaderBufferFloat32AtomicMinMax; + VkBool32 shaderBufferFloat64AtomicMinMax; + VkBool32 shaderSharedFloat16Atomics; + VkBool32 shaderSharedFloat16AtomicAdd; + VkBool32 shaderSharedFloat16AtomicMinMax; + VkBool32 shaderSharedFloat32AtomicMinMax; + VkBool32 shaderSharedFloat64AtomicMinMax; + VkBool32 shaderImageFloat32AtomicMinMax; + VkBool32 sparseImageFloat32AtomicMinMax; +} VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT; + + + +#define VK_EXT_shader_demote_to_helper_invocation 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION 1 +#define VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME "VK_EXT_shader_demote_to_helper_invocation" +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT; + + + +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline, + uint32_t groupIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( + VkDevice device, + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif + + +#define VK_NV_inherited_viewport_scissor 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION 1 +#define VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME "VK_NV_inherited_viewport_scissor" +typedef struct VkPhysicalDeviceInheritedViewportScissorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 inheritedViewportScissor2D; +} VkPhysicalDeviceInheritedViewportScissorFeaturesNV; + +typedef struct VkCommandBufferInheritanceViewportScissorInfoNV { + VkStructureType sType; + const void* pNext; + VkBool32 viewportScissor2D; + uint32_t viewportDepthCount; + const VkViewport* pViewportDepths; +} VkCommandBufferInheritanceViewportScissorInfoNV; + + + +#define VK_EXT_texel_buffer_alignment 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 +#define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" +typedef struct VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 texelBufferAlignment; +} VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT; + + + +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; + +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; + + + +#define VK_EXT_device_memory_report 1 +#define VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION 2 +#define VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME "VK_EXT_device_memory_report" + +typedef enum VkDeviceMemoryReportEventTypeEXT { + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT = 0, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT = 1, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT = 2, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT = 3, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT = 4, + VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDeviceMemoryReportEventTypeEXT; +typedef VkFlags VkDeviceMemoryReportFlagsEXT; +typedef struct VkPhysicalDeviceDeviceMemoryReportFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 deviceMemoryReport; +} VkPhysicalDeviceDeviceMemoryReportFeaturesEXT; + +typedef struct VkDeviceMemoryReportCallbackDataEXT { + VkStructureType sType; + void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + VkDeviceMemoryReportEventTypeEXT type; + uint64_t memoryObjectId; + VkDeviceSize size; + VkObjectType objectType; + uint64_t objectHandle; + uint32_t heapIndex; +} VkDeviceMemoryReportCallbackDataEXT; + +typedef void (VKAPI_PTR *PFN_vkDeviceMemoryReportCallbackEXT)( + const VkDeviceMemoryReportCallbackDataEXT* pCallbackData, + void* pUserData); + +typedef struct VkDeviceDeviceMemoryReportCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemoryReportFlagsEXT flags; + PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback; + void* pUserData; +} VkDeviceDeviceMemoryReportCreateInfoEXT; + + + +#define VK_EXT_acquire_drm_display 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION 1 +#define VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_drm_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( + VkPhysicalDevice physicalDevice, + int32_t drmFd, + uint32_t connectorId, + VkDisplayKHR* display); +#endif + + +#define VK_EXT_robustness2 1 +#define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesEXT; + +typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesEXT; + + + +#define VK_EXT_custom_border_color 1 +#define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 +#define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxCustomBorderColorSamplers; +} VkPhysicalDeviceCustomBorderColorPropertiesEXT; + +typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customBorderColors; + VkBool32 customBorderColorWithoutFormat; +} VkPhysicalDeviceCustomBorderColorFeaturesEXT; + + + +#define VK_GOOGLE_user_type 1 +#define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 +#define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" + + +#define VK_EXT_private_data 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlotEXT) +#define VK_EXT_PRIVATE_DATA_SPEC_VERSION 1 +#define VK_EXT_PRIVATE_DATA_EXTENSION_NAME "VK_EXT_private_data" + +typedef enum VkPrivateDataSlotCreateFlagBitsEXT { + VK_PRIVATE_DATA_SLOT_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPrivateDataSlotCreateFlagBitsEXT; +typedef VkFlags VkPrivateDataSlotCreateFlagsEXT; +typedef struct VkPhysicalDevicePrivateDataFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeaturesEXT; + +typedef struct VkDevicePrivateDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfoEXT; + +typedef struct VkPrivateDataSlotCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkPrivateDataSlotCreateFlagsEXT flags; +} VkPrivateDataSlotCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlotEXT)(VkDevice device, const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlotEXT* pPrivateDataSlot); +typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlotEXT)(VkDevice device, VkPrivateDataSlotEXT privateDataSlot, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t data); +typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlotEXT privateDataSlot, uint64_t* pData); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( + VkDevice device, + const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkPrivateDataSlotEXT* pPrivateDataSlot); + +VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( + VkDevice device, + VkPrivateDataSlotEXT privateDataSlot, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlotEXT privateDataSlot, + uint64_t data); + +VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( + VkDevice device, + VkObjectType objectType, + uint64_t objectHandle, + VkPrivateDataSlotEXT privateDataSlot, + uint64_t* pData); +#endif + + +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; + + + +#define VK_QCOM_render_pass_store_ops 1 +#define VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION 2 +#define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" + + +#define VK_NV_fragment_shading_rate_enums 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION 1 +#define VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME "VK_NV_fragment_shading_rate_enums" + +typedef enum VkFragmentShadingRateTypeNV { + VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0, + VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1, + VK_FRAGMENT_SHADING_RATE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateTypeNV; + +typedef enum VkFragmentShadingRateNV { + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9, + VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10, + VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11, + VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12, + VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13, + VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14, + VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15, + VK_FRAGMENT_SHADING_RATE_MAX_ENUM_NV = 0x7FFFFFFF +} VkFragmentShadingRateNV; +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 fragmentShadingRateEnums; + VkBool32 supersampleFragmentShadingRates; + VkBool32 noInvocationFragmentShadingRates; +} VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV; + +typedef struct VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV { + VkStructureType sType; + void* pNext; + VkSampleCountFlagBits maxFragmentShadingRateInvocationCount; +} VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV; + +typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkFragmentShadingRateTypeNV shadingRateType; + VkFragmentShadingRateNV shadingRate; + VkFragmentShadingRateCombinerOpKHR combinerOps[2]; +} VkPipelineFragmentShadingRateEnumStateCreateInfoNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( + VkCommandBuffer commandBuffer, + VkFragmentShadingRateNV shadingRate, + const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); +#endif + + +#define VK_NV_ray_tracing_motion_blur 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION 1 +#define VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME "VK_NV_ray_tracing_motion_blur" + +typedef enum VkAccelerationStructureMotionInstanceTypeNV { + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV = 0, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV = 1, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV = 2, + VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkAccelerationStructureMotionInstanceTypeNV; +typedef VkFlags VkAccelerationStructureMotionInfoFlagsNV; +typedef VkFlags VkAccelerationStructureMotionInstanceFlagsNV; +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureGeometryMotionTrianglesDataNV { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR vertexData; +} VkAccelerationStructureGeometryMotionTrianglesDataNV; + +typedef struct VkAccelerationStructureMotionInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t maxInstances; + VkAccelerationStructureMotionInfoFlagsNV flags; +} VkAccelerationStructureMotionInfoNV; + +typedef struct VkAccelerationStructureMatrixMotionInstanceNV { + VkTransformMatrixKHR transformT0; + VkTransformMatrixKHR transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureMatrixMotionInstanceNV; + +typedef struct VkSRTDataNV { + float sx; + float a; + float b; + float pvx; + float sy; + float c; + float pvy; + float sz; + float pvz; + float qx; + float qy; + float qz; + float qw; + float tx; + float ty; + float tz; +} VkSRTDataNV; + +typedef struct VkAccelerationStructureSRTMotionInstanceNV { + VkSRTDataNV transformT0; + VkSRTDataNV transformT1; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureSRTMotionInstanceNV; + +typedef union VkAccelerationStructureMotionInstanceDataNV { + VkAccelerationStructureInstanceKHR staticInstance; + VkAccelerationStructureMatrixMotionInstanceNV matrixMotionInstance; + VkAccelerationStructureSRTMotionInstanceNV srtMotionInstance; +} VkAccelerationStructureMotionInstanceDataNV; + +typedef struct VkAccelerationStructureMotionInstanceNV { + VkAccelerationStructureMotionInstanceTypeNV type; + VkAccelerationStructureMotionInstanceFlagsNV flags; + VkAccelerationStructureMotionInstanceDataNV data; +} VkAccelerationStructureMotionInstanceNV; + +typedef struct VkPhysicalDeviceRayTracingMotionBlurFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingMotionBlur; + VkBool32 rayTracingMotionBlurPipelineTraceRaysIndirect; +} VkPhysicalDeviceRayTracingMotionBlurFeaturesNV; + + + +#define VK_EXT_ycbcr_2plane_444_formats 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME "VK_EXT_ycbcr_2plane_444_formats" +typedef struct VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 ycbcr2plane444Formats; +} VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT; + + + +#define VK_EXT_fragment_density_map2 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME "VK_EXT_fragment_density_map2" +typedef struct VkPhysicalDeviceFragmentDensityMap2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapDeferred; +} VkPhysicalDeviceFragmentDensityMap2FeaturesEXT; + +typedef struct VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 subsampledLoads; + VkBool32 subsampledCoarseReconstructionEarlyAccess; + uint32_t maxSubsampledArrayLayers; + uint32_t maxDescriptorSetSubsampledSamplers; +} VkPhysicalDeviceFragmentDensityMap2PropertiesEXT; + + + +#define VK_QCOM_rotated_copy_commands 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION 1 +#define VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME "VK_QCOM_rotated_copy_commands" +typedef struct VkCopyCommandTransformInfoQCOM { + VkStructureType sType; + const void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkCopyCommandTransformInfoQCOM; + + + +#define VK_EXT_image_robustness 1 +#define VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION 1 +#define VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME "VK_EXT_image_robustness" +typedef struct VkPhysicalDeviceImageRobustnessFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeaturesEXT; + + + +#define VK_EXT_4444_formats 1 +#define VK_EXT_4444_FORMATS_SPEC_VERSION 1 +#define VK_EXT_4444_FORMATS_EXTENSION_NAME "VK_EXT_4444_formats" +typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatA4R4G4B4; + VkBool32 formatA4B4G4R4; +} VkPhysicalDevice4444FormatsFeaturesEXT; + + + +#define VK_EXT_rgba10x6_formats 1 +#define VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION 1 +#define VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME "VK_EXT_rgba10x6_formats" +typedef struct VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 formatRgba10x6WithoutYCbCrSampler; +} VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT; + + + +#define VK_NV_acquire_winrt_display 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION 1 +#define VK_NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME "VK_NV_acquire_winrt_display" +typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); +typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + VkDisplayKHR display); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( + VkPhysicalDevice physicalDevice, + uint32_t deviceRelativeId, + VkDisplayKHR* pDisplay); +#endif + + +#define VK_VALVE_mutable_descriptor_type 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION 1 +#define VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME "VK_VALVE_mutable_descriptor_type" +typedef struct VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 mutableDescriptorType; +} VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE; + +typedef struct VkMutableDescriptorTypeListVALVE { + uint32_t descriptorTypeCount; + const VkDescriptorType* pDescriptorTypes; +} VkMutableDescriptorTypeListVALVE; + +typedef struct VkMutableDescriptorTypeCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t mutableDescriptorTypeListCount; + const VkMutableDescriptorTypeListVALVE* pMutableDescriptorTypeLists; +} VkMutableDescriptorTypeCreateInfoVALVE; + + + +#define VK_EXT_vertex_input_dynamic_state 1 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION 2 +#define VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME "VK_EXT_vertex_input_dynamic_state" +typedef struct VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 vertexInputDynamicState; +} VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT; + +typedef struct VkVertexInputBindingDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; + uint32_t divisor; +} VkVertexInputBindingDescription2EXT; + +typedef struct VkVertexInputAttributeDescription2EXT { + VkStructureType sType; + void* pNext; + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription2EXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( + VkCommandBuffer commandBuffer, + uint32_t vertexBindingDescriptionCount, + const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, + uint32_t vertexAttributeDescriptionCount, + const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); +#endif + + +#define VK_EXT_physical_device_drm 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION 1 +#define VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME "VK_EXT_physical_device_drm" +typedef struct VkPhysicalDeviceDrmPropertiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 hasPrimary; + VkBool32 hasRender; + int64_t primaryMajor; + int64_t primaryMinor; + int64_t renderMajor; + int64_t renderMinor; +} VkPhysicalDeviceDrmPropertiesEXT; + + + +#define VK_EXT_primitive_topology_list_restart 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME "VK_EXT_primitive_topology_list_restart" +typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveTopologyListRestart; + VkBool32 primitiveTopologyPatchListRestart; +} VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT; + + + +#define VK_HUAWEI_subpass_shading 1 +#define VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION 2 +#define VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME "VK_HUAWEI_subpass_shading" +typedef struct VkSubpassShadingPipelineCreateInfoHUAWEI { + VkStructureType sType; + void* pNext; + VkRenderPass renderPass; + uint32_t subpass; +} VkSubpassShadingPipelineCreateInfoHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 subpassShading; +} VkPhysicalDeviceSubpassShadingFeaturesHUAWEI; + +typedef struct VkPhysicalDeviceSubpassShadingPropertiesHUAWEI { + VkStructureType sType; + void* pNext; + uint32_t maxSubpassShadingWorkgroupSizeAspectRatio; +} VkPhysicalDeviceSubpassShadingPropertiesHUAWEI; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI)(VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( + VkDevice device, + VkRenderPass renderpass, + VkExtent2D* pMaxWorkgroupSize); + +VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( + VkCommandBuffer commandBuffer); +#endif + + +#define VK_HUAWEI_invocation_mask 1 +#define VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION 1 +#define VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME "VK_HUAWEI_invocation_mask" +typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { + VkStructureType sType; + void* pNext; + VkBool32 invocationMask; +} VkPhysicalDeviceInvocationMaskFeaturesHUAWEI; + +typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( + VkCommandBuffer commandBuffer, + VkImageView imageView, + VkImageLayout imageLayout); +#endif + + +#define VK_NV_external_memory_rdma 1 +typedef void* VkRemoteAddressNV; +#define VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME "VK_NV_external_memory_rdma" +typedef struct VkMemoryGetRemoteAddressInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetRemoteAddressInfoNV; + +typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 externalMemoryRDMA; +} VkPhysicalDeviceExternalMemoryRDMAFeaturesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( + VkDevice device, + const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, + VkRemoteAddressNV* pAddress); +#endif + + +#define VK_EXT_extended_dynamic_state2 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION 1 +#define VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME "VK_EXT_extended_dynamic_state2" +typedef struct VkPhysicalDeviceExtendedDynamicState2FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 extendedDynamicState2; + VkBool32 extendedDynamicState2LogicOp; + VkBool32 extendedDynamicState2PatchControlPoints; +} VkPhysicalDeviceExtendedDynamicState2FeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPatchControlPointsEXT)(VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, VkLogicOp logicOp); +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( + VkCommandBuffer commandBuffer, + uint32_t patchControlPoints); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 rasterizerDiscardEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 depthBiasEnable); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( + VkCommandBuffer commandBuffer, + VkLogicOp logicOp); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( + VkCommandBuffer commandBuffer, + VkBool32 primitiveRestartEnable); +#endif + + +#define VK_EXT_color_write_enable 1 +#define VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION 1 +#define VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME "VK_EXT_color_write_enable" +typedef struct VkPhysicalDeviceColorWriteEnableFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 colorWriteEnable; +} VkPhysicalDeviceColorWriteEnableFeaturesEXT; + +typedef struct VkPipelineColorWriteCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t attachmentCount; + const VkBool32* pColorWriteEnables; +} VkPipelineColorWriteCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( + VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkBool32* pColorWriteEnables); +#endif + + +#define VK_EXT_global_priority_query 1 +#define VK_MAX_GLOBAL_PRIORITY_SIZE_EXT 16U +#define VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION 1 +#define VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME "VK_EXT_global_priority_query" +typedef struct VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 globalPriorityQuery; +} VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + +typedef struct VkQueueFamilyGlobalPriorityPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t priorityCount; + VkQueueGlobalPriorityEXT priorities[VK_MAX_GLOBAL_PRIORITY_SIZE_EXT]; +} VkQueueFamilyGlobalPriorityPropertiesEXT; + + + +#define VK_EXT_multi_draw 1 +#define VK_EXT_MULTI_DRAW_SPEC_VERSION 1 +#define VK_EXT_MULTI_DRAW_EXTENSION_NAME "VK_EXT_multi_draw" +typedef struct VkPhysicalDeviceMultiDrawFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multiDraw; +} VkPhysicalDeviceMultiDrawFeaturesEXT; + +typedef struct VkPhysicalDeviceMultiDrawPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxMultiDrawCount; +} VkPhysicalDeviceMultiDrawPropertiesEXT; + +typedef struct VkMultiDrawInfoEXT { + uint32_t firstVertex; + uint32_t vertexCount; +} VkMultiDrawInfoEXT; + +typedef struct VkMultiDrawIndexedInfoEXT { + uint32_t firstIndex; + uint32_t indexCount; + int32_t vertexOffset; +} VkMultiDrawIndexedInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( + VkCommandBuffer commandBuffer, + uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, + uint32_t instanceCount, + uint32_t firstInstance, + uint32_t stride, + const int32_t* pVertexOffset); +#endif + + +#define VK_EXT_load_store_op_none 1 +#define VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION 1 +#define VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_EXT_load_store_op_none" + + +#define VK_EXT_border_color_swizzle 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION 1 +#define VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME "VK_EXT_border_color_swizzle" +typedef struct VkPhysicalDeviceBorderColorSwizzleFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 borderColorSwizzle; + VkBool32 borderColorSwizzleFromImage; +} VkPhysicalDeviceBorderColorSwizzleFeaturesEXT; + +typedef struct VkSamplerBorderColorComponentMappingCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkComponentMapping components; + VkBool32 srgb; +} VkSamplerBorderColorComponentMappingCreateInfoEXT; + + + +#define VK_EXT_pageable_device_local_memory 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION 1 +#define VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME "VK_EXT_pageable_device_local_memory" +typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pageableDeviceLocalMemory; +} VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( + VkDevice device, + VkDeviceMemory memory, + float priority); +#endif + + +#define VK_KHR_acceleration_structure 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 +#define VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_KHR_acceleration_structure" + +typedef enum VkBuildAccelerationStructureModeKHR { + VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR = 0, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, + VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureModeKHR; + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; + +typedef enum VkAccelerationStructureCompatibilityKHR { + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_INCOMPATIBLE_KHR = 1, + VK_ACCELERATION_STRUCTURE_COMPATIBILITY_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCompatibilityKHR; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef struct VkAccelerationStructureBuildRangeInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildRangeInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + uint32_t maxVertex; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBuildAccelerationStructureModeKHR mode; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* pGeometries; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; + VkAccelerationStructureTypeKHR type; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef struct VkPhysicalDeviceAccelerationStructureFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 accelerationStructure; + VkBool32 accelerationStructureCaptureReplay; + VkBool32 accelerationStructureIndirectBuild; + VkBool32 accelerationStructureHostCommands; + VkBool32 descriptorBindingAccelerationStructureUpdateAfterBind; +} VkPhysicalDeviceAccelerationStructureFeaturesKHR; + +typedef struct VkPhysicalDeviceAccelerationStructurePropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxPerStageDescriptorAccelerationStructures; + uint32_t maxPerStageDescriptorUpdateAfterBindAccelerationStructures; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t maxDescriptorSetUpdateAfterBindAccelerationStructures; + uint32_t minAccelerationStructureScratchOffsetAlignment; +} VkPhysicalDeviceAccelerationStructurePropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionInfoKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* pVersionData; +} VkAccelerationStructureVersionInfoKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef struct VkAccelerationStructureBuildSizesInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize accelerationStructureSize; + VkDeviceSize updateScratchSize; + VkDeviceSize buildScratchSize; +} VkAccelerationStructureBuildSizesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructuresIndirectKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructuresKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkDeviceAddress* pIndirectDeviceAddresses, + const uint32_t* pIndirectStrides, + const uint32_t* const* ppMaxPrimitiveCounts); + +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionInfoKHR* pVersionInfo, + VkAccelerationStructureCompatibilityKHR* pCompatibility); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( + VkDevice device, + VkAccelerationStructureBuildTypeKHR buildType, + const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, + const uint32_t* pMaxPrimitiveCounts, + VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif + + +#define VK_KHR_ray_tracing_pipeline 1 +#define VK_KHR_RAY_TRACING_PIPELINE_SPEC_VERSION 1 +#define VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME "VK_KHR_ray_tracing_pipeline" + +typedef enum VkShaderGroupShaderKHR { + VK_SHADER_GROUP_SHADER_GENERAL_KHR = 0, + VK_SHADER_GROUP_SHADER_CLOSEST_HIT_KHR = 1, + VK_SHADER_GROUP_SHADER_ANY_HIT_KHR = 2, + VK_SHADER_GROUP_SHADER_INTERSECTION_KHR = 3, + VK_SHADER_GROUP_SHADER_MAX_ENUM_KHR = 0x7FFFFFFF +} VkShaderGroupShaderKHR; +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPipelineRayPayloadSize; + uint32_t maxPipelineRayHitAttributeSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxPipelineRayRecursionDepth; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelineFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingPipeline; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay; + VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingPipelineTraceRaysIndirect; + VkBool32 rayTraversalPrimitiveCulling; +} VkPhysicalDeviceRayTracingPipelineFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPipelinePropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRayRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint32_t shaderGroupHandleCaptureReplaySize; + uint32_t maxRayDispatchInvocationCount; + uint32_t shaderGroupHandleAlignment; + uint32_t maxRayHitAttributeSize; +} VkPhysicalDeviceRayTracingPipelinePropertiesKHR; + +typedef struct VkStridedDeviceAddressRegionKHR { + VkDeviceAddress deviceAddress; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedDeviceAddressRegionKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress); + +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t group, + VkShaderGroupShaderKHR groupShader); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( + VkCommandBuffer commandBuffer, + uint32_t pipelineStackSize); +#endif + + +#define VK_KHR_ray_query 1 +#define VK_KHR_RAY_QUERY_SPEC_VERSION 1 +#define VK_KHR_RAY_QUERY_EXTENSION_NAME "VK_KHR_ray_query" +typedef struct VkPhysicalDeviceRayQueryFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayQuery; +} VkPhysicalDeviceRayQueryFeaturesKHR; + + #ifdef __cplusplus } #endif diff --git a/third_party/vulkan/vulkan_directfb.h b/third_party/vulkan/vulkan_directfb.h new file mode 100644 index 000000000..8eaac6e48 --- /dev/null +++ b/third_party/vulkan/vulkan_directfb.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_DIRECTFB_H_ +#define VULKAN_DIRECTFB_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_EXT_directfb_surface 1 +#define VK_EXT_DIRECTFB_SURFACE_SPEC_VERSION 1 +#define VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "VK_EXT_directfb_surface" +typedef VkFlags VkDirectFBSurfaceCreateFlagsEXT; +typedef struct VkDirectFBSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkDirectFBSurfaceCreateFlagsEXT flags; + IDirectFB* dfb; + IDirectFBSurface* surface; +} VkDirectFBSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDirectFBSurfaceEXT)(VkInstance instance, const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, IDirectFB* dfb); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT( + VkInstance instance, + const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceDirectFBPresentationSupportEXT( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + IDirectFB* dfb); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_fuchsia.h b/third_party/vulkan/vulkan_fuchsia.h new file mode 100644 index 000000000..44b4ace3e --- /dev/null +++ b/third_party/vulkan/vulkan_fuchsia.h @@ -0,0 +1,258 @@ +#ifndef VULKAN_FUCHSIA_H_ +#define VULKAN_FUCHSIA_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_FUCHSIA_imagepipe_surface 1 +#define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1 +#define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface" +typedef VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA; +typedef struct VkImagePipeSurfaceCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImagePipeSurfaceCreateFlagsFUCHSIA flags; + zx_handle_t imagePipeHandle; +} VkImagePipeSurfaceCreateInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateImagePipeSurfaceFUCHSIA)(VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA( + VkInstance instance, + const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +#define VK_FUCHSIA_external_memory 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory" +typedef struct VkImportMemoryZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + zx_handle_t handle; +} VkImportMemoryZirconHandleInfoFUCHSIA; + +typedef struct VkMemoryZirconHandlePropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryZirconHandlePropertiesFUCHSIA; + +typedef struct VkMemoryGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandleFUCHSIA)(VkDevice device, const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, zx_handle_t zirconHandle, VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandleFUCHSIA( + VkDevice device, + const VkMemoryGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + zx_handle_t zirconHandle, + VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties); +#endif + + +#define VK_FUCHSIA_external_semaphore 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1 +#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore" +typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkSemaphoreImportFlags flags; + VkExternalSemaphoreHandleTypeFlagBits handleType; + zx_handle_t zirconHandle; +} VkImportSemaphoreZirconHandleInfoFUCHSIA; + +typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkExternalSemaphoreHandleTypeFlagBits handleType; +} VkSemaphoreGetZirconHandleInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreZirconHandleFUCHSIA)(VkDevice device, const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, zx_handle_t* pZirconHandle); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreZirconHandleFUCHSIA( + VkDevice device, + const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo, + zx_handle_t* pZirconHandle); +#endif + + +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 2 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection" +typedef VkFlags VkImageFormatConstraintsFlagsFUCHSIA; + +typedef enum VkImageConstraintsInfoFlagBitsFUCHSIA { + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA = 0x00000001, + VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA = 0x00000002, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA = 0x00000004, + VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA = 0x00000008, + VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA = 0x00000010, + VK_IMAGE_CONSTRAINTS_INFO_FLAG_BITS_MAX_ENUM_FUCHSIA = 0x7FFFFFFF +} VkImageConstraintsInfoFlagBitsFUCHSIA; +typedef VkFlags VkImageConstraintsInfoFlagsFUCHSIA; +typedef struct VkBufferCollectionCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + zx_handle_t collectionToken; +} VkBufferCollectionCreateInfoFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +typedef struct VkBufferCollectionConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t minBufferCount; + uint32_t maxBufferCount; + uint32_t minBufferCountForCamping; + uint32_t minBufferCountForDedicatedSlack; + uint32_t minBufferCountForSharedSlack; +} VkBufferCollectionConstraintsInfoFUCHSIA; + +typedef struct VkBufferConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCreateInfo createInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; +} VkBufferConstraintsInfoFUCHSIA; + +typedef struct VkBufferCollectionBufferCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionBufferCreateInfoFUCHSIA; + +typedef struct VkSysmemColorSpaceFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t colorSpace; +} VkSysmemColorSpaceFUCHSIA; + +typedef struct VkBufferCollectionPropertiesFUCHSIA { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; + uint32_t bufferCount; + uint32_t createInfoIndex; + uint64_t sysmemPixelFormat; + VkFormatFeatureFlags formatFeatures; + VkSysmemColorSpaceFUCHSIA sysmemColorSpaceIndex; + VkComponentMapping samplerYcbcrConversionComponents; + VkSamplerYcbcrModelConversion suggestedYcbcrModel; + VkSamplerYcbcrRange suggestedYcbcrRange; + VkChromaLocation suggestedXChromaOffset; + VkChromaLocation suggestedYChromaOffset; +} VkBufferCollectionPropertiesFUCHSIA; + +typedef struct VkImageFormatConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkImageCreateInfo imageCreateInfo; + VkFormatFeatureFlags requiredFormatFeatures; + VkImageFormatConstraintsFlagsFUCHSIA flags; + uint64_t sysmemPixelFormat; + uint32_t colorSpaceCount; + const VkSysmemColorSpaceFUCHSIA* pColorSpaces; +} VkImageFormatConstraintsInfoFUCHSIA; + +typedef struct VkImageConstraintsInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + uint32_t formatConstraintsCount; + const VkImageFormatConstraintsInfoFUCHSIA* pFormatConstraints; + VkBufferCollectionConstraintsInfoFUCHSIA bufferCollectionConstraints; + VkImageConstraintsInfoFlagsFUCHSIA flags; +} VkImageConstraintsInfoFUCHSIA; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferCollectionFUCHSIA)(VkDevice device, const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferCollectionFUCHSIA* pCollection); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); +typedef VkResult (VKAPI_PTR *PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferCollectionFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetBufferCollectionPropertiesFUCHSIA)(VkDevice device, VkBufferCollectionFUCHSIA collection, VkBufferCollectionPropertiesFUCHSIA* pProperties); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferCollectionFUCHSIA( + VkDevice device, + const VkBufferCollectionCreateInfoFUCHSIA* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferCollectionFUCHSIA* pCollection); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionImageConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetBufferCollectionBufferConstraintsFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferCollectionFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_ggp.h b/third_party/vulkan/vulkan_ggp.h new file mode 100644 index 000000000..9a6a582c5 --- /dev/null +++ b/third_party/vulkan/vulkan_ggp.h @@ -0,0 +1,58 @@ +#ifndef VULKAN_GGP_H_ +#define VULKAN_GGP_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_GGP_stream_descriptor_surface 1 +#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_SPEC_VERSION 1 +#define VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME "VK_GGP_stream_descriptor_surface" +typedef VkFlags VkStreamDescriptorSurfaceCreateFlagsGGP; +typedef struct VkStreamDescriptorSurfaceCreateInfoGGP { + VkStructureType sType; + const void* pNext; + VkStreamDescriptorSurfaceCreateFlagsGGP flags; + GgpStreamDescriptor streamDescriptor; +} VkStreamDescriptorSurfaceCreateInfoGGP; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateStreamDescriptorSurfaceGGP)(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP( + VkInstance instance, + const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + + +#define VK_GGP_frame_token 1 +#define VK_GGP_FRAME_TOKEN_SPEC_VERSION 1 +#define VK_GGP_FRAME_TOKEN_EXTENSION_NAME "VK_GGP_frame_token" +typedef struct VkPresentFrameTokenGGP { + VkStructureType sType; + const void* pNext; + GgpFrameToken frameToken; +} VkPresentFrameTokenGGP; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_ios.h b/third_party/vulkan/vulkan_ios.h index a0924816d..6e7e6afea 100644 --- a/third_party/vulkan/vulkan_ios.h +++ b/third_party/vulkan/vulkan_ios.h @@ -1,24 +1,10 @@ #ifndef VULKAN_IOS_H_ #define VULKAN_IOS_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_MVK_ios_surface 1 -#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_IOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface" - typedef VkFlags VkIOSSurfaceCreateFlagsMVK; - typedef struct VkIOSSurfaceCreateInfoMVK { VkStructureType sType; const void* pNext; @@ -40,7 +30,6 @@ typedef struct VkIOSSurfaceCreateInfoMVK { const void* pView; } VkIOSSurfaceCreateInfoMVK; - typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES diff --git a/third_party/vulkan/vulkan_macos.h b/third_party/vulkan/vulkan_macos.h index ff0b70180..c49b123d0 100644 --- a/third_party/vulkan/vulkan_macos.h +++ b/third_party/vulkan/vulkan_macos.h @@ -1,24 +1,10 @@ #ifndef VULKAN_MACOS_H_ #define VULKAN_MACOS_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_MVK_macos_surface 1 -#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2 +#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 3 #define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface" - typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; - typedef struct VkMacOSSurfaceCreateInfoMVK { VkStructureType sType; const void* pNext; @@ -40,7 +30,6 @@ typedef struct VkMacOSSurfaceCreateInfoMVK { const void* pView; } VkMacOSSurfaceCreateInfoMVK; - typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES diff --git a/third_party/vulkan/vulkan_metal.h b/third_party/vulkan/vulkan_metal.h new file mode 100644 index 000000000..5cf4a703a --- /dev/null +++ b/third_party/vulkan/vulkan_metal.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_METAL_H_ +#define VULKAN_METAL_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_EXT_metal_surface 1 + +#ifdef __OBJC__ +@class CAMetalLayer; +#else +typedef void CAMetalLayer; +#endif + +#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1 +#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" +typedef VkFlags VkMetalSurfaceCreateFlagsEXT; +typedef struct VkMetalSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMetalSurfaceCreateFlagsEXT flags; + const CAMetalLayer* pLayer; +} VkMetalSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( + VkInstance instance, + const VkMetalSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_mir.h b/third_party/vulkan/vulkan_mir.h deleted file mode 100644 index 7d24ed27a..000000000 --- a/third_party/vulkan/vulkan_mir.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef VULKAN_MIR_H_ -#define VULKAN_MIR_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2015-2018 The Khronos Group Inc. -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/* -** This header is generated from the Khronos Vulkan XML API Registry. -** -*/ - - -#define VK_KHR_mir_surface 1 -#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4 -#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface" - -typedef VkFlags VkMirSurfaceCreateFlagsKHR; - -typedef struct VkMirSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkMirSurfaceCreateFlagsKHR flags; - MirConnection* connection; - MirSurface* mirSurface; -} VkMirSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( - VkInstance instance, - const VkMirSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - MirConnection* connection); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/third_party/vulkan/vulkan_screen.h b/third_party/vulkan/vulkan_screen.h new file mode 100644 index 000000000..92ad9bfab --- /dev/null +++ b/third_party/vulkan/vulkan_screen.h @@ -0,0 +1,54 @@ +#ifndef VULKAN_SCREEN_H_ +#define VULKAN_SCREEN_H_ 1 + +/* +** Copyright 2015-2021 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_QNX_screen_surface 1 +#define VK_QNX_SCREEN_SURFACE_SPEC_VERSION 1 +#define VK_QNX_SCREEN_SURFACE_EXTENSION_NAME "VK_QNX_screen_surface" +typedef VkFlags VkScreenSurfaceCreateFlagsQNX; +typedef struct VkScreenSurfaceCreateInfoQNX { + VkStructureType sType; + const void* pNext; + VkScreenSurfaceCreateFlagsQNX flags; + struct _screen_context* context; + struct _screen_window* window; +} VkScreenSurfaceCreateInfoQNX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateScreenSurfaceQNX)(VkInstance instance, const VkScreenSurfaceCreateInfoQNX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct _screen_window* window); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX( + VkInstance instance, + const VkScreenSurfaceCreateInfoQNX* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); + +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct _screen_window* window); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/third_party/vulkan/vulkan_vi.h b/third_party/vulkan/vulkan_vi.h index 015166bfc..9e0dcca20 100644 --- a/third_party/vulkan/vulkan_vi.h +++ b/third_party/vulkan/vulkan_vi.h @@ -1,24 +1,10 @@ #ifndef VULKAN_VI_H_ #define VULKAN_VI_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_NN_vi_surface 1 #define VK_NN_VI_SURFACE_SPEC_VERSION 1 #define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface" - typedef VkFlags VkViSurfaceCreateFlagsNN; - typedef struct VkViSurfaceCreateInfoNN { VkStructureType sType; const void* pNext; @@ -40,7 +30,6 @@ typedef struct VkViSurfaceCreateInfoNN { void* window; } VkViSurfaceCreateInfoNN; - typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES diff --git a/third_party/vulkan/vulkan_wayland.h b/third_party/vulkan/vulkan_wayland.h index 5ba0827aa..2a329be9d 100644 --- a/third_party/vulkan/vulkan_wayland.h +++ b/third_party/vulkan/vulkan_wayland.h @@ -1,24 +1,10 @@ #ifndef VULKAN_WAYLAND_H_ #define VULKAN_WAYLAND_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_KHR_wayland_surface 1 #define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 #define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" - typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; - typedef struct VkWaylandSurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -41,7 +31,6 @@ typedef struct VkWaylandSurfaceCreateInfoKHR { struct wl_surface* surface; } VkWaylandSurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); diff --git a/third_party/vulkan/vulkan_win32.h b/third_party/vulkan/vulkan_win32.h index 6a85409eb..1b680f0b1 100644 --- a/third_party/vulkan/vulkan_win32.h +++ b/third_party/vulkan/vulkan_win32.h @@ -1,24 +1,10 @@ #ifndef VULKAN_WIN32_H_ #define VULKAN_WIN32_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_KHR_win32_surface 1 #define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6 #define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface" - typedef VkFlags VkWin32SurfaceCreateFlagsKHR; - typedef struct VkWin32SurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -41,7 +31,6 @@ typedef struct VkWin32SurfaceCreateInfoKHR { HWND hwnd; } VkWin32SurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); @@ -57,10 +46,10 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( uint32_t queueFamilyIndex); #endif + #define VK_KHR_external_memory_win32 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32" - typedef struct VkImportMemoryWin32HandleInfoKHR { VkStructureType sType; const void* pNext; @@ -90,7 +79,6 @@ typedef struct VkMemoryGetWin32HandleInfoKHR { VkExternalMemoryHandleTypeFlagBits handleType; } VkMemoryGetWin32HandleInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); @@ -107,10 +95,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); #endif + #define VK_KHR_win32_keyed_mutex 1 #define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1 #define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex" - typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { VkStructureType sType; const void* pNext; @@ -128,7 +116,6 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR { #define VK_KHR_external_semaphore_win32 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32" - typedef struct VkImportSemaphoreWin32HandleInfoKHR { VkStructureType sType; const void* pNext; @@ -163,7 +150,6 @@ typedef struct VkSemaphoreGetWin32HandleInfoKHR { VkExternalSemaphoreHandleTypeFlagBits handleType; } VkSemaphoreGetWin32HandleInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); @@ -178,10 +164,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( HANDLE* pHandle); #endif + #define VK_KHR_external_fence_win32 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1 #define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32" - typedef struct VkImportFenceWin32HandleInfoKHR { VkStructureType sType; const void* pNext; @@ -207,7 +193,6 @@ typedef struct VkFenceGetWin32HandleInfoKHR { VkExternalFenceHandleTypeFlagBits handleType; } VkFenceGetWin32HandleInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); @@ -222,10 +207,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( HANDLE* pHandle); #endif + #define VK_NV_external_memory_win32 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1 #define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32" - typedef struct VkImportMemoryWin32HandleInfoNV { VkStructureType sType; const void* pNext; @@ -240,7 +225,6 @@ typedef struct VkExportMemoryWin32HandleInfoNV { DWORD dwAccess; } VkExportMemoryWin32HandleInfoNV; - typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); #ifndef VK_NO_PROTOTYPES @@ -251,10 +235,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( HANDLE* pHandle); #endif -#define VK_NV_win32_keyed_mutex 1 -#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1 -#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" +#define VK_NV_win32_keyed_mutex 1 +#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2 +#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex" typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { VkStructureType sType; const void* pNext; @@ -269,6 +253,61 @@ typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV { +#define VK_EXT_full_screen_exclusive 1 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4 +#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive" + +typedef enum VkFullScreenExclusiveEXT { + VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0, + VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1, + VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2, + VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3, + VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkFullScreenExclusiveEXT; +typedef struct VkSurfaceFullScreenExclusiveInfoEXT { + VkStructureType sType; + void* pNext; + VkFullScreenExclusiveEXT fullScreenExclusive; +} VkSurfaceFullScreenExclusiveInfoEXT; + +typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT { + VkStructureType sType; + void* pNext; + VkBool32 fullScreenExclusiveSupported; +} VkSurfaceCapabilitiesFullScreenExclusiveEXT; + +typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT { + VkStructureType sType; + const void* pNext; + HMONITOR hmonitor; +} VkSurfaceFullScreenExclusiveWin32InfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); +typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes); + +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); + +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT( + VkDevice device, + VkSwapchainKHR swapchain); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( + VkDevice device, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + VkDeviceGroupPresentModeFlagsKHR* pModes); +#endif + #ifdef __cplusplus } #endif diff --git a/third_party/vulkan/vulkan_xcb.h b/third_party/vulkan/vulkan_xcb.h index ba0360060..5ba2ad850 100644 --- a/third_party/vulkan/vulkan_xcb.h +++ b/third_party/vulkan/vulkan_xcb.h @@ -1,24 +1,10 @@ #ifndef VULKAN_XCB_H_ #define VULKAN_XCB_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_KHR_xcb_surface 1 #define VK_KHR_XCB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface" - typedef VkFlags VkXcbSurfaceCreateFlagsKHR; - typedef struct VkXcbSurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -41,7 +31,6 @@ typedef struct VkXcbSurfaceCreateInfoKHR { xcb_window_t window; } VkXcbSurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); diff --git a/third_party/vulkan/vulkan_xlib.h b/third_party/vulkan/vulkan_xlib.h index e1d967e01..75c75dc2e 100644 --- a/third_party/vulkan/vulkan_xlib.h +++ b/third_party/vulkan/vulkan_xlib.h @@ -1,24 +1,10 @@ #ifndef VULKAN_XLIB_H_ #define VULKAN_XLIB_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,12 +13,16 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_KHR_xlib_surface 1 #define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6 #define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface" - typedef VkFlags VkXlibSurfaceCreateFlagsKHR; - typedef struct VkXlibSurfaceCreateInfoKHR { VkStructureType sType; const void* pNext; @@ -41,7 +31,6 @@ typedef struct VkXlibSurfaceCreateInfoKHR { Window window; } VkXlibSurfaceCreateInfoKHR; - typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); diff --git a/third_party/vulkan/vulkan_xlib_xrandr.h b/third_party/vulkan/vulkan_xlib_xrandr.h index 117d01799..fa2749342 100644 --- a/third_party/vulkan/vulkan_xlib_xrandr.h +++ b/third_party/vulkan/vulkan_xlib_xrandr.h @@ -1,24 +1,10 @@ #ifndef VULKAN_XLIB_XRANDR_H_ #define VULKAN_XLIB_XRANDR_H_ 1 -#ifdef __cplusplus -extern "C" { -#endif - /* -** Copyright (c) 2015-2018 The Khronos Group Inc. +** Copyright 2015-2021 The Khronos Group Inc. ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. +** SPDX-License-Identifier: Apache-2.0 */ /* @@ -27,10 +13,15 @@ extern "C" { */ +#ifdef __cplusplus +extern "C" { +#endif + + + #define VK_EXT_acquire_xlib_display 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1 #define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display" - typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display); typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay); diff --git a/xenia-build b/xenia-build index 2efb2400e..a37f76d8e 100755 --- a/xenia-build +++ b/xenia-build @@ -902,7 +902,8 @@ class BuildShadersCommand(Command): if sys.platform == 'win32': print('Building Direct3D 12 Shader Model 5.1 DXBC shaders...') windows_sdk_bin_path = os.path.join( - os.environ['ProgramFiles(x86)'], 'Windows Kits/10/bin/x64') + os.environ['ProgramFiles(x86)'], + 'Windows Kits/10/bin/10.0.19041.0/x64') fxc = os.path.join(windows_sdk_bin_path, 'fxc') # Ensure we have the tools. if not os.path.exists(windows_sdk_bin_path): @@ -921,12 +922,16 @@ class BuildShadersCommand(Command): os.makedirs(dxbc_dir_path, exist_ok=True) dxbc_file_path_base = os.path.join(dxbc_dir_path, dxbc_identifier) + # Not enabling treating warnings as errors (/WX) because it + # overrides #pragma warning, and the FXAA shader triggers a + # bug in FXC causing an uninitialized variable warning if + # early exit from a function is done. if subprocess.call([ fxc, + '/D', 'XESL_LANGUAGE_HLSL=1', '/Fh', dxbc_file_path_base + '.h', '/T', dxbc_identifier[-2:] + '_5_1', '/Vn', dxbc_identifier, - '/WX', '/nologo', src_path ], stdout=subprocess.DEVNULL): @@ -966,7 +971,6 @@ class GenSpirvCommand(Command): vulkan_bin_path = os.path.join(vulkan_sdk_path, 'bin') glslang = os.path.join(vulkan_bin_path, 'glslangValidator') spirv_dis = os.path.join(vulkan_bin_path, 'spirv-dis') - spirv_remap = os.path.join(vulkan_bin_path, 'spirv-remap') # Ensure we have the tools. if not os.path.exists(vulkan_sdk_path): @@ -978,9 +982,6 @@ class GenSpirvCommand(Command): elif not has_bin(spirv_dis): print('ERROR: could not find spirv-dis') return 1 - elif not has_bin(spirv_remap): - print('ERROR: could not find spirv-remap') - return 1 src_files = [os.path.join(root, name) for root, dirs, files in os.walk('src') @@ -994,7 +995,8 @@ class GenSpirvCommand(Command): src_name = os.path.splitext(os.path.basename(src_file))[0] identifier = os.path.basename(src_file).replace('.', '_') - bin_path = os.path.join(os.path.dirname(src_file), 'bin') + bin_path = os.path.join(os.path.dirname(src_file), + 'bytecode/vulkan_spirv') spv_file = os.path.join(bin_path, identifier) + '.spv' txt_file = os.path.join(bin_path, identifier) + '.txt' h_file = os.path.join(bin_path, identifier) + '.h' @@ -1002,6 +1004,7 @@ class GenSpirvCommand(Command): # GLSL source -> .spv binary shell_call([ glslang, + '-DXESL_LANGUAGE_GLSL=1', '-Os', '-V', src_file, '-o', spv_file,