summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/atomic_ops.h5
-rw-r--r--src/common/bit_field.h1
-rw-r--r--src/common/dynamic_library.cpp1
-rw-r--r--src/common/fs/file.cpp1
-rw-r--r--src/common/fs/file.h2
-rw-r--r--src/common/fs/fs_types.h1
-rw-r--r--src/common/fs/fs_util.h1
-rw-r--r--src/common/hex_util.h1
-rw-r--r--src/common/host_memory.cpp2
-rw-r--r--src/common/intrusive_red_black_tree.h1
-rw-r--r--src/common/logging/backend.cpp2
-rw-r--r--src/common/logging/backend.h1
-rw-r--r--src/common/logging/filter.cpp1
-rw-r--r--src/common/logging/filter.h1
-rw-r--r--src/common/logging/text_formatter.cpp2
-rw-r--r--src/common/logging/text_formatter.h1
-rw-r--r--src/common/logging/types.h1
-rw-r--r--src/common/math_util.h50
-rw-r--r--src/common/memory_detect.cpp2
-rw-r--r--src/common/nvidia_flags.cpp1
-rw-r--r--src/common/page_table.h1
-rw-r--r--src/common/parent_of_member.h1
-rw-r--r--src/common/ring_buffer.h1
-rw-r--r--src/common/string_util.cpp2
-rw-r--r--src/common/telemetry.cpp1
-rw-r--r--src/common/telemetry.h1
-rw-r--r--src/common/uint128.h2
-rw-r--r--src/common/uuid.h1
-rw-r--r--src/common/virtual_buffer.h1
-rw-r--r--src/common/wall_clock.cpp2
-rw-r--r--src/common/x64/cpu_detect.cpp1
-rw-r--r--src/common/x64/native_clock.cpp2
-rw-r--r--src/common/x64/native_clock.h2
-rw-r--r--src/core/CMakeLists.txt38
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp10
-rw-r--r--src/core/arm/dynarmic/arm_exclusive_monitor.h2
-rw-r--r--src/core/core.cpp1
-rw-r--r--src/core/file_sys/directory.h1
-rw-r--r--src/core/file_sys/patch_manager.cpp3
-rw-r--r--src/core/file_sys/program_metadata.h2
-rw-r--r--src/core/frontend/applets/mii.cpp19
-rw-r--r--src/core/frontend/applets/mii.h35
-rw-r--r--src/core/frontend/applets/mii_edit.cpp18
-rw-r--r--src/core/frontend/applets/mii_edit.h23
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp1
-rw-r--r--src/core/hle/kernel/k_class_token.h2
-rw-r--r--src/core/hle/kernel/k_code_memory.cpp4
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp1
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp1
-rw-r--r--src/core/hle/kernel/k_page_buffer.h1
-rw-r--r--src/core/hle/kernel/k_page_linked_list.h4
-rw-r--r--src/core/hle/kernel/k_page_table.cpp242
-rw-r--r--src/core/hle/kernel/k_page_table.h33
-rw-r--r--src/core/hle/kernel/k_process.cpp2
-rw-r--r--src/core/hle/kernel/k_process.h1
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp1
-rw-r--r--src/core/hle/kernel/k_thread.cpp3
-rw-r--r--src/core/hle/kernel/k_thread_local_page.cpp2
-rw-r--r--src/core/hle/kernel/k_thread_local_page.h1
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/svc.cpp13
-rw-r--r--src/core/hle/service/acc/acc.cpp1
-rw-r--r--src/core/hle/service/acc/profile_manager.h1
-rw-r--r--src/core/hle/service/am/applets/applet_mii.cpp101
-rw-r--r--src/core/hle/service/am/applets/applet_mii.h90
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp139
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.h45
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit_types.h83
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.cpp474
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.h35
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard_types.h72
-rw-r--r--src/core/hle/service/am/applets/applets.cpp28
-rw-r--r--src/core/hle/service/am/applets/applets.h8
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp1
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.h1
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h1
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h3
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h4
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h3
-rw-r--r--src/core/hle/service/hid/controllers/npad.h3
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp1
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h3
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp4
-rw-r--r--src/core/hle/service/ldr/ldr.cpp1
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp3
-rw-r--r--src/core/hle/service/mii/mii_manager.h303
-rw-r--r--src/core/hle/service/mii/raw_data.h2
-rw-r--r--src/core/hle/service/mii/types.h307
-rw-r--r--src/core/hle/service/nfp/nfp.cpp1
-rw-r--r--src/core/hle/service/nfp/nfp.h2
-rw-r--r--src/core/hle/service/nifm/nifm.cpp1
-rw-r--r--src/core/hle/service/ns/pdm_qry.cpp1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp10
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h7
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp7
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h11
-rw-r--r--src/core/hle/service/nvdrv/nvdata.h10
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h3
-rw-r--r--src/core/hle/service/nvflinger/binder.h42
-rw-r--r--src/core/hle/service/nvflinger/buffer_item.h46
-rw-r--r--src/core/hle/service/nvflinger/buffer_item_consumer.cpp59
-rw-r--r--src/core/hle/service/nvflinger/buffer_item_consumer.h28
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp206
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h154
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.cpp203
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.h37
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_core.cpp118
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_core.h81
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_defs.h21
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp942
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.h83
-rw-r--r--src/core/hle/service/nvflinger/buffer_slot.h39
-rw-r--r--src/core/hle/service/nvflinger/buffer_transform_flags.h25
-rw-r--r--src/core/hle/service/nvflinger/consumer_base.cpp130
-rw-r--r--src/core/hle/service/nvflinger/consumer_base.h61
-rw-r--r--src/core/hle/service/nvflinger/consumer_listener.h26
-rw-r--r--src/core/hle/service/nvflinger/graphic_buffer_producer.cpp20
-rw-r--r--src/core/hle/service/nvflinger/graphic_buffer_producer.h76
-rw-r--r--src/core/hle/service/nvflinger/hos_binder_driver_server.cpp36
-rw-r--r--src/core/hle/service/nvflinger/hos_binder_driver_server.h37
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp81
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h26
-rw-r--r--src/core/hle/service/nvflinger/parcel.h172
-rw-r--r--src/core/hle/service/nvflinger/pixel_format.h21
-rw-r--r--src/core/hle/service/nvflinger/producer_listener.h16
-rw-r--r--src/core/hle/service/nvflinger/status.h28
-rw-r--r--src/core/hle/service/nvflinger/ui/fence.h32
-rw-r--r--src/core/hle/service/nvflinger/ui/graphic_buffer.h100
-rw-r--r--src/core/hle/service/nvflinger/window.h53
-rw-r--r--src/core/hle/service/service.cpp6
-rw-r--r--src/core/hle/service/service.h4
-rw-r--r--src/core/hle/service/sockets/bsd.cpp1
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp50
-rw-r--r--src/core/hle/service/vi/display/vi_display.h29
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp6
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h57
-rw-r--r--src/core/hle/service/vi/vi.cpp690
-rw-r--r--src/core/hle/service/vi/vi.h10
-rw-r--r--src/core/hle/service/vi/vi_m.cpp9
-rw-r--r--src/core/hle/service/vi/vi_m.h7
-rw-r--r--src/core/hle/service/vi/vi_s.cpp9
-rw-r--r--src/core/hle/service/vi/vi_s.h7
-rw-r--r--src/core/hle/service/vi/vi_u.cpp9
-rw-r--r--src/core/hle/service/vi/vi_u.h7
-rw-r--r--src/core/network/sockets.h1
-rw-r--r--src/core/reporter.cpp1
-rw-r--r--src/input_common/drivers/gc_adapter.h1
-rw-r--r--src/input_common/helpers/udp_protocol.h1
-rw-r--r--src/input_common/input_engine.cpp1
-rw-r--r--src/input_common/main.cpp1
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp3
-rw-r--r--src/shader_recompiler/backend/glasm/glasm_emit_context.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/reg_alloc.cpp3
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp1
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_special.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_select.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h1
-rw-r--r--src/shader_recompiler/exception.h1
-rw-r--r--src/shader_recompiler/frontend/ir/basic_block.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/condition.h1
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp5
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.h1
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp1
-rw-r--r--src/shader_recompiler/frontend/ir/value.h4
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/decode.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/indirect_branch_table_track.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/instruction.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/location.h3
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/attribute_memory_to_physical.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp5
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set_predicate.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/move_register.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.h5
-rw-r--r--src/shader_recompiler/ir_opt/constant_propagation_pass.cpp1
-rw-r--r--src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp98
-rw-r--r--src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp3
-rw-r--r--src/shader_recompiler/ir_opt/lower_fp16_to_fp32.cpp3
-rw-r--r--src/shader_recompiler/ir_opt/passes.h3
-rw-r--r--src/shader_recompiler/ir_opt/rescaling_pass.cpp1
-rw-r--r--src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp1
-rw-r--r--src/shader_recompiler/program_header.h5
-rw-r--r--src/shader_recompiler/runtime_info.h1
-rw-r--r--src/video_core/buffer_cache/buffer_base.h3
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h36
-rw-r--r--src/video_core/cdma_pusher.cpp2
-rw-r--r--src/video_core/cdma_pusher.h1
-rw-r--r--src/video_core/command_classes/codecs/codec.cpp1
-rw-r--r--src/video_core/command_classes/codecs/codec.h2
-rw-r--r--src/video_core/command_classes/codecs/vp8.cpp1
-rw-r--r--src/video_core/command_classes/codecs/vp9_types.h1
-rw-r--r--src/video_core/command_classes/host1x.h2
-rw-r--r--src/video_core/dma_pusher.cpp1
-rw-r--r--src/video_core/engines/fermi_2d.h1
-rw-r--r--src/video_core/engines/kepler_compute.cpp1
-rw-r--r--src/video_core/engines/kepler_compute.h1
-rw-r--r--src/video_core/engines/kepler_memory.cpp2
-rw-r--r--src/video_core/engines/kepler_memory.h2
-rw-r--r--src/video_core/engines/maxwell_3d.h1
-rw-r--r--src/video_core/engines/maxwell_dma.h2
-rw-r--r--src/video_core/framebuffer_config.h29
-rw-r--r--src/video_core/gpu.h1
-rw-r--r--src/video_core/memory_manager.cpp1
-rw-r--r--src/video_core/query_cache.h1
-rw-r--r--src/video_core/renderer_base.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp14
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h14
-rw-r--r--src/video_core/renderer_opengl/gl_compute_pipeline.h1
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_device.h7
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.h1
-rw-r--r--src/video_core/renderer_opengl/gl_query_cache.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h10
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.h4
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.h1
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h13
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp11
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h6
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp7
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h2
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp3
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.h1
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp3
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h3
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_util.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h1
-rw-r--r--src/video_core/shader_environment.cpp1
-rw-r--r--src/video_core/shader_notify.cpp1
-rw-r--r--src/video_core/shader_notify.h1
-rw-r--r--src/video_core/surface.cpp8
-rw-r--r--src/video_core/surface.h2
-rw-r--r--src/video_core/texture_cache/descriptor_table.h1
-rw-r--r--src/video_core/texture_cache/image_base.h7
-rw-r--r--src/video_core/texture_cache/render_targets.h1
-rw-r--r--src/video_core/texture_cache/slot_vector.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h66
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h8
-rw-r--r--src/video_core/texture_cache/util.h2
-rw-r--r--src/video_core/textures/astc.cpp1
-rw-r--r--src/video_core/textures/astc.h3
-rw-r--r--src/video_core/textures/decoders.cpp2
-rw-r--r--src/video_core/textures/texture.cpp1
-rw-r--r--src/video_core/vulkan_common/nsight_aftermath_tracker.h14
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp57
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h12
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_library.cpp1
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.h1
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp15
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h5
-rw-r--r--src/web_service/web_backend.cpp1
-rw-r--r--src/yuzu/applets/qt_controller.cpp1
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp1
-rw-r--r--src/yuzu/applets/qt_profile_select.h2
-rw-r--r--src/yuzu/applets/qt_web_browser.cpp8
-rw-r--r--src/yuzu/applets/qt_web_browser.h1
-rw-r--r--src/yuzu/bootmanager.cpp3
-rw-r--r--src/yuzu/bootmanager.h1
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp1
-rw-r--r--src/yuzu/configuration/configuration_shared.h1
-rw-r--r--src/yuzu/configuration/configure_audio.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp4
-rw-r--r--src/yuzu/configuration/configure_cpu.h1
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.cpp4
-rw-r--r--src/yuzu/configuration/configure_debug.cpp8
-rw-r--r--src/yuzu/configuration/configure_debug.ui91
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp7
-rw-r--r--src/yuzu/configuration/configure_general.cpp3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp1
-rw-r--r--src/yuzu/configuration/configure_input.cpp4
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp2
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp5
-rw-r--r--src/yuzu/configuration/configure_motion_touch.h1
-rw-r--r--src/yuzu/configuration/configure_network.cpp1
-rw-r--r--src/yuzu/configuration/configure_network.h1
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp6
-rw-r--r--src/yuzu/configuration/configure_per_game.h1
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp1
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.cpp2
-rw-r--r--src/yuzu/configuration/configure_system.h1
-rw-r--r--src/yuzu/configuration/configure_tas.h2
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp1
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp6
-rw-r--r--src/yuzu/configuration/input_profiles.h1
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
-rw-r--r--src/yuzu/debugger/wait_tree.h1
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/game_list.h5
-rw-r--r--src/yuzu/game_list_p.h1
-rw-r--r--src/yuzu/game_list_worker.cpp1
-rw-r--r--src/yuzu/game_list_worker.h4
-rw-r--r--src/yuzu/hotkeys.cpp1
-rw-r--r--src/yuzu/install_dialog.cpp1
-rw-r--r--src/yuzu/loading_screen.cpp7
-rw-r--r--src/yuzu/main.cpp32
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/uisettings.h1
-rw-r--r--src/yuzu/util/overlay_dialog.h1
-rw-r--r--src/yuzu_cmd/config.cpp1
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h1
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp1
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp2
-rw-r--r--src/yuzu_cmd/yuzu.cpp5
378 files changed, 4752 insertions, 2524 deletions
diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h
index 2b1f515e8..b94d73c7a 100644
--- a/src/common/atomic_ops.h
+++ b/src/common/atomic_ops.h
@@ -4,13 +4,12 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstring>
8#include <memory>
9
10#include "common/common_types.h" 7#include "common/common_types.h"
11 8
12#if _MSC_VER 9#if _MSC_VER
13#include <intrin.h> 10#include <intrin.h>
11#else
12#include <cstring>
14#endif 13#endif
15 14
16namespace Common { 15namespace Common {
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 0f0661172..7f8620e7d 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -33,7 +33,6 @@
33#include <cstddef> 33#include <cstddef>
34#include <limits> 34#include <limits>
35#include <type_traits> 35#include <type_traits>
36#include "common/common_funcs.h"
37#include "common/swap.h" 36#include "common/swap.h"
38 37
39/* 38/*
diff --git a/src/common/dynamic_library.cpp b/src/common/dynamic_library.cpp
index 7f0a10521..11003e1d6 100644
--- a/src/common/dynamic_library.cpp
+++ b/src/common/dynamic_library.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include <string> 5#include <string>
7#include <utility> 6#include <utility>
8 7
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp
index 274f57659..5d71275ef 100644
--- a/src/common/fs/file.cpp
+++ b/src/common/fs/file.cpp
@@ -4,7 +4,6 @@
4 4
5#include "common/fs/file.h" 5#include "common/fs/file.h"
6#include "common/fs/fs.h" 6#include "common/fs/fs.h"
7#include "common/fs/path_util.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9 8
10#ifdef _WIN32 9#ifdef _WIN32
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index a4f7944cd..8a2cab0af 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -6,10 +6,8 @@
6 6
7#include <cstdio> 7#include <cstdio>
8#include <filesystem> 8#include <filesystem>
9#include <fstream>
10#include <span> 9#include <span>
11#include <type_traits> 10#include <type_traits>
12#include <vector>
13 11
14#include "common/concepts.h" 12#include "common/concepts.h"
15#include "common/fs/fs_types.h" 13#include "common/fs/fs_types.h"
diff --git a/src/common/fs/fs_types.h b/src/common/fs/fs_types.h
index 089980aee..f5853f624 100644
--- a/src/common/fs/fs_types.h
+++ b/src/common/fs/fs_types.h
@@ -7,7 +7,6 @@
7#include <functional> 7#include <functional>
8 8
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h"
11 10
12namespace Common::FS { 11namespace Common::FS {
13 12
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index 1620d38c9..392af89f7 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -8,7 +8,6 @@
8#include <filesystem> 8#include <filesystem>
9#include <span> 9#include <span>
10#include <string> 10#include <string>
11#include <string_view>
12 11
13#include "common/common_types.h" 12#include "common/common_types.h"
14 13
diff --git a/src/common/hex_util.h b/src/common/hex_util.h
index 5e9b6ef8b..323c8fb33 100644
--- a/src/common/hex_util.h
+++ b/src/common/hex_util.h
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <string> 9#include <string>
10#include <type_traits>
11#include <vector> 10#include <vector>
12#include <fmt/format.h> 11#include <fmt/format.h>
13#include "common/common_types.h" 12#include "common/common_types.h"
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index c465cfc14..e829af1ac 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -18,6 +18,7 @@
18#include <fcntl.h> 18#include <fcntl.h>
19#include <sys/mman.h> 19#include <sys/mman.h>
20#include <unistd.h> 20#include <unistd.h>
21#include "common/scope_exit.h"
21 22
22#endif // ^^^ Linux ^^^ 23#endif // ^^^ Linux ^^^
23 24
@@ -27,7 +28,6 @@
27#include "common/assert.h" 28#include "common/assert.h"
28#include "common/host_memory.h" 29#include "common/host_memory.h"
29#include "common/logging/log.h" 30#include "common/logging/log.h"
30#include "common/scope_exit.h"
31 31
32namespace Common { 32namespace Common {
33 33
diff --git a/src/common/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h
index b296b639e..eaf5675e3 100644
--- a/src/common/intrusive_red_black_tree.h
+++ b/src/common/intrusive_red_black_tree.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/alignment.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
9#include "common/parent_of_member.h" 8#include "common/parent_of_member.h"
10#include "common/tree.h" 9#include "common/tree.h"
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 4a2462ec4..b3793106d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -5,10 +5,8 @@
5#include <atomic> 5#include <atomic>
6#include <chrono> 6#include <chrono>
7#include <climits> 7#include <climits>
8#include <exception>
9#include <stop_token> 8#include <stop_token>
10#include <thread> 9#include <thread>
11#include <vector>
12 10
13#include <fmt/format.h> 11#include <fmt/format.h>
14 12
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index bf785f402..a0e80fe3c 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <filesystem>
8#include "common/logging/filter.h" 7#include "common/logging/filter.h"
9 8
10namespace Common::Log { 9namespace Common::Log {
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 4afc1369a..9120cc178 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -119,6 +119,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
119 SUB(Service, NPNS) \ 119 SUB(Service, NPNS) \
120 SUB(Service, NS) \ 120 SUB(Service, NS) \
121 SUB(Service, NVDRV) \ 121 SUB(Service, NVDRV) \
122 SUB(Service, NVFlinger) \
122 SUB(Service, OLSC) \ 123 SUB(Service, OLSC) \
123 SUB(Service, PCIE) \ 124 SUB(Service, PCIE) \
124 SUB(Service, PCTL) \ 125 SUB(Service, PCTL) \
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index 1a3074e04..29419f051 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8#include <chrono> 8#include <chrono>
9#include <cstddef> 9#include <cstddef>
10#include <string_view>
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12 11
13namespace Common::Log { 12namespace Common::Log {
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 10b2281db..b2cad58d8 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -10,12 +10,10 @@
10#endif 10#endif
11 11
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/common_funcs.h"
14#include "common/logging/filter.h" 13#include "common/logging/filter.h"
15#include "common/logging/log.h" 14#include "common/logging/log.h"
16#include "common/logging/log_entry.h" 15#include "common/logging/log_entry.h"
17#include "common/logging/text_formatter.h" 16#include "common/logging/text_formatter.h"
18#include "common/string_util.h"
19 17
20namespace Common::Log { 18namespace Common::Log {
21 19
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index 171e74cfe..92c0bf0c5 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstddef>
8#include <string> 7#include <string>
9 8
10namespace Common::Log { 9namespace Common::Log {
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 2b6e4daa7..f803ab796 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -87,6 +87,7 @@ enum class Class : u8 {
87 Service_NPNS, ///< The NPNS service 87 Service_NPNS, ///< The NPNS service
88 Service_NS, ///< The NS services 88 Service_NS, ///< The NS services
89 Service_NVDRV, ///< The NVDRV (Nvidia driver) service 89 Service_NVDRV, ///< The NVDRV (Nvidia driver) service
90 Service_NVFlinger, ///< The NVFlinger service
90 Service_OLSC, ///< The OLSC service 91 Service_OLSC, ///< The OLSC service
91 Service_PCIE, ///< The PCIe service 92 Service_PCIE, ///< The PCIe service
92 Service_PCTL, ///< The PCTL (Parental control) service 93 Service_PCTL, ///< The PCTL (Parental control) service
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 510c4e56d..54485bf53 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm>
7#include <cstdlib> 8#include <cstdlib>
8#include <type_traits> 9#include <type_traits>
9 10
@@ -20,10 +21,32 @@ struct Rectangle {
20 21
21 constexpr Rectangle() = default; 22 constexpr Rectangle() = default;
22 23
24 constexpr Rectangle(T width, T height) : right(width), bottom(height) {}
25
23 constexpr Rectangle(T left_, T top_, T right_, T bottom_) 26 constexpr Rectangle(T left_, T top_, T right_, T bottom_)
24 : left(left_), top(top_), right(right_), bottom(bottom_) {} 27 : left(left_), top(top_), right(right_), bottom(bottom_) {}
25 28
26 [[nodiscard]] T GetWidth() const { 29 [[nodiscard]] constexpr T Left() const {
30 return left;
31 }
32
33 [[nodiscard]] constexpr T Top() const {
34 return top;
35 }
36
37 [[nodiscard]] constexpr T Right() const {
38 return right;
39 }
40
41 [[nodiscard]] constexpr T Bottom() const {
42 return bottom;
43 }
44
45 [[nodiscard]] constexpr bool IsEmpty() const {
46 return (GetWidth() <= 0) || (GetHeight() <= 0);
47 }
48
49 [[nodiscard]] constexpr T GetWidth() const {
27 if constexpr (std::is_floating_point_v<T>) { 50 if constexpr (std::is_floating_point_v<T>) {
28 return std::abs(right - left); 51 return std::abs(right - left);
29 } else { 52 } else {
@@ -31,7 +54,7 @@ struct Rectangle {
31 } 54 }
32 } 55 }
33 56
34 [[nodiscard]] T GetHeight() const { 57 [[nodiscard]] constexpr T GetHeight() const {
35 if constexpr (std::is_floating_point_v<T>) { 58 if constexpr (std::is_floating_point_v<T>) {
36 return std::abs(bottom - top); 59 return std::abs(bottom - top);
37 } else { 60 } else {
@@ -39,18 +62,35 @@ struct Rectangle {
39 } 62 }
40 } 63 }
41 64
42 [[nodiscard]] Rectangle<T> TranslateX(const T x) const { 65 [[nodiscard]] constexpr Rectangle<T> TranslateX(const T x) const {
43 return Rectangle{left + x, top, right + x, bottom}; 66 return Rectangle{left + x, top, right + x, bottom};
44 } 67 }
45 68
46 [[nodiscard]] Rectangle<T> TranslateY(const T y) const { 69 [[nodiscard]] constexpr Rectangle<T> TranslateY(const T y) const {
47 return Rectangle{left, top + y, right, bottom + y}; 70 return Rectangle{left, top + y, right, bottom + y};
48 } 71 }
49 72
50 [[nodiscard]] Rectangle<T> Scale(const float s) const { 73 [[nodiscard]] constexpr Rectangle<T> Scale(const float s) const {
51 return Rectangle{left, top, static_cast<T>(static_cast<float>(left + GetWidth()) * s), 74 return Rectangle{left, top, static_cast<T>(static_cast<float>(left + GetWidth()) * s),
52 static_cast<T>(static_cast<float>(top + GetHeight()) * s)}; 75 static_cast<T>(static_cast<float>(top + GetHeight()) * s)};
53 } 76 }
77
78 [[nodiscard]] constexpr bool operator==(const Rectangle<T>& rhs) const {
79 return (left == rhs.left) && (top == rhs.top) && (right == rhs.right) &&
80 (bottom == rhs.bottom);
81 }
82
83 [[nodiscard]] constexpr bool operator!=(const Rectangle<T>& rhs) const {
84 return !operator==(rhs);
85 }
86
87 [[nodiscard]] constexpr bool Intersect(const Rectangle<T>& with, Rectangle<T>* result) const {
88 result->left = std::max(left, with.left);
89 result->top = std::max(top, with.top);
90 result->right = std::min(right, with.right);
91 result->bottom = std::min(bottom, with.bottom);
92 return !result->IsEmpty();
93 }
54}; 94};
55 95
56template <typename T> 96template <typename T>
diff --git a/src/common/memory_detect.cpp b/src/common/memory_detect.cpp
index 8cff6ec37..7a75a5ff4 100644
--- a/src/common/memory_detect.cpp
+++ b/src/common/memory_detect.cpp
@@ -70,4 +70,4 @@ const MemoryInfo& GetMemInfo() {
70 return mem_info; 70 return mem_info;
71} 71}
72 72
73} // namespace Common \ No newline at end of file 73} // namespace Common
diff --git a/src/common/nvidia_flags.cpp b/src/common/nvidia_flags.cpp
index d1afd1f1d..c732c233e 100644
--- a/src/common/nvidia_flags.cpp
+++ b/src/common/nvidia_flags.cpp
@@ -6,7 +6,6 @@
6 6
7#include <fmt/format.h> 7#include <fmt/format.h>
8 8
9#include "common/fs/file.h"
10#include "common/fs/fs.h" 9#include "common/fs/fs.h"
11#include "common/fs/path_util.h" 10#include "common/fs/path_util.h"
12#include "common/nvidia_flags.h" 11#include "common/nvidia_flags.h"
diff --git a/src/common/page_table.h b/src/common/page_table.h
index 82d91e9f3..13f4b44c0 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <atomic> 7#include <atomic>
8#include <tuple>
9 8
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/virtual_buffer.h" 10#include "common/virtual_buffer.h"
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h
index 58c70b0e7..ad075615b 100644
--- a/src/common/parent_of_member.h
+++ b/src/common/parent_of_member.h
@@ -7,7 +7,6 @@
7#include <type_traits> 7#include <type_traits>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/common_types.h"
11 10
12namespace Common { 11namespace Common {
13namespace detail { 12namespace detail {
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 4a8d09806..db6aa6b95 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -12,7 +12,6 @@
12#include <new> 12#include <new>
13#include <type_traits> 13#include <type_traits>
14#include <vector> 14#include <vector>
15#include "common/common_types.h"
16 15
17namespace Common { 16namespace Common {
18 17
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 662171138..3695dae4d 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -5,11 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <cctype> 6#include <cctype>
7#include <codecvt> 7#include <codecvt>
8#include <cstdlib>
9#include <locale> 8#include <locale>
10#include <sstream> 9#include <sstream>
11 10
12#include "common/logging/log.h"
13#include "common/string_util.h" 11#include "common/string_util.h"
14 12
15#ifdef _WIN32 13#ifdef _WIN32
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp
index 98c82cd17..67261c55b 100644
--- a/src/common/telemetry.cpp
+++ b/src/common/telemetry.cpp
@@ -4,7 +4,6 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include "common/assert.h"
8#include "common/scm_rev.h" 7#include "common/scm_rev.h"
9#include "common/telemetry.h" 8#include "common/telemetry.h"
10 9
diff --git a/src/common/telemetry.h b/src/common/telemetry.h
index 3524c857e..f9a824a7d 100644
--- a/src/common/telemetry.h
+++ b/src/common/telemetry.h
@@ -8,7 +8,6 @@
8#include <map> 8#include <map>
9#include <memory> 9#include <memory>
10#include <string> 10#include <string>
11#include <string_view>
12#include "common/common_funcs.h" 11#include "common/common_funcs.h"
13#include "common/common_types.h" 12#include "common/common_types.h"
14 13
diff --git a/src/common/uint128.h b/src/common/uint128.h
index 4780b2f9d..ad1b90414 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstring>
8#include <utility> 7#include <utility>
9 8
10#ifdef _MSC_VER 9#ifdef _MSC_VER
@@ -13,6 +12,7 @@
13#pragma intrinsic(_umul128) 12#pragma intrinsic(_umul128)
14#pragma intrinsic(_udiv128) 13#pragma intrinsic(_udiv128)
15#else 14#else
15#include <cstring>
16#include <x86intrin.h> 16#include <x86intrin.h>
17#endif 17#endif
18 18
diff --git a/src/common/uuid.h b/src/common/uuid.h
index fe31e64e6..c450d9e20 100644
--- a/src/common/uuid.h
+++ b/src/common/uuid.h
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8#include <functional> 8#include <functional>
9#include <string> 9#include <string>
10#include <string_view>
11 10
12#include "common/common_types.h" 11#include "common/common_types.h"
13 12
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h
index fb1a6f81f..cac4f4895 100644
--- a/src/common/virtual_buffer.h
+++ b/src/common/virtual_buffer.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <type_traits>
8#include <utility> 7#include <utility>
9 8
10namespace Common { 9namespace Common {
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 9acf7551e..f30d91692 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstdint>
6
7#include "common/uint128.h" 5#include "common/uint128.h"
8#include "common/wall_clock.h" 6#include "common/wall_clock.h"
9 7
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index d81edb140..f5296b32a 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -4,7 +4,6 @@
4#include <array> 4#include <array>
5#include <cstring> 5#include <cstring>
6#include <iterator> 6#include <iterator>
7#include <span>
8#include <string_view> 7#include <string_view>
9#include "common/bit_util.h" 8#include "common/bit_util.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 91b842829..347e41efc 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -4,8 +4,6 @@
4 4
5#include <array> 5#include <array>
6#include <chrono> 6#include <chrono>
7#include <limits>
8#include <mutex>
9#include <thread> 7#include <thread>
10 8
11#include "common/atomic_ops.h" 9#include "common/atomic_ops.h"
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 7cbd400d2..2c3082ea0 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <optional>
8
9#include "common/wall_clock.h" 7#include "common/wall_clock.h"
10 8
11namespace Common { 9namespace Common {
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1d4e92edb..6536d0544 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -122,8 +122,8 @@ add_library(core STATIC
122 frontend/applets/error.h 122 frontend/applets/error.h
123 frontend/applets/general_frontend.cpp 123 frontend/applets/general_frontend.cpp
124 frontend/applets/general_frontend.h 124 frontend/applets/general_frontend.h
125 frontend/applets/mii.cpp 125 frontend/applets/mii_edit.cpp
126 frontend/applets/mii.h 126 frontend/applets/mii_edit.h
127 frontend/applets/profile_select.cpp 127 frontend/applets/profile_select.cpp
128 frontend/applets/profile_select.h 128 frontend/applets/profile_select.h
129 frontend/applets/software_keyboard.cpp 129 frontend/applets/software_keyboard.cpp
@@ -306,8 +306,9 @@ add_library(core STATIC
306 hle/service/am/applets/applet_error.h 306 hle/service/am/applets/applet_error.h
307 hle/service/am/applets/applet_general_backend.cpp 307 hle/service/am/applets/applet_general_backend.cpp
308 hle/service/am/applets/applet_general_backend.h 308 hle/service/am/applets/applet_general_backend.h
309 hle/service/am/applets/applet_mii.cpp 309 hle/service/am/applets/applet_mii_edit.cpp
310 hle/service/am/applets/applet_mii.h 310 hle/service/am/applets/applet_mii_edit.h
311 hle/service/am/applets/applet_mii_edit_types.h
311 hle/service/am/applets/applet_profile_select.cpp 312 hle/service/am/applets/applet_profile_select.cpp
312 hle/service/am/applets/applet_profile_select.h 313 hle/service/am/applets/applet_profile_select.h
313 hle/service/am/applets/applet_software_keyboard.cpp 314 hle/service/am/applets/applet_software_keyboard.cpp
@@ -534,10 +535,35 @@ add_library(core STATIC
534 hle/service/nvdrv/nvmemp.h 535 hle/service/nvdrv/nvmemp.h
535 hle/service/nvdrv/syncpoint_manager.cpp 536 hle/service/nvdrv/syncpoint_manager.cpp
536 hle/service/nvdrv/syncpoint_manager.h 537 hle/service/nvdrv/syncpoint_manager.h
537 hle/service/nvflinger/buffer_queue.cpp 538 hle/service/nvflinger/binder.h
538 hle/service/nvflinger/buffer_queue.h 539 hle/service/nvflinger/buffer_item.h
540 hle/service/nvflinger/buffer_item_consumer.cpp
541 hle/service/nvflinger/buffer_item_consumer.h
542 hle/service/nvflinger/buffer_queue_consumer.cpp
543 hle/service/nvflinger/buffer_queue_consumer.h
544 hle/service/nvflinger/buffer_queue_core.cpp
545 hle/service/nvflinger/buffer_queue_core.h
546 hle/service/nvflinger/buffer_queue_defs.h
547 hle/service/nvflinger/buffer_queue_producer.cpp
548 hle/service/nvflinger/buffer_queue_producer.h
549 hle/service/nvflinger/buffer_slot.h
550 hle/service/nvflinger/buffer_transform_flags.h
551 hle/service/nvflinger/consumer_base.cpp
552 hle/service/nvflinger/consumer_base.h
553 hle/service/nvflinger/consumer_listener.h
554 hle/service/nvflinger/graphic_buffer_producer.cpp
555 hle/service/nvflinger/graphic_buffer_producer.h
556 hle/service/nvflinger/hos_binder_driver_server.cpp
557 hle/service/nvflinger/hos_binder_driver_server.h
539 hle/service/nvflinger/nvflinger.cpp 558 hle/service/nvflinger/nvflinger.cpp
540 hle/service/nvflinger/nvflinger.h 559 hle/service/nvflinger/nvflinger.h
560 hle/service/nvflinger/parcel.h
561 hle/service/nvflinger/pixel_format.h
562 hle/service/nvflinger/producer_listener.h
563 hle/service/nvflinger/status.h
564 hle/service/nvflinger/ui/fence.h
565 hle/service/nvflinger/ui/graphic_buffer.h
566 hle/service/nvflinger/window.h
541 hle/service/olsc/olsc.cpp 567 hle/service/olsc/olsc.cpp
542 hle/service/olsc/olsc.h 568 hle/service/olsc/olsc.h
543 hle/service/pcie/pcie.cpp 569 hle/service/pcie/pcie.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index c1c843b8f..286976623 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -148,8 +148,8 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
148 config.wall_clock_cntpct = uses_wall_clock; 148 config.wall_clock_cntpct = uses_wall_clock;
149 149
150 // Code cache size 150 // Code cache size
151 config.code_cache_size = 128_MiB; 151 config.code_cache_size = 512_MiB;
152 config.far_code_offset = 100_MiB; 152 config.far_code_offset = 400_MiB;
153 153
154 // Safe optimizations 154 // Safe optimizations
155 if (Settings::values.cpu_debug_mode) { 155 if (Settings::values.cpu_debug_mode) {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index aa74fce4d..24107f9f6 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -93,17 +93,19 @@ public:
93 static constexpr u64 ICACHE_LINE_SIZE = 64; 93 static constexpr u64 ICACHE_LINE_SIZE = 64;
94 94
95 const u64 cache_line_start = value & ~(ICACHE_LINE_SIZE - 1); 95 const u64 cache_line_start = value & ~(ICACHE_LINE_SIZE - 1);
96 parent.InvalidateCacheRange(cache_line_start, ICACHE_LINE_SIZE); 96 parent.system.InvalidateCpuInstructionCacheRange(cache_line_start, ICACHE_LINE_SIZE);
97 break; 97 break;
98 } 98 }
99 case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU: 99 case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoU:
100 parent.ClearInstructionCache(); 100 parent.system.InvalidateCpuInstructionCaches();
101 break; 101 break;
102 case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable: 102 case Dynarmic::A64::InstructionCacheOperation::InvalidateAllToPoUInnerSharable:
103 default: 103 default:
104 LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation: {}", op); 104 LOG_DEBUG(Core_ARM, "Unprocesseed instruction cache operation: {}", op);
105 break; 105 break;
106 } 106 }
107
108 parent.jit->HaltExecution();
107 } 109 }
108 110
109 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { 111 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -208,8 +210,8 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
208 config.wall_clock_cntpct = uses_wall_clock; 210 config.wall_clock_cntpct = uses_wall_clock;
209 211
210 // Code cache size 212 // Code cache size
211 config.code_cache_size = 128_MiB; 213 config.code_cache_size = 512_MiB;
212 config.far_code_offset = 100_MiB; 214 config.far_code_offset = 400_MiB;
213 215
214 // Safe optimizations 216 // Safe optimizations
215 if (Settings::values.cpu_debug_mode) { 217 if (Settings::values.cpu_debug_mode) {
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h
index 5a15b43ef..b82c77f76 100644
--- a/src/core/arm/dynarmic/arm_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <unordered_map>
8
9#include <dynarmic/interface/exclusive_monitor.h> 7#include <dynarmic/interface/exclusive_monitor.h>
10 8
11#include "common/common_types.h" 9#include "common/common_types.h"
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c60a784c3..b5e2bcae2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -38,7 +38,6 @@
38#include "core/hle/service/apm/apm_controller.h" 38#include "core/hle/service/apm/apm_controller.h"
39#include "core/hle/service/filesystem/filesystem.h" 39#include "core/hle/service/filesystem/filesystem.h"
40#include "core/hle/service/glue/glue_manager.h" 40#include "core/hle/service/glue/glue_manager.h"
41#include "core/hle/service/hid/hid.h"
42#include "core/hle/service/service.h" 41#include "core/hle/service/service.h"
43#include "core/hle/service/sm/sm.h" 42#include "core/hle/service/sm/sm.h"
44#include "core/hle/service/time/time_manager.h" 43#include "core/hle/service/time/time_manager.h"
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h
index 21c7aefc8..9a3b62117 100644
--- a/src/core/file_sys/directory.h
+++ b/src/core/file_sys/directory.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8#include <iterator>
9#include "common/common_funcs.h" 8#include "common/common_funcs.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index f19ac4607..c4e185757 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -10,7 +10,10 @@
10#include "common/hex_util.h" 10#include "common/hex_util.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h" 12#include "common/settings.h"
13#ifndef _WIN32
13#include "common/string_util.h" 14#include "common/string_util.h"
15#endif
16
14#include "core/core.h" 17#include "core/core.h"
15#include "core/file_sys/common_funcs.h" 18#include "core/file_sys/common_funcs.h"
16#include "core/file_sys/content_archive.h" 19#include "core/file_sys/content_archive.h"
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 1eee916be..32435e123 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -6,7 +6,9 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9
9#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_funcs.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "common/swap.h" 13#include "common/swap.h"
12#include "core/file_sys/vfs_types.h" 14#include "core/file_sys/vfs_types.h"
diff --git a/src/core/frontend/applets/mii.cpp b/src/core/frontend/applets/mii.cpp
deleted file mode 100644
index 1c05ff412..000000000
--- a/src/core/frontend/applets/mii.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/frontend/applets/mii.h"
7
8namespace Core::Frontend {
9
10MiiApplet::~MiiApplet() = default;
11
12void DefaultMiiApplet::ShowMii(
13 const MiiParameters& parameters,
14 const std::function<void(const Core::Frontend::MiiParameters& parameters)> callback) const {
15 LOG_INFO(Service_HID, "(STUBBED) called");
16 callback(parameters);
17}
18
19} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/mii.h b/src/core/frontend/applets/mii.h
deleted file mode 100644
index 1fc40a9c6..000000000
--- a/src/core/frontend/applets/mii.h
+++ /dev/null
@@ -1,35 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <functional>
8
9#include "core/hle/result.h"
10#include "core/hle/service/mii/mii_manager.h"
11
12namespace Core::Frontend {
13
14struct MiiParameters {
15 bool is_editable;
16 Service::Mii::MiiInfo mii_data{};
17};
18
19class MiiApplet {
20public:
21 virtual ~MiiApplet();
22
23 virtual void ShowMii(const MiiParameters& parameters,
24 const std::function<void(const Core::Frontend::MiiParameters& parameters)>
25 callback) const = 0;
26};
27
28class DefaultMiiApplet final : public MiiApplet {
29public:
30 void ShowMii(const MiiParameters& parameters,
31 const std::function<void(const Core::Frontend::MiiParameters& parameters)>
32 callback) const override;
33};
34
35} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/mii_edit.cpp b/src/core/frontend/applets/mii_edit.cpp
new file mode 100644
index 000000000..fadb5fb15
--- /dev/null
+++ b/src/core/frontend/applets/mii_edit.cpp
@@ -0,0 +1,18 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/frontend/applets/mii_edit.h"
7
8namespace Core::Frontend {
9
10MiiEditApplet::~MiiEditApplet() = default;
11
12void DefaultMiiEditApplet::ShowMiiEdit(const std::function<void()>& callback) const {
13 LOG_WARNING(Service_AM, "(STUBBED) called");
14
15 callback();
16}
17
18} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/mii_edit.h b/src/core/frontend/applets/mii_edit.h
new file mode 100644
index 000000000..cca0e931d
--- /dev/null
+++ b/src/core/frontend/applets/mii_edit.h
@@ -0,0 +1,23 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <functional>
8
9namespace Core::Frontend {
10
11class MiiEditApplet {
12public:
13 virtual ~MiiEditApplet();
14
15 virtual void ShowMiiEdit(const std::function<void()>& callback) const = 0;
16};
17
18class DefaultMiiEditApplet final : public MiiEditApplet {
19public:
20 void ShowMiiEdit(const std::function<void()>& callback) const override;
21};
22
23} // namespace Core::Frontend
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 9f2175f82..42d1b0e31 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -17,7 +17,6 @@
17#include "core/hle/kernel/k_auto_object.h" 17#include "core/hle/kernel/k_auto_object.h"
18#include "core/hle/kernel/k_handle_table.h" 18#include "core/hle/kernel/k_handle_table.h"
19#include "core/hle/kernel/k_process.h" 19#include "core/hle/kernel/k_process.h"
20#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_server_session.h" 20#include "core/hle/kernel/k_server_session.h"
22#include "core/hle/kernel/k_thread.h" 21#include "core/hle/kernel/k_thread.h"
23#include "core/hle/kernel/kernel.h" 22#include "core/hle/kernel/kernel.h"
diff --git a/src/core/hle/kernel/k_class_token.h b/src/core/hle/kernel/k_class_token.h
index 980010150..93fc8786d 100644
--- a/src/core/hle/kernel/k_class_token.h
+++ b/src/core/hle/kernel/k_class_token.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
8
9#include "common/bit_util.h" 7#include "common/bit_util.h"
10#include "common/common_types.h" 8#include "common/common_types.h"
11 9
diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp
index 0b225e8e0..63bbe02e9 100644
--- a/src/core/hle/kernel/k_code_memory.cpp
+++ b/src/core/hle/kernel/k_code_memory.cpp
@@ -5,7 +5,6 @@
5#include "common/alignment.h" 5#include "common/alignment.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/device_memory.h" 7#include "core/device_memory.h"
8#include "core/hle/kernel/k_auto_object.h"
9#include "core/hle/kernel/k_code_memory.h" 8#include "core/hle/kernel/k_code_memory.h"
10#include "core/hle/kernel/k_light_lock.h" 9#include "core/hle/kernel/k_light_lock.h"
11#include "core/hle/kernel/k_memory_block.h" 10#include "core/hle/kernel/k_memory_block.h"
@@ -29,7 +28,8 @@ ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr
29 auto& page_table = m_owner->PageTable(); 28 auto& page_table = m_owner->PageTable();
30 29
31 // Construct the page group. 30 // Construct the page group.
32 m_page_group = KPageLinkedList(addr, Common::DivideUp(size, PageSize)); 31 m_page_group =
32 KPageLinkedList(page_table.GetPhysicalAddr(addr), Common::DivideUp(size, PageSize));
33 33
34 // Lock the memory. 34 // Lock the memory.
35 R_TRY(page_table.LockForCodeMemory(addr, size)) 35 R_TRY(page_table.LockForCodeMemory(addr, size))
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index 8e2a9593c..aa29922d0 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -9,7 +9,6 @@
9#include "core/hle/kernel/k_process.h" 9#include "core/hle/kernel/k_process.h"
10#include "core/hle/kernel/k_scheduler.h" 10#include "core/hle/kernel/k_scheduler.h"
11#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 11#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
12#include "core/hle/kernel/k_synchronization_object.h"
13#include "core/hle/kernel/k_thread.h" 12#include "core/hle/kernel/k_thread.h"
14#include "core/hle/kernel/k_thread_queue.h" 13#include "core/hle/kernel/k_thread_queue.h"
15#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index a2f18f643..17a1b76c7 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -15,7 +15,6 @@
15#include "core/hle/kernel/k_page_linked_list.h" 15#include "core/hle/kernel/k_page_linked_list.h"
16#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/svc_results.h" 17#include "core/hle/kernel/svc_results.h"
18#include "core/memory.h"
19 18
20namespace Kernel { 19namespace Kernel {
21 20
diff --git a/src/core/hle/kernel/k_page_buffer.h b/src/core/hle/kernel/k_page_buffer.h
index 6ff3c1568..1d11a4e27 100644
--- a/src/core/hle/kernel/k_page_buffer.h
+++ b/src/core/hle/kernel/k_page_buffer.h
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/device_memory.h"
11#include "core/hle/kernel/memory_types.h" 10#include "core/hle/kernel/memory_types.h"
12#include "core/hle/kernel/slab_helpers.h" 11#include "core/hle/kernel/slab_helpers.h"
13 12
diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h
index 0e2ae582a..869228322 100644
--- a/src/core/hle/kernel/k_page_linked_list.h
+++ b/src/core/hle/kernel/k_page_linked_list.h
@@ -89,6 +89,10 @@ public:
89 return ResultSuccess; 89 return ResultSuccess;
90 } 90 }
91 91
92 bool Empty() const {
93 return nodes.empty();
94 }
95
92private: 96private:
93 std::list<Node> nodes; 97 std::list<Node> nodes;
94}; 98};
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 02d93b12e..599013cf6 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -486,6 +486,58 @@ VAddr KPageTable::FindFreeArea(VAddr region_start, std::size_t region_num_pages,
486 return address; 486 return address;
487} 487}
488 488
489ResultCode KPageTable::MakePageGroup(KPageLinkedList& pg, VAddr addr, size_t num_pages) {
490 ASSERT(this->IsLockedByCurrentThread());
491
492 const size_t size = num_pages * PageSize;
493
494 // We're making a new group, not adding to an existing one.
495 R_UNLESS(pg.Empty(), ResultInvalidCurrentMemory);
496
497 // Begin traversal.
498 Common::PageTable::TraversalContext context;
499 Common::PageTable::TraversalEntry next_entry;
500 R_UNLESS(page_table_impl.BeginTraversal(next_entry, context, addr), ResultInvalidCurrentMemory);
501
502 // Prepare tracking variables.
503 PAddr cur_addr = next_entry.phys_addr;
504 size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1));
505 size_t tot_size = cur_size;
506
507 // Iterate, adding to group as we go.
508 const auto& memory_layout = system.Kernel().MemoryLayout();
509 while (tot_size < size) {
510 R_UNLESS(page_table_impl.ContinueTraversal(next_entry, context),
511 ResultInvalidCurrentMemory);
512
513 if (next_entry.phys_addr != (cur_addr + cur_size)) {
514 const size_t cur_pages = cur_size / PageSize;
515
516 R_UNLESS(IsHeapPhysicalAddress(memory_layout, cur_addr), ResultInvalidCurrentMemory);
517 R_TRY(pg.AddBlock(cur_addr, cur_pages));
518
519 cur_addr = next_entry.phys_addr;
520 cur_size = next_entry.block_size;
521 } else {
522 cur_size += next_entry.block_size;
523 }
524
525 tot_size += next_entry.block_size;
526 }
527
528 // Ensure we add the right amount for the last block.
529 if (tot_size > size) {
530 cur_size -= (tot_size - size);
531 }
532
533 // Add the last block.
534 const size_t cur_pages = cur_size / PageSize;
535 R_UNLESS(IsHeapPhysicalAddress(memory_layout, cur_addr), ResultInvalidCurrentMemory);
536 R_TRY(pg.AddBlock(cur_addr, cur_pages));
537
538 return ResultSuccess;
539}
540
489ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, 541ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
490 KPageTable& src_page_table, VAddr src_addr) { 542 KPageTable& src_page_table, VAddr src_addr) {
491 KScopedLightLock lk(general_lock); 543 KScopedLightLock lk(general_lock);
@@ -1223,6 +1275,31 @@ ResultCode KPageTable::UnmapPages(VAddr address, std::size_t num_pages, KMemoryS
1223 return ResultSuccess; 1275 return ResultSuccess;
1224} 1276}
1225 1277
1278ResultCode KPageTable::MakeAndOpenPageGroup(KPageLinkedList* out, VAddr address, size_t num_pages,
1279 KMemoryState state_mask, KMemoryState state,
1280 KMemoryPermission perm_mask, KMemoryPermission perm,
1281 KMemoryAttribute attr_mask, KMemoryAttribute attr) {
1282 // Ensure that the page group isn't null.
1283 ASSERT(out != nullptr);
1284
1285 // Make sure that the region we're mapping is valid for the table.
1286 const size_t size = num_pages * PageSize;
1287 R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
1288
1289 // Lock the table.
1290 KScopedLightLock lk(general_lock);
1291
1292 // Check if state allows us to create the group.
1293 R_TRY(this->CheckMemoryState(address, size, state_mask | KMemoryState::FlagReferenceCounted,
1294 state | KMemoryState::FlagReferenceCounted, perm_mask, perm,
1295 attr_mask, attr));
1296
1297 // Create a new page group for the region.
1298 R_TRY(this->MakePageGroup(*out, address, num_pages));
1299
1300 return ResultSuccess;
1301}
1302
1226ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size, 1303ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
1227 Svc::MemoryPermission svc_perm) { 1304 Svc::MemoryPermission svc_perm) {
1228 const size_t num_pages = size / PageSize; 1305 const size_t num_pages = size / PageSize;
@@ -1605,57 +1682,21 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
1605} 1682}
1606 1683
1607ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { 1684ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
1608 KScopedLightLock lk(general_lock); 1685 return this->LockMemoryAndOpen(
1609 1686 nullptr, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
1610 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite; 1687 KMemoryState::FlagCanCodeMemory, KMemoryPermission::All, KMemoryPermission::UserReadWrite,
1611 1688 KMemoryAttribute::All, KMemoryAttribute::None,
1612 KMemoryPermission old_perm{}; 1689 static_cast<KMemoryPermission>(KMemoryPermission::NotMapped |
1613 1690 KMemoryPermission::KernelReadWrite),
1614 if (const ResultCode result{CheckMemoryState( 1691 KMemoryAttribute::Locked);
1615 nullptr, &old_perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
1616 KMemoryState::FlagCanCodeMemory, KMemoryPermission::All,
1617 KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
1618 result.IsError()) {
1619 return result;
1620 }
1621
1622 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
1623
1624 block_manager->UpdateLock(
1625 addr, size / PageSize,
1626 [](KMemoryBlockManager::iterator block, KMemoryPermission permission) {
1627 block->ShareToDevice(permission);
1628 },
1629 new_perm);
1630
1631 return ResultSuccess;
1632} 1692}
1633 1693
1634ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { 1694ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) {
1635 KScopedLightLock lk(general_lock); 1695 return this->UnlockMemory(addr, size, KMemoryState::FlagCanCodeMemory,
1636 1696 KMemoryState::FlagCanCodeMemory, KMemoryPermission::None,
1637 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite; 1697 KMemoryPermission::None, KMemoryAttribute::All,
1638 1698 KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite,
1639 KMemoryPermission old_perm{}; 1699 KMemoryAttribute::Locked, nullptr);
1640
1641 if (const ResultCode result{CheckMemoryState(
1642 nullptr, &old_perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
1643 KMemoryState::FlagCanCodeMemory, KMemoryPermission::None, KMemoryPermission::None,
1644 KMemoryAttribute::All, KMemoryAttribute::Locked)};
1645 result.IsError()) {
1646 return result;
1647 }
1648
1649 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
1650
1651 block_manager->UpdateLock(
1652 addr, size / PageSize,
1653 [](KMemoryBlockManager::iterator block, KMemoryPermission permission) {
1654 block->UnshareToDevice(permission);
1655 },
1656 new_perm);
1657
1658 return ResultSuccess;
1659} 1700}
1660 1701
1661ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { 1702ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
@@ -1991,4 +2032,109 @@ ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermissi
1991 return ResultSuccess; 2032 return ResultSuccess;
1992} 2033}
1993 2034
2035ResultCode KPageTable::LockMemoryAndOpen(KPageLinkedList* out_pg, PAddr* out_paddr, VAddr addr,
2036 size_t size, KMemoryState state_mask, KMemoryState state,
2037 KMemoryPermission perm_mask, KMemoryPermission perm,
2038 KMemoryAttribute attr_mask, KMemoryAttribute attr,
2039 KMemoryPermission new_perm, KMemoryAttribute lock_attr) {
2040 // Validate basic preconditions.
2041 ASSERT((lock_attr & attr) == KMemoryAttribute::None);
2042 ASSERT((lock_attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) ==
2043 KMemoryAttribute::None);
2044
2045 // Validate the lock request.
2046 const size_t num_pages = size / PageSize;
2047 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory);
2048
2049 // Lock the table.
2050 KScopedLightLock lk(general_lock);
2051
2052 // Check that the output page group is empty, if it exists.
2053 if (out_pg) {
2054 ASSERT(out_pg->GetNumPages() == 0);
2055 }
2056
2057 // Check the state.
2058 KMemoryState old_state{};
2059 KMemoryPermission old_perm{};
2060 KMemoryAttribute old_attr{};
2061 size_t num_allocator_blocks{};
2062 R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm),
2063 std::addressof(old_attr), std::addressof(num_allocator_blocks),
2064 addr, size, state_mask | KMemoryState::FlagReferenceCounted,
2065 state | KMemoryState::FlagReferenceCounted, perm_mask, perm,
2066 attr_mask, attr));
2067
2068 // Get the physical address, if we're supposed to.
2069 if (out_paddr != nullptr) {
2070 ASSERT(this->GetPhysicalAddressLocked(out_paddr, addr));
2071 }
2072
2073 // Make the page group, if we're supposed to.
2074 if (out_pg != nullptr) {
2075 R_TRY(this->MakePageGroup(*out_pg, addr, num_pages));
2076 }
2077
2078 // Decide on new perm and attr.
2079 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
2080 KMemoryAttribute new_attr = static_cast<KMemoryAttribute>(old_attr | lock_attr);
2081
2082 // Update permission, if we need to.
2083 if (new_perm != old_perm) {
2084 R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
2085 }
2086
2087 // Apply the memory block updates.
2088 block_manager->Update(addr, num_pages, old_state, new_perm, new_attr);
2089
2090 return ResultSuccess;
2091}
2092
2093ResultCode KPageTable::UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask,
2094 KMemoryState state, KMemoryPermission perm_mask,
2095 KMemoryPermission perm, KMemoryAttribute attr_mask,
2096 KMemoryAttribute attr, KMemoryPermission new_perm,
2097 KMemoryAttribute lock_attr, const KPageLinkedList* pg) {
2098 // Validate basic preconditions.
2099 ASSERT((attr_mask & lock_attr) == lock_attr);
2100 ASSERT((attr & lock_attr) == lock_attr);
2101
2102 // Validate the unlock request.
2103 const size_t num_pages = size / PageSize;
2104 R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory);
2105
2106 // Lock the table.
2107 KScopedLightLock lk(general_lock);
2108
2109 // Check the state.
2110 KMemoryState old_state{};
2111 KMemoryPermission old_perm{};
2112 KMemoryAttribute old_attr{};
2113 size_t num_allocator_blocks{};
2114 R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm),
2115 std::addressof(old_attr), std::addressof(num_allocator_blocks),
2116 addr, size, state_mask | KMemoryState::FlagReferenceCounted,
2117 state | KMemoryState::FlagReferenceCounted, perm_mask, perm,
2118 attr_mask, attr));
2119
2120 // Check the page group.
2121 if (pg != nullptr) {
2122 UNIMPLEMENTED_MSG("PageGroup support is unimplemented!");
2123 }
2124
2125 // Decide on new perm and attr.
2126 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
2127 KMemoryAttribute new_attr = static_cast<KMemoryAttribute>(old_attr & ~lock_attr);
2128
2129 // Update permission, if we need to.
2130 if (new_perm != old_perm) {
2131 R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
2132 }
2133
2134 // Apply the memory block updates.
2135 block_manager->Update(addr, num_pages, old_state, new_perm, new_attr);
2136
2137 return ResultSuccess;
2138}
2139
1994} // namespace Kernel 2140} // namespace Kernel
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 54c6adf8d..bfabdf38c 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -12,6 +12,7 @@
12#include "core/file_sys/program_metadata.h" 12#include "core/file_sys/program_metadata.h"
13#include "core/hle/kernel/k_light_lock.h" 13#include "core/hle/kernel/k_light_lock.h"
14#include "core/hle/kernel/k_memory_block.h" 14#include "core/hle/kernel/k_memory_block.h"
15#include "core/hle/kernel/k_memory_layout.h"
15#include "core/hle/kernel/k_memory_manager.h" 16#include "core/hle/kernel/k_memory_manager.h"
16#include "core/hle/result.h" 17#include "core/hle/result.h"
17 18
@@ -71,6 +72,10 @@ public:
71 ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); 72 ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
72 ResultCode LockForCodeMemory(VAddr addr, std::size_t size); 73 ResultCode LockForCodeMemory(VAddr addr, std::size_t size);
73 ResultCode UnlockForCodeMemory(VAddr addr, std::size_t size); 74 ResultCode UnlockForCodeMemory(VAddr addr, std::size_t size);
75 ResultCode MakeAndOpenPageGroup(KPageLinkedList* out, VAddr address, size_t num_pages,
76 KMemoryState state_mask, KMemoryState state,
77 KMemoryPermission perm_mask, KMemoryPermission perm,
78 KMemoryAttribute attr_mask, KMemoryAttribute attr);
74 79
75 Common::PageTable& PageTableImpl() { 80 Common::PageTable& PageTableImpl() {
76 return page_table_impl; 81 return page_table_impl;
@@ -159,10 +164,37 @@ private:
159 attr_mask, attr, ignore_attr); 164 attr_mask, attr, ignore_attr);
160 } 165 }
161 166
167 ResultCode LockMemoryAndOpen(KPageLinkedList* out_pg, PAddr* out_paddr, VAddr addr, size_t size,
168 KMemoryState state_mask, KMemoryState state,
169 KMemoryPermission perm_mask, KMemoryPermission perm,
170 KMemoryAttribute attr_mask, KMemoryAttribute attr,
171 KMemoryPermission new_perm, KMemoryAttribute lock_attr);
172 ResultCode UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, KMemoryState state,
173 KMemoryPermission perm_mask, KMemoryPermission perm,
174 KMemoryAttribute attr_mask, KMemoryAttribute attr,
175 KMemoryPermission new_perm, KMemoryAttribute lock_attr,
176 const KPageLinkedList* pg);
177
178 ResultCode MakePageGroup(KPageLinkedList& pg, VAddr addr, size_t num_pages);
179
162 bool IsLockedByCurrentThread() const { 180 bool IsLockedByCurrentThread() const {
163 return general_lock.IsLockedByCurrentThread(); 181 return general_lock.IsLockedByCurrentThread();
164 } 182 }
165 183
184 bool IsHeapPhysicalAddress(const KMemoryLayout& layout, PAddr phys_addr) {
185 ASSERT(this->IsLockedByCurrentThread());
186
187 return layout.IsHeapPhysicalAddress(cached_physical_heap_region, phys_addr);
188 }
189
190 bool GetPhysicalAddressLocked(PAddr* out, VAddr virt_addr) const {
191 ASSERT(this->IsLockedByCurrentThread());
192
193 *out = GetPhysicalAddr(virt_addr);
194
195 return *out != 0;
196 }
197
166 mutable KLightLock general_lock; 198 mutable KLightLock general_lock;
167 mutable KLightLock map_physical_memory_lock; 199 mutable KLightLock map_physical_memory_lock;
168 200
@@ -322,6 +354,7 @@ private:
322 bool is_aslr_enabled{}; 354 bool is_aslr_enabled{};
323 355
324 u32 heap_fill_value{}; 356 u32 heap_fill_value{};
357 const KMemoryRegion* cached_physical_heap_region{};
325 358
326 KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application}; 359 KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application};
327 KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront}; 360 KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront};
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index b39405496..490e31fc7 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -13,7 +13,6 @@
13#include "common/scope_exit.h" 13#include "common/scope_exit.h"
14#include "common/settings.h" 14#include "common/settings.h"
15#include "core/core.h" 15#include "core/core.h"
16#include "core/device_memory.h"
17#include "core/file_sys/program_metadata.h" 16#include "core/file_sys/program_metadata.h"
18#include "core/hle/kernel/code_set.h" 17#include "core/hle/kernel/code_set.h"
19#include "core/hle/kernel/k_memory_block_manager.h" 18#include "core/hle/kernel/k_memory_block_manager.h"
@@ -24,7 +23,6 @@
24#include "core/hle/kernel/k_scoped_resource_reservation.h" 23#include "core/hle/kernel/k_scoped_resource_reservation.h"
25#include "core/hle/kernel/k_shared_memory.h" 24#include "core/hle/kernel/k_shared_memory.h"
26#include "core/hle/kernel/k_shared_memory_info.h" 25#include "core/hle/kernel/k_shared_memory_info.h"
27#include "core/hle/kernel/k_slab_heap.h"
28#include "core/hle/kernel/k_thread.h" 26#include "core/hle/kernel/k_thread.h"
29#include "core/hle/kernel/kernel.h" 27#include "core/hle/kernel/kernel.h"
30#include "core/hle/kernel/svc_results.h" 28#include "core/hle/kernel/svc_results.h"
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 5ed0f2d83..48b17fc74 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -8,7 +8,6 @@
8#include <cstddef> 8#include <cstddef>
9#include <list> 9#include <list>
10#include <string> 10#include <string>
11#include <vector>
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "core/hle/kernel/k_address_arbiter.h" 12#include "core/hle/kernel/k_address_arbiter.h"
14#include "core/hle/kernel/k_auto_object.h" 13#include "core/hle/kernel/k_auto_object.h"
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index c96520828..6c0bb1672 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -22,7 +22,6 @@
22#include "core/hle/kernel/k_thread.h" 22#include "core/hle/kernel/k_thread.h"
23#include "core/hle/kernel/kernel.h" 23#include "core/hle/kernel/kernel.h"
24#include "core/hle/kernel/physical_core.h" 24#include "core/hle/kernel/physical_core.h"
25#include "core/hle/kernel/time_manager.h"
26 25
27namespace Kernel { 26namespace Kernel {
28 27
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index ba7f72c6b..94c8faf68 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -14,9 +14,7 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/fiber.h" 15#include "common/fiber.h"
16#include "common/logging/log.h" 16#include "common/logging/log.h"
17#include "common/scope_exit.h"
18#include "common/settings.h" 17#include "common/settings.h"
19#include "common/thread_queue_list.h"
20#include "core/core.h" 18#include "core/core.h"
21#include "core/cpu_manager.h" 19#include "core/cpu_manager.h"
22#include "core/hardware_properties.h" 20#include "core/hardware_properties.h"
@@ -33,7 +31,6 @@
33#include "core/hle/kernel/k_worker_task_manager.h" 31#include "core/hle/kernel/k_worker_task_manager.h"
34#include "core/hle/kernel/kernel.h" 32#include "core/hle/kernel/kernel.h"
35#include "core/hle/kernel/svc_results.h" 33#include "core/hle/kernel/svc_results.h"
36#include "core/hle/kernel/time_manager.h"
37#include "core/hle/result.h" 34#include "core/hle/result.h"
38#include "core/memory.h" 35#include "core/memory.h"
39 36
diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp
index 17b233fca..3fb277eba 100644
--- a/src/core/hle/kernel/k_thread_local_page.cpp
+++ b/src/core/hle/kernel/k_thread_local_page.cpp
@@ -4,7 +4,9 @@
4 4
5#include "common/scope_exit.h" 5#include "common/scope_exit.h"
6#include "core/core.h" 6#include "core/core.h"
7
7#include "core/hle/kernel/k_memory_block.h" 8#include "core/hle/kernel/k_memory_block.h"
9#include "core/hle/kernel/k_page_buffer.h"
8#include "core/hle/kernel/k_page_table.h" 10#include "core/hle/kernel/k_page_table.h"
9#include "core/hle/kernel/k_process.h" 11#include "core/hle/kernel/k_process.h"
10#include "core/hle/kernel/k_thread_local_page.h" 12#include "core/hle/kernel/k_thread_local_page.h"
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h
index 658c67e94..74b565a71 100644
--- a/src/core/hle/kernel/k_thread_local_page.h
+++ b/src/core/hle/kernel/k_thread_local_page.h
@@ -11,7 +11,6 @@
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/intrusive_red_black_tree.h" 13#include "common/intrusive_red_black_tree.h"
14#include "core/hle/kernel/k_page_buffer.h"
15#include "core/hle/kernel/memory_types.h" 14#include "core/hle/kernel/memory_types.h"
16#include "core/hle/kernel/slab_helpers.h" 15#include "core/hle/kernel/slab_helpers.h"
17#include "core/hle/result.h" 16#include "core/hle/result.h"
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f9828bc43..34da7c23b 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -22,9 +22,7 @@
22#include "core/arm/exclusive_monitor.h" 22#include "core/arm/exclusive_monitor.h"
23#include "core/core.h" 23#include "core/core.h"
24#include "core/core_timing.h" 24#include "core/core_timing.h"
25#include "core/core_timing_util.h"
26#include "core/cpu_manager.h" 25#include "core/cpu_manager.h"
27#include "core/device_memory.h"
28#include "core/hardware_properties.h" 26#include "core/hardware_properties.h"
29#include "core/hle/kernel/init/init_slab_setup.h" 27#include "core/hle/kernel/init/init_slab_setup.h"
30#include "core/hle/kernel/k_client_port.h" 28#include "core/hle/kernel/k_client_port.h"
@@ -35,7 +33,6 @@
35#include "core/hle/kernel/k_resource_limit.h" 33#include "core/hle/kernel/k_resource_limit.h"
36#include "core/hle/kernel/k_scheduler.h" 34#include "core/hle/kernel/k_scheduler.h"
37#include "core/hle/kernel/k_shared_memory.h" 35#include "core/hle/kernel/k_shared_memory.h"
38#include "core/hle/kernel/k_slab_heap.h"
39#include "core/hle/kernel/k_thread.h" 36#include "core/hle/kernel/k_thread.h"
40#include "core/hle/kernel/k_worker_task_manager.h" 37#include "core/hle/kernel/k_worker_task_manager.h"
41#include "core/hle/kernel/kernel.h" 38#include "core/hle/kernel/kernel.h"
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7087bbda6..4c68e96df 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -14,7 +14,6 @@
14#include "core/hardware_properties.h" 14#include "core/hardware_properties.h"
15#include "core/hle/kernel/k_auto_object.h" 15#include "core/hle/kernel/k_auto_object.h"
16#include "core/hle/kernel/k_slab_heap.h" 16#include "core/hle/kernel/k_slab_heap.h"
17#include "core/hle/kernel/memory_types.h"
18#include "core/hle/kernel/svc_common.h" 17#include "core/hle/kernel/svc_common.h"
19 18
20namespace Core { 19namespace Core {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 839171e85..976d63234 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1362,8 +1362,11 @@ static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Hand
1362 ResultInvalidMemoryRegion); 1362 ResultInvalidMemoryRegion);
1363 1363
1364 // Create a new page group. 1364 // Create a new page group.
1365 KMemoryInfo kBlockInfo = dst_pt.QueryInfo(dst_address); 1365 KPageLinkedList pg;
1366 KPageLinkedList pg(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages()); 1366 R_TRY(src_pt.MakeAndOpenPageGroup(
1367 std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess,
1368 KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None,
1369 KMemoryAttribute::All, KMemoryAttribute::None));
1367 1370
1368 // Map the group. 1371 // Map the group.
1369 R_TRY(dst_pt.MapPages(dst_address, pg, KMemoryState::SharedCode, 1372 R_TRY(dst_pt.MapPages(dst_address, pg, KMemoryState::SharedCode,
@@ -1408,8 +1411,8 @@ static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Ha
1408} 1411}
1409 1412
1410static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) { 1413static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) {
1411 LOG_TRACE(Kernel_SVC, "called, handle_out={}, address=0x{:X}, size=0x{:X}", 1414 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size);
1412 static_cast<void*>(out), address, size); 1415
1413 // Get kernel instance. 1416 // Get kernel instance.
1414 auto& kernel = system.Kernel(); 1417 auto& kernel = system.Kernel();
1415 1418
@@ -1664,7 +1667,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
1664 return ResultInvalidAddress; 1667 return ResultInvalidAddress;
1665 } 1668 }
1666 1669
1667 if (size == 0 || Common::Is4KBAligned(size)) { 1670 if (size == 0 || !Common::Is4KBAligned(size)) {
1668 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size); 1671 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
1669 return ResultInvalidSize; 1672 return ResultInvalidSize;
1670 } 1673 }
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index e34ef5a78..8a5332991 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -16,7 +16,6 @@
16#include "core/file_sys/control_metadata.h" 16#include "core/file_sys/control_metadata.h"
17#include "core/file_sys/patch_manager.h" 17#include "core/file_sys/patch_manager.h"
18#include "core/hle/ipc_helpers.h" 18#include "core/hle/ipc_helpers.h"
19#include "core/hle/kernel/kernel.h"
20#include "core/hle/service/acc/acc.h" 19#include "core/hle/service/acc/acc.h"
21#include "core/hle/service/acc/acc_aa.h" 20#include "core/hle/service/acc/acc_aa.h"
22#include "core/hle/service/acc/acc_su.h" 21#include "core/hle/service/acc/acc_su.h"
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 17347f7ef..5b690b406 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <optional> 8#include <optional>
9 9
10#include "common/common_funcs.h"
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "common/swap.h" 12#include "common/swap.h"
12#include "common/uuid.h" 13#include "common/uuid.h"
diff --git a/src/core/hle/service/am/applets/applet_mii.cpp b/src/core/hle/service/am/applets/applet_mii.cpp
deleted file mode 100644
index 8c4173737..000000000
--- a/src/core/hle/service/am/applets/applet_mii.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "common/logging/log.h"
7#include "core/core.h"
8#include "core/frontend/applets/mii.h"
9#include "core/hle/service/am/am.h"
10#include "core/hle/service/am/applets/applet_mii.h"
11#include "core/reporter.h"
12
13namespace Service::AM::Applets {
14
15Mii::Mii(Core::System& system_, LibraryAppletMode applet_mode_,
16 const Core::Frontend::MiiApplet& frontend_)
17 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
18
19Mii::~Mii() = default;
20
21void Mii::Initialize() {
22 is_complete = false;
23
24 const auto storage = broker.PopNormalDataToApplet();
25 ASSERT(storage != nullptr);
26
27 const auto data = storage->GetData();
28 ASSERT(data.size() == sizeof(MiiAppletInput));
29
30 std::memcpy(&input_data, data.data(), sizeof(MiiAppletInput));
31}
32
33bool Mii::TransactionComplete() const {
34 return is_complete;
35}
36
37ResultCode Mii::GetStatus() const {
38 return ResultSuccess;
39}
40
41void Mii::ExecuteInteractive() {
42 UNREACHABLE_MSG("Unexpected interactive applet data!");
43}
44
45void Mii::Execute() {
46 if (is_complete) {
47 return;
48 }
49
50 const auto callback = [this](const Core::Frontend::MiiParameters& parameters) {
51 DisplayCompleted(parameters);
52 };
53
54 switch (input_data.applet_mode) {
55 case MiiAppletMode::ShowMiiEdit: {
56 Service::Mii::MiiManager manager;
57 Core::Frontend::MiiParameters params{
58 .is_editable = false,
59 .mii_data = input_data.mii_char_info.mii_data,
60 };
61 frontend.ShowMii(params, callback);
62 break;
63 }
64 case MiiAppletMode::EditMii: {
65 Service::Mii::MiiManager manager;
66 Core::Frontend::MiiParameters params{
67 .is_editable = true,
68 .mii_data = input_data.mii_char_info.mii_data,
69 };
70 frontend.ShowMii(params, callback);
71 break;
72 }
73 case MiiAppletMode::CreateMii: {
74 Service::Mii::MiiManager manager;
75 Core::Frontend::MiiParameters params{
76 .is_editable = true,
77 .mii_data = manager.BuildDefault(0),
78 };
79 frontend.ShowMii(params, callback);
80 break;
81 }
82 default:
83 UNIMPLEMENTED_MSG("Unimplemented LibAppletMiiEdit mode={:02X}!", input_data.applet_mode);
84 }
85}
86
87void Mii::DisplayCompleted(const Core::Frontend::MiiParameters& parameters) {
88 is_complete = true;
89
90 std::vector<u8> reply(sizeof(AppletOutputForCharInfoEditing));
91 output_data = {
92 .result = ResultSuccess,
93 .mii_data = parameters.mii_data,
94 };
95
96 std::memcpy(reply.data(), &output_data, sizeof(AppletOutputForCharInfoEditing));
97 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
98 broker.SignalStateChanged();
99}
100
101} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_mii.h b/src/core/hle/service/am/applets/applet_mii.h
deleted file mode 100644
index 42326bfc2..000000000
--- a/src/core/hle/service/am/applets/applet_mii.h
+++ /dev/null
@@ -1,90 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "core/hle/result.h"
10#include "core/hle/service/am/applets/applets.h"
11#include "core/hle/service/mii/mii_manager.h"
12
13namespace Core {
14class System;
15}
16
17namespace Service::AM::Applets {
18
19// This is nn::mii::AppletMode
20enum class MiiAppletMode : u32 {
21 ShowMiiEdit = 0,
22 AppendMii = 1,
23 AppendMiiImage = 2,
24 UpdateMiiImage = 3,
25 CreateMii = 4,
26 EditMii = 5,
27};
28
29struct MiiCharInfo {
30 Service::Mii::MiiInfo mii_data{};
31 INSERT_PADDING_BYTES(0x28);
32};
33static_assert(sizeof(MiiCharInfo) == 0x80, "MiiCharInfo has incorrect size.");
34
35// This is nn::mii::AppletInput
36struct MiiAppletInput {
37 s32 version{};
38 MiiAppletMode applet_mode{};
39 u32 special_mii_key_code{};
40 union {
41 std::array<Common::UUID, 8> valid_uuid;
42 MiiCharInfo mii_char_info;
43 };
44 Common::UUID used_uuid;
45 INSERT_PADDING_BYTES(0x64);
46};
47static_assert(sizeof(MiiAppletInput) == 0x100, "MiiAppletInput has incorrect size.");
48
49// This is nn::mii::AppletOutput
50struct MiiAppletOutput {
51 ResultCode result{ResultSuccess};
52 s32 index{};
53 INSERT_PADDING_BYTES(0x18);
54};
55static_assert(sizeof(MiiAppletOutput) == 0x20, "MiiAppletOutput has incorrect size.");
56
57// This is nn::mii::AppletOutputForCharInfoEditing
58struct AppletOutputForCharInfoEditing {
59 ResultCode result{ResultSuccess};
60 Service::Mii::MiiInfo mii_data{};
61 INSERT_PADDING_BYTES(0x24);
62};
63static_assert(sizeof(AppletOutputForCharInfoEditing) == 0x80,
64 "AppletOutputForCharInfoEditing has incorrect size.");
65
66class Mii final : public Applet {
67public:
68 explicit Mii(Core::System& system_, LibraryAppletMode applet_mode_,
69 const Core::Frontend::MiiApplet& frontend_);
70 ~Mii() override;
71
72 void Initialize() override;
73
74 bool TransactionComplete() const override;
75 ResultCode GetStatus() const override;
76 void ExecuteInteractive() override;
77 void Execute() override;
78
79 void DisplayCompleted(const Core::Frontend::MiiParameters& parameters);
80
81private:
82 const Core::Frontend::MiiApplet& frontend;
83 MiiAppletInput input_data{};
84 AppletOutputForCharInfoEditing output_data{};
85
86 bool is_complete = false;
87 Core::System& system;
88};
89
90} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
new file mode 100644
index 000000000..8fbde1be4
--- /dev/null
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -0,0 +1,139 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "common/logging/log.h"
7#include "core/core.h"
8#include "core/frontend/applets/mii_edit.h"
9#include "core/hle/service/am/am.h"
10#include "core/hle/service/am/applets/applet_mii_edit.h"
11#include "core/hle/service/mii/mii_manager.h"
12
13namespace Service::AM::Applets {
14
15MiiEdit::MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
16 const Core::Frontend::MiiEditApplet& frontend_)
17 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
18
19MiiEdit::~MiiEdit() = default;
20
21void MiiEdit::Initialize() {
22 // Note: MiiEdit is not initialized with common arguments.
23 // Instead, it is initialized by an AppletInput storage with size 0x100 bytes.
24 // Do NOT call Applet::Initialize() here.
25
26 const auto storage = broker.PopNormalDataToApplet();
27 ASSERT(storage != nullptr);
28
29 const auto applet_input_data = storage->GetData();
30 ASSERT(applet_input_data.size() >= sizeof(MiiEditAppletInputCommon));
31
32 std::memcpy(&applet_input_common, applet_input_data.data(), sizeof(MiiEditAppletInputCommon));
33
34 LOG_INFO(Service_AM,
35 "Initializing MiiEdit Applet with MiiEditAppletVersion={} and MiiEditAppletMode={}",
36 applet_input_common.version, applet_input_common.applet_mode);
37
38 switch (applet_input_common.version) {
39 case MiiEditAppletVersion::Version3:
40 ASSERT(applet_input_data.size() ==
41 sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV3));
42 std::memcpy(&applet_input_v3, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
43 sizeof(MiiEditAppletInputV3));
44 break;
45 case MiiEditAppletVersion::Version4:
46 ASSERT(applet_input_data.size() ==
47 sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
48 std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
49 sizeof(MiiEditAppletInputV4));
50 break;
51 default:
52 UNIMPLEMENTED_MSG("Unknown MiiEditAppletVersion={} with size={}",
53 applet_input_common.version, applet_input_data.size());
54 ASSERT(applet_input_data.size() >=
55 sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
56 std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
57 sizeof(MiiEditAppletInputV4));
58 break;
59 }
60}
61
62bool MiiEdit::TransactionComplete() const {
63 return is_complete;
64}
65
66ResultCode MiiEdit::GetStatus() const {
67 return ResultSuccess;
68}
69
70void MiiEdit::ExecuteInteractive() {
71 UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet.");
72}
73
74void MiiEdit::Execute() {
75 if (is_complete) {
76 return;
77 }
78
79 // This is a default stub for each of the MiiEdit applet modes.
80 switch (applet_input_common.applet_mode) {
81 case MiiEditAppletMode::ShowMiiEdit:
82 case MiiEditAppletMode::AppendMii:
83 case MiiEditAppletMode::AppendMiiImage:
84 case MiiEditAppletMode::UpdateMiiImage:
85 MiiEditOutput(MiiEditResult::Success, 0);
86 break;
87 case MiiEditAppletMode::CreateMii:
88 case MiiEditAppletMode::EditMii: {
89 Service::Mii::MiiManager mii_manager;
90
91 const MiiEditCharInfo char_info{
92 .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
93 ? applet_input_v4.char_info.mii_info
94 : mii_manager.BuildDefault(0)},
95 };
96
97 MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
98 break;
99 }
100 default:
101 UNIMPLEMENTED_MSG("Unknown MiiEditAppletMode={}", applet_input_common.applet_mode);
102
103 MiiEditOutput(MiiEditResult::Success, 0);
104 break;
105 }
106}
107
108void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) {
109 const MiiEditAppletOutput applet_output{
110 .result{result},
111 .index{index},
112 };
113
114 std::vector<u8> out_data(sizeof(MiiEditAppletOutput));
115 std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput));
116
117 is_complete = true;
118
119 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
120 broker.SignalStateChanged();
121}
122
123void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
124 const MiiEditCharInfo& char_info) {
125 const MiiEditAppletOutputForCharInfoEditing applet_output{
126 .result{result},
127 .char_info{char_info},
128 };
129
130 std::vector<u8> out_data(sizeof(MiiEditAppletOutputForCharInfoEditing));
131 std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutputForCharInfoEditing));
132
133 is_complete = true;
134
135 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
136 broker.SignalStateChanged();
137}
138
139} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h
new file mode 100644
index 000000000..e9ca0e2af
--- /dev/null
+++ b/src/core/hle/service/am/applets/applet_mii_edit.h
@@ -0,0 +1,45 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/result.h"
8#include "core/hle/service/am/applets/applet_mii_edit_types.h"
9#include "core/hle/service/am/applets/applets.h"
10
11namespace Core {
12class System;
13} // namespace Core
14
15namespace Service::AM::Applets {
16
17class MiiEdit final : public Applet {
18public:
19 explicit MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
20 const Core::Frontend::MiiEditApplet& frontend_);
21 ~MiiEdit() override;
22
23 void Initialize() override;
24
25 bool TransactionComplete() const override;
26 ResultCode GetStatus() const override;
27 void ExecuteInteractive() override;
28 void Execute() override;
29
30 void MiiEditOutput(MiiEditResult result, s32 index);
31
32 void MiiEditOutputForCharInfoEditing(MiiEditResult result, const MiiEditCharInfo& char_info);
33
34private:
35 const Core::Frontend::MiiEditApplet& frontend;
36 Core::System& system;
37
38 MiiEditAppletInputCommon applet_input_common{};
39 MiiEditAppletInputV3 applet_input_v3{};
40 MiiEditAppletInputV4 applet_input_v4{};
41
42 bool is_complete{false};
43};
44
45} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_mii_edit_types.h b/src/core/hle/service/am/applets/applet_mii_edit_types.h
new file mode 100644
index 000000000..70dea0007
--- /dev/null
+++ b/src/core/hle/service/am/applets/applet_mii_edit_types.h
@@ -0,0 +1,83 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/common_funcs.h"
10#include "common/common_types.h"
11#include "core/hle/service/mii/types.h"
12
13namespace Service::AM::Applets {
14
15enum class MiiEditAppletVersion : s32 {
16 Version3 = 0x3, // 1.0.0 - 10.1.1
17 Version4 = 0x4, // 10.2.0+
18};
19
20// This is nn::mii::AppletMode
21enum class MiiEditAppletMode : u32 {
22 ShowMiiEdit = 0,
23 AppendMii = 1,
24 AppendMiiImage = 2,
25 UpdateMiiImage = 3,
26 CreateMii = 4,
27 EditMii = 5,
28};
29
30enum class MiiEditResult : u32 {
31 Success,
32 Cancel,
33};
34
35struct MiiEditCharInfo {
36 Service::Mii::MiiInfo mii_info{};
37};
38static_assert(sizeof(MiiEditCharInfo) == 0x58, "MiiEditCharInfo has incorrect size.");
39
40struct MiiEditAppletInputCommon {
41 MiiEditAppletVersion version{};
42 MiiEditAppletMode applet_mode{};
43};
44static_assert(sizeof(MiiEditAppletInputCommon) == 0x8,
45 "MiiEditAppletInputCommon has incorrect size.");
46
47struct MiiEditAppletInputV3 {
48 u32 special_mii_key_code{};
49 std::array<Common::UUID, 8> valid_uuids{};
50 Common::UUID used_uuid{};
51 INSERT_PADDING_BYTES(0x64);
52};
53static_assert(sizeof(MiiEditAppletInputV3) == 0x100 - sizeof(MiiEditAppletInputCommon),
54 "MiiEditAppletInputV3 has incorrect size.");
55
56struct MiiEditAppletInputV4 {
57 u32 special_mii_key_code{};
58 MiiEditCharInfo char_info{};
59 INSERT_PADDING_BYTES(0x28);
60 Common::UUID used_uuid{};
61 INSERT_PADDING_BYTES(0x64);
62};
63static_assert(sizeof(MiiEditAppletInputV4) == 0x100 - sizeof(MiiEditAppletInputCommon),
64 "MiiEditAppletInputV4 has incorrect size.");
65
66// This is nn::mii::AppletOutput
67struct MiiEditAppletOutput {
68 MiiEditResult result{};
69 s32 index{};
70 INSERT_PADDING_BYTES(0x18);
71};
72static_assert(sizeof(MiiEditAppletOutput) == 0x20, "MiiEditAppletOutput has incorrect size.");
73
74// This is nn::mii::AppletOutputForCharInfoEditing
75struct MiiEditAppletOutputForCharInfoEditing {
76 MiiEditResult result{};
77 MiiEditCharInfo char_info{};
78 INSERT_PADDING_BYTES(0x24);
79};
80static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80,
81 "MiiEditAppletOutputForCharInfoEditing has incorrect size.");
82
83} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index f38f53f69..ee669686c 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -226,7 +226,7 @@ void SoftwareKeyboard::InitializeForeground() {
226 ASSERT(work_buffer_storage != nullptr); 226 ASSERT(work_buffer_storage != nullptr);
227 227
228 if (swkbd_config_common.initial_string_length == 0) { 228 if (swkbd_config_common.initial_string_length == 0) {
229 InitializeFrontendKeyboard(); 229 InitializeFrontendNormalKeyboard();
230 return; 230 return;
231 } 231 }
232 232
@@ -243,7 +243,7 @@ void SoftwareKeyboard::InitializeForeground() {
243 243
244 LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text)); 244 LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text));
245 245
246 InitializeFrontendKeyboard(); 246 InitializeFrontendNormalKeyboard();
247} 247}
248 248
249void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) { 249void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) {
@@ -480,129 +480,173 @@ void SoftwareKeyboard::ChangeState(SwkbdState state) {
480 ReplyDefault(); 480 ReplyDefault();
481} 481}
482 482
483void SoftwareKeyboard::InitializeFrontendKeyboard() { 483void SoftwareKeyboard::InitializeFrontendNormalKeyboard() {
484 if (is_background) { 484 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
485 const auto& appear_arg = swkbd_calc_arg.appear_arg; 485 swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size());
486 486
487 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 487 std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
488 appear_arg.ok_text.data(), appear_arg.ok_text.size()); 488 swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size());
489 489
490 const u32 max_text_length = 490 std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
491 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH 491 swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size());
492 ? appear_arg.max_text_length 492
493 : DEFAULT_MAX_TEXT_LENGTH; 493 std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
494 494 swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size());
495 const u32 min_text_length = 495
496 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0; 496 const u32 max_text_length =
497 497 swkbd_config_common.max_text_length > 0 &&
498 const s32 initial_cursor_position = 498 swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
499 current_cursor_position > 0 ? current_cursor_position : 0; 499 ? swkbd_config_common.max_text_length
500 500 : DEFAULT_MAX_TEXT_LENGTH;
501 const auto text_draw_type = 501
502 max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; 502 const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length
503 503 ? swkbd_config_common.min_text_length
504 Core::Frontend::KeyboardInitializeParameters initialize_parameters{ 504 : 0;
505 .ok_text{std::move(ok_text)}, 505
506 .header_text{}, 506 const s32 initial_cursor_position = [this] {
507 .sub_text{}, 507 switch (swkbd_config_common.initial_cursor_position) {
508 .guide_text{}, 508 case SwkbdInitialCursorPosition::Start:
509 .initial_text{current_text}, 509 default:
510 .max_text_length{max_text_length}, 510 return 0;
511 .min_text_length{min_text_length}, 511 case SwkbdInitialCursorPosition::End:
512 .initial_cursor_position{initial_cursor_position}, 512 return static_cast<s32>(initial_text.size());
513 .type{appear_arg.type}, 513 }
514 .password_mode{SwkbdPasswordMode::Disabled}, 514 }();
515 .text_draw_type{text_draw_type}, 515
516 .key_disable_flags{appear_arg.key_disable_flags}, 516 const auto text_draw_type = [this, max_text_length] {
517 .use_blur_background{false}, 517 switch (swkbd_config_common.text_draw_type) {
518 .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, 518 case SwkbdTextDrawType::Line:
519 .enable_return_button{appear_arg.enable_return_button}, 519 default:
520 .disable_cancel_button{appear_arg.disable_cancel_button}, 520 return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
521 }; 521 case SwkbdTextDrawType::Box:
522 522 case SwkbdTextDrawType::DownloadCode:
523 frontend.InitializeKeyboard( 523 return swkbd_config_common.text_draw_type;
524 true, std::move(initialize_parameters), {}, 524 }
525 [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) { 525 }();
526 SubmitTextInline(reply_type, submitted_text, cursor_position); 526
527 }); 527 const auto enable_return_button =
528 } else { 528 text_draw_type == SwkbdTextDrawType::Box ? swkbd_config_common.enable_return_button : false;
529 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 529
530 swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size()); 530 const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227
531 531 ? swkbd_config_new.disable_cancel_button
532 std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 532 : false;
533 swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size()); 533
534 534 Core::Frontend::KeyboardInitializeParameters initialize_parameters{
535 std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 535 .ok_text{std::move(ok_text)},
536 swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size()); 536 .header_text{std::move(header_text)},
537 537 .sub_text{std::move(sub_text)},
538 std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 538 .guide_text{std::move(guide_text)},
539 swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size()); 539 .initial_text{initial_text},
540 540 .max_text_length{max_text_length},
541 const u32 max_text_length = 541 .min_text_length{min_text_length},
542 swkbd_config_common.max_text_length > 0 && 542 .initial_cursor_position{initial_cursor_position},
543 swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH 543 .type{swkbd_config_common.type},
544 ? swkbd_config_common.max_text_length 544 .password_mode{swkbd_config_common.password_mode},
545 : DEFAULT_MAX_TEXT_LENGTH; 545 .text_draw_type{text_draw_type},
546 546 .key_disable_flags{swkbd_config_common.key_disable_flags},
547 const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length 547 .use_blur_background{swkbd_config_common.use_blur_background},
548 ? swkbd_config_common.min_text_length 548 .enable_backspace_button{true},
549 : 0; 549 .enable_return_button{enable_return_button},
550 550 .disable_cancel_button{disable_cancel_button},
551 const s32 initial_cursor_position = [this] { 551 };
552 switch (swkbd_config_common.initial_cursor_position) { 552
553 case SwkbdInitialCursorPosition::Start: 553 frontend.InitializeKeyboard(
554 default: 554 false, std::move(initialize_parameters),
555 return 0; 555 [this](SwkbdResult result, std::u16string submitted_text, bool confirmed) {
556 case SwkbdInitialCursorPosition::End: 556 SubmitTextNormal(result, submitted_text, confirmed);
557 return static_cast<s32>(initial_text.size()); 557 },
558 } 558 {});
559 }(); 559}
560 560
561 const auto text_draw_type = [this, max_text_length] { 561void SoftwareKeyboard::InitializeFrontendInlineKeyboard(
562 switch (swkbd_config_common.text_draw_type) { 562 Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
563 case SwkbdTextDrawType::Line: 563 frontend.InitializeKeyboard(
564 default: 564 true, std::move(initialize_parameters), {},
565 return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; 565 [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) {
566 case SwkbdTextDrawType::Box: 566 SubmitTextInline(reply_type, submitted_text, cursor_position);
567 case SwkbdTextDrawType::DownloadCode: 567 });
568 return swkbd_config_common.text_draw_type; 568}
569 } 569
570 }(); 570void SoftwareKeyboard::InitializeFrontendInlineKeyboardOld() {
571 571 const auto& appear_arg = swkbd_calc_arg_old.appear_arg;
572 const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box 572
573 ? swkbd_config_common.enable_return_button 573 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
574 : false; 574 appear_arg.ok_text.data(), appear_arg.ok_text.size());
575 575
576 const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227 576 const u32 max_text_length =
577 ? swkbd_config_new.disable_cancel_button 577 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
578 : false; 578 ? appear_arg.max_text_length
579 579 : DEFAULT_MAX_TEXT_LENGTH;
580 Core::Frontend::KeyboardInitializeParameters initialize_parameters{ 580
581 .ok_text{std::move(ok_text)}, 581 const u32 min_text_length =
582 .header_text{std::move(header_text)}, 582 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
583 .sub_text{std::move(sub_text)}, 583
584 .guide_text{std::move(guide_text)}, 584 const s32 initial_cursor_position = current_cursor_position > 0 ? current_cursor_position : 0;
585 .initial_text{initial_text}, 585
586 .max_text_length{max_text_length}, 586 const auto text_draw_type =
587 .min_text_length{min_text_length}, 587 max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
588 .initial_cursor_position{initial_cursor_position}, 588
589 .type{swkbd_config_common.type}, 589 Core::Frontend::KeyboardInitializeParameters initialize_parameters{
590 .password_mode{swkbd_config_common.password_mode}, 590 .ok_text{std::move(ok_text)},
591 .text_draw_type{text_draw_type}, 591 .header_text{},
592 .key_disable_flags{swkbd_config_common.key_disable_flags}, 592 .sub_text{},
593 .use_blur_background{swkbd_config_common.use_blur_background}, 593 .guide_text{},
594 .enable_backspace_button{true}, 594 .initial_text{current_text},
595 .enable_return_button{enable_return_button}, 595 .max_text_length{max_text_length},
596 .disable_cancel_button{disable_cancel_button}, 596 .min_text_length{min_text_length},
597 }; 597 .initial_cursor_position{initial_cursor_position},
598 598 .type{appear_arg.type},
599 frontend.InitializeKeyboard( 599 .password_mode{SwkbdPasswordMode::Disabled},
600 false, std::move(initialize_parameters), 600 .text_draw_type{text_draw_type},
601 [this](SwkbdResult result, std::u16string submitted_text, bool confirmed) { 601 .key_disable_flags{appear_arg.key_disable_flags},
602 SubmitTextNormal(result, submitted_text, confirmed); 602 .use_blur_background{false},
603 }, 603 .enable_backspace_button{swkbd_calc_arg_old.enable_backspace_button},
604 {}); 604 .enable_return_button{appear_arg.enable_return_button},
605 } 605 .disable_cancel_button{appear_arg.disable_cancel_button},
606 };
607
608 InitializeFrontendInlineKeyboard(std::move(initialize_parameters));
609}
610
611void SoftwareKeyboard::InitializeFrontendInlineKeyboardNew() {
612 const auto& appear_arg = swkbd_calc_arg_new.appear_arg;
613
614 std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
615 appear_arg.ok_text.data(), appear_arg.ok_text.size());
616
617 const u32 max_text_length =
618 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
619 ? appear_arg.max_text_length
620 : DEFAULT_MAX_TEXT_LENGTH;
621
622 const u32 min_text_length =
623 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
624
625 const s32 initial_cursor_position = current_cursor_position > 0 ? current_cursor_position : 0;
626
627 const auto text_draw_type =
628 max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
629
630 Core::Frontend::KeyboardInitializeParameters initialize_parameters{
631 .ok_text{std::move(ok_text)},
632 .header_text{},
633 .sub_text{},
634 .guide_text{},
635 .initial_text{current_text},
636 .max_text_length{max_text_length},
637 .min_text_length{min_text_length},
638 .initial_cursor_position{initial_cursor_position},
639 .type{appear_arg.type},
640 .password_mode{SwkbdPasswordMode::Disabled},
641 .text_draw_type{text_draw_type},
642 .key_disable_flags{appear_arg.key_disable_flags},
643 .use_blur_background{false},
644 .enable_backspace_button{swkbd_calc_arg_new.enable_backspace_button},
645 .enable_return_button{appear_arg.enable_return_button},
646 .disable_cancel_button{appear_arg.disable_cancel_button},
647 };
648
649 InitializeFrontendInlineKeyboard(std::move(initialize_parameters));
606} 650}
607 651
608void SoftwareKeyboard::ShowNormalKeyboard() { 652void SoftwareKeyboard::ShowNormalKeyboard() {
@@ -614,14 +658,21 @@ void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_resul
614 frontend.ShowTextCheckDialog(text_check_result, std::move(text_check_message)); 658 frontend.ShowTextCheckDialog(text_check_result, std::move(text_check_message));
615} 659}
616 660
617void SoftwareKeyboard::ShowInlineKeyboard() { 661void SoftwareKeyboard::ShowInlineKeyboard(
662 Core::Frontend::InlineAppearParameters appear_parameters) {
663 frontend.ShowInlineKeyboard(std::move(appear_parameters));
664
665 ChangeState(SwkbdState::InitializedIsShown);
666}
667
668void SoftwareKeyboard::ShowInlineKeyboardOld() {
618 if (swkbd_state != SwkbdState::InitializedIsHidden) { 669 if (swkbd_state != SwkbdState::InitializedIsHidden) {
619 return; 670 return;
620 } 671 }
621 672
622 ChangeState(SwkbdState::InitializedIsAppearing); 673 ChangeState(SwkbdState::InitializedIsAppearing);
623 674
624 const auto& appear_arg = swkbd_calc_arg.appear_arg; 675 const auto& appear_arg = swkbd_calc_arg_old.appear_arg;
625 676
626 const u32 max_text_length = 677 const u32 max_text_length =
627 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH 678 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
@@ -634,21 +685,54 @@ void SoftwareKeyboard::ShowInlineKeyboard() {
634 Core::Frontend::InlineAppearParameters appear_parameters{ 685 Core::Frontend::InlineAppearParameters appear_parameters{
635 .max_text_length{max_text_length}, 686 .max_text_length{max_text_length},
636 .min_text_length{min_text_length}, 687 .min_text_length{min_text_length},
637 .key_top_scale_x{swkbd_calc_arg.key_top_scale_x}, 688 .key_top_scale_x{swkbd_calc_arg_old.key_top_scale_x},
638 .key_top_scale_y{swkbd_calc_arg.key_top_scale_y}, 689 .key_top_scale_y{swkbd_calc_arg_old.key_top_scale_y},
639 .key_top_translate_x{swkbd_calc_arg.key_top_translate_x}, 690 .key_top_translate_x{swkbd_calc_arg_old.key_top_translate_x},
640 .key_top_translate_y{swkbd_calc_arg.key_top_translate_y}, 691 .key_top_translate_y{swkbd_calc_arg_old.key_top_translate_y},
641 .type{appear_arg.type}, 692 .type{appear_arg.type},
642 .key_disable_flags{appear_arg.key_disable_flags}, 693 .key_disable_flags{appear_arg.key_disable_flags},
643 .key_top_as_floating{swkbd_calc_arg.key_top_as_floating}, 694 .key_top_as_floating{swkbd_calc_arg_old.key_top_as_floating},
644 .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, 695 .enable_backspace_button{swkbd_calc_arg_old.enable_backspace_button},
645 .enable_return_button{appear_arg.enable_return_button}, 696 .enable_return_button{appear_arg.enable_return_button},
646 .disable_cancel_button{appear_arg.disable_cancel_button}, 697 .disable_cancel_button{appear_arg.disable_cancel_button},
647 }; 698 };
648 699
649 frontend.ShowInlineKeyboard(std::move(appear_parameters)); 700 ShowInlineKeyboard(std::move(appear_parameters));
701}
650 702
651 ChangeState(SwkbdState::InitializedIsShown); 703void SoftwareKeyboard::ShowInlineKeyboardNew() {
704 if (swkbd_state != SwkbdState::InitializedIsHidden) {
705 return;
706 }
707
708 ChangeState(SwkbdState::InitializedIsAppearing);
709
710 const auto& appear_arg = swkbd_calc_arg_new.appear_arg;
711
712 const u32 max_text_length =
713 appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
714 ? appear_arg.max_text_length
715 : DEFAULT_MAX_TEXT_LENGTH;
716
717 const u32 min_text_length =
718 appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
719
720 Core::Frontend::InlineAppearParameters appear_parameters{
721 .max_text_length{max_text_length},
722 .min_text_length{min_text_length},
723 .key_top_scale_x{swkbd_calc_arg_new.key_top_scale_x},
724 .key_top_scale_y{swkbd_calc_arg_new.key_top_scale_y},
725 .key_top_translate_x{swkbd_calc_arg_new.key_top_translate_x},
726 .key_top_translate_y{swkbd_calc_arg_new.key_top_translate_y},
727 .type{appear_arg.type},
728 .key_disable_flags{appear_arg.key_disable_flags},
729 .key_top_as_floating{swkbd_calc_arg_new.key_top_as_floating},
730 .enable_backspace_button{swkbd_calc_arg_new.enable_backspace_button},
731 .enable_return_button{appear_arg.enable_return_button},
732 .disable_cancel_button{appear_arg.disable_cancel_button},
733 };
734
735 ShowInlineKeyboard(std::move(appear_parameters));
652} 736}
653 737
654void SoftwareKeyboard::HideInlineKeyboard() { 738void SoftwareKeyboard::HideInlineKeyboard() {
@@ -693,6 +777,8 @@ void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) {
693 777
694void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) { 778void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) {
695 LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented."); 779 LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented.");
780
781 ReplyReleasedUserWordInfo();
696} 782}
697 783
698void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) { 784void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) {
@@ -702,53 +788,135 @@ void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_dat
702void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) { 788void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) {
703 LOG_DEBUG(Service_AM, "Processing Request: Calc"); 789 LOG_DEBUG(Service_AM, "Processing Request: Calc");
704 790
705 ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg)); 791 ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon));
706 792
707 std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand), 793 std::memcpy(&swkbd_calc_arg_common, request_data.data() + sizeof(SwkbdRequestCommand),
708 sizeof(SwkbdCalcArg)); 794 sizeof(SwkbdCalcArgCommon));
795
796 switch (swkbd_calc_arg_common.calc_arg_size) {
797 case sizeof(SwkbdCalcArgCommon) + sizeof(SwkbdCalcArgOld):
798 ASSERT(request_data.size() ==
799 sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon) + sizeof(SwkbdCalcArgOld));
800 std::memcpy(&swkbd_calc_arg_old,
801 request_data.data() + sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon),
802 sizeof(SwkbdCalcArgOld));
803 RequestCalcOld();
804 break;
805 case sizeof(SwkbdCalcArgCommon) + sizeof(SwkbdCalcArgNew):
806 ASSERT(request_data.size() ==
807 sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon) + sizeof(SwkbdCalcArgNew));
808 std::memcpy(&swkbd_calc_arg_new,
809 request_data.data() + sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon),
810 sizeof(SwkbdCalcArgNew));
811 RequestCalcNew();
812 break;
813 default:
814 UNIMPLEMENTED_MSG("Unknown SwkbdCalcArg size={}", swkbd_calc_arg_common.calc_arg_size);
815 ASSERT(request_data.size() >=
816 sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon) + sizeof(SwkbdCalcArgNew));
817 std::memcpy(&swkbd_calc_arg_new,
818 request_data.data() + sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArgCommon),
819 sizeof(SwkbdCalcArgNew));
820 RequestCalcNew();
821 break;
822 }
823}
824
825void SoftwareKeyboard::RequestCalcOld() {
826 if (swkbd_calc_arg_common.flags.set_input_text) {
827 current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
828 swkbd_calc_arg_old.input_text.data(), swkbd_calc_arg_old.input_text.size());
829 }
830
831 if (swkbd_calc_arg_common.flags.set_cursor_position) {
832 current_cursor_position = swkbd_calc_arg_old.cursor_position;
833 }
834
835 if (swkbd_calc_arg_common.flags.set_utf8_mode) {
836 inline_use_utf8 = swkbd_calc_arg_old.utf8_mode;
837 }
838
839 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
840 swkbd_calc_arg_common.flags.unset_customize_dic) {
841 ReplyUnsetCustomizeDic();
842 }
843
844 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
845 swkbd_calc_arg_common.flags.unset_user_word_info) {
846 ReplyReleasedUserWordInfo();
847 }
848
849 if (swkbd_state == SwkbdState::NotInitialized &&
850 swkbd_calc_arg_common.flags.set_initialize_arg) {
851 InitializeFrontendInlineKeyboardOld();
852
853 ChangeState(SwkbdState::InitializedIsHidden);
854
855 ReplyFinishedInitialize();
856 }
857
858 if (!swkbd_calc_arg_common.flags.set_initialize_arg &&
859 (swkbd_calc_arg_common.flags.set_input_text ||
860 swkbd_calc_arg_common.flags.set_cursor_position)) {
861 InlineTextChanged();
862 }
863
864 if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg_common.flags.appear) {
865 ShowInlineKeyboardOld();
866 return;
867 }
868
869 if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg_common.flags.disappear) {
870 HideInlineKeyboard();
871 return;
872 }
873}
709 874
710 if (swkbd_calc_arg.flags.set_input_text) { 875void SoftwareKeyboard::RequestCalcNew() {
876 if (swkbd_calc_arg_common.flags.set_input_text) {
711 current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( 877 current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
712 swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size()); 878 swkbd_calc_arg_new.input_text.data(), swkbd_calc_arg_new.input_text.size());
713 } 879 }
714 880
715 if (swkbd_calc_arg.flags.set_cursor_position) { 881 if (swkbd_calc_arg_common.flags.set_cursor_position) {
716 current_cursor_position = swkbd_calc_arg.cursor_position; 882 current_cursor_position = swkbd_calc_arg_new.cursor_position;
717 } 883 }
718 884
719 if (swkbd_calc_arg.flags.set_utf8_mode) { 885 if (swkbd_calc_arg_common.flags.set_utf8_mode) {
720 inline_use_utf8 = swkbd_calc_arg.utf8_mode; 886 inline_use_utf8 = swkbd_calc_arg_new.utf8_mode;
721 } 887 }
722 888
723 if (swkbd_state <= SwkbdState::InitializedIsHidden && 889 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
724 swkbd_calc_arg.flags.unset_customize_dic) { 890 swkbd_calc_arg_common.flags.unset_customize_dic) {
725 ReplyUnsetCustomizeDic(); 891 ReplyUnsetCustomizeDic();
726 } 892 }
727 893
728 if (swkbd_state <= SwkbdState::InitializedIsHidden && 894 if (swkbd_state <= SwkbdState::InitializedIsHidden &&
729 swkbd_calc_arg.flags.unset_user_word_info) { 895 swkbd_calc_arg_common.flags.unset_user_word_info) {
730 ReplyReleasedUserWordInfo(); 896 ReplyReleasedUserWordInfo();
731 } 897 }
732 898
733 if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) { 899 if (swkbd_state == SwkbdState::NotInitialized &&
734 InitializeFrontendKeyboard(); 900 swkbd_calc_arg_common.flags.set_initialize_arg) {
901 InitializeFrontendInlineKeyboardNew();
735 902
736 ChangeState(SwkbdState::InitializedIsHidden); 903 ChangeState(SwkbdState::InitializedIsHidden);
737 904
738 ReplyFinishedInitialize(); 905 ReplyFinishedInitialize();
739 } 906 }
740 907
741 if (!swkbd_calc_arg.flags.set_initialize_arg && 908 if (!swkbd_calc_arg_common.flags.set_initialize_arg &&
742 (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) { 909 (swkbd_calc_arg_common.flags.set_input_text ||
910 swkbd_calc_arg_common.flags.set_cursor_position)) {
743 InlineTextChanged(); 911 InlineTextChanged();
744 } 912 }
745 913
746 if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) { 914 if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg_common.flags.appear) {
747 ShowInlineKeyboard(); 915 ShowInlineKeyboardNew();
748 return; 916 return;
749 } 917 }
750 918
751 if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) { 919 if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg_common.flags.disappear) {
752 HideInlineKeyboard(); 920 HideInlineKeyboard();
753 return; 921 return;
754 } 922 }
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h
index a0fddd965..7ee4c5eea 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.h
@@ -13,6 +13,11 @@ namespace Core {
13class System; 13class System;
14} 14}
15 15
16namespace Core::Frontend {
17struct KeyboardInitializeParameters;
18struct InlineAppearParameters;
19} // namespace Core::Frontend
20
16namespace Service::AM::Applets { 21namespace Service::AM::Applets {
17 22
18class SoftwareKeyboard final : public Applet { 23class SoftwareKeyboard final : public Applet {
@@ -78,13 +83,22 @@ private:
78 void ChangeState(SwkbdState state); 83 void ChangeState(SwkbdState state);
79 84
80 /** 85 /**
81 * Signals the frontend to initialize the software keyboard with common parameters. 86 * Signals the frontend to initialize the normal software keyboard with common parameters.
82 * This initializes either the normal software keyboard or the inline software keyboard
83 * depending on the state of is_background.
84 * Note that this does not cause the keyboard to appear. 87 * Note that this does not cause the keyboard to appear.
85 * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear. 88 * Use the ShowNormalKeyboard() functions to cause the keyboard to appear.
86 */ 89 */
87 void InitializeFrontendKeyboard(); 90 void InitializeFrontendNormalKeyboard();
91
92 /**
93 * Signals the frontend to initialize the inline software keyboard with common parameters.
94 * Note that this does not cause the keyboard to appear.
95 * Use the ShowInlineKeyboard() to cause the keyboard to appear.
96 */
97 void InitializeFrontendInlineKeyboard(
98 Core::Frontend::KeyboardInitializeParameters initialize_parameters);
99
100 void InitializeFrontendInlineKeyboardOld();
101 void InitializeFrontendInlineKeyboardNew();
88 102
89 /// Signals the frontend to show the normal software keyboard. 103 /// Signals the frontend to show the normal software keyboard.
90 void ShowNormalKeyboard(); 104 void ShowNormalKeyboard();
@@ -94,7 +108,10 @@ private:
94 std::u16string text_check_message); 108 std::u16string text_check_message);
95 109
96 /// Signals the frontend to show the inline software keyboard. 110 /// Signals the frontend to show the inline software keyboard.
97 void ShowInlineKeyboard(); 111 void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters);
112
113 void ShowInlineKeyboardOld();
114 void ShowInlineKeyboardNew();
98 115
99 /// Signals the frontend to hide the inline software keyboard. 116 /// Signals the frontend to hide the inline software keyboard.
100 void HideInlineKeyboard(); 117 void HideInlineKeyboard();
@@ -111,6 +128,8 @@ private:
111 void RequestSetUserWordInfo(const std::vector<u8>& request_data); 128 void RequestSetUserWordInfo(const std::vector<u8>& request_data);
112 void RequestSetCustomizeDic(const std::vector<u8>& request_data); 129 void RequestSetCustomizeDic(const std::vector<u8>& request_data);
113 void RequestCalc(const std::vector<u8>& request_data); 130 void RequestCalc(const std::vector<u8>& request_data);
131 void RequestCalcOld();
132 void RequestCalcNew();
114 void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data); 133 void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data);
115 void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data); 134 void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data);
116 void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data); 135 void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data);
@@ -149,7 +168,9 @@ private:
149 168
150 SwkbdState swkbd_state{SwkbdState::NotInitialized}; 169 SwkbdState swkbd_state{SwkbdState::NotInitialized};
151 SwkbdInitializeArg swkbd_initialize_arg; 170 SwkbdInitializeArg swkbd_initialize_arg;
152 SwkbdCalcArg swkbd_calc_arg; 171 SwkbdCalcArgCommon swkbd_calc_arg_common;
172 SwkbdCalcArgOld swkbd_calc_arg_old;
173 SwkbdCalcArgNew swkbd_calc_arg_new;
153 bool use_changed_string_v2{false}; 174 bool use_changed_string_v2{false};
154 bool use_moved_cursor_v2{false}; 175 bool use_moved_cursor_v2{false};
155 bool inline_use_utf8{false}; 176 bool inline_use_utf8{false};
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard_types.h b/src/core/hle/service/am/applets/applet_software_keyboard_types.h
index 21aa8e800..de1ca7aa5 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard_types.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard_types.h
@@ -10,6 +10,7 @@
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/swap.h" 12#include "common/swap.h"
13#include "common/uuid.h"
13 14
14namespace Service::AM::Applets { 15namespace Service::AM::Applets {
15 16
@@ -216,7 +217,7 @@ struct SwkbdInitializeArg {
216}; 217};
217static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size."); 218static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size.");
218 219
219struct SwkbdAppearArg { 220struct SwkbdAppearArgOld {
220 SwkbdType type{}; 221 SwkbdType type{};
221 std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{}; 222 std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
222 char16_t left_optional_symbol_key{}; 223 char16_t left_optional_symbol_key{};
@@ -229,19 +230,76 @@ struct SwkbdAppearArg {
229 bool enable_return_button{}; 230 bool enable_return_button{};
230 INSERT_PADDING_BYTES(3); 231 INSERT_PADDING_BYTES(3);
231 u32 flags{}; 232 u32 flags{};
232 INSERT_PADDING_WORDS(6); 233 bool is_use_save_data{};
234 INSERT_PADDING_BYTES(7);
235 Common::UUID user_id{};
233}; 236};
234static_assert(sizeof(SwkbdAppearArg) == 0x48, "SwkbdAppearArg has incorrect size."); 237static_assert(sizeof(SwkbdAppearArgOld) == 0x48, "SwkbdAppearArg has incorrect size.");
235 238
236struct SwkbdCalcArg { 239struct SwkbdAppearArgNew {
240 SwkbdType type{};
241 std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
242 char16_t left_optional_symbol_key{};
243 char16_t right_optional_symbol_key{};
244 bool use_prediction{};
245 bool disable_cancel_button{};
246 SwkbdKeyDisableFlags key_disable_flags{};
247 u32 max_text_length{};
248 u32 min_text_length{};
249 bool enable_return_button{};
250 INSERT_PADDING_BYTES(3);
251 u32 flags{};
252 bool is_use_save_data{};
253 INSERT_PADDING_BYTES(7);
254 Common::UUID user_id{};
255 u64 start_sampling_number{};
256 INSERT_PADDING_WORDS(8);
257};
258static_assert(sizeof(SwkbdAppearArgNew) == 0x70, "SwkbdAppearArg has incorrect size.");
259
260struct SwkbdCalcArgCommon {
237 u32 unknown{}; 261 u32 unknown{};
238 u16 calc_arg_size{}; 262 u16 calc_arg_size{};
239 INSERT_PADDING_BYTES(2); 263 INSERT_PADDING_BYTES(2);
240 SwkbdCalcArgFlags flags{}; 264 SwkbdCalcArgFlags flags{};
241 SwkbdInitializeArg initialize_arg{}; 265 SwkbdInitializeArg initialize_arg{};
266};
267static_assert(sizeof(SwkbdCalcArgCommon) == 0x18, "SwkbdCalcArgCommon has incorrect size.");
268
269struct SwkbdCalcArgOld {
270 f32 volume{};
271 s32 cursor_position{};
272 SwkbdAppearArgOld appear_arg{};
273 std::array<char16_t, 0x1FA> input_text{};
274 bool utf8_mode{};
275 INSERT_PADDING_BYTES(1);
276 bool enable_backspace_button{};
277 INSERT_PADDING_BYTES(3);
278 bool key_top_as_floating{};
279 bool footer_scalable{};
280 bool alpha_enabled_in_input_mode{};
281 u8 input_mode_fade_type{};
282 bool disable_touch{};
283 bool disable_hardware_keyboard{};
284 INSERT_PADDING_BYTES(8);
285 f32 key_top_scale_x{};
286 f32 key_top_scale_y{};
287 f32 key_top_translate_x{};
288 f32 key_top_translate_y{};
289 f32 key_top_bg_alpha{};
290 f32 footer_bg_alpha{};
291 f32 balloon_scale{};
292 INSERT_PADDING_WORDS(4);
293 u8 se_group{};
294 INSERT_PADDING_BYTES(3);
295};
296static_assert(sizeof(SwkbdCalcArgOld) == 0x4A0 - sizeof(SwkbdCalcArgCommon),
297 "SwkbdCalcArgOld has incorrect size.");
298
299struct SwkbdCalcArgNew {
300 SwkbdAppearArgNew appear_arg{};
242 f32 volume{}; 301 f32 volume{};
243 s32 cursor_position{}; 302 s32 cursor_position{};
244 SwkbdAppearArg appear_arg{};
245 std::array<char16_t, 0x1FA> input_text{}; 303 std::array<char16_t, 0x1FA> input_text{};
246 bool utf8_mode{}; 304 bool utf8_mode{};
247 INSERT_PADDING_BYTES(1); 305 INSERT_PADDING_BYTES(1);
@@ -264,8 +322,10 @@ struct SwkbdCalcArg {
264 INSERT_PADDING_WORDS(4); 322 INSERT_PADDING_WORDS(4);
265 u8 se_group{}; 323 u8 se_group{};
266 INSERT_PADDING_BYTES(3); 324 INSERT_PADDING_BYTES(3);
325 INSERT_PADDING_WORDS(8);
267}; 326};
268static_assert(sizeof(SwkbdCalcArg) == 0x4A0, "SwkbdCalcArg has incorrect size."); 327static_assert(sizeof(SwkbdCalcArgNew) == 0x4E8 - sizeof(SwkbdCalcArgCommon),
328 "SwkbdCalcArgNew has incorrect size.");
269 329
270struct SwkbdChangedStringArg { 330struct SwkbdChangedStringArg {
271 u32 text_length{}; 331 u32 text_length{};
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 79e62679d..1f4c9786a 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -9,7 +9,7 @@
9#include "core/frontend/applets/controller.h" 9#include "core/frontend/applets/controller.h"
10#include "core/frontend/applets/error.h" 10#include "core/frontend/applets/error.h"
11#include "core/frontend/applets/general_frontend.h" 11#include "core/frontend/applets/general_frontend.h"
12#include "core/frontend/applets/mii.h" 12#include "core/frontend/applets/mii_edit.h"
13#include "core/frontend/applets/profile_select.h" 13#include "core/frontend/applets/profile_select.h"
14#include "core/frontend/applets/software_keyboard.h" 14#include "core/frontend/applets/software_keyboard.h"
15#include "core/frontend/applets/web_browser.h" 15#include "core/frontend/applets/web_browser.h"
@@ -20,7 +20,7 @@
20#include "core/hle/service/am/applets/applet_controller.h" 20#include "core/hle/service/am/applets/applet_controller.h"
21#include "core/hle/service/am/applets/applet_error.h" 21#include "core/hle/service/am/applets/applet_error.h"
22#include "core/hle/service/am/applets/applet_general_backend.h" 22#include "core/hle/service/am/applets/applet_general_backend.h"
23#include "core/hle/service/am/applets/applet_mii.h" 23#include "core/hle/service/am/applets/applet_mii_edit.h"
24#include "core/hle/service/am/applets/applet_profile_select.h" 24#include "core/hle/service/am/applets/applet_profile_select.h"
25#include "core/hle/service/am/applets/applet_software_keyboard.h" 25#include "core/hle/service/am/applets/applet_software_keyboard.h"
26#include "core/hle/service/am/applets/applet_web_browser.h" 26#include "core/hle/service/am/applets/applet_web_browser.h"
@@ -173,12 +173,12 @@ void Applet::Initialize() {
173AppletFrontendSet::AppletFrontendSet() = default; 173AppletFrontendSet::AppletFrontendSet() = default;
174 174
175AppletFrontendSet::AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet, 175AppletFrontendSet::AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet,
176 MiiEdit mii_edit_,
176 ParentalControlsApplet parental_controls_applet, 177 ParentalControlsApplet parental_controls_applet,
177 MiiApplet mii_applet, PhotoViewer photo_viewer_, 178 PhotoViewer photo_viewer_, ProfileSelect profile_select_,
178 ProfileSelect profile_select_,
179 SoftwareKeyboard software_keyboard_, WebBrowser web_browser_) 179 SoftwareKeyboard software_keyboard_, WebBrowser web_browser_)
180 : controller{std::move(controller_applet)}, error{std::move(error_applet)}, 180 : controller{std::move(controller_applet)}, error{std::move(error_applet)},
181 parental_controls{std::move(parental_controls_applet)}, mii{std::move(mii_applet)}, 181 mii_edit{std::move(mii_edit_)}, parental_controls{std::move(parental_controls_applet)},
182 photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)}, 182 photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)},
183 software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {} 183 software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {}
184 184
@@ -205,12 +205,12 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
205 frontend.error = std::move(set.error); 205 frontend.error = std::move(set.error);
206 } 206 }
207 207
208 if (set.parental_controls != nullptr) { 208 if (set.mii_edit != nullptr) {
209 frontend.parental_controls = std::move(set.parental_controls); 209 frontend.mii_edit = std::move(set.mii_edit);
210 } 210 }
211 211
212 if (set.mii != nullptr) { 212 if (set.parental_controls != nullptr) {
213 frontend.mii = std::move(set.mii); 213 frontend.parental_controls = std::move(set.parental_controls);
214 } 214 }
215 215
216 if (set.photo_viewer != nullptr) { 216 if (set.photo_viewer != nullptr) {
@@ -245,15 +245,15 @@ void AppletManager::SetDefaultAppletsIfMissing() {
245 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>(); 245 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
246 } 246 }
247 247
248 if (frontend.mii_edit == nullptr) {
249 frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>();
250 }
251
248 if (frontend.parental_controls == nullptr) { 252 if (frontend.parental_controls == nullptr) {
249 frontend.parental_controls = 253 frontend.parental_controls =
250 std::make_unique<Core::Frontend::DefaultParentalControlsApplet>(); 254 std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
251 } 255 }
252 256
253 if (frontend.mii == nullptr) {
254 frontend.mii = std::make_unique<Core::Frontend::DefaultMiiApplet>();
255 }
256
257 if (frontend.photo_viewer == nullptr) { 257 if (frontend.photo_viewer == nullptr) {
258 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>(); 258 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
259 } 259 }
@@ -289,7 +289,7 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode
289 case AppletId::SoftwareKeyboard: 289 case AppletId::SoftwareKeyboard:
290 return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard); 290 return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
291 case AppletId::MiiEdit: 291 case AppletId::MiiEdit:
292 return std::make_shared<Mii>(system, mode, *frontend.mii); 292 return std::make_shared<MiiEdit>(system, mode, *frontend.mii_edit);
293 case AppletId::Web: 293 case AppletId::Web:
294 case AppletId::Shop: 294 case AppletId::Shop:
295 case AppletId::OfflineWeb: 295 case AppletId::OfflineWeb:
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 0c44aec79..50a7bdceb 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -20,8 +20,8 @@ namespace Core::Frontend {
20class ControllerApplet; 20class ControllerApplet;
21class ECommerceApplet; 21class ECommerceApplet;
22class ErrorApplet; 22class ErrorApplet;
23class MiiEditApplet;
23class ParentalControlsApplet; 24class ParentalControlsApplet;
24class MiiApplet;
25class PhotoViewerApplet; 25class PhotoViewerApplet;
26class ProfileSelectApplet; 26class ProfileSelectApplet;
27class SoftwareKeyboardApplet; 27class SoftwareKeyboardApplet;
@@ -179,8 +179,8 @@ protected:
179struct AppletFrontendSet { 179struct AppletFrontendSet {
180 using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>; 180 using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>;
181 using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; 181 using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>;
182 using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>;
182 using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>; 183 using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>;
183 using MiiApplet = std::unique_ptr<Core::Frontend::MiiApplet>;
184 using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; 184 using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>;
185 using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; 185 using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>;
186 using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; 186 using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>;
@@ -188,7 +188,7 @@ struct AppletFrontendSet {
188 188
189 AppletFrontendSet(); 189 AppletFrontendSet();
190 AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet, 190 AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet,
191 ParentalControlsApplet parental_controls_applet, MiiApplet mii_applet, 191 MiiEdit mii_edit_, ParentalControlsApplet parental_controls_applet,
192 PhotoViewer photo_viewer_, ProfileSelect profile_select_, 192 PhotoViewer photo_viewer_, ProfileSelect profile_select_,
193 SoftwareKeyboard software_keyboard_, WebBrowser web_browser_); 193 SoftwareKeyboard software_keyboard_, WebBrowser web_browser_);
194 ~AppletFrontendSet(); 194 ~AppletFrontendSet();
@@ -201,8 +201,8 @@ struct AppletFrontendSet {
201 201
202 ControllerApplet controller; 202 ControllerApplet controller;
203 ErrorApplet error; 203 ErrorApplet error;
204 MiiEdit mii_edit;
204 ParentalControlsApplet parental_controls; 205 ParentalControlsApplet parental_controls;
205 MiiApplet mii;
206 PhotoViewer photo_viewer; 206 PhotoViewer photo_viewer;
207 ProfileSelect profile_select; 207 ProfileSelect profile_select;
208 SoftwareKeyboard software_keyboard; 208 SoftwareKeyboard software_keyboard;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index a727b3582..8450eaf93 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/settings.h"
6#include "core/core_timing.h" 5#include "core/core_timing.h"
7#include "core/hid/emulated_console.h" 6#include "core/hid/emulated_console.h"
8#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 26d153f0c..93454585a 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -8,7 +8,6 @@
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/quaternion.h" 10#include "common/quaternion.h"
11#include "core/hid/hid_types.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 11#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h" 12#include "core/hle/service/hid/ring_lifo.h"
14 13
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 7450eb20a..5e464149c 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/swap.h"
9 8
10namespace Core::Timing { 9namespace Core::Timing {
11class CoreTiming; 10class CoreTiming;
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index afe374fc2..4396780a1 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -4,11 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include "common/bit_field.h" 7#include "common/bit_field.h"
9#include "common/common_funcs.h"
10#include "common/common_types.h" 8#include "common/common_types.h"
11#include "common/swap.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h" 10#include "core/hle/service/hid/ring_lifo.h"
14 11
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index cf62d3896..b869352b9 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -4,11 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include "common/bit_field.h"
9#include "common/common_funcs.h"
10#include "common/common_types.h" 7#include "common/common_types.h"
11#include "common/swap.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 8#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h" 9#include "core/hle/service/hid/ring_lifo.h"
14 10
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 7559fc78d..8858887b2 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -4,10 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include "common/bit_field.h"
9#include "common/common_types.h" 7#include "common/common_types.h"
10#include "common/swap.h"
11#include "core/hle/service/hid/controllers/controller_base.h" 8#include "core/hle/service/hid/controllers/controller_base.h"
12#include "core/hle/service/hid/ring_lifo.h" 9#include "core/hle/service/hid/ring_lifo.h"
13 10
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 6b2872bad..3287cf435 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -10,7 +10,8 @@
10 10
11#include "common/bit_field.h" 11#include "common/bit_field.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/quaternion.h" 13#include "common/vector_math.h"
14
14#include "core/hid/hid_types.h" 15#include "core/hid/hid_types.h"
15#include "core/hle/service/hid/controllers/controller_base.h" 16#include "core/hle/service/hid/controllers/controller_base.h"
16#include "core/hle/service/hid/ring_lifo.h" 17#include "core/hle/service/hid/ring_lifo.h"
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 48978e5c6..65b799e78 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h"
9#include "common/settings.h" 8#include "common/settings.h"
10#include "core/core.h" 9#include "core/core.h"
11#include "core/core_timing.h" 10#include "core/core_timing.h"
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 708dde4f0..483552767 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -4,11 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/bit_field.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/point.h"
11#include "common/swap.h"
12#include "core/hid/hid_types.h" 9#include "core/hid/hid_types.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 10#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/hle/service/hid/ring_lifo.h" 11#include "core/hle/service/hid/ring_lifo.h"
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index ba8db8d9d..4973e1bd9 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "common/bit_field.h" 7#include "common/bit_field.h"
8#include "common/common_funcs.h"
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/swap.h"
11#include "core/hid/hid_types.h" 9#include "core/hid/hid_types.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 10#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h" 11#include "core/hle/service/hid/ring_lifo.h"
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index d9202ea6c..b2cec2253 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -878,6 +878,10 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
878 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", 878 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
879 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); 879 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
880 880
881 // Games expect this event to be signaled after calling this function
882 applet_resource->GetController<Controller_NPad>(HidController::NPad)
883 .SignalStyleSetChangedEvent(parameters.npad_id);
884
881 IPC::ResponseBuilder rb{ctx, 2, 1}; 885 IPC::ResponseBuilder rb{ctx, 2, 1};
882 rb.Push(ResultSuccess); 886 rb.Push(ResultSuccess);
883 rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) 887 rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 099276420..2477c5612 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -12,7 +12,6 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/k_page_table.h" 14#include "core/hle/kernel/k_page_table.h"
15#include "core/hle/kernel/k_system_control.h"
16#include "core/hle/kernel/svc_results.h" 15#include "core/hle/kernel/svc_results.h"
17#include "core/hle/kernel/svc_types.h" 16#include "core/hle/kernel/svc_types.h"
18#include "core/hle/service/ldr/ldr.h" 17#include "core/hle/service/ldr/ldr.h"
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 0a57c3cde..188231615 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -1,4 +1,4 @@
1// Copyright 2020 yuzu emulator team 1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -12,7 +12,6 @@
12#include "core/hle/service/acc/profile_manager.h" 12#include "core/hle/service/acc/profile_manager.h"
13#include "core/hle/service/mii/mii_manager.h" 13#include "core/hle/service/mii/mii_manager.h"
14#include "core/hle/service/mii/raw_data.h" 14#include "core/hle/service/mii/raw_data.h"
15#include "core/hle/service/mii/types.h"
16 15
17namespace Service::Mii { 16namespace Service::Mii {
18 17
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index 6999d15b1..5d134c425 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -1,315 +1,16 @@
1// Copyright 2020 yuzu emulator team 1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <vector> 7#include <vector>
9#include "common/bit_field.h" 8
10#include "common/common_funcs.h"
11#include "common/uuid.h"
12#include "core/hle/result.h" 9#include "core/hle/result.h"
13#include "core/hle/service/mii/types.h" 10#include "core/hle/service/mii/types.h"
14 11
15namespace Service::Mii { 12namespace Service::Mii {
16 13
17enum class Source : u32 {
18 Database = 0,
19 Default = 1,
20 Account = 2,
21 Friend = 3,
22};
23
24enum class SourceFlag : u32 {
25 None = 0,
26 Database = 1 << 0,
27 Default = 1 << 1,
28};
29DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
30
31struct MiiInfo {
32 Common::UUID uuid;
33 std::array<char16_t, 11> name;
34 u8 font_region;
35 u8 favorite_color;
36 u8 gender;
37 u8 height;
38 u8 build;
39 u8 type;
40 u8 region_move;
41 u8 faceline_type;
42 u8 faceline_color;
43 u8 faceline_wrinkle;
44 u8 faceline_make;
45 u8 hair_type;
46 u8 hair_color;
47 u8 hair_flip;
48 u8 eye_type;
49 u8 eye_color;
50 u8 eye_scale;
51 u8 eye_aspect;
52 u8 eye_rotate;
53 u8 eye_x;
54 u8 eye_y;
55 u8 eyebrow_type;
56 u8 eyebrow_color;
57 u8 eyebrow_scale;
58 u8 eyebrow_aspect;
59 u8 eyebrow_rotate;
60 u8 eyebrow_x;
61 u8 eyebrow_y;
62 u8 nose_type;
63 u8 nose_scale;
64 u8 nose_y;
65 u8 mouth_type;
66 u8 mouth_color;
67 u8 mouth_scale;
68 u8 mouth_aspect;
69 u8 mouth_y;
70 u8 beard_color;
71 u8 beard_type;
72 u8 mustache_type;
73 u8 mustache_scale;
74 u8 mustache_y;
75 u8 glasses_type;
76 u8 glasses_color;
77 u8 glasses_scale;
78 u8 glasses_y;
79 u8 mole_type;
80 u8 mole_scale;
81 u8 mole_x;
82 u8 mole_y;
83 u8 padding;
84
85 std::u16string Name() const;
86};
87static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
88static_assert(std::has_unique_object_representations_v<MiiInfo>,
89 "All bits of MiiInfo must contribute to its value.");
90
91#pragma pack(push, 4)
92
93struct MiiInfoElement {
94 MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {}
95
96 MiiInfo info{};
97 Source source{};
98};
99static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
100
101struct MiiStoreBitFields {
102 union {
103 u32 word_0{};
104
105 BitField<0, 8, u32> hair_type;
106 BitField<8, 7, u32> height;
107 BitField<15, 1, u32> mole_type;
108 BitField<16, 7, u32> build;
109 BitField<23, 1, HairFlip> hair_flip;
110 BitField<24, 7, u32> hair_color;
111 BitField<31, 1, u32> type;
112 };
113
114 union {
115 u32 word_1{};
116
117 BitField<0, 7, u32> eye_color;
118 BitField<7, 1, Gender> gender;
119 BitField<8, 7, u32> eyebrow_color;
120 BitField<16, 7, u32> mouth_color;
121 BitField<24, 7, u32> beard_color;
122 };
123
124 union {
125 u32 word_2{};
126
127 BitField<0, 7, u32> glasses_color;
128 BitField<8, 6, u32> eye_type;
129 BitField<14, 2, u32> region_move;
130 BitField<16, 6, u32> mouth_type;
131 BitField<22, 2, FontRegion> font_region;
132 BitField<24, 5, u32> eye_y;
133 BitField<29, 3, u32> glasses_scale;
134 };
135
136 union {
137 u32 word_3{};
138
139 BitField<0, 5, u32> eyebrow_type;
140 BitField<5, 3, MustacheType> mustache_type;
141 BitField<8, 5, u32> nose_type;
142 BitField<13, 3, BeardType> beard_type;
143 BitField<16, 5, u32> nose_y;
144 BitField<21, 3, u32> mouth_aspect;
145 BitField<24, 5, u32> mouth_y;
146 BitField<29, 3, u32> eyebrow_aspect;
147 };
148
149 union {
150 u32 word_4{};
151
152 BitField<0, 5, u32> mustache_y;
153 BitField<5, 3, u32> eye_rotate;
154 BitField<8, 5, u32> glasses_y;
155 BitField<13, 3, u32> eye_aspect;
156 BitField<16, 5, u32> mole_x;
157 BitField<21, 3, u32> eye_scale;
158 BitField<24, 5, u32> mole_y;
159 };
160
161 union {
162 u32 word_5{};
163
164 BitField<0, 5, u32> glasses_type;
165 BitField<8, 4, u32> favorite_color;
166 BitField<12, 4, u32> faceline_type;
167 BitField<16, 4, u32> faceline_color;
168 BitField<20, 4, u32> faceline_wrinkle;
169 BitField<24, 4, u32> faceline_makeup;
170 BitField<28, 4, u32> eye_x;
171 };
172
173 union {
174 u32 word_6{};
175
176 BitField<0, 4, u32> eyebrow_scale;
177 BitField<4, 4, u32> eyebrow_rotate;
178 BitField<8, 4, u32> eyebrow_x;
179 BitField<12, 4, u32> eyebrow_y;
180 BitField<16, 4, u32> nose_scale;
181 BitField<20, 4, u32> mouth_scale;
182 BitField<24, 4, u32> mustache_scale;
183 BitField<28, 4, u32> mole_scale;
184 };
185};
186static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
187static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
188 "MiiStoreBitFields is not trivially copyable.");
189
190struct MiiStoreData {
191 using Name = std::array<char16_t, 10>;
192
193 MiiStoreData();
194 MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
195 const Common::UUID& user_id);
196
197 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
198 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
199 // not suitable for our uses.
200 struct {
201 std::array<u8, 0x1C> data{};
202 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
203
204 Name name{};
205 Common::UUID uuid{};
206 } data;
207
208 u16 data_crc{};
209 u16 device_crc{};
210};
211static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
212
213struct MiiStoreDataElement {
214 MiiStoreData data{};
215 Source source{};
216};
217static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
218
219struct MiiDatabase {
220 u32 magic{}; // 'NFDB'
221 std::array<MiiStoreData, 0x64> miis{};
222 INSERT_PADDING_BYTES(1);
223 u8 count{};
224 u16 crc{};
225};
226static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
227
228struct RandomMiiValues {
229 std::array<u8, 0xbc> values{};
230};
231static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
232
233struct RandomMiiData4 {
234 Gender gender{};
235 Age age{};
236 Race race{};
237 u32 values_count{};
238 std::array<u32, 47> values{};
239};
240static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
241
242struct RandomMiiData3 {
243 u32 arg_1;
244 u32 arg_2;
245 u32 values_count;
246 std::array<u32, 47> values{};
247};
248static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
249
250struct RandomMiiData2 {
251 u32 arg_1;
252 u32 values_count;
253 std::array<u32, 47> values{};
254};
255static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
256
257struct DefaultMii {
258 u32 face_type{};
259 u32 face_color{};
260 u32 face_wrinkle{};
261 u32 face_makeup{};
262 u32 hair_type{};
263 u32 hair_color{};
264 u32 hair_flip{};
265 u32 eye_type{};
266 u32 eye_color{};
267 u32 eye_scale{};
268 u32 eye_aspect{};
269 u32 eye_rotate{};
270 u32 eye_x{};
271 u32 eye_y{};
272 u32 eyebrow_type{};
273 u32 eyebrow_color{};
274 u32 eyebrow_scale{};
275 u32 eyebrow_aspect{};
276 u32 eyebrow_rotate{};
277 u32 eyebrow_x{};
278 u32 eyebrow_y{};
279 u32 nose_type{};
280 u32 nose_scale{};
281 u32 nose_y{};
282 u32 mouth_type{};
283 u32 mouth_color{};
284 u32 mouth_scale{};
285 u32 mouth_aspect{};
286 u32 mouth_y{};
287 u32 mustache_type{};
288 u32 beard_type{};
289 u32 beard_color{};
290 u32 mustache_scale{};
291 u32 mustache_y{};
292 u32 glasses_type{};
293 u32 glasses_color{};
294 u32 glasses_scale{};
295 u32 glasses_y{};
296 u32 mole_type{};
297 u32 mole_scale{};
298 u32 mole_x{};
299 u32 mole_y{};
300 u32 height{};
301 u32 weight{};
302 Gender gender{};
303 u32 favorite_color{};
304 u32 region{};
305 FontRegion font_region{};
306 u32 type{};
307 INSERT_PADDING_WORDS(5);
308};
309static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
310
311#pragma pack(pop)
312
313// The Mii manager is responsible for loading and storing the Miis to the database in NAND along 14// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
314// with providing an easy interface for HLE emulation of the mii service. 15// with providing an easy interface for HLE emulation of the mii service.
315class MiiManager { 16class MiiManager {
diff --git a/src/core/hle/service/mii/raw_data.h b/src/core/hle/service/mii/raw_data.h
index bd90c2162..2e39c0d4f 100644
--- a/src/core/hle/service/mii/raw_data.h
+++ b/src/core/hle/service/mii/raw_data.h
@@ -6,7 +6,7 @@
6 6
7#include <array> 7#include <array>
8 8
9#include "core/hle/service/mii/mii_manager.h" 9#include "core/hle/service/mii/types.h"
10 10
11namespace Service::Mii::RawData { 11namespace Service::Mii::RawData {
12 12
diff --git a/src/core/hle/service/mii/types.h b/src/core/hle/service/mii/types.h
index d65a1055e..5580b8c6a 100644
--- a/src/core/hle/service/mii/types.h
+++ b/src/core/hle/service/mii/types.h
@@ -1,11 +1,16 @@
1// Copyright 2020 yuzu emulator team 1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <type_traits>
9
10#include "common/bit_field.h"
7#include "common/common_funcs.h" 11#include "common/common_funcs.h"
8#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/uuid.h"
9 14
10namespace Service::Mii { 15namespace Service::Mii {
11 16
@@ -25,7 +30,11 @@ enum class BeardType : u32 {
25 Beard5, 30 Beard5,
26}; 31};
27 32
28enum class BeardAndMustacheFlag : u32 { Beard = 1, Mustache, All = Beard | Mustache }; 33enum class BeardAndMustacheFlag : u32 {
34 Beard = 1,
35 Mustache,
36 All = Beard | Mustache,
37};
29DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag); 38DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
30 39
31enum class FontRegion : u32 { 40enum class FontRegion : u32 {
@@ -64,4 +73,298 @@ enum class Race : u32 {
64 All, 73 All,
65}; 74};
66 75
76enum class Source : u32 {
77 Database = 0,
78 Default = 1,
79 Account = 2,
80 Friend = 3,
81};
82
83enum class SourceFlag : u32 {
84 None = 0,
85 Database = 1 << 0,
86 Default = 1 << 1,
87};
88DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
89
90struct MiiInfo {
91 Common::UUID uuid;
92 std::array<char16_t, 11> name;
93 u8 font_region;
94 u8 favorite_color;
95 u8 gender;
96 u8 height;
97 u8 build;
98 u8 type;
99 u8 region_move;
100 u8 faceline_type;
101 u8 faceline_color;
102 u8 faceline_wrinkle;
103 u8 faceline_make;
104 u8 hair_type;
105 u8 hair_color;
106 u8 hair_flip;
107 u8 eye_type;
108 u8 eye_color;
109 u8 eye_scale;
110 u8 eye_aspect;
111 u8 eye_rotate;
112 u8 eye_x;
113 u8 eye_y;
114 u8 eyebrow_type;
115 u8 eyebrow_color;
116 u8 eyebrow_scale;
117 u8 eyebrow_aspect;
118 u8 eyebrow_rotate;
119 u8 eyebrow_x;
120 u8 eyebrow_y;
121 u8 nose_type;
122 u8 nose_scale;
123 u8 nose_y;
124 u8 mouth_type;
125 u8 mouth_color;
126 u8 mouth_scale;
127 u8 mouth_aspect;
128 u8 mouth_y;
129 u8 beard_color;
130 u8 beard_type;
131 u8 mustache_type;
132 u8 mustache_scale;
133 u8 mustache_y;
134 u8 glasses_type;
135 u8 glasses_color;
136 u8 glasses_scale;
137 u8 glasses_y;
138 u8 mole_type;
139 u8 mole_scale;
140 u8 mole_x;
141 u8 mole_y;
142 u8 padding;
143};
144static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
145static_assert(std::has_unique_object_representations_v<MiiInfo>,
146 "All bits of MiiInfo must contribute to its value.");
147
148#pragma pack(push, 4)
149
150struct MiiInfoElement {
151 MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {}
152
153 MiiInfo info{};
154 Source source{};
155};
156static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
157
158struct MiiStoreBitFields {
159 union {
160 u32 word_0{};
161
162 BitField<0, 8, u32> hair_type;
163 BitField<8, 7, u32> height;
164 BitField<15, 1, u32> mole_type;
165 BitField<16, 7, u32> build;
166 BitField<23, 1, HairFlip> hair_flip;
167 BitField<24, 7, u32> hair_color;
168 BitField<31, 1, u32> type;
169 };
170
171 union {
172 u32 word_1{};
173
174 BitField<0, 7, u32> eye_color;
175 BitField<7, 1, Gender> gender;
176 BitField<8, 7, u32> eyebrow_color;
177 BitField<16, 7, u32> mouth_color;
178 BitField<24, 7, u32> beard_color;
179 };
180
181 union {
182 u32 word_2{};
183
184 BitField<0, 7, u32> glasses_color;
185 BitField<8, 6, u32> eye_type;
186 BitField<14, 2, u32> region_move;
187 BitField<16, 6, u32> mouth_type;
188 BitField<22, 2, FontRegion> font_region;
189 BitField<24, 5, u32> eye_y;
190 BitField<29, 3, u32> glasses_scale;
191 };
192
193 union {
194 u32 word_3{};
195
196 BitField<0, 5, u32> eyebrow_type;
197 BitField<5, 3, MustacheType> mustache_type;
198 BitField<8, 5, u32> nose_type;
199 BitField<13, 3, BeardType> beard_type;
200 BitField<16, 5, u32> nose_y;
201 BitField<21, 3, u32> mouth_aspect;
202 BitField<24, 5, u32> mouth_y;
203 BitField<29, 3, u32> eyebrow_aspect;
204 };
205
206 union {
207 u32 word_4{};
208
209 BitField<0, 5, u32> mustache_y;
210 BitField<5, 3, u32> eye_rotate;
211 BitField<8, 5, u32> glasses_y;
212 BitField<13, 3, u32> eye_aspect;
213 BitField<16, 5, u32> mole_x;
214 BitField<21, 3, u32> eye_scale;
215 BitField<24, 5, u32> mole_y;
216 };
217
218 union {
219 u32 word_5{};
220
221 BitField<0, 5, u32> glasses_type;
222 BitField<8, 4, u32> favorite_color;
223 BitField<12, 4, u32> faceline_type;
224 BitField<16, 4, u32> faceline_color;
225 BitField<20, 4, u32> faceline_wrinkle;
226 BitField<24, 4, u32> faceline_makeup;
227 BitField<28, 4, u32> eye_x;
228 };
229
230 union {
231 u32 word_6{};
232
233 BitField<0, 4, u32> eyebrow_scale;
234 BitField<4, 4, u32> eyebrow_rotate;
235 BitField<8, 4, u32> eyebrow_x;
236 BitField<12, 4, u32> eyebrow_y;
237 BitField<16, 4, u32> nose_scale;
238 BitField<20, 4, u32> mouth_scale;
239 BitField<24, 4, u32> mustache_scale;
240 BitField<28, 4, u32> mole_scale;
241 };
242};
243static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
244static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
245 "MiiStoreBitFields is not trivially copyable.");
246
247struct MiiStoreData {
248 using Name = std::array<char16_t, 10>;
249
250 MiiStoreData();
251 MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
252 const Common::UUID& user_id);
253
254 // This corresponds to the above structure MiiStoreBitFields. I did it like this because the
255 // BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
256 // not suitable for our uses.
257 struct {
258 std::array<u8, 0x1C> data{};
259 static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
260
261 Name name{};
262 Common::UUID uuid{};
263 } data;
264
265 u16 data_crc{};
266 u16 device_crc{};
267};
268static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
269
270struct MiiStoreDataElement {
271 MiiStoreData data{};
272 Source source{};
273};
274static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
275
276struct MiiDatabase {
277 u32 magic{}; // 'NFDB'
278 std::array<MiiStoreData, 0x64> miis{};
279 INSERT_PADDING_BYTES(1);
280 u8 count{};
281 u16 crc{};
282};
283static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
284
285struct RandomMiiValues {
286 std::array<u8, 0xbc> values{};
287};
288static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
289
290struct RandomMiiData4 {
291 Gender gender{};
292 Age age{};
293 Race race{};
294 u32 values_count{};
295 std::array<u32, 47> values{};
296};
297static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
298
299struct RandomMiiData3 {
300 u32 arg_1;
301 u32 arg_2;
302 u32 values_count;
303 std::array<u32, 47> values{};
304};
305static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
306
307struct RandomMiiData2 {
308 u32 arg_1;
309 u32 values_count;
310 std::array<u32, 47> values{};
311};
312static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
313
314struct DefaultMii {
315 u32 face_type{};
316 u32 face_color{};
317 u32 face_wrinkle{};
318 u32 face_makeup{};
319 u32 hair_type{};
320 u32 hair_color{};
321 u32 hair_flip{};
322 u32 eye_type{};
323 u32 eye_color{};
324 u32 eye_scale{};
325 u32 eye_aspect{};
326 u32 eye_rotate{};
327 u32 eye_x{};
328 u32 eye_y{};
329 u32 eyebrow_type{};
330 u32 eyebrow_color{};
331 u32 eyebrow_scale{};
332 u32 eyebrow_aspect{};
333 u32 eyebrow_rotate{};
334 u32 eyebrow_x{};
335 u32 eyebrow_y{};
336 u32 nose_type{};
337 u32 nose_scale{};
338 u32 nose_y{};
339 u32 mouth_type{};
340 u32 mouth_color{};
341 u32 mouth_scale{};
342 u32 mouth_aspect{};
343 u32 mouth_y{};
344 u32 mustache_type{};
345 u32 beard_type{};
346 u32 beard_color{};
347 u32 mustache_scale{};
348 u32 mustache_y{};
349 u32 glasses_type{};
350 u32 glasses_color{};
351 u32 glasses_scale{};
352 u32 glasses_y{};
353 u32 mole_type{};
354 u32 mole_scale{};
355 u32 mole_x{};
356 u32 mole_y{};
357 u32 height{};
358 u32 weight{};
359 Gender gender{};
360 u32 favorite_color{};
361 u32 region{};
362 FontRegion font_region{};
363 u32 type{};
364 INSERT_PADDING_WORDS(5);
365};
366static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
367
368#pragma pack(pop)
369
67} // namespace Service::Mii 370} // namespace Service::Mii
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 513107715..dab99b675 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -12,6 +12,7 @@
12#include "core/hid/hid_types.h" 12#include "core/hid/hid_types.h"
13#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/k_event.h" 14#include "core/hle/kernel/k_event.h"
15#include "core/hle/service/mii/mii_manager.h"
15#include "core/hle/service/nfp/nfp.h" 16#include "core/hle/service/nfp/nfp.h"
16#include "core/hle/service/nfp/nfp_user.h" 17#include "core/hle/service/nfp/nfp_user.h"
17 18
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 022f13b29..ab652f635 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -9,7 +9,7 @@
9 9
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "core/hle/service/kernel_helpers.h" 11#include "core/hle/service/kernel_helpers.h"
12#include "core/hle/service/mii/mii_manager.h" 12#include "core/hle/service/mii/types.h"
13#include "core/hle/service/service.h" 13#include "core/hle/service/service.h"
14 14
15namespace Kernel { 15namespace Kernel {
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index a253dd066..edb576ad3 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -5,7 +5,6 @@
5#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/service/kernel_helpers.h" 8#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/nifm/nifm.h" 9#include "core/hle/service/nifm/nifm.h"
11#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp
index 36ce46353..3a83d0698 100644
--- a/src/core/hle/service/ns/pdm_qry.cpp
+++ b/src/core/hle/service/ns/pdm_qry.cpp
@@ -9,7 +9,6 @@
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/service/ns/pdm_qry.h" 10#include "core/hle/service/ns/pdm_qry.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12#include "core/hle/service/sm/sm.h"
13 12
14namespace Service::NS { 13namespace Service::NS {
15 14
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 68f1e9060..9fad45fe1 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -38,18 +38,16 @@ NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>&
38void nvdisp_disp0::OnOpen(DeviceFD fd) {} 38void nvdisp_disp0::OnOpen(DeviceFD fd) {}
39void nvdisp_disp0::OnClose(DeviceFD fd) {} 39void nvdisp_disp0::OnClose(DeviceFD fd) {}
40 40
41void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, 41void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width,
42 u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform, 42 u32 height, u32 stride, android::BufferTransformFlags transform,
43 const Common::Rectangle<int>& crop_rect) { 43 const Common::Rectangle<int>& crop_rect) {
44 const VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); 44 const VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
45 LOG_TRACE(Service, 45 LOG_TRACE(Service,
46 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", 46 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
47 addr, offset, width, height, stride, format); 47 addr, offset, width, height, stride, format);
48 48
49 const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format); 49 const Tegra::FramebufferConfig framebuffer{addr, offset, width, height,
50 const auto transform_flags = static_cast<Tegra::FramebufferConfig::TransformFlags>(transform); 50 stride, format, transform, crop_rect};
51 const Tegra::FramebufferConfig framebuffer{addr, offset, width, height,
52 stride, pixel_format, transform_flags, crop_rect};
53 51
54 system.GetPerfStats().EndSystemFrame(); 52 system.GetPerfStats().EndSystemFrame();
55 system.GPU().SwapBuffers(&framebuffer); 53 system.GPU().SwapBuffers(&framebuffer);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index de01e1d5f..30b5da429 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -9,7 +9,8 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/math_util.h" 10#include "common/math_util.h"
11#include "core/hle/service/nvdrv/devices/nvdevice.h" 11#include "core/hle/service/nvdrv/devices/nvdevice.h"
12#include "core/hle/service/nvflinger/buffer_queue.h" 12#include "core/hle/service/nvflinger/buffer_transform_flags.h"
13#include "core/hle/service/nvflinger/pixel_format.h"
13 14
14namespace Service::Nvidia::Devices { 15namespace Service::Nvidia::Devices {
15 16
@@ -31,8 +32,8 @@ public:
31 void OnClose(DeviceFD fd) override; 32 void OnClose(DeviceFD fd) override;
32 33
33 /// Performs a screen flip, drawing the buffer pointed to by the handle. 34 /// Performs a screen flip, drawing the buffer pointed to by the handle.
34 void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, 35 void flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, u32 height,
35 NVFlinger::BufferQueue::BufferTransformFlags transform, 36 u32 stride, android::BufferTransformFlags transform,
36 const Common::Rectangle<int>& crop_rect); 37 const Common::Rectangle<int>& crop_rect);
37 38
38private: 39private:
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index f9b82b504..44c54c665 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -134,7 +134,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
134 } 134 }
135 135
136 EventState status = events_interface.status[event_id]; 136 EventState status = events_interface.status[event_id];
137 const bool bad_parameter = status != EventState::Free && status != EventState::Registered; 137 const bool bad_parameter = status == EventState::Busy;
138 if (bad_parameter) { 138 if (bad_parameter) {
139 std::memcpy(output.data(), &params, sizeof(params)); 139 std::memcpy(output.data(), &params, sizeof(params));
140 return NvResult::BadParameter; 140 return NvResult::BadParameter;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index 898d00a17..f434f6929 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -5,6 +5,8 @@
5#pragma once 5#pragma once
6 6
7#include <vector> 7#include <vector>
8
9#include "common/common_funcs.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
9#include "common/swap.h" 11#include "common/swap.h"
10#include "core/hle/service/nvdrv/devices/nvdevice.h" 12#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 0a043e386..dde5b1507 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -187,7 +187,7 @@ NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::ve
187 return NvResult::Success; 187 return NvResult::Success;
188} 188}
189 189
190static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) { 190static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) {
191 return { 191 return {
192 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1, 192 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1,
193 Tegra::SubmissionMode::Increasing), 193 Tegra::SubmissionMode::Increasing),
@@ -198,7 +198,8 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) {
198 }; 198 };
199} 199}
200 200
201static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(Fence fence, u32 add_increment) { 201static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence,
202 u32 add_increment) {
202 std::vector<Tegra::CommandHeader> result{ 203 std::vector<Tegra::CommandHeader> result{
203 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1, 204 Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceValue, 1,
204 Tegra::SubmissionMode::Increasing), 205 Tegra::SubmissionMode::Increasing),
@@ -213,7 +214,7 @@ static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(Fence fence,
213 return result; 214 return result;
214} 215}
215 216
216static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(Fence fence, 217static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence,
217 u32 add_increment) { 218 u32 add_increment) {
218 std::vector<Tegra::CommandHeader> result{ 219 std::vector<Tegra::CommandHeader> result{
219 Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForInterrupt, 1, 220 Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForInterrupt, 1,
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index f27a82bff..b2e943e45 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -7,6 +7,7 @@
7#include <memory> 7#include <memory>
8#include <vector> 8#include <vector>
9#include "common/bit_field.h" 9#include "common/bit_field.h"
10#include "common/common_funcs.h"
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "common/swap.h" 12#include "common/swap.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 13#include "core/hle/service/nvdrv/devices/nvdevice.h"
@@ -108,7 +109,7 @@ private:
108 static_assert(sizeof(IoctlGetErrorNotification) == 16, 109 static_assert(sizeof(IoctlGetErrorNotification) == 16,
109 "IoctlGetErrorNotification is incorrect size"); 110 "IoctlGetErrorNotification is incorrect size");
110 111
111 static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); 112 static_assert(sizeof(NvFence) == 8, "Fence is incorrect size");
112 113
113 struct IoctlAllocGpfifoEx { 114 struct IoctlAllocGpfifoEx {
114 u32_le num_entries{}; 115 u32_le num_entries{};
@@ -126,7 +127,7 @@ private:
126 u32_le num_entries{}; // in 127 u32_le num_entries{}; // in
127 u32_le flags{}; // in 128 u32_le flags{}; // in
128 u32_le unk0{}; // in (1 works) 129 u32_le unk0{}; // in (1 works)
129 Fence fence_out{}; // out 130 NvFence fence_out{}; // out
130 u32_le unk1{}; // in 131 u32_le unk1{}; // in
131 u32_le unk2{}; // in 132 u32_le unk2{}; // in
132 u32_le unk3{}; // in 133 u32_le unk3{}; // in
@@ -152,13 +153,13 @@ private:
152 BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt 153 BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt
153 BitField<8, 1, u32_le> increment; // increment the returned fence 154 BitField<8, 1, u32_le> increment; // increment the returned fence
154 } flags; 155 } flags;
155 Fence fence_out{}; // returned new fence object for others to wait on 156 NvFence fence_out{}; // returned new fence object for others to wait on
156 157
157 u32 AddIncrementValue() const { 158 u32 AddIncrementValue() const {
158 return flags.add_increment.Value() << 1; 159 return flags.add_increment.Value() << 1;
159 } 160 }
160 }; 161 };
161 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence), 162 static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(NvFence),
162 "IoctlSubmitGpfifo is incorrect size"); 163 "IoctlSubmitGpfifo is incorrect size");
163 164
164 struct IoctlGetWaitbase { 165 struct IoctlGetWaitbase {
@@ -193,7 +194,7 @@ private:
193 194
194 std::shared_ptr<nvmap> nvmap_dev; 195 std::shared_ptr<nvmap> nvmap_dev;
195 SyncpointManager& syncpoint_manager; 196 SyncpointManager& syncpoint_manager;
196 Fence channel_fence; 197 NvFence channel_fence;
197}; 198};
198 199
199} // namespace Service::Nvidia::Devices 200} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h
index 5ab221fc1..3069c3c80 100644
--- a/src/core/hle/service/nvdrv/nvdata.h
+++ b/src/core/hle/service/nvdrv/nvdata.h
@@ -16,17 +16,11 @@ using DeviceFD = s32;
16 16
17constexpr DeviceFD INVALID_NVDRV_FD = -1; 17constexpr DeviceFD INVALID_NVDRV_FD = -1;
18 18
19struct Fence { 19struct NvFence {
20 s32 id; 20 s32 id;
21 u32 value; 21 u32 value;
22}; 22};
23 23static_assert(sizeof(NvFence) == 8, "NvFence has wrong size");
24static_assert(sizeof(Fence) == 8, "Fence has wrong size");
25
26struct MultiFence {
27 u32 num_fences;
28 std::array<Fence, 4> fences;
29};
30 24
31enum class NvResult : u32 { 25enum class NvResult : u32 {
32 Success = 0x0, 26 Success = 0x0,
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index a5af5b785..11cf6c0d1 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -12,6 +12,7 @@
12#include "core/hle/service/kernel_helpers.h" 12#include "core/hle/service/kernel_helpers.h"
13#include "core/hle/service/nvdrv/nvdata.h" 13#include "core/hle/service/nvdrv/nvdata.h"
14#include "core/hle/service/nvdrv/syncpoint_manager.h" 14#include "core/hle/service/nvdrv/syncpoint_manager.h"
15#include "core/hle/service/nvflinger/ui/fence.h"
15#include "core/hle/service/service.h" 16#include "core/hle/service/service.h"
16 17
17namespace Core { 18namespace Core {
@@ -37,7 +38,7 @@ class nvdevice;
37/// Represents an Nvidia event 38/// Represents an Nvidia event
38struct NvEvent { 39struct NvEvent {
39 Kernel::KEvent* event{}; 40 Kernel::KEvent* event{};
40 Fence fence{}; 41 NvFence fence{};
41}; 42};
42 43
43struct EventInterface { 44struct EventInterface {
diff --git a/src/core/hle/service/nvflinger/binder.h b/src/core/hle/service/nvflinger/binder.h
new file mode 100644
index 000000000..7d0d4d819
--- /dev/null
+++ b/src/core/hle/service/nvflinger/binder.h
@@ -0,0 +1,42 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/binder/IBinder.h
6
7#pragma once
8
9#include "common/common_types.h"
10
11namespace Kernel {
12class HLERequestContext;
13class KReadableEvent;
14} // namespace Kernel
15
16namespace Service::android {
17
18enum class TransactionId {
19 RequestBuffer = 1,
20 SetBufferCount = 2,
21 DequeueBuffer = 3,
22 DetachBuffer = 4,
23 DetachNextBuffer = 5,
24 AttachBuffer = 6,
25 QueueBuffer = 7,
26 CancelBuffer = 8,
27 Query = 9,
28 Connect = 10,
29 Disconnect = 11,
30 AllocateBuffers = 13,
31 SetPreallocatedBuffer = 14,
32 GetBufferHistory = 17,
33};
34
35class IBinder {
36public:
37 virtual void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code,
38 u32 flags) = 0;
39 virtual Kernel::KReadableEvent& GetNativeHandle() = 0;
40};
41
42} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_item.h b/src/core/hle/service/nvflinger/buffer_item.h
new file mode 100644
index 000000000..64b82b851
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_item.h
@@ -0,0 +1,46 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferItem.h
6
7#pragma once
8
9#include <memory>
10
11#include "common/common_types.h"
12#include "common/math_util.h"
13#include "core/hle/service/nvflinger/ui/fence.h"
14#include "core/hle/service/nvflinger/window.h"
15
16namespace Service::android {
17
18class GraphicBuffer;
19
20class BufferItem final {
21public:
22 constexpr BufferItem() = default;
23
24 std::shared_ptr<GraphicBuffer> graphic_buffer;
25 Fence fence;
26 Common::Rectangle<s32> crop;
27 NativeWindowTransform transform{};
28 u32 scaling_mode{};
29 s64 timestamp{};
30 bool is_auto_timestamp{};
31 u64 frame_number{};
32
33 // The default value for buf, used to indicate this doesn't correspond to a slot.
34 static constexpr s32 INVALID_BUFFER_SLOT = -1;
35 union {
36 s32 slot{INVALID_BUFFER_SLOT};
37 s32 buf;
38 };
39
40 bool is_droppable{};
41 bool acquire_called{};
42 bool transform_to_display_inverse{};
43 s32 swap_interval{};
44};
45
46} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp
new file mode 100644
index 000000000..93fa1ec10
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp
@@ -0,0 +1,59 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2012 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferItemConsumer.cpp
6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "core/hle/service/nvflinger/buffer_item.h"
10#include "core/hle/service/nvflinger/buffer_item_consumer.h"
11#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
12
13namespace Service::android {
14
15BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_)
16 : ConsumerBase{std::move(consumer_)} {}
17
18Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
19 bool wait_for_fence) {
20 if (!item) {
21 return Status::BadValue;
22 }
23
24 std::scoped_lock lock(mutex);
25
26 if (const auto status = AcquireBufferLocked(item, present_when); status != Status::NoError) {
27 if (status != Status::NoBufferAvailable) {
28 LOG_ERROR(Service_NVFlinger, "Failed to acquire buffer: {}", status);
29 }
30 return status;
31 }
32
33 if (wait_for_fence) {
34 UNIMPLEMENTED();
35 }
36
37 item->graphic_buffer = slots[item->slot].graphic_buffer;
38
39 return Status::NoError;
40}
41
42Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, Fence& release_fence) {
43 std::scoped_lock lock(mutex);
44
45 if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence);
46 status != Status::NoError) {
47 LOG_ERROR(Service_NVFlinger, "Failed to add fence: {}", status);
48 }
49
50 if (const auto status = ReleaseBufferLocked(item.buf, item.graphic_buffer);
51 status != Status::NoError) {
52 LOG_WARNING(Service_NVFlinger, "Failed to release buffer: {}", status);
53 return status;
54 }
55
56 return Status::NoError;
57}
58
59} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.h b/src/core/hle/service/nvflinger/buffer_item_consumer.h
new file mode 100644
index 000000000..536db81e2
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_item_consumer.h
@@ -0,0 +1,28 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2012 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferItemConsumer.h
6
7#pragma once
8
9#include <chrono>
10#include <memory>
11
12#include "common/common_types.h"
13#include "core/hle/service/nvflinger/consumer_base.h"
14#include "core/hle/service/nvflinger/status.h"
15
16namespace Service::android {
17
18class BufferItem;
19
20class BufferItemConsumer final : public ConsumerBase {
21public:
22 explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer);
23 Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
24 bool wait_for_fence = true);
25 Status ReleaseBuffer(const BufferItem& item, Fence& release_fence);
26};
27
28} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
deleted file mode 100644
index 5fead6d1b..000000000
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "core/core.h"
10#include "core/hle/kernel/k_writable_event.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/service/kernel_helpers.h"
13#include "core/hle/service/nvflinger/buffer_queue.h"
14
15namespace Service::NVFlinger {
16
17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
18 KernelHelpers::ServiceContext& service_context_)
19 : id(id_), layer_id(layer_id_), service_context{service_context_} {
20 buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
21}
22
23BufferQueue::~BufferQueue() {
24 service_context.CloseEvent(buffer_wait_event);
25}
26
27void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
28 ASSERT(slot < buffer_slots);
29 LOG_WARNING(Service, "Adding graphics buffer {}", slot);
30
31 {
32 std::unique_lock lock{free_buffers_mutex};
33 free_buffers.push_back(slot);
34 }
35 free_buffers_condition.notify_one();
36
37 buffers[slot] = {
38 .slot = slot,
39 .status = Buffer::Status::Free,
40 .igbp_buffer = igbp_buffer,
41 .transform = {},
42 .crop_rect = {},
43 .swap_interval = 0,
44 .multi_fence = {},
45 };
46
47 buffer_wait_event->GetWritableEvent().Signal();
48}
49
50std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
51 u32 height) {
52 // Wait for first request before trying to dequeue
53 {
54 std::unique_lock lock{free_buffers_mutex};
55 free_buffers_condition.wait(lock, [this] { return !free_buffers.empty() || !is_connect; });
56 }
57
58 if (!is_connect) {
59 // Buffer was disconnected while the thread was blocked, this is most likely due to
60 // emulation being stopped
61 return std::nullopt;
62 }
63
64 std::unique_lock lock{free_buffers_mutex};
65
66 auto f_itr = free_buffers.begin();
67 auto slot = buffers.size();
68
69 while (f_itr != free_buffers.end()) {
70 const Buffer& buffer = buffers[*f_itr];
71 if (buffer.status == Buffer::Status::Free && buffer.igbp_buffer.width == width &&
72 buffer.igbp_buffer.height == height) {
73 slot = *f_itr;
74 free_buffers.erase(f_itr);
75 break;
76 }
77 ++f_itr;
78 }
79 if (slot == buffers.size()) {
80 return std::nullopt;
81 }
82 buffers[slot].status = Buffer::Status::Dequeued;
83 return {{buffers[slot].slot, &buffers[slot].multi_fence}};
84}
85
86const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
87 ASSERT(slot < buffers.size());
88 ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
89 ASSERT(buffers[slot].slot == slot);
90
91 return buffers[slot].igbp_buffer;
92}
93
94void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
95 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
96 Service::Nvidia::MultiFence& multi_fence) {
97 ASSERT(slot < buffers.size());
98 ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
99 ASSERT(buffers[slot].slot == slot);
100
101 buffers[slot].status = Buffer::Status::Queued;
102 buffers[slot].transform = transform;
103 buffers[slot].crop_rect = crop_rect;
104 buffers[slot].swap_interval = swap_interval;
105 buffers[slot].multi_fence = multi_fence;
106 std::unique_lock lock{queue_sequence_mutex};
107 queue_sequence.push_back(slot);
108}
109
110void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) {
111 ASSERT(slot < buffers.size());
112 ASSERT(buffers[slot].status != Buffer::Status::Free);
113 ASSERT(buffers[slot].slot == slot);
114
115 buffers[slot].status = Buffer::Status::Free;
116 buffers[slot].multi_fence = multi_fence;
117 buffers[slot].swap_interval = 0;
118
119 {
120 std::unique_lock lock{free_buffers_mutex};
121 free_buffers.push_back(slot);
122 }
123 free_buffers_condition.notify_one();
124
125 buffer_wait_event->GetWritableEvent().Signal();
126}
127
128std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
129 std::unique_lock lock{queue_sequence_mutex};
130 std::size_t buffer_slot = buffers.size();
131 // Iterate to find a queued buffer matching the requested slot.
132 while (buffer_slot == buffers.size() && !queue_sequence.empty()) {
133 const auto slot = static_cast<std::size_t>(queue_sequence.front());
134 ASSERT(slot < buffers.size());
135 if (buffers[slot].status == Buffer::Status::Queued) {
136 ASSERT(buffers[slot].slot == slot);
137 buffer_slot = slot;
138 }
139 queue_sequence.pop_front();
140 }
141 if (buffer_slot == buffers.size()) {
142 return std::nullopt;
143 }
144 buffers[buffer_slot].status = Buffer::Status::Acquired;
145 return {{buffers[buffer_slot]}};
146}
147
148void BufferQueue::ReleaseBuffer(u32 slot) {
149 ASSERT(slot < buffers.size());
150 ASSERT(buffers[slot].status == Buffer::Status::Acquired);
151 ASSERT(buffers[slot].slot == slot);
152
153 buffers[slot].status = Buffer::Status::Free;
154 {
155 std::unique_lock lock{free_buffers_mutex};
156 free_buffers.push_back(slot);
157 }
158 free_buffers_condition.notify_one();
159
160 buffer_wait_event->GetWritableEvent().Signal();
161}
162
163void BufferQueue::Connect() {
164 std::unique_lock lock{queue_sequence_mutex};
165 queue_sequence.clear();
166 is_connect = true;
167}
168
169void BufferQueue::Disconnect() {
170 buffers.fill({});
171 {
172 std::unique_lock lock{queue_sequence_mutex};
173 queue_sequence.clear();
174 }
175 buffer_wait_event->GetWritableEvent().Signal();
176 is_connect = false;
177 free_buffers_condition.notify_one();
178}
179
180u32 BufferQueue::Query(QueryType type) {
181 LOG_WARNING(Service, "(STUBBED) called type={}", type);
182
183 switch (type) {
184 case QueryType::NativeWindowFormat:
185 return static_cast<u32>(PixelFormat::RGBA8888);
186 case QueryType::NativeWindowWidth:
187 case QueryType::NativeWindowHeight:
188 break;
189 case QueryType::NativeWindowMinUndequeuedBuffers:
190 return 0;
191 case QueryType::NativeWindowConsumerUsageBits:
192 return 0;
193 }
194 UNIMPLEMENTED_MSG("Unimplemented query type={}", type);
195 return 0;
196}
197
198Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() {
199 return buffer_wait_event->GetWritableEvent();
200}
201
202Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() {
203 return buffer_wait_event->GetReadableEvent();
204}
205
206} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
deleted file mode 100644
index f2a579133..000000000
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ /dev/null
@@ -1,154 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <condition_variable>
8#include <list>
9#include <mutex>
10#include <optional>
11
12#include "common/common_funcs.h"
13#include "common/math_util.h"
14#include "common/swap.h"
15#include "core/hle/kernel/k_event.h"
16#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/service/nvdrv/nvdata.h"
18
19namespace Kernel {
20class KernelCore;
21class KEvent;
22class KReadableEvent;
23class KWritableEvent;
24} // namespace Kernel
25
26namespace Service::KernelHelpers {
27class ServiceContext;
28} // namespace Service::KernelHelpers
29
30namespace Service::NVFlinger {
31
32constexpr u32 buffer_slots = 0x40;
33struct IGBPBuffer {
34 u32_le magic;
35 u32_le width;
36 u32_le height;
37 u32_le stride;
38 u32_le format;
39 u32_le usage;
40 INSERT_PADDING_WORDS(1);
41 u32_le index;
42 INSERT_PADDING_WORDS(3);
43 u32_le gpu_buffer_id;
44 INSERT_PADDING_WORDS(6);
45 u32_le external_format;
46 INSERT_PADDING_WORDS(10);
47 u32_le nvmap_handle;
48 u32_le offset;
49 INSERT_PADDING_WORDS(60);
50};
51
52static_assert(sizeof(IGBPBuffer) == 0x16C, "IGBPBuffer has wrong size");
53
54class BufferQueue final {
55public:
56 enum class QueryType {
57 NativeWindowWidth = 0,
58 NativeWindowHeight = 1,
59 NativeWindowFormat = 2,
60 /// The minimum number of buffers that must remain un-dequeued after a buffer has been
61 /// queued
62 NativeWindowMinUndequeuedBuffers = 3,
63 /// The consumer gralloc usage bits currently set by the consumer
64 NativeWindowConsumerUsageBits = 10,
65 };
66
67 explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
68 KernelHelpers::ServiceContext& service_context_);
69 ~BufferQueue();
70
71 enum class BufferTransformFlags : u32 {
72 /// No transform flags are set
73 Unset = 0x00,
74 /// Flip source image horizontally (around the vertical axis)
75 FlipH = 0x01,
76 /// Flip source image vertically (around the horizontal axis)
77 FlipV = 0x02,
78 /// Rotate source image 90 degrees clockwise
79 Rotate90 = 0x04,
80 /// Rotate source image 180 degrees
81 Rotate180 = 0x03,
82 /// Rotate source image 270 degrees clockwise
83 Rotate270 = 0x07,
84 };
85
86 enum class PixelFormat : u32 {
87 RGBA8888 = 1,
88 RGBX8888 = 2,
89 RGB888 = 3,
90 RGB565 = 4,
91 BGRA8888 = 5,
92 RGBA5551 = 6,
93 RRGBA4444 = 7,
94 };
95
96 struct Buffer {
97 enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 };
98
99 u32 slot;
100 Status status = Status::Free;
101 IGBPBuffer igbp_buffer;
102 BufferTransformFlags transform;
103 Common::Rectangle<int> crop_rect;
104 u32 swap_interval;
105 Service::Nvidia::MultiFence multi_fence;
106 };
107
108 void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
109 std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> DequeueBuffer(u32 width,
110 u32 height);
111 const IGBPBuffer& RequestBuffer(u32 slot) const;
112 void QueueBuffer(u32 slot, BufferTransformFlags transform,
113 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
114 Service::Nvidia::MultiFence& multi_fence);
115 void CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence);
116 std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
117 void ReleaseBuffer(u32 slot);
118 void Connect();
119 void Disconnect();
120 u32 Query(QueryType type);
121
122 u32 GetId() const {
123 return id;
124 }
125
126 bool IsConnected() const {
127 return is_connect;
128 }
129
130 Kernel::KWritableEvent& GetWritableBufferWaitEvent();
131
132 Kernel::KReadableEvent& GetBufferWaitEvent();
133
134private:
135 BufferQueue(const BufferQueue&) = delete;
136
137 u32 id{};
138 u64 layer_id{};
139 std::atomic_bool is_connect{};
140
141 std::list<u32> free_buffers;
142 std::array<Buffer, buffer_slots> buffers;
143 std::list<u32> queue_sequence;
144 Kernel::KEvent* buffer_wait_event{};
145
146 std::mutex free_buffers_mutex;
147 std::condition_variable free_buffers_condition;
148
149 std::mutex queue_sequence_mutex;
150
151 KernelHelpers::ServiceContext& service_context;
152};
153
154} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
new file mode 100644
index 000000000..41fbba219
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
@@ -0,0 +1,203 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
6
7#include "common/logging/log.h"
8#include "core/hle/service/nvflinger/buffer_item.h"
9#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
10#include "core/hle/service/nvflinger/buffer_queue_core.h"
11#include "core/hle/service/nvflinger/producer_listener.h"
12
13namespace Service::android {
14
15BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
16 : core{std::move(core_)}, slots{core->slots} {}
17
18BufferQueueConsumer::~BufferQueueConsumer() = default;
19
20Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
21 std::chrono::nanoseconds expected_present,
22 u64 max_frame_number) {
23 std::scoped_lock lock(core->mutex);
24
25 // Check that the consumer doesn't currently have the maximum number of buffers acquired.
26 const s32 num_acquired_buffers{
27 static_cast<s32>(std::count_if(slots.begin(), slots.end(), [](const auto& slot) {
28 return slot.buffer_state == BufferState::Acquired;
29 }))};
30
31 if (num_acquired_buffers >= core->max_acquired_buffer_count + 1) {
32 LOG_ERROR(Service_NVFlinger, "max acquired buffer count reached: {} (max {})",
33 num_acquired_buffers, core->max_acquired_buffer_count);
34 return Status::InvalidOperation;
35 }
36
37 // Check if the queue is empty.
38 if (core->queue.empty()) {
39 return Status::NoBufferAvailable;
40 }
41
42 auto front(core->queue.begin());
43
44 // If expected_present is specified, we may not want to return a buffer yet.
45 if (expected_present.count() != 0) {
46 constexpr auto MAX_REASONABLE_NSEC = 1000000000LL; // 1 second
47
48 // The expected_present argument indicates when the buffer is expected to be presented
49 // on-screen.
50 while (core->queue.size() > 1 && !core->queue[0].is_auto_timestamp) {
51 const auto& buffer_item{core->queue[1]};
52
53 // If dropping entry[0] would leave us with a buffer that the consumer is not yet ready
54 // for, don't drop it.
55 if (max_frame_number && buffer_item.frame_number > max_frame_number) {
56 break;
57 }
58
59 // If entry[1] is timely, drop entry[0] (and repeat).
60 const auto desired_present = buffer_item.timestamp;
61 if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC ||
62 desired_present > expected_present.count()) {
63 // This buffer is set to display in the near future, or desired_present is garbage.
64 LOG_DEBUG(Service_NVFlinger, "nodrop desire={} expect={}", desired_present,
65 expected_present.count());
66 break;
67 }
68
69 LOG_DEBUG(Service_NVFlinger, "drop desire={} expect={} size={}", desired_present,
70 expected_present.count(), core->queue.size());
71
72 if (core->StillTracking(*front)) {
73 // Front buffer is still in mSlots, so mark the slot as free
74 slots[front->slot].buffer_state = BufferState::Free;
75 }
76
77 core->queue.erase(front);
78 front = core->queue.begin();
79 }
80
81 // See if the front buffer is ready to be acquired.
82 const auto desired_present = front->timestamp;
83 if (desired_present > expected_present.count() &&
84 desired_present < expected_present.count() + MAX_REASONABLE_NSEC) {
85 LOG_DEBUG(Service_NVFlinger, "defer desire={} expect={}", desired_present,
86 expected_present.count());
87 return Status::PresentLater;
88 }
89
90 LOG_DEBUG(Service_NVFlinger, "accept desire={} expect={}", desired_present,
91 expected_present.count());
92 }
93
94 const auto slot = front->slot;
95 *out_buffer = *front;
96
97 LOG_DEBUG(Service_NVFlinger, "acquiring slot={}", slot);
98
99 // If the front buffer is still being tracked, update its slot state
100 if (core->StillTracking(*front)) {
101 slots[slot].acquire_called = true;
102 slots[slot].needs_cleanup_on_release = false;
103 slots[slot].buffer_state = BufferState::Acquired;
104 slots[slot].fence = Fence::NoFence();
105 }
106
107 // If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to
108 // avoid unnecessarily remapping this buffer on the consumer side.
109 if (out_buffer->acquire_called) {
110 out_buffer->graphic_buffer = nullptr;
111 }
112
113 core->queue.erase(front);
114
115 // We might have freed a slot while dropping old buffers, or the producer may be blocked
116 // waiting for the number of buffers in the queue to decrease.
117 core->SignalDequeueCondition();
118
119 return Status::NoError;
120}
121
122Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence) {
123 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
124 LOG_ERROR(Service_NVFlinger, "slot {} out of range", slot);
125 return Status::BadValue;
126 }
127
128 std::shared_ptr<IProducerListener> listener;
129 {
130 std::scoped_lock lock(core->mutex);
131
132 // If the frame number has changed because the buffer has been reallocated, we can ignore
133 // this ReleaseBuffer for the old buffer.
134 if (frame_number != slots[slot].frame_number) {
135 return Status::StaleBufferSlot;
136 }
137
138 // Make sure this buffer hasn't been queued while acquired by the consumer.
139 auto current(core->queue.begin());
140 while (current != core->queue.end()) {
141 if (current->slot == slot) {
142 LOG_ERROR(Service_NVFlinger, "buffer slot {} pending release is currently queued",
143 slot);
144 return Status::BadValue;
145 }
146 ++current;
147 }
148
149 if (slots[slot].buffer_state == BufferState::Acquired) {
150 slots[slot].fence = release_fence;
151 slots[slot].buffer_state = BufferState::Free;
152
153 listener = core->connected_producer_listener;
154
155 LOG_DEBUG(Service_NVFlinger, "releasing slot {}", slot);
156 } else if (slots[slot].needs_cleanup_on_release) {
157 LOG_DEBUG(Service_NVFlinger, "releasing a stale buffer slot {} (state = {})", slot,
158 slots[slot].buffer_state);
159
160 slots[slot].needs_cleanup_on_release = false;
161
162 return Status::StaleBufferSlot;
163 } else {
164 LOG_ERROR(Service_NVFlinger, "attempted to release buffer slot {} but its state was {}",
165 slot, slots[slot].buffer_state);
166
167 return Status::BadValue;
168 }
169
170 core->SignalDequeueCondition();
171 }
172
173 // Call back without lock held
174 if (listener != nullptr) {
175 listener->OnBufferReleased();
176 }
177
178 return Status::NoError;
179}
180
181Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_listener,
182 bool controlled_by_app) {
183 if (consumer_listener == nullptr) {
184 LOG_ERROR(Service_NVFlinger, "consumer_listener may not be nullptr");
185 return Status::BadValue;
186 }
187
188 LOG_DEBUG(Service_NVFlinger, "controlled_by_app={}", controlled_by_app);
189
190 std::scoped_lock lock(core->mutex);
191
192 if (core->is_abandoned) {
193 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
194 return Status::NoInit;
195 }
196
197 core->consumer_listener = consumer_listener;
198 core->consumer_controlled_by_app = controlled_by_app;
199
200 return Status::NoError;
201}
202
203} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.h b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
new file mode 100644
index 000000000..f22854394
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
@@ -0,0 +1,37 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueConsumer.h
6
7#pragma once
8
9#include <chrono>
10#include <memory>
11
12#include "common/common_types.h"
13#include "core/hle/service/nvflinger/buffer_queue_defs.h"
14#include "core/hle/service/nvflinger/status.h"
15
16namespace Service::android {
17
18class BufferItem;
19class BufferQueueCore;
20class IConsumerListener;
21
22class BufferQueueConsumer final {
23public:
24 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
25 ~BufferQueueConsumer();
26
27 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present,
28 u64 max_frame_number = 0);
29 Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
30 Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
31
32private:
33 std::shared_ptr<BufferQueueCore> core;
34 BufferQueueDefs::SlotsType& slots;
35};
36
37} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
new file mode 100644
index 000000000..6082610e0
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
@@ -0,0 +1,118 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueCore.cpp
6
7#include "common/assert.h"
8
9#include "core/hle/service/nvflinger/buffer_queue_core.h"
10
11namespace Service::android {
12
13BufferQueueCore::BufferQueueCore() = default;
14
15BufferQueueCore::~BufferQueueCore() = default;
16
17void BufferQueueCore::NotifyShutdown() {
18 std::scoped_lock lock(mutex);
19
20 is_shutting_down = true;
21
22 SignalDequeueCondition();
23}
24
25void BufferQueueCore::SignalDequeueCondition() {
26 dequeue_condition.notify_all();
27}
28
29bool BufferQueueCore::WaitForDequeueCondition() {
30 if (is_shutting_down) {
31 return false;
32 }
33
34 dequeue_condition.wait(mutex);
35
36 return true;
37}
38
39s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const {
40 // If DequeueBuffer is allowed to error out, we don't have to add an extra buffer.
41 if (!use_async_buffer) {
42 return max_acquired_buffer_count;
43 }
44
45 if (dequeue_buffer_cannot_block || async) {
46 return max_acquired_buffer_count + 1;
47 }
48
49 return max_acquired_buffer_count;
50}
51
52s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const {
53 return GetMinUndequeuedBufferCountLocked(async) + 1;
54}
55
56s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const {
57 const auto min_buffer_count = GetMinMaxBufferCountLocked(async);
58 auto max_buffer_count = std::max(default_max_buffer_count, min_buffer_count);
59
60 if (override_max_buffer_count != 0) {
61 ASSERT(override_max_buffer_count >= min_buffer_count);
62 max_buffer_count = override_max_buffer_count;
63 }
64
65 // Any buffers that are dequeued by the producer or sitting in the queue waiting to be consumed
66 // need to have their slots preserved.
67 for (s32 slot = max_buffer_count; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
68 const auto state = slots[slot].buffer_state;
69 if (state == BufferState::Queued || state == BufferState::Dequeued) {
70 max_buffer_count = slot + 1;
71 }
72 }
73
74 return max_buffer_count;
75}
76
77s32 BufferQueueCore::GetPreallocatedBufferCountLocked() const {
78 return static_cast<s32>(std::count_if(slots.begin(), slots.end(),
79 [](const auto& slot) { return slot.is_preallocated; }));
80}
81
82void BufferQueueCore::FreeBufferLocked(s32 slot) {
83 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
84
85 slots[slot].graphic_buffer.reset();
86
87 if (slots[slot].buffer_state == BufferState::Acquired) {
88 slots[slot].needs_cleanup_on_release = true;
89 }
90
91 slots[slot].buffer_state = BufferState::Free;
92 slots[slot].frame_number = UINT32_MAX;
93 slots[slot].acquire_called = false;
94 slots[slot].fence = Fence::NoFence();
95}
96
97void BufferQueueCore::FreeAllBuffersLocked() {
98 queue.clear();
99 buffer_has_been_queued = false;
100
101 for (s32 slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
102 FreeBufferLocked(slot);
103 }
104}
105
106bool BufferQueueCore::StillTracking(const BufferItem& item) const {
107 const BufferSlot& slot = slots[item.slot];
108
109 return (slot.graphic_buffer != nullptr) && (item.graphic_buffer == slot.graphic_buffer);
110}
111
112void BufferQueueCore::WaitWhileAllocatingLocked() const {
113 while (is_allocating) {
114 is_allocating_condition.wait(mutex);
115 }
116}
117
118} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h
new file mode 100644
index 000000000..4dfd53387
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_core.h
@@ -0,0 +1,81 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueCore.h
6
7#pragma once
8
9#include <condition_variable>
10#include <list>
11#include <memory>
12#include <mutex>
13#include <set>
14#include <vector>
15
16#include "core/hle/service/nvflinger/buffer_item.h"
17#include "core/hle/service/nvflinger/buffer_queue_defs.h"
18#include "core/hle/service/nvflinger/pixel_format.h"
19#include "core/hle/service/nvflinger/status.h"
20#include "core/hle/service/nvflinger/window.h"
21
22namespace Service::android {
23
24class IConsumerListener;
25class IProducerListener;
26
27class BufferQueueCore final {
28 friend class BufferQueueProducer;
29 friend class BufferQueueConsumer;
30
31public:
32 static constexpr s32 INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT;
33
34 BufferQueueCore();
35 ~BufferQueueCore();
36
37 void NotifyShutdown();
38
39private:
40 void SignalDequeueCondition();
41 bool WaitForDequeueCondition();
42
43 s32 GetMinUndequeuedBufferCountLocked(bool async) const;
44 s32 GetMinMaxBufferCountLocked(bool async) const;
45 s32 GetMaxBufferCountLocked(bool async) const;
46 s32 GetPreallocatedBufferCountLocked() const;
47 void FreeBufferLocked(s32 slot);
48 void FreeAllBuffersLocked();
49 bool StillTracking(const BufferItem& item) const;
50 void WaitWhileAllocatingLocked() const;
51
52private:
53 mutable std::mutex mutex;
54 bool is_abandoned{};
55 bool consumer_controlled_by_app{};
56 std::shared_ptr<IConsumerListener> consumer_listener;
57 u32 consumer_usage_bit{};
58 NativeWindowApi connected_api{NativeWindowApi::NoConnectedApi};
59 std::shared_ptr<IProducerListener> connected_producer_listener;
60 BufferQueueDefs::SlotsType slots{};
61 std::vector<BufferItem> queue;
62 s32 override_max_buffer_count{};
63 mutable std::condition_variable_any dequeue_condition;
64 const bool use_async_buffer{}; // This is always disabled on HOS
65 bool dequeue_buffer_cannot_block{};
66 PixelFormat default_buffer_format{PixelFormat::Rgba8888};
67 u32 default_width{1};
68 u32 default_height{1};
69 s32 default_max_buffer_count{2};
70 const s32 max_acquired_buffer_count{}; // This is always zero on HOS
71 bool buffer_has_been_queued{};
72 u64 frame_counter{};
73 u32 transform_hint{};
74 bool is_allocating{};
75 mutable std::condition_variable_any is_allocating_condition;
76 bool allow_allocation{true};
77 u64 buffer_age{};
78 bool is_shutting_down{};
79};
80
81} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_defs.h b/src/core/hle/service/nvflinger/buffer_queue_defs.h
new file mode 100644
index 000000000..387d3d36a
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_defs.h
@@ -0,0 +1,21 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueDefs.h
6
7#pragma once
8
9#include <array>
10
11#include "common/common_types.h"
12#include "core/hle/service/nvflinger/buffer_slot.h"
13
14namespace Service::android::BufferQueueDefs {
15
16// BufferQueue will keep track of at most this value of buffers.
17constexpr s32 NUM_BUFFER_SLOTS = 64;
18
19using SlotsType = std::array<BufferSlot, NUM_BUFFER_SLOTS>;
20
21} // namespace Service::android::BufferQueueDefs
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
new file mode 100644
index 000000000..0833be57a
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -0,0 +1,942 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueProducer.cpp
6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "common/settings.h"
10#include "core/core.h"
11#include "core/hle/kernel/hle_ipc.h"
12#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_readable_event.h"
14#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/kernel.h"
16#include "core/hle/service/kernel_helpers.h"
17#include "core/hle/service/nvdrv/nvdrv.h"
18#include "core/hle/service/nvflinger/buffer_queue_core.h"
19#include "core/hle/service/nvflinger/buffer_queue_producer.h"
20#include "core/hle/service/nvflinger/consumer_listener.h"
21#include "core/hle/service/nvflinger/parcel.h"
22#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
23#include "core/hle/service/nvflinger/window.h"
24#include "core/hle/service/vi/vi.h"
25
26namespace Service::android {
27
28BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
29 std::shared_ptr<BufferQueueCore> buffer_queue_core_)
30 : service_context{service_context_}, core{std::move(buffer_queue_core_)}, slots(core->slots) {
31 buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
32}
33
34BufferQueueProducer::~BufferQueueProducer() {
35 service_context.CloseEvent(buffer_wait_event);
36}
37
38Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf) {
39 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
40
41 std::scoped_lock lock(core->mutex);
42
43 if (core->is_abandoned) {
44 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
45 return Status::NoInit;
46 }
47 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
48 LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot,
49 BufferQueueDefs::NUM_BUFFER_SLOTS);
50 return Status::BadValue;
51 } else if (slots[slot].buffer_state != BufferState::Dequeued) {
52 LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot,
53 slots[slot].buffer_state);
54 return Status::BadValue;
55 }
56
57 slots[slot].request_buffer_called = true;
58 *buf = slots[slot].graphic_buffer;
59
60 return Status::NoError;
61}
62
63Status BufferQueueProducer::SetBufferCount(s32 buffer_count) {
64 LOG_DEBUG(Service_NVFlinger, "count = {}", buffer_count);
65 std::shared_ptr<IConsumerListener> listener;
66
67 {
68 std::scoped_lock lock(core->mutex);
69 core->WaitWhileAllocatingLocked();
70 if (core->is_abandoned) {
71 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
72 return Status::NoInit;
73 }
74
75 if (buffer_count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
76 LOG_ERROR(Service_NVFlinger, "buffer_count {} too large (max {})", buffer_count,
77 BufferQueueDefs::NUM_BUFFER_SLOTS);
78 return Status::BadValue;
79 }
80
81 // There must be no dequeued buffers when changing the buffer count.
82 for (s32 s{}; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
83 if (slots[s].buffer_state == BufferState::Dequeued) {
84 LOG_ERROR(Service_NVFlinger, "buffer owned by producer");
85 return Status::BadValue;
86 }
87 }
88
89 if (buffer_count == 0) {
90 core->override_max_buffer_count = 0;
91 core->SignalDequeueCondition();
92 return Status::NoError;
93 }
94
95 const s32 min_buffer_slots = core->GetMinMaxBufferCountLocked(false);
96 if (buffer_count < min_buffer_slots) {
97 LOG_ERROR(Service_NVFlinger, "requested buffer count {} is less than minimum {}",
98 buffer_count, min_buffer_slots);
99 return Status::BadValue;
100 }
101
102 // Here we are guaranteed that the producer doesn't have any dequeued buffers and will
103 // release all of its buffer references.
104 if (core->GetPreallocatedBufferCountLocked() <= 0) {
105 core->FreeAllBuffersLocked();
106 }
107
108 core->override_max_buffer_count = buffer_count;
109 core->SignalDequeueCondition();
110 buffer_wait_event->GetWritableEvent().Signal();
111 listener = core->consumer_listener;
112 }
113
114 // Call back without lock held
115 if (listener != nullptr) {
116 listener->OnBuffersReleased();
117 }
118
119 return Status::NoError;
120}
121
122Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found,
123 Status* returnFlags) const {
124 bool try_again = true;
125
126 while (try_again) {
127 if (core->is_abandoned) {
128 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
129 return Status::NoInit;
130 }
131
132 const s32 max_buffer_count = core->GetMaxBufferCountLocked(async);
133 if (async && core->override_max_buffer_count) {
134 if (core->override_max_buffer_count < max_buffer_count) {
135 LOG_ERROR(Service_NVFlinger, "async mode is invalid with buffer count override");
136 return Status::BadValue;
137 }
138 }
139
140 // Free up any buffers that are in slots beyond the max buffer count
141 for (s32 s = max_buffer_count; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
142 ASSERT(slots[s].buffer_state == BufferState::Free);
143 if (slots[s].graphic_buffer != nullptr) {
144 core->FreeBufferLocked(s);
145 *returnFlags |= Status::ReleaseAllBuffers;
146 }
147 }
148
149 s32 dequeued_count{};
150 s32 acquired_count{};
151 for (s32 s{}; s < max_buffer_count; ++s) {
152 switch (slots[s].buffer_state) {
153 case BufferState::Dequeued:
154 ++dequeued_count;
155 break;
156 case BufferState::Acquired:
157 ++acquired_count;
158 break;
159 case BufferState::Free:
160 // We return the oldest of the free buffers to avoid stalling the producer if
161 // possible, since the consumer may still have pending reads of in-flight buffers
162 if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
163 slots[s].frame_number < slots[*found].frame_number) {
164 *found = s;
165 }
166 break;
167 default:
168 break;
169 }
170 }
171
172 // Producers are not allowed to dequeue more than one buffer if they did not set a buffer
173 // count
174 if (!core->override_max_buffer_count && dequeued_count) {
175 LOG_ERROR(Service_NVFlinger,
176 "can't dequeue multiple buffers without setting the buffer count");
177 return Status::InvalidOperation;
178 }
179
180 // See whether a buffer has been queued since the last SetBufferCount so we know whether to
181 // perform the min undequeued buffers check below
182 if (core->buffer_has_been_queued) {
183 // Make sure the producer is not trying to dequeue more buffers than allowed
184 const s32 new_undequeued_count = max_buffer_count - (dequeued_count + 1);
185 const s32 min_undequeued_count = core->GetMinUndequeuedBufferCountLocked(async);
186 if (new_undequeued_count < min_undequeued_count) {
187 LOG_ERROR(Service_NVFlinger,
188 "min undequeued buffer count({}) exceeded (dequeued={} undequeued={})",
189 min_undequeued_count, dequeued_count, new_undequeued_count);
190 return Status::InvalidOperation;
191 }
192 }
193
194 // If we disconnect and reconnect quickly, we can be in a state where our slots are empty
195 // but we have many buffers in the queue. This can cause us to run out of memory if we
196 // outrun the consumer. Wait here if it looks like we have too many buffers queued up.
197 const bool too_many_buffers = core->queue.size() > static_cast<size_t>(max_buffer_count);
198 if (too_many_buffers) {
199 LOG_ERROR(Service_NVFlinger, "queue size is {}, waiting", core->queue.size());
200 }
201
202 // If no buffer is found, or if the queue has too many buffers outstanding, wait for a
203 // buffer to be acquired or released, or for the max buffer count to change.
204 try_again = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) || too_many_buffers;
205 if (try_again) {
206 // Return an error if we're in non-blocking mode (producer and consumer are controlled
207 // by the application).
208 if (core->dequeue_buffer_cannot_block &&
209 (acquired_count <= core->max_acquired_buffer_count)) {
210 return Status::WouldBlock;
211 }
212
213 if (!core->WaitForDequeueCondition()) {
214 // We are no longer running
215 return Status::NoError;
216 }
217 }
218 }
219
220 return Status::NoError;
221}
222
223Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool async, u32 width,
224 u32 height, PixelFormat format, u32 usage) {
225 LOG_DEBUG(Service_NVFlinger, "async={} w={} h={} format={}, usage={}", async ? "true" : "false",
226 width, height, format, usage);
227
228 if ((width != 0 && height == 0) || (width == 0 && height != 0)) {
229 LOG_ERROR(Service_NVFlinger, "invalid size: w={} h={}", width, height);
230 return Status::BadValue;
231 }
232
233 Status return_flags = Status::NoError;
234 bool attached_by_consumer = false;
235 {
236 std::scoped_lock lock(core->mutex);
237 core->WaitWhileAllocatingLocked();
238 if (format == PixelFormat::NoFormat) {
239 format = core->default_buffer_format;
240 }
241
242 // Enable the usage bits the consumer requested
243 usage |= core->consumer_usage_bit;
244 const bool use_default_size = !width && !height;
245 if (use_default_size) {
246 width = core->default_width;
247 height = core->default_height;
248 }
249
250 s32 found = BufferItem::INVALID_BUFFER_SLOT;
251 while (found == BufferItem::INVALID_BUFFER_SLOT) {
252 Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags);
253 if (status != Status::NoError) {
254 return status;
255 }
256
257 // This should not happen
258 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
259 LOG_DEBUG(Service_NVFlinger, "no available buffer slots");
260 return Status::Busy;
261 }
262
263 const std::shared_ptr<GraphicBuffer>& buffer(slots[found].graphic_buffer);
264
265 // If we are not allowed to allocate new buffers, WaitForFreeSlotThenRelock must have
266 // returned a slot containing a buffer. If this buffer would require reallocation to
267 // meet the requested attributes, we free it and attempt to get another one.
268 if (!core->allow_allocation) {
269 if (buffer->NeedsReallocation(width, height, format, usage)) {
270 core->FreeBufferLocked(found);
271 found = BufferItem::INVALID_BUFFER_SLOT;
272 continue;
273 }
274 }
275 }
276
277 *out_slot = found;
278 attached_by_consumer = slots[found].attached_by_consumer;
279 slots[found].buffer_state = BufferState::Dequeued;
280
281 const std::shared_ptr<GraphicBuffer>& buffer(slots[found].graphic_buffer);
282
283 if ((buffer == nullptr) || buffer->NeedsReallocation(width, height, format, usage)) {
284 slots[found].acquire_called = false;
285 slots[found].graphic_buffer = nullptr;
286 slots[found].request_buffer_called = false;
287 slots[found].fence = Fence::NoFence();
288 core->buffer_age = 0;
289 return_flags |= Status::BufferNeedsReallocation;
290 } else {
291 // We add 1 because that will be the frame number when this buffer
292 // is queued
293 core->buffer_age = core->frame_counter + 1 - slots[found].frame_number;
294 }
295
296 LOG_DEBUG(Service_NVFlinger, "setting buffer age to {}", core->buffer_age);
297
298 *out_fence = slots[found].fence;
299
300 slots[found].fence = Fence::NoFence();
301 }
302
303 if ((return_flags & Status::BufferNeedsReallocation) != Status::None) {
304 LOG_DEBUG(Service_NVFlinger, "allocating a new buffer for slot {}", *out_slot);
305
306 auto graphic_buffer = std::make_shared<GraphicBuffer>(width, height, format, usage);
307 if (graphic_buffer == nullptr) {
308 LOG_ERROR(Service_NVFlinger, "creating GraphicBuffer failed");
309 return Status::NoMemory;
310 }
311
312 {
313 std::scoped_lock lock(core->mutex);
314 if (core->is_abandoned) {
315 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
316 return Status::NoInit;
317 }
318
319 slots[*out_slot].frame_number = UINT32_MAX;
320 slots[*out_slot].graphic_buffer = graphic_buffer;
321 }
322 }
323
324 if (attached_by_consumer) {
325 return_flags |= Status::BufferNeedsReallocation;
326 }
327
328 LOG_DEBUG(Service_NVFlinger, "returning slot={} frame={}, flags={}", *out_slot,
329 slots[*out_slot].frame_number, return_flags);
330 return return_flags;
331}
332
333Status BufferQueueProducer::DetachBuffer(s32 slot) {
334 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
335
336 std::scoped_lock lock(core->mutex);
337 if (core->is_abandoned) {
338 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
339 return Status::NoInit;
340 }
341
342 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
343 LOG_ERROR(Service_NVFlinger, "slot {} out of range [0, {})", slot,
344 BufferQueueDefs::NUM_BUFFER_SLOTS);
345 return Status::BadValue;
346 } else if (slots[slot].buffer_state != BufferState::Dequeued) {
347 LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot,
348 slots[slot].buffer_state);
349 return Status::BadValue;
350 } else if (!slots[slot].request_buffer_called) {
351 LOG_ERROR(Service_NVFlinger, "buffer in slot {} has not been requested", slot);
352 return Status::BadValue;
353 }
354
355 core->FreeBufferLocked(slot);
356 core->SignalDequeueCondition();
357
358 return Status::NoError;
359}
360
361Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out_buffer,
362 Fence* out_fence) {
363 if (out_buffer == nullptr) {
364 LOG_ERROR(Service_NVFlinger, "out_buffer must not be nullptr");
365 return Status::BadValue;
366 } else if (out_fence == nullptr) {
367 LOG_ERROR(Service_NVFlinger, "out_fence must not be nullptr");
368 return Status::BadValue;
369 }
370
371 std::scoped_lock lock(core->mutex);
372
373 core->WaitWhileAllocatingLocked();
374
375 if (core->is_abandoned) {
376 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
377 return Status::NoInit;
378 }
379
380 // Find the oldest valid slot
381 int found = BufferQueueCore::INVALID_BUFFER_SLOT;
382 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
383 if (slots[s].buffer_state == BufferState::Free && slots[s].graphic_buffer != nullptr) {
384 if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
385 slots[s].frame_number < slots[found].frame_number) {
386 found = s;
387 }
388 }
389 }
390
391 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
392 return Status::NoMemory;
393 }
394
395 LOG_DEBUG(Service_NVFlinger, "Detached slot {}", found);
396
397 *out_buffer = slots[found].graphic_buffer;
398 *out_fence = slots[found].fence;
399
400 core->FreeBufferLocked(found);
401
402 return Status::NoError;
403}
404
405Status BufferQueueProducer::AttachBuffer(s32* out_slot,
406 const std::shared_ptr<GraphicBuffer>& buffer) {
407 if (out_slot == nullptr) {
408 LOG_ERROR(Service_NVFlinger, "out_slot must not be nullptr");
409 return Status::BadValue;
410 } else if (buffer == nullptr) {
411 LOG_ERROR(Service_NVFlinger, "Cannot attach nullptr buffer");
412 return Status::BadValue;
413 }
414
415 std::scoped_lock lock(core->mutex);
416 core->WaitWhileAllocatingLocked();
417
418 Status return_flags = Status::NoError;
419 s32 found{};
420
421 const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags);
422 if (status != Status::NoError) {
423 return status;
424 }
425
426 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
427 LOG_ERROR(Service_NVFlinger, "No available buffer slots");
428 return Status::Busy;
429 }
430
431 *out_slot = found;
432
433 LOG_DEBUG(Service_NVFlinger, "Returning slot {} flags={}", *out_slot, return_flags);
434
435 slots[*out_slot].graphic_buffer = buffer;
436 slots[*out_slot].buffer_state = BufferState::Dequeued;
437 slots[*out_slot].fence = Fence::NoFence();
438 slots[*out_slot].request_buffer_called = true;
439
440 return return_flags;
441}
442
443Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
444 QueueBufferOutput* output) {
445 s64 timestamp{};
446 bool is_auto_timestamp{};
447 Common::Rectangle<s32> crop;
448 NativeWindowScalingMode scaling_mode{};
449 NativeWindowTransform transform;
450 u32 sticky_transform_{};
451 bool async{};
452 s32 swap_interval{};
453 Fence fence{};
454
455 input.Deflate(&timestamp, &is_auto_timestamp, &crop, &scaling_mode, &transform,
456 &sticky_transform_, &async, &swap_interval, &fence);
457
458 switch (scaling_mode) {
459 case NativeWindowScalingMode::Freeze:
460 case NativeWindowScalingMode::ScaleToWindow:
461 case NativeWindowScalingMode::ScaleCrop:
462 case NativeWindowScalingMode::NoScaleCrop:
463 break;
464 default:
465 LOG_ERROR(Service_NVFlinger, "unknown scaling mode {}", scaling_mode);
466 return Status::BadValue;
467 }
468
469 std::shared_ptr<IConsumerListener> frameAvailableListener;
470 std::shared_ptr<IConsumerListener> frameReplacedListener;
471 s32 callback_ticket{};
472 BufferItem item;
473
474 {
475 std::scoped_lock lock(core->mutex);
476
477 if (core->is_abandoned) {
478 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
479 return Status::NoInit;
480 }
481
482 const s32 max_buffer_count = core->GetMaxBufferCountLocked(async);
483 if (async && core->override_max_buffer_count) {
484 if (core->override_max_buffer_count < max_buffer_count) {
485 LOG_ERROR(Service_NVFlinger, "async mode is invalid with "
486 "buffer count override");
487 return Status::BadValue;
488 }
489 }
490
491 if (slot < 0 || slot >= max_buffer_count) {
492 LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot,
493 max_buffer_count);
494 return Status::BadValue;
495 } else if (slots[slot].buffer_state != BufferState::Dequeued) {
496 LOG_ERROR(Service_NVFlinger,
497 "slot {} is not owned by the producer "
498 "(state = {})",
499 slot, slots[slot].buffer_state);
500 return Status::BadValue;
501 } else if (!slots[slot].request_buffer_called) {
502 LOG_ERROR(Service_NVFlinger,
503 "slot {} was queued without requesting "
504 "a buffer",
505 slot);
506 return Status::BadValue;
507 }
508
509 LOG_DEBUG(Service_NVFlinger,
510 "slot={} frame={} time={} crop=[{},{},{},{}] transform={} scale={}", slot,
511 core->frame_counter + 1, timestamp, crop.Left(), crop.Top(), crop.Right(),
512 crop.Bottom(), transform, scaling_mode);
513
514 const std::shared_ptr<GraphicBuffer>& graphic_buffer(slots[slot].graphic_buffer);
515 Common::Rectangle<s32> buffer_rect(graphic_buffer->Width(), graphic_buffer->Height());
516 Common::Rectangle<s32> cropped_rect;
517 [[maybe_unused]] const bool unused = crop.Intersect(buffer_rect, &cropped_rect);
518
519 if (cropped_rect != crop) {
520 LOG_ERROR(Service_NVFlinger, "crop rect is not contained within the buffer in slot {}",
521 slot);
522 return Status::BadValue;
523 }
524
525 slots[slot].fence = fence;
526 slots[slot].buffer_state = BufferState::Queued;
527 ++core->frame_counter;
528 slots[slot].frame_number = core->frame_counter;
529
530 item.acquire_called = slots[slot].acquire_called;
531 item.graphic_buffer = slots[slot].graphic_buffer;
532 item.crop = crop;
533 item.transform = transform & ~NativeWindowTransform::InverseDisplay;
534 item.transform_to_display_inverse =
535 (transform & NativeWindowTransform::InverseDisplay) != NativeWindowTransform::None;
536 item.scaling_mode = static_cast<u32>(scaling_mode);
537 item.timestamp = timestamp;
538 item.is_auto_timestamp = is_auto_timestamp;
539 item.frame_number = core->frame_counter;
540 item.slot = slot;
541 item.fence = fence;
542 item.is_droppable = core->dequeue_buffer_cannot_block || async;
543 item.swap_interval = swap_interval;
544 sticky_transform = sticky_transform_;
545
546 if (core->queue.empty()) {
547 // When the queue is empty, we can simply queue this buffer
548 core->queue.push_back(item);
549 frameAvailableListener = core->consumer_listener;
550 } else {
551 // When the queue is not empty, we need to look at the front buffer
552 // state to see if we need to replace it
553 auto front(core->queue.begin());
554
555 if (front->is_droppable) {
556 // If the front queued buffer is still being tracked, we first
557 // mark it as freed
558 if (core->StillTracking(*front)) {
559 slots[front->slot].buffer_state = BufferState::Free;
560 // Reset the frame number of the freed buffer so that it is the first in line to
561 // be dequeued again
562 slots[front->slot].frame_number = 0;
563 }
564 // Overwrite the droppable buffer with the incoming one
565 *front = item;
566 frameReplacedListener = core->consumer_listener;
567 } else {
568 core->queue.push_back(item);
569 frameAvailableListener = core->consumer_listener;
570 }
571 }
572
573 core->buffer_has_been_queued = true;
574 core->SignalDequeueCondition();
575 output->Inflate(core->default_width, core->default_height, core->transform_hint,
576 static_cast<u32>(core->queue.size()));
577
578 // Take a ticket for the callback functions
579 callback_ticket = next_callback_ticket++;
580 }
581
582 // Don't send the GraphicBuffer through the callback, and don't send the slot number, since the
583 // consumer shouldn't need it
584 item.graphic_buffer.reset();
585 item.slot = BufferItem::INVALID_BUFFER_SLOT;
586
587 // Call back without the main BufferQueue lock held, but with the callback lock held so we can
588 // ensure that callbacks occur in order
589 {
590 std::scoped_lock lock(callback_mutex);
591 while (callback_ticket != current_callback_ticket) {
592 callback_condition.wait(callback_mutex);
593 }
594
595 if (frameAvailableListener != nullptr) {
596 frameAvailableListener->OnFrameAvailable(item);
597 } else if (frameReplacedListener != nullptr) {
598 frameReplacedListener->OnFrameReplaced(item);
599 }
600
601 ++current_callback_ticket;
602 callback_condition.notify_all();
603 }
604
605 return Status::NoError;
606}
607
608void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) {
609 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
610
611 std::scoped_lock lock(core->mutex);
612
613 if (core->is_abandoned) {
614 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
615 return;
616 }
617
618 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
619 LOG_ERROR(Service_NVFlinger, "slot index {} out of range [0, {})", slot,
620 BufferQueueDefs::NUM_BUFFER_SLOTS);
621 return;
622 } else if (slots[slot].buffer_state != BufferState::Dequeued) {
623 LOG_ERROR(Service_NVFlinger, "slot {} is not owned by the producer (state = {})", slot,
624 slots[slot].buffer_state);
625 return;
626 }
627
628 slots[slot].buffer_state = BufferState::Free;
629 slots[slot].frame_number = 0;
630 slots[slot].fence = fence;
631
632 core->SignalDequeueCondition();
633 buffer_wait_event->GetWritableEvent().Signal();
634}
635
636Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) {
637 std::scoped_lock lock(core->mutex);
638
639 if (out_value == nullptr) {
640 LOG_ERROR(Service_NVFlinger, "outValue was nullptr");
641 return Status::BadValue;
642 }
643
644 if (core->is_abandoned) {
645 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
646 return Status::NoInit;
647 }
648
649 u32 value{};
650 switch (what) {
651 case NativeWindow::Width:
652 value = core->default_width;
653 break;
654 case NativeWindow::Height:
655 value = core->default_height;
656 break;
657 case NativeWindow::Format:
658 value = static_cast<u32>(core->default_buffer_format);
659 break;
660 case NativeWindow::MinUndequeedBuffers:
661 value = core->GetMinUndequeuedBufferCountLocked(false);
662 break;
663 case NativeWindow::StickyTransform:
664 value = sticky_transform;
665 break;
666 case NativeWindow::ConsumerRunningBehind:
667 value = (core->queue.size() > 1);
668 break;
669 case NativeWindow::ConsumerUsageBits:
670 value = core->consumer_usage_bit;
671 break;
672 case NativeWindow::BufferAge:
673 if (core->buffer_age > INT32_MAX) {
674 value = 0;
675 } else {
676 value = static_cast<u32>(core->buffer_age);
677 }
678 break;
679 default:
680 UNREACHABLE();
681 return Status::BadValue;
682 }
683
684 LOG_DEBUG(Service_NVFlinger, "what = {}, value = {}", what, value);
685
686 *out_value = static_cast<s32>(value);
687
688 return Status::NoError;
689}
690
691Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& listener,
692 NativeWindowApi api, bool producer_controlled_by_app,
693 QueueBufferOutput* output) {
694 std::scoped_lock lock(core->mutex);
695
696 LOG_DEBUG(Service_NVFlinger, "api = {} producer_controlled_by_app = {}", api,
697 producer_controlled_by_app);
698
699 if (core->is_abandoned) {
700 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
701 return Status::NoInit;
702 }
703
704 if (core->consumer_listener == nullptr) {
705 LOG_ERROR(Service_NVFlinger, "BufferQueue has no consumer");
706 return Status::NoInit;
707 }
708
709 if (output == nullptr) {
710 LOG_ERROR(Service_NVFlinger, "output was nullptr");
711 return Status::BadValue;
712 }
713
714 if (core->connected_api != NativeWindowApi::NoConnectedApi) {
715 LOG_ERROR(Service_NVFlinger, "already connected (cur = {} req = {})", core->connected_api,
716 api);
717 return Status::BadValue;
718 }
719
720 Status status = Status::NoError;
721 switch (api) {
722 case NativeWindowApi::Egl:
723 case NativeWindowApi::Cpu:
724 case NativeWindowApi::Media:
725 case NativeWindowApi::Camera:
726 core->connected_api = api;
727 output->Inflate(core->default_width, core->default_height, core->transform_hint,
728 static_cast<u32>(core->queue.size()));
729 core->connected_producer_listener = listener;
730 break;
731 default:
732 LOG_ERROR(Service_NVFlinger, "unknown api = {}", api);
733 status = Status::BadValue;
734 break;
735 }
736
737 core->buffer_has_been_queued = false;
738 core->dequeue_buffer_cannot_block =
739 core->consumer_controlled_by_app && producer_controlled_by_app;
740 core->allow_allocation = true;
741
742 return status;
743}
744
745Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
746 LOG_DEBUG(Service_NVFlinger, "api = {}", api);
747
748 Status status = Status::NoError;
749 std::shared_ptr<IConsumerListener> listener;
750
751 {
752 std::scoped_lock lock(core->mutex);
753
754 core->WaitWhileAllocatingLocked();
755
756 if (core->is_abandoned) {
757 // Disconnecting after the surface has been abandoned is a no-op.
758 return Status::NoError;
759 }
760
761 switch (api) {
762 case NativeWindowApi::Egl:
763 case NativeWindowApi::Cpu:
764 case NativeWindowApi::Media:
765 case NativeWindowApi::Camera:
766 if (core->connected_api == api) {
767 core->FreeAllBuffersLocked();
768 core->connected_producer_listener = nullptr;
769 core->connected_api = NativeWindowApi::NoConnectedApi;
770 core->SignalDequeueCondition();
771 buffer_wait_event->GetWritableEvent().Signal();
772 listener = core->consumer_listener;
773 } else if (core->connected_api != NativeWindowApi::NoConnectedApi) {
774 LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})",
775 core->connected_api, api);
776 status = Status::BadValue;
777 }
778 break;
779 default:
780 LOG_ERROR(Service_NVFlinger, "unknown api = {}", api);
781 status = Status::BadValue;
782 break;
783 }
784 }
785
786 // Call back without lock held
787 if (listener != nullptr) {
788 listener->OnBuffersReleased();
789 }
790
791 return status;
792}
793
794Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
795 const std::shared_ptr<GraphicBuffer>& buffer) {
796 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
797
798 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
799 return Status::BadValue;
800 }
801
802 std::scoped_lock lock(core->mutex);
803
804 slots[slot] = {};
805 slots[slot].graphic_buffer = buffer;
806 slots[slot].frame_number = 0;
807
808 // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for
809 // this to be called with an empty buffer, Naruto Ultimate Ninja Storm is a game that does this.
810 if (buffer) {
811 slots[slot].is_preallocated = true;
812
813 core->override_max_buffer_count = core->GetPreallocatedBufferCountLocked();
814 core->default_width = buffer->Width();
815 core->default_height = buffer->Height();
816 core->default_buffer_format = buffer->Format();
817 }
818
819 core->SignalDequeueCondition();
820 buffer_wait_event->GetWritableEvent().Signal();
821
822 return Status::NoError;
823}
824
825void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) {
826 Status status{Status::NoError};
827 Parcel parcel_in{ctx.ReadBuffer()};
828 Parcel parcel_out{};
829
830 switch (code) {
831 case TransactionId::Connect: {
832 const auto enable_listener = parcel_in.Read<bool>();
833 const auto api = parcel_in.Read<NativeWindowApi>();
834 const auto producer_controlled_by_app = parcel_in.Read<bool>();
835
836 UNIMPLEMENTED_IF_MSG(enable_listener, "Listener is unimplemented!");
837
838 std::shared_ptr<IProducerListener> listener;
839 QueueBufferOutput output{};
840
841 status = Connect(listener, api, producer_controlled_by_app, &output);
842
843 parcel_out.Write(output);
844 break;
845 }
846 case TransactionId::SetPreallocatedBuffer: {
847 const auto slot = parcel_in.Read<s32>();
848 const auto buffer = parcel_in.ReadObject<GraphicBuffer>();
849
850 status = SetPreallocatedBuffer(slot, buffer);
851 break;
852 }
853 case TransactionId::DequeueBuffer: {
854 const auto is_async = parcel_in.Read<bool>();
855 const auto width = parcel_in.Read<u32>();
856 const auto height = parcel_in.Read<u32>();
857 const auto pixel_format = parcel_in.Read<PixelFormat>();
858 const auto usage = parcel_in.Read<u32>();
859
860 s32 slot{};
861 Fence fence{};
862
863 status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage);
864
865 parcel_out.Write(slot);
866 parcel_out.WriteObject(&fence);
867 break;
868 }
869 case TransactionId::RequestBuffer: {
870 const auto slot = parcel_in.Read<s32>();
871
872 std::shared_ptr<GraphicBuffer> buf;
873
874 status = RequestBuffer(slot, &buf);
875
876 parcel_out.WriteObject(buf);
877 break;
878 }
879 case TransactionId::QueueBuffer: {
880 const auto slot = parcel_in.Read<s32>();
881
882 QueueBufferInput input{parcel_in};
883 QueueBufferOutput output;
884
885 status = QueueBuffer(slot, input, &output);
886
887 parcel_out.Write(output);
888 break;
889 }
890 case TransactionId::Query: {
891 const auto what = parcel_in.Read<NativeWindow>();
892
893 s32 value{};
894
895 status = Query(what, &value);
896
897 parcel_out.Write(value);
898 break;
899 }
900 case TransactionId::CancelBuffer: {
901 const auto slot = parcel_in.Read<s32>();
902 const auto fence = parcel_in.ReadFlattened<Fence>();
903
904 CancelBuffer(slot, fence);
905 break;
906 }
907 case TransactionId::Disconnect: {
908 const auto api = parcel_in.Read<NativeWindowApi>();
909
910 status = Disconnect(api);
911 break;
912 }
913 case TransactionId::DetachBuffer: {
914 const auto slot = parcel_in.Read<s32>();
915
916 status = DetachBuffer(slot);
917 break;
918 }
919 case TransactionId::SetBufferCount: {
920 const auto buffer_count = parcel_in.Read<s32>();
921
922 status = SetBufferCount(buffer_count);
923 break;
924 }
925 case TransactionId::GetBufferHistory:
926 LOG_WARNING(Service_NVFlinger, "(STUBBED) called, transaction=GetBufferHistory");
927 break;
928 default:
929 ASSERT_MSG(false, "Unimplemented TransactionId {}", code);
930 break;
931 }
932
933 parcel_out.Write(status);
934
935 ctx.WriteBuffer(parcel_out.Serialize());
936}
937
938Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() {
939 return buffer_wait_event->GetReadableEvent();
940}
941
942} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h
new file mode 100644
index 000000000..77fdcae8e
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h
@@ -0,0 +1,83 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferQueueProducer.h
6
7#pragma once
8
9#include <condition_variable>
10#include <memory>
11#include <mutex>
12
13#include "common/common_funcs.h"
14#include "core/hle/service/nvdrv/nvdata.h"
15#include "core/hle/service/nvflinger/binder.h"
16#include "core/hle/service/nvflinger/buffer_queue_defs.h"
17#include "core/hle/service/nvflinger/buffer_slot.h"
18#include "core/hle/service/nvflinger/graphic_buffer_producer.h"
19#include "core/hle/service/nvflinger/pixel_format.h"
20#include "core/hle/service/nvflinger/status.h"
21#include "core/hle/service/nvflinger/window.h"
22
23namespace Kernel {
24class KernelCore;
25class KEvent;
26class KReadableEvent;
27class KWritableEvent;
28} // namespace Kernel
29
30namespace Service::KernelHelpers {
31class ServiceContext;
32} // namespace Service::KernelHelpers
33
34namespace Service::android {
35
36class BufferQueueCore;
37class IProducerListener;
38
39class BufferQueueProducer final : public IBinder {
40public:
41 explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
42 std::shared_ptr<BufferQueueCore> buffer_queue_core_);
43 ~BufferQueueProducer();
44
45 void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
46
47 Kernel::KReadableEvent& GetNativeHandle() override;
48
49public:
50 Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
51 Status SetBufferCount(s32 buffer_count);
52 Status DequeueBuffer(s32* out_slot, android::Fence* out_fence, bool async, u32 width,
53 u32 height, PixelFormat format, u32 usage);
54 Status DetachBuffer(s32 slot);
55 Status DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out_buffer, Fence* out_fence);
56 Status AttachBuffer(s32* outSlot, const std::shared_ptr<GraphicBuffer>& buffer);
57 Status QueueBuffer(s32 slot, const QueueBufferInput& input, QueueBufferOutput* output);
58 void CancelBuffer(s32 slot, const Fence& fence);
59 Status Query(NativeWindow what, s32* out_value);
60 Status Connect(const std::shared_ptr<IProducerListener>& listener, NativeWindowApi api,
61 bool producer_controlled_by_app, QueueBufferOutput* output);
62
63 Status Disconnect(NativeWindowApi api);
64 Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer);
65
66private:
67 BufferQueueProducer(const BufferQueueProducer&) = delete;
68
69 Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* returnFlags) const;
70
71 Kernel::KEvent* buffer_wait_event{};
72 Service::KernelHelpers::ServiceContext& service_context;
73
74 std::shared_ptr<BufferQueueCore> core;
75 BufferQueueDefs::SlotsType& slots;
76 u32 sticky_transform{};
77 std::mutex callback_mutex;
78 s32 next_callback_ticket{};
79 s32 current_callback_ticket{};
80 std::condition_variable_any callback_condition;
81};
82
83} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_slot.h b/src/core/hle/service/nvflinger/buffer_slot.h
new file mode 100644
index 000000000..e3ea58910
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_slot.h
@@ -0,0 +1,39 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/BufferSlot.h
6
7#pragma once
8
9#include <memory>
10
11#include "common/common_types.h"
12#include "core/hle/service/nvflinger/ui/fence.h"
13
14namespace Service::android {
15
16class GraphicBuffer;
17
18enum class BufferState : u32 {
19 Free = 0,
20 Dequeued = 1,
21 Queued = 2,
22 Acquired = 3,
23};
24
25struct BufferSlot final {
26 constexpr BufferSlot() = default;
27
28 std::shared_ptr<GraphicBuffer> graphic_buffer;
29 BufferState buffer_state{BufferState::Free};
30 bool request_buffer_called{};
31 u64 frame_number{};
32 Fence fence;
33 bool acquire_called{};
34 bool needs_cleanup_on_release{};
35 bool attached_by_consumer{};
36 bool is_preallocated{};
37};
38
39} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_transform_flags.h b/src/core/hle/service/nvflinger/buffer_transform_flags.h
new file mode 100644
index 000000000..e8e6300e3
--- /dev/null
+++ b/src/core/hle/service/nvflinger/buffer_transform_flags.h
@@ -0,0 +1,25 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include "common/common_types.h"
7
8namespace Service::android {
9
10enum class BufferTransformFlags : u32 {
11 /// No transform flags are set
12 Unset = 0x00,
13 /// Flip source image horizontally (around the vertical axis)
14 FlipH = 0x01,
15 /// Flip source image vertically (around the horizontal axis)
16 FlipV = 0x02,
17 /// Rotate source image 90 degrees clockwise
18 Rotate90 = 0x04,
19 /// Rotate source image 180 degrees
20 Rotate180 = 0x03,
21 /// Rotate source image 270 degrees clockwise
22 Rotate270 = 0x07,
23};
24
25} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp
new file mode 100644
index 000000000..be65a3f88
--- /dev/null
+++ b/src/core/hle/service/nvflinger/consumer_base.cpp
@@ -0,0 +1,130 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2010 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/ConsumerBase.cpp
6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "core/hle/service/nvflinger/buffer_item.h"
10#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
11#include "core/hle/service/nvflinger/buffer_queue_core.h"
12#include "core/hle/service/nvflinger/consumer_base.h"
13#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
14
15namespace Service::android {
16
17ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
18 : consumer{std::move(consumer_)} {}
19
20ConsumerBase::~ConsumerBase() {
21 std::scoped_lock lock(mutex);
22
23 ASSERT_MSG(is_abandoned, "consumer is not abandoned!");
24}
25
26void ConsumerBase::Connect(bool controlled_by_app) {
27 consumer->Connect(shared_from_this(), controlled_by_app);
28}
29
30void ConsumerBase::FreeBufferLocked(s32 slot_index) {
31 LOG_DEBUG(Service_NVFlinger, "slot_index={}", slot_index);
32
33 slots[slot_index].graphic_buffer = nullptr;
34 slots[slot_index].fence = Fence::NoFence();
35 slots[slot_index].frame_number = 0;
36}
37
38void ConsumerBase::OnFrameAvailable(const BufferItem& item) {
39 std::scoped_lock lock(mutex);
40 LOG_DEBUG(Service_NVFlinger, "called");
41}
42
43void ConsumerBase::OnFrameReplaced(const BufferItem& item) {
44 std::scoped_lock lock(mutex);
45 LOG_DEBUG(Service_NVFlinger, "called");
46}
47
48void ConsumerBase::OnBuffersReleased() {
49 std::scoped_lock lock(mutex);
50 LOG_DEBUG(Service_NVFlinger, "called");
51}
52
53void ConsumerBase::OnSidebandStreamChanged() {}
54
55Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when,
56 u64 max_frame_number) {
57 if (is_abandoned) {
58 LOG_ERROR(Service_NVFlinger, "consumer is abandoned!");
59 return Status::NoInit;
60 }
61
62 Status err = consumer->AcquireBuffer(item, present_when, max_frame_number);
63 if (err != Status::NoError) {
64 return err;
65 }
66
67 if (item->graphic_buffer != nullptr) {
68 if (slots[item->slot].graphic_buffer != nullptr) {
69 FreeBufferLocked(item->slot);
70 }
71 slots[item->slot].graphic_buffer = item->graphic_buffer;
72 }
73
74 slots[item->slot].frame_number = item->frame_number;
75 slots[item->slot].fence = item->fence;
76
77 LOG_DEBUG(Service_NVFlinger, "slot={}", item->slot);
78
79 return Status::NoError;
80}
81
82Status ConsumerBase::AddReleaseFenceLocked(s32 slot,
83 const std::shared_ptr<GraphicBuffer> graphic_buffer,
84 const Fence& fence) {
85 LOG_DEBUG(Service_NVFlinger, "slot={}", slot);
86
87 // If consumer no longer tracks this graphic_buffer, we can safely
88 // drop this fence, as it will never be received by the producer.
89
90 if (!StillTracking(slot, graphic_buffer)) {
91 return Status::NoError;
92 }
93
94 slots[slot].fence = fence;
95
96 return Status::NoError;
97}
98
99Status ConsumerBase::ReleaseBufferLocked(s32 slot,
100 const std::shared_ptr<GraphicBuffer> graphic_buffer) {
101 // If consumer no longer tracks this graphic_buffer (we received a new
102 // buffer on the same slot), the buffer producer is definitely no longer
103 // tracking it.
104
105 if (!StillTracking(slot, graphic_buffer)) {
106 return Status::NoError;
107 }
108
109 LOG_DEBUG(Service_NVFlinger, "slot={}", slot);
110 Status err = consumer->ReleaseBuffer(slot, slots[slot].frame_number, slots[slot].fence);
111 if (err == Status::StaleBufferSlot) {
112 FreeBufferLocked(slot);
113 }
114
115 slots[slot].fence = Fence::NoFence();
116
117 return err;
118}
119
120bool ConsumerBase::StillTracking(s32 slot,
121 const std::shared_ptr<GraphicBuffer> graphic_buffer) const {
122 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
123 return false;
124 }
125
126 return (slots[slot].graphic_buffer != nullptr &&
127 slots[slot].graphic_buffer->Handle() == graphic_buffer->Handle());
128}
129
130} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvflinger/consumer_base.h
new file mode 100644
index 000000000..9ab949420
--- /dev/null
+++ b/src/core/hle/service/nvflinger/consumer_base.h
@@ -0,0 +1,61 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2010 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/ConsumerBase.h
6
7#pragma once
8
9#include <array>
10#include <chrono>
11#include <memory>
12#include <mutex>
13
14#include "common/common_types.h"
15#include "core/hle/service/nvflinger/buffer_queue_defs.h"
16#include "core/hle/service/nvflinger/consumer_listener.h"
17#include "core/hle/service/nvflinger/status.h"
18
19namespace Service::android {
20
21class BufferItem;
22class BufferQueueConsumer;
23
24class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
25public:
26 void Connect(bool controlled_by_app);
27
28protected:
29 explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
30 virtual ~ConsumerBase();
31
32 virtual void OnFrameAvailable(const BufferItem& item) override;
33 virtual void OnFrameReplaced(const BufferItem& item) override;
34 virtual void OnBuffersReleased() override;
35 virtual void OnSidebandStreamChanged() override;
36
37 void FreeBufferLocked(s32 slot_index);
38 Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when,
39 u64 max_frame_number = 0);
40 Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer);
41 bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) const;
42 Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer,
43 const Fence& fence);
44
45 struct Slot final {
46 std::shared_ptr<GraphicBuffer> graphic_buffer;
47 Fence fence;
48 u64 frame_number{};
49 };
50
51protected:
52 std::array<Slot, BufferQueueDefs::NUM_BUFFER_SLOTS> slots;
53
54 bool is_abandoned{};
55
56 std::unique_ptr<BufferQueueConsumer> consumer;
57
58 mutable std::mutex mutex;
59};
60
61} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/consumer_listener.h b/src/core/hle/service/nvflinger/consumer_listener.h
new file mode 100644
index 000000000..b6d1c3e9a
--- /dev/null
+++ b/src/core/hle/service/nvflinger/consumer_listener.h
@@ -0,0 +1,26 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IConsumerListener.h
6
7#pragma once
8
9namespace Service::android {
10
11class BufferItem;
12
13/// ConsumerListener is the interface through which the BufferQueue notifies the consumer of events
14/// that the consumer may wish to react to.
15class IConsumerListener {
16public:
17 IConsumerListener() = default;
18 virtual ~IConsumerListener() = default;
19
20 virtual void OnFrameAvailable(const BufferItem& item) = 0;
21 virtual void OnFrameReplaced(const BufferItem& item) = 0;
22 virtual void OnBuffersReleased() = 0;
23 virtual void OnSidebandStreamChanged() = 0;
24};
25
26}; // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp
new file mode 100644
index 000000000..d4da98ddb
--- /dev/null
+++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.cpp
@@ -0,0 +1,20 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2010 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/IGraphicBufferProducer.cpp
6
7#pragma once
8
9#include "core/hle/service/nvflinger/graphic_buffer_producer.h"
10#include "core/hle/service/nvflinger/parcel.h"
11
12namespace Service::android {
13
14QueueBufferInput::QueueBufferInput(Parcel& parcel) {
15 parcel.ReadFlattened(*this);
16}
17
18QueueBufferOutput::QueueBufferOutput() = default;
19
20} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/graphic_buffer_producer.h b/src/core/hle/service/nvflinger/graphic_buffer_producer.h
new file mode 100644
index 000000000..98d27871c
--- /dev/null
+++ b/src/core/hle/service/nvflinger/graphic_buffer_producer.h
@@ -0,0 +1,76 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2010 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IGraphicBufferProducer.h
6
7#pragma once
8
9#include "common/common_funcs.h"
10#include "common/common_types.h"
11#include "common/math_util.h"
12#include "core/hle/service/nvflinger/ui/fence.h"
13#include "core/hle/service/nvflinger/window.h"
14
15namespace Service::android {
16
17class Parcel;
18
19#pragma pack(push, 1)
20struct QueueBufferInput final {
21 explicit QueueBufferInput(Parcel& parcel);
22
23 void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_,
24 NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_,
25 u32* sticky_transform_, bool* async_, s32* swap_interval_, Fence* fence_) const {
26 *timestamp_ = timestamp;
27 *is_auto_timestamp_ = static_cast<bool>(is_auto_timestamp);
28 *crop_ = crop;
29 *scaling_mode_ = scaling_mode;
30 *transform_ = transform;
31 *sticky_transform_ = sticky_transform;
32 *async_ = static_cast<bool>(async);
33 *swap_interval_ = swap_interval;
34 *fence_ = fence;
35 }
36
37private:
38 s64 timestamp{};
39 s32 is_auto_timestamp{};
40 Common::Rectangle<s32> crop{};
41 NativeWindowScalingMode scaling_mode{};
42 NativeWindowTransform transform{};
43 u32 sticky_transform{};
44 s32 async{};
45 s32 swap_interval{};
46 Fence fence{};
47};
48#pragma pack(pop)
49static_assert(sizeof(QueueBufferInput) == 84, "QueueBufferInput has wrong size");
50
51struct QueueBufferOutput final {
52 QueueBufferOutput();
53
54 void Deflate(u32* width_, u32* height_, u32* transform_hint_, u32* num_pending_buffers_) const {
55 *width_ = width;
56 *height_ = height;
57 *transform_hint_ = transform_hint;
58 *num_pending_buffers_ = num_pending_buffers;
59 }
60
61 void Inflate(u32 width_, u32 height_, u32 transform_hint_, u32 num_pending_buffers_) {
62 width = width_;
63 height = height_;
64 transform_hint = transform_hint_;
65 num_pending_buffers = num_pending_buffers_;
66 }
67
68private:
69 u32 width{};
70 u32 height{};
71 u32 transform_hint{};
72 u32 num_pending_buffers{};
73};
74static_assert(sizeof(QueueBufferOutput) == 16, "QueueBufferOutput has wrong size");
75
76} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp
new file mode 100644
index 000000000..0c937d682
--- /dev/null
+++ b/src/core/hle/service/nvflinger/hos_binder_driver_server.cpp
@@ -0,0 +1,36 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#include <mutex>
5
6#include "common/common_types.h"
7#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
8
9namespace Service::NVFlinger {
10
11HosBinderDriverServer::HosBinderDriverServer(Core::System& system_)
12 : service_context(system_, "HosBinderDriverServer") {}
13
14HosBinderDriverServer::~HosBinderDriverServer() {}
15
16u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) {
17 std::lock_guard lk{lock};
18
19 last_id++;
20
21 producers[last_id] = std::move(binder);
22
23 return last_id;
24}
25
26android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) {
27 std::lock_guard lk{lock};
28
29 if (auto search = producers.find(id); search != producers.end()) {
30 return search->second.get();
31 }
32
33 return {};
34}
35
36} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/hos_binder_driver_server.h b/src/core/hle/service/nvflinger/hos_binder_driver_server.h
new file mode 100644
index 000000000..cbca87fa0
--- /dev/null
+++ b/src/core/hle/service/nvflinger/hos_binder_driver_server.h
@@ -0,0 +1,37 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include <memory>
7#include <mutex>
8#include <unordered_map>
9
10#include "common/common_types.h"
11#include "core/hle/service/kernel_helpers.h"
12#include "core/hle/service/nvflinger/binder.h"
13
14namespace Core {
15class System;
16}
17
18namespace Service::NVFlinger {
19
20class HosBinderDriverServer final {
21public:
22 explicit HosBinderDriverServer(Core::System& system_);
23 ~HosBinderDriverServer();
24
25 u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder);
26
27 android::IBinder* TryGetProducer(u64 id);
28
29private:
30 KernelHelpers::ServiceContext service_context;
31
32 std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers;
33 std::mutex lock;
34 u64 last_id{};
35};
36
37} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 01e69de30..76ce1fbfd 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -1,6 +1,5 @@
1// Copyright 2018 yuzu emulator team 1// SPDX-License-Identifier: GPL-3.0-or-later
2// Licensed under GPLv2 or any later version 2// Copyright 2021 yuzu Emulator Project
3// Refer to the license.txt file included.
4 3
5#include <algorithm> 4#include <algorithm>
6#include <optional> 5#include <optional>
@@ -16,8 +15,11 @@
16#include "core/hle/kernel/k_readable_event.h" 15#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 16#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
18#include "core/hle/service/nvdrv/nvdrv.h" 17#include "core/hle/service/nvdrv/nvdrv.h"
19#include "core/hle/service/nvflinger/buffer_queue.h" 18#include "core/hle/service/nvflinger/buffer_item_consumer.h"
19#include "core/hle/service/nvflinger/buffer_queue_core.h"
20#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
20#include "core/hle/service/nvflinger/nvflinger.h" 21#include "core/hle/service/nvflinger/nvflinger.h"
22#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
21#include "core/hle/service/vi/display/vi_display.h" 23#include "core/hle/service/vi/display/vi_display.h"
22#include "core/hle/service/vi/layer/vi_layer.h" 24#include "core/hle/service/vi/layer/vi_layer.h"
23#include "video_core/gpu.h" 25#include "video_core/gpu.h"
@@ -53,13 +55,14 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) {
53 } 55 }
54} 56}
55 57
56NVFlinger::NVFlinger(Core::System& system_) 58NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_)
57 : system(system_), service_context(system_, "nvflinger") { 59 : system(system_), service_context(system_, "nvflinger"),
58 displays.emplace_back(0, "Default", service_context, system); 60 hos_binder_driver_server(hos_binder_driver_server_) {
59 displays.emplace_back(1, "External", service_context, system); 61 displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system);
60 displays.emplace_back(2, "Edid", service_context, system); 62 displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system);
61 displays.emplace_back(3, "Internal", service_context, system); 63 displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system);
62 displays.emplace_back(4, "Null", service_context, system); 64 displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system);
65 displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system);
63 guard = std::make_shared<std::mutex>(); 66 guard = std::make_shared<std::mutex>();
64 67
65 // Schedule the screen composition events 68 // Schedule the screen composition events
@@ -83,12 +86,15 @@ NVFlinger::NVFlinger(Core::System& system_)
83} 86}
84 87
85NVFlinger::~NVFlinger() { 88NVFlinger::~NVFlinger() {
86 for (auto& buffer_queue : buffer_queues) {
87 buffer_queue->Disconnect();
88 }
89 if (!system.IsMulticore()) { 89 if (!system.IsMulticore()) {
90 system.CoreTiming().UnscheduleEvent(composition_event, 0); 90 system.CoreTiming().UnscheduleEvent(composition_event, 0);
91 } 91 }
92
93 for (auto& display : displays) {
94 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
95 display.GetLayer(layer).Core().NotifyShutdown();
96 }
97 }
92} 98}
93 99
94void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { 100void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
@@ -125,10 +131,8 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
125} 131}
126 132
127void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { 133void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
128 const u32 buffer_queue_id = next_buffer_queue_id++; 134 const auto buffer_id = next_buffer_queue_id++;
129 buffer_queues.emplace_back( 135 display.CreateLayer(layer_id, buffer_id);
130 std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id, service_context));
131 display.CreateLayer(layer_id, *buffer_queues.back());
132} 136}
133 137
134void NVFlinger::CloseLayer(u64 layer_id) { 138void NVFlinger::CloseLayer(u64 layer_id) {
@@ -147,7 +151,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
147 return std::nullopt; 151 return std::nullopt;
148 } 152 }
149 153
150 return layer->GetBufferQueue().GetId(); 154 return layer->GetBinderId();
151} 155}
152 156
153Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) { 157Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) {
@@ -161,18 +165,6 @@ Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) {
161 return &display->GetVSyncEvent(); 165 return &display->GetVSyncEvent();
162} 166}
163 167
164BufferQueue* NVFlinger::FindBufferQueue(u32 id) {
165 const auto lock_guard = Lock();
166 const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(),
167 [id](const auto& queue) { return queue->GetId() == id; });
168
169 if (itr == buffer_queues.end()) {
170 return nullptr;
171 }
172
173 return itr->get();
174}
175
176VI::Display* NVFlinger::FindDisplay(u64 display_id) { 168VI::Display* NVFlinger::FindDisplay(u64 display_id) {
177 const auto itr = 169 const auto itr =
178 std::find_if(displays.begin(), displays.end(), 170 std::find_if(displays.begin(), displays.end(),
@@ -246,23 +238,22 @@ void NVFlinger::Compose() {
246 238
247 // TODO(Subv): Support more than 1 layer. 239 // TODO(Subv): Support more than 1 layer.
248 VI::Layer& layer = display.GetLayer(0); 240 VI::Layer& layer = display.GetLayer(0);
249 auto& buffer_queue = layer.GetBufferQueue();
250 241
251 // Search for a queued buffer and acquire it 242 android::BufferItem buffer{};
252 auto buffer = buffer_queue.AcquireBuffer(); 243 const auto status = layer.GetConsumer().AcquireBuffer(&buffer, {}, false);
253 244
254 if (!buffer) { 245 if (status != android::Status::NoError) {
255 continue; 246 continue;
256 } 247 }
257 248
258 const auto& igbp_buffer = buffer->get().igbp_buffer; 249 const auto& igbp_buffer = *buffer.graphic_buffer;
259 250
260 if (!system.IsPoweredOn()) { 251 if (!system.IsPoweredOn()) {
261 return; // We are likely shutting down 252 return; // We are likely shutting down
262 } 253 }
263 254
264 auto& gpu = system.GPU(); 255 auto& gpu = system.GPU();
265 const auto& multi_fence = buffer->get().multi_fence; 256 const auto& multi_fence = buffer.fence;
266 guard->unlock(); 257 guard->unlock();
267 for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) { 258 for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
268 const auto& fence = multi_fence.fences[fence_id]; 259 const auto& fence = multi_fence.fences[fence_id];
@@ -278,12 +269,18 @@ void NVFlinger::Compose() {
278 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); 269 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
279 ASSERT(nvdisp); 270 ASSERT(nvdisp);
280 271
281 nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.external_format, 272 Common::Rectangle<int> crop_rect{
282 igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, 273 static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()),
283 buffer->get().transform, buffer->get().crop_rect); 274 static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())};
275
276 nvdisp->flip(igbp_buffer.BufferId(), igbp_buffer.Offset(), igbp_buffer.ExternalFormat(),
277 igbp_buffer.Width(), igbp_buffer.Height(), igbp_buffer.Stride(),
278 static_cast<android::BufferTransformFlags>(buffer.transform), crop_rect);
279
280 swap_interval = buffer.swap_interval;
284 281
285 swap_interval = buffer->get().swap_interval; 282 auto fence = android::Fence::NoFence();
286 buffer_queue.ReleaseBuffer(buffer->get().slot); 283 layer.GetConsumer().ReleaseBuffer(buffer, fence);
287 } 284 }
288} 285}
289 286
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 7935cf773..ed160f6f9 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -1,6 +1,5 @@
1// Copyright 2018 yuzu emulator team 1// SPDX-License-Identifier: GPL-3.0-or-later
2// Licensed under GPLv2 or any later version 2// Copyright 2021 yuzu Emulator Project
3// Refer to the license.txt file included.
4 3
5#pragma once 4#pragma once
6 5
@@ -37,13 +36,16 @@ class Display;
37class Layer; 36class Layer;
38} // namespace Service::VI 37} // namespace Service::VI
39 38
40namespace Service::NVFlinger { 39namespace Service::android {
40class BufferQueueCore;
41class BufferQueueProducer;
42} // namespace Service::android
41 43
42class BufferQueue; 44namespace Service::NVFlinger {
43 45
44class NVFlinger final { 46class NVFlinger final {
45public: 47public:
46 explicit NVFlinger(Core::System& system_); 48 explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
47 ~NVFlinger(); 49 ~NVFlinger();
48 50
49 /// Sets the NVDrv module instance to use to send buffers to the GPU. 51 /// Sets the NVDrv module instance to use to send buffers to the GPU.
@@ -72,9 +74,6 @@ public:
72 /// If an invalid display ID is provided, then nullptr is returned. 74 /// If an invalid display ID is provided, then nullptr is returned.
73 [[nodiscard]] Kernel::KReadableEvent* FindVsyncEvent(u64 display_id); 75 [[nodiscard]] Kernel::KReadableEvent* FindVsyncEvent(u64 display_id);
74 76
75 /// Obtains a buffer queue identified by the ID.
76 [[nodiscard]] BufferQueue* FindBufferQueue(u32 id);
77
78 /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when 77 /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
79 /// finished. 78 /// finished.
80 void Compose(); 79 void Compose();
@@ -82,6 +81,12 @@ public:
82 [[nodiscard]] s64 GetNextTicks() const; 81 [[nodiscard]] s64 GetNextTicks() const;
83 82
84private: 83private:
84 struct Layer {
85 std::unique_ptr<android::BufferQueueCore> core;
86 std::unique_ptr<android::BufferQueueProducer> producer;
87 };
88
89private:
85 [[nodiscard]] std::unique_lock<std::mutex> Lock() const { 90 [[nodiscard]] std::unique_lock<std::mutex> Lock() const {
86 return std::unique_lock{*guard}; 91 return std::unique_lock{*guard};
87 } 92 }
@@ -111,7 +116,6 @@ private:
111 std::shared_ptr<Nvidia::Module> nvdrv; 116 std::shared_ptr<Nvidia::Module> nvdrv;
112 117
113 std::list<VI::Display> displays; 118 std::list<VI::Display> displays;
114 std::vector<std::unique_ptr<BufferQueue>> buffer_queues;
115 119
116 /// Id to use for the next layer that is created, this counter is shared among all displays. 120 /// Id to use for the next layer that is created, this counter is shared among all displays.
117 u64 next_layer_id = 1; 121 u64 next_layer_id = 1;
@@ -131,6 +135,8 @@ private:
131 std::jthread vsync_thread; 135 std::jthread vsync_thread;
132 136
133 KernelHelpers::ServiceContext service_context; 137 KernelHelpers::ServiceContext service_context;
138
139 HosBinderDriverServer& hos_binder_driver_server;
134}; 140};
135 141
136} // namespace Service::NVFlinger 142} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h
new file mode 100644
index 000000000..aa36e6479
--- /dev/null
+++ b/src/core/hle/service/nvflinger/parcel.h
@@ -0,0 +1,172 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include <memory>
7#include <vector>
8
9#include "common/alignment.h"
10#include "common/assert.h"
11#include "common/common_types.h"
12
13namespace Service::android {
14
15class Parcel final {
16public:
17 static constexpr std::size_t DefaultBufferSize = 0x40;
18
19 Parcel() : buffer(DefaultBufferSize) {}
20
21 template <typename T>
22 explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) {
23 Write(out_data);
24 }
25
26 explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) {
27 DeserializeHeader();
28 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
29 }
30
31 template <typename T>
32 void Read(T& val) {
33 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
34 ASSERT(read_index + sizeof(T) <= buffer.size());
35
36 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
37 read_index += sizeof(T);
38 read_index = Common::AlignUp(read_index, 4);
39 }
40
41 template <typename T>
42 T Read() {
43 T val;
44 Read(val);
45 return val;
46 }
47
48 template <typename T>
49 void ReadFlattened(T& val) {
50 const auto flattened_size = Read<s64>();
51 ASSERT(sizeof(T) == flattened_size);
52 Read(val);
53 }
54
55 template <typename T>
56 T ReadFlattened() {
57 T val;
58 ReadFlattened(val);
59 return val;
60 }
61
62 template <typename T>
63 T ReadUnaligned() {
64 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
65 ASSERT(read_index + sizeof(T) <= buffer.size());
66
67 T val;
68 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
69 read_index += sizeof(T);
70 return val;
71 }
72
73 template <typename T>
74 const std::shared_ptr<T> ReadObject() {
75 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
76
77 const auto is_valid{Read<bool>()};
78
79 if (is_valid) {
80 auto result = std::make_shared<T>();
81 ReadFlattened(*result);
82 return result;
83 }
84
85 return {};
86 }
87
88 std::u16string ReadInterfaceToken() {
89 [[maybe_unused]] const u32 unknown = Read<u32>();
90 const u32 length = Read<u32>();
91
92 std::u16string token;
93 token.reserve(length + 1);
94
95 for (u32 ch = 0; ch < length + 1; ++ch) {
96 token.push_back(ReadUnaligned<u16>());
97 }
98
99 read_index = Common::AlignUp(read_index, 4);
100
101 return token;
102 }
103
104 template <typename T>
105 void Write(const T& val) {
106 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
107
108 if (buffer.size() < write_index + sizeof(T)) {
109 buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
110 }
111
112 std::memcpy(buffer.data() + write_index, &val, sizeof(T));
113 write_index += sizeof(T);
114 write_index = Common::AlignUp(write_index, 4);
115 }
116
117 template <typename T>
118 void WriteObject(const T* ptr) {
119 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
120
121 if (!ptr) {
122 Write<u32>(0);
123 return;
124 }
125
126 Write<u32>(1);
127 Write<s64>(sizeof(T));
128 Write(*ptr);
129 }
130
131 template <typename T>
132 void WriteObject(const std::shared_ptr<T> ptr) {
133 WriteObject(ptr.get());
134 }
135
136 void DeserializeHeader() {
137 ASSERT(buffer.size() > sizeof(Header));
138
139 Header header{};
140 std::memcpy(&header, buffer.data(), sizeof(Header));
141
142 read_index = header.data_offset;
143 }
144
145 std::vector<u8> Serialize() const {
146 ASSERT(read_index == 0);
147
148 Header header{};
149 header.data_size = static_cast<u32>(write_index - sizeof(Header));
150 header.data_offset = sizeof(Header);
151 header.objects_size = 4;
152 header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
153 std::memcpy(buffer.data(), &header, sizeof(Header));
154
155 return buffer;
156 }
157
158private:
159 struct Header {
160 u32 data_size;
161 u32 data_offset;
162 u32 objects_size;
163 u32 objects_offset;
164 };
165 static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
166
167 mutable std::vector<u8> buffer;
168 std::size_t read_index = 0;
169 std::size_t write_index = sizeof(Header);
170};
171
172} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/pixel_format.h b/src/core/hle/service/nvflinger/pixel_format.h
new file mode 100644
index 000000000..8a77d8bea
--- /dev/null
+++ b/src/core/hle/service/nvflinger/pixel_format.h
@@ -0,0 +1,21 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include "common/common_types.h"
7
8namespace Service::android {
9
10enum class PixelFormat : u32 {
11 NoFormat = 0,
12 Rgba8888 = 1,
13 Rgbx8888 = 2,
14 Rgb888 = 3,
15 Rgb565 = 4,
16 Bgra8888 = 5,
17 Rgba5551 = 6,
18 Rgba4444 = 7,
19};
20
21} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/producer_listener.h b/src/core/hle/service/nvflinger/producer_listener.h
new file mode 100644
index 000000000..468e06431
--- /dev/null
+++ b/src/core/hle/service/nvflinger/producer_listener.h
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2014 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/IProducerListener.h
6
7#pragma once
8
9namespace Service::android {
10
11class IProducerListener {
12public:
13 virtual void OnBufferReleased() = 0;
14};
15
16} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/status.h b/src/core/hle/service/nvflinger/status.h
new file mode 100644
index 000000000..a003eda89
--- /dev/null
+++ b/src/core/hle/service/nvflinger/status.h
@@ -0,0 +1,28 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8
9namespace Service::android {
10
11enum class Status : s32 {
12 None = 0,
13 NoError = 0,
14 StaleBufferSlot = 1,
15 NoBufferAvailable = 2,
16 PresentLater = 3,
17 WouldBlock = -11,
18 NoMemory = -12,
19 Busy = -16,
20 NoInit = -19,
21 BadValue = -22,
22 InvalidOperation = -37,
23 BufferNeedsReallocation = 1,
24 ReleaseAllBuffers = 2,
25};
26DECLARE_ENUM_FLAG_OPERATORS(Status);
27
28} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/ui/fence.h b/src/core/hle/service/nvflinger/ui/fence.h
new file mode 100644
index 000000000..4a74e26a3
--- /dev/null
+++ b/src/core/hle/service/nvflinger/ui/fence.h
@@ -0,0 +1,32 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2012 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/ui/Fence.h
6
7#pragma once
8
9#include <array>
10
11#include "common/common_types.h"
12#include "core/hle/service/nvdrv/nvdata.h"
13
14namespace Service::android {
15
16class Fence {
17public:
18 constexpr Fence() = default;
19
20 static constexpr Fence NoFence() {
21 Fence fence;
22 fence.fences[0].id = -1;
23 return fence;
24 }
25
26public:
27 u32 num_fences{};
28 std::array<Service::Nvidia::NvFence, 4> fences{};
29};
30static_assert(sizeof(Fence) == 36, "Fence has wrong size");
31
32} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/ui/graphic_buffer.h b/src/core/hle/service/nvflinger/ui/graphic_buffer.h
new file mode 100644
index 000000000..7abbf78ba
--- /dev/null
+++ b/src/core/hle/service/nvflinger/ui/graphic_buffer.h
@@ -0,0 +1,100 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3// Copyright 2007 The Android Open Source Project
4// Parts of this implementation were base on:
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/ui/GraphicBuffer.h
6
7#pragma once
8
9#include "common/common_funcs.h"
10#include "common/common_types.h"
11#include "core/hle/service/nvflinger/pixel_format.h"
12
13namespace Service::android {
14
15class GraphicBuffer final {
16public:
17 constexpr GraphicBuffer() = default;
18
19 constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
20 : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_},
21 usage{static_cast<s32>(usage_)} {}
22
23 constexpr u32 Width() const {
24 return static_cast<u32>(width);
25 }
26
27 constexpr u32 Height() const {
28 return static_cast<u32>(height);
29 }
30
31 constexpr u32 Stride() const {
32 return static_cast<u32>(stride);
33 }
34
35 constexpr u32 Usage() const {
36 return static_cast<u32>(usage);
37 }
38
39 constexpr PixelFormat Format() const {
40 return format;
41 }
42
43 constexpr u32 BufferId() const {
44 return buffer_id;
45 }
46
47 constexpr PixelFormat ExternalFormat() const {
48 return external_format;
49 }
50
51 constexpr u32 Handle() const {
52 return handle;
53 }
54
55 constexpr u32 Offset() const {
56 return offset;
57 }
58
59 constexpr bool NeedsReallocation(u32 width_, u32 height_, PixelFormat format_,
60 u32 usage_) const {
61 if (static_cast<s32>(width_) != width) {
62 return true;
63 }
64
65 if (static_cast<s32>(height_) != height) {
66 return true;
67 }
68
69 if (format_ != format) {
70 return true;
71 }
72
73 if ((static_cast<u32>(usage) & usage_) != usage_) {
74 return true;
75 }
76
77 return false;
78 }
79
80private:
81 u32 magic{};
82 s32 width{};
83 s32 height{};
84 s32 stride{};
85 PixelFormat format{};
86 s32 usage{};
87 INSERT_PADDING_WORDS(1);
88 u32 index{};
89 INSERT_PADDING_WORDS(3);
90 u32 buffer_id{};
91 INSERT_PADDING_WORDS(6);
92 PixelFormat external_format{};
93 INSERT_PADDING_WORDS(10);
94 u32 handle{};
95 u32 offset{};
96 INSERT_PADDING_WORDS(60);
97};
98static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size");
99
100} // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/window.h b/src/core/hle/service/nvflinger/window.h
new file mode 100644
index 000000000..e26f8160e
--- /dev/null
+++ b/src/core/hle/service/nvflinger/window.h
@@ -0,0 +1,53 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8
9namespace Service::android {
10
11/// Attributes queryable with Query
12enum class NativeWindow : s32 {
13 Width = 0,
14 Height = 1,
15 Format = 2,
16 MinUndequeedBuffers = 3,
17 QueuesToWindowComposer = 4,
18 ConcreteType = 5,
19 DefaultWidth = 6,
20 DefaultHeight = 7,
21 TransformHint = 8,
22 ConsumerRunningBehind = 9,
23 ConsumerUsageBits = 10,
24 StickyTransform = 11,
25 DefaultDataSpace = 12,
26 BufferAge = 13,
27};
28
29/// Parameter for Connect/Disconnect
30enum class NativeWindowApi : s32 {
31 NoConnectedApi = 0,
32 Egl = 1,
33 Cpu = 2,
34 Media = 3,
35 Camera = 4,
36};
37
38/// Scaling mode parameter for QueueBuffer
39enum class NativeWindowScalingMode : s32 {
40 Freeze = 0,
41 ScaleToWindow = 1,
42 ScaleCrop = 2,
43 NoScaleCrop = 3,
44};
45
46/// Transform parameter for QueueBuffer
47enum class NativeWindowTransform : u32 {
48 None = 0x0,
49 InverseDisplay = 0x08,
50};
51DECLARE_ENUM_FLAG_OPERATORS(NativeWindowTransform);
52
53} // namespace Service::android
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index eb1138313..ab3286db9 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -49,6 +49,7 @@
49#include "core/hle/service/npns/npns.h" 49#include "core/hle/service/npns/npns.h"
50#include "core/hle/service/ns/ns.h" 50#include "core/hle/service/ns/ns.h"
51#include "core/hle/service/nvdrv/nvdrv.h" 51#include "core/hle/service/nvdrv/nvdrv.h"
52#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
52#include "core/hle/service/nvflinger/nvflinger.h" 53#include "core/hle/service/nvflinger/nvflinger.h"
53#include "core/hle/service/olsc/olsc.h" 54#include "core/hle/service/olsc/olsc.h"
54#include "core/hle/service/pcie/pcie.h" 55#include "core/hle/service/pcie/pcie.h"
@@ -230,7 +231,8 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& sessi
230 231
231/// Initialize Services 232/// Initialize Services
232Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) 233Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system)
233 : nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} { 234 : hos_binder_driver_server{std::make_unique<NVFlinger::HosBinderDriverServer>(system)},
235 nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system, *hos_binder_driver_server)} {
234 236
235 // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it 237 // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
236 // here and pass it into the respective InstallInterfaces functions. 238 // here and pass it into the respective InstallInterfaces functions.
@@ -290,7 +292,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
290 SSL::InstallInterfaces(*sm, system); 292 SSL::InstallInterfaces(*sm, system);
291 Time::InstallInterfaces(system); 293 Time::InstallInterfaces(system);
292 USB::InstallInterfaces(*sm, system); 294 USB::InstallInterfaces(*sm, system);
293 VI::InstallInterfaces(*sm, system, *nv_flinger); 295 VI::InstallInterfaces(*sm, system, *nv_flinger, *hos_binder_driver_server);
294 WLAN::InstallInterfaces(*sm, system); 296 WLAN::InstallInterfaces(*sm, system);
295} 297}
296 298
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index c9d6b879d..b9ab2c465 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -33,8 +33,9 @@ class FileSystemController;
33} 33}
34 34
35namespace NVFlinger { 35namespace NVFlinger {
36class HosBinderDriverServer;
36class NVFlinger; 37class NVFlinger;
37} 38} // namespace NVFlinger
38 39
39namespace SM { 40namespace SM {
40class ServiceManager; 41class ServiceManager;
@@ -236,6 +237,7 @@ public:
236 ~Services(); 237 ~Services();
237 238
238private: 239private:
240 std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server;
239 std::unique_ptr<NVFlinger::NVFlinger> nv_flinger; 241 std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;
240}; 242};
241 243
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 3dbac5a23..fc93fb743 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -10,7 +10,6 @@
10#include <fmt/format.h> 10#include <fmt/format.h>
11 11
12#include "common/microprofile.h" 12#include "common/microprofile.h"
13#include "common/thread.h"
14#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
15#include "core/hle/kernel/k_thread.h" 14#include "core/hle/kernel/k_thread.h"
16#include "core/hle/service/sockets/bsd.h" 15#include "core/hle/service/sockets/bsd.h"
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index b7705c02a..558022511 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -13,14 +13,34 @@
13#include "core/hle/kernel/k_readable_event.h" 13#include "core/hle/kernel/k_readable_event.h"
14#include "core/hle/kernel/k_writable_event.h" 14#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/service/kernel_helpers.h" 15#include "core/hle/service/kernel_helpers.h"
16#include "core/hle/service/nvflinger/buffer_item_consumer.h"
17#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
18#include "core/hle/service/nvflinger/buffer_queue_core.h"
19#include "core/hle/service/nvflinger/buffer_queue_producer.h"
20#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
16#include "core/hle/service/vi/display/vi_display.h" 21#include "core/hle/service/vi/display/vi_display.h"
17#include "core/hle/service/vi/layer/vi_layer.h" 22#include "core/hle/service/vi/layer/vi_layer.h"
18 23
19namespace Service::VI { 24namespace Service::VI {
20 25
21Display::Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_, 26struct BufferQueue {
22 Core::System& system_) 27 std::shared_ptr<android::BufferQueueCore> core;
23 : display_id{id}, name{std::move(name_)}, service_context{service_context_} { 28 std::unique_ptr<android::BufferQueueProducer> producer;
29 std::unique_ptr<android::BufferQueueConsumer> consumer;
30};
31
32static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context) {
33 auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
34 return {buffer_queue_core,
35 std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core),
36 std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
37}
38
39Display::Display(u64 id, std::string name_,
40 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_,
41 KernelHelpers::ServiceContext& service_context_, Core::System& system_)
42 : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_},
43 service_context{service_context_} {
24 vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); 44 vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id));
25} 45}
26 46
@@ -44,21 +64,29 @@ void Display::SignalVSyncEvent() {
44 vsync_event->GetWritableEvent().Signal(); 64 vsync_event->GetWritableEvent().Signal();
45} 65}
46 66
47void Display::CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue) { 67void Display::CreateLayer(u64 layer_id, u32 binder_id) {
48 // TODO(Subv): Support more than 1 layer.
49 ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); 68 ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
50 69
51 layers.emplace_back(std::make_shared<Layer>(layer_id, buffer_queue)); 70 auto [core, producer, consumer] = CreateBufferQueue(service_context);
71
72 auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
73 buffer_item_consumer->Connect(false);
74
75 layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer,
76 std::move(buffer_item_consumer)));
77
78 hos_binder_driver_server.RegisterProducer(std::move(producer));
52} 79}
53 80
54void Display::CloseLayer(u64 layer_id) { 81void Display::CloseLayer(u64 layer_id) {
55 std::erase_if(layers, [layer_id](const auto& layer) { return layer->GetID() == layer_id; }); 82 std::erase_if(layers,
83 [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
56} 84}
57 85
58Layer* Display::FindLayer(u64 layer_id) { 86Layer* Display::FindLayer(u64 layer_id) {
59 const auto itr = 87 const auto itr =
60 std::find_if(layers.begin(), layers.end(), [layer_id](const std::shared_ptr<Layer>& layer) { 88 std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
61 return layer->GetID() == layer_id; 89 return layer->GetLayerId() == layer_id;
62 }); 90 });
63 91
64 if (itr == layers.end()) { 92 if (itr == layers.end()) {
@@ -70,8 +98,8 @@ Layer* Display::FindLayer(u64 layer_id) {
70 98
71const Layer* Display::FindLayer(u64 layer_id) const { 99const Layer* Display::FindLayer(u64 layer_id) const {
72 const auto itr = 100 const auto itr =
73 std::find_if(layers.begin(), layers.end(), [layer_id](const std::shared_ptr<Layer>& layer) { 101 std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
74 return layer->GetID() == layer_id; 102 return layer->GetLayerId() == layer_id;
75 }); 103 });
76 104
77 if (itr == layers.end()) { 105 if (itr == layers.end()) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 329f4ba86..e93d084ee 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -15,12 +15,17 @@ namespace Kernel {
15class KEvent; 15class KEvent;
16} 16}
17 17
18namespace Service::NVFlinger { 18namespace Service::android {
19class BufferQueue; 19class BufferQueueProducer;
20} 20}
21
21namespace Service::KernelHelpers { 22namespace Service::KernelHelpers {
22class ServiceContext; 23class ServiceContext;
23} // namespace Service::KernelHelpers 24}
25
26namespace Service::NVFlinger {
27class HosBinderDriverServer;
28}
24 29
25namespace Service::VI { 30namespace Service::VI {
26 31
@@ -35,12 +40,13 @@ public:
35 /// Constructs a display with a given unique ID and name. 40 /// Constructs a display with a given unique ID and name.
36 /// 41 ///
37 /// @param id The unique ID for this display. 42 /// @param id The unique ID for this display.
43 /// @param hos_binder_driver_server_ NVFlinger HOSBinderDriver server instance.
38 /// @param service_context_ The ServiceContext for the owning service. 44 /// @param service_context_ The ServiceContext for the owning service.
39 /// @param name_ The name for this display. 45 /// @param name_ The name for this display.
40 /// @param system_ The global system instance. 46 /// @param system_ The global system instance.
41 /// 47 ///
42 Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_, 48 Display(u64 id, std::string name_, NVFlinger::HosBinderDriverServer& hos_binder_driver_server_,
43 Core::System& system_); 49 KernelHelpers::ServiceContext& service_context_, Core::System& system_);
44 ~Display(); 50 ~Display();
45 51
46 /// Gets the unique ID assigned to this display. 52 /// Gets the unique ID assigned to this display.
@@ -64,6 +70,10 @@ public:
64 /// Gets a layer for this display based off an index. 70 /// Gets a layer for this display based off an index.
65 const Layer& GetLayer(std::size_t index) const; 71 const Layer& GetLayer(std::size_t index) const;
66 72
73 std::size_t GetNumLayers() const {
74 return layers.size();
75 }
76
67 /// Gets the readable vsync event. 77 /// Gets the readable vsync event.
68 Kernel::KReadableEvent& GetVSyncEvent(); 78 Kernel::KReadableEvent& GetVSyncEvent();
69 79
@@ -72,10 +82,10 @@ public:
72 82
73 /// Creates and adds a layer to this display with the given ID. 83 /// Creates and adds a layer to this display with the given ID.
74 /// 84 ///
75 /// @param layer_id The ID to assign to the created layer. 85 /// @param layer_id The ID to assign to the created layer.
76 /// @param buffer_queue The buffer queue for the layer instance to use. 86 /// @param binder_id The ID assigned to the buffer queue.
77 /// 87 ///
78 void CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue); 88 void CreateLayer(u64 layer_id, u32 binder_id);
79 89
80 /// Closes and removes a layer from this display with the given ID. 90 /// Closes and removes a layer from this display with the given ID.
81 /// 91 ///
@@ -104,9 +114,10 @@ public:
104private: 114private:
105 u64 display_id; 115 u64 display_id;
106 std::string name; 116 std::string name;
117 NVFlinger::HosBinderDriverServer& hos_binder_driver_server;
107 KernelHelpers::ServiceContext& service_context; 118 KernelHelpers::ServiceContext& service_context;
108 119
109 std::vector<std::shared_ptr<Layer>> layers; 120 std::vector<std::unique_ptr<Layer>> layers;
110 Kernel::KEvent* vsync_event{}; 121 Kernel::KEvent* vsync_event{};
111}; 122};
112 123
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp
index 9bc382587..93858e91f 100644
--- a/src/core/hle/service/vi/layer/vi_layer.cpp
+++ b/src/core/hle/service/vi/layer/vi_layer.cpp
@@ -6,7 +6,11 @@
6 6
7namespace Service::VI { 7namespace Service::VI {
8 8
9Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : layer_id{id}, buffer_queue{queue} {} 9Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
10 android::BufferQueueProducer& binder_,
11 std::shared_ptr<android::BufferItemConsumer>&& consumer_)
12 : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
13 consumer_)} {}
10 14
11Layer::~Layer() = default; 15Layer::~Layer() = default;
12 16
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
index ebdd85505..c28b14450 100644
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ b/src/core/hle/service/vi/layer/vi_layer.h
@@ -4,11 +4,15 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
9namespace Service::NVFlinger { 11namespace Service::android {
10class BufferQueue; 12class BufferItemConsumer;
11} 13class BufferQueueCore;
14class BufferQueueProducer;
15} // namespace Service::android
12 16
13namespace Service::VI { 17namespace Service::VI {
14 18
@@ -17,10 +21,13 @@ class Layer {
17public: 21public:
18 /// Constructs a layer with a given ID and buffer queue. 22 /// Constructs a layer with a given ID and buffer queue.
19 /// 23 ///
20 /// @param id The ID to assign to this layer. 24 /// @param layer_id_ The ID to assign to this layer.
21 /// @param queue The buffer queue for this layer to use. 25 /// @param binder_id_ The binder ID to assign to this layer.
26 /// @param binder_ The buffer producer queue for this layer to use.
22 /// 27 ///
23 Layer(u64 id, NVFlinger::BufferQueue& queue); 28 Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
29 android::BufferQueueProducer& binder_,
30 std::shared_ptr<android::BufferItemConsumer>&& consumer_);
24 ~Layer(); 31 ~Layer();
25 32
26 Layer(const Layer&) = delete; 33 Layer(const Layer&) = delete;
@@ -30,23 +37,47 @@ public:
30 Layer& operator=(Layer&&) = delete; 37 Layer& operator=(Layer&&) = delete;
31 38
32 /// Gets the ID for this layer. 39 /// Gets the ID for this layer.
33 u64 GetID() const { 40 u64 GetLayerId() const {
34 return layer_id; 41 return layer_id;
35 } 42 }
36 43
44 /// Gets the binder ID for this layer.
45 u32 GetBinderId() const {
46 return binder_id;
47 }
48
37 /// Gets a reference to the buffer queue this layer is using. 49 /// Gets a reference to the buffer queue this layer is using.
38 NVFlinger::BufferQueue& GetBufferQueue() { 50 android::BufferQueueProducer& GetBufferQueue() {
39 return buffer_queue; 51 return binder;
40 } 52 }
41 53
42 /// Gets a const reference to the buffer queue this layer is using. 54 /// Gets a const reference to the buffer queue this layer is using.
43 const NVFlinger::BufferQueue& GetBufferQueue() const { 55 const android::BufferQueueProducer& GetBufferQueue() const {
44 return buffer_queue; 56 return binder;
57 }
58
59 android::BufferItemConsumer& GetConsumer() {
60 return *consumer;
61 }
62
63 const android::BufferItemConsumer& GetConsumer() const {
64 return *consumer;
65 }
66
67 android::BufferQueueCore& Core() {
68 return core;
69 }
70
71 const android::BufferQueueCore& Core() const {
72 return core;
45 } 73 }
46 74
47private: 75private:
48 u64 layer_id; 76 const u64 layer_id;
49 NVFlinger::BufferQueue& buffer_queue; 77 const u32 binder_id;
78 android::BufferQueueCore& core;
79 android::BufferQueueProducer& binder;
80 std::shared_ptr<android::BufferItemConsumer> consumer;
50}; 81};
51 82
52} // namespace Service::VI 83} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 75ee3e5e4..430cbc546 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -22,8 +22,11 @@
22#include "core/hle/kernel/k_readable_event.h" 22#include "core/hle/kernel/k_readable_event.h"
23#include "core/hle/kernel/k_thread.h" 23#include "core/hle/kernel/k_thread.h"
24#include "core/hle/service/nvdrv/nvdata.h" 24#include "core/hle/service/nvdrv/nvdata.h"
25#include "core/hle/service/nvflinger/buffer_queue.h" 25#include "core/hle/service/nvflinger/binder.h"
26#include "core/hle/service/nvflinger/buffer_queue_producer.h"
27#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
26#include "core/hle/service/nvflinger/nvflinger.h" 28#include "core/hle/service/nvflinger/nvflinger.h"
29#include "core/hle/service/nvflinger/parcel.h"
27#include "core/hle/service/service.h" 30#include "core/hle/service/service.h"
28#include "core/hle/service/vi/vi.h" 31#include "core/hle/service/vi/vi.h"
29#include "core/hle/service/vi/vi_m.h" 32#include "core/hle/service/vi/vi_m.h"
@@ -57,447 +60,24 @@ struct DisplayInfo {
57}; 60};
58static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); 61static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
59 62
60class Parcel { 63class NativeWindow final {
61public: 64public:
62 // This default size was chosen arbitrarily. 65 constexpr explicit NativeWindow(u32 id_) : id{id_} {}
63 static constexpr std::size_t DefaultBufferSize = 0x40;
64 Parcel() : buffer(DefaultBufferSize) {}
65 explicit Parcel(std::vector<u8> data) : buffer(std::move(data)) {}
66 virtual ~Parcel() = default;
67
68 template <typename T>
69 T Read() {
70 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
71 ASSERT(read_index + sizeof(T) <= buffer.size());
72
73 T val;
74 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
75 read_index += sizeof(T);
76 read_index = Common::AlignUp(read_index, 4);
77 return val;
78 }
79
80 template <typename T>
81 T ReadUnaligned() {
82 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
83 ASSERT(read_index + sizeof(T) <= buffer.size());
84
85 T val;
86 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
87 read_index += sizeof(T);
88 return val;
89 }
90
91 std::vector<u8> ReadBlock(std::size_t length) {
92 ASSERT(read_index + length <= buffer.size());
93 const u8* const begin = buffer.data() + read_index;
94 const u8* const end = begin + length;
95 std::vector<u8> data(begin, end);
96 read_index += length;
97 read_index = Common::AlignUp(read_index, 4);
98 return data;
99 }
100
101 std::u16string ReadInterfaceToken() {
102 [[maybe_unused]] const u32 unknown = Read<u32_le>();
103 const u32 length = Read<u32_le>();
104
105 std::u16string token{};
106
107 for (u32 ch = 0; ch < length + 1; ++ch) {
108 token.push_back(ReadUnaligned<u16_le>());
109 }
110
111 read_index = Common::AlignUp(read_index, 4);
112
113 return token;
114 }
115
116 template <typename T>
117 void Write(const T& val) {
118 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
119
120 if (buffer.size() < write_index + sizeof(T)) {
121 buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
122 }
123
124 std::memcpy(buffer.data() + write_index, &val, sizeof(T));
125 write_index += sizeof(T);
126 write_index = Common::AlignUp(write_index, 4);
127 }
128
129 template <typename T>
130 void WriteObject(const T& val) {
131 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
132
133 const u32_le size = static_cast<u32>(sizeof(val));
134 Write(size);
135 // TODO(Subv): Support file descriptors.
136 Write<u32_le>(0); // Fd count.
137 Write(val);
138 }
139
140 void Deserialize() {
141 ASSERT(buffer.size() > sizeof(Header));
142
143 Header header{};
144 std::memcpy(&header, buffer.data(), sizeof(Header));
145
146 read_index = header.data_offset;
147 DeserializeData();
148 }
149
150 std::vector<u8> Serialize() {
151 ASSERT(read_index == 0);
152 write_index = sizeof(Header);
153
154 SerializeData();
155
156 Header header{};
157 header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
158 header.data_offset = sizeof(Header);
159 header.objects_size = 4;
160 header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
161 std::memcpy(buffer.data(), &header, sizeof(Header));
162
163 return buffer;
164 }
165
166protected:
167 virtual void SerializeData() {}
168
169 virtual void DeserializeData() {}
170
171private:
172 struct Header {
173 u32_le data_size;
174 u32_le data_offset;
175 u32_le objects_size;
176 u32_le objects_offset;
177 };
178 static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
179
180 std::vector<u8> buffer;
181 std::size_t read_index = 0;
182 std::size_t write_index = 0;
183};
184
185class NativeWindow : public Parcel {
186public:
187 explicit NativeWindow(u32 id) {
188 data.id = id;
189 }
190 ~NativeWindow() override = default;
191
192protected:
193 void SerializeData() override {
194 Write(data);
195 }
196
197private:
198 struct Data {
199 u32_le magic = 2;
200 u32_le process_id = 1;
201 u32_le id;
202 INSERT_PADDING_WORDS(3);
203 std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
204 INSERT_PADDING_WORDS(2);
205 };
206 static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size");
207
208 Data data{};
209};
210
211class IGBPConnectRequestParcel : public Parcel {
212public:
213 explicit IGBPConnectRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
214 Deserialize();
215 }
216
217 void DeserializeData() override {
218 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
219 data = Read<Data>();
220 }
221
222 struct Data {
223 u32_le unk;
224 u32_le api;
225 u32_le producer_controlled_by_app;
226 };
227
228 Data data;
229};
230
231class IGBPConnectResponseParcel : public Parcel {
232public:
233 explicit IGBPConnectResponseParcel(u32 width, u32 height) {
234 data.width = width;
235 data.height = height;
236 }
237 ~IGBPConnectResponseParcel() override = default;
238
239protected:
240 void SerializeData() override {
241 Write(data);
242 }
243
244private:
245 struct Data {
246 u32_le width;
247 u32_le height;
248 u32_le transform_hint;
249 u32_le num_pending_buffers;
250 u32_le status;
251 };
252 static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
253
254 Data data{};
255};
256
257/// Represents a parcel containing one int '0' as its data
258/// Used by DetachBuffer and Disconnect
259class IGBPEmptyResponseParcel : public Parcel {
260protected:
261 void SerializeData() override {
262 Write(data);
263 }
264
265private:
266 struct Data {
267 u32_le unk_0{};
268 };
269
270 Data data{};
271};
272
273class IGBPSetPreallocatedBufferRequestParcel : public Parcel {
274public:
275 explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer_)
276 : Parcel(std::move(buffer_)) {
277 Deserialize();
278 }
279
280 void DeserializeData() override {
281 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
282 data = Read<Data>();
283 if (data.contains_object != 0) {
284 buffer_container = Read<BufferContainer>();
285 }
286 }
287
288 struct Data {
289 u32_le slot;
290 u32_le contains_object;
291 };
292
293 struct BufferContainer {
294 u32_le graphic_buffer_length;
295 INSERT_PADDING_WORDS(1);
296 NVFlinger::IGBPBuffer buffer{};
297 };
298
299 Data data{};
300 BufferContainer buffer_container{};
301};
302
303class IGBPSetPreallocatedBufferResponseParcel : public Parcel {
304protected:
305 void SerializeData() override {
306 // TODO(Subv): Find out what this means
307 Write<u32>(0);
308 }
309};
310
311class IGBPCancelBufferRequestParcel : public Parcel {
312public:
313 explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
314 Deserialize();
315 }
316
317 void DeserializeData() override {
318 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
319 data = Read<Data>();
320 }
321
322 struct Data {
323 u32_le slot;
324 Service::Nvidia::MultiFence multi_fence;
325 };
326
327 Data data;
328};
329
330class IGBPCancelBufferResponseParcel : public Parcel {
331protected:
332 void SerializeData() override {
333 Write<u32>(0); // Success
334 }
335};
336
337class IGBPDequeueBufferRequestParcel : public Parcel {
338public:
339 explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
340 Deserialize();
341 }
342
343 void DeserializeData() override {
344 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
345 data = Read<Data>();
346 }
347
348 struct Data {
349 u32_le pixel_format;
350 u32_le width;
351 u32_le height;
352 u32_le get_frame_timestamps;
353 u32_le usage;
354 };
355
356 Data data;
357};
358
359class IGBPDequeueBufferResponseParcel : public Parcel {
360public:
361 explicit IGBPDequeueBufferResponseParcel(u32 slot_, Nvidia::MultiFence& multi_fence_)
362 : slot(slot_), multi_fence(multi_fence_) {}
363
364protected:
365 void SerializeData() override {
366 Write(slot);
367 Write<u32_le>(1);
368 WriteObject(multi_fence);
369 Write<u32_le>(0);
370 }
371
372 u32_le slot;
373 Service::Nvidia::MultiFence multi_fence;
374};
375
376class IGBPRequestBufferRequestParcel : public Parcel {
377public:
378 explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
379 Deserialize();
380 }
381
382 void DeserializeData() override {
383 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
384 slot = Read<u32_le>();
385 }
386
387 u32_le slot;
388};
389
390class IGBPRequestBufferResponseParcel : public Parcel {
391public:
392 explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer_) : buffer(buffer_) {}
393 ~IGBPRequestBufferResponseParcel() override = default;
394
395protected:
396 void SerializeData() override {
397 // TODO(Subv): Figure out what this value means, writing non-zero here will make libnx
398 // try to read an IGBPBuffer object from the parcel.
399 Write<u32_le>(1);
400 WriteObject(buffer);
401 Write<u32_le>(0);
402 }
403
404 NVFlinger::IGBPBuffer buffer;
405};
406
407class IGBPQueueBufferRequestParcel : public Parcel {
408public:
409 explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
410 Deserialize();
411 }
412
413 void DeserializeData() override {
414 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
415 data = Read<Data>();
416 }
417
418 struct Data {
419 u32_le slot;
420 INSERT_PADDING_WORDS(3);
421 u32_le timestamp;
422 s32_le is_auto_timestamp;
423 s32_le crop_top;
424 s32_le crop_left;
425 s32_le crop_right;
426 s32_le crop_bottom;
427 s32_le scaling_mode;
428 NVFlinger::BufferQueue::BufferTransformFlags transform;
429 u32_le sticky_transform;
430 INSERT_PADDING_WORDS(1);
431 u32_le swap_interval;
432 Service::Nvidia::MultiFence multi_fence;
433
434 Common::Rectangle<int> GetCropRect() const {
435 return {crop_left, crop_top, crop_right, crop_bottom};
436 }
437 };
438 static_assert(sizeof(Data) == 96, "ParcelData has wrong size");
439
440 Data data;
441};
442
443class IGBPQueueBufferResponseParcel : public Parcel {
444public:
445 explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) {
446 data.width = width;
447 data.height = height;
448 }
449 ~IGBPQueueBufferResponseParcel() override = default;
450
451protected:
452 void SerializeData() override {
453 Write(data);
454 }
455
456private:
457 struct Data {
458 u32_le width;
459 u32_le height;
460 u32_le transform_hint;
461 u32_le num_pending_buffers;
462 u32_le status;
463 };
464 static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
465
466 Data data{};
467};
468
469class IGBPQueryRequestParcel : public Parcel {
470public:
471 explicit IGBPQueryRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) {
472 Deserialize();
473 }
474
475 void DeserializeData() override {
476 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
477 type = Read<u32_le>();
478 }
479
480 u32 type;
481};
482
483class IGBPQueryResponseParcel : public Parcel {
484public:
485 explicit IGBPQueryResponseParcel(u32 value_) : value{value_} {}
486 ~IGBPQueryResponseParcel() override = default;
487
488protected:
489 void SerializeData() override {
490 Write(value);
491 }
492 66
493private: 67private:
494 u32_le value; 68 const u32 magic = 2;
69 const u32 process_id = 1;
70 const u32 id;
71 INSERT_PADDING_WORDS(3);
72 std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
73 INSERT_PADDING_WORDS(2);
495}; 74};
75static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
496 76
497class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { 77class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
498public: 78public:
499 explicit IHOSBinderDriver(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) 79 explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_)
500 : ServiceFramework{system_, "IHOSBinderDriver"}, nv_flinger(nv_flinger_) { 80 : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) {
501 static const FunctionInfo functions[] = { 81 static const FunctionInfo functions[] = {
502 {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, 82 {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
503 {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, 83 {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
@@ -508,147 +88,16 @@ public:
508 } 88 }
509 89
510private: 90private:
511 enum class TransactionId {
512 RequestBuffer = 1,
513 SetBufferCount = 2,
514 DequeueBuffer = 3,
515 DetachBuffer = 4,
516 DetachNextBuffer = 5,
517 AttachBuffer = 6,
518 QueueBuffer = 7,
519 CancelBuffer = 8,
520 Query = 9,
521 Connect = 10,
522 Disconnect = 11,
523
524 AllocateBuffers = 13,
525 SetPreallocatedBuffer = 14,
526
527 GetBufferHistory = 17
528 };
529
530 void TransactParcel(Kernel::HLERequestContext& ctx) { 91 void TransactParcel(Kernel::HLERequestContext& ctx) {
531 IPC::RequestParser rp{ctx}; 92 IPC::RequestParser rp{ctx};
532 const u32 id = rp.Pop<u32>(); 93 const u32 id = rp.Pop<u32>();
533 const auto transaction = static_cast<TransactionId>(rp.Pop<u32>()); 94 const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>());
534 const u32 flags = rp.Pop<u32>(); 95 const u32 flags = rp.Pop<u32>();
535 96
536 LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, 97 LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
537 transaction, flags); 98 transaction, flags);
538 99
539 auto& buffer_queue = *nv_flinger.FindBufferQueue(id); 100 server.TryGetProducer(id)->Transact(ctx, transaction, flags);
540
541 switch (transaction) {
542 case TransactionId::Connect: {
543 IGBPConnectRequestParcel request{ctx.ReadBuffer()};
544 IGBPConnectResponseParcel response{static_cast<u32>(DisplayResolution::UndockedWidth),
545 static_cast<u32>(DisplayResolution::UndockedHeight)};
546
547 buffer_queue.Connect();
548
549 ctx.WriteBuffer(response.Serialize());
550 break;
551 }
552 case TransactionId::SetPreallocatedBuffer: {
553 IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()};
554
555 buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer_container.buffer);
556
557 IGBPSetPreallocatedBufferResponseParcel response{};
558 ctx.WriteBuffer(response.Serialize());
559 break;
560 }
561 case TransactionId::DequeueBuffer: {
562 IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
563 const u32 width{request.data.width};
564 const u32 height{request.data.height};
565
566 do {
567 if (auto result = buffer_queue.DequeueBuffer(width, height); result) {
568 // Buffer is available
569 IGBPDequeueBufferResponseParcel response{result->first, *result->second};
570 ctx.WriteBuffer(response.Serialize());
571 break;
572 }
573 } while (buffer_queue.IsConnected());
574
575 break;
576 }
577 case TransactionId::RequestBuffer: {
578 IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
579
580 auto& buffer = buffer_queue.RequestBuffer(request.slot);
581 IGBPRequestBufferResponseParcel response{buffer};
582 ctx.WriteBuffer(response.Serialize());
583
584 break;
585 }
586 case TransactionId::QueueBuffer: {
587 IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
588
589 buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
590 request.data.GetCropRect(), request.data.swap_interval,
591 request.data.multi_fence);
592
593 IGBPQueueBufferResponseParcel response{1280, 720};
594 ctx.WriteBuffer(response.Serialize());
595 break;
596 }
597 case TransactionId::Query: {
598 IGBPQueryRequestParcel request{ctx.ReadBuffer()};
599
600 const u32 value =
601 buffer_queue.Query(static_cast<NVFlinger::BufferQueue::QueryType>(request.type));
602
603 IGBPQueryResponseParcel response{value};
604 ctx.WriteBuffer(response.Serialize());
605 break;
606 }
607 case TransactionId::CancelBuffer: {
608 IGBPCancelBufferRequestParcel request{ctx.ReadBuffer()};
609
610 buffer_queue.CancelBuffer(request.data.slot, request.data.multi_fence);
611
612 IGBPCancelBufferResponseParcel response{};
613 ctx.WriteBuffer(response.Serialize());
614 break;
615 }
616 case TransactionId::Disconnect: {
617 LOG_WARNING(Service_VI, "(STUBBED) called, transaction=Disconnect");
618 const auto buffer = ctx.ReadBuffer();
619
620 buffer_queue.Disconnect();
621
622 IGBPEmptyResponseParcel response{};
623 ctx.WriteBuffer(response.Serialize());
624 break;
625 }
626 case TransactionId::DetachBuffer: {
627 const auto buffer = ctx.ReadBuffer();
628
629 IGBPEmptyResponseParcel response{};
630 ctx.WriteBuffer(response.Serialize());
631 break;
632 }
633 case TransactionId::SetBufferCount: {
634 LOG_WARNING(Service_VI, "(STUBBED) called, transaction=SetBufferCount");
635 [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
636
637 IGBPEmptyResponseParcel response{};
638 ctx.WriteBuffer(response.Serialize());
639 break;
640 }
641 case TransactionId::GetBufferHistory: {
642 LOG_WARNING(Service_VI, "(STUBBED) called, transaction=GetBufferHistory");
643 [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
644
645 IGBPEmptyResponseParcel response{};
646 ctx.WriteBuffer(response.Serialize());
647 break;
648 }
649 default:
650 ASSERT_MSG(false, "Unimplemented");
651 }
652 101
653 IPC::ResponseBuilder rb{ctx, 2}; 102 IPC::ResponseBuilder rb{ctx, 2};
654 rb.Push(ResultSuccess); 103 rb.Push(ResultSuccess);
@@ -674,13 +123,13 @@ private:
674 123
675 LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); 124 LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
676 125
677 // TODO(Subv): Find out what this actually is.
678 IPC::ResponseBuilder rb{ctx, 2, 1}; 126 IPC::ResponseBuilder rb{ctx, 2, 1};
679 rb.Push(ResultSuccess); 127 rb.Push(ResultSuccess);
680 rb.PushCopyObjects(nv_flinger.FindBufferQueue(id)->GetBufferWaitEvent()); 128 rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle());
681 } 129 }
682 130
683 NVFlinger::NVFlinger& nv_flinger; 131private:
132 NVFlinger::HosBinderDriverServer& server;
684}; 133};
685 134
686class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { 135class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
@@ -937,7 +386,40 @@ private:
937 386
938class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 387class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
939public: 388public:
940 explicit IApplicationDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); 389 IApplicationDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
390 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_)
391 : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_},
392 hos_binder_driver_server{hos_binder_driver_server_} {
393
394 static const FunctionInfo functions[] = {
395 {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
396 {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
397 {102, &IApplicationDisplayService::GetManagerDisplayService,
398 "GetManagerDisplayService"},
399 {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
400 "GetIndirectDisplayTransactionService"},
401 {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
402 {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
403 {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
404 {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
405 {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
406 {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
407 {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
408 {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
409 {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
410 {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
411 {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
412 {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
413 {2450, &IApplicationDisplayService::GetIndirectLayerImageMap,
414 "GetIndirectLayerImageMap"},
415 {2451, nullptr, "GetIndirectLayerImageCropMap"},
416 {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo,
417 "GetIndirectLayerImageRequiredMemoryInfo"},
418 {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
419 {5203, nullptr, "GetDisplayVsyncEventForDebug"},
420 };
421 RegisterHandlers(functions);
422 }
941 423
942private: 424private:
943 enum class ConvertedScaleMode : u64 { 425 enum class ConvertedScaleMode : u64 {
@@ -961,7 +443,7 @@ private:
961 443
962 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 444 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
963 rb.Push(ResultSuccess); 445 rb.Push(ResultSuccess);
964 rb.PushIpcInterface<IHOSBinderDriver>(system, nv_flinger); 446 rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
965 } 447 }
966 448
967 void GetSystemDisplayService(Kernel::HLERequestContext& ctx) { 449 void GetSystemDisplayService(Kernel::HLERequestContext& ctx) {
@@ -985,7 +467,7 @@ private:
985 467
986 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 468 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
987 rb.Push(ResultSuccess); 469 rb.Push(ResultSuccess);
988 rb.PushIpcInterface<IHOSBinderDriver>(system, nv_flinger); 470 rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
989 } 471 }
990 472
991 void OpenDisplay(Kernel::HLERequestContext& ctx) { 473 void OpenDisplay(Kernel::HLERequestContext& ctx) {
@@ -1089,7 +571,7 @@ private:
1089 void ListDisplays(Kernel::HLERequestContext& ctx) { 571 void ListDisplays(Kernel::HLERequestContext& ctx) {
1090 LOG_WARNING(Service_VI, "(STUBBED) called"); 572 LOG_WARNING(Service_VI, "(STUBBED) called");
1091 573
1092 DisplayInfo display_info; 574 const DisplayInfo display_info;
1093 ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); 575 ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
1094 IPC::ResponseBuilder rb{ctx, 4}; 576 IPC::ResponseBuilder rb{ctx, 4};
1095 rb.Push(ResultSuccess); 577 rb.Push(ResultSuccess);
@@ -1124,8 +606,8 @@ private:
1124 return; 606 return;
1125 } 607 }
1126 608
1127 NativeWindow native_window{*buffer_queue_id}; 609 const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}};
1128 const auto buffer_size = ctx.WriteBuffer(native_window.Serialize()); 610 const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
1129 611
1130 IPC::ResponseBuilder rb{ctx, 4}; 612 IPC::ResponseBuilder rb{ctx, 4};
1131 rb.Push(ResultSuccess); 613 rb.Push(ResultSuccess);
@@ -1170,8 +652,8 @@ private:
1170 return; 652 return;
1171 } 653 }
1172 654
1173 NativeWindow native_window{*buffer_queue_id}; 655 const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}};
1174 const auto buffer_size = ctx.WriteBuffer(native_window.Serialize()); 656 const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
1175 657
1176 IPC::ResponseBuilder rb{ctx, 6}; 658 IPC::ResponseBuilder rb{ctx, 6};
1177 rb.Push(ResultSuccess); 659 rb.Push(ResultSuccess);
@@ -1287,39 +769,9 @@ private:
1287 } 769 }
1288 770
1289 NVFlinger::NVFlinger& nv_flinger; 771 NVFlinger::NVFlinger& nv_flinger;
772 NVFlinger::HosBinderDriverServer& hos_binder_driver_server;
1290}; 773};
1291 774
1292IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
1293 NVFlinger::NVFlinger& nv_flinger_)
1294 : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_} {
1295 static const FunctionInfo functions[] = {
1296 {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
1297 {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
1298 {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"},
1299 {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
1300 "GetIndirectDisplayTransactionService"},
1301 {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
1302 {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
1303 {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
1304 {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
1305 {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
1306 {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
1307 {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
1308 {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
1309 {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
1310 {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
1311 {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
1312 {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
1313 {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, "GetIndirectLayerImageMap"},
1314 {2451, nullptr, "GetIndirectLayerImageCropMap"},
1315 {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo,
1316 "GetIndirectLayerImageRequiredMemoryInfo"},
1317 {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
1318 {5203, nullptr, "GetDisplayVsyncEventForDebug"},
1319 };
1320 RegisterHandlers(functions);
1321}
1322
1323static bool IsValidServiceAccess(Permission permission, Policy policy) { 775static bool IsValidServiceAccess(Permission permission, Policy policy) {
1324 if (permission == Permission::User) { 776 if (permission == Permission::User) {
1325 return policy == Policy::User; 777 return policy == Policy::User;
@@ -1333,7 +785,9 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
1333} 785}
1334 786
1335void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, 787void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system,
1336 NVFlinger::NVFlinger& nv_flinger, Permission permission) { 788 NVFlinger::NVFlinger& nv_flinger,
789 NVFlinger::HosBinderDriverServer& hos_binder_driver_server,
790 Permission permission) {
1337 IPC::RequestParser rp{ctx}; 791 IPC::RequestParser rp{ctx};
1338 const auto policy = rp.PopEnum<Policy>(); 792 const auto policy = rp.PopEnum<Policy>();
1339 793
@@ -1346,14 +800,18 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System&
1346 800
1347 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 801 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1348 rb.Push(ResultSuccess); 802 rb.Push(ResultSuccess);
1349 rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger); 803 rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server);
1350} 804}
1351 805
1352void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, 806void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system,
1353 NVFlinger::NVFlinger& nv_flinger) { 807 NVFlinger::NVFlinger& nv_flinger,
1354 std::make_shared<VI_M>(system, nv_flinger)->InstallAsService(service_manager); 808 NVFlinger::HosBinderDriverServer& hos_binder_driver_server) {
1355 std::make_shared<VI_S>(system, nv_flinger)->InstallAsService(service_manager); 809 std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server)
1356 std::make_shared<VI_U>(system, nv_flinger)->InstallAsService(service_manager); 810 ->InstallAsService(service_manager);
811 std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server)
812 ->InstallAsService(service_manager);
813 std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server)
814 ->InstallAsService(service_manager);
1357} 815}
1358 816
1359} // namespace Service::VI 817} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 2fd7f8e61..d68f2646b 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -15,8 +15,9 @@ class HLERequestContext;
15} 15}
16 16
17namespace Service::NVFlinger { 17namespace Service::NVFlinger {
18class HosBinderDriverServer;
18class NVFlinger; 19class NVFlinger;
19} 20} // namespace Service::NVFlinger
20 21
21namespace Service::SM { 22namespace Service::SM {
22class ServiceManager; 23class ServiceManager;
@@ -47,11 +48,14 @@ enum class Policy {
47 48
48namespace detail { 49namespace detail {
49void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, 50void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system,
50 NVFlinger::NVFlinger& nv_flinger, Permission permission); 51 NVFlinger::NVFlinger& nv_flinger,
52 NVFlinger::HosBinderDriverServer& hos_binder_driver_server,
53 Permission permission);
51} // namespace detail 54} // namespace detail
52 55
53/// Registers all VI services with the specified service manager. 56/// Registers all VI services with the specified service manager.
54void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, 57void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system,
55 NVFlinger::NVFlinger& nv_flinger); 58 NVFlinger::NVFlinger& nv_flinger,
59 NVFlinger::HosBinderDriverServer& hos_binder_driver_server);
56 60
57} // namespace Service::VI 61} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp
index 87db1c416..be0255f3d 100644
--- a/src/core/hle/service/vi/vi_m.cpp
+++ b/src/core/hle/service/vi/vi_m.cpp
@@ -8,8 +8,10 @@
8 8
9namespace Service::VI { 9namespace Service::VI {
10 10
11VI_M::VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) 11VI_M::VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
12 : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_} { 12 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_)
13 : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
14 hos_binder_driver_server_} {
13 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
14 {2, &VI_M::GetDisplayService, "GetDisplayService"}, 16 {2, &VI_M::GetDisplayService, "GetDisplayService"},
15 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 17 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -22,7 +24,8 @@ VI_M::~VI_M() = default;
22void VI_M::GetDisplayService(Kernel::HLERequestContext& ctx) { 24void VI_M::GetDisplayService(Kernel::HLERequestContext& ctx) {
23 LOG_DEBUG(Service_VI, "called"); 25 LOG_DEBUG(Service_VI, "called");
24 26
25 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::Manager); 27 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
28 Permission::Manager);
26} 29}
27 30
28} // namespace Service::VI 31} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
index d79c41beb..efbd34e09 100644
--- a/src/core/hle/service/vi/vi_m.h
+++ b/src/core/hle/service/vi/vi_m.h
@@ -15,20 +15,23 @@ class HLERequestContext;
15} 15}
16 16
17namespace Service::NVFlinger { 17namespace Service::NVFlinger {
18class HosBinderDriverServer;
18class NVFlinger; 19class NVFlinger;
19} 20} // namespace Service::NVFlinger
20 21
21namespace Service::VI { 22namespace Service::VI {
22 23
23class VI_M final : public ServiceFramework<VI_M> { 24class VI_M final : public ServiceFramework<VI_M> {
24public: 25public:
25 explicit VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); 26 explicit VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
27 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_);
26 ~VI_M() override; 28 ~VI_M() override;
27 29
28private: 30private:
29 void GetDisplayService(Kernel::HLERequestContext& ctx); 31 void GetDisplayService(Kernel::HLERequestContext& ctx);
30 32
31 NVFlinger::NVFlinger& nv_flinger; 33 NVFlinger::NVFlinger& nv_flinger;
34 NVFlinger::HosBinderDriverServer& hos_binder_driver_server;
32}; 35};
33 36
34} // namespace Service::VI 37} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
index 5cd22f7df..7996a6811 100644
--- a/src/core/hle/service/vi/vi_s.cpp
+++ b/src/core/hle/service/vi/vi_s.cpp
@@ -8,8 +8,10 @@
8 8
9namespace Service::VI { 9namespace Service::VI {
10 10
11VI_S::VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) 11VI_S::VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
12 : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_} { 12 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_)
13 : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
14 hos_binder_driver_server_} {
13 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
14 {1, &VI_S::GetDisplayService, "GetDisplayService"}, 16 {1, &VI_S::GetDisplayService, "GetDisplayService"},
15 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 17 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -22,7 +24,8 @@ VI_S::~VI_S() = default;
22void VI_S::GetDisplayService(Kernel::HLERequestContext& ctx) { 24void VI_S::GetDisplayService(Kernel::HLERequestContext& ctx) {
23 LOG_DEBUG(Service_VI, "called"); 25 LOG_DEBUG(Service_VI, "called");
24 26
25 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::System); 27 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
28 Permission::System);
26} 29}
27 30
28} // namespace Service::VI 31} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
index 5f1f8f290..3812c5061 100644
--- a/src/core/hle/service/vi/vi_s.h
+++ b/src/core/hle/service/vi/vi_s.h
@@ -15,20 +15,23 @@ class HLERequestContext;
15} 15}
16 16
17namespace Service::NVFlinger { 17namespace Service::NVFlinger {
18class HosBinderDriverServer;
18class NVFlinger; 19class NVFlinger;
19} 20} // namespace Service::NVFlinger
20 21
21namespace Service::VI { 22namespace Service::VI {
22 23
23class VI_S final : public ServiceFramework<VI_S> { 24class VI_S final : public ServiceFramework<VI_S> {
24public: 25public:
25 explicit VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); 26 explicit VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
27 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_);
26 ~VI_S() override; 28 ~VI_S() override;
27 29
28private: 30private:
29 void GetDisplayService(Kernel::HLERequestContext& ctx); 31 void GetDisplayService(Kernel::HLERequestContext& ctx);
30 32
31 NVFlinger::NVFlinger& nv_flinger; 33 NVFlinger::NVFlinger& nv_flinger;
34 NVFlinger::HosBinderDriverServer& hos_binder_driver_server;
32}; 35};
33 36
34} // namespace Service::VI 37} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
index 0079d51f0..57c888313 100644
--- a/src/core/hle/service/vi/vi_u.cpp
+++ b/src/core/hle/service/vi/vi_u.cpp
@@ -8,8 +8,10 @@
8 8
9namespace Service::VI { 9namespace Service::VI {
10 10
11VI_U::VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) 11VI_U::VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
12 : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_} { 12 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_)
13 : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
14 hos_binder_driver_server_} {
13 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
14 {0, &VI_U::GetDisplayService, "GetDisplayService"}, 16 {0, &VI_U::GetDisplayService, "GetDisplayService"},
15 {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 17 {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -22,7 +24,8 @@ VI_U::~VI_U() = default;
22void VI_U::GetDisplayService(Kernel::HLERequestContext& ctx) { 24void VI_U::GetDisplayService(Kernel::HLERequestContext& ctx) {
23 LOG_DEBUG(Service_VI, "called"); 25 LOG_DEBUG(Service_VI, "called");
24 26
25 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::User); 27 detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
28 Permission::User);
26} 29}
27 30
28} // namespace Service::VI 31} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
index 8e3885c73..b08e56576 100644
--- a/src/core/hle/service/vi/vi_u.h
+++ b/src/core/hle/service/vi/vi_u.h
@@ -15,20 +15,23 @@ class HLERequestContext;
15} 15}
16 16
17namespace Service::NVFlinger { 17namespace Service::NVFlinger {
18class HosBinderDriverServer;
18class NVFlinger; 19class NVFlinger;
19} 20} // namespace Service::NVFlinger
20 21
21namespace Service::VI { 22namespace Service::VI {
22 23
23class VI_U final : public ServiceFramework<VI_U> { 24class VI_U final : public ServiceFramework<VI_U> {
24public: 25public:
25 explicit VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); 26 explicit VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_,
27 NVFlinger::HosBinderDriverServer& hos_binder_driver_server_);
26 ~VI_U() override; 28 ~VI_U() override;
27 29
28private: 30private:
29 void GetDisplayService(Kernel::HLERequestContext& ctx); 31 void GetDisplayService(Kernel::HLERequestContext& ctx);
30 32
31 NVFlinger::NVFlinger& nv_flinger; 33 NVFlinger::NVFlinger& nv_flinger;
34 NVFlinger::HosBinderDriverServer& hos_binder_driver_server;
32}; 35};
33 36
34} // namespace Service::VI 37} // namespace Service::VI
diff --git a/src/core/network/sockets.h b/src/core/network/sockets.h
index a44393325..5e39e7c54 100644
--- a/src/core/network/sockets.h
+++ b/src/core/network/sockets.h
@@ -8,7 +8,6 @@
8#include <utility> 8#include <utility>
9 9
10#if defined(_WIN32) 10#if defined(_WIN32)
11#include <winsock.h>
12#elif !YUZU_UNIX 11#elif !YUZU_UNIX
13#error "Platform not implemented" 12#error "Platform not implemented"
14#endif 13#endif
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index d4becdc0a..89faed6ee 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -8,7 +8,6 @@
8 8
9#include <fmt/chrono.h> 9#include <fmt/chrono.h>
10#include <fmt/format.h> 10#include <fmt/format.h>
11#include <fmt/ostream.h>
12#include <nlohmann/json.hpp> 11#include <nlohmann/json.hpp>
13 12
14#include "common/fs/file.h" 13#include "common/fs/file.h"
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index 7ce1912a3..43ad58c85 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <memory> 8#include <memory>
9#include <mutex>
10#include <stop_token> 9#include <stop_token>
11#include <string> 10#include <string>
12#include <thread> 11#include <thread>
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index 2d5d54ddb..9c205e944 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -10,7 +10,6 @@
10 10
11#include <boost/crc.hpp> 11#include <boost/crc.hpp>
12 12
13#include "common/bit_field.h"
14#include "common/swap.h" 13#include "common/swap.h"
15 14
16namespace InputCommon::CemuhookUDP { 15namespace InputCommon::CemuhookUDP {
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
index 7adf7e3d7..738022ece 100644
--- a/src/input_common/input_engine.cpp
+++ b/src/input_common/input_engine.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included 3// Refer to the license.txt file included
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/param_package.h"
7#include "input_common/input_engine.h" 6#include "input_common/input_engine.h"
8 7
9namespace InputCommon { 8namespace InputCommon {
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index a4d7ed645..28769c6d8 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6#include <thread>
7#include "common/input.h" 6#include "common/input.h"
8#include "common/param_package.h" 7#include "common/param_package.h"
9#include "input_common/drivers/gc_adapter.h" 8#include "input_common/drivers/gc_adapter.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
index 4cff70fe4..8603c6be2 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
index 356640471..e4b6b6f31 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
index f0fd94a28..44b363b50 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 7#include "shader_recompiler/frontend/ir/program.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 86287ee3f..affe35be7 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -2,11 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
11 8
12#ifdef _MSC_VER 9#ifdef _MSC_VER
diff --git a/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp b/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
index 0401953f7..af88b7dfa 100644
--- a/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
+++ b/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/bindings.h" 5#include "shader_recompiler/backend/bindings.h"
8#include "shader_recompiler/backend/glasm/emit_glasm.h" 6#include "shader_recompiler/backend/glasm/emit_glasm.h"
9#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 7#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
index 201e428c1..4e98d3ea0 100644
--- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
@@ -2,11 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string>
6
7#include <fmt/format.h> 5#include <fmt/format.h>
8 6
9#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
10#include "shader_recompiler/backend/glasm/reg_alloc.h" 7#include "shader_recompiler/backend/glasm/reg_alloc.h"
11#include "shader_recompiler/exception.h" 8#include "shader_recompiler/exception.h"
12#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
index 8a9faa394..0f204495c 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
@@ -4,7 +4,6 @@
4 4
5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
6#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h"
8 7
9namespace Shader::Backend::GLSL { 8namespace Shader::Backend::GLSL {
10void EmitBarrier(EmitContext& ctx) { 9void EmitBarrier(EmitContext& ctx) {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
index c86465e8b..6f61560f1 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/exception.h" 7#include "shader_recompiler/exception.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index b0d85be99..64322cdbf 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
index 742fec9cf..162a8c461 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
index 74ae345e5..f8aa4ecd6 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
index fcf620b79..8b94ea90a 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 7#include "shader_recompiler/frontend/ir/program.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
index cace1db85..9367524e8 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
index d3cbb14a9..cb47d253c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bit>
6
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 7#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 8#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 9#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
index 9ce95a41b..6ecaa3937 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
@@ -2,10 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8#include "shader_recompiler/frontend/ir/modifiers.h"
9 7
10namespace Shader::Backend::SPIRV { 8namespace Shader::Backend::SPIRV {
11namespace { 9namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
index 02d1e63f7..831c6f158 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
index 5c3e1ee2b..812c3668d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
@@ -2,10 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8#include "shader_recompiler/frontend/ir/modifiers.h"
9 7
10namespace Shader::Backend::SPIRV { 8namespace Shader::Backend::SPIRV {
11 9
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 80b4bbd27..aa7082978 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -2,10 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bit>
5#include <tuple> 6#include <tuple>
6#include <utility> 7#include <utility>
7 8
8#include "shader_recompiler/backend/spirv/emit_spirv.h"
9#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 9#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
10#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 10#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
11 11
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
index 1eca3aa85..d1afd47b8 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
index 832de2452..137a0e257 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
index 0cdc46495..9f65fa269 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
index a96190bc6..727ac2027 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index 44521f539..45a384e46 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
index 47745f7ee..74b6efe01 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
index 48caf1ffc..ce55cd31c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
index 330c9052c..b57c66828 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
index b5766fc52..00c6e86e2 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
index 7034228bf..905c735ad 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 5#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h" 6#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
8 7
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index aa5b6c9b7..28f6a6184 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -4,8 +4,8 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <array> 6#include <array>
7#include <bit>
7#include <climits> 8#include <climits>
8#include <string_view>
9 9
10#include <boost/container/static_vector.hpp> 10#include <boost/container/static_vector.hpp>
11 11
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index 906a1dc2c..b9115a405 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <string_view>
9 8
10#include <sirit/sirit.h> 9#include <sirit/sirit.h>
11 10
diff --git a/src/shader_recompiler/exception.h b/src/shader_recompiler/exception.h
index d98b6029b..a6aecde3e 100644
--- a/src/shader_recompiler/exception.h
+++ b/src/shader_recompiler/exception.h
@@ -6,7 +6,6 @@
6 6
7#include <exception> 7#include <exception>
8#include <string> 8#include <string>
9#include <string_view>
10#include <utility> 9#include <utility>
11 10
12#include "common/logging/formatter.h" 11#include "common/logging/formatter.h"
diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp
index 974efa4a0..a1472cb76 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.cpp
+++ b/src/shader_recompiler/frontend/ir/basic_block.cpp
@@ -5,9 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <initializer_list> 6#include <initializer_list>
7#include <map> 7#include <map>
8#include <memory>
9 8
10#include "common/bit_cast.h"
11#include "common/common_types.h" 9#include "common/common_types.h"
12#include "shader_recompiler/frontend/ir/basic_block.h" 10#include "shader_recompiler/frontend/ir/basic_block.h"
13#include "shader_recompiler/frontend/ir/value.h" 11#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/frontend/ir/condition.h b/src/shader_recompiler/frontend/ir/condition.h
index aa8597c60..2f8c10e71 100644
--- a/src/shader_recompiler/frontend/ir/condition.h
+++ b/src/shader_recompiler/frontend/ir/condition.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <compare>
8#include <string> 7#include <string>
9 8
10#include <fmt/format.h> 9#include <fmt/format.h>
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 631446cf7..4a2564f47 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -326,6 +326,11 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
326 phi_args.emplace_back(predecessor, value); 326 phi_args.emplace_back(predecessor, value);
327} 327}
328 328
329void Inst::ErasePhiOperand(size_t index) {
330 const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)};
331 phi_args.erase(operand_it);
332}
333
329void Inst::OrderPhiArgs() { 334void Inst::OrderPhiArgs() {
330 if (op != Opcode::Phi) { 335 if (op != Opcode::Phi) {
331 throw LogicError("{} is not a Phi instruction", op); 336 throw LogicError("{} is not a Phi instruction", op);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.cpp b/src/shader_recompiler/frontend/ir/opcodes.cpp
index 24d024ad7..5baa6792f 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.cpp
+++ b/src/shader_recompiler/frontend/ir/opcodes.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view>
6
7#include "shader_recompiler/frontend/ir/opcodes.h" 5#include "shader_recompiler/frontend/ir/opcodes.h"
8 6
9namespace Shader::IR { 7namespace Shader::IR {
diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h
index 9ab108292..85f7aac02 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.h
+++ b/src/shader_recompiler/frontend/ir/opcodes.h
@@ -6,7 +6,6 @@
6 6
7#include <algorithm> 7#include <algorithm>
8#include <array> 8#include <array>
9#include <string_view>
10 9
11#include <fmt/format.h> 10#include <fmt/format.h>
12 11
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index d365ea1bc..0248d9c6e 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/frontend/ir/opcodes.h"
6#include "shader_recompiler/frontend/ir/value.h" 5#include "shader_recompiler/frontend/ir/value.h"
7 6
8namespace Shader::IR { 7namespace Shader::IR {
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 947579852..14f6e55bc 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -179,9 +179,13 @@ public:
179 179
180 /// Get a pointer to the block of a phi argument. 180 /// Get a pointer to the block of a phi argument.
181 [[nodiscard]] Block* PhiBlock(size_t index) const; 181 [[nodiscard]] Block* PhiBlock(size_t index) const;
182
182 /// Add phi operand to a phi instruction. 183 /// Add phi operand to a phi instruction.
183 void AddPhiOperand(Block* predecessor, const Value& value); 184 void AddPhiOperand(Block* predecessor, const Value& value);
184 185
186 // Erase the phi operand at the given index.
187 void ErasePhiOperand(size_t index);
188
185 /// Orders the Phi arguments from farthest away to nearest. 189 /// Orders the Phi arguments from farthest away to nearest.
186 void OrderPhiArgs(); 190 void OrderPhiArgs();
187 191
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.h b/src/shader_recompiler/frontend/maxwell/control_flow.h
index a6bd3e196..7e91fac46 100644
--- a/src/shader_recompiler/frontend/maxwell/control_flow.h
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <compare>
8#include <optional> 7#include <optional>
9#include <span> 8#include <span>
10#include <string> 9#include <string>
@@ -15,6 +14,7 @@
15 14
16#include "shader_recompiler/environment.h" 15#include "shader_recompiler/environment.h"
17#include "shader_recompiler/frontend/ir/condition.h" 16#include "shader_recompiler/frontend/ir/condition.h"
17#include "shader_recompiler/frontend/ir/reg.h"
18#include "shader_recompiler/frontend/maxwell/instruction.h" 18#include "shader_recompiler/frontend/maxwell/instruction.h"
19#include "shader_recompiler/frontend/maxwell/location.h" 19#include "shader_recompiler/frontend/maxwell/location.h"
20#include "shader_recompiler/frontend/maxwell/opcodes.h" 20#include "shader_recompiler/frontend/maxwell/opcodes.h"
diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp
index 972f677dc..e688e648b 100644
--- a/src/shader_recompiler/frontend/maxwell/decode.cpp
+++ b/src/shader_recompiler/frontend/maxwell/decode.cpp
@@ -6,7 +6,6 @@
6#include <array> 6#include <array>
7#include <bit> 7#include <bit>
8#include <memory> 8#include <memory>
9#include <string_view>
10 9
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "shader_recompiler/exception.h" 11#include "shader_recompiler/exception.h"
diff --git a/src/shader_recompiler/frontend/maxwell/indirect_branch_table_track.h b/src/shader_recompiler/frontend/maxwell/indirect_branch_table_track.h
index eee5102fa..2a23f7abf 100644
--- a/src/shader_recompiler/frontend/maxwell/indirect_branch_table_track.h
+++ b/src/shader_recompiler/frontend/maxwell/indirect_branch_table_track.h
@@ -6,7 +6,6 @@
6 6
7#include <optional> 7#include <optional>
8 8
9#include "common/bit_field.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "shader_recompiler/environment.h" 10#include "shader_recompiler/environment.h"
12#include "shader_recompiler/frontend/ir/reg.h" 11#include "shader_recompiler/frontend/ir/reg.h"
diff --git a/src/shader_recompiler/frontend/maxwell/instruction.h b/src/shader_recompiler/frontend/maxwell/instruction.h
index 743d68d61..57fd531f2 100644
--- a/src/shader_recompiler/frontend/maxwell/instruction.h
+++ b/src/shader_recompiler/frontend/maxwell/instruction.h
@@ -7,7 +7,6 @@
7#include "common/bit_field.h" 7#include "common/bit_field.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/flow_test.h" 9#include "shader_recompiler/frontend/ir/flow_test.h"
10#include "shader_recompiler/frontend/ir/reg.h"
11 10
12namespace Shader::Maxwell { 11namespace Shader::Maxwell {
13 12
diff --git a/src/shader_recompiler/frontend/maxwell/location.h b/src/shader_recompiler/frontend/maxwell/location.h
index 26d29eae2..17107f082 100644
--- a/src/shader_recompiler/frontend/maxwell/location.h
+++ b/src/shader_recompiler/frontend/maxwell/location.h
@@ -4,9 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <compare>
8#include <iterator>
9
10#include <fmt/format.h> 7#include <fmt/format.h>
11 8
12#include "common/common_types.h" 9#include "common/common_types.h"
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index 69eeaa3e6..7bad628aa 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -8,7 +8,6 @@
8#include <unordered_map> 8#include <unordered_map>
9#include <utility> 9#include <utility>
10#include <vector> 10#include <vector>
11#include <version>
12 11
13#include <fmt/format.h> 12#include <fmt/format.h>
14 13
@@ -17,7 +16,6 @@
17#include "shader_recompiler/environment.h" 16#include "shader_recompiler/environment.h"
18#include "shader_recompiler/frontend/ir/basic_block.h" 17#include "shader_recompiler/frontend/ir/basic_block.h"
19#include "shader_recompiler/frontend/ir/ir_emitter.h" 18#include "shader_recompiler/frontend/ir/ir_emitter.h"
20#include "shader_recompiler/frontend/maxwell/decode.h"
21#include "shader_recompiler/frontend/maxwell/structured_control_flow.h" 19#include "shader_recompiler/frontend/maxwell/structured_control_flow.h"
22#include "shader_recompiler/frontend/maxwell/translate/translate.h" 20#include "shader_recompiler/frontend/maxwell/translate/translate.h"
23#include "shader_recompiler/host_translate_info.h" 21#include "shader_recompiler/host_translate_info.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/attribute_memory_to_physical.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/attribute_memory_to_physical.cpp
index fb3f00d3f..d26d0982b 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/attribute_memory_to_physical.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/attribute_memory_to_physical.cpp
@@ -4,7 +4,6 @@
4 4
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/frontend/maxwell/opcodes.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9 8
10namespace Shader::Maxwell { 9namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp
index 86e433e41..d92d4e929 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp
@@ -4,8 +4,6 @@
4 4
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/frontend/ir/modifiers.h"
8#include "shader_recompiler/frontend/maxwell/opcodes.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10 8
11namespace Shader::Maxwell { 9namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
index 214d0af3c..24f041a4f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9 8
10namespace Shader::Maxwell { 9namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp
index c2443c886..62d20ebe4 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/exit_program.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "shader_recompiler/exception.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 6#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
8 7
9namespace Shader::Maxwell { 8namespace Shader::Maxwell {
@@ -12,9 +11,13 @@ void ExitFragment(TranslatorVisitor& v) {
12 const ProgramHeader sph{v.env.SPH()}; 11 const ProgramHeader sph{v.env.SPH()};
13 IR::Reg src_reg{IR::Reg::R0}; 12 IR::Reg src_reg{IR::Reg::R0};
14 for (u32 render_target = 0; render_target < 8; ++render_target) { 13 for (u32 render_target = 0; render_target < 8; ++render_target) {
14 if (!sph.ps.HasOutputComponents(render_target)) {
15 continue;
16 }
15 const std::array<bool, 4> mask{sph.ps.EnabledOutputComponents(render_target)}; 17 const std::array<bool, 4> mask{sph.ps.EnabledOutputComponents(render_target)};
16 for (u32 component = 0; component < 4; ++component) { 18 for (u32 component = 0; component < 4; ++component) {
17 if (!mask[component]) { 19 if (!mask[component]) {
20 ++src_reg;
18 continue; 21 continue;
19 } 22 }
20 v.ir.SetFragColor(render_target, component, v.F(src_reg)); 23 v.ir.SetFragColor(render_target, component, v.F(src_reg));
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp
index 2f8605619..bb8512400 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp
@@ -5,7 +5,6 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/exception.h" 7#include "shader_recompiler/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcodes.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10 9
11namespace Shader::Maxwell { 10namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h
index 59da56a7e..c5e80a559 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h
@@ -6,8 +6,6 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "shader_recompiler/exception.h" 8#include "shader_recompiler/exception.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/common_encoding.h"
10#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
11#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
12 10
13namespace Shader::Maxwell { 11namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set.cpp
index cca5b831f..01bc9c49f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
5#include "shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h" 6#include "shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h"
6 7
7namespace Shader::Maxwell { 8namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set_predicate.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set_predicate.cpp
index b3931dae3..2b9c4fc0f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set_predicate.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_set_predicate.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
5#include "shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h" 6#include "shader_recompiler/frontend/maxwell/translate/impl/half_floating_point_helper.h"
6 7
7namespace Shader::Maxwell { 8namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
index 924fb7a40..00d1d8438 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
@@ -6,7 +6,6 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/exception.h" 7#include "shader_recompiler/exception.h"
8#include "shader_recompiler/frontend/ir/ir_emitter.h" 8#include "shader_recompiler/frontend/ir/ir_emitter.h"
9#include "shader_recompiler/frontend/maxwell/opcodes.h"
10#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
11 10
12namespace Shader::Maxwell { 11namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp
index 36c5cff2f..4792cd4a5 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp
@@ -5,7 +5,6 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/exception.h" 7#include "shader_recompiler/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcodes.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10 9
11namespace Shader::Maxwell { 10namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/move_register.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/move_register.cpp
index 6bb08db8a..c317e14c9 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/move_register.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/move_register.cpp
@@ -5,7 +5,6 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "shader_recompiler/exception.h" 7#include "shader_recompiler/exception.h"
8#include "shader_recompiler/frontend/maxwell/opcodes.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
10 9
11namespace Shader::Maxwell { 10namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp
index 63b588ad4..100c94c19 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/surface_atomic_operations.cpp
@@ -2,9 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <bit>
7
8#include "common/bit_field.h" 5#include "common/bit_field.h"
9#include "common/common_types.h" 6#include "common/common_types.h"
10#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
index 154e7f1a1..00dbcd86f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <utility>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
index 218cbc1a8..959c63ba9 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <optional>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp
index 34efa2d50..86e68a830 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gather_swizzled.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <utility>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp
index c3fe3ffda..6f4feff11 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <optional>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp
index 983058303..57b4f0eee 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <optional>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
index aea3c0e62..311a9e763 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <optional>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 7#include "shader_recompiler/frontend/ir/modifiers.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp
index 0459e5473..72131301c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp
@@ -6,7 +6,6 @@
6 6
7#include "common/bit_field.h" 7#include "common/bit_field.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
11 10
12namespace Shader::Maxwell { 11namespace Shader::Maxwell {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp
index 550fed55c..f98f66940 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <optional>
6
7#include "common/bit_field.h" 5#include "common/bit_field.h"
8#include "common/common_types.h" 6#include "common/common_types.h"
9#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.h b/src/shader_recompiler/frontend/maxwell/translate_program.h
index eac83da9d..7b024c627 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.h
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.h
@@ -8,10 +8,13 @@
8#include "shader_recompiler/frontend/ir/basic_block.h" 8#include "shader_recompiler/frontend/ir/basic_block.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/maxwell/control_flow.h" 10#include "shader_recompiler/frontend/maxwell/control_flow.h"
11#include "shader_recompiler/host_translate_info.h"
12#include "shader_recompiler/object_pool.h" 11#include "shader_recompiler/object_pool.h"
13#include "shader_recompiler/runtime_info.h" 12#include "shader_recompiler/runtime_info.h"
14 13
14namespace Shader {
15struct HostTranslateInfo;
16}
17
15namespace Shader::Maxwell { 18namespace Shader::Maxwell {
16 19
17[[nodiscard]] IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, 20[[nodiscard]] IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool,
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
index c134a12bc..2a14e7f12 100644
--- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
+++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
@@ -8,7 +8,6 @@
8#include <type_traits> 8#include <type_traits>
9 9
10#include "common/bit_cast.h" 10#include "common/bit_cast.h"
11#include "common/bit_util.h"
12#include "shader_recompiler/exception.h" 11#include "shader_recompiler/exception.h"
13#include "shader_recompiler/frontend/ir/ir_emitter.h" 12#include "shader_recompiler/frontend/ir/ir_emitter.h"
14#include "shader_recompiler/frontend/ir/value.h" 13#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
index 400836301..6697fde85 100644
--- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
+++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
@@ -2,24 +2,104 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6
7#include <boost/container/small_vector.hpp>
8
5#include "shader_recompiler/frontend/ir/basic_block.h" 9#include "shader_recompiler/frontend/ir/basic_block.h"
6#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
7#include "shader_recompiler/ir_opt/passes.h" 11#include "shader_recompiler/ir_opt/passes.h"
8 12
9namespace Shader::Optimization { 13namespace Shader::Optimization {
10 14namespace {
11void DeadCodeEliminationPass(IR::Program& program) { 15template <bool TEST_USES>
16void DeadInstElimination(IR::Block* const block) {
12 // We iterate over the instructions in reverse order. 17 // We iterate over the instructions in reverse order.
13 // This is because removing an instruction reduces the number of uses for earlier instructions. 18 // This is because removing an instruction reduces the number of uses for earlier instructions.
14 for (IR::Block* const block : program.post_order_blocks) { 19 auto it{block->end()};
15 auto it{block->end()}; 20 while (it != block->begin()) {
16 while (it != block->begin()) { 21 --it;
17 --it; 22 if constexpr (TEST_USES) {
18 if (!it->HasUses() && !it->MayHaveSideEffects()) { 23 if (it->HasUses() || it->MayHaveSideEffects()) {
19 it->Invalidate(); 24 continue;
20 it = block->Instructions().erase(it); 25 }
26 }
27 it->Invalidate();
28 it = block->Instructions().erase(it);
29 }
30}
31
32void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) {
33 for (IR::Block* const block : program.blocks) {
34 for (IR::Inst& phi : *block) {
35 if (!IR::IsPhi(phi)) {
36 continue;
37 }
38 for (size_t i = 0; i < phi.NumArgs(); ++i) {
39 if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) {
40 continue;
41 }
42 // Phi operand at this index is an unreachable block
43 phi.ErasePhiOperand(i);
44 --i;
45 }
46 }
47 }
48}
49
50void DeadBranchElimination(IR::Program& program) {
51 boost::container::small_vector<const IR::Block*, 3> dead_blocks;
52 const auto begin_it{program.syntax_list.begin()};
53 for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) {
54 if (node_it->type != IR::AbstractSyntaxNode::Type::If) {
55 continue;
56 }
57 IR::Inst* const cond_ref{node_it->data.if_node.cond.Inst()};
58 const IR::U1 cond{cond_ref->Arg(0)};
59 if (!cond.IsImmediate()) {
60 continue;
61 }
62 if (cond.U1()) {
63 continue;
64 }
65 // False immediate condition. Remove condition ref, erase the entire branch.
66 cond_ref->Invalidate();
67 // Account for nested if-statements within the if(false) branch
68 u32 nested_ifs{1u};
69 while (node_it->type != IR::AbstractSyntaxNode::Type::EndIf || nested_ifs > 0) {
70 node_it = program.syntax_list.erase(node_it);
71 switch (node_it->type) {
72 case IR::AbstractSyntaxNode::Type::If:
73 ++nested_ifs;
74 break;
75 case IR::AbstractSyntaxNode::Type::EndIf:
76 --nested_ifs;
77 break;
78 case IR::AbstractSyntaxNode::Type::Block: {
79 IR::Block* const block{node_it->data.block};
80 DeadInstElimination<false>(block);
81 dead_blocks.push_back(block);
82 break;
83 }
84 default:
85 break;
21 } 86 }
22 } 87 }
88 // Erase EndIf node of the if(false) branch
89 node_it = program.syntax_list.erase(node_it);
90 // Account for loop increment
91 --node_it;
92 }
93 if (!dead_blocks.empty()) {
94 DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size()));
95 }
96}
97} // namespace
98
99void DeadCodeEliminationPass(IR::Program& program) {
100 DeadBranchElimination(program);
101 for (IR::Block* const block : program.post_order_blocks) {
102 DeadInstElimination<true>(block);
23 } 103 }
24} 104}
25 105
diff --git a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp
index ddf497e32..3cc1cc07a 100644
--- a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp
+++ b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp
@@ -2,10 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <compare>
7#include <optional> 5#include <optional>
8#include <queue>
9 6
10#include <boost/container/flat_set.hpp> 7#include <boost/container/flat_set.hpp>
11#include <boost/container/small_vector.hpp> 8#include <boost/container/small_vector.hpp>
diff --git a/src/shader_recompiler/ir_opt/lower_fp16_to_fp32.cpp b/src/shader_recompiler/ir_opt/lower_fp16_to_fp32.cpp
index 773e1f961..622f94fc7 100644
--- a/src/shader_recompiler/ir_opt/lower_fp16_to_fp32.cpp
+++ b/src/shader_recompiler/ir_opt/lower_fp16_to_fp32.cpp
@@ -2,9 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6
7#include "shader_recompiler/frontend/ir/ir_emitter.h"
8#include "shader_recompiler/frontend/ir/value.h" 5#include "shader_recompiler/frontend/ir/value.h"
9#include "shader_recompiler/ir_opt/passes.h" 6#include "shader_recompiler/ir_opt/passes.h"
10 7
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h
index f877c7ba0..16ea3d80a 100644
--- a/src/shader_recompiler/ir_opt/passes.h
+++ b/src/shader_recompiler/ir_opt/passes.h
@@ -4,10 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <span>
8
9#include "shader_recompiler/environment.h" 7#include "shader_recompiler/environment.h"
10#include "shader_recompiler/frontend/ir/basic_block.h"
11#include "shader_recompiler/frontend/ir/program.h" 8#include "shader_recompiler/frontend/ir/program.h"
12 9
13namespace Shader::Optimization { 10namespace Shader::Optimization {
diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp
index 496d4667e..75679c793 100644
--- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp
+++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/alignment.h"
6#include "common/settings.h" 5#include "common/settings.h"
7#include "shader_recompiler/environment.h" 6#include "shader_recompiler/environment.h"
8#include "shader_recompiler/frontend/ir/ir_emitter.h" 7#include "shader_recompiler/frontend/ir/ir_emitter.h"
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
index 87aa09358..928557acb 100644
--- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
+++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
@@ -20,7 +20,6 @@
20#include <vector> 20#include <vector>
21 21
22#include <boost/container/flat_map.hpp> 22#include <boost/container/flat_map.hpp>
23#include <boost/container/flat_set.hpp>
24 23
25#include "shader_recompiler/frontend/ir/basic_block.h" 24#include "shader_recompiler/frontend/ir/basic_block.h"
26#include "shader_recompiler/frontend/ir/opcodes.h" 25#include "shader_recompiler/frontend/ir/opcodes.h"
diff --git a/src/shader_recompiler/program_header.h b/src/shader_recompiler/program_header.h
index bd6c2bfb5..0cd6597ef 100644
--- a/src/shader_recompiler/program_header.h
+++ b/src/shader_recompiler/program_header.h
@@ -196,6 +196,11 @@ struct ProgramHeader {
196 return {(bits & 1) != 0, (bits & 2) != 0, (bits & 4) != 0, (bits & 8) != 0}; 196 return {(bits & 1) != 0, (bits & 2) != 0, (bits & 4) != 0, (bits & 8) != 0};
197 } 197 }
198 198
199 [[nodiscard]] bool HasOutputComponents(u32 rt) const noexcept {
200 const u32 bits{omap.target >> (rt * 4)};
201 return (bits & 0xf) != 0;
202 }
203
199 [[nodiscard]] std::array<PixelImap, 4> GenericInputMap(u32 attribute) const { 204 [[nodiscard]] std::array<PixelImap, 4> GenericInputMap(u32 attribute) const {
200 const auto& vector{imap_generic_vector[attribute]}; 205 const auto& vector{imap_generic_vector[attribute]};
201 return {vector.x, vector.y, vector.z, vector.w}; 206 return {vector.x, vector.y, vector.z, vector.w};
diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h
index f3f83a258..722e9d729 100644
--- a/src/shader_recompiler/runtime_info.h
+++ b/src/shader_recompiler/runtime_info.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <bitset>
9#include <optional> 8#include <optional>
10#include <vector> 9#include <vector>
11 10
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h
index be2113f5a..10975884b 100644
--- a/src/video_core/buffer_cache/buffer_base.h
+++ b/src/video_core/buffer_cache/buffer_base.h
@@ -212,7 +212,7 @@ public:
212 void FlushCachedWrites() noexcept { 212 void FlushCachedWrites() noexcept {
213 flags &= ~BufferFlagBits::CachedWrites; 213 flags &= ~BufferFlagBits::CachedWrites;
214 const u64 num_words = NumWords(); 214 const u64 num_words = NumWords();
215 const u64* const cached_words = Array<Type::CachedCPU>(); 215 u64* const cached_words = Array<Type::CachedCPU>();
216 u64* const untracked_words = Array<Type::Untracked>(); 216 u64* const untracked_words = Array<Type::Untracked>();
217 u64* const cpu_words = Array<Type::CPU>(); 217 u64* const cpu_words = Array<Type::CPU>();
218 for (u64 word_index = 0; word_index < num_words; ++word_index) { 218 for (u64 word_index = 0; word_index < num_words; ++word_index) {
@@ -220,6 +220,7 @@ public:
220 NotifyRasterizer<false>(word_index, untracked_words[word_index], cached_bits); 220 NotifyRasterizer<false>(word_index, untracked_words[word_index], cached_bits);
221 untracked_words[word_index] |= cached_bits; 221 untracked_words[word_index] |= cached_bits;
222 cpu_words[word_index] |= cached_bits; 222 cpu_words[word_index] |= cached_bits;
223 cached_words[word_index] = 0;
223 } 224 }
224 } 225 }
225 226
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 6d8955ca3..21bfb76a4 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -11,7 +11,6 @@
11#include <mutex> 11#include <mutex>
12#include <numeric> 12#include <numeric>
13#include <span> 13#include <span>
14#include <unordered_map>
15#include <vector> 14#include <vector>
16 15
17#include <boost/container/small_vector.hpp> 16#include <boost/container/small_vector.hpp>
@@ -22,7 +21,6 @@
22#include "common/literals.h" 21#include "common/literals.h"
23#include "common/lru_cache.h" 22#include "common/lru_cache.h"
24#include "common/microprofile.h" 23#include "common/microprofile.h"
25#include "common/scope_exit.h"
26#include "common/settings.h" 24#include "common/settings.h"
27#include "core/memory.h" 25#include "core/memory.h"
28#include "video_core/buffer_cache/buffer_base.h" 26#include "video_core/buffer_cache/buffer_base.h"
@@ -78,8 +76,9 @@ class BufferCache {
78 76
79 static constexpr BufferId NULL_BUFFER_ID{0}; 77 static constexpr BufferId NULL_BUFFER_ID{0};
80 78
81 static constexpr u64 EXPECTED_MEMORY = 512_MiB; 79 static constexpr s64 DEFAULT_EXPECTED_MEMORY = 512_MiB;
82 static constexpr u64 CRITICAL_MEMORY = 1_GiB; 80 static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB;
81 static constexpr s64 TARGET_THRESHOLD = 4_GiB;
83 82
84 using Maxwell = Tegra::Engines::Maxwell3D::Regs; 83 using Maxwell = Tegra::Engines::Maxwell3D::Regs;
85 84
@@ -438,6 +437,8 @@ private:
438 Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache; 437 Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
439 u64 frame_tick = 0; 438 u64 frame_tick = 0;
440 u64 total_used_memory = 0; 439 u64 total_used_memory = 0;
440 u64 minimum_memory = 0;
441 u64 critical_memory = 0;
441 442
442 std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table; 443 std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table;
443}; 444};
@@ -453,11 +454,30 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
453 // Ensure the first slot is used for the null buffer 454 // Ensure the first slot is used for the null buffer
454 void(slot_buffers.insert(runtime, NullBufferParams{})); 455 void(slot_buffers.insert(runtime, NullBufferParams{}));
455 common_ranges.clear(); 456 common_ranges.clear();
457
458 if (!runtime.CanReportMemoryUsage()) {
459 minimum_memory = DEFAULT_EXPECTED_MEMORY;
460 critical_memory = DEFAULT_CRITICAL_MEMORY;
461 return;
462 }
463
464 const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory());
465 const s64 min_spacing_expected = device_memory - 1_GiB - 512_MiB;
466 const s64 min_spacing_critical = device_memory - 1_GiB;
467 const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD);
468 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
469 const s64 min_vacancy_critical = (3 * mem_threshold) / 10;
470 minimum_memory = static_cast<u64>(
471 std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected),
472 DEFAULT_EXPECTED_MEMORY));
473 critical_memory = static_cast<u64>(
474 std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical),
475 DEFAULT_CRITICAL_MEMORY));
456} 476}
457 477
458template <class P> 478template <class P>
459void BufferCache<P>::RunGarbageCollector() { 479void BufferCache<P>::RunGarbageCollector() {
460 const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; 480 const bool aggressive_gc = total_used_memory >= critical_memory;
461 const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; 481 const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
462 int num_iterations = aggressive_gc ? 64 : 32; 482 int num_iterations = aggressive_gc ? 64 : 32;
463 const auto clean_up = [this, &num_iterations](BufferId buffer_id) { 483 const auto clean_up = [this, &num_iterations](BufferId buffer_id) {
@@ -488,7 +508,11 @@ void BufferCache<P>::TickFrame() {
488 const bool skip_preferred = hits * 256 < shots * 251; 508 const bool skip_preferred = hits * 256 < shots * 251;
489 uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; 509 uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0;
490 510
491 if (total_used_memory >= EXPECTED_MEMORY) { 511 // If we can obtain the memory info, use it instead of the estimate.
512 if (runtime.CanReportMemoryUsage()) {
513 total_used_memory = runtime.GetDeviceMemoryUsage();
514 }
515 if (total_used_memory >= minimum_memory) {
492 RunGarbageCollector(); 516 RunGarbageCollector();
493 } 517 }
494 ++frame_tick; 518 ++frame_tick;
diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp
index a8c4b4415..8dd840558 100644
--- a/src/video_core/cdma_pusher.cpp
+++ b/src/video_core/cdma_pusher.cpp
@@ -23,11 +23,9 @@
23#include "command_classes/nvdec.h" 23#include "command_classes/nvdec.h"
24#include "command_classes/vic.h" 24#include "command_classes/vic.h"
25#include "video_core/cdma_pusher.h" 25#include "video_core/cdma_pusher.h"
26#include "video_core/command_classes/nvdec_common.h"
27#include "video_core/command_classes/sync_manager.h" 26#include "video_core/command_classes/sync_manager.h"
28#include "video_core/engines/maxwell_3d.h" 27#include "video_core/engines/maxwell_3d.h"
29#include "video_core/gpu.h" 28#include "video_core/gpu.h"
30#include "video_core/memory_manager.h"
31 29
32namespace Tegra { 30namespace Tegra {
33CDmaPusher::CDmaPusher(GPU& gpu_) 31CDmaPusher::CDmaPusher(GPU& gpu_)
diff --git a/src/video_core/cdma_pusher.h b/src/video_core/cdma_pusher.h
index 87b49d6ea..cb1d16b71 100644
--- a/src/video_core/cdma_pusher.h
+++ b/src/video_core/cdma_pusher.h
@@ -8,6 +8,7 @@
8#include <vector> 8#include <vector>
9 9
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_funcs.h"
11#include "common/common_types.h" 12#include "common/common_types.h"
12 13
13namespace Tegra { 14namespace Tegra {
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp
index c9ab11e53..40f7755e8 100644
--- a/src/video_core/command_classes/codecs/codec.cpp
+++ b/src/video_core/command_classes/codecs/codec.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cstdio>
7#include <fstream> 6#include <fstream>
8#include <vector> 7#include <vector>
9#include "common/assert.h" 8#include "common/assert.h"
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h
index de5672155..661673b4e 100644
--- a/src/video_core/command_classes/codecs/codec.h
+++ b/src/video_core/command_classes/codecs/codec.h
@@ -7,7 +7,7 @@
7#include <memory> 7#include <memory>
8#include <string_view> 8#include <string_view>
9#include <queue> 9#include <queue>
10#include "common/common_types.h" 10
11#include "video_core/command_classes/nvdec_common.h" 11#include "video_core/command_classes/nvdec_common.h"
12 12
13extern "C" { 13extern "C" {
diff --git a/src/video_core/command_classes/codecs/vp8.cpp b/src/video_core/command_classes/codecs/vp8.cpp
index 32ad0ec16..2f280cb7c 100644
--- a/src/video_core/command_classes/codecs/vp8.cpp
+++ b/src/video_core/command_classes/codecs/vp8.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <vector> 5#include <vector>
7 6
8#include "video_core/command_classes/codecs/vp8.h" 7#include "video_core/command_classes/codecs/vp8.h"
diff --git a/src/video_core/command_classes/codecs/vp9_types.h b/src/video_core/command_classes/codecs/vp9_types.h
index 3b1ed4b3a..af1290016 100644
--- a/src/video_core/command_classes/codecs/vp9_types.h
+++ b/src/video_core/command_classes/codecs/vp9_types.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <cstring>
9#include <vector> 8#include <vector>
10#include "common/common_funcs.h" 9#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
diff --git a/src/video_core/command_classes/host1x.h b/src/video_core/command_classes/host1x.h
index 7e94799dd..736d2fd0c 100644
--- a/src/video_core/command_classes/host1x.h
+++ b/src/video_core/command_classes/host1x.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <vector>
8#include "common/common_funcs.h"
9#include "common/common_types.h" 7#include "common/common_types.h"
10 8
11namespace Tegra { 9namespace Tegra {
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 8d28bd884..0b51e402a 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -6,7 +6,6 @@
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/memory.h"
10#include "video_core/dma_pusher.h" 9#include "video_core/dma_pusher.h"
11#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
12#include "video_core/gpu.h" 11#include "video_core/gpu.h"
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index d76c5ed56..4c0568c4c 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -9,7 +9,6 @@
9#include "common/bit_field.h" 9#include "common/bit_field.h"
10#include "common/common_funcs.h" 10#include "common/common_funcs.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/math_util.h"
13#include "video_core/engines/engine_interface.h" 12#include "video_core/engines/engine_interface.h"
14#include "video_core/gpu.h" 13#include "video_core/gpu.h"
15 14
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index 5a1c12076..f7ff92c57 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -10,7 +10,6 @@
10#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
11#include "video_core/memory_manager.h" 11#include "video_core/memory_manager.h"
12#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
13#include "video_core/renderer_base.h"
14#include "video_core/textures/decoders.h" 13#include "video_core/textures/decoders.h"
15 14
16namespace Tegra::Engines { 15namespace Tegra::Engines {
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index f8b8d06ac..c6b8adb56 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -12,7 +12,6 @@
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "video_core/engines/engine_interface.h" 13#include "video_core/engines/engine_interface.h"
14#include "video_core/engines/engine_upload.h" 14#include "video_core/engines/engine_upload.h"
15#include "video_core/gpu.h"
16#include "video_core/textures/texture.h" 15#include "video_core/textures/texture.h"
17 16
18namespace Core { 17namespace Core {
diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp
index 8aed16caa..f930e02b6 100644
--- a/src/video_core/engines/kepler_memory.cpp
+++ b/src/video_core/engines/kepler_memory.cpp
@@ -9,8 +9,6 @@
9#include "video_core/engines/maxwell_3d.h" 9#include "video_core/engines/maxwell_3d.h"
10#include "video_core/memory_manager.h" 10#include "video_core/memory_manager.h"
11#include "video_core/rasterizer_interface.h" 11#include "video_core/rasterizer_interface.h"
12#include "video_core/renderer_base.h"
13#include "video_core/textures/decoders.h"
14 12
15namespace Tegra::Engines { 13namespace Tegra::Engines {
16 14
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index 949e2fae1..4cb4a3d2d 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -6,13 +6,11 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <vector>
10#include "common/bit_field.h" 9#include "common/bit_field.h"
11#include "common/common_funcs.h" 10#include "common/common_funcs.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "video_core/engines/engine_interface.h" 12#include "video_core/engines/engine_interface.h"
14#include "video_core/engines/engine_upload.h" 13#include "video_core/engines/engine_upload.h"
15#include "video_core/gpu.h"
16 14
17namespace Core { 15namespace Core {
18class System; 16class System;
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 357a74c70..3f5b38e55 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -10,7 +10,6 @@
10#include <limits> 10#include <limits>
11#include <optional> 11#include <optional>
12#include <type_traits> 12#include <type_traits>
13#include <unordered_map>
14#include <vector> 13#include <vector>
15 14
16#include "common/assert.h" 15#include "common/assert.h"
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 2692cac8a..9d0c77793 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -8,10 +8,8 @@
8#include <cstddef> 8#include <cstddef>
9#include <vector> 9#include <vector>
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_funcs.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "video_core/engines/engine_interface.h" 12#include "video_core/engines/engine_interface.h"
14#include "video_core/gpu.h"
15 13
16namespace Core { 14namespace Core {
17class System; 15class System;
diff --git a/src/video_core/framebuffer_config.h b/src/video_core/framebuffer_config.h
index b1d455e30..93349bb78 100644
--- a/src/video_core/framebuffer_config.h
+++ b/src/video_core/framebuffer_config.h
@@ -6,41 +6,22 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/math_util.h" 8#include "common/math_util.h"
9#include "core/hle/service/nvflinger/buffer_transform_flags.h"
10#include "core/hle/service/nvflinger/pixel_format.h"
9 11
10namespace Tegra { 12namespace Tegra {
13
11/** 14/**
12 * Struct describing framebuffer configuration 15 * Struct describing framebuffer configuration
13 */ 16 */
14struct FramebufferConfig { 17struct FramebufferConfig {
15 enum class PixelFormat : u32 {
16 A8B8G8R8_UNORM = 1,
17 RGB565_UNORM = 4,
18 B8G8R8A8_UNORM = 5,
19 };
20
21 enum class TransformFlags : u32 {
22 /// No transform flags are set
23 Unset = 0x00,
24 /// Flip source image horizontally (around the vertical axis)
25 FlipH = 0x01,
26 /// Flip source image vertically (around the horizontal axis)
27 FlipV = 0x02,
28 /// Rotate source image 90 degrees clockwise
29 Rotate90 = 0x04,
30 /// Rotate source image 180 degrees
31 Rotate180 = 0x03,
32 /// Rotate source image 270 degrees clockwise
33 Rotate270 = 0x07,
34 };
35
36 VAddr address{}; 18 VAddr address{};
37 u32 offset{}; 19 u32 offset{};
38 u32 width{}; 20 u32 width{};
39 u32 height{}; 21 u32 height{};
40 u32 stride{}; 22 u32 stride{};
41 PixelFormat pixel_format{}; 23 Service::android::PixelFormat pixel_format{};
42 24 Service::android::BufferTransformFlags transform_flags{};
43 TransformFlags transform_flags{};
44 Common::Rectangle<int> crop_rect; 25 Common::Rectangle<int> crop_rect;
45}; 26};
46 27
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 26b8ea233..97c029140 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -8,6 +8,7 @@
8 8
9#include "common/bit_field.h" 9#include "common/bit_field.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/service/nvdrv/nvdata.h"
11#include "video_core/cdma_pusher.h" 12#include "video_core/cdma_pusher.h"
12#include "video_core/framebuffer_config.h" 13#include "video_core/framebuffer_config.h"
13 14
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 4ff3fa268..722ebd9ad 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -11,7 +11,6 @@
11#include "core/hle/kernel/k_page_table.h" 11#include "core/hle/kernel/k_page_table.h"
12#include "core/hle/kernel/k_process.h" 12#include "core/hle/kernel/k_process.h"
13#include "core/memory.h" 13#include "core/memory.h"
14#include "video_core/gpu.h"
15#include "video_core/memory_manager.h" 14#include "video_core/memory_manager.h"
16#include "video_core/rasterizer_interface.h" 15#include "video_core/rasterizer_interface.h"
17#include "video_core/renderer_base.h" 16#include "video_core/renderer_base.h"
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index 0173b54d8..8a84bcfa9 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -19,7 +19,6 @@
19#include "common/assert.h" 19#include "common/assert.h"
20#include "common/settings.h" 20#include "common/settings.h"
21#include "video_core/engines/maxwell_3d.h" 21#include "video_core/engines/maxwell_3d.h"
22#include "video_core/gpu.h"
23#include "video_core/memory_manager.h" 22#include "video_core/memory_manager.h"
24#include "video_core/rasterizer_interface.h" 23#include "video_core/rasterizer_interface.h"
25 24
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index a99c33c37..c9627cffd 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/settings.h"
7#include "core/frontend/emu_window.h" 6#include "core/frontend/emu_window.h"
8#include "video_core/renderer_base.h" 7#include "video_core/renderer_base.h"
9 8
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index d4dd10bb6..f1f7b384b 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -135,6 +135,20 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_)
135 buffer.Create(); 135 buffer.Create();
136 glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); 136 glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY);
137 } 137 }
138
139 device_access_memory = [this]() -> u64 {
140 if (device.CanReportMemoryUsage()) {
141 return device.GetCurrentDedicatedVideoMemory() + 512_MiB;
142 }
143 return 2_GiB; // Return minimum requirements
144 }();
145}
146
147u64 BufferCacheRuntime::GetDeviceMemoryUsage() const {
148 if (device.CanReportMemoryUsage()) {
149 return device_access_memory - device.GetCurrentDedicatedVideoMemory();
150 }
151 return 2_GiB;
138} 152}
139 153
140void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, 154void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 060d36427..a8699f28c 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -7,9 +7,7 @@
7#include <array> 7#include <array>
8#include <span> 8#include <span>
9 9
10#include "common/alignment.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/dynamic_library.h"
13#include "video_core/buffer_cache/buffer_cache.h" 11#include "video_core/buffer_cache/buffer_cache.h"
14#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
15#include "video_core/renderer_opengl/gl_device.h" 13#include "video_core/renderer_opengl/gl_device.h"
@@ -91,6 +89,8 @@ public:
91 void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, 89 void BindImageBuffer(Buffer& buffer, u32 offset, u32 size,
92 VideoCore::Surface::PixelFormat format); 90 VideoCore::Surface::PixelFormat format);
93 91
92 u64 GetDeviceMemoryUsage() const;
93
94 void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { 94 void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) {
95 const GLuint handle = fast_uniforms[stage][binding_index].handle; 95 const GLuint handle = fast_uniforms[stage][binding_index].handle;
96 const GLsizeiptr gl_size = static_cast<GLsizeiptr>(size); 96 const GLsizeiptr gl_size = static_cast<GLsizeiptr>(size);
@@ -153,6 +153,14 @@ public:
153 use_storage_buffers = use_storage_buffers_; 153 use_storage_buffers = use_storage_buffers_;
154 } 154 }
155 155
156 u64 GetDeviceLocalMemory() const {
157 return device_access_memory;
158 }
159
160 bool CanReportMemoryUsage() const {
161 return device.CanReportMemoryUsage();
162 }
163
156private: 164private:
157 static constexpr std::array PABO_LUT{ 165 static constexpr std::array PABO_LUT{
158 GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV, 166 GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV,
@@ -186,6 +194,8 @@ private:
186 std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms; 194 std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms;
187 195
188 u32 index_buffer_offset = 0; 196 u32 index_buffer_offset = 0;
197
198 u64 device_access_memory;
189}; 199};
190 200
191struct BufferCacheParams { 201struct BufferCacheParams {
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h
index 50c676365..b0d183b46 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <type_traits> 8#include <type_traits>
9#include <utility>
10 9
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "shader_recompiler/shader_info.h" 11#include "shader_recompiler/shader_info.h"
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index e62912a22..656dd7eb0 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -6,8 +6,6 @@
6#include <array> 6#include <array>
7#include <cstddef> 7#include <cstddef>
8#include <cstdlib> 8#include <cstdlib>
9#include <cstring>
10#include <limits>
11#include <optional> 9#include <optional>
12#include <span> 10#include <span>
13#include <stdexcept> 11#include <stdexcept>
@@ -15,13 +13,15 @@
15 13
16#include <glad/glad.h> 14#include <glad/glad.h>
17 15
16#include "common/literals.h"
18#include "common/logging/log.h" 17#include "common/logging/log.h"
19#include "common/scope_exit.h"
20#include "common/settings.h" 18#include "common/settings.h"
21#include "shader_recompiler/stage.h" 19#include "shader_recompiler/stage.h"
22#include "video_core/renderer_opengl/gl_device.h" 20#include "video_core/renderer_opengl/gl_device.h"
23#include "video_core/renderer_opengl/gl_resource_manager.h" 21#include "video_core/renderer_opengl/gl_resource_manager.h"
24 22
23using namespace Common::Literals;
24
25namespace OpenGL { 25namespace OpenGL {
26namespace { 26namespace {
27constexpr std::array LIMIT_UBOS = { 27constexpr std::array LIMIT_UBOS = {
@@ -168,6 +168,7 @@ Device::Device() {
168 has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2; 168 has_sparse_texture_2 = GLAD_GL_ARB_sparse_texture2;
169 warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel; 169 warp_size_potentially_larger_than_guest = !is_nvidia && !is_intel;
170 need_fastmath_off = is_nvidia; 170 need_fastmath_off = is_nvidia;
171 can_report_memory = GLAD_GL_NVX_gpu_memory_info;
171 172
172 // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive 173 // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive
173 // uniform buffers as "push constants" 174 // uniform buffers as "push constants"
@@ -279,4 +280,10 @@ void main() {
279})"); 280})");
280} 281}
281 282
283u64 Device::GetCurrentDedicatedVideoMemory() const {
284 GLint cur_avail_mem_kb = 0;
285 glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &cur_avail_mem_kb);
286 return static_cast<u64>(cur_avail_mem_kb) * 1_KiB;
287}
288
282} // namespace OpenGL 289} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 95c2e8d38..9bb0b9148 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -20,6 +20,8 @@ public:
20 20
21 [[nodiscard]] std::string GetVendorName() const; 21 [[nodiscard]] std::string GetVendorName() const;
22 22
23 u64 GetCurrentDedicatedVideoMemory() const;
24
23 u32 GetMaxUniformBuffers(Shader::Stage stage) const noexcept { 25 u32 GetMaxUniformBuffers(Shader::Stage stage) const noexcept {
24 return max_uniform_buffers[static_cast<size_t>(stage)]; 26 return max_uniform_buffers[static_cast<size_t>(stage)];
25 } 27 }
@@ -168,6 +170,10 @@ public:
168 return vendor_name == "ATI Technologies Inc."; 170 return vendor_name == "ATI Technologies Inc.";
169 } 171 }
170 172
173 bool CanReportMemoryUsage() const {
174 return can_report_memory;
175 }
176
171private: 177private:
172 static bool TestVariableAoffi(); 178 static bool TestVariableAoffi();
173 static bool TestPreciseBug(); 179 static bool TestPreciseBug();
@@ -210,6 +216,7 @@ private:
210 bool need_fastmath_off{}; 216 bool need_fastmath_off{};
211 bool has_cbuf_ftou_bug{}; 217 bool has_cbuf_ftou_bug{};
212 bool has_bool_ref_bug{}; 218 bool has_bool_ref_bug{};
219 bool can_report_memory{};
213 220
214 std::string vendor_name; 221 std::string vendor_name;
215}; 222};
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
index 311d49f3f..4f8049717 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
@@ -14,7 +14,6 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "shader_recompiler/shader_info.h" 15#include "shader_recompiler/shader_info.h"
16#include "video_core/engines/maxwell_3d.h" 16#include "video_core/engines/maxwell_3d.h"
17#include "video_core/memory_manager.h"
18#include "video_core/renderer_opengl/gl_buffer_cache.h" 17#include "video_core/renderer_opengl/gl_buffer_cache.h"
19#include "video_core/renderer_opengl/gl_resource_manager.h" 18#include "video_core/renderer_opengl/gl_resource_manager.h"
20#include "video_core/renderer_opengl/gl_texture_cache.h" 19#include "video_core/renderer_opengl/gl_texture_cache.h"
diff --git a/src/video_core/renderer_opengl/gl_query_cache.cpp b/src/video_core/renderer_opengl/gl_query_cache.cpp
index acebbf5f4..9e6c50055 100644
--- a/src/video_core/renderer_opengl/gl_query_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_query_cache.cpp
@@ -3,15 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cstring>
7#include <memory> 6#include <memory>
8#include <unordered_map>
9#include <utility> 7#include <utility>
10#include <vector> 8#include <vector>
11 9
12#include <glad/glad.h> 10#include <glad/glad.h>
13 11
14#include "common/assert.h"
15#include "core/core.h" 12#include "core/core.h"
16#include "video_core/engines/maxwell_3d.h" 13#include "video_core/engines/maxwell_3d.h"
17#include "video_core/memory_manager.h" 14#include "video_core/memory_manager.h"
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 142412a8e..e6f9ece8b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -6,9 +6,7 @@
6#include <array> 6#include <array>
7#include <bitset> 7#include <bitset>
8#include <memory> 8#include <memory>
9#include <string>
10#include <string_view> 9#include <string_view>
11#include <tuple>
12#include <utility> 10#include <utility>
13 11
14#include <glad/glad.h> 12#include <glad/glad.h>
@@ -17,8 +15,9 @@
17#include "common/logging/log.h" 15#include "common/logging/log.h"
18#include "common/math_util.h" 16#include "common/math_util.h"
19#include "common/microprofile.h" 17#include "common/microprofile.h"
18#include "common/scope_exit.h"
20#include "common/settings.h" 19#include "common/settings.h"
21#include "core/memory.h" 20
22#include "video_core/engines/kepler_compute.h" 21#include "video_core/engines/kepler_compute.h"
23#include "video_core/engines/maxwell_3d.h" 22#include "video_core/engines/maxwell_3d.h"
24#include "video_core/memory_manager.h" 23#include "video_core/memory_manager.h"
@@ -212,6 +211,7 @@ void RasterizerOpenGL::Clear() {
212void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { 211void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
213 MICROPROFILE_SCOPE(OpenGL_Drawing); 212 MICROPROFILE_SCOPE(OpenGL_Drawing);
214 213
214 SCOPE_EXIT({ gpu.TickWork(); });
215 query_cache.UpdateCounters(); 215 query_cache.UpdateCounters();
216 216
217 GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()}; 217 GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()};
@@ -267,8 +267,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
267 267
268 ++num_queued_commands; 268 ++num_queued_commands;
269 has_written_global_memory |= pipeline->WritesGlobalMemory(); 269 has_written_global_memory |= pipeline->WritesGlobalMemory();
270
271 gpu.TickWork();
272} 270}
273 271
274void RasterizerOpenGL::DispatchCompute() { 272void RasterizerOpenGL::DispatchCompute() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 98f6fd342..c79461d59 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -5,20 +5,14 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <atomic>
9#include <cstddef> 8#include <cstddef>
10#include <memory>
11#include <optional> 9#include <optional>
12#include <tuple>
13#include <utility>
14 10
15#include <boost/container/static_vector.hpp> 11#include <boost/container/static_vector.hpp>
16 12
17#include <glad/glad.h> 13#include <glad/glad.h>
18 14
19#include "common/common_types.h" 15#include "common/common_types.h"
20#include "video_core/engines/const_buffer_info.h"
21#include "video_core/engines/maxwell_3d.h"
22#include "video_core/engines/maxwell_dma.h" 16#include "video_core/engines/maxwell_dma.h"
23#include "video_core/rasterizer_accelerated.h" 17#include "video_core/rasterizer_accelerated.h"
24#include "video_core/rasterizer_interface.h" 18#include "video_core/rasterizer_interface.h"
@@ -26,12 +20,8 @@
26#include "video_core/renderer_opengl/gl_device.h" 20#include "video_core/renderer_opengl/gl_device.h"
27#include "video_core/renderer_opengl/gl_fence_manager.h" 21#include "video_core/renderer_opengl/gl_fence_manager.h"
28#include "video_core/renderer_opengl/gl_query_cache.h" 22#include "video_core/renderer_opengl/gl_query_cache.h"
29#include "video_core/renderer_opengl/gl_resource_manager.h"
30#include "video_core/renderer_opengl/gl_shader_cache.h" 23#include "video_core/renderer_opengl/gl_shader_cache.h"
31#include "video_core/renderer_opengl/gl_shader_manager.h"
32#include "video_core/renderer_opengl/gl_state_tracker.h"
33#include "video_core/renderer_opengl/gl_texture_cache.h" 24#include "video_core/renderer_opengl/gl_texture_cache.h"
34#include "video_core/textures/texture.h"
35 25
36namespace Core::Memory { 26namespace Core::Memory {
37class Memory; 27class Memory;
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
index 5e7101d28..f6839a657 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string_view> 5#include <string_view>
6#include <utility>
7#include <glad/glad.h> 6#include <glad/glad.h>
8#include "common/common_types.h"
9#include "common/microprofile.h" 7#include "common/microprofile.h"
10#include "video_core/renderer_opengl/gl_resource_manager.h" 8#include "video_core/renderer_opengl/gl_resource_manager.h"
11#include "video_core/renderer_opengl/gl_shader_util.h" 9#include "video_core/renderer_opengl/gl_shader_util.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index f71e01a34..6423992c3 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -14,10 +14,8 @@
14#include "common/fs/fs.h" 14#include "common/fs/fs.h"
15#include "common/fs/path_util.h" 15#include "common/fs/path_util.h"
16#include "common/logging/log.h" 16#include "common/logging/log.h"
17#include "common/scope_exit.h"
18#include "common/settings.h" 17#include "common/settings.h"
19#include "common/thread_worker.h" 18#include "common/thread_worker.h"
20#include "core/core.h"
21#include "shader_recompiler/backend/glasm/emit_glasm.h" 19#include "shader_recompiler/backend/glasm/emit_glasm.h"
22#include "shader_recompiler/backend/glsl/emit_glsl.h" 20#include "shader_recompiler/backend/glsl/emit_glsl.h"
23#include "shader_recompiler/backend/spirv/emit_spirv.h" 21#include "shader_recompiler/backend/spirv/emit_spirv.h"
@@ -29,7 +27,6 @@
29#include "video_core/engines/maxwell_3d.h" 27#include "video_core/engines/maxwell_3d.h"
30#include "video_core/memory_manager.h" 28#include "video_core/memory_manager.h"
31#include "video_core/renderer_opengl/gl_rasterizer.h" 29#include "video_core/renderer_opengl/gl_rasterizer.h"
32#include "video_core/renderer_opengl/gl_resource_manager.h"
33#include "video_core/renderer_opengl/gl_shader_cache.h" 30#include "video_core/renderer_opengl/gl_shader_cache.h"
34#include "video_core/renderer_opengl/gl_shader_util.h" 31#include "video_core/renderer_opengl/gl_shader_util.h"
35#include "video_core/renderer_opengl/gl_state_tracker.h" 32#include "video_core/renderer_opengl/gl_state_tracker.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index a34110b37..06d4b38bb 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -4,18 +4,13 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <filesystem> 7#include <filesystem>
9#include <stop_token> 8#include <stop_token>
10#include <unordered_map> 9#include <unordered_map>
11 10
12#include <glad/glad.h>
13
14#include "common/common_types.h" 11#include "common/common_types.h"
15#include "common/thread_worker.h" 12#include "common/thread_worker.h"
16#include "shader_recompiler/frontend/ir/value.h"
17#include "shader_recompiler/host_translate_info.h" 13#include "shader_recompiler/host_translate_info.h"
18#include "shader_recompiler/object_pool.h"
19#include "shader_recompiler/profile.h" 14#include "shader_recompiler/profile.h"
20#include "video_core/renderer_opengl/gl_compute_pipeline.h" 15#include "video_core/renderer_opengl/gl_compute_pipeline.h"
21#include "video_core/renderer_opengl/gl_graphics_pipeline.h" 16#include "video_core/renderer_opengl/gl_graphics_pipeline.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index d432072ad..129966e72 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -6,7 +6,6 @@
6#include <vector> 6#include <vector>
7#include <glad/glad.h> 7#include <glad/glad.h>
8 8
9#include "common/assert.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/settings.h" 10#include "common/settings.h"
12#include "video_core/renderer_opengl/gl_shader_util.h" 11#include "video_core/renderer_opengl/gl_shader_util.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h
index 4e1a2a8e1..a64ef37dc 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.h
+++ b/src/video_core/renderer_opengl/gl_shader_util.h
@@ -5,14 +5,10 @@
5#pragma once 5#pragma once
6 6
7#include <span> 7#include <span>
8#include <string>
9#include <string_view> 8#include <string_view>
10#include <vector>
11 9
12#include <glad/glad.h> 10#include <glad/glad.h>
13 11
14#include "common/assert.h"
15#include "common/logging/log.h"
16#include "video_core/renderer_opengl/gl_resource_manager.h" 12#include "video_core/renderer_opengl/gl_resource_manager.h"
17 13
18namespace OpenGL { 14namespace OpenGL {
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index 2e67922a6..f0cb29dca 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <memory>
9#include <span> 8#include <span>
10#include <utility> 9#include <utility>
11 10
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 3c1f79a27..8f9a65beb 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -484,6 +484,13 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
484 rescale_read_fbos[i].Create(); 484 rescale_read_fbos[i].Create();
485 } 485 }
486 } 486 }
487
488 device_access_memory = [this]() -> u64 {
489 if (device.CanReportMemoryUsage()) {
490 return device.GetCurrentDedicatedVideoMemory() + 512_MiB;
491 }
492 return 2_GiB; // Return minimum requirements
493 }();
487} 494}
488 495
489TextureCacheRuntime::~TextureCacheRuntime() = default; 496TextureCacheRuntime::~TextureCacheRuntime() = default;
@@ -500,13 +507,11 @@ ImageBufferMap TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
500 return download_buffers.RequestMap(size, false); 507 return download_buffers.RequestMap(size, false);
501} 508}
502 509
503u64 TextureCacheRuntime::GetDeviceLocalMemory() const { 510u64 TextureCacheRuntime::GetDeviceMemoryUsage() const {
504 if (GLAD_GL_NVX_gpu_memory_info) { 511 if (device.CanReportMemoryUsage()) {
505 GLint cur_avail_mem_kb = 0; 512 return device_access_memory - device.GetCurrentDedicatedVideoMemory();
506 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &cur_avail_mem_kb);
507 return static_cast<u64>(cur_avail_mem_kb) * 1_KiB;
508 } 513 }
509 return 2_GiB; // Return minimum requirements 514 return 2_GiB;
510} 515}
511 516
512void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image, 517void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image,
@@ -686,6 +691,7 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
686 } 691 }
687 if (IsConverted(runtime->device, info.format, info.type)) { 692 if (IsConverted(runtime->device, info.format, info.type)) {
688 flags |= ImageFlagBits::Converted; 693 flags |= ImageFlagBits::Converted;
694 flags |= ImageFlagBits::CostlyLoad;
689 gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8; 695 gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
690 gl_format = GL_RGBA; 696 gl_format = GL_RGBA;
691 gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 697 gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 7f425631f..53088b66e 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -10,6 +10,7 @@
10#include <glad/glad.h> 10#include <glad/glad.h>
11 11
12#include "shader_recompiler/shader_info.h" 12#include "shader_recompiler/shader_info.h"
13#include "video_core/renderer_opengl/gl_device.h"
13#include "video_core/renderer_opengl/gl_resource_manager.h" 14#include "video_core/renderer_opengl/gl_resource_manager.h"
14#include "video_core/renderer_opengl/util_shaders.h" 15#include "video_core/renderer_opengl/util_shaders.h"
15#include "video_core/texture_cache/image_view_base.h" 16#include "video_core/texture_cache/image_view_base.h"
@@ -21,7 +22,6 @@ struct ResolutionScalingInfo;
21 22
22namespace OpenGL { 23namespace OpenGL {
23 24
24class Device;
25class ProgramManager; 25class ProgramManager;
26class StateTracker; 26class StateTracker;
27 27
@@ -83,7 +83,15 @@ public:
83 83
84 ImageBufferMap DownloadStagingBuffer(size_t size); 84 ImageBufferMap DownloadStagingBuffer(size_t size);
85 85
86 u64 GetDeviceLocalMemory() const; 86 u64 GetDeviceLocalMemory() const {
87 return device_access_memory;
88 }
89
90 u64 GetDeviceMemoryUsage() const;
91
92 bool CanReportMemoryUsage() const {
93 return device.CanReportMemoryUsage();
94 }
87 95
88 bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) { 96 bool ShouldReinterpret([[maybe_unused]] Image& dst, [[maybe_unused]] Image& src) {
89 return true; 97 return true;
@@ -172,6 +180,7 @@ private:
172 std::array<OGLFramebuffer, 4> rescale_draw_fbos; 180 std::array<OGLFramebuffer, 4> rescale_draw_fbos;
173 std::array<OGLFramebuffer, 4> rescale_read_fbos; 181 std::array<OGLFramebuffer, 4> rescale_read_fbos;
174 const Settings::ResolutionScalingInfo& resolution; 182 const Settings::ResolutionScalingInfo& resolution;
183 u64 device_access_memory;
175}; 184};
176 185
177class Image : public VideoCommon::ImageBase { 186class Image : public VideoCommon::ImageBase {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index f81c1b233..f8f29013a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstddef> 6#include <cstddef>
7#include <cstdlib> 7#include <cstdlib>
8#include <cstring>
9#include <memory> 8#include <memory>
10 9
11#include <glad/glad.h> 10#include <glad/glad.h>
@@ -15,11 +14,9 @@
15#include "common/microprofile.h" 14#include "common/microprofile.h"
16#include "common/settings.h" 15#include "common/settings.h"
17#include "common/telemetry.h" 16#include "common/telemetry.h"
18#include "core/core.h"
19#include "core/core_timing.h" 17#include "core/core_timing.h"
20#include "core/frontend/emu_window.h" 18#include "core/frontend/emu_window.h"
21#include "core/memory.h" 19#include "core/memory.h"
22#include "core/perf_stats.h"
23#include "core/telemetry_session.h" 20#include "core/telemetry_session.h"
24#include "video_core/host_shaders/fxaa_frag.h" 21#include "video_core/host_shaders/fxaa_frag.h"
25#include "video_core/host_shaders/fxaa_vert.h" 22#include "video_core/host_shaders/fxaa_vert.h"
@@ -326,12 +323,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
326 323
327 GLint internal_format; 324 GLint internal_format;
328 switch (framebuffer.pixel_format) { 325 switch (framebuffer.pixel_format) {
329 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: 326 case Service::android::PixelFormat::Rgba8888:
330 internal_format = GL_RGBA8; 327 internal_format = GL_RGBA8;
331 texture.gl_format = GL_RGBA; 328 texture.gl_format = GL_RGBA;
332 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 329 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
333 break; 330 break;
334 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: 331 case Service::android::PixelFormat::Rgb565:
335 internal_format = GL_RGB565; 332 internal_format = GL_RGB565;
336 texture.gl_format = GL_RGB; 333 texture.gl_format = GL_RGB;
337 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; 334 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
@@ -467,8 +464,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
467 const auto& texcoords = screen_info.display_texcoords; 464 const auto& texcoords = screen_info.display_texcoords;
468 auto left = texcoords.left; 465 auto left = texcoords.left;
469 auto right = texcoords.right; 466 auto right = texcoords.right;
470 if (framebuffer_transform_flags != Tegra::FramebufferConfig::TransformFlags::Unset) { 467 if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) {
471 if (framebuffer_transform_flags == Tegra::FramebufferConfig::TransformFlags::FlipV) { 468 if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) {
472 // Flip the framebuffer vertically 469 // Flip the framebuffer vertically
473 left = texcoords.right; 470 left = texcoords.right;
474 right = texcoords.left; 471 right = texcoords.left;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index cda333cad..aa206878b 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -8,10 +8,12 @@
8#include <glad/glad.h> 8#include <glad/glad.h>
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/math_util.h" 10#include "common/math_util.h"
11
11#include "video_core/renderer_base.h" 12#include "video_core/renderer_base.h"
12#include "video_core/renderer_opengl/gl_device.h" 13#include "video_core/renderer_opengl/gl_device.h"
13#include "video_core/renderer_opengl/gl_rasterizer.h" 14#include "video_core/renderer_opengl/gl_rasterizer.h"
14#include "video_core/renderer_opengl/gl_resource_manager.h" 15#include "video_core/renderer_opengl/gl_resource_manager.h"
16#include "video_core/renderer_opengl/gl_shader_manager.h"
15#include "video_core/renderer_opengl/gl_state_tracker.h" 17#include "video_core/renderer_opengl/gl_state_tracker.h"
16 18
17namespace Core { 19namespace Core {
@@ -44,7 +46,7 @@ struct TextureInfo {
44 GLsizei height; 46 GLsizei height;
45 GLenum gl_format; 47 GLenum gl_format;
46 GLenum gl_type; 48 GLenum gl_type;
47 Tegra::FramebufferConfig::PixelFormat pixel_format; 49 Service::android::PixelFormat pixel_format;
48}; 50};
49 51
50/// Structure used for storing information about the display target for the Switch screen 52/// Structure used for storing information about the display target for the Switch screen
@@ -133,7 +135,7 @@ private:
133 std::vector<u8> gl_framebuffer_data; 135 std::vector<u8> gl_framebuffer_data;
134 136
135 /// Used for transforming the framebuffer orientation 137 /// Used for transforming the framebuffer orientation
136 Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{}; 138 Service::android::BufferTransformFlags framebuffer_transform_flags{};
137 Common::Rectangle<int> framebuffer_crop_rect; 139 Common::Rectangle<int> framebuffer_crop_rect;
138}; 140};
139 141
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index ec03cca38..abda1c490 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -367,17 +367,14 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
367 PipelineLayoutCreateInfo(two_textures_set_layout.address()))), 367 PipelineLayoutCreateInfo(two_textures_set_layout.address()))),
368 full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)), 368 full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
369 blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), 369 blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)),
370 blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)),
370 convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), 371 convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)),
371 convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), 372 convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
372 convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), 373 convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
373 convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)), 374 convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
374 convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)), 375 convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
375 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), 376 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
376 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { 377 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
377 if (device.IsExtShaderStencilExportSupported()) {
378 blit_depth_stencil_frag = BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV);
379 }
380}
381 378
382BlitImageHelper::~BlitImageHelper() = default; 379BlitImageHelper::~BlitImageHelper() = default;
383 380
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index 1a3944179..29ee0f67a 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <compare>
8
9#include "video_core/engines/fermi_2d.h" 7#include "video_core/engines/fermi_2d.h"
10#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 8#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
11#include "video_core/texture_cache/types.h" 9#include "video_core/texture_cache/types.h"
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index d70153df3..c2259ac5f 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -4,9 +4,6 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include <tuple>
8
9#include <boost/functional/hash.hpp>
10 7
11#include "common/bit_cast.h" 8#include "common/bit_cast.h"
12#include "common/cityhash.h" 9#include "common/cityhash.h"
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.h b/src/video_core/renderer_vulkan/maxwell_to_vk.h
index 8a9616039..1c1f420f2 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.h
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "shader_recompiler/stage.h" 7#include "shader_recompiler/stage.h"
9#include "video_core/engines/maxwell_3d.h" 8#include "video_core/engines/maxwell_3d.h"
10#include "video_core/surface.h" 9#include "video_core/surface.h"
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 11c160570..c25d469e6 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -8,7 +8,6 @@
8 8
9#include <boost/container/small_vector.hpp> 9#include <boost/container/small_vector.hpp>
10 10
11#include "common/assert.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "shader_recompiler/backend/spirv/emit_spirv.h" 12#include "shader_recompiler/backend/spirv/emit_spirv.h"
14#include "shader_recompiler/shader_info.h" 13#include "shader_recompiler/shader_info.h"
@@ -16,7 +15,6 @@
16#include "video_core/renderer_vulkan/vk_update_descriptor.h" 15#include "video_core/renderer_vulkan/vk_update_descriptor.h"
17#include "video_core/texture_cache/texture_cache.h" 16#include "video_core/texture_cache/texture_cache.h"
18#include "video_core/texture_cache/types.h" 17#include "video_core/texture_cache/types.h"
19#include "video_core/textures/texture.h"
20#include "video_core/vulkan_common/vulkan_device.h" 18#include "video_core/vulkan_common/vulkan_device.h"
21 19
22namespace Vulkan { 20namespace Vulkan {
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 74822814d..ef57fdfa4 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -13,16 +13,15 @@
13#include <fmt/format.h> 13#include <fmt/format.h>
14 14
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/scope_exit.h"
16#include "common/settings.h" 17#include "common/settings.h"
17#include "common/telemetry.h" 18#include "common/telemetry.h"
18#include "core/core.h"
19#include "core/core_timing.h" 19#include "core/core_timing.h"
20#include "core/frontend/emu_window.h" 20#include "core/frontend/emu_window.h"
21#include "core/telemetry_session.h" 21#include "core/telemetry_session.h"
22#include "video_core/gpu.h" 22#include "video_core/gpu.h"
23#include "video_core/renderer_vulkan/renderer_vulkan.h" 23#include "video_core/renderer_vulkan/renderer_vulkan.h"
24#include "video_core/renderer_vulkan/vk_blit_screen.h" 24#include "video_core/renderer_vulkan/vk_blit_screen.h"
25#include "video_core/renderer_vulkan/vk_master_semaphore.h"
26#include "video_core/renderer_vulkan/vk_rasterizer.h" 25#include "video_core/renderer_vulkan/vk_rasterizer.h"
27#include "video_core/renderer_vulkan/vk_scheduler.h" 26#include "video_core/renderer_vulkan/vk_scheduler.h"
28#include "video_core/renderer_vulkan/vk_state_tracker.h" 27#include "video_core/renderer_vulkan/vk_state_tracker.h"
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 6dc985109..9680108b6 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9#include <vector>
10 9
11#include "common/dynamic_library.h" 10#include "common/dynamic_library.h"
12#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 621a6a071..d893c1952 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -6,7 +6,6 @@
6#include <array> 6#include <array>
7#include <cstring> 7#include <cstring>
8#include <memory> 8#include <memory>
9#include <tuple>
10#include <vector> 9#include <vector>
11 10
12#include "common/assert.h" 11#include "common/assert.h"
@@ -28,7 +27,6 @@
28#include "video_core/renderer_vulkan/renderer_vulkan.h" 27#include "video_core/renderer_vulkan/renderer_vulkan.h"
29#include "video_core/renderer_vulkan/vk_blit_screen.h" 28#include "video_core/renderer_vulkan/vk_blit_screen.h"
30#include "video_core/renderer_vulkan/vk_fsr.h" 29#include "video_core/renderer_vulkan/vk_fsr.h"
31#include "video_core/renderer_vulkan/vk_master_semaphore.h"
32#include "video_core/renderer_vulkan/vk_scheduler.h" 30#include "video_core/renderer_vulkan/vk_scheduler.h"
33#include "video_core/renderer_vulkan/vk_shader_util.h" 31#include "video_core/renderer_vulkan/vk_shader_util.h"
34#include "video_core/renderer_vulkan/vk_swapchain.h" 32#include "video_core/renderer_vulkan/vk_swapchain.h"
@@ -96,11 +94,11 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
96 94
97VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { 95VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
98 switch (framebuffer.pixel_format) { 96 switch (framebuffer.pixel_format) {
99 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: 97 case Service::android::PixelFormat::Rgba8888:
100 return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 98 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
101 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: 99 case Service::android::PixelFormat::Rgb565:
102 return VK_FORMAT_R5G6B5_UNORM_PACK16; 100 return VK_FORMAT_R5G6B5_UNORM_PACK16;
103 case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM: 101 case Service::android::PixelFormat::Bgra8888:
104 return VK_FORMAT_B8G8R8A8_UNORM; 102 return VK_FORMAT_B8G8R8A8_UNORM;
105 default: 103 default:
106 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", 104 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
@@ -1392,9 +1390,9 @@ void VKBlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfi
1392 auto right = texcoords.right; 1390 auto right = texcoords.right;
1393 1391
1394 switch (framebuffer_transform_flags) { 1392 switch (framebuffer_transform_flags) {
1395 case Tegra::FramebufferConfig::TransformFlags::Unset: 1393 case Service::android::BufferTransformFlags::Unset:
1396 break; 1394 break;
1397 case Tegra::FramebufferConfig::TransformFlags::FlipV: 1395 case Service::android::BufferTransformFlags::FlipV:
1398 // Flip the framebuffer vertically 1396 // Flip the framebuffer vertically
1399 left = texcoords.right; 1397 left = texcoords.right;
1400 right = texcoords.left; 1398 right = texcoords.left;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 5ffd93499..def838c34 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -141,6 +141,18 @@ StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size) {
141 return staging_pool.Request(size, MemoryUsage::Download); 141 return staging_pool.Request(size, MemoryUsage::Download);
142} 142}
143 143
144u64 BufferCacheRuntime::GetDeviceLocalMemory() const {
145 return device.GetDeviceLocalMemory();
146}
147
148u64 BufferCacheRuntime::GetDeviceMemoryUsage() const {
149 return device.GetDeviceMemoryUsage();
150}
151
152bool BufferCacheRuntime::CanReportMemoryUsage() const {
153 return device.CanReportMemoryUsage();
154}
155
144void BufferCacheRuntime::Finish() { 156void BufferCacheRuntime::Finish() {
145 scheduler.Finish(); 157 scheduler.Finish();
146} 158}
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 1ee0d8420..d7fdd18ff 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -65,6 +65,12 @@ public:
65 65
66 void Finish(); 66 void Finish();
67 67
68 u64 GetDeviceLocalMemory() const;
69
70 u64 GetDeviceMemoryUsage() const;
71
72 bool CanReportMemoryUsage() const;
73
68 [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); 74 [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);
69 75
70 [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); 76 [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 4d73427b4..713794410 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -3,12 +3,10 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <cstring>
7#include <memory> 6#include <memory>
8#include <optional> 7#include <optional>
9#include <utility> 8#include <utility>
10 9
11#include "common/alignment.h"
12#include "common/assert.h" 10#include "common/assert.h"
13#include "common/common_types.h" 11#include "common/common_types.h"
14#include "common/div_ceil.h" 12#include "common/div_ceil.h"
@@ -23,7 +21,6 @@
23#include "video_core/renderer_vulkan/vk_update_descriptor.h" 21#include "video_core/renderer_vulkan/vk_update_descriptor.h"
24#include "video_core/texture_cache/accelerated_swizzle.h" 22#include "video_core/texture_cache/accelerated_swizzle.h"
25#include "video_core/texture_cache/types.h" 23#include "video_core/texture_cache/types.h"
26#include "video_core/textures/astc.h"
27#include "video_core/textures/decoders.h" 24#include "video_core/textures/decoders.h"
28#include "video_core/vulkan_common/vulkan_device.h" 25#include "video_core/vulkan_common/vulkan_device.h"
29#include "video_core/vulkan_common/vulkan_wrapper.h" 26#include "video_core/vulkan_common/vulkan_wrapper.h"
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index 8c4b0a301..c64bd9a06 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -11,7 +11,6 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/thread_worker.h" 12#include "common/thread_worker.h"
13#include "shader_recompiler/shader_info.h" 13#include "shader_recompiler/shader_info.h"
14#include "video_core/memory_manager.h"
15#include "video_core/renderer_vulkan/vk_buffer_cache.h" 14#include "video_core/renderer_vulkan/vk_buffer_cache.h"
16#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 15#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
17#include "video_core/renderer_vulkan/vk_texture_cache.h" 16#include "video_core/renderer_vulkan/vk_texture_cache.h"
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
index 3bec48d14..0c1098c8f 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
@@ -9,7 +9,6 @@
9#include "video_core/renderer_vulkan/vk_scheduler.h" 9#include "video_core/renderer_vulkan/vk_scheduler.h"
10#include "video_core/renderer_vulkan/vk_texture_cache.h" 10#include "video_core/renderer_vulkan/vk_texture_cache.h"
11#include "video_core/vulkan_common/vulkan_device.h" 11#include "video_core/vulkan_common/vulkan_device.h"
12#include "video_core/vulkan_common/vulkan_wrapper.h"
13 12
14namespace Vulkan { 13namespace Vulkan {
15 14
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h
index 2f8322d29..cf9f4adbf 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.h
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.h
@@ -9,7 +9,6 @@
9#include "video_core/fence_manager.h" 9#include "video_core/fence_manager.h"
10#include "video_core/renderer_vulkan/vk_buffer_cache.h" 10#include "video_core/renderer_vulkan/vk_buffer_cache.h"
11#include "video_core/renderer_vulkan/vk_texture_cache.h" 11#include "video_core/renderer_vulkan/vk_texture_cache.h"
12#include "video_core/vulkan_common/vulkan_wrapper.h"
13 12
14namespace Core { 13namespace Core {
15class System; 14class System;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index a633b73e5..27e59df73 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -16,13 +16,11 @@
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/thread_worker.h" 17#include "common/thread_worker.h"
18#include "core/core.h" 18#include "core/core.h"
19#include "core/memory.h"
20#include "shader_recompiler/backend/spirv/emit_spirv.h" 19#include "shader_recompiler/backend/spirv/emit_spirv.h"
21#include "shader_recompiler/environment.h" 20#include "shader_recompiler/environment.h"
22#include "shader_recompiler/frontend/maxwell/control_flow.h" 21#include "shader_recompiler/frontend/maxwell/control_flow.h"
23#include "shader_recompiler/frontend/maxwell/translate_program.h" 22#include "shader_recompiler/frontend/maxwell/translate_program.h"
24#include "shader_recompiler/program_header.h" 23#include "shader_recompiler/program_header.h"
25#include "video_core/dirty_flags.h"
26#include "video_core/engines/kepler_compute.h" 24#include "video_core/engines/kepler_compute.h"
27#include "video_core/engines/maxwell_3d.h" 25#include "video_core/engines/maxwell_3d.h"
28#include "video_core/memory_manager.h" 26#include "video_core/memory_manager.h"
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 4c135b5dd..579e25a4a 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -7,11 +7,9 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <filesystem> 9#include <filesystem>
10#include <iosfwd>
11#include <memory> 10#include <memory>
12#include <type_traits> 11#include <type_traits>
13#include <unordered_map> 12#include <unordered_map>
14#include <utility>
15#include <vector> 13#include <vector>
16 14
17#include "common/common_types.h" 15#include "common/common_types.h"
@@ -29,7 +27,6 @@
29#include "video_core/renderer_vulkan/vk_graphics_pipeline.h" 27#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
30#include "video_core/renderer_vulkan/vk_texture_cache.h" 28#include "video_core/renderer_vulkan/vk_texture_cache.h"
31#include "video_core/shader_cache.h" 29#include "video_core/shader_cache.h"
32#include "video_core/vulkan_common/vulkan_wrapper.h"
33 30
34namespace Core { 31namespace Core {
35class System; 32class System;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 2227d9197..fa87d37f8 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -6,15 +6,12 @@
6#include <array> 6#include <array>
7#include <memory> 7#include <memory>
8#include <mutex> 8#include <mutex>
9#include <vector>
10 9
11#include "common/alignment.h"
12#include "common/assert.h" 10#include "common/assert.h"
13#include "common/logging/log.h" 11#include "common/logging/log.h"
14#include "common/microprofile.h" 12#include "common/microprofile.h"
15#include "common/scope_exit.h" 13#include "common/scope_exit.h"
16#include "common/settings.h" 14#include "common/settings.h"
17#include "core/core.h"
18#include "video_core/engines/kepler_compute.h" 15#include "video_core/engines/kepler_compute.h"
19#include "video_core/engines/maxwell_3d.h" 16#include "video_core/engines/maxwell_3d.h"
20#include "video_core/renderer_vulkan/blit_image.h" 17#include "video_core/renderer_vulkan/blit_image.h"
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 5af2e275b..c25036fb3 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -5,10 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <bitset>
9#include <memory>
10#include <utility>
11#include <vector>
12 8
13#include <boost/container/static_vector.hpp> 9#include <boost/container/static_vector.hpp>
14 10
@@ -17,14 +13,12 @@
17#include "video_core/rasterizer_accelerated.h" 13#include "video_core/rasterizer_accelerated.h"
18#include "video_core/rasterizer_interface.h" 14#include "video_core/rasterizer_interface.h"
19#include "video_core/renderer_vulkan/blit_image.h" 15#include "video_core/renderer_vulkan/blit_image.h"
20#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
21#include "video_core/renderer_vulkan/vk_buffer_cache.h" 16#include "video_core/renderer_vulkan/vk_buffer_cache.h"
22#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 17#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
23#include "video_core/renderer_vulkan/vk_fence_manager.h" 18#include "video_core/renderer_vulkan/vk_fence_manager.h"
24#include "video_core/renderer_vulkan/vk_pipeline_cache.h" 19#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
25#include "video_core/renderer_vulkan/vk_query_cache.h" 20#include "video_core/renderer_vulkan/vk_query_cache.h"
26#include "video_core/renderer_vulkan/vk_render_pass_cache.h" 21#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
27#include "video_core/renderer_vulkan/vk_scheduler.h"
28#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 22#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
29#include "video_core/renderer_vulkan/vk_texture_cache.h" 23#include "video_core/renderer_vulkan/vk_texture_cache.h"
30#include "video_core/renderer_vulkan/vk_update_descriptor.h" 24#include "video_core/renderer_vulkan/vk_update_descriptor.h"
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index 7d9d4f7ba..ad320991b 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -4,7 +4,6 @@
4 4
5#include <memory> 5#include <memory>
6#include <mutex> 6#include <mutex>
7#include <optional>
8#include <thread> 7#include <thread>
9#include <utility> 8#include <utility>
10 9
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index e69aa136b..25c5e6ca1 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
8#include <condition_variable> 7#include <condition_variable>
9#include <cstddef> 8#include <cstddef>
10#include <memory> 9#include <memory>
diff --git a/src/video_core/renderer_vulkan/vk_shader_util.cpp b/src/video_core/renderer_vulkan/vk_shader_util.cpp
index aaad4f292..e8e339f3c 100644
--- a/src/video_core/renderer_vulkan/vk_shader_util.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_util.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6#include <memory>
7 6
8#include "common/assert.h"
9#include "common/common_types.h" 7#include "common/common_types.h"
10#include "video_core/renderer_vulkan/vk_shader_util.h" 8#include "video_core/renderer_vulkan/vk_shader_util.h"
11#include "video_core/vulkan_common/vulkan_device.h" 9#include "video_core/vulkan_common/vulkan_device.h"
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 5d5329abf..64a58304b 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -118,7 +118,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
118 .image = nullptr, 118 .image = nullptr,
119 .buffer = *stream_buffer, 119 .buffer = *stream_buffer,
120 }; 120 };
121 const auto memory_properties = device.GetPhysical().GetMemoryProperties(); 121 const auto memory_properties = device.GetPhysical().GetMemoryProperties().memoryProperties;
122 VkMemoryAllocateInfo stream_memory_info{ 122 VkMemoryAllocateInfo stream_memory_info{
123 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 123 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
124 .pNext = make_dedicated ? &dedicated_info : nullptr, 124 .pNext = make_dedicated ? &dedicated_info : nullptr,
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index c00913f55..1e597f98c 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <array> 6#include <array>
7#include <cstddef> 7#include <cstddef>
8#include <iterator>
9 8
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "core/core.h" 10#include "core/core.h"
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 8972a6921..ce744f4ca 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -7,11 +7,9 @@
7#include <limits> 7#include <limits>
8#include <vector> 8#include <vector>
9 9
10#include "common/assert.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/settings.h" 11#include "common/settings.h"
13#include "core/core.h" 12#include "core/core.h"
14#include "core/frontend/framebuffer_layout.h"
15#include "video_core/renderer_vulkan/vk_scheduler.h" 13#include "video_core/renderer_vulkan/vk_scheduler.h"
16#include "video_core/renderer_vulkan/vk_swapchain.h" 14#include "video_core/renderer_vulkan/vk_swapchain.h"
17#include "video_core/vulkan_common/vulkan_device.h" 15#include "video_core/vulkan_common/vulkan_device.h"
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 83a23b66a..2c2ccc7c6 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1189,6 +1189,14 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
1189 return device.GetDeviceLocalMemory(); 1189 return device.GetDeviceLocalMemory();
1190} 1190}
1191 1191
1192u64 TextureCacheRuntime::GetDeviceMemoryUsage() const {
1193 return device.GetDeviceMemoryUsage();
1194}
1195
1196bool TextureCacheRuntime::CanReportMemoryUsage() const {
1197 return device.CanReportMemoryUsage();
1198}
1199
1192void TextureCacheRuntime::TickFrame() {} 1200void TextureCacheRuntime::TickFrame() {}
1193 1201
1194Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_, 1202Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_,
@@ -1203,6 +1211,7 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
1203 } else { 1211 } else {
1204 flags |= VideoCommon::ImageFlagBits::Converted; 1212 flags |= VideoCommon::ImageFlagBits::Converted;
1205 } 1213 }
1214 flags |= VideoCommon::ImageFlagBits::CostlyLoad;
1206 } 1215 }
1207 if (runtime->device.HasDebuggingToolAttached()) { 1216 if (runtime->device.HasDebuggingToolAttached()) {
1208 original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); 1217 original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
@@ -1442,8 +1451,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
1442 1451
1443 runtime->blit_image_helper.BlitColor(blit_framebuffer.get(), color_view, dst_region, 1452 runtime->blit_image_helper.BlitColor(blit_framebuffer.get(), color_view, dst_region,
1444 src_region, operation, BLIT_OPERATION); 1453 src_region, operation, BLIT_OPERATION);
1445 } else if (!runtime->device.IsBlitDepthStencilSupported() && 1454 } else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1446 aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1447 if (!blit_framebuffer) { 1455 if (!blit_framebuffer) {
1448 blit_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent); 1456 blit_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent);
1449 } 1457 }
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index c81130dd2..cb15b4a1c 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -55,6 +55,10 @@ public:
55 55
56 u64 GetDeviceLocalMemory() const; 56 u64 GetDeviceLocalMemory() const;
57 57
58 u64 GetDeviceMemoryUsage() const;
59
60 bool CanReportMemoryUsage() const;
61
58 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 62 void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
59 const Region2D& dst_region, const Region2D& src_region, 63 const Region2D& dst_region, const Region2D& src_region,
60 Tegra::Engines::Fermi2D::Filter filter, 64 Tegra::Engines::Fermi2D::Filter filter,
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
index 0df3a7fe9..89f1b508d 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
@@ -5,7 +5,6 @@
5#include <variant> 5#include <variant>
6#include <boost/container/static_vector.hpp> 6#include <boost/container/static_vector.hpp>
7 7
8#include "common/assert.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "video_core/renderer_vulkan/vk_scheduler.h" 9#include "video_core/renderer_vulkan/vk_scheduler.h"
11#include "video_core/renderer_vulkan/vk_update_descriptor.h" 10#include "video_core/renderer_vulkan/vk_update_descriptor.h"
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h
index d7de4c490..971a4eb34 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.h
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8 8
9#include "common/common_types.h"
10#include "video_core/vulkan_common/vulkan_wrapper.h" 9#include "video_core/vulkan_common/vulkan_wrapper.h"
11 10
12namespace Vulkan { 11namespace Vulkan {
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 3e673c437..3c22124c4 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <bit>
7#include <filesystem> 6#include <filesystem>
8#include <fstream> 7#include <fstream>
9#include <memory> 8#include <memory>
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp
index bcaf5f575..ce8925896 100644
--- a/src/video_core/shader_notify.cpp
+++ b/src/video_core/shader_notify.cpp
@@ -4,7 +4,6 @@
4 4
5#include <atomic> 5#include <atomic>
6#include <chrono> 6#include <chrono>
7#include <optional>
8 7
9#include "video_core/shader_notify.h" 8#include "video_core/shader_notify.h"
10 9
diff --git a/src/video_core/shader_notify.h b/src/video_core/shader_notify.h
index 4d8d52071..538cda28a 100644
--- a/src/video_core/shader_notify.h
+++ b/src/video_core/shader_notify.h
@@ -6,7 +6,6 @@
6 6
7#include <atomic> 7#include <atomic>
8#include <chrono> 8#include <chrono>
9#include <optional>
10 9
11namespace VideoCore { 10namespace VideoCore {
12class ShaderNotify { 11class ShaderNotify {
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index a36015c8c..5f428d35d 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -190,13 +190,13 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
190 } 190 }
191} 191}
192 192
193PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { 193PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) {
194 switch (format) { 194 switch (format) {
195 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM: 195 case Service::android::PixelFormat::Rgba8888:
196 return PixelFormat::A8B8G8R8_UNORM; 196 return PixelFormat::A8B8G8R8_UNORM;
197 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM: 197 case Service::android::PixelFormat::Rgb565:
198 return PixelFormat::R5G6B5_UNORM; 198 return PixelFormat::R5G6B5_UNORM;
199 case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM: 199 case Service::android::PixelFormat::Bgra8888:
200 return PixelFormat::B8G8R8A8_UNORM; 200 return PixelFormat::B8G8R8A8_UNORM;
201 default: 201 default:
202 UNIMPLEMENTED_MSG("Unimplemented format={}", format); 202 UNIMPLEMENTED_MSG("Unimplemented format={}", format);
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 33e8d24ab..5704cf16a 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -460,7 +460,7 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format);
460 460
461PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format); 461PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format);
462 462
463PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format); 463PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format);
464 464
465SurfaceType GetFormatType(PixelFormat pixel_format); 465SurfaceType GetFormatType(PixelFormat pixel_format);
466 466
diff --git a/src/video_core/texture_cache/descriptor_table.h b/src/video_core/texture_cache/descriptor_table.h
index 3a03b786f..318bd5214 100644
--- a/src/video_core/texture_cache/descriptor_table.h
+++ b/src/video_core/texture_cache/descriptor_table.h
@@ -9,7 +9,6 @@
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/div_ceil.h" 11#include "common/div_ceil.h"
12#include "common/logging/log.h"
13#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
14#include "video_core/rasterizer_interface.h" 13#include "video_core/rasterizer_interface.h"
15 14
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index 89c111c00..dd0106432 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -33,11 +33,12 @@ enum class ImageFlagBits : u32 {
33 ///< garbage collection priority 33 ///< garbage collection priority
34 Alias = 1 << 11, ///< This image has aliases and has priority on garbage 34 Alias = 1 << 11, ///< This image has aliases and has priority on garbage
35 ///< collection 35 ///< collection
36 CostlyLoad = 1 << 12, ///< Protected from low-tier GC as it is costly to load back.
36 37
37 // Rescaler 38 // Rescaler
38 Rescaled = 1 << 12, 39 Rescaled = 1 << 13,
39 CheckingRescalable = 1 << 13, 40 CheckingRescalable = 1 << 14,
40 IsRescalable = 1 << 14, 41 IsRescalable = 1 << 15,
41}; 42};
42DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) 43DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
43 44
diff --git a/src/video_core/texture_cache/render_targets.h b/src/video_core/texture_cache/render_targets.h
index 0cb227d69..f8f13e84c 100644
--- a/src/video_core/texture_cache/render_targets.h
+++ b/src/video_core/texture_cache/render_targets.h
@@ -6,7 +6,6 @@
6 6
7#include <algorithm> 7#include <algorithm>
8#include <span> 8#include <span>
9#include <utility>
10 9
11#include "common/bit_cast.h" 10#include "common/bit_cast.h"
12#include "video_core/texture_cache/types.h" 11#include "video_core/texture_cache/types.h"
diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h
index 50df06409..6aabaef7b 100644
--- a/src/video_core/texture_cache/slot_vector.h
+++ b/src/video_core/texture_cache/slot_vector.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <array>
9#include <bit> 8#include <bit>
10#include <concepts>
11#include <numeric> 9#include <numeric>
12#include <type_traits> 10#include <type_traits>
13#include <utility> 11#include <utility>
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 72eeb8bbd..efc1c4525 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -50,14 +50,20 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
50 void(slot_samplers.insert(runtime, sampler_descriptor)); 50 void(slot_samplers.insert(runtime, sampler_descriptor));
51 51
52 if constexpr (HAS_DEVICE_MEMORY_INFO) { 52 if constexpr (HAS_DEVICE_MEMORY_INFO) {
53 const auto device_memory = runtime.GetDeviceLocalMemory(); 53 const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory());
54 const u64 possible_expected_memory = (device_memory * 4) / 10; 54 const s64 min_spacing_expected = device_memory - 1_GiB - 512_MiB;
55 const u64 possible_critical_memory = (device_memory * 7) / 10; 55 const s64 min_spacing_critical = device_memory - 1_GiB;
56 expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY - 256_MiB); 56 const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD);
57 critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY - 512_MiB); 57 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
58 minimum_memory = 0; 58 const s64 min_vacancy_critical = (3 * mem_threshold) / 10;
59 expected_memory = static_cast<u64>(
60 std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected),
61 DEFAULT_EXPECTED_MEMORY));
62 critical_memory = static_cast<u64>(
63 std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical),
64 DEFAULT_CRITICAL_MEMORY));
65 minimum_memory = static_cast<u64>((device_memory - mem_threshold) / 2);
59 } else { 66 } else {
60 // On OpenGL we can be more conservatives as the driver takes care.
61 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; 67 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
62 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; 68 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
63 minimum_memory = 0; 69 minimum_memory = 0;
@@ -66,18 +72,21 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
66 72
67template <class P> 73template <class P>
68void TextureCache<P>::RunGarbageCollector() { 74void TextureCache<P>::RunGarbageCollector() {
69 const bool high_priority_mode = total_used_memory >= expected_memory; 75 bool high_priority_mode = total_used_memory >= expected_memory;
70 const bool aggressive_mode = total_used_memory >= critical_memory; 76 bool aggressive_mode = total_used_memory >= critical_memory;
71 const u64 ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 100ULL; 77 const u64 ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
72 size_t num_iterations = aggressive_mode ? 300 : (high_priority_mode ? 50 : 10); 78 size_t num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
73 const auto clean_up = [this, &num_iterations, high_priority_mode](ImageId image_id) { 79 const auto clean_up = [this, &num_iterations, &high_priority_mode,
80 &aggressive_mode](ImageId image_id) {
74 if (num_iterations == 0) { 81 if (num_iterations == 0) {
75 return true; 82 return true;
76 } 83 }
77 --num_iterations; 84 --num_iterations;
78 auto& image = slot_images[image_id]; 85 auto& image = slot_images[image_id];
79 const bool must_download = image.IsSafeDownload(); 86 const bool must_download =
80 if (!high_priority_mode && must_download) { 87 image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
88 if (!high_priority_mode &&
89 (must_download || True(image.flags & ImageFlagBits::CostlyLoad))) {
81 return false; 90 return false;
82 } 91 }
83 if (must_download) { 92 if (must_download) {
@@ -92,6 +101,18 @@ void TextureCache<P>::RunGarbageCollector() {
92 } 101 }
93 UnregisterImage(image_id); 102 UnregisterImage(image_id);
94 DeleteImage(image_id, image.scale_tick > frame_tick + 5); 103 DeleteImage(image_id, image.scale_tick > frame_tick + 5);
104 if (total_used_memory < critical_memory) {
105 if (aggressive_mode) {
106 // Sink the aggresiveness.
107 num_iterations >>= 2;
108 aggressive_mode = false;
109 return false;
110 }
111 if (high_priority_mode && total_used_memory < expected_memory) {
112 num_iterations >>= 1;
113 high_priority_mode = false;
114 }
115 }
95 return false; 116 return false;
96 }; 117 };
97 lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up); 118 lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up);
@@ -99,6 +120,10 @@ void TextureCache<P>::RunGarbageCollector() {
99 120
100template <class P> 121template <class P>
101void TextureCache<P>::TickFrame() { 122void TextureCache<P>::TickFrame() {
123 // If we can obtain the memory info, use it instead of the estimate.
124 if (runtime.CanReportMemoryUsage()) {
125 total_used_memory = runtime.GetDeviceMemoryUsage();
126 }
102 if (total_used_memory > minimum_memory) { 127 if (total_used_memory > minimum_memory) {
103 RunGarbageCollector(); 128 RunGarbageCollector();
104 } 129 }
@@ -106,6 +131,7 @@ void TextureCache<P>::TickFrame() {
106 sentenced_framebuffers.Tick(); 131 sentenced_framebuffers.Tick();
107 sentenced_image_view.Tick(); 132 sentenced_image_view.Tick();
108 runtime.TickFrame(); 133 runtime.TickFrame();
134 critical_gc = 0;
109 ++frame_tick; 135 ++frame_tick;
110} 136}
111 137
@@ -1052,6 +1078,11 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
1052 1078
1053 for (const ImageId overlap_id : overlap_ids) { 1079 for (const ImageId overlap_id : overlap_ids) {
1054 Image& overlap = slot_images[overlap_id]; 1080 Image& overlap = slot_images[overlap_id];
1081 if (True(overlap.flags & ImageFlagBits::GpuModified)) {
1082 new_image.flags |= ImageFlagBits::GpuModified;
1083 new_image.modification_tick =
1084 std::max(overlap.modification_tick, new_image.modification_tick);
1085 }
1055 if (overlap.info.num_samples != new_image.info.num_samples) { 1086 if (overlap.info.num_samples != new_image.info.num_samples) {
1056 LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented"); 1087 LOG_WARNING(HW_GPU, "Copying between images with different samples is not implemented");
1057 } else { 1088 } else {
@@ -1414,6 +1445,10 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
1414 tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); 1445 tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format);
1415 } 1446 }
1416 total_used_memory += Common::AlignUp(tentative_size, 1024); 1447 total_used_memory += Common::AlignUp(tentative_size, 1024);
1448 if (total_used_memory > critical_memory && critical_gc < GC_EMERGENCY_COUNTS) {
1449 RunGarbageCollector();
1450 critical_gc++;
1451 }
1417 image.lru_index = lru_cache.Insert(image_id, frame_tick); 1452 image.lru_index = lru_cache.Insert(image_id, frame_tick);
1418 1453
1419 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, 1454 ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
@@ -1704,6 +1739,9 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
1704 most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); 1739 most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick);
1705 aliased_images.push_back(&aliased); 1740 aliased_images.push_back(&aliased);
1706 any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled); 1741 any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled);
1742 if (True(aliased_image.flags & ImageFlagBits::GpuModified)) {
1743 image.flags |= ImageFlagBits::GpuModified;
1744 }
1707 } 1745 }
1708 } 1746 }
1709 if (aliased_images.empty()) { 1747 if (aliased_images.empty()) {
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 7107887a6..b1324edf3 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -22,7 +22,6 @@
22#include "video_core/texture_cache/image_base.h" 22#include "video_core/texture_cache/image_base.h"
23#include "video_core/texture_cache/image_info.h" 23#include "video_core/texture_cache/image_info.h"
24#include "video_core/texture_cache/image_view_base.h" 24#include "video_core/texture_cache/image_view_base.h"
25#include "video_core/texture_cache/image_view_info.h"
26#include "video_core/texture_cache/render_targets.h" 25#include "video_core/texture_cache/render_targets.h"
27#include "video_core/texture_cache/slot_vector.h" 26#include "video_core/texture_cache/slot_vector.h"
28#include "video_core/texture_cache/types.h" 27#include "video_core/texture_cache/types.h"
@@ -60,8 +59,10 @@ class TextureCache {
60 /// True when the API can provide info about the memory of the device. 59 /// True when the API can provide info about the memory of the device.
61 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; 60 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
62 61
63 static constexpr u64 DEFAULT_EXPECTED_MEMORY = 1_GiB; 62 static constexpr s64 TARGET_THRESHOLD = 4_GiB;
64 static constexpr u64 DEFAULT_CRITICAL_MEMORY = 2_GiB; 63 static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB;
64 static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB;
65 static constexpr size_t GC_EMERGENCY_COUNTS = 2;
65 66
66 using Runtime = typename P::Runtime; 67 using Runtime = typename P::Runtime;
67 using Image = typename P::Image; 68 using Image = typename P::Image;
@@ -373,6 +374,7 @@ private:
373 u64 minimum_memory; 374 u64 minimum_memory;
374 u64 expected_memory; 375 u64 expected_memory;
375 u64 critical_memory; 376 u64 critical_memory;
377 size_t critical_gc;
376 378
377 SlotVector<Image> slot_images; 379 SlotVector<Image> slot_images;
378 SlotVector<ImageMapView> slot_map_views; 380 SlotVector<ImageMapView> slot_map_views;
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index 7af52de2e..f13669ea5 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -9,10 +9,8 @@
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
12#include "video_core/engines/maxwell_3d.h"
13#include "video_core/surface.h" 12#include "video_core/surface.h"
14#include "video_core/texture_cache/image_base.h" 13#include "video_core/texture_cache/image_base.h"
15#include "video_core/texture_cache/image_view_base.h"
16#include "video_core/texture_cache/types.h" 14#include "video_core/texture_cache/types.h"
17#include "video_core/textures/texture.h" 15#include "video_core/textures/texture.h"
18 16
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index 25161df1f..28e4beafd 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -16,6 +16,7 @@
16// <http://gamma.cs.unc.edu/FasTC/> 16// <http://gamma.cs.unc.edu/FasTC/>
17 17
18#include <algorithm> 18#include <algorithm>
19#include <bit>
19#include <cassert> 20#include <cassert>
20#include <cstring> 21#include <cstring>
21#include <span> 22#include <span>
diff --git a/src/video_core/textures/astc.h b/src/video_core/textures/astc.h
index 14d2beec0..564ae1e36 100644
--- a/src/video_core/textures/astc.h
+++ b/src/video_core/textures/astc.h
@@ -4,9 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <bit>
8#include "common/common_types.h"
9
10namespace Tegra::Texture::ASTC { 7namespace Tegra::Texture::ASTC {
11 8
12void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth, 9void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 24e943e4c..6dae23049 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -6,7 +6,6 @@
6#include <cmath> 6#include <cmath>
7#include <cstring> 7#include <cstring>
8#include <span> 8#include <span>
9#include <utility>
10 9
11#include "common/alignment.h" 10#include "common/alignment.h"
12#include "common/assert.h" 11#include "common/assert.h"
@@ -14,7 +13,6 @@
14#include "common/div_ceil.h" 13#include "common/div_ceil.h"
15#include "video_core/gpu.h" 14#include "video_core/gpu.h"
16#include "video_core/textures/decoders.h" 15#include "video_core/textures/decoders.h"
17#include "video_core/textures/texture.h"
18 16
19namespace Tegra::Texture { 17namespace Tegra::Texture {
20namespace { 18namespace {
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp
index 06954963d..f56b4b9f9 100644
--- a/src/video_core/textures/texture.cpp
+++ b/src/video_core/textures/texture.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <array> 5#include <array>
7 6
8#include "common/cityhash.h" 7#include "common/cityhash.h"
diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.h b/src/video_core/vulkan_common/nsight_aftermath_tracker.h
index eae1891dd..55c115081 100644
--- a/src/video_core/vulkan_common/nsight_aftermath_tracker.h
+++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.h
@@ -4,20 +4,22 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <filesystem>
8#include <mutex>
9#include <span> 7#include <span>
10#include <string>
11#include <vector>
12 8
13#include "common/common_types.h" 9#include "common/common_types.h"
14#include "common/dynamic_library.h"
15#include "video_core/vulkan_common/vulkan_wrapper.h"
16 10
17#ifdef HAS_NSIGHT_AFTERMATH 11#ifdef HAS_NSIGHT_AFTERMATH
12#include <filesystem>
13#include <mutex>
14
15// Vulkan headers must be included before Aftermath
16#include "video_core/vulkan_common/vulkan_wrapper.h"
17
18#include <GFSDK_Aftermath_Defines.h> 18#include <GFSDK_Aftermath_Defines.h>
19#include <GFSDK_Aftermath_GpuCrashDump.h> 19#include <GFSDK_Aftermath_GpuCrashDump.h>
20#include <GFSDK_Aftermath_GpuCrashDumpDecoding.h> 20#include <GFSDK_Aftermath_GpuCrashDumpDecoding.h>
21
22#include "common/dynamic_library.h"
21#endif 23#endif
22 24
23namespace Vulkan { 25namespace Vulkan {
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index effde73c9..4a5de9ddf 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -6,19 +6,20 @@
6#include <bitset> 6#include <bitset>
7#include <chrono> 7#include <chrono>
8#include <optional> 8#include <optional>
9#include <string_view>
10#include <thread> 9#include <thread>
11#include <unordered_set> 10#include <unordered_set>
12#include <utility> 11#include <utility>
13#include <vector> 12#include <vector>
14 13
15#include "common/assert.h" 14#include "common/assert.h"
15#include "common/literals.h"
16#include "common/settings.h" 16#include "common/settings.h"
17#include "video_core/vulkan_common/nsight_aftermath_tracker.h" 17#include "video_core/vulkan_common/nsight_aftermath_tracker.h"
18#include "video_core/vulkan_common/vulkan_device.h" 18#include "video_core/vulkan_common/vulkan_device.h"
19#include "video_core/vulkan_common/vulkan_wrapper.h" 19#include "video_core/vulkan_common/vulkan_wrapper.h"
20 20
21namespace Vulkan { 21namespace Vulkan {
22using namespace Common::Literals;
22namespace { 23namespace {
23namespace Alternatives { 24namespace Alternatives {
24constexpr std::array STENCIL8_UINT{ 25constexpr std::array STENCIL8_UINT{
@@ -597,6 +598,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
597 } 598 }
598 logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld); 599 logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld);
599 600
601 is_integrated = properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
602 is_virtual = properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU;
603 is_non_gpu = properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_OTHER ||
604 properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU;
605
600 CollectPhysicalMemoryInfo(); 606 CollectPhysicalMemoryInfo();
601 CollectTelemetryParameters(); 607 CollectTelemetryParameters();
602 CollectToolingInfo(); 608 CollectToolingInfo();
@@ -615,6 +621,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
615 khr_push_descriptor = false; 621 khr_push_descriptor = false;
616 break; 622 break;
617 } 623 }
624 const u32 nv_major_version = (properties.driverVersion >> 22) & 0x3ff;
625 if (nv_major_version >= 510) {
626 LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits");
627 cant_blit_msaa = true;
628 }
618 } 629 }
619 const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV; 630 const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV;
620 if (ext_extended_dynamic_state && is_radv) { 631 if (ext_extended_dynamic_state && is_radv) {
@@ -986,6 +997,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
986 test(has_khr_swapchain_mutable_format, VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME, 997 test(has_khr_swapchain_mutable_format, VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME,
987 false); 998 false);
988 test(has_ext_line_rasterization, VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, false); 999 test(has_ext_line_rasterization, VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, false);
1000 test(ext_memory_budget, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, true);
989 if (Settings::values.enable_nsight_aftermath) { 1001 if (Settings::values.enable_nsight_aftermath) {
990 test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME, 1002 test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
991 true); 1003 true);
@@ -998,7 +1010,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
998 VkPhysicalDeviceFeatures2KHR features{}; 1010 VkPhysicalDeviceFeatures2KHR features{};
999 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; 1011 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
1000 1012
1001 VkPhysicalDeviceProperties2KHR physical_properties; 1013 VkPhysicalDeviceProperties2KHR physical_properties{};
1002 physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; 1014 physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
1003 1015
1004 if (has_khr_shader_float16_int8) { 1016 if (has_khr_shader_float16_int8) {
@@ -1268,15 +1280,50 @@ void Device::CollectTelemetryParameters() {
1268 vendor_name = driver.driverName; 1280 vendor_name = driver.driverName;
1269} 1281}
1270 1282
1283u64 Device::GetDeviceMemoryUsage() const {
1284 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget;
1285 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1286 budget.pNext = nullptr;
1287 physical.GetMemoryProperties(&budget);
1288 u64 result{};
1289 for (const size_t heap : valid_heap_memory) {
1290 result += budget.heapUsage[heap];
1291 }
1292 return result;
1293}
1294
1271void Device::CollectPhysicalMemoryInfo() { 1295void Device::CollectPhysicalMemoryInfo() {
1272 const auto mem_properties = physical.GetMemoryProperties(); 1296 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{};
1297 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1298 const auto mem_info = physical.GetMemoryProperties(ext_memory_budget ? &budget : nullptr);
1299 const auto& mem_properties = mem_info.memoryProperties;
1273 const size_t num_properties = mem_properties.memoryHeapCount; 1300 const size_t num_properties = mem_properties.memoryHeapCount;
1274 device_access_memory = 0; 1301 device_access_memory = 0;
1302 u64 device_initial_usage = 0;
1303 u64 local_memory = 0;
1275 for (size_t element = 0; element < num_properties; ++element) { 1304 for (size_t element = 0; element < num_properties; ++element) {
1276 if ((mem_properties.memoryHeaps[element].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0) { 1305 const bool is_heap_local =
1277 device_access_memory += mem_properties.memoryHeaps[element].size; 1306 (mem_properties.memoryHeaps[element].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
1307 if (!is_integrated && !is_heap_local) {
1308 continue;
1278 } 1309 }
1310 valid_heap_memory.push_back(element);
1311 if (is_heap_local) {
1312 local_memory += mem_properties.memoryHeaps[element].size;
1313 }
1314 if (ext_memory_budget) {
1315 device_initial_usage += budget.heapUsage[element];
1316 device_access_memory += budget.heapBudget[element];
1317 continue;
1318 }
1319 device_access_memory += mem_properties.memoryHeaps[element].size;
1320 }
1321 if (!is_integrated) {
1322 return;
1279 } 1323 }
1324 const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);
1325 device_access_memory = static_cast<u64>(std::max<s64>(
1326 std::min<s64>(available_memory - 8_GiB, 4_GiB), static_cast<s64>(local_memory)));
1280} 1327}
1281 1328
1282void Device::CollectToolingInfo() { 1329void Device::CollectToolingInfo() {
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 34b1add16..2d709d069 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -6,7 +6,6 @@
6 6
7#include <span> 7#include <span>
8#include <string> 8#include <string>
9#include <string_view>
10#include <unordered_map> 9#include <unordered_map>
11#include <vector> 10#include <vector>
12 11
@@ -342,6 +341,12 @@ public:
342 return device_access_memory; 341 return device_access_memory;
343 } 342 }
344 343
344 bool CanReportMemoryUsage() const {
345 return ext_memory_budget;
346 }
347
348 u64 GetDeviceMemoryUsage() const;
349
345 u32 GetSetsPerPool() const { 350 u32 GetSetsPerPool() const {
346 return sets_per_pool; 351 return sets_per_pool;
347 } 352 }
@@ -422,6 +427,9 @@ private:
422 bool is_topology_list_restart_supported{}; ///< Support for primitive restart with list 427 bool is_topology_list_restart_supported{}; ///< Support for primitive restart with list
423 ///< topologies. 428 ///< topologies.
424 bool is_patch_list_restart_supported{}; ///< Support for primitive restart with list patch. 429 bool is_patch_list_restart_supported{}; ///< Support for primitive restart with list patch.
430 bool is_integrated{}; ///< Is GPU an iGPU.
431 bool is_virtual{}; ///< Is GPU a virtual GPU.
432 bool is_non_gpu{}; ///< Is SoftwareRasterizer, FPGA, non-GPU device.
425 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. 433 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
426 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. 434 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2.
427 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough. 435 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough.
@@ -446,6 +454,7 @@ private:
446 bool ext_shader_atomic_int64{}; ///< Support for VK_KHR_shader_atomic_int64. 454 bool ext_shader_atomic_int64{}; ///< Support for VK_KHR_shader_atomic_int64.
447 bool ext_conservative_rasterization{}; ///< Support for VK_EXT_conservative_rasterization. 455 bool ext_conservative_rasterization{}; ///< Support for VK_EXT_conservative_rasterization.
448 bool ext_provoking_vertex{}; ///< Support for VK_EXT_provoking_vertex. 456 bool ext_provoking_vertex{}; ///< Support for VK_EXT_provoking_vertex.
457 bool ext_memory_budget{}; ///< Support for VK_EXT_memory_budget.
449 bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config. 458 bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
450 bool has_broken_cube_compatibility{}; ///< Has broken cube compatiblity bit 459 bool has_broken_cube_compatibility{}; ///< Has broken cube compatiblity bit
451 bool has_renderdoc{}; ///< Has RenderDoc attached 460 bool has_renderdoc{}; ///< Has RenderDoc attached
@@ -457,6 +466,7 @@ private:
457 // Telemetry parameters 466 // Telemetry parameters
458 std::string vendor_name; ///< Device's driver name. 467 std::string vendor_name; ///< Device's driver name.
459 std::vector<std::string> supported_extensions; ///< Reported Vulkan extensions. 468 std::vector<std::string> supported_extensions; ///< Reported Vulkan extensions.
469 std::vector<size_t> valid_heap_memory; ///< Heaps used.
460 470
461 /// Format properties dictionary. 471 /// Format properties dictionary.
462 std::unordered_map<VkFormat, VkFormatProperties> format_properties; 472 std::unordered_map<VkFormat, VkFormatProperties> format_properties;
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp
index bfd6e6add..662694f16 100644
--- a/src/video_core/vulkan_common/vulkan_instance.cpp
+++ b/src/video_core/vulkan_common/vulkan_instance.cpp
@@ -2,11 +2,9 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <future> 5#include <future>
7#include <optional> 6#include <optional>
8#include <span> 7#include <span>
9#include <utility>
10#include <vector> 8#include <vector>
11 9
12#include "common/common_types.h" 10#include "common/common_types.h"
diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp
index 22833fa56..d69de05ef 100644
--- a/src/video_core/vulkan_common/vulkan_library.cpp
+++ b/src/video_core/vulkan_common/vulkan_library.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstdlib>
6#include <string> 5#include <string>
7 6
8#include "common/dynamic_library.h" 7#include "common/dynamic_library.h"
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index 300a61205..e6e97b332 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -227,7 +227,7 @@ void MemoryCommit::Release() {
227} 227}
228 228
229MemoryAllocator::MemoryAllocator(const Device& device_, bool export_allocations_) 229MemoryAllocator::MemoryAllocator(const Device& device_, bool export_allocations_)
230 : device{device_}, properties{device_.GetPhysical().GetMemoryProperties()}, 230 : device{device_}, properties{device_.GetPhysical().GetMemoryProperties().memoryProperties},
231 export_allocations{export_allocations_}, 231 export_allocations{export_allocations_},
232 buffer_image_granularity{ 232 buffer_image_granularity{
233 device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} 233 device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {}
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h
index 86e8ed119..338daf5ba 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.h
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <span> 8#include <span>
9#include <utility>
10#include <vector> 9#include <vector>
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "video_core/vulkan_common/vulkan_wrapper.h" 11#include "video_core/vulkan_common/vulkan_wrapper.h"
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index a9faa4807..742cc39da 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -3,10 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <exception>
7#include <memory> 6#include <memory>
8#include <optional> 7#include <optional>
9#include <string_view>
10#include <utility> 8#include <utility>
11#include <vector> 9#include <vector>
12 10
@@ -239,8 +237,8 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
239 return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) && 237 return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) &&
240 X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) && 238 X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) &&
241 X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) && 239 X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) &&
242 X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceProperties) && 240 X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceMemoryProperties2) &&
243 X(vkGetPhysicalDeviceQueueFamilyProperties); 241 X(vkGetPhysicalDeviceProperties) && X(vkGetPhysicalDeviceQueueFamilyProperties);
244#undef X 242#undef X
245} 243}
246 244
@@ -928,9 +926,12 @@ std::vector<VkPresentModeKHR> PhysicalDevice::GetSurfacePresentModesKHR(
928 return modes; 926 return modes;
929} 927}
930 928
931VkPhysicalDeviceMemoryProperties PhysicalDevice::GetMemoryProperties() const noexcept { 929VkPhysicalDeviceMemoryProperties2 PhysicalDevice::GetMemoryProperties(
932 VkPhysicalDeviceMemoryProperties properties; 930 void* next_structures) const noexcept {
933 dld->vkGetPhysicalDeviceMemoryProperties(physical_device, &properties); 931 VkPhysicalDeviceMemoryProperties2 properties{};
932 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
933 properties.pNext = next_structures;
934 dld->vkGetPhysicalDeviceMemoryProperties2(physical_device, &properties);
934 return properties; 935 return properties;
935} 936}
936 937
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index b7ae01c6c..0a5f9931c 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <exception> 7#include <exception>
8#include <iterator>
9#include <limits> 8#include <limits>
10#include <memory> 9#include <memory>
11#include <optional> 10#include <optional>
@@ -173,6 +172,7 @@ struct InstanceDispatch {
173 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR{}; 172 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR{};
174 PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{}; 173 PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{};
175 PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{}; 174 PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{};
175 PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2{};
176 PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{}; 176 PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{};
177 PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR{}; 177 PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR{};
178 PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{}; 178 PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{};
@@ -951,7 +951,8 @@ public:
951 951
952 std::vector<VkPresentModeKHR> GetSurfacePresentModesKHR(VkSurfaceKHR) const; 952 std::vector<VkPresentModeKHR> GetSurfacePresentModesKHR(VkSurfaceKHR) const;
953 953
954 VkPhysicalDeviceMemoryProperties GetMemoryProperties() const noexcept; 954 VkPhysicalDeviceMemoryProperties2 GetMemoryProperties(
955 void* next_structures = nullptr) const noexcept;
955 956
956private: 957private:
957 VkPhysicalDevice physical_device = nullptr; 958 VkPhysicalDevice physical_device = nullptr;
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index b1e02c57a..4208bd044 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <cstdlib>
7#include <mutex> 6#include <mutex>
8#include <string> 7#include <string>
9 8
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 4104928d1..90a27e573 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -6,7 +6,6 @@
6#include <thread> 6#include <thread>
7 7
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/param_package.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11#include "core/core.h" 10#include "core/core.h"
12#include "core/hid/emulated_controller.h" 11#include "core/hid/emulated_controller.h"
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 4cd8f7784..44502883c 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -10,6 +10,7 @@
10#include <QLineEdit> 10#include <QLineEdit>
11#include <QScrollArea> 11#include <QScrollArea>
12#include <QStandardItemModel> 12#include <QStandardItemModel>
13#include <QTreeView>
13#include <QVBoxLayout> 14#include <QVBoxLayout>
14#include "common/fs/path_util.h" 15#include "common/fs/path_util.h"
15#include "common/string_util.h" 16#include "common/string_util.h"
diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h
index 56496ed31..0a9d4f982 100644
--- a/src/yuzu/applets/qt_profile_select.h
+++ b/src/yuzu/applets/qt_profile_select.h
@@ -7,7 +7,6 @@
7#include <vector> 7#include <vector>
8#include <QDialog> 8#include <QDialog>
9#include <QList> 9#include <QList>
10#include <QTreeView>
11#include "core/frontend/applets/profile_select.h" 10#include "core/frontend/applets/profile_select.h"
12#include "core/hle/service/acc/profile_manager.h" 11#include "core/hle/service/acc/profile_manager.h"
13 12
@@ -19,6 +18,7 @@ class QLabel;
19class QScrollArea; 18class QScrollArea;
20class QStandardItem; 19class QStandardItem;
21class QStandardItemModel; 20class QStandardItemModel;
21class QTreeView;
22class QVBoxLayout; 22class QVBoxLayout;
23 23
24namespace Core::HID { 24namespace Core::HID {
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index cb3c5d826..116ef54db 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -11,17 +11,15 @@
11#include <QWebEngineScriptCollection> 11#include <QWebEngineScriptCollection>
12#include <QWebEngineSettings> 12#include <QWebEngineSettings>
13#include <QWebEngineUrlScheme> 13#include <QWebEngineUrlScheme>
14
15#include "core/hid/input_interpreter.h"
16#include "yuzu/applets/qt_web_browser_scripts.h"
14#endif 17#endif
15 18
16#include "common/fs/path_util.h" 19#include "common/fs/path_util.h"
17#include "common/param_package.h"
18#include "core/core.h" 20#include "core/core.h"
19#include "core/hid/hid_types.h"
20#include "core/hid/input_interpreter.h"
21#include "input_common/drivers/keyboard.h" 21#include "input_common/drivers/keyboard.h"
22#include "input_common/main.h"
23#include "yuzu/applets/qt_web_browser.h" 22#include "yuzu/applets/qt_web_browser.h"
24#include "yuzu/applets/qt_web_browser_scripts.h"
25#include "yuzu/main.h" 23#include "yuzu/main.h"
26#include "yuzu/util/url_request_interceptor.h" 24#include "yuzu/util/url_request_interceptor.h"
27 25
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h
index fa18aecac..a47059412 100644
--- a/src/yuzu/applets/qt_web_browser.h
+++ b/src/yuzu/applets/qt_web_browser.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <atomic> 7#include <atomic>
8#include <memory>
9#include <thread> 8#include <thread>
10 9
11#include <QObject> 10#include <QObject>
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 114f17c06..27b0300d2 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -6,7 +6,6 @@
6 6
7#include <QApplication> 7#include <QApplication>
8#include <QHBoxLayout> 8#include <QHBoxLayout>
9#include <QKeyEvent>
10#include <QMessageBox> 9#include <QMessageBox>
11#include <QPainter> 10#include <QPainter>
12#include <QScreen> 11#include <QScreen>
@@ -28,7 +27,6 @@
28#include "common/assert.h" 27#include "common/assert.h"
29#include "common/microprofile.h" 28#include "common/microprofile.h"
30#include "common/scm_rev.h" 29#include "common/scm_rev.h"
31#include "common/scope_exit.h"
32#include "common/settings.h" 30#include "common/settings.h"
33#include "core/core.h" 31#include "core/core.h"
34#include "core/frontend/framebuffer_layout.h" 32#include "core/frontend/framebuffer_layout.h"
@@ -38,7 +36,6 @@
38#include "input_common/drivers/touch_screen.h" 36#include "input_common/drivers/touch_screen.h"
39#include "input_common/main.h" 37#include "input_common/main.h"
40#include "video_core/renderer_base.h" 38#include "video_core/renderer_base.h"
41#include "video_core/video_core.h"
42#include "yuzu/bootmanager.h" 39#include "yuzu/bootmanager.h"
43#include "yuzu/main.h" 40#include "yuzu/main.h"
44 41
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 92297a43b..4b0ce0293 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -13,7 +13,6 @@
13#include <QThread> 13#include <QThread>
14#include <QTouchEvent> 14#include <QTouchEvent>
15#include <QWidget> 15#include <QWidget>
16#include <QWindow>
17 16
18#include "common/thread.h" 17#include "common/thread.h"
19#include "core/frontend/emu_window.h" 18#include "core/frontend/emu_window.h"
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 4b943c6ba..d2e735f48 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -775,6 +775,7 @@ void Config::ReadUIValues() {
775 ReadBasicSetting(UISettings::values.pause_when_in_background); 775 ReadBasicSetting(UISettings::values.pause_when_in_background);
776 ReadBasicSetting(UISettings::values.mute_when_in_background); 776 ReadBasicSetting(UISettings::values.mute_when_in_background);
777 ReadBasicSetting(UISettings::values.hide_mouse); 777 ReadBasicSetting(UISettings::values.hide_mouse);
778 ReadBasicSetting(UISettings::values.disable_web_applet);
778 779
779 qt_config->endGroup(); 780 qt_config->endGroup();
780} 781}
@@ -1308,6 +1309,7 @@ void Config::SaveUIValues() {
1308 WriteBasicSetting(UISettings::values.pause_when_in_background); 1309 WriteBasicSetting(UISettings::values.pause_when_in_background);
1309 WriteBasicSetting(UISettings::values.mute_when_in_background); 1310 WriteBasicSetting(UISettings::values.mute_when_in_background);
1310 WriteBasicSetting(UISettings::values.hide_mouse); 1311 WriteBasicSetting(UISettings::values.hide_mouse);
1312 WriteBasicSetting(UISettings::values.disable_web_applet);
1311 1313
1312 qt_config->endGroup(); 1314 qt_config->endGroup();
1313} 1315}
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 251aab912..5190bd18b 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QCheckBox> 5#include <QCheckBox>
6#include <QComboBox>
7#include <QObject> 6#include <QObject>
8#include <QString> 7#include <QString>
9#include "common/settings.h" 8#include "common/settings.h"
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 5423dbc92..903a9baae 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -6,7 +6,6 @@
6 6
7#include <QCheckBox> 7#include <QCheckBox>
8#include <QComboBox> 8#include <QComboBox>
9#include <QString>
10#include "common/settings.h" 9#include "common/settings.h"
11 10
12namespace ConfigurationShared { 11namespace ConfigurationShared {
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index c33488718..2f9285e77 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -4,8 +4,6 @@
4 4
5#include <memory> 5#include <memory>
6 6
7#include <QSignalBlocker>
8
9#include "audio_core/sink.h" 7#include "audio_core/sink.h"
10#include "audio_core/sink_details.h" 8#include "audio_core/sink_details.h"
11#include "common/settings.h" 9#include "common/settings.h"
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index bf74ccc7c..0de7fbfed 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -2,11 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QComboBox>
6#include <QMessageBox>
7
8#include "common/common_types.h" 5#include "common/common_types.h"
9#include "common/logging/log.h"
10#include "common/settings.h" 6#include "common/settings.h"
11#include "core/core.h" 7#include "core/core.h"
12#include "ui_configure_cpu.h" 8#include "ui_configure_cpu.h"
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index 733e38be4..3209c11d5 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9#include "common/settings.h"
10 9
11namespace Core { 10namespace Core {
12class System; 11class System;
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp
index 616a0be75..087d9496c 100644
--- a/src/yuzu/configuration/configure_cpu_debug.cpp
+++ b/src/yuzu/configuration/configure_cpu_debug.cpp
@@ -2,10 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QComboBox>
6
7#include "common/common_types.h"
8#include "common/logging/log.h"
9#include "common/settings.h" 5#include "common/settings.h"
10#include "core/core.h" 6#include "core/core.h"
11#include "ui_configure_cpu_debug.h" 7#include "ui_configure_cpu_debug.h"
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index c1cf4050c..bd50f7a68 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -59,6 +59,13 @@ void ConfigureDebug::SetConfiguration() {
59 ui->disable_loop_safety_checks->setChecked( 59 ui->disable_loop_safety_checks->setChecked(
60 Settings::values.disable_shader_loop_safety_checks.GetValue()); 60 Settings::values.disable_shader_loop_safety_checks.GetValue());
61 ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); 61 ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue());
62
63#ifdef YUZU_USE_QT_WEB_ENGINE
64 ui->disable_web_applet->setChecked(UISettings::values.disable_web_applet.GetValue());
65#else
66 ui->disable_web_applet->setEnabled(false);
67 ui->disable_web_applet->setText(QString::fromUtf8("Web applet not compiled"));
68#endif
62} 69}
63 70
64void ConfigureDebug::ApplyConfiguration() { 71void ConfigureDebug::ApplyConfiguration() {
@@ -80,6 +87,7 @@ void ConfigureDebug::ApplyConfiguration() {
80 ui->disable_loop_safety_checks->isChecked(); 87 ui->disable_loop_safety_checks->isChecked();
81 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); 88 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
82 Settings::values.extended_logging = ui->extended_logging->isChecked(); 89 Settings::values.extended_logging = ui->extended_logging->isChecked();
90 UISettings::values.disable_web_applet = ui->disable_web_applet->isChecked();
83 Debugger::ToggleConsole(); 91 Debugger::ToggleConsole();
84 Common::Log::Filter filter; 92 Common::Log::Filter filter;
85 filter.ParseFilterString(Settings::values.log_filter.GetValue()); 93 filter.ParseFilterString(Settings::values.log_filter.GetValue());
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 4dd870855..edb525e82 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -8,49 +8,49 @@
8 <property name="title"> 8 <property name="title">
9 <string>Logging</string> 9 <string>Logging</string>
10 </property> 10 </property>
11 <layout class="QGridLayout" name="gridLayout_1"> 11 <layout class="QGridLayout" name="gridLayout_1">
12 <item row="0" column="0" colspan="2"> 12 <item row="0" column="0" colspan="2">
13 <layout class="QHBoxLayout" name="horizontalLayout_1"> 13 <layout class="QHBoxLayout" name="horizontalLayout_1">
14 <item> 14 <item>
15 <widget class="QLabel" name="label_1"> 15 <widget class="QLabel" name="label_1">
16 <property name="text">
17 <string>Global Log Filter</string>
18 </property>
19 </widget>
20 </item>
21 <item>
22 <widget class="QLineEdit" name="log_filter_edit"/>
23 </item>
24 </layout>
25 </item>
26 <item row="1" column="0">
27 <widget class="QCheckBox" name="toggle_console">
28 <property name="text">
29 <string>Show Log in Console</string>
30 </property>
31 </widget>
32 </item>
33 <item row="1" column="1">
34 <widget class="QPushButton" name="open_log_button">
35 <property name="text">
36 <string>Open Log Location</string>
37 </property>
38 </widget>
39 </item>
40 <item row="2" column="0">
41 <widget class="QCheckBox" name="extended_logging">
42 <property name="enabled">
43 <bool>true</bool>
44 </property>
45 <property name="toolTip">
46 <string>When checked, the max size of the log increases from 100 MB to 1 GB</string>
47 </property>
48 <property name="text"> 16 <property name="text">
49 <string>Enable Extended Logging**</string> 17 <string>Global Log Filter</string>
50 </property> 18 </property>
51 </widget> 19 </widget>
52 </item> 20 </item>
53 </layout> 21 <item>
22 <widget class="QLineEdit" name="log_filter_edit"/>
23 </item>
24 </layout>
25 </item>
26 <item row="1" column="0">
27 <widget class="QCheckBox" name="toggle_console">
28 <property name="text">
29 <string>Show Log in Console</string>
30 </property>
31 </widget>
32 </item>
33 <item row="1" column="1">
34 <widget class="QPushButton" name="open_log_button">
35 <property name="text">
36 <string>Open Log Location</string>
37 </property>
38 </widget>
39 </item>
40 <item row="2" column="0">
41 <widget class="QCheckBox" name="extended_logging">
42 <property name="enabled">
43 <bool>true</bool>
44 </property>
45 <property name="toolTip">
46 <string>When checked, the max size of the log increases from 100 MB to 1 GB</string>
47 </property>
48 <property name="text">
49 <string>Enable Extended Logging**</string>
50 </property>
51 </widget>
52 </item>
53 </layout>
54 </widget> 54 </widget>
55 </item> 55 </item>
56 <item> 56 <item>
@@ -183,7 +183,7 @@
183 <string>Advanced</string> 183 <string>Advanced</string>
184 </property> 184 </property>
185 <layout class="QGridLayout" name="gridLayout_4"> 185 <layout class="QGridLayout" name="gridLayout_4">
186 <item> row="0" column="0"> 186 <item row="0" column="0">
187 <widget class="QCheckBox" name="quest_flag"> 187 <widget class="QCheckBox" name="quest_flag">
188 <property name="text"> 188 <property name="text">
189 <string>Kiosk (Quest) Mode</string> 189 <string>Kiosk (Quest) Mode</string>
@@ -218,6 +218,13 @@
218 </property> 218 </property>
219 </widget> 219 </widget>
220 </item> 220 </item>
221 <item row="2" column="1">
222 <widget class="QCheckBox" name="disable_web_applet">
223 <property name="text">
224 <string>Disable Web Applet**</string>
225 </property>
226 </widget>
227 </item>
221 </layout> 228 </layout>
222 </widget> 229 </widget>
223 </item> 230 </item>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 19133ccf5..69458a3ff 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -3,13 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6#include <QAbstractButton>
7#include <QDialogButtonBox>
8#include <QHash>
9#include <QListWidgetItem>
10#include <QPushButton>
11#include <QSignalBlocker>
12#include <QTabWidget>
13#include "common/logging/log.h" 6#include "common/logging/log.h"
14#include "common/settings.h" 7#include "common/settings.h"
15#include "core/core.h" 8#include "core/core.h"
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 08d5444ec..a31fabd3f 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -4,13 +4,10 @@
4 4
5#include <functional> 5#include <functional>
6#include <utility> 6#include <utility>
7#include <QCheckBox>
8#include <QMessageBox> 7#include <QMessageBox>
9#include <QSpinBox>
10#include "common/settings.h" 8#include "common/settings.h"
11#include "core/core.h" 9#include "core/core.h"
12#include "ui_configure_general.h" 10#include "ui_configure_general.h"
13#include "yuzu/configuration/config.h"
14#include "yuzu/configuration/configuration_shared.h" 11#include "yuzu/configuration/configuration_shared.h"
15#include "yuzu/configuration/configure_general.h" 12#include "yuzu/configuration/configure_general.h"
16#include "yuzu/uisettings.h" 13#include "yuzu/uisettings.h"
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 59f975a6e..2f1435b10 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -6,7 +6,6 @@
6#include "video_core/vulkan_common/vulkan_wrapper.h" 6#include "video_core/vulkan_common/vulkan_wrapper.h"
7 7
8#include <QColorDialog> 8#include <QColorDialog>
9#include <QComboBox>
10#include <QVulkanInstance> 9#include <QVulkanInstance>
11 10
12#include "common/common_types.h" 11#include "common/common_types.h"
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 7c5776189..4ca74a5f7 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -2,13 +2,9 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <memory> 5#include <memory>
7#include <thread> 6#include <thread>
8 7
9#include <QSignalBlocker>
10#include <QTimer>
11
12#include "core/core.h" 8#include "core/core.h"
13#include "core/hid/emulated_controller.h" 9#include "core/hid/emulated_controller.h"
14#include "core/hid/hid_core.h" 10#include "core/hid/hid_core.h"
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 0aa4ac3e4..8ef3596dd 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -7,7 +7,6 @@
7#include <utility> 7#include <utility>
8#include <QGridLayout> 8#include <QGridLayout>
9#include <QInputDialog> 9#include <QInputDialog>
10#include <QKeyEvent>
11#include <QMenu> 10#include <QMenu>
12#include <QMessageBox> 11#include <QMessageBox>
13#include <QTimer> 12#include <QTimer>
@@ -23,7 +22,6 @@
23#include "yuzu/configuration/config.h" 22#include "yuzu/configuration/config.h"
24#include "yuzu/configuration/configure_input_player.h" 23#include "yuzu/configuration/configure_input_player.h"
25#include "yuzu/configuration/configure_input_player_widget.h" 24#include "yuzu/configuration/configure_input_player_widget.h"
26#include "yuzu/configuration/configure_vibration.h"
27#include "yuzu/configuration/input_profiles.h" 25#include "yuzu/configuration/input_profiles.h"
28#include "yuzu/util/limitable_input_dialog.h" 26#include "yuzu/util/limitable_input_dialog.h"
29 27
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index 4340de304..27559c37b 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -2,16 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <sstream> 5#include <sstream>
7 6
8#include <QCloseEvent> 7#include <QCloseEvent>
9#include <QLabel>
10#include <QMessageBox> 8#include <QMessageBox>
11#include <QPushButton>
12#include <QRegularExpression>
13#include <QStringListModel> 9#include <QStringListModel>
14#include <QVBoxLayout>
15 10
16#include "common/logging/log.h" 11#include "common/logging/log.h"
17#include "common/settings.h" 12#include "common/settings.h"
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h
index 8b707d2ff..91d1ae671 100644
--- a/src/yuzu/configuration/configure_motion_touch.h
+++ b/src/yuzu/configuration/configure_motion_touch.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <QDialog> 8#include <QDialog>
9#include "common/param_package.h"
10 9
11class QLabel; 10class QLabel;
12class QPushButton; 11class QPushButton;
diff --git a/src/yuzu/configuration/configure_network.cpp b/src/yuzu/configuration/configure_network.cpp
index 7020d2964..1f5799546 100644
--- a/src/yuzu/configuration/configure_network.cpp
+++ b/src/yuzu/configuration/configure_network.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QGraphicsItem>
6#include <QtConcurrent/QtConcurrent> 5#include <QtConcurrent/QtConcurrent>
7#include "common/settings.h" 6#include "common/settings.h"
8#include "core/core.h" 7#include "core/core.h"
diff --git a/src/yuzu/configuration/configure_network.h b/src/yuzu/configuration/configure_network.h
index 8507c62eb..1d07d0b53 100644
--- a/src/yuzu/configuration/configure_network.h
+++ b/src/yuzu/configuration/configure_network.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <QFutureWatcher>
9#include <QWidget> 8#include <QWidget>
10 9
11namespace Ui { 10namespace Ui {
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index f4cf25f05..55b2aa74f 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -12,17 +12,11 @@
12 12
13#include <QAbstractButton> 13#include <QAbstractButton>
14#include <QCheckBox> 14#include <QCheckBox>
15#include <QDialogButtonBox>
16#include <QHeaderView>
17#include <QMenu>
18#include <QPushButton> 15#include <QPushButton>
19#include <QStandardItemModel>
20#include <QString> 16#include <QString>
21#include <QTimer> 17#include <QTimer>
22#include <QTreeView>
23 18
24#include "common/fs/fs_util.h" 19#include "common/fs/fs_util.h"
25#include "common/fs/path_util.h"
26#include "core/core.h" 20#include "core/core.h"
27#include "core/file_sys/control_metadata.h" 21#include "core/file_sys/control_metadata.h"
28#include "core/file_sys/patch_manager.h" 22#include "core/file_sys/patch_manager.h"
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index c1a57d87b..b34b28577 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9#include <vector>
10 9
11#include <QDialog> 10#include <QDialog>
12#include <QList> 11#include <QList>
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 65e615963..21e51d749 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -24,7 +24,6 @@
24#include "yuzu/configuration/configure_input.h" 24#include "yuzu/configuration/configure_input.h"
25#include "yuzu/configuration/configure_per_game_addons.h" 25#include "yuzu/configuration/configure_per_game_addons.h"
26#include "yuzu/uisettings.h" 26#include "yuzu/uisettings.h"
27#include "yuzu/util/util.h"
28 27
29ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* parent) 28ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* parent)
30 : QWidget(parent), ui{std::make_unique<Ui::ConfigurePerGameAddons>()}, system{system_} { 29 : QWidget(parent), ui{std::make_unique<Ui::ConfigurePerGameAddons>()}, system{system_} {
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index d9f6dee4e..5442fe328 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -5,12 +5,10 @@
5#include <algorithm> 5#include <algorithm>
6#include <QFileDialog> 6#include <QFileDialog>
7#include <QGraphicsItem> 7#include <QGraphicsItem>
8#include <QGraphicsScene>
9#include <QHeaderView> 8#include <QHeaderView>
10#include <QMessageBox> 9#include <QMessageBox>
11#include <QStandardItemModel> 10#include <QStandardItemModel>
12#include <QTreeView> 11#include <QTreeView>
13#include <QVBoxLayout>
14#include "common/assert.h" 12#include "common/assert.h"
15#include "common/fs/path_util.h" 13#include "common/fs/path_util.h"
16#include "common/settings.h" 14#include "common/settings.h"
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 56c762d64..19aa589f9 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -2,14 +2,12 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <chrono> 5#include <chrono>
7#include <optional> 6#include <optional>
8 7
9#include <QFileDialog> 8#include <QFileDialog>
10#include <QGraphicsItem> 9#include <QGraphicsItem>
11#include <QMessageBox> 10#include <QMessageBox>
12#include "common/assert.h"
13#include "common/settings.h" 11#include "common/settings.h"
14#include "core/core.h" 12#include "core/core.h"
15#include "core/hle/service/time/time_manager.h" 13#include "core/hle/service/time/time_manager.h"
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index bb24c9ae7..5a1633192 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8 8
9#include <QList>
10#include <QWidget> 9#include <QWidget>
11 10
12namespace Core { 11namespace Core {
diff --git a/src/yuzu/configuration/configure_tas.h b/src/yuzu/configuration/configure_tas.h
index 1546bf16f..23a3673a7 100644
--- a/src/yuzu/configuration/configure_tas.h
+++ b/src/yuzu/configuration/configure_tas.h
@@ -6,6 +6,8 @@
6 6
7#include <QDialog> 7#include <QDialog>
8 8
9class QLineEdit;
10
9namespace Ui { 11namespace Ui {
10class ConfigureTas; 12class ConfigureTas;
11} 13}
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index 211a00217..c17da6fd1 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -6,7 +6,6 @@
6#include <QKeyEvent> 6#include <QKeyEvent>
7#include <QMessageBox> 7#include <QMessageBox>
8#include <QMouseEvent> 8#include <QMouseEvent>
9#include <QResizeEvent>
10#include <QStandardItemModel> 9#include <QStandardItemModel>
11#include <QTimer> 10#include <QTimer>
12#include "common/param_package.h" 11#include "common/param_package.h"
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index 779b6401c..d134ed02f 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -2,12 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <unordered_map>
7
8#include <fmt/format.h>
9
10#include "common/param_package.h"
11#include "common/settings.h" 5#include "common/settings.h"
12#include "core/hid/emulated_controller.h" 6#include "core/hid/emulated_controller.h"
13#include "core/hid/hid_core.h" 7#include "core/hid/hid_core.h"
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h
index a567bd5a9..7353aa77b 100644
--- a/src/yuzu/configuration/input_profiles.h
+++ b/src/yuzu/configuration/input_profiles.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8#include <string_view>
9#include <unordered_map> 8#include <unordered_map>
10 9
11namespace Core { 10namespace Core {
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 2d1a2d9cb..8f486a131 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -7,9 +7,7 @@
7 7
8#include "yuzu/debugger/wait_tree.h" 8#include "yuzu/debugger/wait_tree.h"
9#include "yuzu/uisettings.h" 9#include "yuzu/uisettings.h"
10#include "yuzu/util/util.h"
11 10
12#include "common/assert.h"
13#include "core/arm/arm_interface.h" 11#include "core/arm/arm_interface.h"
14#include "core/core.h" 12#include "core/core.h"
15#include "core/hle/kernel/k_class_token.h" 13#include "core/hle/kernel/k_class_token.h"
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index ea4d2e299..4a36dfc48 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -8,7 +8,6 @@
8#include <memory> 8#include <memory>
9#include <vector> 9#include <vector>
10 10
11#include <QAbstractItemModel>
12#include <QDockWidget> 11#include <QDockWidget>
13#include <QTreeView> 12#include <QTreeView>
14 13
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index e3661b390..4a6d74a7e 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -10,10 +10,10 @@
10#include <QJsonArray> 10#include <QJsonArray>
11#include <QJsonDocument> 11#include <QJsonDocument>
12#include <QJsonObject> 12#include <QJsonObject>
13#include <QKeyEvent>
14#include <QList> 13#include <QList>
15#include <QMenu> 14#include <QMenu>
16#include <QThreadPool> 15#include <QThreadPool>
16#include <QToolButton>
17#include <fmt/format.h> 17#include <fmt/format.h>
18#include "common/common_types.h" 18#include "common/common_types.h"
19#include "common/logging/log.h" 19#include "common/logging/log.h"
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index a94ea1477..d19dbe4b0 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -5,16 +5,11 @@
5#pragma once 5#pragma once
6 6
7#include <QFileSystemWatcher> 7#include <QFileSystemWatcher>
8#include <QHBoxLayout>
9#include <QLabel> 8#include <QLabel>
10#include <QLineEdit> 9#include <QLineEdit>
11#include <QList> 10#include <QList>
12#include <QModelIndex>
13#include <QSettings>
14#include <QStandardItem>
15#include <QStandardItemModel> 11#include <QStandardItemModel>
16#include <QString> 12#include <QString>
17#include <QToolButton>
18#include <QTreeView> 13#include <QTreeView>
19#include <QVBoxLayout> 14#include <QVBoxLayout>
20#include <QVector> 15#include <QVector>
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index 9dc3cc7c3..211a84dde 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -11,7 +11,6 @@
11 11
12#include <QCoreApplication> 12#include <QCoreApplication>
13#include <QFileInfo> 13#include <QFileInfo>
14#include <QImage>
15#include <QObject> 14#include <QObject>
16#include <QStandardItem> 15#include <QStandardItem>
17#include <QString> 16#include <QString>
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index fd92b36df..5e9b3eee8 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -23,7 +23,6 @@
23#include "core/file_sys/patch_manager.h" 23#include "core/file_sys/patch_manager.h"
24#include "core/file_sys/registered_cache.h" 24#include "core/file_sys/registered_cache.h"
25#include "core/file_sys/submission_package.h" 25#include "core/file_sys/submission_package.h"
26#include "core/hle/service/filesystem/filesystem.h"
27#include "core/loader/loader.h" 26#include "core/loader/loader.h"
28#include "yuzu/compatibility_list.h" 27#include "yuzu/compatibility_list.h"
29#include "yuzu/game_list.h" 28#include "yuzu/game_list.h"
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 1383e9fbc..2e0f89cbd 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -5,18 +5,14 @@
5#pragma once 5#pragma once
6 6
7#include <atomic> 7#include <atomic>
8#include <map>
9#include <memory> 8#include <memory>
10#include <string> 9#include <string>
11#include <unordered_map>
12 10
13#include <QList> 11#include <QList>
14#include <QObject> 12#include <QObject>
15#include <QRunnable> 13#include <QRunnable>
16#include <QString> 14#include <QString>
17#include <QVector>
18 15
19#include "common/common_types.h"
20#include "yuzu/compatibility_list.h" 16#include "yuzu/compatibility_list.h"
21 17
22namespace Core { 18namespace Core {
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 6ed9611c7..d59aa5d18 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <sstream> 5#include <sstream>
6#include <QKeySequence>
7#include <QShortcut> 6#include <QShortcut>
8#include <QTreeWidgetItem> 7#include <QTreeWidgetItem>
9#include <QtGlobal> 8#include <QtGlobal>
diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp
index 06b0b1874..55088bd87 100644
--- a/src/yuzu/install_dialog.cpp
+++ b/src/yuzu/install_dialog.cpp
@@ -5,7 +5,6 @@
5#include <QCheckBox> 5#include <QCheckBox>
6#include <QDialogButtonBox> 6#include <QDialogButtonBox>
7#include <QFileInfo> 7#include <QFileInfo>
8#include <QHBoxLayout>
9#include <QLabel> 8#include <QLabel>
10#include <QListWidget> 9#include <QListWidget>
11#include <QVBoxLayout> 10#include <QVBoxLayout>
diff --git a/src/yuzu/loading_screen.cpp b/src/yuzu/loading_screen.cpp
index b001b8c23..cd2148deb 100644
--- a/src/yuzu/loading_screen.cpp
+++ b/src/yuzu/loading_screen.cpp
@@ -6,19 +6,12 @@
6#include <QBuffer> 6#include <QBuffer>
7#include <QByteArray> 7#include <QByteArray>
8#include <QGraphicsOpacityEffect> 8#include <QGraphicsOpacityEffect>
9#include <QHBoxLayout>
10#include <QIODevice> 9#include <QIODevice>
11#include <QImage> 10#include <QImage>
12#include <QLabel>
13#include <QPainter> 11#include <QPainter>
14#include <QPalette>
15#include <QPixmap> 12#include <QPixmap>
16#include <QProgressBar>
17#include <QPropertyAnimation> 13#include <QPropertyAnimation>
18#include <QStyleOption> 14#include <QStyleOption>
19#include <QTime>
20#include <QtConcurrent/QtConcurrentRun>
21#include "common/logging/log.h"
22#include "core/frontend/framebuffer_layout.h" 15#include "core/frontend/framebuffer_layout.h"
23#include "core/loader/loader.h" 16#include "core/loader/loader.h"
24#include "ui_loading_screen.h" 17#include "ui_loading_screen.h"
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 06774768d..62d15f8cd 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -20,12 +20,11 @@
20#include "configuration/configure_input.h" 20#include "configuration/configure_input.h"
21#include "configuration/configure_per_game.h" 21#include "configuration/configure_per_game.h"
22#include "configuration/configure_tas.h" 22#include "configuration/configure_tas.h"
23#include "configuration/configure_vibration.h"
24#include "core/file_sys/vfs.h" 23#include "core/file_sys/vfs.h"
25#include "core/file_sys/vfs_real.h" 24#include "core/file_sys/vfs_real.h"
26#include "core/frontend/applets/controller.h" 25#include "core/frontend/applets/controller.h"
27#include "core/frontend/applets/general_frontend.h" 26#include "core/frontend/applets/general_frontend.h"
28#include "core/frontend/applets/mii.h" 27#include "core/frontend/applets/mii_edit.h"
29#include "core/frontend/applets/software_keyboard.h" 28#include "core/frontend/applets/software_keyboard.h"
30#include "core/hid/emulated_controller.h" 29#include "core/hid/emulated_controller.h"
31#include "core/hid/hid_core.h" 30#include "core/hid/hid_core.h"
@@ -54,8 +53,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
54#include <QClipboard> 53#include <QClipboard>
55#include <QDesktopServices> 54#include <QDesktopServices>
56#include <QDesktopWidget> 55#include <QDesktopWidget>
57#include <QDialogButtonBox>
58#include <QDir>
59#include <QFile> 56#include <QFile>
60#include <QFileDialog> 57#include <QFileDialog>
61#include <QInputDialog> 58#include <QInputDialog>
@@ -77,11 +74,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
77#include <fmt/format.h> 74#include <fmt/format.h>
78#include "common/detached_tasks.h" 75#include "common/detached_tasks.h"
79#include "common/fs/fs.h" 76#include "common/fs/fs.h"
80#include "common/fs/fs_paths.h"
81#include "common/fs/path_util.h" 77#include "common/fs/path_util.h"
82#include "common/literals.h" 78#include "common/literals.h"
83#include "common/logging/backend.h" 79#include "common/logging/backend.h"
84#include "common/logging/filter.h"
85#include "common/logging/log.h" 80#include "common/logging/log.h"
86#include "common/memory_detect.h" 81#include "common/memory_detect.h"
87#include "common/microprofile.h" 82#include "common/microprofile.h"
@@ -298,8 +293,6 @@ GMainWindow::GMainWindow()
298 293
299 MigrateConfigFiles(); 294 MigrateConfigFiles();
300 295
301 ui->action_Fullscreen->setChecked(false);
302
303#if defined(HAVE_SDL2) && !defined(_WIN32) 296#if defined(HAVE_SDL2) && !defined(_WIN32)
304 SDL_InitSubSystem(SDL_INIT_VIDEO); 297 SDL_InitSubSystem(SDL_INIT_VIDEO);
305 // SDL disables the screen saver by default, and setting the hint 298 // SDL disables the screen saver by default, and setting the hint
@@ -317,17 +310,20 @@ GMainWindow::GMainWindow()
317 } 310 }
318 311
319 QString game_path; 312 QString game_path;
313 bool has_gamepath = false;
314 bool is_fullscreen = false;
320 315
321 for (int i = 1; i < args.size(); ++i) { 316 for (int i = 1; i < args.size(); ++i) {
322 // Preserves drag/drop functionality 317 // Preserves drag/drop functionality
323 if (args.size() == 2 && !args[1].startsWith(QChar::fromLatin1('-'))) { 318 if (args.size() == 2 && !args[1].startsWith(QChar::fromLatin1('-'))) {
324 game_path = args[1]; 319 game_path = args[1];
320 has_gamepath = true;
325 break; 321 break;
326 } 322 }
327 323
328 // Launch game in fullscreen mode 324 // Launch game in fullscreen mode
329 if (args[i] == QStringLiteral("-f")) { 325 if (args[i] == QStringLiteral("-f")) {
330 ui->action_Fullscreen->setChecked(true); 326 is_fullscreen = true;
331 continue; 327 continue;
332 } 328 }
333 329
@@ -370,9 +366,15 @@ GMainWindow::GMainWindow()
370 } 366 }
371 367
372 game_path = args[++i]; 368 game_path = args[++i];
369 has_gamepath = true;
373 } 370 }
374 } 371 }
375 372
373 // Override fullscreen setting if gamepath or argument is provided
374 if (has_gamepath || is_fullscreen) {
375 ui->action_Fullscreen->setChecked(is_fullscreen);
376 }
377
376 if (!game_path.isEmpty()) { 378 if (!game_path.isEmpty()) {
377 BootGame(game_path); 379 BootGame(game_path);
378 } 380 }
@@ -587,7 +589,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
587#ifdef YUZU_USE_QT_WEB_ENGINE 589#ifdef YUZU_USE_QT_WEB_ENGINE
588 590
589 // Raw input breaks with the web applet, Disable web applets if enabled 591 // Raw input breaks with the web applet, Disable web applets if enabled
590 if (disable_web_applet || Settings::values.enable_raw_input) { 592 if (UISettings::values.disable_web_applet || Settings::values.enable_raw_input) {
591 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, 593 emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed,
592 "http://localhost/"); 594 "http://localhost/");
593 return; 595 return;
@@ -652,12 +654,12 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
652 connect(exit_action, &QAction::triggered, this, [this, &web_browser_view] { 654 connect(exit_action, &QAction::triggered, this, [this, &web_browser_view] {
653 const auto result = QMessageBox::warning( 655 const auto result = QMessageBox::warning(
654 this, tr("Disable Web Applet"), 656 this, tr("Disable Web Applet"),
655 tr("Disabling the web applet will cause it to not be shown again for the rest of the " 657 tr("Disabling the web applet can lead to undefined behavior and should only be used "
656 "emulated session. This can lead to undefined behavior and should only be used with " 658 "with Super Mario 3D All-Stars. Are you sure you want to disable the web "
657 "Super Mario 3D All-Stars. Are you sure you want to disable the web applet?"), 659 "applet?\n(This can be re-enabled in the Debug settings.)"),
658 QMessageBox::Yes | QMessageBox::No); 660 QMessageBox::Yes | QMessageBox::No);
659 if (result == QMessageBox::Yes) { 661 if (result == QMessageBox::Yes) {
660 disable_web_applet = true; 662 UISettings::values.disable_web_applet = true;
661 web_browser_view.SetFinished(true); 663 web_browser_view.SetFinished(true);
662 } 664 }
663 }); 665 });
@@ -1285,8 +1287,8 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1285 system->SetAppletFrontendSet({ 1287 system->SetAppletFrontendSet({
1286 std::make_unique<QtControllerSelector>(*this), // Controller Selector 1288 std::make_unique<QtControllerSelector>(*this), // Controller Selector
1287 std::make_unique<QtErrorDisplay>(*this), // Error Display 1289 std::make_unique<QtErrorDisplay>(*this), // Error Display
1290 nullptr, // Mii Editor
1288 nullptr, // Parental Controls 1291 nullptr, // Parental Controls
1289 nullptr, // Mii editor
1290 nullptr, // Photo Viewer 1292 nullptr, // Photo Viewer
1291 std::make_unique<QtProfileSelector>(*this), // Profile Selector 1293 std::make_unique<QtProfileSelector>(*this), // Profile Selector
1292 std::make_unique<QtSoftwareKeyboard>(*this), // Software Keyboard 1294 std::make_unique<QtSoftwareKeyboard>(*this), // Software Keyboard
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 6a35b9e3d..ab95a7518 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -6,14 +6,12 @@
6 6
7#include <memory> 7#include <memory>
8#include <optional> 8#include <optional>
9#include <unordered_map>
10 9
11#include <QMainWindow> 10#include <QMainWindow>
12#include <QTimer> 11#include <QTimer>
13#include <QTranslator> 12#include <QTranslator>
14 13
15#include "common/common_types.h" 14#include "common/common_types.h"
16#include "core/hle/service/acc/profile_manager.h"
17#include "yuzu/compatibility_list.h" 15#include "yuzu/compatibility_list.h"
18#include "yuzu/hotkeys.h" 16#include "yuzu/hotkeys.h"
19 17
@@ -400,9 +398,6 @@ private:
400 // Last game booted, used for multi-process apps 398 // Last game booted, used for multi-process apps
401 QString last_filename_booted; 399 QString last_filename_booted;
402 400
403 // Disables the web applet for the rest of the emulated session
404 bool disable_web_applet{};
405
406 // Applets 401 // Applets
407 QtSoftwareKeyboardDialog* software_keyboard = nullptr; 402 QtSoftwareKeyboardDialog* software_keyboard = nullptr;
408 403
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 06e8b46da..cc5aee382 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -114,6 +114,7 @@ struct Values {
114 114
115 bool configuration_applied; 115 bool configuration_applied;
116 bool reset_to_defaults; 116 bool reset_to_defaults;
117 Settings::BasicSetting<bool> disable_web_applet{true, "disable_web_applet"};
117}; 118};
118 119
119extern Values values; 120extern Values values;
diff --git a/src/yuzu/util/overlay_dialog.h b/src/yuzu/util/overlay_dialog.h
index d8a140ff3..014c943c7 100644
--- a/src/yuzu/util/overlay_dialog.h
+++ b/src/yuzu/util/overlay_dialog.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <atomic> 7#include <atomic>
9#include <memory> 8#include <memory>
10#include <thread> 9#include <thread>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 131bc2201..fc16f0f0c 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -21,7 +21,6 @@
21#include "common/fs/fs.h" 21#include "common/fs/fs.h"
22#include "common/fs/path_util.h" 22#include "common/fs/path_util.h"
23#include "common/logging/log.h" 23#include "common/logging/log.h"
24#include "common/param_package.h"
25#include "common/settings.h" 24#include "common/settings.h"
26#include "core/hle/service/acc/profile_manager.h" 25#include "core/hle/service/acc/profile_manager.h"
27#include "input_common/main.h" 26#include "input_common/main.h"
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 0af002693..9746585f5 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
8#include <utility> 7#include <utility>
9#include "core/frontend/emu_window.h" 8#include "core/frontend/emu_window.h"
10 9
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index 70db865ec..bbe90eb77 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -11,7 +11,6 @@
11 11
12#include <fmt/format.h> 12#include <fmt/format.h>
13#include <glad/glad.h> 13#include <glad/glad.h>
14#include "common/assert.h"
15#include "common/logging/log.h" 14#include "common/logging/log.h"
16#include "common/scm_rev.h" 15#include "common/scm_rev.h"
17#include "common/settings.h" 16#include "common/settings.h"
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index de40b76bf..49cd9213c 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -8,10 +8,8 @@
8 8
9#include <fmt/format.h> 9#include <fmt/format.h>
10 10
11#include "common/assert.h"
12#include "common/logging/log.h" 11#include "common/logging/log.h"
13#include "common/scm_rev.h" 12#include "common/scm_rev.h"
14#include "common/settings.h"
15#include "video_core/renderer_vulkan/renderer_vulkan.h" 13#include "video_core/renderer_vulkan/renderer_vulkan.h"
16#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" 14#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
17 15
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index f6d563017..ab12dd15d 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -11,11 +11,7 @@
11#include <fmt/ostream.h> 11#include <fmt/ostream.h>
12 12
13#include "common/detached_tasks.h" 13#include "common/detached_tasks.h"
14#include "common/fs/fs.h"
15#include "common/fs/fs_paths.h"
16#include "common/fs/path_util.h"
17#include "common/logging/backend.h" 14#include "common/logging/backend.h"
18#include "common/logging/filter.h"
19#include "common/logging/log.h" 15#include "common/logging/log.h"
20#include "common/microprofile.h" 16#include "common/microprofile.h"
21#include "common/nvidia_flags.h" 17#include "common/nvidia_flags.h"
@@ -78,6 +74,7 @@ static void PrintVersion() {
78int main(int argc, char** argv) { 74int main(int argc, char** argv) {
79 Common::Log::Initialize(); 75 Common::Log::Initialize();
80 Common::Log::SetColorConsoleBackendEnabled(true); 76 Common::Log::SetColorConsoleBackendEnabled(true);
77 Common::Log::Start();
81 Common::DetachedTasks detached_tasks; 78 Common::DetachedTasks detached_tasks;
82 79
83 int option_index = 0; 80 int option_index = 0;