mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 13:26:52 +01:00
graphics: make raw image synchronization an opt-in setting
This commit is contained in:
@@ -152,6 +152,10 @@ bool ReadbackLinearImagesEnabled() {
|
|||||||
return g_config->readback_linear_images;
|
return g_config->readback_linear_images;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SyncRawImageBuffersEnabled() {
|
||||||
|
return g_config->sync_raw_image_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
bool TessellationEnabled() {
|
bool TessellationEnabled() {
|
||||||
return g_config->tessellation_enabled;
|
return g_config->tessellation_enabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ struct ConfigOptions {
|
|||||||
bool gpu_assisted_validation_enabled = false;
|
bool gpu_assisted_validation_enabled = false;
|
||||||
bool renderdoc_enabled = false;
|
bool renderdoc_enabled = false;
|
||||||
bool readback_linear_images = false;
|
bool readback_linear_images = false;
|
||||||
|
bool sync_raw_image_buffers = false;
|
||||||
bool tessellation_enabled = false;
|
bool tessellation_enabled = false;
|
||||||
bool trophy_enabled = true;
|
bool trophy_enabled = true;
|
||||||
bool playgo_hack_enabled = false;
|
bool playgo_hack_enabled = false;
|
||||||
@@ -124,6 +125,7 @@ bool GpuAssistedValidationEnabled();
|
|||||||
|
|
||||||
bool RenderDocEnabled();
|
bool RenderDocEnabled();
|
||||||
bool ReadbackLinearImagesEnabled();
|
bool ReadbackLinearImagesEnabled();
|
||||||
|
bool SyncRawImageBuffersEnabled();
|
||||||
bool TessellationEnabled();
|
bool TessellationEnabled();
|
||||||
bool TrophyEnabled();
|
bool TrophyEnabled();
|
||||||
bool PlayGoHackEnabled();
|
bool PlayGoHackEnabled();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
#include "common/emulatorConfig.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/profiler.h"
|
#include "common/profiler.h"
|
||||||
@@ -127,7 +128,8 @@ NativeStorageBuffer(RenderContext& context, const PreparedBindings::BufferSource
|
|||||||
EXIT("storage buffer range is unsupported\n");
|
EXIT("storage buffer range is unsupported\n");
|
||||||
}
|
}
|
||||||
auto [buffer, offset] = context.GetBufferCache().ObtainBuffer(
|
auto [buffer, offset] = context.GetBufferCache().ObtainBuffer(
|
||||||
address, size, resource.written, resource.read || resource.formatted, id);
|
address, size, resource.written,
|
||||||
|
resource.formatted || (resource.read && Config::SyncRawImageBuffersEnabled()), id);
|
||||||
const auto aligned_offset = Common::AlignDown(offset, alignment);
|
const auto aligned_offset = Common::AlignDown(offset, alignment);
|
||||||
const auto adjustment = offset - aligned_offset;
|
const auto adjustment = offset - aligned_offset;
|
||||||
const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange;
|
const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange;
|
||||||
|
|||||||
@@ -185,6 +185,12 @@
|
|||||||
<property name="text"><string>Skip boot logos</string></property>
|
<property name="text"><string>Skip boot logos</string></property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="10" column="1">
|
||||||
|
<widget class="QCheckBox" name="checkBox_sync_raw_image_buffers">
|
||||||
|
<property name="toolTip"><string>Can fix missing textures and incorrect transparency in some games. May reduce performance.</string></property>
|
||||||
|
<property name="text"><string>Accurate texture synchronization</string></property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ public:
|
|||||||
bool fullscreen_enabled = false;
|
bool fullscreen_enabled = false;
|
||||||
bool hide_cursor_enabled = false;
|
bool hide_cursor_enabled = false;
|
||||||
bool readback_linear_images = false;
|
bool readback_linear_images = false;
|
||||||
|
bool sync_raw_image_buffers = false;
|
||||||
bool tessellation_enabled = false;
|
bool tessellation_enabled = false;
|
||||||
bool trophy_enabled = true;
|
bool trophy_enabled = true;
|
||||||
bool skip_notice_screen = false;
|
bool skip_notice_screen = false;
|
||||||
@@ -153,6 +154,7 @@ public:
|
|||||||
fullscreen_enabled = other.fullscreen_enabled;
|
fullscreen_enabled = other.fullscreen_enabled;
|
||||||
hide_cursor_enabled = other.hide_cursor_enabled;
|
hide_cursor_enabled = other.hide_cursor_enabled;
|
||||||
readback_linear_images = other.readback_linear_images;
|
readback_linear_images = other.readback_linear_images;
|
||||||
|
sync_raw_image_buffers = other.sync_raw_image_buffers;
|
||||||
tessellation_enabled = other.tessellation_enabled;
|
tessellation_enabled = other.tessellation_enabled;
|
||||||
trophy_enabled = other.trophy_enabled;
|
trophy_enabled = other.trophy_enabled;
|
||||||
skip_notice_screen = other.skip_notice_screen;
|
skip_notice_screen = other.skip_notice_screen;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ QVariantMap Configuration::GameSettings() const {
|
|||||||
KYTY_CFG_SET(fullscreen_enabled);
|
KYTY_CFG_SET(fullscreen_enabled);
|
||||||
KYTY_CFG_SET(hide_cursor_enabled);
|
KYTY_CFG_SET(hide_cursor_enabled);
|
||||||
KYTY_CFG_SET(readback_linear_images);
|
KYTY_CFG_SET(readback_linear_images);
|
||||||
|
KYTY_CFG_SET(sync_raw_image_buffers);
|
||||||
KYTY_CFG_SET(tessellation_enabled);
|
KYTY_CFG_SET(tessellation_enabled);
|
||||||
KYTY_CFG_SET(trophy_enabled);
|
KYTY_CFG_SET(trophy_enabled);
|
||||||
KYTY_CFG_SET(skip_notice_screen);
|
KYTY_CFG_SET(skip_notice_screen);
|
||||||
@@ -56,6 +57,7 @@ void Configuration::ReadGameSettingsValues(const Settings& s) {
|
|||||||
KYTY_CFG_GET(fullscreen_enabled);
|
KYTY_CFG_GET(fullscreen_enabled);
|
||||||
KYTY_CFG_GET(hide_cursor_enabled);
|
KYTY_CFG_GET(hide_cursor_enabled);
|
||||||
KYTY_CFG_GET(readback_linear_images);
|
KYTY_CFG_GET(readback_linear_images);
|
||||||
|
KYTY_CFG_GET(sync_raw_image_buffers);
|
||||||
KYTY_CFG_GET(tessellation_enabled);
|
KYTY_CFG_GET(tessellation_enabled);
|
||||||
trophy_enabled = s.value("trophy_enabled", trophy_enabled).toBool();
|
trophy_enabled = s.value("trophy_enabled", trophy_enabled).toBool();
|
||||||
KYTY_CFG_GET(skip_notice_screen);
|
KYTY_CFG_GET(skip_notice_screen);
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ void ConfigurationEditDialog::Init(const Configuration& info) {
|
|||||||
m_ui->checkBox_fullscreen->setChecked(info.fullscreen_enabled);
|
m_ui->checkBox_fullscreen->setChecked(info.fullscreen_enabled);
|
||||||
m_ui->checkBox_hide_cursor->setChecked(info.hide_cursor_enabled);
|
m_ui->checkBox_hide_cursor->setChecked(info.hide_cursor_enabled);
|
||||||
m_ui->checkBox_readback->setChecked(info.readback_linear_images);
|
m_ui->checkBox_readback->setChecked(info.readback_linear_images);
|
||||||
|
m_ui->checkBox_sync_raw_image_buffers->setChecked(info.sync_raw_image_buffers);
|
||||||
m_ui->checkBox_tessellation->setChecked(info.tessellation_enabled);
|
m_ui->checkBox_tessellation->setChecked(info.tessellation_enabled);
|
||||||
m_ui->checkBox_skip_notice_screen->setChecked(info.skip_notice_screen);
|
m_ui->checkBox_skip_notice_screen->setChecked(info.skip_notice_screen);
|
||||||
m_ui->checkBox_trophy_notifications->setChecked(info.trophy_enabled);
|
m_ui->checkBox_trophy_notifications->setChecked(info.trophy_enabled);
|
||||||
@@ -435,6 +436,7 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui, boo
|
|||||||
info.fullscreen_enabled = ui.checkBox_fullscreen->isChecked();
|
info.fullscreen_enabled = ui.checkBox_fullscreen->isChecked();
|
||||||
info.hide_cursor_enabled = ui.checkBox_hide_cursor->isChecked();
|
info.hide_cursor_enabled = ui.checkBox_hide_cursor->isChecked();
|
||||||
info.readback_linear_images = ui.checkBox_readback->isChecked();
|
info.readback_linear_images = ui.checkBox_readback->isChecked();
|
||||||
|
info.sync_raw_image_buffers = ui.checkBox_sync_raw_image_buffers->isChecked();
|
||||||
info.tessellation_enabled = ui.checkBox_tessellation->isChecked();
|
info.tessellation_enabled = ui.checkBox_tessellation->isChecked();
|
||||||
info.skip_notice_screen = ui.checkBox_skip_notice_screen->isChecked();
|
info.skip_notice_screen = ui.checkBox_skip_notice_screen->isChecked();
|
||||||
info.trophy_enabled = ui.checkBox_trophy_notifications->isChecked();
|
info.trophy_enabled = ui.checkBox_trophy_notifications->isChecked();
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ static QStringList CreateEmulatorArgs(const Configuration& info) {
|
|||||||
args << "--hide-cursor";
|
args << "--hide-cursor";
|
||||||
}
|
}
|
||||||
args << "--readback-linear-images" << BoolArg(info.readback_linear_images);
|
args << "--readback-linear-images" << BoolArg(info.readback_linear_images);
|
||||||
|
args << "--sync-raw-image-buffers" << BoolArg(info.sync_raw_image_buffers);
|
||||||
args << "--trophy-notifications" << BoolArg(info.trophy_enabled);
|
args << "--trophy-notifications" << BoolArg(info.trophy_enabled);
|
||||||
args << "--skip-notice-screen" << BoolArg(info.skip_notice_screen);
|
args << "--skip-notice-screen" << BoolArg(info.skip_notice_screen);
|
||||||
if (info.tessellation_enabled) {
|
if (info.tessellation_enabled) {
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ static void PrintUsage() {
|
|||||||
::printf(" --spirv-debug-printf <true|false> Enable SPIR-V debug printf.\n");
|
::printf(" --spirv-debug-printf <true|false> Enable SPIR-V debug printf.\n");
|
||||||
::printf(
|
::printf(
|
||||||
" --readback-linear-images <true|false> Read back writable linear images on submit.\n");
|
" --readback-linear-images <true|false> Read back writable linear images on submit.\n");
|
||||||
|
::printf(
|
||||||
|
" --sync-raw-image-buffers <true|false> Synchronize raw reads of GPU images. Default: false.\n");
|
||||||
::printf(
|
::printf(
|
||||||
" --trophy-notifications <true|false> Show trophy unlock toasts and play their sound.\n");
|
" --trophy-notifications <true|false> Show trophy unlock toasts and play their sound.\n");
|
||||||
::printf(" --playgo-hack Use the supplied PlayGo stub fallback.\n");
|
::printf(" --playgo-hack Use the supplied PlayGo stub fallback.\n");
|
||||||
@@ -426,6 +428,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he
|
|||||||
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());
|
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (arg == "--sync-raw-image-buffers") {
|
||||||
|
if (!ParseBool(value, options.config.sync_raw_image_buffers)) {
|
||||||
|
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (arg == "--trophy-notifications") {
|
} else if (arg == "--trophy-notifications") {
|
||||||
if (!ParseBool(value, options.config.trophy_enabled)) {
|
if (!ParseBool(value, options.config.trophy_enabled)) {
|
||||||
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());
|
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());
|
||||||
|
|||||||
@@ -14022,8 +14022,14 @@ public:
|
|||||||
"backing");
|
"backing");
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
|
||||||
for (const bool formatted : {false, true}) {
|
Require(name, "raw image synchronization default",
|
||||||
const uint32_t before = formatted ? 0x13579bdfu : 0x89abcdefu;
|
!Config::SyncRawImageBuffersEnabled(),
|
||||||
|
"raw image synchronization should be disabled by default");
|
||||||
|
for (const auto [sync_raw, formatted] :
|
||||||
|
{std::pair{false, false}, {true, false}, {false, true}, {true, true}}) {
|
||||||
|
Config::Load({.sync_raw_image_buffers = sync_raw});
|
||||||
|
const bool sync_image = sync_raw || formatted;
|
||||||
|
const uint32_t before = 0x13579bd0u | (uint32_t(sync_raw) << 1u) | uint32_t(formatted);
|
||||||
constexpr uint32_t guard = 0x2468ace0u;
|
constexpr uint32_t guard = 0x2468ace0u;
|
||||||
constexpr uint32_t after = 0xa1b2c3d4u;
|
constexpr uint32_t after = 0xa1b2c3d4u;
|
||||||
vk::ClearValue clear{};
|
vk::ClearValue clear{};
|
||||||
@@ -14065,8 +14071,9 @@ public:
|
|||||||
buffer.range == buffer_size &&
|
buffer.range == buffer_size &&
|
||||||
buffer_bindings.images.empty() &&
|
buffer_bindings.images.empty() &&
|
||||||
texture_cache.GetImage(target.image_id).backing.state.layout ==
|
texture_cache.GetImage(target.image_id).backing.state.layout ==
|
||||||
vk::ImageLayout::eTransferSrcOptimal,
|
(sync_image ? vk::ImageLayout::eTransferSrcOptimal
|
||||||
"target discovery did not precede the image-to-buffer copy");
|
: vk::ImageLayout::eTransferDstOptimal),
|
||||||
|
"image-to-buffer synchronization ignored its setting or formatted reads");
|
||||||
auto readback = CreateHostBuffer(name, 2 * sizeof(uint32_t),
|
auto readback = CreateHostBuffer(name, 2 * sizeof(uint32_t),
|
||||||
vk::BufferUsageFlagBits::eTransferDst, {0, 0});
|
vk::BufferUsageFlagBits::eTransferDst, {0, 0});
|
||||||
const std::array copies{
|
const std::array copies{
|
||||||
@@ -14104,8 +14111,9 @@ public:
|
|||||||
scheduler.EndRendering();
|
scheduler.EndRendering();
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
Require(name, "buffer alias observes prior GPU contents",
|
Require(name, "buffer alias observes prior GPU contents",
|
||||||
ReadBuffer(name, readback, 2) == std::vector<u32>{before, guard},
|
ReadBuffer(name, readback, 2) ==
|
||||||
"buffer acquisition copied stale guest bytes instead of the image");
|
(sync_image ? std::vector<u32>{before, guard} : std::vector<u32>{0, 0}),
|
||||||
|
"buffer contents did not match the selected image synchronization mode");
|
||||||
DestroyBuffer(&readback);
|
DestroyBuffer(&readback);
|
||||||
Require(name, "rendering after buffer acquisition",
|
Require(name, "rendering after buffer acquisition",
|
||||||
ReadCachedTexel(name, context, target.image_id) == std::vector<u32>{after} &&
|
ReadCachedTexel(name, context, target.image_id) == std::vector<u32>{after} &&
|
||||||
@@ -14114,6 +14122,7 @@ public:
|
|||||||
"attachment rendering lost its new color or changed the untouched array layer");
|
"attachment rendering lost its new color or changed the untouched array layer");
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
}
|
}
|
||||||
|
Config::Load({});
|
||||||
|
|
||||||
auto colliding_msaa_texture = array_texture;
|
auto colliding_msaa_texture = array_texture;
|
||||||
colliding_msaa_texture.fields[3] =
|
colliding_msaa_texture.fields[3] =
|
||||||
|
|||||||
Reference in New Issue
Block a user