early-access version 3649
This commit is contained in:
parent
f0a3664d7e
commit
8967a0437b
21 changed files with 211 additions and 50 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3648.
|
This is the source code for early-access 3649.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -47,12 +47,4 @@ AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() {
|
||||||
return *adsp;
|
return *adsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioCore::SetNVDECActive(bool active) {
|
|
||||||
nvdec_active = active;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioCore::IsNVDECActive() const {
|
|
||||||
return nvdec_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace AudioCore
|
} // namespace AudioCore
|
||||||
|
|
|
@ -57,18 +57,6 @@ public:
|
||||||
*/
|
*/
|
||||||
AudioRenderer::ADSP::ADSP& GetADSP();
|
AudioRenderer::ADSP::ADSP& GetADSP();
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle NVDEC state, used to avoid stall in playback.
|
|
||||||
*
|
|
||||||
* @param active - Set true if nvdec is active, otherwise false.
|
|
||||||
*/
|
|
||||||
void SetNVDECActive(bool active);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get NVDEC state.
|
|
||||||
*/
|
|
||||||
bool IsNVDECActive() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Create the sinks on startup.
|
* Create the sinks on startup.
|
||||||
|
@ -83,8 +71,6 @@ private:
|
||||||
std::unique_ptr<Sink::Sink> input_sink;
|
std::unique_ptr<Sink::Sink> input_sink;
|
||||||
/// The ADSP in the sysmodule
|
/// The ADSP in the sysmodule
|
||||||
std::unique_ptr<AudioRenderer::ADSP::ADSP> adsp;
|
std::unique_ptr<AudioRenderer::ADSP::ADSP> adsp;
|
||||||
/// Is NVDec currently active?
|
|
||||||
bool nvdec_active{false};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AudioCore
|
} // namespace AudioCore
|
||||||
|
|
|
@ -235,6 +235,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||||
values.bg_green.SetGlobal(true);
|
values.bg_green.SetGlobal(true);
|
||||||
values.bg_blue.SetGlobal(true);
|
values.bg_blue.SetGlobal(true);
|
||||||
values.enable_compute_pipelines.SetGlobal(true);
|
values.enable_compute_pipelines.SetGlobal(true);
|
||||||
|
values.use_video_framerate.SetGlobal(true);
|
||||||
|
|
||||||
// System
|
// System
|
||||||
values.language_index.SetGlobal(true);
|
values.language_index.SetGlobal(true);
|
||||||
|
|
|
@ -482,6 +482,7 @@ struct Values {
|
||||||
SwitchableSetting<AstcRecompression, true> astc_recompression{
|
SwitchableSetting<AstcRecompression, true> astc_recompression{
|
||||||
AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3,
|
AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3,
|
||||||
"astc_recompression"};
|
"astc_recompression"};
|
||||||
|
SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"};
|
||||||
|
|
||||||
SwitchableSetting<u8> bg_red{0, "bg_red"};
|
SwitchableSetting<u8> bg_red{0, "bg_red"};
|
||||||
SwitchableSetting<u8> bg_green{0, "bg_green"};
|
SwitchableSetting<u8> bg_green{0, "bg_green"};
|
||||||
|
|
|
@ -216,6 +216,14 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNVDECActive(bool is_nvdec_active) {
|
||||||
|
nvdec_active = is_nvdec_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetNVDECActive() {
|
||||||
|
return nvdec_active;
|
||||||
|
}
|
||||||
|
|
||||||
void InitializeDebugger(System& system, u16 port) {
|
void InitializeDebugger(System& system, u16 port) {
|
||||||
debugger = std::make_unique<Debugger>(system, port);
|
debugger = std::make_unique<Debugger>(system, port);
|
||||||
}
|
}
|
||||||
|
@ -485,6 +493,8 @@ struct System::Impl {
|
||||||
std::atomic_bool is_powered_on{};
|
std::atomic_bool is_powered_on{};
|
||||||
bool exit_lock = false;
|
bool exit_lock = false;
|
||||||
|
|
||||||
|
bool nvdec_active{};
|
||||||
|
|
||||||
Reporter reporter;
|
Reporter reporter;
|
||||||
std::unique_ptr<Memory::CheatEngine> cheat_engine;
|
std::unique_ptr<Memory::CheatEngine> cheat_engine;
|
||||||
std::unique_ptr<Tools::Freezer> memory_freezer;
|
std::unique_ptr<Tools::Freezer> memory_freezer;
|
||||||
|
@ -594,6 +604,14 @@ void System::UnstallApplication() {
|
||||||
impl->UnstallApplication();
|
impl->UnstallApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::SetNVDECActive(bool is_nvdec_active) {
|
||||||
|
impl->SetNVDECActive(is_nvdec_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool System::GetNVDECActive() {
|
||||||
|
return impl->GetNVDECActive();
|
||||||
|
}
|
||||||
|
|
||||||
void System::InitializeDebugger() {
|
void System::InitializeDebugger() {
|
||||||
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
|
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,9 @@ public:
|
||||||
std::unique_lock<std::mutex> StallApplication();
|
std::unique_lock<std::mutex> StallApplication();
|
||||||
void UnstallApplication();
|
void UnstallApplication();
|
||||||
|
|
||||||
|
void SetNVDECActive(bool is_nvdec_active);
|
||||||
|
[[nodiscard]] bool GetNVDECActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the debugger.
|
* Initialize the debugger.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -69,7 +69,7 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
|
||||||
|
|
||||||
void nvhost_nvdec::OnOpen(DeviceFD fd) {
|
void nvhost_nvdec::OnOpen(DeviceFD fd) {
|
||||||
LOG_INFO(Service_NVDRV, "NVDEC video stream started");
|
LOG_INFO(Service_NVDRV, "NVDEC video stream started");
|
||||||
system.AudioCore().SetNVDECActive(true);
|
system.SetNVDECActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvhost_nvdec::OnClose(DeviceFD fd) {
|
void nvhost_nvdec::OnClose(DeviceFD fd) {
|
||||||
|
@ -79,7 +79,7 @@ void nvhost_nvdec::OnClose(DeviceFD fd) {
|
||||||
if (iter != host1x_file.fd_to_id.end()) {
|
if (iter != host1x_file.fd_to_id.end()) {
|
||||||
system.GPU().ClearCdmaInstance(iter->second);
|
system.GPU().ClearCdmaInstance(iter->second);
|
||||||
}
|
}
|
||||||
system.AudioCore().SetNVDECActive(false);
|
system.SetNVDECActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -325,6 +325,10 @@ s64 Nvnflinger::GetNextTicks() const {
|
||||||
speed_scale = 0.01f;
|
speed_scale = 0.01f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
|
||||||
|
// Run at intended presentation rate during video playback.
|
||||||
|
speed_scale = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
// As an extension, treat nonpositive swap interval as framerate multiplier.
|
// As an extension, treat nonpositive swap interval as framerate multiplier.
|
||||||
const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval)
|
const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval)
|
||||||
|
|
|
@ -715,20 +715,38 @@ void BufferCache<P>::BindHostIndexBuffer() {
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindHostVertexBuffers() {
|
void BufferCache<P>::BindHostVertexBuffers() {
|
||||||
|
HostBindings host_bindings;
|
||||||
|
bool any_valid{false};
|
||||||
auto& flags = maxwell3d->dirty.flags;
|
auto& flags = maxwell3d->dirty.flags;
|
||||||
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
|
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
|
||||||
const Binding& binding = channel_state->vertex_buffers[index];
|
|
||||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
|
||||||
TouchBuffer(buffer, binding.buffer_id);
|
|
||||||
SynchronizeBuffer(buffer, binding.cpu_addr, binding.size);
|
|
||||||
if (!flags[Dirty::VertexBuffer0 + index]) {
|
if (!flags[Dirty::VertexBuffer0 + index]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
flags[Dirty::VertexBuffer0 + index] = false;
|
host_bindings.min_index = std::min(host_bindings.min_index, index);
|
||||||
|
host_bindings.max_index = std::max(host_bindings.max_index, index);
|
||||||
|
any_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
|
if (any_valid) {
|
||||||
const u32 offset = buffer.Offset(binding.cpu_addr);
|
host_bindings.max_index++;
|
||||||
runtime.BindVertexBuffer(index, buffer, offset, binding.size, stride);
|
for (u32 index = host_bindings.min_index; index < host_bindings.max_index; index++) {
|
||||||
|
flags[Dirty::VertexBuffer0 + index] = false;
|
||||||
|
|
||||||
|
const Binding& binding = channel_state->vertex_buffers[index];
|
||||||
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
|
|
||||||
|
TouchBuffer(buffer, binding.buffer_id);
|
||||||
|
SynchronizeBuffer(buffer, binding.cpu_addr, binding.size);
|
||||||
|
|
||||||
|
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
|
||||||
|
const u32 offset = buffer.Offset(binding.cpu_addr);
|
||||||
|
|
||||||
|
host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer));
|
||||||
|
host_bindings.offsets.push_back(offset);
|
||||||
|
host_bindings.sizes.push_back(binding.size);
|
||||||
|
host_bindings.strides.push_back(stride);
|
||||||
|
}
|
||||||
|
runtime.BindVertexBuffers(host_bindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,15 +900,25 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
||||||
if (maxwell3d->regs.transform_feedback_enabled == 0) {
|
if (maxwell3d->regs.transform_feedback_enabled == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
HostBindings host_bindings;
|
||||||
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
|
||||||
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
const Binding& binding = channel_state->transform_feedback_buffers[index];
|
||||||
|
if (maxwell3d->regs.transform_feedback.controls[index].varying_count == 0 &&
|
||||||
|
maxwell3d->regs.transform_feedback.controls[index].stride == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
TouchBuffer(buffer, binding.buffer_id);
|
TouchBuffer(buffer, binding.buffer_id);
|
||||||
const u32 size = binding.size;
|
const u32 size = binding.size;
|
||||||
SynchronizeBuffer(buffer, binding.cpu_addr, size);
|
SynchronizeBuffer(buffer, binding.cpu_addr, size);
|
||||||
|
|
||||||
const u32 offset = buffer.Offset(binding.cpu_addr);
|
const u32 offset = buffer.Offset(binding.cpu_addr);
|
||||||
runtime.BindTransformFeedbackBuffer(index, buffer, offset, size);
|
host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer));
|
||||||
|
host_bindings.offsets.push_back(offset);
|
||||||
|
host_bindings.sizes.push_back(binding.size);
|
||||||
|
}
|
||||||
|
if (host_bindings.buffers.size() > 0) {
|
||||||
|
runtime.BindTransformFeedbackBuffers(host_bindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1616,6 +1644,8 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
||||||
|
bool dirty_index{false};
|
||||||
|
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> dirty_vertex_buffers;
|
||||||
const auto scalar_replace = [buffer_id](Binding& binding) {
|
const auto scalar_replace = [buffer_id](Binding& binding) {
|
||||||
if (binding.buffer_id == buffer_id) {
|
if (binding.buffer_id == buffer_id) {
|
||||||
binding.buffer_id = BufferId{};
|
binding.buffer_id = BufferId{};
|
||||||
|
@ -1624,8 +1654,19 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
||||||
const auto replace = [scalar_replace](std::span<Binding> bindings) {
|
const auto replace = [scalar_replace](std::span<Binding> bindings) {
|
||||||
std::ranges::for_each(bindings, scalar_replace);
|
std::ranges::for_each(bindings, scalar_replace);
|
||||||
};
|
};
|
||||||
scalar_replace(channel_state->index_buffer);
|
|
||||||
replace(channel_state->vertex_buffers);
|
if (channel_state->index_buffer.buffer_id == buffer_id) {
|
||||||
|
channel_state->index_buffer.buffer_id = BufferId{};
|
||||||
|
dirty_index = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 index = 0; index < channel_state->vertex_buffers.size(); index++) {
|
||||||
|
auto& binding = channel_state->vertex_buffers[index];
|
||||||
|
if (binding.buffer_id == buffer_id) {
|
||||||
|
binding.buffer_id = BufferId{};
|
||||||
|
dirty_vertex_buffers.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
std::ranges::for_each(channel_state->uniform_buffers, replace);
|
std::ranges::for_each(channel_state->uniform_buffers, replace);
|
||||||
std::ranges::for_each(channel_state->storage_buffers, replace);
|
std::ranges::for_each(channel_state->storage_buffers, replace);
|
||||||
replace(channel_state->transform_feedback_buffers);
|
replace(channel_state->transform_feedback_buffers);
|
||||||
|
@ -1642,20 +1683,21 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
|
||||||
delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
|
delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
|
||||||
slot_buffers.erase(buffer_id);
|
slot_buffers.erase(buffer_id);
|
||||||
|
|
||||||
NotifyBufferDeletion();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::NotifyBufferDeletion() {
|
|
||||||
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
|
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
|
||||||
channel_state->dirty_uniform_buffers.fill(~u32{0});
|
channel_state->dirty_uniform_buffers.fill(~u32{0});
|
||||||
channel_state->uniform_buffer_binding_sizes.fill({});
|
channel_state->uniform_buffer_binding_sizes.fill({});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& flags = maxwell3d->dirty.flags;
|
auto& flags = maxwell3d->dirty.flags;
|
||||||
flags[Dirty::IndexBuffer] = true;
|
if (dirty_index) {
|
||||||
flags[Dirty::VertexBuffers] = true;
|
flags[Dirty::IndexBuffer] = true;
|
||||||
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
|
}
|
||||||
flags[Dirty::VertexBuffer0 + index] = true;
|
|
||||||
|
if (dirty_vertex_buffers.size() > 0) {
|
||||||
|
flags[Dirty::VertexBuffers] = true;
|
||||||
|
for (auto index : dirty_vertex_buffers) {
|
||||||
|
flags[Dirty::VertexBuffer0 + index] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
channel_state->has_deleted_buffers = true;
|
channel_state->has_deleted_buffers = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,15 @@ static constexpr Binding NULL_BINDING{
|
||||||
.buffer_id = NULL_BUFFER_ID,
|
.buffer_id = NULL_BUFFER_ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HostBindings {
|
||||||
|
boost::container::small_vector<void*, NUM_VERTEX_BUFFERS> buffers;
|
||||||
|
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> offsets;
|
||||||
|
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> sizes;
|
||||||
|
boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> strides;
|
||||||
|
u32 min_index{NUM_VERTEX_BUFFERS};
|
||||||
|
u32 max_index{0};
|
||||||
|
};
|
||||||
|
|
||||||
class BufferCacheChannelInfo : public ChannelInfo {
|
class BufferCacheChannelInfo : public ChannelInfo {
|
||||||
public:
|
public:
|
||||||
BufferCacheChannelInfo() = delete;
|
BufferCacheChannelInfo() = delete;
|
||||||
|
@ -519,8 +528,6 @@ private:
|
||||||
|
|
||||||
void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false);
|
void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false);
|
||||||
|
|
||||||
void NotifyBufferDeletion();
|
|
||||||
|
|
||||||
[[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
|
[[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
|
||||||
bool is_written) const;
|
bool is_written) const;
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,15 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) {
|
||||||
|
for (u32 index = 0; index < bindings.buffers.size(); index++) {
|
||||||
|
BindVertexBuffer(
|
||||||
|
bindings.min_index + index, *reinterpret_cast<Buffer*>(bindings.buffers[index]),
|
||||||
|
static_cast<u32>(bindings.offsets[index]), static_cast<u32>(bindings.sizes[index]),
|
||||||
|
static_cast<u32>(bindings.strides[index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
|
void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
|
||||||
u32 offset, u32 size) {
|
u32 offset, u32 size) {
|
||||||
if (use_assembly_shaders) {
|
if (use_assembly_shaders) {
|
||||||
|
@ -320,6 +329,15 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer,
|
||||||
static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
|
static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) {
|
||||||
|
for (u32 index = 0; index < bindings.buffers.size(); index++) {
|
||||||
|
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index,
|
||||||
|
reinterpret_cast<Buffer*>(bindings.buffers[index])->Handle(),
|
||||||
|
static_cast<GLintptr>(bindings.offsets[index]),
|
||||||
|
static_cast<GLsizeiptr>(bindings.sizes[index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
||||||
PixelFormat format) {
|
PixelFormat format) {
|
||||||
*texture_handles++ = buffer.View(offset, size, format);
|
*texture_handles++ = buffer.View(offset, size, format);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/buffer_cache/buffer_cache.h"
|
#include "video_core/buffer_cache/buffer_cache_base.h"
|
||||||
#include "video_core/buffer_cache/memory_tracker_base.h"
|
#include "video_core/buffer_cache/memory_tracker_base.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/renderer_opengl/gl_device.h"
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
|
@ -87,6 +87,7 @@ public:
|
||||||
void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size);
|
void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size);
|
||||||
|
|
||||||
void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride);
|
void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride);
|
||||||
|
void BindVertexBuffers(VideoCommon::HostBindings& bindings);
|
||||||
|
|
||||||
void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size);
|
void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size);
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ public:
|
||||||
bool is_written);
|
bool is_written);
|
||||||
|
|
||||||
void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size);
|
void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size);
|
||||||
|
void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings);
|
||||||
|
|
||||||
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
||||||
VideoCore::Surface::PixelFormat format);
|
VideoCore::Surface::PixelFormat format);
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "video_core/buffer_cache/buffer_cache.h"
|
|
||||||
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
||||||
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
|
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
@ -502,6 +501,40 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) {
|
||||||
|
boost::container::small_vector<VkBuffer, 32> buffer_handles;
|
||||||
|
for (u32 index = 0; index < bindings.buffers.size(); index++) {
|
||||||
|
auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]);
|
||||||
|
auto handle = buffer.Handle();
|
||||||
|
if (handle == VK_NULL_HANDLE) {
|
||||||
|
bindings.offsets[index] = 0;
|
||||||
|
bindings.sizes[index] = VK_WHOLE_SIZE;
|
||||||
|
if (!device.HasNullDescriptor()) {
|
||||||
|
ReserveNullBuffer();
|
||||||
|
handle = *null_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer_handles.push_back(handle);
|
||||||
|
}
|
||||||
|
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||||
|
scheduler.Record([bindings = bindings,
|
||||||
|
buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
|
||||||
|
cmdbuf.BindVertexBuffers2EXT(
|
||||||
|
bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data()),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.strides.data()));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
scheduler.Record([bindings = bindings,
|
||||||
|
buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
|
||||||
|
cmdbuf.BindVertexBuffers(
|
||||||
|
bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset,
|
void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset,
|
||||||
u32 size) {
|
u32 size) {
|
||||||
if (!device.IsExtTransformFeedbackSupported()) {
|
if (!device.IsExtTransformFeedbackSupported()) {
|
||||||
|
@ -523,6 +556,25 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) {
|
||||||
|
if (!device.IsExtTransformFeedbackSupported()) {
|
||||||
|
// Already logged in the rasterizer
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boost::container::small_vector<VkBuffer, 4> buffer_handles;
|
||||||
|
for (u32 index = 0; index < bindings.buffers.size(); index++) {
|
||||||
|
auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]);
|
||||||
|
buffer_handles.push_back(buffer.Handle());
|
||||||
|
}
|
||||||
|
scheduler.Record(
|
||||||
|
[bindings = bindings, buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
|
||||||
|
cmdbuf.BindTransformFeedbackBuffersEXT(
|
||||||
|
0, static_cast<u32>(buffer_handles.size()), buffer_handles.data(),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()),
|
||||||
|
reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::ReserveNullBuffer() {
|
void BufferCacheRuntime::ReserveNullBuffer() {
|
||||||
if (null_buffer) {
|
if (null_buffer) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Vulkan {
|
||||||
class Device;
|
class Device;
|
||||||
class DescriptorPool;
|
class DescriptorPool;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
|
struct HostVertexBinding;
|
||||||
|
|
||||||
class BufferCacheRuntime;
|
class BufferCacheRuntime;
|
||||||
|
|
||||||
|
@ -96,8 +97,10 @@ public:
|
||||||
void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count);
|
void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count);
|
||||||
|
|
||||||
void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride);
|
void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride);
|
||||||
|
void BindVertexBuffers(VideoCommon::HostBindings& bindings);
|
||||||
|
|
||||||
void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
|
void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
|
||||||
|
void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings);
|
||||||
|
|
||||||
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
|
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
|
||||||
[[maybe_unused]] u32 binding_index, u32 size) {
|
[[maybe_unused]] u32 binding_index, u32 size) {
|
||||||
|
|
|
@ -101,6 +101,12 @@ const std::map<Settings::RendererBackend, QString> Config::renderer_backend_text
|
||||||
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
|
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_map = {
|
||||||
|
{Settings::ShaderBackend::GLSL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))},
|
||||||
|
{Settings::ShaderBackend::GLASM, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))},
|
||||||
|
{Settings::ShaderBackend::SPIRV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))},
|
||||||
|
};
|
||||||
|
|
||||||
// This shouldn't have anything except static initializers (no functions). So
|
// This shouldn't have anything except static initializers (no functions). So
|
||||||
// QKeySequence(...).toString() is NOT ALLOWED HERE.
|
// QKeySequence(...).toString() is NOT ALLOWED HERE.
|
||||||
// This must be in alphabetical order according to action name as it must have the same order as
|
// This must be in alphabetical order according to action name as it must have the same order as
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
static const std::map<bool, QString> use_docked_mode_texts_map;
|
static const std::map<bool, QString> use_docked_mode_texts_map;
|
||||||
static const std::map<Settings::GPUAccuracy, QString> gpu_accuracy_texts_map;
|
static const std::map<Settings::GPUAccuracy, QString> gpu_accuracy_texts_map;
|
||||||
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
|
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
|
||||||
|
static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;
|
||||||
|
|
||||||
static constexpr UISettings::Theme default_theme{
|
static constexpr UISettings::Theme default_theme{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -42,6 +42,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
|
||||||
Settings::values.use_vulkan_driver_pipeline_cache.GetValue());
|
Settings::values.use_vulkan_driver_pipeline_cache.GetValue());
|
||||||
ui->enable_compute_pipelines_checkbox->setChecked(
|
ui->enable_compute_pipelines_checkbox->setChecked(
|
||||||
Settings::values.enable_compute_pipelines.GetValue());
|
Settings::values.enable_compute_pipelines.GetValue());
|
||||||
|
ui->use_video_framerate_checkbox->setChecked(Settings::values.use_video_framerate.GetValue());
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
ui->gpu_accuracy->setCurrentIndex(
|
ui->gpu_accuracy->setCurrentIndex(
|
||||||
|
@ -91,6 +92,8 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
|
||||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines,
|
ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines,
|
||||||
ui->enable_compute_pipelines_checkbox,
|
ui->enable_compute_pipelines_checkbox,
|
||||||
enable_compute_pipelines);
|
enable_compute_pipelines);
|
||||||
|
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_video_framerate,
|
||||||
|
ui->use_video_framerate_checkbox, use_video_framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
|
void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
|
||||||
|
@ -125,6 +128,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
|
||||||
Settings::values.max_anisotropy.UsingGlobal());
|
Settings::values.max_anisotropy.UsingGlobal());
|
||||||
ui->enable_compute_pipelines_checkbox->setEnabled(
|
ui->enable_compute_pipelines_checkbox->setEnabled(
|
||||||
Settings::values.enable_compute_pipelines.UsingGlobal());
|
Settings::values.enable_compute_pipelines.UsingGlobal());
|
||||||
|
ui->use_video_framerate_checkbox->setEnabled(
|
||||||
|
Settings::values.use_video_framerate.UsingGlobal());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -149,6 +154,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
|
||||||
ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox,
|
ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox,
|
||||||
Settings::values.enable_compute_pipelines,
|
Settings::values.enable_compute_pipelines,
|
||||||
enable_compute_pipelines);
|
enable_compute_pipelines);
|
||||||
|
ConfigurationShared::SetColoredTristate(ui->use_video_framerate_checkbox,
|
||||||
|
Settings::values.use_video_framerate,
|
||||||
|
use_video_framerate);
|
||||||
ConfigurationShared::SetColoredComboBox(
|
ConfigurationShared::SetColoredComboBox(
|
||||||
ui->gpu_accuracy, ui->label_gpu_accuracy,
|
ui->gpu_accuracy, ui->label_gpu_accuracy,
|
||||||
static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
|
static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
|
||||||
|
|
|
@ -47,6 +47,7 @@ private:
|
||||||
ConfigurationShared::CheckState use_fast_gpu_time;
|
ConfigurationShared::CheckState use_fast_gpu_time;
|
||||||
ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
|
ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
|
||||||
ConfigurationShared::CheckState enable_compute_pipelines;
|
ConfigurationShared::CheckState enable_compute_pipelines;
|
||||||
|
ConfigurationShared::CheckState use_video_framerate;
|
||||||
|
|
||||||
const Core::System& system;
|
const Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
|
@ -191,6 +191,16 @@ Compute pipelines are always enabled on all other drivers.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="use_video_framerate_checkbox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Run the game at normal speed during video playback, even when the framerate is unlocked.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sync to framerate of video playback</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="af_layout" native="true">
|
<widget class="QWidget" name="af_layout" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
||||||
|
|
|
@ -4116,7 +4116,13 @@ void GMainWindow::UpdateDockedButton() {
|
||||||
void GMainWindow::UpdateAPIText() {
|
void GMainWindow::UpdateAPIText() {
|
||||||
const auto api = Settings::values.renderer_backend.GetValue();
|
const auto api = Settings::values.renderer_backend.GetValue();
|
||||||
const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second;
|
const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second;
|
||||||
renderer_status_button->setText(renderer_status_text.toUpper());
|
renderer_status_button->setText(
|
||||||
|
api == Settings::RendererBackend::OpenGL
|
||||||
|
? tr("%1 %2").arg(
|
||||||
|
renderer_status_text.toUpper(),
|
||||||
|
Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue())
|
||||||
|
->second)
|
||||||
|
: renderer_status_text.toUpper());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::UpdateFilterText() {
|
void GMainWindow::UpdateFilterText() {
|
||||||
|
|
Loading…
Reference in a new issue