early-access version 3629
This commit is contained in:
@@ -89,6 +89,9 @@ public:
|
||||
void RequestScreenshot(void* data, std::function<void(bool)> 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<Core::Frontend::GraphicsContext> context;
|
||||
|
||||
@@ -54,6 +54,10 @@ public:
|
||||
return device.GetDriverName();
|
||||
}
|
||||
|
||||
void NotifySurfaceChanged() override {
|
||||
present_manager.NotifySurfaceChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
void Report() const;
|
||||
|
||||
|
||||
@@ -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<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};
|
||||
|
||||
std::array<f32, 4 * 4> 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<f32, 4 * 4> 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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -300,6 +307,21 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
|
||||
};
|
||||
|
||||
#ifdef ANDROID
|
||||
std::unique_lock lock{recreate_surface_mutex};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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:
|
||||
|
||||
@@ -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<Frame*> 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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<std::chrono::steady_clock> m_submission_time{};
|
||||
|
||||
Reference in New Issue
Block a user