mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-09 22:58:54 +02:00
[vulkan] Adjustment ExtendedDynamicState System Nª1
This commit is contained in:
parent
3ca8bdce0d
commit
a8f4fe55cb
8 changed files with 147 additions and 29 deletions
|
|
@ -806,6 +806,58 @@ void BufferCache<P>::UpdateVertexBufferSlot(u32 index, const Binding& binding) {
|
|||
template <class P>
|
||||
void BufferCache<P>::BindHostVertexBuffers() {
|
||||
|
||||
bool needs_vertex_input_refresh = false;
|
||||
bool use_vertex_input_dynamic_state = false;
|
||||
bool use_dynamic_stride = false;
|
||||
u32 max_dynamic_stride = 0;
|
||||
std::array<u32, NUM_VERTEX_BUFFERS> min_dynamic_stride{};
|
||||
if constexpr (!IS_OPENGL) {
|
||||
use_vertex_input_dynamic_state = runtime.UsesVertexInputDynamicState();
|
||||
if (use_vertex_input_dynamic_state) {
|
||||
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
|
||||
if (maxwell3d->dirty.flags[Dirty::VertexBuffer0 + index]) {
|
||||
needs_vertex_input_refresh = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use_dynamic_stride = runtime.UsesDynamicVertexBindingStride();
|
||||
if (use_dynamic_stride) {
|
||||
max_dynamic_stride = runtime.GetMaxVertexInputBindingStride();
|
||||
for (const auto& attribute : maxwell3d->regs.vertex_attrib_format) {
|
||||
if (attribute.constant != 0) {
|
||||
continue;
|
||||
}
|
||||
const u32 binding = attribute.buffer;
|
||||
if (binding >= NUM_VERTEX_BUFFERS) {
|
||||
continue;
|
||||
}
|
||||
const u32 extent = attribute.offset + attribute.SizeInBytes();
|
||||
min_dynamic_stride[binding] = (std::max)(min_dynamic_stride[binding], extent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto sanitize_stride = [&](u32 binding, u32 stride) -> u32 {
|
||||
if constexpr (IS_OPENGL) {
|
||||
return stride;
|
||||
} else {
|
||||
if (!use_dynamic_stride || stride == 0) {
|
||||
return stride;
|
||||
}
|
||||
const u32 min_stride = min_dynamic_stride[binding];
|
||||
const u32 required_stride = (std::max)(stride, min_stride);
|
||||
if (required_stride <= max_dynamic_stride) {
|
||||
return required_stride;
|
||||
}
|
||||
if (min_stride > max_dynamic_stride) {
|
||||
return 0;
|
||||
}
|
||||
return max_dynamic_stride;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ANDROID
|
||||
const bool use_optimized_vertex_buffers = Settings::values.use_optimized_vertex_buffers.GetValue();
|
||||
#else
|
||||
|
|
@ -838,7 +890,8 @@ void BufferCache<P>::BindHostVertexBuffers() {
|
|||
continue;
|
||||
}
|
||||
flags[Dirty::VertexBuffer0 + index] = false;
|
||||
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
|
||||
const u32 stride =
|
||||
sanitize_stride(index, maxwell3d->regs.vertex_streams[index].stride);
|
||||
const u32 offset = buffer.Offset(binding.device_addr);
|
||||
buffer.MarkUsage(offset, binding.size);
|
||||
if (!bindings.buffers.empty() && index != last_index + 1) {
|
||||
|
|
@ -881,7 +934,8 @@ void BufferCache<P>::BindHostVertexBuffers() {
|
|||
const Binding& binding = channel_state->vertex_buffers[index];
|
||||
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||
|
||||
const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
|
||||
const u32 stride =
|
||||
sanitize_stride(index, maxwell3d->regs.vertex_streams[index].stride);
|
||||
const u32 offset = buffer.Offset(binding.device_addr);
|
||||
buffer.MarkUsage(offset, binding.size);
|
||||
|
||||
|
|
@ -893,6 +947,12 @@ void BufferCache<P>::BindHostVertexBuffers() {
|
|||
runtime.BindVertexBuffers(host_bindings);
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (!IS_OPENGL) {
|
||||
if (needs_vertex_input_refresh) {
|
||||
runtime.NotifyVertexInputBindingChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class P>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
|
@ -161,6 +161,28 @@ public:
|
|||
return max_dynamic_storage_buffers;
|
||||
}
|
||||
|
||||
bool UsesDynamicVertexBindingStride() const {
|
||||
return device.IsExtExtendedDynamicStateSupported() && !use_vertex_input_dynamic_state;
|
||||
}
|
||||
|
||||
bool UsesVertexInputDynamicState() const {
|
||||
return use_vertex_input_dynamic_state;
|
||||
}
|
||||
|
||||
void NotifyVertexInputBindingChange() {
|
||||
needs_vertex_input_refresh = true;
|
||||
}
|
||||
|
||||
bool ConsumeVertexInputBindingChange() {
|
||||
const bool refresh = needs_vertex_input_refresh;
|
||||
needs_vertex_input_refresh = false;
|
||||
return refresh;
|
||||
}
|
||||
|
||||
u32 GetMaxVertexInputBindingStride() const {
|
||||
return device.GetMaxVertexInputBindingStride();
|
||||
}
|
||||
|
||||
private:
|
||||
void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
|
||||
guest_descriptor_queue.AddBuffer(buffer, offset, size);
|
||||
|
|
@ -184,6 +206,7 @@ private:
|
|||
QuadIndexedPass quad_index_pass;
|
||||
|
||||
bool use_vertex_input_dynamic_state = false;
|
||||
bool needs_vertex_input_refresh = false;
|
||||
bool limit_dynamic_storage_buffers = false;
|
||||
u32 max_dynamic_storage_buffers = (std::numeric_limits<u32>::max)();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ public:
|
|||
const std::array<const Shader::Info*, NUM_STAGES>& infos);
|
||||
|
||||
bool HasDynamicVertexInput() const noexcept { return key.state.dynamic_vertex_input; }
|
||||
bool UsesVertexAttribute(size_t index) const noexcept {
|
||||
return index < Maxwell::NumVertexAttributes && stage_infos[0].loads.Generic(index);
|
||||
}
|
||||
bool SupportsAlphaToCoverage() const noexcept {
|
||||
return fragment_has_color0_output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1014,20 +1014,6 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
|||
|
||||
// EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster
|
||||
if (device.IsExtExtendedDynamicState3EnablesSupported()) {
|
||||
using namespace Tegra::Engines;
|
||||
// AMD Workaround: LogicOp incompatible with float render targets
|
||||
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
|
||||
device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
|
||||
const auto has_float = std::any_of(
|
||||
regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(),
|
||||
[](const auto& attrib) {
|
||||
return attrib.type == Maxwell3D::Regs::VertexAttribute::Type::Float;
|
||||
}
|
||||
);
|
||||
if (regs.logic_op.enable) {
|
||||
regs.logic_op.enable = static_cast<u32>(!has_float);
|
||||
}
|
||||
}
|
||||
UpdateLogicOpEnable(regs);
|
||||
UpdateDepthClampEnable(regs);
|
||||
UpdateLineRasterizationMode(regs);
|
||||
|
|
@ -1045,7 +1031,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
|||
// Vertex Input Dynamic State: Independent from EDS levels
|
||||
if (device.IsExtVertexInputDynamicStateSupported()) {
|
||||
if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) {
|
||||
UpdateVertexInput(regs);
|
||||
UpdateVertexInput(regs, *gp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1725,9 +1711,11 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs&
|
|||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs,
|
||||
const GraphicsPipeline& pipeline) {
|
||||
auto& dirty{maxwell3d->dirty.flags};
|
||||
if (!dirty[Dirty::VertexInput]) {
|
||||
const bool force_vertex_input_refresh = buffer_cache_runtime.ConsumeVertexInputBindingChange();
|
||||
if (!dirty[Dirty::VertexInput] && !force_vertex_input_refresh) {
|
||||
return;
|
||||
}
|
||||
dirty[Dirty::VertexInput] = false;
|
||||
|
|
@ -1758,6 +1746,9 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
|
|||
if (attribute.constant) {
|
||||
continue;
|
||||
}
|
||||
if (!pipeline.UsesVertexAttribute(index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t binding{attribute.buffer};
|
||||
if (binding >= max_vertex_bindings) {
|
||||
|
|
|
|||
|
|
@ -191,7 +191,8 @@ private:
|
|||
void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateBlending(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs,
|
||||
const GraphicsPipeline& pipeline);
|
||||
|
||||
Tegra::GPU& gpu;
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||
|
|
|
|||
|
|
@ -153,11 +153,17 @@ void Scheduler::RequestOutsideRenderPassOperationContext() {
|
|||
}
|
||||
|
||||
bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
|
||||
if (state.graphics_pipeline == pipeline) {
|
||||
if (pipeline && pipeline->UsesExtendedDynamicState() &&
|
||||
state.needs_state_enable_refresh) {
|
||||
state_tracker.InvalidateStateEnableFlag();
|
||||
const auto consume_eds_refresh = [this] {
|
||||
if (!state.needs_state_enable_refresh) {
|
||||
return;
|
||||
}
|
||||
state_tracker.InvalidateExtendedDynamicStateFlags();
|
||||
state.needs_state_enable_refresh = false;
|
||||
};
|
||||
|
||||
if (state.graphics_pipeline == pipeline) {
|
||||
if (pipeline && pipeline->UsesExtendedDynamicState()) {
|
||||
consume_eds_refresh();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -170,9 +176,8 @@ bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
|
|||
|
||||
if (!pipeline->UsesExtendedDynamicState()) {
|
||||
state.needs_state_enable_refresh = true;
|
||||
} else if (state.needs_state_enable_refresh) {
|
||||
state_tracker.InvalidateStateEnableFlag();
|
||||
state.needs_state_enable_refresh = false;
|
||||
} else {
|
||||
consume_eds_refresh();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
|
|
@ -101,6 +101,37 @@ public:
|
|||
(*flags)[Dirty::StateEnable] = true;
|
||||
}
|
||||
|
||||
void InvalidateExtendedDynamicStateFlags() {
|
||||
InvalidateStateEnableFlag();
|
||||
|
||||
(*flags)[Dirty::CullMode] = true;
|
||||
(*flags)[Dirty::DepthCompareOp] = true;
|
||||
(*flags)[Dirty::FrontFace] = true;
|
||||
(*flags)[Dirty::StencilOp] = true;
|
||||
(*flags)[Dirty::DepthBoundsEnable] = true;
|
||||
(*flags)[Dirty::DepthTestEnable] = true;
|
||||
(*flags)[Dirty::DepthWriteEnable] = true;
|
||||
(*flags)[Dirty::StencilTestEnable] = true;
|
||||
|
||||
(*flags)[Dirty::PrimitiveRestartEnable] = true;
|
||||
(*flags)[Dirty::RasterizerDiscardEnable] = true;
|
||||
(*flags)[Dirty::DepthBiasEnable] = true;
|
||||
(*flags)[Dirty::LogicOp] = true;
|
||||
|
||||
(*flags)[Dirty::LogicOpEnable] = true;
|
||||
(*flags)[Dirty::DepthClampEnable] = true;
|
||||
(*flags)[Dirty::LineRasterizationMode] = true;
|
||||
(*flags)[Dirty::LineStippleEnable] = true;
|
||||
(*flags)[Dirty::ConservativeRasterizationMode] = true;
|
||||
(*flags)[Dirty::AlphaToCoverageEnable] = true;
|
||||
(*flags)[Dirty::AlphaToOneEnable] = true;
|
||||
|
||||
(*flags)[Dirty::Blending] = true;
|
||||
(*flags)[Dirty::ColorMask] = true;
|
||||
(*flags)[Dirty::BlendEnable] = true;
|
||||
(*flags)[Dirty::BlendEquations] = true;
|
||||
}
|
||||
|
||||
bool TouchViewports() {
|
||||
const bool dirty_viewports = Exchange(Dirty::Viewports, false);
|
||||
const bool rescale_viewports = Exchange(VideoCommon::Dirty::RescaleViewports, false);
|
||||
|
|
|
|||
|
|
@ -783,6 +783,10 @@ public:
|
|||
return properties.properties.limits.maxVertexInputBindings;
|
||||
}
|
||||
|
||||
u32 GetMaxVertexInputBindingStride() const {
|
||||
return properties.properties.limits.maxVertexInputBindingStride;
|
||||
}
|
||||
|
||||
u32 GetMaxViewports() const {
|
||||
return properties.properties.limits.maxViewports;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue