From 18527a8c42ddd97befd76d44413ff6b7652faf31 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 17 Dec 2022 23:55:05 -0800 Subject: video_core: vk_blit_screen: Rotate viewport for Android landscape. --- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 1e0fdd3d9..df948292f 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -76,10 +76,18 @@ struct ScreenRectVertex { constexpr std::array MakeOrthographicMatrix(f32 width, f32 height) { // clang-format off +#ifdef ANDROID + // Android renders in portrait, so rotate the matrix. + return { 0.f, 2.f / width, 0.f, 0.f, + -2.f / height, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 1.f, -1.f, 0.f, 1.f}; +#else return { 2.f / width, 0.f, 0.f, 0.f, 0.f, 2.f / height, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, -1.f, -1.f, 0.f, 1.f}; +#endif // ANDROID // clang-format on } -- cgit v1.2.3 From 6ed62a9f109ed7e09586f33777505132acb261df Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 Dec 2022 01:11:14 -0800 Subject: video_core: vk_swapchain: Fix image format for Android. --- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 5 +++++ src/video_core/renderer_vulkan/vk_swapchain.cpp | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index df948292f..e4c581a28 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -449,7 +449,12 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f if (const std::size_t swapchain_images = swapchain.GetImageCount(); swapchain_images != image_count || current_srgb != is_srgb) { current_srgb = is_srgb; +#ifdef ANDROID + // Android is already ordered the same as Switch. + image_view_format = current_srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; +#else image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; +#endif image_count = swapchain_images; Recreate(); } diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 8c0dec590..e43a993f9 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -266,7 +266,12 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo images = swapchain.GetImages(); image_count = static_cast(images.size()); +#ifdef ANDROID + // Android is already ordered the same as Switch. + image_view_format = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; +#else image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; +#endif } void Swapchain::CreateSemaphores() { -- cgit v1.2.3 From 91350524c29f01ae1019baa3848364059224d41c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 18 Dec 2022 02:57:43 -0800 Subject: video_core: vk_pipeline_cache: Disable support_descriptor_aliasing on Android. --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 66dfe5733..b77ed2200 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -293,7 +293,11 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device profile = Shader::Profile{ .supported_spirv = device.SupportedSpirvVersion(), .unified_descriptor_binding = true, +#ifdef ANDROID + .support_descriptor_aliasing = false, +#else .support_descriptor_aliasing = true, +#endif .support_int8 = device.IsInt8Supported(), .support_int16 = device.IsShaderInt16Supported(), .support_int64 = device.IsShaderInt64Supported(), -- cgit v1.2.3 From a3c261d9406a747759097155d181abe7a67b2a7a Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 18 Feb 2023 17:23:12 +0000 Subject: Disable multithreaded pipeline compilation on Qualcomm drivers This causes crashes during compilation on several 6xx and 5xx driver versions. --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index b77ed2200..ec55e11b1 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -286,7 +286,10 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device texture_cache{texture_cache_}, shader_notify{shader_notify_}, use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()}, - workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), + workers(device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY + ? 1 + : (std::max(std::thread::hardware_concurrency(), 2U) - 1), + "VkPipelineBuilder"), serialization_thread(1, "VkPipelineSerialization") { const auto& float_control{device.FloatControlProperties()}; const VkDriverId driver_id{device.GetDriverID()}; -- cgit v1.2.3 From 158a1896ec91c46a43fa3172fa472e6fc7c9eb05 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 18 Feb 2023 18:23:36 +0000 Subject: Implement scaled vertex buffer format emulation These formats are unsupported by mobile GPUs so they need to be emulated in shaders instead. --- .../backend/spirv/emit_spirv_context_get_set.cpp | 44 ++++++---------- .../backend/spirv/spirv_emit_context.cpp | 61 ++++++++++++++-------- .../backend/spirv/spirv_emit_context.h | 16 +++++- src/shader_recompiler/profile.h | 1 + src/shader_recompiler/runtime_info.h | 2 + src/video_core/renderer_vulkan/maxwell_to_vk.cpp | 8 +++ .../renderer_vulkan/vk_pipeline_cache.cpp | 7 ++- src/video_core/vulkan_common/vulkan_device.cpp | 4 ++ src/video_core/vulkan_common/vulkan_device.h | 5 ++ 9 files changed, 97 insertions(+), 51 deletions(-) (limited to 'src/video_core/renderer_vulkan') 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 07c2b7b8a..2868fc57d 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 @@ -10,27 +10,6 @@ namespace Shader::Backend::SPIRV { namespace { -struct AttrInfo { - Id pointer; - Id id; - bool needs_cast; -}; - -std::optional AttrTypes(EmitContext& ctx, u32 index) { - const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; - switch (type) { - case AttributeType::Float: - return AttrInfo{ctx.input_f32, ctx.F32[1], false}; - case AttributeType::UnsignedInt: - return AttrInfo{ctx.input_u32, ctx.U32[1], true}; - case AttributeType::SignedInt: - return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true}; - case AttributeType::Disabled: - return std::nullopt; - } - throw InvalidArgument("Invalid attribute type {}", type); -} - template Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&... args) { switch (ctx.stage) { @@ -302,15 +281,26 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { const u32 element{static_cast(attr) % 4}; if (IR::IsGeneric(attr)) { const u32 index{IR::GenericAttributeIndex(attr)}; - const std::optional type{AttrTypes(ctx, index)}; - if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index, element)) { + const auto& generic{ctx.input_generics.at(index)}; + if (!ValidId(generic.id)) { // Attribute is disabled or varying component is not written return ctx.Const(element == 3 ? 1.0f : 0.0f); } - const Id generic_id{ctx.input_generics.at(index)}; - const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))}; - const Id value{ctx.OpLoad(type->id, pointer)}; - return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; + const Id pointer{ + AttrPointer(ctx, generic.pointer_type, vertex, generic.id, ctx.Const(element))}; + const Id value{ctx.OpLoad(generic.component_type, pointer)}; + return [&ctx, generic, value]() { + switch (generic.load_op) { + case InputGenericLoadOp::Bitcast: + return ctx.OpBitcast(ctx.F32[1], value); + case InputGenericLoadOp::SToF: + return ctx.OpConvertSToF(ctx.F32[1], value); + case InputGenericLoadOp::UToF: + return ctx.OpConvertUToF(ctx.F32[1], value); + default: + return value; + }; + }(); } switch (attr) { case IR::Attribute::PrimitiveId: diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 47739794f..fd15f47ea 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -25,12 +25,6 @@ enum class Operation { FPMax, }; -struct AttrInfo { - Id pointer; - Id id; - bool needs_cast; -}; - Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { const spv::ImageFormat format{spv::ImageFormat::Unknown}; const Id type{ctx.F32[1]}; @@ -206,23 +200,37 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { return ctx.TypeVector(ctx.TypeInt(32, true), 4); case AttributeType::UnsignedInt: return ctx.U32[4]; + case AttributeType::SignedScaled: + return ctx.profile.support_scaled_attributes ? ctx.F32[4] + : ctx.TypeVector(ctx.TypeInt(32, true), 4); + case AttributeType::UnsignedScaled: + return ctx.profile.support_scaled_attributes ? ctx.F32[4] : ctx.U32[4]; case AttributeType::Disabled: break; } throw InvalidArgument("Invalid attribute type {}", type); } -std::optional AttrTypes(EmitContext& ctx, u32 index) { - const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; +InputGenericInfo GetAttributeInfo(EmitContext& ctx, AttributeType type, Id id) { switch (type) { case AttributeType::Float: - return AttrInfo{ctx.input_f32, ctx.F32[1], false}; + return InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None}; case AttributeType::UnsignedInt: - return AttrInfo{ctx.input_u32, ctx.U32[1], true}; + return InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::Bitcast}; case AttributeType::SignedInt: - return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true}; + return InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), + InputGenericLoadOp::Bitcast}; + case AttributeType::SignedScaled: + return ctx.profile.support_scaled_attributes + ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} + : InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), + InputGenericLoadOp::SToF}; + case AttributeType::UnsignedScaled: + return ctx.profile.support_scaled_attributes + ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} + : InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::UToF}; case AttributeType::Disabled: - return std::nullopt; + return InputGenericInfo{}; } throw InvalidArgument("Invalid attribute type {}", type); } @@ -746,18 +754,29 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { continue; } AddLabel(labels[label_index]); - const auto type{AttrTypes(*this, static_cast(index))}; - if (!type) { + const auto& generic{input_generics.at(index)}; + const Id generic_id{generic.id}; + if (!ValidId(generic_id)) { OpReturnValue(Const(0.0f)); ++label_index; continue; } - const Id generic_id{input_generics.at(index)}; - const Id pointer{is_array - ? OpAccessChain(type->pointer, generic_id, vertex, masked_index) - : OpAccessChain(type->pointer, generic_id, masked_index)}; - const Id value{OpLoad(type->id, pointer)}; - const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; + const Id pointer{ + is_array ? OpAccessChain(generic.pointer_type, generic_id, vertex, masked_index) + : OpAccessChain(generic.pointer_type, generic_id, masked_index)}; + const Id value{OpLoad(generic.component_type, pointer)}; + const Id result{[this, generic, value]() { + switch (generic.load_op) { + case InputGenericLoadOp::Bitcast: + return OpBitcast(F32[1], value); + case InputGenericLoadOp::SToF: + return OpConvertSToF(F32[1], value); + case InputGenericLoadOp::UToF: + return OpConvertUToF(F32[1], value); + default: + return value; + }; + }()}; OpReturnValue(result); ++label_index; } @@ -1457,7 +1476,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { const Id id{DefineInput(*this, type, true)}; Decorate(id, spv::Decoration::Location, static_cast(index)); Name(id, fmt::format("in_attr{}", index)); - input_generics[index] = id; + input_generics[index] = GetAttributeInfo(*this, input_type, id); if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) { Decorate(id, spv::Decoration::PassthroughNV); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 768a4fbb5..e63330f11 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -95,6 +95,20 @@ struct StorageDefinitions { Id U32x4{}; }; +enum class InputGenericLoadOp { + None, + Bitcast, + SToF, + UToF, +}; + +struct InputGenericInfo { + Id id; + Id pointer_type; + Id component_type; + InputGenericLoadOp load_op; +}; + struct GenericElementInfo { Id id{}; u32 first_element{}; @@ -283,7 +297,7 @@ public: bool need_input_position_indirect{}; Id input_position{}; - std::array input_generics{}; + std::array input_generics{}; Id output_point_size{}; Id output_position{}; diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 9f88fb440..3bb4a7e6f 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -43,6 +43,7 @@ struct Profile { bool support_gl_variable_aoffi{}; bool support_gl_sparse_textures{}; bool support_gl_derivative_control{}; + bool support_scaled_attributes{}; bool warp_size_potentially_larger_than_guest{}; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 549b81ef7..3b63c249f 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -17,6 +17,8 @@ enum class AttributeType : u8 { Float, SignedInt, UnsignedInt, + SignedScaled, + UnsignedScaled, Disabled, }; diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index b75d7220d..9a0b10568 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -347,6 +347,14 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const Device& device, VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) { + if (device.MustEmulateScaledFormats()) { + if (type == Maxwell::VertexAttribute::Type::SScaled) { + type = Maxwell::VertexAttribute::Type::SInt; + } else if (type == Maxwell::VertexAttribute::Type::UScaled) { + type = Maxwell::VertexAttribute::Type::UInt; + } + } + const VkFormat format{([&]() { switch (type) { case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway: diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ec55e11b1..e39713761 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -114,14 +114,16 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut return Shader::AttributeType::Disabled; case Maxwell::VertexAttribute::Type::SNorm: case Maxwell::VertexAttribute::Type::UNorm: - case Maxwell::VertexAttribute::Type::UScaled: - case Maxwell::VertexAttribute::Type::SScaled: case Maxwell::VertexAttribute::Type::Float: return Shader::AttributeType::Float; case Maxwell::VertexAttribute::Type::SInt: return Shader::AttributeType::SignedInt; case Maxwell::VertexAttribute::Type::UInt: return Shader::AttributeType::UnsignedInt; + case Maxwell::VertexAttribute::Type::UScaled: + return Shader::AttributeType::UnsignedScaled; + case Maxwell::VertexAttribute::Type::SScaled: + return Shader::AttributeType::SignedScaled; } return Shader::AttributeType::Float; } @@ -331,6 +333,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .support_derivative_control = true, .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .support_native_ndc = device.IsExtDepthClipControlSupported(), + .support_scaled_attributes = !device.MustEmulateScaledFormats(), .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 01540c10b..63e1c7d63 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -363,6 +363,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR #ifdef ANDROID if (is_adreno) { + must_emulate_scaled_formats = true; + LOG_WARNING(Render_Vulkan, "Adreno drivers have broken VK_EXT_extended_dynamic_state"); extensions.extended_dynamic_state = false; loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); @@ -391,6 +393,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } if (is_arm) { + must_emulate_scaled_formats = true; + LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); extensions.extended_dynamic_state = false; loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5f1c63ff9..f9d8c47ba 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -551,6 +551,10 @@ public: return cant_blit_msaa; } + bool MustEmulateScaledFormats() const { + return must_emulate_scaled_formats; + } + bool MustEmulateBGR565() const { return must_emulate_bgr565; } @@ -666,6 +670,7 @@ private: bool has_nsight_graphics{}; ///< Has Nsight Graphics attached bool supports_d24_depth{}; ///< Supports D24 depth buffers. bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. + bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. -- cgit v1.2.3 From b4a12b889ee0182bbe05423933b122fd9e78b132 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 18 Feb 2023 18:26:47 +0000 Subject: Avoid using VectorExtractDynamic for subgroup mask on Adreno GPUs This crashes their shader compiler for some reason. --- src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp | 17 ++++++++++++++++- src/shader_recompiler/profile.h | 2 ++ src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index c5db19d09..77ff8c573 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp @@ -17,7 +17,22 @@ Id GetThreadId(EmitContext& ctx) { Id WarpExtract(EmitContext& ctx, Id value) { const Id thread_id{GetThreadId(ctx)}; const Id local_index{ctx.OpShiftRightArithmetic(ctx.U32[1], thread_id, ctx.Const(5U))}; - return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index); + if (ctx.profile.has_broken_spirv_subgroup_mask_vector_extract_dynamic) { + const Id c0_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(0U)), + ctx.OpCompositeExtract(ctx.U32[1], value, 0U), ctx.Const(0U))}; + const Id c1_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(1U)), + ctx.OpCompositeExtract(ctx.U32[1], value, 1U), ctx.Const(0U))}; + const Id c2_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(2U)), + ctx.OpCompositeExtract(ctx.U32[1], value, 2U), ctx.Const(0U))}; + const Id c3_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(3U)), + ctx.OpCompositeExtract(ctx.U32[1], value, 3U), ctx.Const(0U))}; + const Id c0_or_c1{ctx.OpBitwiseOr(ctx.U32[1], c0_sel, c1_sel)}; + const Id c2_or_c3{ctx.OpBitwiseOr(ctx.U32[1], c2_sel, c3_sel)}; + const Id c0_or_c1_or_c2_or_c3{ctx.OpBitwiseOr(ctx.U32[1], c0_or_c1, c2_or_c3)}; + return c0_or_c1_or_c2_or_c3; + } else { + return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index); + } } Id LoadMask(EmitContext& ctx, Id mask) { diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 3bb4a7e6f..9ca97f6a4 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -78,6 +78,8 @@ struct Profile { bool has_gl_bool_ref_bug{}; /// Ignores SPIR-V ordered vs unordered using GLSL semantics bool ignore_nan_fp_comparisons{}; + /// Some drivers have broken support for OpVectorExtractDynamic on subgroup mask inputs + bool has_broken_spirv_subgroup_mask_vector_extract_dynamic{}; u32 gl_max_compute_smem_size{}; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index e39713761..e506a8b30 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -351,6 +351,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .has_broken_signed_operations = false, .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, .ignore_nan_fp_comparisons = false, + .has_broken_spirv_subgroup_mask_vector_extract_dynamic = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY }; host_info = Shader::HostTranslateInfo{ .support_float16 = device.IsFloat16Supported(), -- cgit v1.2.3 From ae099d583cf93175fe54359ea2b7c5b665398c8b Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 18 Feb 2023 23:31:39 -0800 Subject: core: frontend: Refactor GraphicsContext to its own module. --- src/core/CMakeLists.txt | 1 + src/core/frontend/emu_window.cpp | 2 - src/core/frontend/emu_window.h | 48 +-------------- src/core/frontend/graphics_context.h | 69 ++++++++++++++++++++++ src/video_core/gpu.cpp | 1 + src/video_core/gpu_thread.cpp | 2 +- src/video_core/renderer_base.cpp | 1 + src/video_core/renderer_base.h | 2 +- src/video_core/renderer_null/renderer_null.cpp | 2 + src/video_core/renderer_opengl/gl_shader_context.h | 1 + src/video_core/renderer_vulkan/renderer_vulkan.cpp | 2 +- src/yuzu/bootmanager.cpp | 1 + src/yuzu_cmd/emu_window/emu_window_sdl2.h | 2 + 13 files changed, 84 insertions(+), 50 deletions(-) create mode 100644 src/core/frontend/graphics_context.h (limited to 'src/video_core/renderer_vulkan') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 45328158f..157858c82 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -140,6 +140,7 @@ add_library(core STATIC frontend/emu_window.h frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h + frontend/graphics_context.h hid/emulated_console.cpp hid/emulated_console.h hid/emulated_controller.cpp diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 1be2dccb0..d1f1ca8c9 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -6,8 +6,6 @@ namespace Core::Frontend { -GraphicsContext::~GraphicsContext() = default; - EmuWindow::EmuWindow() { // TODO: Find a better place to set this. config.min_client_area_size = diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 1093800f6..a72df034e 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -5,11 +5,14 @@ #include #include + #include "common/common_types.h" #include "core/frontend/framebuffer_layout.h" namespace Core::Frontend { +class GraphicsContext; + /// Information for the Graphics Backends signifying what type of screen pointer is in /// WindowInformation enum class WindowSystemType { @@ -21,51 +24,6 @@ enum class WindowSystemType { Android, }; -/** - * Represents a drawing context that supports graphics operations. - */ -class GraphicsContext { -public: - virtual ~GraphicsContext(); - - /// Inform the driver to swap the front/back buffers and present the current image - virtual void SwapBuffers() {} - - /// Makes the graphics context current for the caller thread - virtual void MakeCurrent() {} - - /// Releases (dunno if this is the "right" word) the context from the caller thread - virtual void DoneCurrent() {} - - class Scoped { - public: - [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { - context.MakeCurrent(); - } - ~Scoped() { - if (active) { - context.DoneCurrent(); - } - } - - /// In the event that context was destroyed before the Scoped is destroyed, this provides a - /// mechanism to prevent calling a destroyed object's method during the deconstructor - void Cancel() { - active = false; - } - - private: - GraphicsContext& context; - bool active{true}; - }; - - /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value - /// ends - [[nodiscard]] Scoped Acquire() { - return Scoped{*this}; - } -}; - /** * Abstraction class used to provide an interface between emulation code and the frontend * (e.g. SDL, QGLWidget, GLFW, etc...). diff --git a/src/core/frontend/graphics_context.h b/src/core/frontend/graphics_context.h new file mode 100644 index 000000000..064b19a96 --- /dev/null +++ b/src/core/frontend/graphics_context.h @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +namespace Core::Frontend { + +/** + * Represents a drawing context that supports graphics operations. + */ +class GraphicsContext { +public: + virtual ~GraphicsContext() = default; + + /// Inform the driver to swap the front/back buffers and present the current image + virtual void SwapBuffers() {} + + /// Makes the graphics context current for the caller thread + virtual void MakeCurrent() {} + + /// Releases (dunno if this is the "right" word) the context from the caller thread + virtual void DoneCurrent() {} + + /// Parameters used to configure custom drivers (used by Android only) + struct CustomDriverParameters { + std::string hook_lib_dir; + std::string custom_driver_dir; + std::string custom_driver_name; + std::string file_redirect_dir; + }; + + /// Gets custom driver parameters configured by the frontend (used by Android only) + virtual std::optional GetCustomDriverParameters() { + return {}; + } + + class Scoped { + public: + [[nodiscard]] explicit Scoped(GraphicsContext& context_) : context(context_) { + context.MakeCurrent(); + } + ~Scoped() { + if (active) { + context.DoneCurrent(); + } + } + + /// In the event that context was destroyed before the Scoped is destroyed, this provides a + /// mechanism to prevent calling a destroyed object's method during the deconstructor + void Cancel() { + active = false; + } + + private: + GraphicsContext& context; + bool active{true}; + }; + + /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value + /// ends + [[nodiscard]] Scoped Acquire() { + return Scoped{*this}; + } +}; + +} // namespace Core::Frontend diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 295a416a8..456f733cf 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -14,6 +14,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "core/hle/service/nvdrv/nvdata.h" #include "core/perf_stats.h" #include "video_core/cdma_pusher.h" diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 3c5317777..889144f38 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -7,7 +7,7 @@ #include "common/settings.h" #include "common/thread.h" #include "core/core.h" -#include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "video_core/control/scheduler.h" #include "video_core/dma_pusher.h" #include "video_core/gpu.h" diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index e8761a747..2d3f58201 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp @@ -5,6 +5,7 @@ #include "common/logging/log.h" #include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "video_core/renderer_base.h" namespace VideoCore { diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 8d20cbece..78ea5208b 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -9,7 +9,7 @@ #include "common/common_funcs.h" #include "common/common_types.h" -#include "core/frontend/emu_window.h" +#include "core/frontend/framebuffer_layout.h" #include "video_core/gpu.h" #include "video_core/rasterizer_interface.h" diff --git a/src/video_core/renderer_null/renderer_null.cpp b/src/video_core/renderer_null/renderer_null.cpp index e2a189b63..be92cc2f4 100644 --- a/src/video_core/renderer_null/renderer_null.cpp +++ b/src/video_core/renderer_null/renderer_null.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "video_core/renderer_null/renderer_null.h" namespace Null { diff --git a/src/video_core/renderer_opengl/gl_shader_context.h b/src/video_core/renderer_opengl/gl_shader_context.h index ca2bd8e8e..207a75d42 100644 --- a/src/video_core/renderer_opengl/gl_shader_context.h +++ b/src/video_core/renderer_opengl/gl_shader_context.h @@ -4,6 +4,7 @@ #pragma once #include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/maxwell/control_flow.h" diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 8e31eba34..fbcf4c1d3 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -16,7 +16,7 @@ #include "common/settings.h" #include "common/telemetry.h" #include "core/core_timing.h" -#include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "core/telemetry_session.h" #include "video_core/gpu.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 59d226113..cc6b6a25a 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -46,6 +46,7 @@ #include "core/core.h" #include "core/cpu_manager.h" #include "core/frontend/framebuffer_layout.h" +#include "core/frontend/graphics_context.h" #include "input_common/drivers/camera.h" #include "input_common/drivers/keyboard.h" #include "input_common/drivers/mouse.h" diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index d9b453dee..4ad05e0e1 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h @@ -4,7 +4,9 @@ #pragma once #include + #include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" struct SDL_Window; -- cgit v1.2.3 From 4c38220a644f8292f4915eaabb2f80d3d0badab0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 18 Feb 2023 23:42:07 -0800 Subject: android: native: Add support for custom Vulkan driver loading. --- .../main/java/org/yuzu/yuzu_emu/NativeLibrary.java | 2 + src/android/app/src/main/jni/CMakeLists.txt | 2 +- .../app/src/main/jni/emu_window/emu_window.cpp | 39 ++++++------- .../app/src/main/jni/emu_window/emu_window.h | 41 +++++++++----- src/android/app/src/main/jni/native.cpp | 64 ++++++++++++++++++---- src/android/app/src/main/jni/native.h | 5 ++ src/core/frontend/graphics_context.h | 17 ++---- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 4 +- src/video_core/renderer_vulkan/renderer_vulkan.h | 2 +- src/video_core/vulkan_common/vulkan_device.cpp | 14 +++-- src/video_core/vulkan_common/vulkan_library.cpp | 18 ++++-- src/video_core/vulkan_common/vulkan_library.h | 6 +- src/yuzu/configuration/configure_graphics.cpp | 4 +- src/yuzu/startup_checks.cpp | 4 +- 14 files changed, 146 insertions(+), 76 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java index a0f6c1f7b..e56196310 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java @@ -181,6 +181,8 @@ public final class NativeLibrary { public static native void SetAppDirectory(String directory); + public static native void SetGpuDriverParameters(String hookLibDir, String customDriverDir, String customDriverName, String fileRedirectDir); + public static native boolean ReloadKeys(); // Create the config.ini file. diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index e5c9d57f2..f80c166f4 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -13,6 +13,6 @@ add_library(yuzu-android SHARED set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) -target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) +target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics adrenotools log) set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} yuzu-android) diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp index 2beba6804..ad17cf129 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp @@ -7,61 +7,62 @@ #include "jni/emu_window/emu_window.h" void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { - render_window = surface; + m_render_window = surface; } void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); + m_input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); } void EmuWindow_Android::OnTouchMoved(int id, float x, float y) { const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); + m_input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); } void EmuWindow_Android::OnTouchReleased(int id) { - input_subsystem->GetTouchScreen()->TouchReleased(id); + m_input_subsystem->GetTouchScreen()->TouchReleased(id); } void EmuWindow_Android::OnGamepadButtonEvent(int player_index, int button_id, bool pressed) { - input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed); + m_input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed); } void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) { - input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y); + m_input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y); } void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z) { - input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, - gyro_y, gyro_z, accel_x, accel_y, accel_z); + m_input_subsystem->GetVirtualGamepad()->SetMotionState( + player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); } -EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, - ANativeWindow* surface_) - : input_subsystem{input_subsystem_} { +EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem, + ANativeWindow* surface, + std::shared_ptr driver_library) + : m_input_subsystem{input_subsystem}, m_driver_library{driver_library} { LOG_INFO(Frontend, "initializing"); - if (!surface_) { + if (!surface) { LOG_CRITICAL(Frontend, "surface is nullptr"); return; } - window_width = ANativeWindow_getWidth(surface_); - window_height = ANativeWindow_getHeight(surface_); + m_window_width = ANativeWindow_getWidth(surface); + m_window_height = ANativeWindow_getHeight(surface); // Ensures that we emulate with the correct aspect ratio. - UpdateCurrentFramebufferLayout(window_width, window_height); + UpdateCurrentFramebufferLayout(m_window_width, m_window_height); - host_window = surface_; + m_host_window = surface; window_info.type = Core::Frontend::WindowSystemType::Android; - window_info.render_surface = reinterpret_cast(host_window); + window_info.render_surface = reinterpret_cast(m_host_window); - input_subsystem->Initialize(); + m_input_subsystem->Initialize(); } EmuWindow_Android::~EmuWindow_Android() { - input_subsystem->Shutdown(); + m_input_subsystem->Shutdown(); } diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h index 544924caa..1c1edf62c 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.h +++ b/src/android/app/src/main/jni/emu_window/emu_window.h @@ -1,21 +1,34 @@ #pragma once +#include + #include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "input_common/main.h" struct ANativeWindow; -class SharedContext_Android : public Core::Frontend::GraphicsContext { +class GraphicsContext_Android final : public Core::Frontend::GraphicsContext { public: - SharedContext_Android() = default; - ~SharedContext_Android() = default; - void MakeCurrent() override {} - void DoneCurrent() override {} + explicit GraphicsContext_Android(std::shared_ptr driver_library) + : m_driver_library{driver_library} {} + + ~GraphicsContext_Android() = default; + + std::shared_ptr GetDriverLibrary() override { + return m_driver_library; + } + +private: + std::shared_ptr m_driver_library; }; -class EmuWindow_Android : public Core::Frontend::EmuWindow { +class EmuWindow_Android final : public Core::Frontend::EmuWindow { + public: - EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, ANativeWindow* surface_); + EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem, ANativeWindow* surface, + std::shared_ptr driver_library); + ~EmuWindow_Android(); void OnSurfaceChanged(ANativeWindow* surface); @@ -29,18 +42,20 @@ public: void OnFrameDisplayed() override {} std::unique_ptr CreateSharedContext() const override { - return {std::make_unique()}; + return {std::make_unique(m_driver_library)}; } bool IsShown() const override { return true; }; private: - InputCommon::InputSubsystem* input_subsystem{}; + InputCommon::InputSubsystem* m_input_subsystem{}; + + ANativeWindow* m_render_window{}; + ANativeWindow* m_host_window{}; - ANativeWindow* render_window{}; - ANativeWindow* host_window{}; + float m_window_width{}; + float m_window_height{}; - float window_width{}; - float window_height{}; + std::shared_ptr m_driver_library; }; diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 0a2a65721..a8f3d135e 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -5,11 +5,15 @@ #include #include #include +#include + +#include #include #include #include "common/detached_tasks.h" +#include "common/dynamic_library.h" #include "common/fs/path_util.h" #include "common/logging/backend.h" #include "common/logging/log.h" @@ -70,6 +74,29 @@ public: m_native_window = m_native_window_; } + void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, + const std::string& custom_driver_name, + const std::string& file_redirect_dir) { + void* handle{}; + + // Try to load a custom driver. + if (custom_driver_name.size()) { + handle = adrenotools_open_libvulkan( + RTLD_NOW, ADRENOTOOLS_DRIVER_CUSTOM | ADRENOTOOLS_DRIVER_FILE_REDIRECT, nullptr, + hook_lib_dir.c_str(), custom_driver_dir.c_str(), custom_driver_name.c_str(), + file_redirect_dir.c_str(), nullptr); + } + + // Try to load the system driver. + if (!handle) { + handle = adrenotools_open_libvulkan(RTLD_NOW, ADRENOTOOLS_DRIVER_FILE_REDIRECT, nullptr, + hook_lib_dir.c_str(), nullptr, nullptr, + file_redirect_dir.c_str(), nullptr); + } + + m_vulkan_library = std::make_shared(handle); + } + bool IsRunning() const { std::scoped_lock lock(m_mutex); return m_is_running; @@ -94,7 +121,8 @@ public: Config{}; // Create the render window. - m_window = std::make_unique(&m_input_subsystem, m_native_window); + m_window = std::make_unique(&m_input_subsystem, m_native_window, + m_vulkan_library); // Initialize system. m_system.SetShuttingDown(false); @@ -242,6 +270,9 @@ private: Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized}; bool m_is_running{}; + // GPU driver parameters + std::shared_ptr m_vulkan_library; + // Synchronization std::condition_variable_any m_cv; mutable std::mutex m_perf_stats_mutex; @@ -327,6 +358,14 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNIEnv* env, Common::FS::SetAppDirectory(GetJString(env, j_directory)); } +void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver( + JNIEnv* env, [[maybe_unused]] jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir, + jstring custom_driver_name, jstring file_redirect_dir) { + EmulationSession::GetInstance().InitializeGpuDriver( + GetJString(env, hook_lib_dir), GetJString(env, custom_driver_dir), + GetJString(env, custom_driver_name), GetJString(env, file_redirect_dir)); +} + jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env, [[maybe_unused]] jclass clazz) { Core::Crypto::KeyManager::Instance().ReloadKeys(); @@ -363,7 +402,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadButtonEvent([[maybe_unus [[maybe_unused]] jint j_device, jint j_button, jint action) { if (EmulationSession::GetInstance().IsRunning()) { - EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device,j_button, action != 0); + EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device, j_button, + action != 0); } return static_cast(true); } @@ -373,31 +413,33 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadJoystickEvent([[maybe_un jint j_device, jint stick_id, jfloat x, jfloat y) { if (EmulationSession::GetInstance().IsRunning()) { - EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device,stick_id, x, y); + EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device, stick_id, x, y); } return static_cast(true); } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent([[maybe_unused]] JNIEnv* env, - [[maybe_unused]] jclass clazz, jint j_device,jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y, - jfloat gyro_z, jfloat accel_x, jfloat accel_y, jfloat accel_z){ +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent( + [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint j_device, + jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y, jfloat gyro_z, jfloat accel_x, + jfloat accel_y, jfloat accel_z) { if (EmulationSession::GetInstance().IsRunning()) { - EmulationSession::GetInstance().Window().OnGamepadMotionEvent(j_device,delta_timestamp, gyro_x, gyro_y,gyro_z,accel_x,accel_y,accel_z); + EmulationSession::GetInstance().Window().OnGamepadMotionEvent( + j_device, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); } return static_cast(true); } void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchPressed([[maybe_unused]] JNIEnv* env, - [[maybe_unused]] jclass clazz, jint id, jfloat x, - jfloat y) { + [[maybe_unused]] jclass clazz, jint id, + jfloat x, jfloat y) { if (EmulationSession::GetInstance().IsRunning()) { EmulationSession::GetInstance().Window().OnTouchPressed(id, x, y); } } void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env, - [[maybe_unused]] jclass clazz, jint id, jfloat x, - jfloat y) { + [[maybe_unused]] jclass clazz, jint id, + jfloat x, jfloat y) { if (EmulationSession::GetInstance().IsRunning()) { EmulationSession::GetInstance().Window().OnTouchMoved(id, x, y); } diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index bbc783aa8..f799560e4 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -71,6 +71,11 @@ JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNI jclass clazz, jstring j_directory); +JNIEXPORT void JNICALL +Java_org_yuzu_yuzu_1emu_NativeLibrary_Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver( + JNIEnv* env, jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir, + jstring custom_driver_name, jstring file_redirect_dir); + JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env, jclass clazz); diff --git a/src/core/frontend/graphics_context.h b/src/core/frontend/graphics_context.h index 064b19a96..7554c1583 100644 --- a/src/core/frontend/graphics_context.h +++ b/src/core/frontend/graphics_context.h @@ -3,8 +3,9 @@ #pragma once -#include -#include +#include + +#include "common/dynamic_library.h" namespace Core::Frontend { @@ -24,16 +25,8 @@ public: /// Releases (dunno if this is the "right" word) the context from the caller thread virtual void DoneCurrent() {} - /// Parameters used to configure custom drivers (used by Android only) - struct CustomDriverParameters { - std::string hook_lib_dir; - std::string custom_driver_dir; - std::string custom_driver_name; - std::string file_redirect_dir; - }; - - /// Gets custom driver parameters configured by the frontend (used by Android only) - virtual std::optional GetCustomDriverParameters() { + /// Gets the GPU driver library (used by Android only) + virtual std::shared_ptr GetDriverLibrary() { return {}; } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index fbcf4c1d3..30dc69f13 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, std::unique_ptr context_) try : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), - cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()), - instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, + cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), + instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, Settings::values.renderer_debug.GetValue())), debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), surface(CreateSurface(instance, render_window.GetWindowInfo())), diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index f44367cb2..3c63a2004 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -63,7 +63,7 @@ private: Core::Memory::Memory& cpu_memory; Tegra::GPU& gpu; - Common::DynamicLibrary library; + std::shared_ptr library; vk::InstanceDispatch dld; vk::Instance instance; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 63e1c7d63..40cdf2fde 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -314,10 +314,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; const bool is_nvidia = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY; const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK; - const bool is_adreno = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; - const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; + const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; + const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP; - if ((is_mvk || is_adreno) && !is_suitable) { + if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) { LOG_WARNING(Render_Vulkan, "Unsuitable driver is MoltenVK, continuing anyway"); } else if (!is_suitable) { throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); @@ -362,14 +362,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR CollectToolingInfo(); #ifdef ANDROID - if (is_adreno) { + if (is_qualcomm) { must_emulate_scaled_formats = true; LOG_WARNING(Render_Vulkan, "Adreno drivers have broken VK_EXT_extended_dynamic_state"); extensions.extended_dynamic_state = false; loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - LOG_WARNING(Render_Vulkan, "Adreno drivers have a slow VK_KHR_push_descriptor implementation"); + LOG_WARNING(Render_Vulkan, + "Adreno drivers have a slow VK_KHR_push_descriptor implementation"); extensions.push_descriptor = false; loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); @@ -392,6 +393,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } } + const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; if (is_arm) { must_emulate_scaled_formats = true; @@ -513,7 +515,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); cant_blit_msaa = true; } - if (is_intel_anv || is_adreno) { + if (is_intel_anv || is_qualcomm) { LOG_WARNING(Render_Vulkan, "Driver does not support native BGR format"); must_emulate_bgr565 = true; } diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp index 4eb3913ee..9a7d369f3 100644 --- a/src/video_core/vulkan_common/vulkan_library.cpp +++ b/src/video_core/vulkan_common/vulkan_library.cpp @@ -10,29 +10,35 @@ namespace Vulkan { -Common::DynamicLibrary OpenLibrary() { +std::shared_ptr OpenLibrary( + [[maybe_unused]] Core::Frontend::GraphicsContext* context) { LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); - Common::DynamicLibrary library; +#ifdef ANDROID + // Android manages its Vulkan driver from the frontend. + return context->GetDriverLibrary(); +#else + auto library = std::make_shared(); #ifdef __APPLE__ // Check if a path to a specific Vulkan library has been specified. char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); - if (!libvulkan_env || !library.Open(libvulkan_env)) { + if (!libvulkan_env || !library->Open(libvulkan_env)) { // Use the libvulkan.dylib from the application bundle. const auto filename = Common::FS::GetBundleDirectory() / "Contents/Frameworks/libvulkan.dylib"; - void(library.Open(Common::FS::PathToUTF8String(filename).c_str())); + void(library->Open(Common::FS::PathToUTF8String(filename).c_str())); } #else std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); LOG_DEBUG(Render_Vulkan, "Trying Vulkan library: {}", filename); - if (!library.Open(filename.c_str())) { + if (!library->Open(filename.c_str())) { // Android devices may not have libvulkan.so.1, only libvulkan.so. filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); LOG_DEBUG(Render_Vulkan, "Trying Vulkan library (second attempt): {}", filename); - void(library.Open(filename.c_str())); + void(library->Open(filename.c_str())); } #endif return library; +#endif } } // namespace Vulkan diff --git a/src/video_core/vulkan_common/vulkan_library.h b/src/video_core/vulkan_common/vulkan_library.h index 364ca979b..e1734525e 100644 --- a/src/video_core/vulkan_common/vulkan_library.h +++ b/src/video_core/vulkan_common/vulkan_library.h @@ -3,10 +3,14 @@ #pragma once +#include + #include "common/dynamic_library.h" +#include "core/frontend/graphics_context.h" namespace Vulkan { -Common::DynamicLibrary OpenLibrary(); +std::shared_ptr OpenLibrary( + [[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr); } // namespace Vulkan diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index f316b598c..431585216 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -515,8 +515,8 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { auto wsi = QtCommon::GetWindowSystemInfo(window); vk::InstanceDispatch dld; - const Common::DynamicLibrary library = OpenLibrary(); - const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type); + const auto library = OpenLibrary(); + const vk::Instance instance = CreateInstance(*library, dld, VK_API_VERSION_1_1, wsi.type); const std::vector physical_devices = instance.EnumeratePhysicalDevices(); vk::SurfaceKHR surface = CreateSurface(instance, wsi); diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index 5e1f76339..6eefc94ed 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp @@ -25,9 +25,9 @@ void CheckVulkan() { // Just start the Vulkan loader, this will crash if something is wrong try { Vulkan::vk::InstanceDispatch dld; - const Common::DynamicLibrary library = Vulkan::OpenLibrary(); + const auto library = Vulkan::OpenLibrary(); const Vulkan::vk::Instance instance = - Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1); + Vulkan::CreateInstance(*library, dld, VK_API_VERSION_1_1); } catch (const Vulkan::vk::Exception& exception) { fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what()); -- cgit v1.2.3 From 8248d690935dbd2df8294c75360348a07a30afed Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 19 Feb 2023 02:19:21 -0800 Subject: android: vulkan: Implement adrenotools turbo mode. --- .../features/settings/ui/SettingsFragmentPresenter.java | 2 ++ .../yuzu/yuzu_emu/features/settings/utils/SettingsFile.java | 1 + src/android/app/src/main/jni/config.cpp | 5 ++++- src/android/app/src/main/jni/default_ini.h | 4 ++++ src/android/app/src/main/res/values/strings.xml | 2 ++ src/video_core/renderer_vulkan/vk_turbo_mode.cpp | 12 +++++++++++- src/video_core/vulkan_common/vulkan_device.cpp | 4 +++- 7 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.java index 71ae03ca1..f924a167d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.java @@ -160,12 +160,14 @@ public final class SettingsFragmentPresenter { Setting rendererAccuracy = rendererSection.getSetting(SettingsFile.KEY_RENDERER_ACCURACY); Setting rendererReolution = rendererSection.getSetting(SettingsFile.KEY_RENDERER_RESOLUTION); Setting rendererAspectRation = rendererSection.getSetting(SettingsFile.KEY_RENDERER_ASPECT_RATIO); + Setting rendererForceMaxClocks = rendererSection.getSetting(SettingsFile.KEY_RENDERER_FORCE_MAX_CLOCK); Setting rendererAsynchronousShaders = rendererSection.getSetting(SettingsFile.KEY_RENDERER_ASYNCHRONOUS_SHADERS); sl.add(new SingleChoiceSetting(SettingsFile.KEY_RENDERER_BACKEND, Settings.SECTION_RENDERER, R.string.renderer_api, 0, R.array.rendererApiNames, R.array.rendererApiValues, 1, rendererBackend)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_RENDERER_ACCURACY, Settings.SECTION_RENDERER, R.string.renderer_accuracy, 0, R.array.rendererAccuracyNames, R.array.rendererAccuracyValues, 1, rendererAccuracy)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_RENDERER_RESOLUTION, Settings.SECTION_RENDERER, R.string.renderer_resolution, 0, R.array.rendererResolutionNames, R.array.rendererResolutionValues, 2, rendererReolution)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_RENDERER_ASPECT_RATIO, Settings.SECTION_RENDERER, R.string.renderer_aspect_ratio, 0, R.array.rendererAspectRatioNames, R.array.rendererAspectRatioValues, 0, rendererAspectRation)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_RENDERER_FORCE_MAX_CLOCK, Settings.SECTION_RENDERER, R.string.renderer_force_max_clock, R.string.renderer_force_max_clock_description, true, rendererForceMaxClocks)); sl.add(new CheckBoxSetting(SettingsFile.KEY_RENDERER_ASYNCHRONOUS_SHADERS, Settings.SECTION_RENDERER, R.string.renderer_asynchronous_shaders, R.string.renderer_asynchronous_shaders_description, false, rendererAsynchronousShaders)); } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.java index 392c2e62d..12bc03ffa 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.java @@ -47,6 +47,7 @@ public final class SettingsFile { public static final String KEY_RENDERER_ASPECT_RATIO = "aspect_ratio"; public static final String KEY_RENDERER_ACCURACY = "gpu_accuracy"; public static final String KEY_RENDERER_ASYNCHRONOUS_SHADERS = "use_asynchronous_shaders"; + public static final String KEY_RENDERER_FORCE_MAX_CLOCK = "force_max_clock"; public static final String KEY_RENDERER_USE_SPEED_LIMIT = "use_speed_limit"; public static final String KEY_RENDERER_SPEED_LIMIT = "speed_limit"; // Audio diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 0a3cb9162..d197413b9 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -192,7 +192,6 @@ void Config::ReadValues() { // Renderer ReadSetting("Renderer", Settings::values.renderer_backend); - ReadSetting("Renderer", Settings::values.renderer_force_max_clock); ReadSetting("Renderer", Settings::values.renderer_debug); ReadSetting("Renderer", Settings::values.renderer_shader_feedback); ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); @@ -223,6 +222,10 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.bg_green); ReadSetting("Renderer", Settings::values.bg_blue); + // Enable force_max_clock by default on Android + Settings::values.renderer_force_max_clock = + config->GetBoolean("Renderer", "force_max_clock", true); + // Audio ReadSetting("Audio", Settings::values.sink_id); ReadSetting("Audio", Settings::values.audio_output_device_id); diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index eecda4756..25ec140de 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -247,6 +247,10 @@ cpuopt_unsafe_ignore_global_monitor = # 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null backend = +# Enable graphics API debugging mode. +# 0 (default): Disabled, 1: Enabled +force_max_clock = + # Enable graphics API debugging mode. # 0 (default): Disabled, 1: Enabled debug = diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 27749b287..bdaaa7650 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -29,6 +29,8 @@ Accuracy level Resolution Aspect Ratio + Force maximum clocks (Adreno only) + Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied). Use asynchronous shaders Compiles shaders asynchronously, which will reduce stutter but may introduce glitches. diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index db04943eb..29751e6b4 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp @@ -1,6 +1,10 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#ifdef ANDROID +#include +#endif + #include "common/literals.h" #include "video_core/host_shaders/vulkan_turbo_mode_comp_spv.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" @@ -144,6 +148,9 @@ void TurboMode::Run(std::stop_token stop_token) { auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()}; while (!stop_token.stop_requested()) { +#ifdef ANDROID + adrenotools_set_turbo(true); +#else // Reset the fence. fence.Reset(); @@ -209,7 +216,7 @@ void TurboMode::Run(std::stop_token stop_token) { // Wait for completion. fence.Wait(); - +#endif // Wait for the next graphics queue submission if necessary. std::unique_lock lk{m_submission_lock}; Common::CondvarWait(m_submission_cv, lk, stop_token, [this] { @@ -217,6 +224,9 @@ void TurboMode::Run(std::stop_token stop_token) { std::chrono::milliseconds{100}; }); } +#ifdef ANDROID + adrenotools_set_turbo(false); +#endif } } // namespace Vulkan diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 79686a176..70ee60a96 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -681,7 +681,9 @@ bool Device::ShouldBoostClocks() const { driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE || driver_id == VK_DRIVER_ID_MESA_RADV || driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY || driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS || - driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; + driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA || + driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || + driver_id == VK_DRIVER_ID_MESA_TURNIP; const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; -- cgit v1.2.3 From e26bd1421e3e2f01b4442b9edeb246d953e8dc4f Mon Sep 17 00:00:00 2001 From: liushuyu Date: Sat, 4 Mar 2023 00:16:20 -0700 Subject: video_core: fix clang-format errors --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 4 ++-- src/video_core/vulkan_common/vulkan_device.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index e506a8b30..48820b890 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -351,8 +351,8 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .has_broken_signed_operations = false, .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, .ignore_nan_fp_comparisons = false, - .has_broken_spirv_subgroup_mask_vector_extract_dynamic = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY - }; + .has_broken_spirv_subgroup_mask_vector_extract_dynamic = + driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY}; host_info = Shader::HostTranslateInfo{ .support_float16 = device.IsFloat16Supported(), .support_int64 = device.IsShaderInt64Supported(), diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 52455dbeb..06efa1a6c 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -682,8 +682,7 @@ bool Device::ShouldBoostClocks() const { driver_id == VK_DRIVER_ID_MESA_RADV || driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY || driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS || driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA || - driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || - driver_id == VK_DRIVER_ID_MESA_TURNIP; + driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP; const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; -- cgit v1.2.3 From 616cf70a801ccf7c2312118d163185a8d341e517 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 16 Mar 2023 11:56:51 -0400 Subject: build: only enable adrenotools on arm64 --- CMakeLists.txt | 16 ++++++++++++---- externals/CMakeLists.txt | 4 +++- src/android/app/build.gradle | 5 ++--- src/android/app/src/main/jni/CMakeLists.txt | 5 ++++- src/android/app/src/main/jni/native.cpp | 4 ++++ src/video_core/CMakeLists.txt | 2 +- src/video_core/renderer_vulkan/vk_turbo_mode.cpp | 6 +++--- src/video_core/vulkan_common/vulkan_device.cpp | 4 +++- src/video_core/vulkan_common/vulkan_library.cpp | 2 +- 9 files changed, 33 insertions(+), 15 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d25cc3a9..1771b063c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,12 +106,20 @@ endif() if (YUZU_USE_BUNDLED_VCPKG) if (ANDROID) - set(VCPKG_TARGET_TRIPLET "arm64-android") set(ENV{ANDROID_NDK_HOME} "${ANDROID_NDK}") - # this is to avoid CMake using the host pkg-config to find the host - # libraries when building for Android targets - set(PKG_CONFIG_EXECUTABLE "aarch64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE) list(APPEND VCPKG_MANIFEST_FEATURES "android") + + if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") + set(VCPKG_TARGET_TRIPLET "arm64-android") + # this is to avoid CMake using the host pkg-config to find the host + # libraries when building for Android targets + set(PKG_CONFIG_EXECUTABLE "aarch64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE) + elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") + set(VCPKG_TARGET_TRIPLET "x64-android") + set(PKG_CONFIG_EXECUTABLE "x86_64-none-linux-android-pkg-config" CACHE FILEPATH "" FORCE) + else() + message(FATAL_ERROR "Unsupported Android architecture ${CMAKE_ANDROID_ARCH_ABI}") + endif() endif() if (YUZU_TESTS) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 2bd7b457a..500eb21e3 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -149,5 +149,7 @@ add_library(stb stb/stb_dxt.cpp) target_include_directories(stb PUBLIC ./stb) if (ANDROID) - add_subdirectory(libadrenotools) + if (ARCHITECTURE_arm64) + add_subdirectory(libadrenotools) + endif() endif() diff --git a/src/android/app/build.gradle b/src/android/app/build.gradle index 8b621f5d5..7e2717b11 100644 --- a/src/android/app/build.gradle +++ b/src/android/app/build.gradle @@ -10,7 +10,6 @@ plugins { */ def autoVersion = (int) (((new Date().getTime() / 1000) - 1451606400) / 10) def buildType -def abiFilter = "arm64-v8a" //, "x86" android { namespace 'org.yuzu.yuzu_emu' @@ -44,7 +43,7 @@ android { targetSdkVersion 33 versionCode autoVersion versionName getVersion() - ndk.abiFilters abiFilter + ndk.abiFilters "arm64-v8a", "x86_64" } signingConfigs { @@ -115,7 +114,7 @@ android { "-DYUZU_USE_BUNDLED_VCPKG=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON" - abiFilters abiFilter + abiFilters "arm64-v8a", "x86_64" } } } diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index f80c166f4..21c27d4ee 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -13,6 +13,9 @@ add_library(yuzu-android SHARED set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) -target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics adrenotools log) +target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) +if (ARCHITECTURE_arm64) + target_link_libraries(yuzu-android PRIVATE adrenotools) +endif() set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} yuzu-android) diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 3cfbec87c..6e670e899 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -7,7 +7,9 @@ #include #include +#ifdef ARCHITECTURE_arm64 #include +#endif #include #include @@ -76,6 +78,7 @@ public: void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, const std::string& custom_driver_name, const std::string& file_redirect_dir) { +#ifdef ARCHITECTURE_arm64 void* handle{}; const char* file_redirect_dir_{}; int featureFlags{}; @@ -101,6 +104,7 @@ public: } m_vulkan_library = std::make_shared(handle); +#endif } bool IsRunning() const { diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 05aa5cfe2..94e3000ba 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -346,6 +346,6 @@ if (YUZU_ENABLE_LTO) set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) endif() -if (ANDROID) +if (ANDROID AND ARCHITECTURE_arm64) target_link_libraries(video_core PRIVATE adrenotools) endif() diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index 29751e6b4..22dbf272e 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#ifdef ANDROID +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) #include #endif @@ -148,7 +148,7 @@ void TurboMode::Run(std::stop_token stop_token) { auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()}; while (!stop_token.stop_requested()) { -#ifdef ANDROID +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) adrenotools_set_turbo(true); #else // Reset the fence. @@ -224,7 +224,7 @@ void TurboMode::Run(std::stop_token stop_token) { std::chrono::milliseconds{100}; }); } -#ifdef ANDROID +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) adrenotools_set_turbo(false); #endif } diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 06efa1a6c..9e2dee097 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -18,7 +18,7 @@ #include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_wrapper.h" -#ifdef ANDROID +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) #include #endif @@ -374,6 +374,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR extensions.push_descriptor = false; loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); +#ifdef ARCHITECTURE_arm64 // Patch the driver to enable BCn textures. const auto major = (properties.properties.driverVersion >> 24) << 2; const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU; @@ -391,6 +392,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } else { LOG_WARNING(Render_Vulkan, "Adreno driver can't be patched to enable BCn textures"); } +#endif // ARCHITECTURE_arm64 } const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp index 9a7d369f3..47f6f2a03 100644 --- a/src/video_core/vulkan_common/vulkan_library.cpp +++ b/src/video_core/vulkan_common/vulkan_library.cpp @@ -13,7 +13,7 @@ namespace Vulkan { std::shared_ptr OpenLibrary( [[maybe_unused]] Core::Frontend::GraphicsContext* context) { LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); -#ifdef ANDROID +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) // Android manages its Vulkan driver from the frontend. return context->GetDriverLibrary(); #else -- cgit v1.2.3 From ca4bf3844eb317c816f4b316967c7ae6697473d6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 2 May 2023 17:52:41 -0700 Subject: video_core: Enable support_descriptor_aliasing on Turnip, disable storage atomic otherwise. --- src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp | 10 ++++++++++ src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 6 +----- src/video_core/vulkan_common/vulkan_device.h | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 4b3043b65..0ce73f289 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -69,6 +69,11 @@ Id StorageAtomicU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& Id StorageAtomicU64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id), Id (Sirit::Module::*non_atomic_func)(Id, Id, Id)) { + if (!ctx.profile.support_descriptor_aliasing) { + LOG_WARNING(Shader_SPIRV, "Descriptor aliasing not supported, this cannot be atomic."); + return ctx.ConstantNull(ctx.U64); + } + if (ctx.profile.support_int64_atomics) { const Id pointer{StoragePointer(ctx, ctx.storage_types.U64, &StorageDefinitions::U64, binding, offset, sizeof(u64))}; @@ -86,6 +91,11 @@ Id StorageAtomicU64(EmitContext& ctx, const IR::Value& binding, const IR::Value& Id StorageAtomicU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value, Id (Sirit::Module::*non_atomic_func)(Id, Id, Id)) { + if (!ctx.profile.support_descriptor_aliasing) { + LOG_WARNING(Shader_SPIRV, "Descriptor aliasing not supported, this cannot be atomic."); + return ctx.ConstantNull(ctx.U32[2]); + } + LOG_WARNING(Shader_SPIRV, "Int64 atomics not supported, fallback to non-atomic"); const Id pointer{StoragePointer(ctx, ctx.storage_types.U32x2, &StorageDefinitions::U32x2, binding, offset, sizeof(u32[2]))}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 48820b890..9482e91b0 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -298,11 +298,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device profile = Shader::Profile{ .supported_spirv = device.SupportedSpirvVersion(), .unified_descriptor_binding = true, -#ifdef ANDROID - .support_descriptor_aliasing = false, -#else - .support_descriptor_aliasing = true, -#endif + .support_descriptor_aliasing = device.IsDescriptorAliasingSupported(), .support_int8 = device.IsInt8Supported(), .support_int16 = device.IsShaderInt16Supported(), .support_int64 = device.IsShaderInt64Supported(), diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index f9d8c47ba..3c9d11617 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -295,6 +295,11 @@ public: return features.features.textureCompressionASTC_LDR; } + /// Returns true if descriptor aliasing is natively supported. + bool IsDescriptorAliasingSupported() const { + return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; + } + /// Returns true if the device supports float16 natively. bool IsFloat16Supported() const { return features.shader_float16_int8.shaderFloat16; -- cgit v1.2.3 From 117bc2ae6c9683fd4530cfddb33b4ffc9419cff7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 May 2023 21:54:31 -0700 Subject: android: vulkan: Recreate surface after suspension & adapt to async. presentation. --- src/android/app/src/main/jni/config.cpp | 5 +--- .../app/src/main/jni/emu_window/emu_window.cpp | 7 +++--- .../app/src/main/jni/emu_window/emu_window.h | 3 --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 3 ++- .../renderer_vulkan/vk_present_manager.cpp | 28 ++++++++++++++++------ .../renderer_vulkan/vk_present_manager.h | 10 +++++--- src/video_core/renderer_vulkan/vk_swapchain.cpp | 5 ++-- src/video_core/renderer_vulkan/vk_swapchain.h | 4 ++-- 8 files changed, 39 insertions(+), 26 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 785133057..7a83fea42 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -217,6 +217,7 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.accelerate_astc); ReadSetting("Renderer", Settings::values.use_fast_gpu_time); ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); + ReadSetting("Renderer", Settings::values.async_presentation); // Use GPU accuracy normal by default on Android Settings::values.gpu_accuracy = static_cast(config->GetInteger( @@ -230,10 +231,6 @@ void Config::ReadValues() { Settings::values.renderer_force_max_clock = config->GetBoolean("Renderer", "force_max_clock", true); - // Enable asynchronous presentation by default on Android - Settings::values.async_presentation = - config->GetBoolean("Renderer", "async_presentation", true); - // Audio ReadSetting("Audio", Settings::values.sink_id); ReadSetting("Audio", Settings::values.audio_output_device_id); diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp index 2fdb68823..926bb30e8 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp @@ -8,7 +8,7 @@ #include "jni/emu_window/emu_window.h" void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { - m_render_window = surface; + window_info.render_surface = reinterpret_cast(surface); } void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { @@ -37,7 +37,7 @@ void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timesta float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z) { m_input_subsystem->GetVirtualGamepad()->SetMotionState( - player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); + player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); } void EmuWindow_Android::OnReadNfcTag(std::span data) { @@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste // Ensures that we emulate with the correct aspect ratio. UpdateCurrentFramebufferLayout(m_window_width, m_window_height); - m_host_window = surface; window_info.type = Core::Frontend::WindowSystemType::Android; - window_info.render_surface = reinterpret_cast(m_host_window); + window_info.render_surface = reinterpret_cast(surface); m_input_subsystem->Initialize(); } diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h index 2a0a72077..36d46eb51 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.h +++ b/src/android/app/src/main/jni/emu_window/emu_window.h @@ -54,9 +54,6 @@ public: private: InputCommon::InputSubsystem* m_input_subsystem{}; - ANativeWindow* m_render_window{}; - ANativeWindow* m_host_window{}; - float m_window_width{}; float m_window_height{}; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 30dc69f13..77128c6e2 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, state_tracker(), scheduler(device, state_tracker), swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, render_window.GetFramebufferLayout().height, false), - present_manager(render_window, device, memory_allocator, scheduler, swapchain), + present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, + surface), blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, scheduler, screen_info), rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index c49583013..77832720d 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -4,10 +4,12 @@ #include "common/microprofile.h" #include "common/settings.h" #include "common/thread.h" +#include "core/frontend/emu_window.h" #include "video_core/renderer_vulkan/vk_present_manager.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_swapchain.h" #include "video_core/vulkan_common/vulkan_device.h" +#include "video_core/vulkan_common/vulkan_surface.h" namespace Vulkan { @@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form } // Anonymous namespace -PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_, +PresentManager::PresentManager(const vk::Instance& instance_, + Core::Frontend::EmuWindow& render_window_, const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, - Swapchain& swapchain_) - : render_window{render_window_}, device{device_}, + Swapchain& swapchain_, vk::SurfaceKHR& surface_) + : instance{instance_}, render_window{render_window_}, device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, - blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}, + surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), + swapchain.GetImageViewFormat())}, use_present_thread{Settings::values.async_presentation.GetValue()}, - image_count{swapchain.GetImageCount()} { + image_count{swapchain.GetImageCount()}, last_render_surface{ + render_window_.GetWindowInfo().render_surface} { auto& dld = device.GetLogical(); cmdpool = dld.CreateCommandPool({ @@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) { MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); const auto recreate_swapchain = [&] { - swapchain.Create(frame->width, frame->height, frame->is_srgb); + swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); image_count = swapchain.GetImageCount(); }; +#ifdef ANDROID + // If the frontend recreated the surface, recreate the renderer surface and swapchain. + if (last_render_surface != render_window.GetWindowInfo().render_surface) { + last_render_surface = render_window.GetWindowInfo().render_surface; + surface = CreateSurface(instance, render_window.GetWindowInfo()); + recreate_swapchain(); + } +#endif + // If the size or colorspace of the incoming frames has changed, recreate the swapchain // to account for that. const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); @@ -454,4 +468,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) { swapchain.Present(render_semaphore); } -} // namespace Vulkan +} // namespace Vulkan \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 420a775e2..3cbfce4ed 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h @@ -37,8 +37,9 @@ struct Frame { class PresentManager { public: - PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device, - MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain); + PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, + const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, + Swapchain& swapchain, vk::SurfaceKHR& surface); ~PresentManager(); /// Returns the last used presentation frame @@ -60,11 +61,13 @@ private: void CopyToSwapchain(Frame* frame); private: + const vk::Instance& instance; Core::Frontend::EmuWindow& render_window; const Device& device; MemoryAllocator& memory_allocator; Scheduler& scheduler; Swapchain& swapchain; + vk::SurfaceKHR& surface; vk::CommandPool cmdpool; std::vector frames; std::queue present_queue; @@ -77,7 +80,8 @@ private: std::jthread present_thread; bool blit_supported; bool use_present_thread; - std::size_t image_count; + std::size_t image_count{}; + void* last_render_surface{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index e43a993f9..afcf34fba 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width_, u32 height_, bool srgb) : surface{surface_}, device{device_}, scheduler{scheduler_} { - Create(width_, height_, srgb); + Create(surface_, width_, height_, srgb); } Swapchain::~Swapchain() = default; -void Swapchain::Create(u32 width_, u32 height_, bool srgb) { +void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { is_outdated = false; is_suboptimal = false; width = width_; height = height_; + surface = surface_; const auto physical_device = device.GetPhysical(); const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index bf1ea7254..b8a1465a6 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -24,7 +24,7 @@ public: ~Swapchain(); /// Creates (or recreates) the swapchain with a given size. - void Create(u32 width, u32 height, bool srgb); + void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb); /// Acquires the next image in the swapchain, waits as needed. bool AcquireNextImage(); @@ -118,7 +118,7 @@ private: bool NeedsPresentModeUpdate() const; - const VkSurfaceKHR surface; + VkSurfaceKHR surface; const Device& device; Scheduler& scheduler; -- cgit v1.2.3 From 8dc7fe0c968ef110d987dea75bad30817035372c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 6 May 2023 00:40:10 -0700 Subject: android: video_core: Disable problematic compute shaders. - Fixes #104. --- src/android/app/src/main/jni/config.cpp | 4 +++- src/android/app/src/main/jni/default_ini.h | 2 +- src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 10 ++++++++-- src/video_core/renderer_vulkan/vk_buffer_cache.h | 2 +- src/video_core/vulkan_common/vulkan_device.h | 4 ++++ 5 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 7a83fea42..34aa1ee4c 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -214,7 +214,6 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.shader_backend); ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); ReadSetting("Renderer", Settings::values.nvdec_emulation); - ReadSetting("Renderer", Settings::values.accelerate_astc); ReadSetting("Renderer", Settings::values.use_fast_gpu_time); ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); ReadSetting("Renderer", Settings::values.async_presentation); @@ -227,6 +226,9 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.bg_green); ReadSetting("Renderer", Settings::values.bg_blue); + // Disable ASTC compute by default on Android + Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false); + // Enable force_max_clock by default on Android Settings::values.renderer_force_max_clock = config->GetBoolean("Renderer", "force_max_clock", true); diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index d6bf458a6..da541851e 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -333,7 +333,7 @@ use_asynchronous_shaders = nvdec_emulation = # Accelerate ASTC texture decoding. -# 0: Off, 1 (default): On +# 0 (default): Off, 1: On accelerate_astc = # Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 9627eb129..daa128399 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -303,9 +303,13 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m DescriptorPool& descriptor_pool) : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, - uint8_pass(device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue), quad_index_pass(device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue) { + if (device.GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { + // TODO: FixMe: Uint8Pass compute shader does not build on some Qualcomm drivers. + uint8_pass = std::make_unique(device, scheduler, descriptor_pool, staging_pool, + compute_pass_descriptor_queue); + } quad_array_index_buffer = std::make_shared(device_, memory_allocator_, scheduler_, staging_pool_); quad_strip_index_buffer = std::make_shared(device_, memory_allocator_, @@ -442,7 +446,9 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat topology == PrimitiveTopology::QuadStrip); } else if (vk_index_type == VK_INDEX_TYPE_UINT8_EXT && !device.IsExtIndexTypeUint8Supported()) { vk_index_type = VK_INDEX_TYPE_UINT16; - std::tie(vk_buffer, vk_offset) = uint8_pass.Assemble(num_indices, buffer, offset); + if (uint8_pass) { + std::tie(vk_buffer, vk_offset) = uint8_pass->Assemble(num_indices, buffer, offset); + } } if (vk_buffer == VK_NULL_HANDLE) { // Vulkan doesn't support null index buffers. Replace it with our own null buffer. diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 5e9602905..794dd0758 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -139,7 +139,7 @@ private: vk::Buffer null_buffer; MemoryCommit null_buffer_commit; - Uint8Pass uint8_pass; + std::unique_ptr uint8_pass; QuadIndexedPass quad_index_pass; }; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 3c9d11617..b692b4be4 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -500,6 +500,10 @@ public: } bool HasTimelineSemaphore() const { + if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { + // Timeline semaphores do not work properly on all Qualcomm drivers. + return false; + } return features.timeline_semaphore.timelineSemaphore; } -- cgit v1.2.3 From befd4772799b5e0d2939a91e79f6b123c320e77d Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 5 May 2023 18:00:00 -0700 Subject: android: video_core: Disable some problematic things on GPU Normal. --- src/video_core/engines/maxwell_3d.cpp | 12 ++++++++++++ src/video_core/renderer_vulkan/vk_rasterizer.cpp | 14 ++++++++++++++ src/video_core/renderer_vulkan/vk_scheduler.cpp | 14 ++++++++++++++ 3 files changed, 40 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 2f986097f..62d70e9f3 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -593,6 +593,12 @@ void Maxwell3D::ProcessQueryCondition() { } void Maxwell3D::ProcessCounterReset() { +#if ANDROID + if (!Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + return; + } +#endif switch (regs.clear_report_value) { case Regs::ClearReport::ZPassPixelCount: rasterizer->ResetCounter(QueryType::SamplesPassed); @@ -614,6 +620,12 @@ std::optional Maxwell3D::GetQueryResult() { case Regs::ReportSemaphore::Report::Payload: return regs.report_semaphore.payload; case Regs::ReportSemaphore::Report::ZPassPixelCount64: +#if ANDROID + if (!Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + return 120; + } +#endif // Deferred. rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed, system.GPU().GetTicks()); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 8d3a9736b..4f2346a50 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -188,7 +188,14 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { FlushWork(); gpu_memory->FlushCaching(); +#if ANDROID + if (Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + query_cache.UpdateCounters(); + } +#else query_cache.UpdateCounters(); +#endif GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()}; if (!pipeline) { @@ -272,7 +279,14 @@ void RasterizerVulkan::DrawTexture() { SCOPE_EXIT({ gpu.TickWork(); }); FlushWork(); +#if ANDROID + if (Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + query_cache.UpdateCounters(); + } +#else query_cache.UpdateCounters(); +#endif texture_cache.SynchronizeGraphicsDescriptors(); texture_cache.UpdateRenderTargets(false); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 80455ec08..17ef61147 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -239,7 +239,14 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se void Scheduler::AllocateNewContext() { // Enable counters once again. These are disabled when a command buffer is finished. if (query_cache) { +#if ANDROID + if (Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + query_cache->UpdateCounters(); + } +#else query_cache->UpdateCounters(); +#endif } } @@ -250,7 +257,14 @@ void Scheduler::InvalidateState() { } void Scheduler::EndPendingOperations() { +#if ANDROID + if (Settings::IsGPULevelHigh()) { + // This is problematic on Android, disable on GPU Normal. + query_cache->DisableStreams(); + } +#else query_cache->DisableStreams(); +#endif EndRenderPass(); } -- cgit v1.2.3 From f0ed20c8a26fb95882fa6a2224ea2ad4efa473c4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 24 May 2023 21:29:29 -0700 Subject: android: GPU: Enable async presentation, increase frames in flight. --- src/android/app/src/main/jni/config.cpp | 4 +++- src/video_core/renderer_vulkan/vk_update_descriptor.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index d28f955df..b3aa9071b 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -215,7 +215,6 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.nvdec_emulation); ReadSetting("Renderer", Settings::values.use_fast_gpu_time); ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); - ReadSetting("Renderer", Settings::values.async_presentation); // Use GPU accuracy normal by default on Android Settings::values.gpu_accuracy = static_cast(config->GetInteger( @@ -235,6 +234,9 @@ void Config::ReadValues() { // Disable ASTC compute by default on Android Settings::values.accelerate_astc = config->GetBoolean("Renderer", "accelerate_astc", false); + // Enable asynchronous presentation by default on Android + Settings::values.async_presentation = config->GetBoolean("Renderer", "async_presentation", true); + // Enable force_max_clock by default on Android Settings::values.renderer_force_max_clock = config->GetBoolean("Renderer", "force_max_clock", true); diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index 310fb551a..e77b576ec 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h @@ -31,7 +31,7 @@ struct DescriptorUpdateEntry { class UpdateDescriptorQueue final { // This should be plenty for the vast majority of cases. Most desktop platforms only // provide up to 3 swapchain images. - static constexpr size_t FRAMES_IN_FLIGHT = 5; + static constexpr size_t FRAMES_IN_FLIGHT = 7; static constexpr size_t FRAME_PAYLOAD_SIZE = 0x20000; static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT; -- cgit v1.2.3 From cf9f4f67ddf5869a99a231092d035b2bf4e2a2f0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 26 May 2023 22:19:36 -0700 Subject: video_core: vk_rasterizer: Decrease draw dispatch count for Android. --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 4f2346a50..84e3a30cc 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -757,7 +757,11 @@ void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_load } void RasterizerVulkan::FlushWork() { +#ifdef ANDROID + static constexpr u32 DRAWS_TO_DISPATCH = 1024; +#else static constexpr u32 DRAWS_TO_DISPATCH = 4096; +#endif // ANDROID // Only check multiples of 8 draws static_assert(DRAWS_TO_DISPATCH % 8 == 0); -- cgit v1.2.3 From 057117f0096a47b07f9070d48a0dbd952ab0522e Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Jun 2023 17:57:49 -0700 Subject: android: Fix presentation layout on foldable and tablet devices. --- .../yuzu/yuzu_emu/activities/EmulationActivity.kt | 24 ++++++++++ .../features/settings/ui/SettingsActivity.kt | 6 --- .../java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt | 10 ++-- src/android/app/src/main/jni/native.cpp | 21 +++++++-- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 55 ++++++++++++++++++---- 5 files changed, 94 insertions(+), 22 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index abeb01995..81474b824 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -7,6 +7,7 @@ import android.app.Activity import android.content.Context import android.content.DialogInterface import android.content.Intent +import android.content.res.Configuration import android.graphics.Rect import android.hardware.Sensor import android.hardware.SensorEvent @@ -31,6 +32,7 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings import org.yuzu.yuzu_emu.fragments.EmulationFragment import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.utils.ControllerMappingHelper +import org.yuzu.yuzu_emu.utils.EmulationMenuSettings import org.yuzu.yuzu_emu.utils.ForegroundService import org.yuzu.yuzu_emu.utils.InputHandler import org.yuzu.yuzu_emu.utils.NfcReader @@ -128,6 +130,11 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { super.onResume() nfcReader.startScanning() startMotionSensorListener() + + NativeLibrary.notifyOrientationChange( + EmulationMenuSettings.landscapeScreenLayout, + getAdjustedRotation() + ) } override fun onPause() { @@ -233,6 +240,23 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { override fun onAccuracyChanged(sensor: Sensor, i: Int) {} + private fun getAdjustedRotation():Int { + val rotation = windowManager.defaultDisplay.rotation; + val config: Configuration = resources.configuration + + if ((config.screenLayout and Configuration.SCREENLAYOUT_LONG_YES) != 0 || + (config.screenLayout and Configuration.SCREENLAYOUT_LONG_NO) == 0) { + return rotation; + } + when (rotation) { + Surface.ROTATION_0 -> return Surface.ROTATION_90; + Surface.ROTATION_90 -> return Surface.ROTATION_0; + Surface.ROTATION_180 -> return Surface.ROTATION_270; + Surface.ROTATION_270 -> return Surface.ROTATION_180; + } + return rotation; + } + private fun restoreState(savedInstanceState: Bundle) { game = savedInstanceState.parcelable(EXTRA_SELECTED_GAME)!! } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt index 783122860..72e2cce2a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt @@ -118,12 +118,6 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView { override fun onStop() { super.onStop() presenter.onStop(isFinishing) - - // Update framebuffer layout when closing the settings - NativeLibrary.notifyOrientationChange( - EmulationMenuSettings.landscapeScreenLayout, - windowManager.defaultDisplay.rotation - ) } override fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt index 693e70973..c9f5797ac 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt @@ -767,10 +767,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context var cutoutBottom = 0 val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - maxY = - if (insets.boundingRectTop.bottom != 0) insets.boundingRectTop.bottom.toFloat() else maxY - maxX = - if (insets.boundingRectRight.left != 0) insets.boundingRectRight.left.toFloat() else maxX + if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2) + insets.boundingRectTop.bottom.toFloat() else maxY + if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2) + insets.boundingRectRight.left.toFloat() else maxX + minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom @@ -778,7 +779,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom } - // This makes sure that if we have an inset on one side of the screen, we mirror it on // the other side. Since removing space from one of the max values messes with the scale, // we also have to account for it using our min values. diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index bbe6abdb0..d503ef61d 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -89,8 +89,16 @@ public: return m_native_window; } - void SetNativeWindow(ANativeWindow* m_native_window_) { - m_native_window = m_native_window_; + void SetNativeWindow(ANativeWindow* native_window) { + m_native_window = native_window; + } + + u32 ScreenRotation() const { + return m_screen_rotation; + } + + void SetScreenRotation(u32 screen_rotation) { + m_screen_rotation = screen_rotation; } void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, @@ -379,6 +387,7 @@ private: // Window management std::unique_ptr m_window; ANativeWindow* m_native_window{}; + u32 m_screen_rotation{}; // Core emulation Core::System m_system; @@ -404,6 +413,10 @@ private: } // Anonymous namespace +u32 GetAndroidScreenRotation() { + return EmulationSession::GetInstance().ScreenRotation(); +} + static Core::SystemResultStatus RunEmulation(const std::string& filepath) { Common::Log::Initialize(); Common::Log::SetColorConsoleBackendEnabled(true); @@ -450,7 +463,9 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env, void Java_org_yuzu_yuzu_1emu_NativeLibrary_notifyOrientationChange(JNIEnv* env, [[maybe_unused]] jclass clazz, jint layout_option, - jint rotation) {} + jint rotation) { + return EmulationSession::GetInstance().SetScreenRotation(static_cast(rotation)); +} void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, [[maybe_unused]] jclass clazz, diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index e4c581a28..7cdde992b 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -37,6 +37,10 @@ #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#ifdef ANDROID +extern u32 GetAndroidScreenRotation(); +#endif + namespace Vulkan { namespace { @@ -74,23 +78,58 @@ struct ScreenRectVertex { } }; -constexpr std::array MakeOrthographicMatrix(f32 width, f32 height) { - // clang-format off #ifdef ANDROID - // Android renders in portrait, so rotate the matrix. - return { 0.f, 2.f / width, 0.f, 0.f, - -2.f / height, 0.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 1.f, -1.f, 0.f, 1.f}; + +std::array MakeOrthographicMatrix(f32 width, f32 height) { + constexpr u32 ROTATION_0 = 0; + constexpr u32 ROTATION_90 = 1; + constexpr u32 ROTATION_180 = 2; + constexpr u32 ROTATION_270 = 3; + + // clang-format off + switch (GetAndroidScreenRotation()) { + case ROTATION_0: + // Desktop + return { 2.f / width, 0.f, 0.f, 0.f, + 0.f, 2.f / height, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, -1.f, 0.f, 1.f}; + case ROTATION_180: + // Reverse desktop + return {-2.f / width, 0.f, 0.f, 0.f, + 0.f, -2.f / height, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 1.f, 1.f, 0.f, 1.f}; + case ROTATION_270: + // Reverse landscape + return { 0.f, -2.f / width, 0.f, 0.f, + 2.f / height, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, 1.f, 0.f, 1.f}; + case ROTATION_90: + default: + // Landscape + return { 0.f, 2.f / width, 0.f, 0.f, + -2.f / height, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 1.f, -1.f, 0.f, 1.f}; + } + // clang-format on +} + #else + +std::array MakeOrthographicMatrix(f32 width, f32 height) { + // clang-format off return { 2.f / width, 0.f, 0.f, 0.f, 0.f, 2.f / height, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, -1.f, -1.f, 0.f, 1.f}; -#endif // ANDROID // clang-format on } +#endif + u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { using namespace VideoCore::Surface; return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); -- cgit v1.2.3 From 098e2c4077f62890f83c0785e858080e9e18296c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Jun 2023 20:07:18 -0700 Subject: android: renderer_vulkan: Fix crash with surface recreation. --- src/android/app/src/main/jni/native.cpp | 1 + src/video_core/renderer_base.h | 3 +++ src/video_core/renderer_vulkan/renderer_vulkan.h | 4 ++++ .../renderer_vulkan/vk_present_manager.cpp | 24 +++++++++++++++++++++- .../renderer_vulkan/vk_present_manager.h | 5 +++++ 5 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index d503ef61d..b87e04b3d 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -148,6 +148,7 @@ public: return; } m_window->OnSurfaceChanged(m_native_window); + m_system.Renderer().NotifySurfaceChanged(); } Core::SystemResultStatus InitializeEmulation(const std::string& filepath) { diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 78ea5208b..3e12a8813 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -89,6 +89,9 @@ public: void RequestScreenshot(void* data, std::function callback, const Layout::FramebufferLayout& layout); + /// This is called to notify the rendering backend of a surface change + virtual void NotifySurfaceChanged() {} + protected: Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. std::unique_ptr context; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 3c63a2004..b2e8cbd1b 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -54,6 +54,10 @@ public: return device.GetDriverName(); } + void NotifySurfaceChanged() override { + present_manager.NotifySurfaceChanged(); + } + private: void Report() const; diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 77832720d..dc42982e9 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -291,6 +291,13 @@ void PresentManager::PresentThread(std::stop_token token) { } } +void PresentManager::NotifySurfaceChanged() { +#ifdef ANDROID + std::scoped_lock lock{recreate_surface_mutex}; + recreate_surface_cv.notify_one(); +#endif +} + void PresentManager::CopyToSwapchain(Frame* frame) { MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); @@ -299,7 +306,22 @@ void PresentManager::CopyToSwapchain(Frame* frame) { image_count = swapchain.GetImageCount(); }; + const auto needs_recreation = [&] { + if (last_render_surface != render_window.GetWindowInfo().render_surface) { + return true; + } + if (swapchain.NeedsRecreation(frame->is_srgb)) { + return true; + } + return false; + }; + #ifdef ANDROID + std::unique_lock lock{recreate_surface_mutex}; + + recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400), + [&]() { return !needs_recreation(); }); + // If the frontend recreated the surface, recreate the renderer surface and swapchain. if (last_render_surface != render_window.GetWindowInfo().render_surface) { last_render_surface = render_window.GetWindowInfo().render_surface; @@ -450,7 +472,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) { // Submit the image copy/blit to the swapchain { - std::scoped_lock lock{scheduler.submit_mutex}; + std::scoped_lock submit_lock{scheduler.submit_mutex}; switch (const VkResult result = device.GetGraphicsQueue().Submit(submit_info, *frame->present_done)) { case VK_SUCCESS: diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 3cbfce4ed..4ac2e2395 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h @@ -55,6 +55,9 @@ public: /// Waits for the present thread to finish presenting all queued frames. void WaitPresent(); + /// This is called to notify the rendering backend of a surface change + void NotifySurfaceChanged(); + private: void PresentThread(std::stop_token token); @@ -74,7 +77,9 @@ private: std::queue free_queue; std::condition_variable_any frame_cv; std::condition_variable free_cv; + std::condition_variable recreate_surface_cv; std::mutex swapchain_mutex; + std::mutex recreate_surface_mutex; std::mutex queue_mutex; std::mutex free_mutex; std::jthread present_thread; -- cgit v1.2.3 From df70fdc95b1f1aea81517398c28e6be38e585747 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Jun 2023 20:08:38 -0700 Subject: android: vk_turbo_mode: Remove unnecessary device recreation. - Fixes a rare crash. --- src/video_core/renderer_vulkan/vk_turbo_mode.cpp | 11 +++++++++-- src/video_core/renderer_vulkan/vk_turbo_mode.h | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index 22dbf272e..a802d3c49 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp @@ -17,7 +17,10 @@ namespace Vulkan { using namespace Common::Literals; TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) - : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} { +#ifndef ANDROID + : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} +#endif +{ { std::scoped_lock lk{m_submission_lock}; m_submission_time = std::chrono::steady_clock::now(); @@ -34,6 +37,7 @@ void TurboMode::QueueSubmitted() { } void TurboMode::Run(std::stop_token stop_token) { +#ifndef ANDROID auto& dld = m_device.GetLogical(); // Allocate buffer. 2MiB should be sufficient. @@ -146,10 +150,13 @@ void TurboMode::Run(std::stop_token stop_token) { // Create a single command buffer. auto cmdbufs = command_pool.Allocate(1, VK_COMMAND_BUFFER_LEVEL_PRIMARY); auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()}; +#endif while (!stop_token.stop_requested()) { -#if defined(ANDROID) && defined(ARCHITECTURE_arm64) +#ifdef ANDROID +#ifdef ARCHITECTURE_arm64 adrenotools_set_turbo(true); +#endif #else // Reset the fence. fence.Reset(); diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.h b/src/video_core/renderer_vulkan/vk_turbo_mode.h index 99b5ac50b..9341c9867 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.h +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.h @@ -23,8 +23,10 @@ public: private: void Run(std::stop_token stop_token); +#ifndef ANDROID Device m_device; MemoryAllocator m_allocator; +#endif std::mutex m_submission_lock; std::condition_variable_any m_submission_cv; std::chrono::time_point m_submission_time{}; -- cgit v1.2.3 From db6737f2ba82c7757c189a26114747b8a59322eb Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Jun 2023 21:43:22 -0700 Subject: android: vk_presentation_manager: Fix unusued needs_recreation. --- src/video_core/renderer_vulkan/vk_present_manager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index dc42982e9..10ace0420 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -306,6 +306,9 @@ void PresentManager::CopyToSwapchain(Frame* frame) { image_count = swapchain.GetImageCount(); }; +#ifdef ANDROID + std::unique_lock lock{recreate_surface_mutex}; + const auto needs_recreation = [&] { if (last_render_surface != render_window.GetWindowInfo().render_surface) { return true; @@ -316,9 +319,6 @@ void PresentManager::CopyToSwapchain(Frame* frame) { return false; }; -#ifdef ANDROID - std::unique_lock lock{recreate_surface_mutex}; - recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400), [&]() { return !needs_recreation(); }); -- cgit v1.2.3