diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 3165483388..5705954ae6 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1006,7 +1006,7 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 } template -void BufferCache

::ResolveMultiRangeStorage(Binding& binding, bool is_written, +void BufferCache

::ResolveMultiRangeStorage(Binding& binding, std::vector& pool) { binding.segment_first = 0; binding.segment_count = 0; @@ -1014,15 +1014,17 @@ void BufferCache

::ResolveMultiRangeStorage(Binding& binding, bool is_written, if (binding.gpu_addr == 0 || binding.size == 0) { return; } - if (is_written && !runtime.PrefersSparseSources()) { - return; - } const VirtualSegments* found = virtual_ranges.Query(*gpu_memory, binding.gpu_addr, binding.size); if (!found || found->size() < 2) { return; } const VirtualSegments segments = *found; + for (const VirtualSegment& segment : segments) { + if (memory_tracker.IsRegionGpuModified(segment.device_addr, segment.size)) { + return; + } + } const u32 first = static_cast(pool.size()); const bool prefer_sparse = runtime.PrefersSparseSources(); for (const VirtualSegment& segment : segments) { @@ -1439,8 +1441,7 @@ void BufferCache

::UpdateStorageBuffers(size_t stage) { Binding& binding = channel_state->storage_buffers[stage][index]; const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size, false); binding.buffer_id = buffer_id; - const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0; - ResolveMultiRangeStorage(binding, is_written, graphics_segments); + ResolveMultiRangeStorage(binding, graphics_segments); }); } @@ -1504,9 +1505,7 @@ void BufferCache

::UpdateComputeStorageBuffers() { // Resolve buffer Binding& binding = channel_state->compute_storage_buffers[index]; binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false); - const bool is_written = - ((channel_state->written_compute_storage_buffers >> index) & 1) != 0; - ResolveMultiRangeStorage(binding, is_written, compute_segments); + ResolveMultiRangeStorage(binding, compute_segments); }); } diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 0dbb368c47..61b3e9bbab 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -228,8 +228,7 @@ public: bool BindMultiRangeStorage(const Binding& binding, bool is_written, std::span pool); - void ResolveMultiRangeStorage(Binding& binding, bool is_written, - std::vector& pool); + void ResolveMultiRangeStorage(Binding& binding, std::vector& pool); void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size); diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp index 682b5ae048..b38847db6b 100644 --- a/src/video_core/engines/draw_manager.cpp +++ b/src/video_core/engines/draw_manager.cpp @@ -76,16 +76,20 @@ void Maxwell3D::DrawManager::Clear(Maxwell3D& maxwell3d, u32 layer_count) { } } -void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) { - if (draw_state.draw_mode == DrawMode::InstanceArray) { - const u32 instance_count = draw_state.instance_count + 1; - draw_state.draw_mode = DrawMode::General; - draw_state.instance_count = 0; - if (maxwell3d.ShouldExecute()) { - maxwell3d.rasterizer->Draw(false, instance_count); - } +void Maxwell3D::DrawManager::FlushInstanceArray(Maxwell3D& maxwell3d) { + if (draw_state.draw_mode != DrawMode::InstanceArray) { return; } + const u32 instance_count = draw_state.instance_count + 1; + draw_state.draw_mode = DrawMode::General; + draw_state.instance_count = 0; + if (draw_state.vertex_buffer.count != 0 && maxwell3d.ShouldExecute()) { + maxwell3d.rasterizer->Draw(false, instance_count); + } +} + +void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) { + FlushInstanceArray(maxwell3d); if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) { return; } @@ -94,6 +98,7 @@ void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) { } void Maxwell3D::DrawManager::DrawArray(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, u32 base_instance, u32 num_instances) { + FlushInstanceArray(maxwell3d); draw_state.topology = topology; draw_state.vertex_buffer.first = vertex_first; draw_state.vertex_buffer.count = vertex_count; @@ -124,6 +129,7 @@ void Maxwell3D::DrawManager::DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D: } void Maxwell3D::DrawManager::DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, u32 base_instance, u32 num_instances) { + FlushInstanceArray(maxwell3d); draw_state.topology = topology; draw_state.index_buffer = maxwell3d.regs.index_buffer; draw_state.index_buffer.first = index_first; @@ -134,11 +140,13 @@ void Maxwell3D::DrawManager::DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::Pr } void Maxwell3D::DrawManager::DrawArrayIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology) { + FlushInstanceArray(maxwell3d); draw_state.topology = topology; ProcessDrawIndirect(maxwell3d); } void Maxwell3D::DrawManager::DrawIndexedIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count) { + FlushInstanceArray(maxwell3d); draw_state.topology = topology; draw_state.index_buffer = maxwell3d.regs.index_buffer; draw_state.index_buffer.first = index_first; @@ -209,7 +217,7 @@ void Maxwell3D::DrawManager::DrawBegin(Maxwell3D& maxwell3d) { void Maxwell3D::DrawManager::DrawEnd(Maxwell3D& maxwell3d, u32 instance_count, bool force_draw) { switch (draw_state.draw_mode) { case DrawMode::InstanceArray: - DrawDeferred(maxwell3d); + FlushInstanceArray(maxwell3d); break; case DrawMode::Instance: if (!force_draw) { @@ -301,6 +309,13 @@ void Maxwell3D::DrawManager::UpdateTopology(Maxwell3D& maxwell3d) { void Maxwell3D::DrawManager::ProcessDraw(Maxwell3D& maxwell3d, bool draw_indexed, u32 instance_count) { LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology, draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); UpdateTopology(maxwell3d); + u32 count = draw_state.vertex_buffer.count; + if (draw_indexed) { + count = draw_state.index_buffer.count; + } + if (count == 0) { + return; + } if (maxwell3d.ShouldExecute()) { maxwell3d.rasterizer->Draw(draw_indexed, instance_count); } diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 277304ed76..ae4b761ced 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -3071,6 +3071,7 @@ public: void ProcessMethodCall(Maxwell3D& maxwell3d, u32 method, u32 argument); void Clear(Maxwell3D& maxwell3d, u32 layer_count); void DrawDeferred(Maxwell3D& maxwell3d); + void FlushInstanceArray(Maxwell3D& maxwell3d); void DrawArray(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, u32 base_instance, u32 num_instances); void DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, bool subsequent); void DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, u32 base_instance, u32 num_instances); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 92c5574691..b5eb0c5763 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -166,7 +166,11 @@ DrawParams MakeDrawParams(const Tegra::Engines::Maxwell3D::DrawManager::State& d params.base_vertex = 0; params.is_indexed = true; } else if (draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) { - params.num_vertices = (params.num_vertices - 2) / 2 * 6; + u32 strips = 0; + if (params.num_vertices >= 2) { + strips = (params.num_vertices - 2) / 2; + } + params.num_vertices = strips * 6; params.base_vertex = 0; params.is_indexed = true; } @@ -251,7 +255,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { if (!pipeline->Configure(is_indexed)) return; - UpdateDynamicStates(); + UpdateDynamicStates(pipeline->HasDynamicVertexInput()); query_cache.NotifySegment(true); HandleTransformFeedback(); @@ -361,7 +365,12 @@ void RasterizerVulkan::DrawTexture() { texture_cache.SynchronizeDescriptors(false); texture_cache.UpdateRenderTargets(false); - UpdateDynamicStates(); + bool dynamic_vertex_input = false; + if (device.IsExtVertexInputDynamicStateSupported()) { + GraphicsPipeline* const gp = pipeline_cache.CurrentGraphicsPipeline(); + dynamic_vertex_input = gp && gp->HasDynamicVertexInput(); + } + UpdateDynamicStates(dynamic_vertex_input); query_cache.NotifySegment(true); query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable); @@ -1060,7 +1069,7 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info, return DmaBufferImageCopy(copy_info, buffer_operand, image_operand); } -void RasterizerVulkan::UpdateDynamicStates() { +void RasterizerVulkan::UpdateDynamicStates(bool dynamic_vertex_input) { auto& regs = maxwell3d->regs; auto& flags = maxwell3d->dirty.flags; const auto topology = maxwell3d->draw_manager.draw_state.topology; @@ -1137,10 +1146,8 @@ void RasterizerVulkan::UpdateDynamicStates() { UpdateColorWriteEnable(regs); } - if (device.IsExtVertexInputDynamicStateSupported()) { - if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) { - UpdateVertexInput(regs); - } + if (dynamic_vertex_input) { + UpdateVertexInput(regs); } } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 7470aa4f14..59bcf65ec4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -159,7 +159,7 @@ private: void FlushWork(); - void UpdateDynamicStates(); + void UpdateDynamicStates(bool dynamic_vertex_input); void HandleTransformFeedback();