early-access version 3626
This commit is contained in:
@@ -281,7 +281,7 @@ create_target_directory_groups(video_core)
|
||||
target_link_libraries(video_core PUBLIC common core)
|
||||
target_link_libraries(video_core PUBLIC glad shader_recompiler stb)
|
||||
|
||||
if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32)
|
||||
if (YUZU_USE_BUNDLED_FFMPEG AND NOT (WIN32 OR ANDROID))
|
||||
add_dependencies(video_core ffmpeg-build)
|
||||
endif()
|
||||
|
||||
@@ -345,3 +345,7 @@ endif()
|
||||
if (YUZU_ENABLE_LTO)
|
||||
set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
||||
if (ANDROID AND ARCHITECTURE_arm64)
|
||||
target_link_libraries(video_core PRIVATE adrenotools)
|
||||
endif()
|
||||
|
@@ -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<u64> 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());
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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 {
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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"
|
||||
@@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
||||
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> 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())),
|
||||
@@ -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,
|
||||
|
@@ -63,7 +63,7 @@ private:
|
||||
Core::Memory::Memory& cpu_memory;
|
||||
Tegra::GPU& gpu;
|
||||
|
||||
Common::DynamicLibrary library;
|
||||
std::shared_ptr<Common::DynamicLibrary> library;
|
||||
vk::InstanceDispatch dld;
|
||||
|
||||
vk::Instance instance;
|
||||
|
@@ -76,10 +76,18 @@ struct ScreenRectVertex {
|
||||
|
||||
constexpr std::array<f32, 4 * 4> 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
|
||||
}
|
||||
|
||||
@@ -441,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();
|
||||
}
|
||||
|
@@ -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<Uint8Pass>(device, scheduler, descriptor_pool, staging_pool,
|
||||
compute_pass_descriptor_queue);
|
||||
}
|
||||
quad_array_index_buffer = std::make_shared<QuadArrayIndexBuffer>(device_, memory_allocator_,
|
||||
scheduler_, staging_pool_);
|
||||
quad_strip_index_buffer = std::make_shared<QuadStripIndexBuffer>(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.
|
||||
|
@@ -139,7 +139,7 @@ private:
|
||||
vk::Buffer null_buffer;
|
||||
MemoryCommit null_buffer_commit;
|
||||
|
||||
Uint8Pass uint8_pass;
|
||||
std::unique_ptr<Uint8Pass> uint8_pass;
|
||||
QuadIndexedPass quad_index_pass;
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
@@ -286,14 +288,17 @@ 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()};
|
||||
profile = Shader::Profile{
|
||||
.supported_spirv = device.SupportedSpirvVersion(),
|
||||
.unified_descriptor_binding = true,
|
||||
.support_descriptor_aliasing = true,
|
||||
.support_descriptor_aliasing = device.IsDescriptorAliasingSupported(),
|
||||
.support_int8 = device.IsInt8Supported(),
|
||||
.support_int16 = device.IsShaderInt16Supported(),
|
||||
.support_int64 = device.IsShaderInt64Supported(),
|
||||
@@ -324,6 +329,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(),
|
||||
|
||||
@@ -341,7 +347,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};
|
||||
host_info = Shader::HostTranslateInfo{
|
||||
.support_float16 = device.IsFloat16Supported(),
|
||||
.support_int64 = device.IsShaderInt64Supported(),
|
||||
|
@@ -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
|
@@ -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<Frame> frames;
|
||||
std::queue<Frame*> 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
|
||||
|
@@ -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);
|
||||
@@ -743,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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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)};
|
||||
@@ -266,7 +267,12 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
|
||||
|
||||
images = swapchain.GetImages();
|
||||
image_count = static_cast<u32>(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() {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -1,6 +1,10 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
#include <adrenotools/driver.h>
|
||||
#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()) {
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
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};
|
||||
});
|
||||
}
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
adrenotools_set_turbo(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -13,11 +13,39 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||
[[maybe_unused]] void* user_data) {
|
||||
// Skip logging known false-positive validation errors
|
||||
switch (static_cast<u32>(data->messageIdNumber)) {
|
||||
#ifdef ANDROID
|
||||
case 0xbf9cf353u: // VUID-vkCmdBindVertexBuffers2-pBuffers-04111
|
||||
// The below are due to incorrect reporting of extendedDynamicState
|
||||
case 0x1093bebbu: // VUID-vkCmdSetCullMode-None-03384
|
||||
case 0x9215850fu: // VUID-vkCmdSetDepthTestEnable-None-03352
|
||||
case 0x86bf18dcu: // VUID-vkCmdSetDepthWriteEnable-None-03354
|
||||
case 0x0792ad08u: // VUID-vkCmdSetStencilOp-None-03351
|
||||
case 0x93e1ba4eu: // VUID-vkCmdSetFrontFace-None-03383
|
||||
case 0xac9c13c5u: // VUID-vkCmdSetStencilTestEnable-None-03350
|
||||
case 0xc9a2001bu: // VUID-vkCmdSetDepthBoundsTestEnable-None-03349
|
||||
case 0x8b7159a7u: // VUID-vkCmdSetDepthCompareOp-None-03353
|
||||
// The below are due to incorrect reporting of extendedDynamicState2
|
||||
case 0xb13c8036u: // VUID-vkCmdSetDepthBiasEnable-None-04872
|
||||
case 0xdff2e5c1u: // VUID-vkCmdSetRasterizerDiscardEnable-None-04871
|
||||
case 0x0cc85f41u: // VUID-vkCmdSetPrimitiveRestartEnable-None-04866
|
||||
case 0x01257b492: // VUID-vkCmdSetLogicOpEXT-None-0486
|
||||
// The below are due to incorrect reporting of vertexInputDynamicState
|
||||
case 0x398e0dabu: // VUID-vkCmdSetVertexInputEXT-None-04790
|
||||
// The below are due to incorrect reporting of extendedDynamicState3
|
||||
case 0x970c11a5u: // VUID-vkCmdSetColorWriteMaskEXT-extendedDynamicState3ColorWriteMask-07364
|
||||
case 0x6b453f78u: // VUID-vkCmdSetColorBlendEnableEXT-extendedDynamicState3ColorBlendEnable-07355
|
||||
case 0xf66469d0u: // VUID-vkCmdSetColorBlendEquationEXT-extendedDynamicState3ColorBlendEquation-07356
|
||||
case 0x1d43405eu: // VUID-vkCmdSetLogicOpEnableEXT-extendedDynamicState3LogicOpEnable-07365
|
||||
case 0x638462e8u: // VUID-vkCmdSetDepthClampEnableEXT-extendedDynamicState3DepthClampEnable-07448
|
||||
// Misc
|
||||
case 0xe0a2da61u: // VUID-vkCmdDrawIndexed-format-07753
|
||||
#else
|
||||
case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter
|
||||
case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0])
|
||||
case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related
|
||||
case 0x1608dec0u: // Image layout in vkUpdateDescriptorSet doesn't match descriptor use
|
||||
case 0x55362756u: // Descriptor binding and framebuffer attachment overlap
|
||||
#endif
|
||||
return VK_FALSE;
|
||||
default:
|
||||
break;
|
||||
|
@@ -18,6 +18,10 @@
|
||||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
#include <adrenotools/bcenabler.h>
|
||||
#endif
|
||||
|
||||
namespace Vulkan {
|
||||
using namespace Common::Literals;
|
||||
namespace {
|
||||
@@ -262,6 +266,32 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
|
||||
return format_properties;
|
||||
}
|
||||
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
void OverrideBcnFormats(std::unordered_map<VkFormat, VkFormatProperties>& format_properties) {
|
||||
// These properties are extracted from Adreno driver 512.687.0
|
||||
constexpr VkFormatFeatureFlags tiling_features{
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_TRANSFER_DST_BIT};
|
||||
|
||||
constexpr VkFormatFeatureFlags buffer_features{VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT};
|
||||
|
||||
static constexpr std::array bcn_formats{
|
||||
VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, VK_FORMAT_BC2_SRGB_BLOCK,
|
||||
VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK,
|
||||
VK_FORMAT_BC4_SNORM_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC5_SNORM_BLOCK,
|
||||
VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC6H_UFLOAT_BLOCK,
|
||||
VK_FORMAT_BC7_SRGB_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK,
|
||||
};
|
||||
|
||||
for (const auto format : bcn_formats) {
|
||||
format_properties[format].linearTilingFeatures = tiling_features;
|
||||
format_properties[format].optimalTilingFeatures = tiling_features;
|
||||
format_properties[format].bufferFeatures = buffer_features;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
|
||||
const std::set<std::string, std::less<>>& exts) {
|
||||
if (exts.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
|
||||
@@ -302,6 +332,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
const bool is_suitable = GetSuitability(surface != nullptr);
|
||||
|
||||
const VkDriverId driver_id = properties.driver.driverID;
|
||||
const auto device_id = properties.properties.deviceID;
|
||||
const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV;
|
||||
const bool is_amd_driver =
|
||||
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
|
||||
@@ -310,9 +341,12 @@ 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_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
|
||||
const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP;
|
||||
const bool is_s8gen2 = device_id == 0x43050a01;
|
||||
|
||||
if (is_mvk && !is_suitable) {
|
||||
LOG_WARNING(Render_Vulkan, "Unsuitable driver is MoltenVK, continuing anyway");
|
||||
if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) {
|
||||
LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway");
|
||||
} else if (!is_suitable) {
|
||||
throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
}
|
||||
@@ -355,6 +389,59 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
CollectPhysicalMemoryInfo();
|
||||
CollectToolingInfo();
|
||||
|
||||
#ifdef ANDROID
|
||||
if (is_qualcomm || is_turnip) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
|
||||
extensions.custom_border_color = false;
|
||||
loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (is_qualcomm) {
|
||||
must_emulate_scaled_formats = true;
|
||||
|
||||
LOG_WARNING(Render_Vulkan, "Qualcomm 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,
|
||||
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
||||
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;
|
||||
const auto vendor = properties.properties.vendorID;
|
||||
const auto patch_status = adrenotools_get_bcn_type(major, minor, vendor);
|
||||
|
||||
if (patch_status == ADRENOTOOLS_BCN_PATCH) {
|
||||
LOG_INFO(Render_Vulkan, "Patching Adreno driver to support BCn texture formats");
|
||||
if (adrenotools_patch_bcn(
|
||||
reinterpret_cast<void*>(dld.vkGetPhysicalDeviceFormatProperties))) {
|
||||
OverrideBcnFormats(format_properties);
|
||||
} else {
|
||||
LOG_ERROR(Render_Vulkan, "Patch failed! Driver code may now crash");
|
||||
}
|
||||
} else if (patch_status == ADRENOTOOLS_BCN_BLOB) {
|
||||
LOG_INFO(Render_Vulkan, "Adreno driver supports BCn textures without patches");
|
||||
} 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;
|
||||
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);
|
||||
}
|
||||
#endif // ANDROID
|
||||
|
||||
if (is_nvidia) {
|
||||
const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff;
|
||||
const auto arch = GetNvidiaArchitecture(physical, supported_extensions);
|
||||
@@ -388,7 +475,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state2 && is_radv) {
|
||||
if (extensions.extended_dynamic_state2 && (is_radv || is_qualcomm)) {
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) {
|
||||
LOG_WARNING(
|
||||
@@ -415,7 +502,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
dynamic_state3_enables = false;
|
||||
}
|
||||
}
|
||||
if (extensions.vertex_input_dynamic_state && is_radv) {
|
||||
if (extensions.vertex_input_dynamic_state && (is_radv || is_qualcomm)) {
|
||||
// Qualcomm S8gen2 drivers do not properly support vertex_input_dynamic_state.
|
||||
// TODO(ameerj): Blacklist only offending driver versions
|
||||
// TODO(ameerj): Confirm if RDNA1 is affected
|
||||
const bool is_rdna2 =
|
||||
@@ -467,8 +555,8 @@ 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) {
|
||||
LOG_WARNING(Render_Vulkan, "ANV driver does not support native BGR format");
|
||||
if (is_intel_anv || (is_qualcomm && !is_s8gen2)) {
|
||||
LOG_WARNING(Render_Vulkan, "Driver does not support native BGR format");
|
||||
must_emulate_bgr565 = true;
|
||||
}
|
||||
if (extensions.push_descriptor && is_intel_anv) {
|
||||
@@ -633,7 +721,8 @@ 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;
|
||||
|
||||
|
@@ -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;
|
||||
@@ -495,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;
|
||||
}
|
||||
|
||||
@@ -551,6 +560,10 @@ public:
|
||||
return cant_blit_msaa;
|
||||
}
|
||||
|
||||
bool MustEmulateScaledFormats() const {
|
||||
return must_emulate_scaled_formats;
|
||||
}
|
||||
|
||||
bool MustEmulateBGR565() const {
|
||||
return must_emulate_bgr565;
|
||||
}
|
||||
@@ -666,6 +679,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.
|
||||
|
@@ -10,29 +10,35 @@
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
Common::DynamicLibrary OpenLibrary() {
|
||||
std::shared_ptr<Common::DynamicLibrary> OpenLibrary(
|
||||
[[maybe_unused]] Core::Frontend::GraphicsContext* context) {
|
||||
LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library");
|
||||
Common::DynamicLibrary library;
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
// Android manages its Vulkan driver from the frontend.
|
||||
return context->GetDriverLibrary();
|
||||
#else
|
||||
auto library = std::make_shared<Common::DynamicLibrary>();
|
||||
#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
|
||||
|
@@ -3,10 +3,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/dynamic_library.h"
|
||||
#include "core/frontend/graphics_context.h"
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
Common::DynamicLibrary OpenLibrary();
|
||||
std::shared_ptr<Common::DynamicLibrary> OpenLibrary(
|
||||
[[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr);
|
||||
|
||||
} // namespace Vulkan
|
||||
|
Reference in New Issue
Block a user