Compare commits

..

7 Commits

Author SHA1 Message Date
lizzie
9c879b6914 fx 2025-12-20 02:56:17 +01:00
lizzie
4a2422316d fx 2025-12-20 02:56:17 +01:00
lizzie
8bd9059ed7 fix android 2025-12-20 02:56:17 +01:00
lizzie
3ade21551b [vk] unify VkSurfaceKHR with Android and the rest of platforms; remove technically incorrect nullptr() ctor for handles 2025-12-20 02:56:17 +01:00
John
c5bd7dc047 [sdl]Mouse Panning Regression Fix (#3181)
Fix the mouse panning issues

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3181
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: John <john@eden-emu.dev>
Co-committed-by: John <john@eden-emu.dev>
2025-12-19 23:32:42 +01:00
lizzie
557876b222 [core] use memcpy instead of hand rolling aligned cases (#2639)
Hand rolling memcpy like this is always frowned upon because the compiler has more insight on whats going on (plus the code resolves to a worse version of itself on assembly). This removes some branches that are just straight up redundant. May save stuff especially for systems without fastmem enabled.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2639
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-12-19 03:58:20 +01:00
lizzie
22dfc560e0 [sdl] fix mouse panning delay (#3174)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3174
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-12-19 00:30:18 +01:00
22 changed files with 147 additions and 352 deletions

View File

@@ -10,6 +10,7 @@
#include <mutex>
#include <span>
#include <thread>
#include <type_traits>
#include <vector>
#include "common/assert.h"
@@ -681,22 +682,17 @@ struct Memory::Impl {
}
}
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, auto on_unmapped, auto on_rasterizer) const {
template<typename F, typename G>
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, F&& on_unmapped, G&& on_rasterizer) const {
// AARCH64 masks the upper 16 bit of all memory accesses
vaddr = vaddr & 0xffffffffffffULL;
if (!AddressSpaceContains(*current_page_table, vaddr, 1)) [[unlikely]] {
on_unmapped();
return nullptr;
} else {
vaddr &= 0xffffffffffffULL;
if (AddressSpaceContains(*current_page_table, vaddr, 1)) [[likely]] {
// Avoid adding any extra logic to this fast-path block
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) [[likely]] {
return reinterpret_cast<u8*>(pointer + vaddr);
} else {
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
case Common::PageType::Unmapped:
on_unmapped();
return nullptr;
case Common::PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
return nullptr;
@@ -707,11 +703,18 @@ struct Memory::Impl {
on_rasterizer();
return host_ptr;
}
case Common::PageType::Unmapped: [[unlikely]] {
on_unmapped();
return nullptr;
}
default:
UNREACHABLE();
}
return nullptr;
}
} else {
on_unmapped();
return nullptr;
}
}
@@ -729,172 +732,38 @@ struct Memory::Impl {
GetInteger(vaddr), []() {}, []() {});
}
/**
* Reads a particular data type out of memory at the given virtual address.
*
* @param vaddr The virtual address to read the data type from.
*
* @tparam T The data type to read out of memory. This type *must* be
* trivially copyable, otherwise the behavior of this function
* is undefined.
*
* @returns The instance of T read from the specified virtual address.
*/
/// @brief Reads a particular data type out of memory at the given virtual address.
/// @param vaddr The virtual address to read the data type from.
/// @tparam T The data type to read out of memory.
/// @returns The instance of T read from the specified virtual address.
template <typename T>
T Read(Common::ProcessAddress vaddr) {
// Fast path for aligned reads of common sizes
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
const u64 addr = GetInteger(vaddr);
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
// 8-bit reads are always aligned
const u8* const ptr = GetPointerImpl(
addr,
[addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read8 @ 0x{:016X}", addr);
},
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
if (ptr) {
return static_cast<T>(*ptr);
}
return 0;
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
// Check alignment for 16-bit reads
if ((addr & 1) == 0) {
const u8* const ptr = GetPointerImpl(
addr,
[addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read16 @ 0x{:016X}", addr);
},
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
if (ptr) {
return static_cast<T>(*reinterpret_cast<const u16*>(ptr));
}
}
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
// Check alignment for 32-bit reads
if ((addr & 3) == 0) {
const u8* const ptr = GetPointerImpl(
addr,
[addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read32 @ 0x{:016X}", addr);
},
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
if (ptr) {
return static_cast<T>(*reinterpret_cast<const u32*>(ptr));
}
}
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
// Check alignment for 64-bit reads
if ((addr & 7) == 0) {
const u8* const ptr = GetPointerImpl(
addr,
[addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read64 @ 0x{:016X}", addr);
},
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
if (ptr) {
return static_cast<T>(*reinterpret_cast<const u64*>(ptr));
}
}
}
// Fall back to the general case for other types or unaligned access
T result = 0;
const u8* const ptr = GetPointerImpl(
addr,
[addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
},
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
if (ptr) {
if (auto const ptr = GetPointerImpl(addr, [addr]() {
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
}, [&]() {
HandleRasterizerDownload(addr, sizeof(T));
}); ptr) [[likely]] {
// It may be tempting to rewrite this particular section to use "reinterpret_cast";
// afterall, it's trivially copyable so surely it can be copied ov- Alignment.
// Remember, alignment. memcpy() will deal with all the alignment extremely fast.
T result{};
std::memcpy(&result, ptr, sizeof(T));
return result;
}
return result;
return T{};
}
/**
* Writes a particular data type to memory at the given virtual address.
*
* @param vaddr The virtual address to write the data type to.
*
* @tparam T The data type to write to memory. This type *must* be
* trivially copyable, otherwise the behavior of this function
* is undefined.
*/
/// @brief Writes a particular data type to memory at the given virtual address.
/// @param vaddr The virtual address to write the data type to.
/// @tparam T The data type to write to memory.
template <typename T>
void Write(Common::ProcessAddress vaddr, const T data) {
// Fast path for aligned writes of common sizes
inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) {
const u64 addr = GetInteger(vaddr);
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
// 8-bit writes are always aligned
u8* const ptr = GetPointerImpl(
addr,
[addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write8 @ 0x{:016X} = 0x{:02X}", addr,
static_cast<u8>(data));
},
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
if (ptr) {
*ptr = static_cast<u8>(data);
}
return;
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
// Check alignment for 16-bit writes
if ((addr & 1) == 0) {
u8* const ptr = GetPointerImpl(
addr,
[addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write16 @ 0x{:016X} = 0x{:04X}", addr,
static_cast<u16>(data));
},
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
if (ptr) {
*reinterpret_cast<u16*>(ptr) = static_cast<u16>(data);
return;
}
}
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
// Check alignment for 32-bit writes
if ((addr & 3) == 0) {
u8* const ptr = GetPointerImpl(
addr,
[addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write32 @ 0x{:016X} = 0x{:08X}", addr,
static_cast<u32>(data));
},
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
if (ptr) {
*reinterpret_cast<u32*>(ptr) = static_cast<u32>(data);
return;
}
}
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
// Check alignment for 64-bit writes
if ((addr & 7) == 0) {
u8* const ptr = GetPointerImpl(
addr,
[addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write64 @ 0x{:016X} = 0x{:016X}", addr,
static_cast<u64>(data));
},
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
if (ptr) {
*reinterpret_cast<u64*>(ptr) = static_cast<u64>(data);
return;
}
}
}
// Fall back to the general case for other types or unaligned access
u8* const ptr = GetPointerImpl(
addr,
[addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8,
addr, static_cast<u64>(data));
},
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
if (ptr) {
if (auto const ptr = GetPointerImpl(addr, [addr, data]() {
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, addr, u64(data));
}, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]]
std::memcpy(ptr, &data, sizeof(T));
}
}
template <typename T>

View File

@@ -57,7 +57,7 @@ class SigHandler {
public:
SigHandler() noexcept {
signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
signal_stack_memory = std::malloc(signal_stack_size);
signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
stack_t signal_stack{};
signal_stack.ss_sp = signal_stack_memory;
@@ -89,7 +89,7 @@ public:
}
~SigHandler() noexcept {
std::free(signal_stack_memory);
munmap(signal_stack_memory, signal_stack_size);
}
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {

View File

@@ -82,8 +82,7 @@ FP::FPCR A32EmitContext::FPCR(bool fpcr_controlled) const {
A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_interface)
: EmitX64(code), conf(std::move(conf)), jit_interface(jit_interface) {
if (conf.fastmem_pointer.has_value())
GenFastmemFallbacks();
GenFastmemFallbacks();
GenTerminalHandlers();
code.PreludeComplete();
ClearFastDispatchTable();

View File

@@ -56,8 +56,7 @@ FP::FPCR A64EmitContext::FPCR(bool fpcr_controlled) const {
A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_interface)
: EmitX64(code), conf(conf), jit_interface{jit_interface} {
GenMemory128Accessors();
if (conf.fastmem_pointer.has_value())
GenFastmemFallbacks();
GenFastmemFallbacks();
GenTerminalHandlers();
code.PreludeComplete();
ClearFastDispatchTable();

View File

@@ -14,7 +14,7 @@
#include "input_common/drivers/mouse.h"
namespace InputCommon {
constexpr int update_time = 250; // 4 TPS
constexpr int update_time = 10;
constexpr float default_panning_sensitivity = 0.0010f;
constexpr float default_stick_sensitivity = 0.0006f;
constexpr float default_deadzone_counterweight = 0.01f;

View File

@@ -1049,7 +1049,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
VkShaderModule frag_shader = *convert_float_to_depth_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -1079,7 +1079,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
VkShaderModule frag_shader = *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -1110,7 +1110,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
}
const std::array stages = MakeStages(*full_screen_vert, *module);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -1152,7 +1152,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,

View File

@@ -137,14 +137,8 @@ try
memory_allocator,
scheduler,
swapchain,
#ifdef ANDROID
surface)
,
#else
*surface)
,
#endif
blit_swapchain(device_memory,
, blit_swapchain(device_memory,
device,
memory_allocator,
present_manager,

View File

@@ -284,7 +284,7 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
.requiredSubgroupSize = optional_subgroup_size ? *optional_subgroup_size : 32U,
};
bool use_setup_size = device.IsExtSubgroupSizeControlSupported() && optional_subgroup_size;
pipeline = device.GetLogical().CreateComputePipeline({
pipeline = device.GetLogical().CreateComputePipeline(VkComputePipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -298,7 +298,7 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
.pSpecializationInfo = nullptr,
},
.layout = *layout,
.basePipelineHandle = nullptr,
.basePipelineHandle = {},
.basePipelineIndex = 0,
});
}
@@ -653,7 +653,7 @@ MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_,
.codeSize = static_cast<u32>(code.size_bytes()),
.pCode = code.data(),
});
pipelines[i] = device.GetLogical().CreateComputePipeline({
pipelines[i] = device.GetLogical().CreateComputePipeline(VkComputePipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
@@ -667,7 +667,7 @@ MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_,
.pSpecializationInfo = nullptr,
},
.layout = *layout,
.basePipelineHandle = nullptr,
.basePipelineHandle = {},
.basePipelineIndex = 0,
});
};

View File

@@ -61,26 +61,24 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
}
pipeline = device.GetLogical().CreateComputePipeline(
{
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = flags,
.stage{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext =
device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
.flags = 0,
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
.module = *spv_module,
.pName = "main",
.pSpecializationInfo = nullptr,
},
.layout = *pipeline_layout,
.basePipelineHandle = 0,
.basePipelineIndex = 0,
pipeline = device.GetLogical().CreateComputePipeline(VkComputePipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = flags,
.stage{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext =
device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr,
.flags = 0,
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
.module = *spv_module,
.pName = "main",
.pSpecializationInfo = nullptr,
},
*pipeline_cache);
.layout = *pipeline_layout,
.basePipelineHandle = 0,
.basePipelineIndex = 0,
}, *pipeline_cache);
if (pipeline_statistics) {
pipeline_statistics->Collect(*pipeline);

View File

@@ -936,29 +936,27 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
}
pipeline = device.GetLogical().CreateGraphicsPipeline(
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = flags,
.stageCount = static_cast<u32>(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input_ci,
.pInputAssemblyState = &input_assembly_ci,
.pTessellationState = &tessellation_ci,
.pViewportState = &viewport_ci,
.pRasterizationState = &rasterization_ci,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &depth_stencil_ci,
.pColorBlendState = &color_blend_ci,
.pDynamicState = &dynamic_state_ci,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
},
*pipeline_cache);
pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
.flags = flags,
.stageCount = static_cast<u32>(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input_ci,
.pInputAssemblyState = &input_assembly_ci,
.pTessellationState = &tessellation_ci,
.pViewportState = &viewport_ci,
.pRasterizationState = &rasterization_ci,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &depth_stencil_ci,
.pColorBlendState = &color_blend_ci,
.pDynamicState = &dynamic_state_ci,
.layout = *pipeline_layout,
.renderPass = render_pass,
.subpass = 0,
.basePipelineHandle = {},
.basePipelineIndex = 0,
}, *pipeline_cache);
}
void GraphicsPipeline::Validate() {

View File

@@ -101,22 +101,14 @@ PresentManager::PresentManager(const vk::Instance& instance_,
MemoryAllocator& memory_allocator_,
Scheduler& scheduler_,
Swapchain& swapchain_,
#ifdef ANDROID
vk::SurfaceKHR& surface_)
#else
VkSurfaceKHR_T* surface_handle_)
#endif
VkSurfaceKHR_T* surface_)
: instance{instance_}
, render_window{render_window_}
, device{device_}
, memory_allocator{memory_allocator_}
, scheduler{scheduler_}
, swapchain{swapchain_}
#ifdef ANDROID
, surface{surface_}
#else
, surface_handle{surface_handle_}
#endif
, blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}
, use_present_thread{Settings::values.async_presentation.GetValue()}
{
@@ -299,11 +291,7 @@ void PresentManager::PresentThread(std::stop_token token) {
}
void PresentManager::RecreateSwapchain(Frame* frame) {
#ifndef ANDROID
swapchain.Create(surface_handle, frame->width, frame->height); // Pass raw pointer
#else
swapchain.Create(*surface, frame->width, frame->height); // Pass raw pointer
#endif
swapchain.Create(surface, frame->width, frame->height); // Pass raw pointer
SetImageCount();
}
@@ -322,7 +310,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
// Recreate surface and swapchain if needed.
if (requires_recreation) {
#ifdef ANDROID
surface = CreateSurface(instance, render_window.GetWindowInfo());
surface = reinterpret_cast<VkSurfaceKHR_T*>(CreateSurface(instance, render_window.GetWindowInfo()).address());
#endif
RecreateSwapchain(frame);
}

View File

@@ -15,8 +15,6 @@
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
struct VkSurfaceKHR_T;
namespace Core::Frontend {
class EmuWindow;
} // namespace Core::Frontend
@@ -46,11 +44,7 @@ public:
MemoryAllocator& memory_allocator,
Scheduler& scheduler,
Swapchain& swapchain,
#ifdef ANDROID
vk::SurfaceKHR& surface);
#else
VkSurfaceKHR_T* surface_handle);
#endif
VkSurfaceKHR_T* surface);
~PresentManager();
/// Returns the last used presentation frame
@@ -84,11 +78,7 @@ private:
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
Swapchain& swapchain;
#ifdef ANDROID
vk::SurfaceKHR& surface;
#else
VkSurfaceKHR_T* surface_handle;
#endif
VkSurfaceKHR_T* surface;
vk::CommandPool cmdpool;
std::vector<Frame> frames;
boost::container::deque<Frame*> present_queue;

View File

@@ -1278,7 +1278,7 @@ void QueryCacheRuntime::EndHostConditionalRendering() {
PauseHostConditionalRendering();
impl->hcr_is_set = false;
impl->is_hcr_running = false;
impl->hcr_buffer = nullptr;
impl->hcr_buffer = VkBuffer{};
impl->hcr_offset = 0;
}

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -35,7 +38,7 @@ public:
~QueryCacheRuntime();
template <typename SyncValuesType>
void SyncValues(std::span<SyncValuesType> values, VkBuffer base_src_buffer = nullptr);
void SyncValues(std::span<SyncValuesType> values, VkBuffer base_src_buffer = VkBuffer{});
void Barriers(bool is_prebarrier);

View File

@@ -342,7 +342,7 @@ void Scheduler::EndRenderPass()
);
});
state.renderpass = nullptr;
state.renderpass = VkRenderPass{};
num_renderpass_images = 0;
}

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -40,10 +43,10 @@ public:
~Scheduler();
/// Sends the current execution context to the GPU.
u64 Flush(VkSemaphore signal_semaphore = nullptr, VkSemaphore wait_semaphore = nullptr);
u64 Flush(VkSemaphore signal_semaphore = {}, VkSemaphore wait_semaphore = {});
/// Sends the current execution context to the GPU and waits for it to complete.
void Finish(VkSemaphore signal_semaphore = nullptr, VkSemaphore wait_semaphore = nullptr);
void Finish(VkSemaphore signal_semaphore = {}, VkSemaphore wait_semaphore = {});
/// Waits for the worker thread to finish executing everything. After this function returns it's
/// safe to touch worker resources.
@@ -208,8 +211,8 @@ private:
};
struct State {
VkRenderPass renderpass = nullptr;
VkFramebuffer framebuffer = nullptr;
VkRenderPass renderpass{};
VkFramebuffer framebuffer{};
VkExtent2D render_area = {0, 0};
GraphicsPipeline* graphics_pipeline = nullptr;
bool is_rescaling = false;

View File

@@ -109,38 +109,22 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
} // Anonymous namespace
Swapchain::Swapchain(
#ifdef ANDROID
VkSurfaceKHR surface_,
#else
VkSurfaceKHR_T* surface_handle_,
#endif
VkSurfaceKHR_T* surface_,
const Device& device_,
Scheduler& scheduler_,
u32 width_,
u32 height_)
#ifdef ANDROID
: surface(surface_)
#else
: surface_handle{surface_handle_}
#endif
, device{device_}
, scheduler{scheduler_}
{
#ifdef ANDROID
Create(surface, width_, height_);
#else
Create(surface_handle, width_, height_);
#endif
}
Swapchain::~Swapchain() = default;
void Swapchain::Create(
#ifdef ANDROID
VkSurfaceKHR surface_,
#else
VkSurfaceKHR_T* surface_handle_,
#endif
VkSurfaceKHR_T* surface_,
u32 width_,
u32 height_)
{
@@ -148,18 +132,10 @@ void Swapchain::Create(
is_suboptimal = false;
width = width_;
height = height_;
#ifdef ANDROID
surface = surface_;
#else
surface_handle = surface_handle_;
#endif
const auto physical_device = device.GetPhysical();
#ifdef ANDROID
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
#else
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface_handle)};
#endif
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(VkSurfaceKHR(surface))};
if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) {
return;
}
@@ -237,14 +213,8 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
const auto physical_device{device.GetPhysical()};
#ifdef ANDROID
const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface);
#else
const auto formats{physical_device.GetSurfaceFormatsKHR(surface_handle)};
const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface_handle);
#endif
const auto formats{physical_device.GetSurfaceFormatsKHR(VkSurfaceKHR(surface))};
const auto present_modes = physical_device.GetSurfacePresentModesKHR(VkSurfaceKHR(surface));
has_mailbox = std::find(present_modes.begin(), present_modes.end(), VK_PRESENT_MODE_MAILBOX_KHR)
!= present_modes.end();
@@ -273,11 +243,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
#ifdef ANDROID
.surface = surface,
#else
.surface = surface_handle,
#endif
.surface = VkSurfaceKHR(surface),
.minImageCount = requested_image_count,
.imageFormat = surface_format.format,
.imageColorSpace = surface_format.colorSpace,
@@ -296,7 +262,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
.compositeAlpha = alpha_flags,
.presentMode = present_mode,
.clipped = VK_FALSE,
.oldSwapchain = nullptr,
.oldSwapchain = VkSwapchainKHR{},
};
const u32 graphics_family{device.GetGraphicsFamily()};
const u32 present_family{device.GetPresentFamily()};
@@ -318,11 +284,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
swapchain_ci.flags |= VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR;
}
// Request the size again to reduce the possibility of a TOCTOU race condition.
#ifdef ANDROID
const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface);
#else
const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(surface_handle);
#endif
const auto updated_capabilities = physical_device.GetSurfaceCapabilitiesKHR(VkSurfaceKHR(surface));
swapchain_ci.imageExtent = ChooseSwapExtent(updated_capabilities, width, height);
// Don't add code within this and the swapchain creation.
swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci);

View File

@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,8 +11,6 @@
#include "common/common_types.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
struct VkSurfaceKHR_T;
namespace Layout {
struct FramebufferLayout;
}
@@ -22,11 +23,7 @@ class Scheduler;
class Swapchain {
public:
explicit Swapchain(
#ifdef ANDROID
VkSurfaceKHR surface,
#else
VkSurfaceKHR_T* surface_handle,
#endif
VkSurfaceKHR_T* surface,
const Device& device,
Scheduler& scheduler,
u32 width,
@@ -35,11 +32,7 @@ public:
/// Creates (or recreates) the swapchain with a given size.
void Create(
#ifdef ANDROID
VkSurfaceKHR surface,
#else
VkSurfaceKHR_T* surface_handle,
#endif
VkSurfaceKHR_T* surface,
u32 width,
u32 height);
@@ -125,11 +118,7 @@ private:
bool NeedsPresentModeUpdate() const;
#ifdef ANDROID
VkSurfaceKHR surface;
#else
VkSurfaceKHR_T* surface_handle;
#endif
VkSurfaceKHR_T* surface;
const Device& device;
Scheduler& scheduler;

View File

@@ -29,3 +29,6 @@
#undef False
#undef None
#undef True
// "Catch-all" handle for both Android and.. the rest of platforms
struct VkSurfaceKHR_T;

View File

@@ -413,7 +413,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
: instance{instance_}, dld{dld_}, physical{physical_},
format_properties(GetFormatProperties(physical)) {
// Get suitability and device properties.
const bool is_suitable = GetSuitability(surface != nullptr);
const bool is_suitable = GetSuitability(surface != VkSurfaceKHR{});
const VkDriverId driver_id = properties.driver.driverID;
const auto device_id = properties.properties.deviceID;

View File

@@ -15,7 +15,7 @@ vk::SurfaceKHR CreateSurface(
const vk::Instance& instance,
[[maybe_unused]] const Core::Frontend::EmuWindow::WindowSystemInfo& window_info) {
[[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch();
VkSurfaceKHR unsafe_surface = nullptr;
VkSurfaceKHR unsafe_surface = VkSurfaceKHR{};
#ifdef _WIN32
if (window_info.type == Core::Frontend::WindowSystemType::Windows) {

View File

@@ -399,13 +399,13 @@ public:
/// Construct a handle transferring the ownership from another handle.
Handle(Handle&& rhs) noexcept
: handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
: handle{std::exchange(rhs.handle, Type{})}, owner{rhs.owner}, dld{rhs.dld} {}
/// Assign the current handle transferring the ownership from another handle.
/// Destroys any previously held object.
Handle& operator=(Handle&& rhs) noexcept {
Release();
handle = std::exchange(rhs.handle, nullptr);
handle = std::exchange(rhs.handle, Type{});
owner = rhs.owner;
dld = rhs.dld;
return *this;
@@ -419,7 +419,7 @@ public:
/// Destroys any held object.
void reset() noexcept {
Release();
handle = nullptr;
handle = Type{};
}
/// Returns the address of the held object.
@@ -435,7 +435,7 @@ public:
/// Returns true when there's a held object.
explicit operator bool() const noexcept {
return handle != nullptr;
return handle != Type{};
}
#ifndef ANDROID
@@ -450,7 +450,7 @@ public:
#endif
protected:
Type handle = nullptr;
Type handle{};
OwnerType owner = nullptr;
const Dispatch* dld = nullptr;
@@ -458,7 +458,7 @@ private:
/// Destroys the held object if it exists.
void Release() noexcept {
if (handle) {
Destroy(owner, handle, *dld);
Destroy(OwnerType(owner), Type(handle), *dld);
}
}
};
@@ -501,7 +501,7 @@ public:
/// Destroys any held object.
void reset() noexcept {
Release();
handle = nullptr;
handle = {};
}
/// Returns the address of the held object.
@@ -517,7 +517,7 @@ public:
/// Returns true when there's a held object.
explicit operator bool() const noexcept {
return handle != nullptr;
return handle != Type{};
}
#ifndef ANDROID
@@ -532,7 +532,7 @@ public:
#endif
protected:
Type handle = nullptr;
Type handle{};
const Dispatch* dld = nullptr;
private:
@@ -602,7 +602,7 @@ private:
std::unique_ptr<AllocationType[]> allocations;
std::size_t num = 0;
VkDevice device = nullptr;
PoolType pool = nullptr;
PoolType pool{};
const DeviceDispatch* dld = nullptr;
};
@@ -664,12 +664,12 @@ public:
Image& operator=(const Image&) = delete;
Image(Image&& rhs) noexcept
: handle{std::exchange(rhs.handle, nullptr)}, usage{rhs.usage}, owner{rhs.owner},
: handle{std::exchange(rhs.handle, VkImage{})}, usage{rhs.usage}, owner{rhs.owner},
allocator{rhs.allocator}, allocation{rhs.allocation}, dld{rhs.dld} {}
Image& operator=(Image&& rhs) noexcept {
Release();
handle = std::exchange(rhs.handle, nullptr);
handle = std::exchange(rhs.handle, VkImage{});
usage = rhs.usage;
owner = rhs.owner;
allocator = rhs.allocator;
@@ -688,11 +688,11 @@ public:
void reset() noexcept {
Release();
handle = nullptr;
handle = VkImage{};
}
explicit operator bool() const noexcept {
return handle != nullptr;
return handle != VkImage{};
}
void SetObjectNameEXT(const char* name) const;
@@ -704,7 +704,7 @@ public:
private:
void Release() const noexcept;
VkImage handle = nullptr;
VkImage handle{};
VkImageUsageFlags usage{};
VkDevice owner = nullptr;
VmaAllocator allocator = nullptr;
@@ -725,13 +725,13 @@ public:
Buffer& operator=(const Buffer&) = delete;
Buffer(Buffer&& rhs) noexcept
: handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, allocator{rhs.allocator},
: handle{std::exchange(rhs.handle, VkBuffer{})}, owner{rhs.owner}, allocator{rhs.allocator},
allocation{rhs.allocation}, mapped{rhs.mapped},
is_coherent{rhs.is_coherent}, dld{rhs.dld} {}
Buffer& operator=(Buffer&& rhs) noexcept {
Release();
handle = std::exchange(rhs.handle, nullptr);
handle = std::exchange(rhs.handle, VkBuffer{});
owner = rhs.owner;
allocator = rhs.allocator;
allocation = rhs.allocation;
@@ -751,11 +751,11 @@ public:
void reset() noexcept {
Release();
handle = nullptr;
handle = VkBuffer{};
}
explicit operator bool() const noexcept {
return handle != nullptr;
return handle != VkBuffer{};
}
/// Returns the host mapped memory, an empty span otherwise.
@@ -781,7 +781,7 @@ public:
private:
void Release() const noexcept;
VkBuffer handle = nullptr;
VkBuffer handle{};
VkDevice owner = nullptr;
VmaAllocator allocator = nullptr;
VmaAllocation allocation = nullptr;
@@ -1015,10 +1015,10 @@ public:
[[nodiscard]] PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
[[nodiscard]] Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
VkPipelineCache cache = nullptr) const;
VkPipelineCache cache = {}) const;
[[nodiscard]] Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
VkPipelineCache cache = nullptr) const;
VkPipelineCache cache = {}) const;
[[nodiscard]] Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;