diff options
Diffstat (limited to 'src')
8 files changed, 39 insertions, 11 deletions
diff --git a/src/tests/video_core/vertex_repack.cpp b/src/tests/video_core/vertex_repack.cpp index 3705a97926..5e21e3714c 100644 --- a/src/tests/video_core/vertex_repack.cpp +++ b/src/tests/video_core/vertex_repack.cpp @@ -76,10 +76,15 @@ TEST_CASE("Vertex repacking requires the captured tail and stride", "[vertex_rep REQUIRE(Vulkan::VertexRepackMask(regs) == 0); } -TEST_CASE("Static vertex repacking requires explicit experimental opt-in", "[vertex_repack]") { +TEST_CASE("Static vertex repacking follows the device stride alignment", "[vertex_repack]") { REQUIRE(Vulkan::VertexRepackInputSupported(true, false)); REQUIRE_FALSE(Vulkan::VertexRepackInputSupported(false, false)); REQUIRE(Vulkan::VertexRepackInputSupported(false, true)); + REQUIRE_FALSE(Vulkan::StaticVertexRepackSelected(nullptr, 1)); + REQUIRE(Vulkan::StaticVertexRepackSelected(nullptr, 4)); + REQUIRE(Vulkan::StaticVertexRepackSelected("1", 1)); + REQUIRE_FALSE(Vulkan::StaticVertexRepackSelected("0", 4)); + REQUIRE(Vulkan::StaticVertexRepackSelected("other", 4)); } TEST_CASE("Vertex repack planning keeps descriptor offsets aligned", "[vertex_repack]") { diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index d1f78c0034..76a564aae9 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -269,7 +269,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe if (xfb_enabled) { RefreshXfbState(xfb_state, regs); } - if (!dynamic_vertex_input && ExperimentalStaticVertexRepackEnabled()) { + if (!dynamic_vertex_input && features.has_static_vertex_repack) { const u32 repack_mask = VertexRepackMask(regs); // Refresh from guest values even when only the stride changed: offsets must not accumulate. for (size_t index = 0; index < attributes.size(); ++index) { diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 36a4b4b7a2..1fe5cd75f3 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -33,6 +33,7 @@ struct DynamicFeatures { bool has_dynamic_state3_logic_op_enable; bool has_dynamic_state3_line_stipple_enable; bool has_dynamic_vertex_input; + bool has_static_vertex_repack; bool has_color_write_enable; bool has_provoking_vertex; bool has_provoking_vertex_first_mode; diff --git a/src/video_core/renderer_vulkan/vertex_repack.h b/src/video_core/renderer_vulkan/vertex_repack.h index 456d1c6f20..493eb41bd1 100644 --- a/src/video_core/renderer_vulkan/vertex_repack.h +++ b/src/video_core/renderer_vulkan/vertex_repack.h @@ -15,12 +15,21 @@ constexpr bool VertexRepackInputSupported(bool dynamic_input, bool experimental_ return dynamic_input || experimental_static; } -inline bool ExperimentalStaticVertexRepackEnabled() { - static const bool enabled = [] { - const char* value = std::getenv("EGLANTINE_EXPERIMENTAL_STATIC_VERTEX_REPACK"); - return value && std::strcmp(value, "1") == 0; - }(); - return enabled; +// Pipelines without dynamic vertex input repack when the device cannot fetch the 69-byte stride. +// EGLANTINE_EXPERIMENTAL_STATIC_VERTEX_REPACK=1 forces the repack on, =0 forces it off. +inline bool StaticVertexRepackSelected(const char* override_value, u32 stride_alignment) { + if (override_value && std::strcmp(override_value, "1") == 0) { + return true; + } + if (override_value && std::strcmp(override_value, "0") == 0) { + return false; + } + return stride_alignment > 1 && 69 % stride_alignment != 0; +} + +inline bool StaticVertexRepackEnabled(u32 stride_alignment) { + return StaticVertexRepackSelected(std::getenv("EGLANTINE_EXPERIMENTAL_STATIC_VERTEX_REPACK"), + stride_alignment); } struct VertexRepackParameters { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 4d5ccb6520..43cb7d9414 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -365,6 +365,10 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m LOG_INFO(Render_Vulkan, "69-byte vertex layout repacking {} ({})", enable_vertex_repack ? "enabled" : "disabled", "portable Vulkan layout fallback"); + static_vertex_repack = + StaticVertexRepackEnabled(device.GetMinVertexInputBindingStrideAlignment()); + LOG_INFO(Render_Vulkan, "Vertex repacking without dynamic vertex input {}", + static_vertex_repack ? "enabled" : "disabled"); if (enable_vertex_repack) { vertex_repack_pass = std::make_unique<VertexRepackPass>( device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue); @@ -387,8 +391,7 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m u32 BufferCacheRuntime::SetVertexRepackLayout(const Tegra::Engines::Maxwell3D::Regs& regs, bool dynamic_input) { const u32 old_mask = vertex_repack_mask; - const bool input_supported = VertexRepackInputSupported( - dynamic_input, ExperimentalStaticVertexRepackEnabled()); + const bool input_supported = VertexRepackInputSupported(dynamic_input, static_vertex_repack); vertex_repack_mask = vertex_repack_pass && input_supported ? VertexRepackMask(regs) : 0; if (vertex_repack_mask != old_mask) { LOG_DEBUG(Render_Vulkan, "Vertex repack selection: mask={:#x}, dynamic_input={}", @@ -714,7 +717,7 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi bindings.strides[i] = 72; static bool reported = false; if (!reported) { - LOG_WARNING(Render_Vulkan, "Experimental GPU vertex repacking active: 69 -> 72 bytes"); + LOG_INFO(Render_Vulkan, "GPU vertex repacking active: 69 -> 72 bytes"); reported = true; } } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index a8d0274016..f65b6daf2c 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -271,6 +271,7 @@ private: std::unique_ptr<Uint8Pass> uint8_pass; std::unique_ptr<VertexRepackPass> vertex_repack_pass; u32 vertex_repack_mask{}; + bool static_vertex_repack{}; QuadIndexedPass quad_index_pass; MultiRangeBufferCache multi_range_buffers; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4df940bf71..a3cd93484e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -34,6 +34,7 @@ #include "video_core/renderer_vulkan/maxwell_to_vk.h" #include "video_core/renderer_vulkan/pipeline_helper.h" #include "video_core/renderer_vulkan/pipeline_statistics.h" +#include "video_core/renderer_vulkan/vertex_repack.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_descriptor_pool.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h" @@ -583,6 +584,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, dynamic_features.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported() && Settings::values.vertex_input_dynamic_state.GetValue(); + dynamic_features.has_static_vertex_repack = + StaticVertexRepackEnabled(device.GetMinVertexInputBindingStrideAlignment()); dynamic_features.has_provoking_vertex = device.IsExtProvokingVertexSupported(); dynamic_features.has_provoking_vertex_first_mode = diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 622d792210..5f75bcc18e 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -1161,6 +1161,12 @@ FN_MAX_LIMIT_LIST return properties.driver.driverID == VK_DRIVER_ID_MOLTENVK; } + /// The multiple vertex input binding strides must be. Metal needs 4 bytes, which MoltenVK + /// reports as minVertexInputBindingStrideAlignment through VK_KHR_portability_subset. + u32 GetMinVertexInputBindingStrideAlignment() const noexcept { + return IsMoltenVK() ? 4 : 1; + } + NvidiaArchitecture GetNvidiaArch() const noexcept { return nvidia_arch; } |
