aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h31
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp29
3 files changed, 52 insertions, 10 deletions
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index f65b6daf2c..b9a0225094 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -169,15 +169,40 @@ public:
void BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings);
+ /// This and the two members below are the hooks of VideoCommon::StreamUniformReusable
+ /// (buffer_cache/uniform_stream_reuse.h).
+ struct StreamUniformRef {
+ VkBuffer buffer;
+ VkDeviceAddress device_address; // base of `buffer`, 0 without buffer device address
+ u32 offset;
+ };
+
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
[[maybe_unused]] u32 binding_index,
u32 size) {
const StagingBufferRef ref = staging_pool.Request(size, MemoryUsage::Upload);
- guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address,
- static_cast<u32>(ref.offset), size);
+ last_stream_uniform = StreamUniformRef{
+ .buffer = ref.buffer,
+ .device_address = ref.device_address,
+ .offset = static_cast<u32>(ref.offset),
+ };
+ RebindStreamUniform(last_stream_uniform, size);
return ref.mapped_span;
}
+ /// The allocation of the latest BindMappedUniformBuffer call.
+ [[nodiscard]] StreamUniformRef LastStreamUniformRef() const noexcept {
+ return last_stream_uniform;
+ }
+
+ /// Adds `ref` to the descriptor payload exactly as BindMappedUniformBuffer did when it made
+ /// the allocation (it is the very same call). The caller guarantees the allocation is still
+ /// live: made on the scheduler tick that is current now, so the staging pool has not recycled
+ /// it and the GPU has not even started on it.
+ void RebindStreamUniform(const StreamUniformRef& ref, u32 size) {
+ guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address, ref.offset, size);
+ }
+
[[nodiscard]] VkDeviceSize SparseAlignmentFor(bool sparse_compatible) const noexcept {
if (!sparse_compatible || !multi_range_buffers.use_sparse) {
return 0;
@@ -278,6 +303,8 @@ private:
boost::container::small_vector<MultiRangeSource, 16> multi_range_sources;
VkDeviceSize multi_range_total{};
+ StreamUniformRef last_stream_uniform{};
+
bool limit_dynamic_storage_buffers = false;
u32 max_dynamic_storage_buffers = (std::numeric_limits<u32>::max)();
};
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index a3cd93484e..0223f56ff1 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -1072,7 +1072,7 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const
// Usually these shaders are only used once for building textures so we can assume they
// can't be built async
const auto& draw_state = maxwell3d->draw_manager.draw_state;
- if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) {
+ if (draw_state.draw_element_count <= 6) {
return pipeline;
}
return nullptr;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 978f8be547..3898c571f5 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -1127,12 +1127,10 @@ void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<DAddr, std::s
buffer_cache.WriteMemory(addr, size);
}
}
- {
- for (const auto& [addr, size] : sequences) {
- query_cache.InvalidateRegion(addr, size);
- pipeline_cache.InvalidateRegion(addr, size);
- }
+ for (const auto& [addr, size] : sequences) {
+ query_cache.InvalidateRegion(addr, size);
}
+ pipeline_cache.InvalidateRegions(sequences);
}
bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) {
@@ -1424,10 +1422,27 @@ void RasterizerVulkan::FlushWork() {
#endif // __ANDROID__
static_assert(DRAWS_TO_DISPATCH % (CHECK_MASK + 1) == 0);
- if ((++draw_counter & CHECK_MASK) != CHECK_MASK) {
+ if ((++draw_counter & CHECK_MASK) != 0) {
return;
}
- if (draw_counter < DRAWS_TO_DISPATCH) {
+ // Keep the host GPU working while native commands are still being recorded.
+ static const u32 native_flush_draws = [] {
+ constexpr u32 fallback = 128;
+ const char* value = std::getenv("EDEN_NX2_FLUSH_DRAWS");
+ if (value == nullptr || value[0] < '0' || value[0] > '9') {
+ return fallback;
+ }
+ char* end = nullptr;
+ const unsigned long parsed = std::strtoul(value, &end, 10);
+ if (*end != '\0' || parsed == 0) {
+ return fallback;
+ }
+ return static_cast<u32>(std::clamp(parsed, 32UL, 1'048'576UL));
+ }();
+ const u32 draws_to_dispatch = Tegra::g_nx2_ampere.load(std::memory_order_relaxed)
+ ? native_flush_draws
+ : DRAWS_TO_DISPATCH;
+ if (draw_counter < draws_to_dispatch) {
scheduler.DispatchWork();
return;
}