diff options
| author | 2022-12-06 13:45:26 +0800 | |
|---|---|---|
| committer | 2022-12-08 10:12:19 +0800 | |
| commit | bf0b957c05013f33855e67c31a48e61b1e86d356 (patch) | |
| tree | 72db2458cb7e5b7572b53527e0755d4fe45e9db0 /src | |
| parent | Merge pull request #9381 from liamwhite/uninit (diff) | |
| download | yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.tar.gz yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.tar.xz yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.zip | |
video_core: Implement maxwell3d draw manager and split draw logic
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 32 | ||||
| -rw-r--r-- | src/video_core/engines/draw_manager.cpp | 191 | ||||
| -rw-r--r-- | src/video_core/engines/draw_manager.h | 69 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 171 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 25 | ||||
| -rw-r--r-- | src/video_core/macro/macro_hle.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 18 |
12 files changed, 341 insertions, 267 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index b9bad63ac..33bdae748 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -33,6 +33,8 @@ add_library(video_core STATIC | |||
| 33 | engines/sw_blitter/converter.cpp | 33 | engines/sw_blitter/converter.cpp |
| 34 | engines/sw_blitter/converter.h | 34 | engines/sw_blitter/converter.h |
| 35 | engines/const_buffer_info.h | 35 | engines/const_buffer_info.h |
| 36 | engines/draw_manager.cpp | ||
| 37 | engines/draw_manager.h | ||
| 36 | engines/engine_interface.h | 38 | engines/engine_interface.h |
| 37 | engines/engine_upload.cpp | 39 | engines/engine_upload.cpp |
| 38 | engines/engine_upload.h | 40 | engines/engine_upload.h |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6881b34c4..502b4d90a 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "video_core/control/channel_state_cache.h" | 26 | #include "video_core/control/channel_state_cache.h" |
| 27 | #include "video_core/delayed_destruction_ring.h" | 27 | #include "video_core/delayed_destruction_ring.h" |
| 28 | #include "video_core/dirty_flags.h" | 28 | #include "video_core/dirty_flags.h" |
| 29 | #include "video_core/engines/draw_manager.h" | ||
| 29 | #include "video_core/engines/kepler_compute.h" | 30 | #include "video_core/engines/kepler_compute.h" |
| 30 | #include "video_core/engines/maxwell_3d.h" | 31 | #include "video_core/engines/maxwell_3d.h" |
| 31 | #include "video_core/memory_manager.h" | 32 | #include "video_core/memory_manager.h" |
| @@ -664,9 +665,10 @@ void BufferCache<P>::BindHostGeometryBuffers(bool is_indexed) { | |||
| 664 | if (is_indexed) { | 665 | if (is_indexed) { |
| 665 | BindHostIndexBuffer(); | 666 | BindHostIndexBuffer(); |
| 666 | } else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { | 667 | } else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { |
| 667 | const auto& regs = maxwell3d->regs; | 668 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 668 | if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) { | 669 | if (draw_state.topology == Maxwell::PrimitiveTopology::Quads) { |
| 669 | runtime.BindQuadArrayIndexBuffer(regs.vertex_buffer.first, regs.vertex_buffer.count); | 670 | runtime.BindQuadArrayIndexBuffer(draw_state.vertex_buffer.first, |
| 671 | draw_state.vertex_buffer.count); | ||
| 670 | } | 672 | } |
| 671 | } | 673 | } |
| 672 | BindHostVertexBuffers(); | 674 | BindHostVertexBuffers(); |
| @@ -993,28 +995,29 @@ void BufferCache<P>::BindHostIndexBuffer() { | |||
| 993 | TouchBuffer(buffer, index_buffer.buffer_id); | 995 | TouchBuffer(buffer, index_buffer.buffer_id); |
| 994 | const u32 offset = buffer.Offset(index_buffer.cpu_addr); | 996 | const u32 offset = buffer.Offset(index_buffer.cpu_addr); |
| 995 | const u32 size = index_buffer.size; | 997 | const u32 size = index_buffer.size; |
| 996 | if (maxwell3d->inline_index_draw_indexes.size()) { | 998 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 999 | if (!draw_state.inline_index_draw_indexes.empty()) { | ||
| 997 | if constexpr (USE_MEMORY_MAPS) { | 1000 | if constexpr (USE_MEMORY_MAPS) { |
| 998 | auto upload_staging = runtime.UploadStagingBuffer(size); | 1001 | auto upload_staging = runtime.UploadStagingBuffer(size); |
| 999 | std::array<BufferCopy, 1> copies{ | 1002 | std::array<BufferCopy, 1> copies{ |
| 1000 | {BufferCopy{.src_offset = upload_staging.offset, .dst_offset = 0, .size = size}}}; | 1003 | {BufferCopy{.src_offset = upload_staging.offset, .dst_offset = 0, .size = size}}}; |
| 1001 | std::memcpy(upload_staging.mapped_span.data(), | 1004 | std::memcpy(upload_staging.mapped_span.data(), |
| 1002 | maxwell3d->inline_index_draw_indexes.data(), size); | 1005 | draw_state.inline_index_draw_indexes.data(), size); |
| 1003 | runtime.CopyBuffer(buffer, upload_staging.buffer, copies); | 1006 | runtime.CopyBuffer(buffer, upload_staging.buffer, copies); |
| 1004 | } else { | 1007 | } else { |
| 1005 | buffer.ImmediateUpload(0, maxwell3d->inline_index_draw_indexes); | 1008 | buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes); |
| 1006 | } | 1009 | } |
| 1007 | } else { | 1010 | } else { |
| 1008 | SynchronizeBuffer(buffer, index_buffer.cpu_addr, size); | 1011 | SynchronizeBuffer(buffer, index_buffer.cpu_addr, size); |
| 1009 | } | 1012 | } |
| 1010 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { | 1013 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { |
| 1011 | const u32 new_offset = offset + maxwell3d->regs.index_buffer.first * | 1014 | const u32 new_offset = |
| 1012 | maxwell3d->regs.index_buffer.FormatSizeInBytes(); | 1015 | offset + draw_state.index_buffer.first * draw_state.index_buffer.FormatSizeInBytes(); |
| 1013 | runtime.BindIndexBuffer(buffer, new_offset, size); | 1016 | runtime.BindIndexBuffer(buffer, new_offset, size); |
| 1014 | } else { | 1017 | } else { |
| 1015 | runtime.BindIndexBuffer(maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format, | 1018 | runtime.BindIndexBuffer(draw_state.topology, draw_state.index_buffer.format, |
| 1016 | maxwell3d->regs.index_buffer.first, | 1019 | draw_state.index_buffer.first, draw_state.index_buffer.count, |
| 1017 | maxwell3d->regs.index_buffer.count, buffer, offset, size); | 1020 | buffer, offset, size); |
| 1018 | } | 1021 | } |
| 1019 | } | 1022 | } |
| 1020 | 1023 | ||
| @@ -1282,15 +1285,16 @@ template <class P> | |||
| 1282 | void BufferCache<P>::UpdateIndexBuffer() { | 1285 | void BufferCache<P>::UpdateIndexBuffer() { |
| 1283 | // We have to check for the dirty flags and index count | 1286 | // We have to check for the dirty flags and index count |
| 1284 | // The index count is currently changed without updating the dirty flags | 1287 | // The index count is currently changed without updating the dirty flags |
| 1285 | const auto& index_array = maxwell3d->regs.index_buffer; | 1288 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 1289 | const auto& index_array = draw_state.index_buffer; | ||
| 1286 | auto& flags = maxwell3d->dirty.flags; | 1290 | auto& flags = maxwell3d->dirty.flags; |
| 1287 | if (!flags[Dirty::IndexBuffer] && last_index_count == index_array.count) { | 1291 | if (!flags[Dirty::IndexBuffer] && last_index_count == index_array.count) { |
| 1288 | return; | 1292 | return; |
| 1289 | } | 1293 | } |
| 1290 | flags[Dirty::IndexBuffer] = false; | 1294 | flags[Dirty::IndexBuffer] = false; |
| 1291 | last_index_count = index_array.count; | 1295 | last_index_count = index_array.count; |
| 1292 | if (maxwell3d->inline_index_draw_indexes.size()) { | 1296 | if (!draw_state.inline_index_draw_indexes.empty()) { |
| 1293 | auto inline_index_size = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size()); | 1297 | auto inline_index_size = static_cast<u32>(draw_state.inline_index_draw_indexes.size()); |
| 1294 | index_buffer = Binding{ | 1298 | index_buffer = Binding{ |
| 1295 | .cpu_addr = 0, | 1299 | .cpu_addr = 0, |
| 1296 | .size = inline_index_size, | 1300 | .size = inline_index_size, |
diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp new file mode 100644 index 000000000..c59524e58 --- /dev/null +++ b/src/video_core/engines/draw_manager.cpp | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "video_core/dirty_flags.h" | ||
| 5 | #include "video_core/engines/draw_manager.h" | ||
| 6 | #include "video_core/rasterizer_interface.h" | ||
| 7 | |||
| 8 | namespace Tegra::Engines { | ||
| 9 | DrawManager::DrawManager(Maxwell3D* maxwell3d_) : maxwell3d(maxwell3d_) {} | ||
| 10 | |||
| 11 | void DrawManager::ProcessMethodCall(u32 method, u32 argument) { | ||
| 12 | const auto& regs{maxwell3d->regs}; | ||
| 13 | switch (method) { | ||
| 14 | case MAXWELL3D_REG_INDEX(clear_surface): | ||
| 15 | return Clear(1); | ||
| 16 | case MAXWELL3D_REG_INDEX(draw.begin): | ||
| 17 | return DrawBegin(); | ||
| 18 | case MAXWELL3D_REG_INDEX(draw.end): | ||
| 19 | return DrawEnd(); | ||
| 20 | case MAXWELL3D_REG_INDEX(vertex_buffer.first): | ||
| 21 | case MAXWELL3D_REG_INDEX(vertex_buffer.count): | ||
| 22 | case MAXWELL3D_REG_INDEX(index_buffer.first): | ||
| 23 | break; | ||
| 24 | case MAXWELL3D_REG_INDEX(index_buffer.count): | ||
| 25 | draw_state.draw_indexed = true; | ||
| 26 | break; | ||
| 27 | case MAXWELL3D_REG_INDEX(index_buffer32_subsequent): | ||
| 28 | case MAXWELL3D_REG_INDEX(index_buffer16_subsequent): | ||
| 29 | case MAXWELL3D_REG_INDEX(index_buffer8_subsequent): | ||
| 30 | draw_state.instance_count++; | ||
| 31 | [[fallthrough]]; | ||
| 32 | case MAXWELL3D_REG_INDEX(index_buffer32_first): | ||
| 33 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | ||
| 34 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | ||
| 35 | return DrawIndexSmall(argument); | ||
| 36 | case MAXWELL3D_REG_INDEX(draw_inline_index): | ||
| 37 | SetInlineIndexBuffer(argument); | ||
| 38 | break; | ||
| 39 | case MAXWELL3D_REG_INDEX(inline_index_2x16.even): | ||
| 40 | SetInlineIndexBuffer(regs.inline_index_2x16.even); | ||
| 41 | SetInlineIndexBuffer(regs.inline_index_2x16.odd); | ||
| 42 | break; | ||
| 43 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): | ||
| 44 | SetInlineIndexBuffer(regs.inline_index_4x8.index0); | ||
| 45 | SetInlineIndexBuffer(regs.inline_index_4x8.index1); | ||
| 46 | SetInlineIndexBuffer(regs.inline_index_4x8.index2); | ||
| 47 | SetInlineIndexBuffer(regs.inline_index_4x8.index3); | ||
| 48 | break; | ||
| 49 | case MAXWELL3D_REG_INDEX(topology_override): | ||
| 50 | use_topology_override = true; | ||
| 51 | break; | ||
| 52 | default: | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | void DrawManager::Clear(u32 layer_count) { | ||
| 58 | maxwell3d->rasterizer->Clear(layer_count); | ||
| 59 | } | ||
| 60 | |||
| 61 | void DrawManager::DrawDeferred() { | ||
| 62 | if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) | ||
| 63 | return; | ||
| 64 | DrawEnd(draw_state.instance_count + 1, true); | ||
| 65 | draw_state.instance_count = 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | void DrawManager::DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, | ||
| 69 | u32 base_instance, u32 num_instances) { | ||
| 70 | draw_state.topology = topology; | ||
| 71 | draw_state.vertex_buffer.first = vertex_first; | ||
| 72 | draw_state.vertex_buffer.count = vertex_count; | ||
| 73 | draw_state.base_instance = base_instance; | ||
| 74 | ProcessDraw(false, num_instances); | ||
| 75 | } | ||
| 76 | |||
| 77 | void DrawManager::DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, | ||
| 78 | u32 base_index, u32 base_instance, u32 num_instances) { | ||
| 79 | const auto& regs{maxwell3d->regs}; | ||
| 80 | draw_state.topology = topology; | ||
| 81 | draw_state.index_buffer = regs.index_buffer; | ||
| 82 | draw_state.index_buffer.first = index_first; | ||
| 83 | draw_state.index_buffer.count = index_count; | ||
| 84 | draw_state.base_index = base_index; | ||
| 85 | draw_state.base_instance = base_instance; | ||
| 86 | ProcessDraw(true, num_instances); | ||
| 87 | } | ||
| 88 | |||
| 89 | void DrawManager::SetInlineIndexBuffer(u32 index) { | ||
| 90 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); | ||
| 91 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); | ||
| 92 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); | ||
| 93 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); | ||
| 94 | draw_state.draw_mode = DrawMode::InlineIndex; | ||
| 95 | } | ||
| 96 | |||
| 97 | void DrawManager::DrawBegin() { | ||
| 98 | const auto& regs{maxwell3d->regs}; | ||
| 99 | auto reset_instance_count = regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First; | ||
| 100 | auto increment_instance_count = | ||
| 101 | regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent; | ||
| 102 | if (reset_instance_count) { | ||
| 103 | DrawDeferred(); | ||
| 104 | draw_state.instance_count = 0; | ||
| 105 | draw_state.draw_mode = DrawMode::General; | ||
| 106 | } else if (increment_instance_count) { | ||
| 107 | draw_state.instance_count++; | ||
| 108 | draw_state.draw_mode = DrawMode::Instance; | ||
| 109 | } | ||
| 110 | |||
| 111 | draw_state.topology = regs.draw.topology; | ||
| 112 | } | ||
| 113 | |||
| 114 | void DrawManager::DrawEnd(u32 instance_count, bool force_draw) { | ||
| 115 | const auto& regs{maxwell3d->regs}; | ||
| 116 | switch (draw_state.draw_mode) { | ||
| 117 | case DrawMode::Instance: | ||
| 118 | if (!force_draw) | ||
| 119 | break; | ||
| 120 | [[fallthrough]]; | ||
| 121 | case DrawMode::General: | ||
| 122 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 123 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 124 | if (draw_state.draw_indexed) { | ||
| 125 | draw_state.index_buffer = regs.index_buffer; | ||
| 126 | ProcessDraw(true, instance_count); | ||
| 127 | } else { | ||
| 128 | draw_state.vertex_buffer = regs.vertex_buffer; | ||
| 129 | ProcessDraw(false, instance_count); | ||
| 130 | } | ||
| 131 | draw_state.draw_indexed = false; | ||
| 132 | break; | ||
| 133 | case DrawMode::InlineIndex: | ||
| 134 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 135 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 136 | draw_state.index_buffer = regs.index_buffer; | ||
| 137 | draw_state.index_buffer.count = | ||
| 138 | static_cast<u32>(draw_state.inline_index_draw_indexes.size() / 4); | ||
| 139 | draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt; | ||
| 140 | ProcessDraw(true, instance_count); | ||
| 141 | draw_state.inline_index_draw_indexes.clear(); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void DrawManager::DrawIndexSmall(u32 argument) { | ||
| 147 | const auto& regs{maxwell3d->regs}; | ||
| 148 | IndexBufferSmall index_small_params{argument}; | ||
| 149 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 150 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 151 | draw_state.index_buffer = regs.index_buffer; | ||
| 152 | draw_state.index_buffer.first = index_small_params.first; | ||
| 153 | draw_state.index_buffer.count = index_small_params.count; | ||
| 154 | draw_state.topology = index_small_params.topology; | ||
| 155 | maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 156 | ProcessDraw(true, 1); | ||
| 157 | } | ||
| 158 | |||
| 159 | void DrawManager::ProcessTopologyOverride() { | ||
| 160 | if (!use_topology_override) | ||
| 161 | return; | ||
| 162 | |||
| 163 | const auto& regs{maxwell3d->regs}; | ||
| 164 | switch (regs.topology_override) { | ||
| 165 | case PrimitiveTopologyOverride::None: | ||
| 166 | break; | ||
| 167 | case PrimitiveTopologyOverride::Points: | ||
| 168 | draw_state.topology = PrimitiveTopology::Points; | ||
| 169 | break; | ||
| 170 | case PrimitiveTopologyOverride::Lines: | ||
| 171 | draw_state.topology = PrimitiveTopology::Lines; | ||
| 172 | break; | ||
| 173 | case PrimitiveTopologyOverride::LineStrip: | ||
| 174 | draw_state.topology = PrimitiveTopology::LineStrip; | ||
| 175 | break; | ||
| 176 | default: | ||
| 177 | draw_state.topology = static_cast<PrimitiveTopology>(regs.topology_override); | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | void DrawManager::ProcessDraw(bool draw_indexed, u32 instance_count) { | ||
| 183 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology.Value(), | ||
| 184 | draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); | ||
| 185 | |||
| 186 | ProcessTopologyOverride(); | ||
| 187 | |||
| 188 | if (maxwell3d->ShouldExecute()) | ||
| 189 | maxwell3d->rasterizer->Draw(draw_indexed, instance_count); | ||
| 190 | } | ||
| 191 | } // namespace Tegra::Engines | ||
diff --git a/src/video_core/engines/draw_manager.h b/src/video_core/engines/draw_manager.h new file mode 100644 index 000000000..4f67027ca --- /dev/null +++ b/src/video_core/engines/draw_manager.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "video_core/engines/maxwell_3d.h" | ||
| 7 | |||
| 8 | namespace VideoCore { | ||
| 9 | class RasterizerInterface; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Tegra::Engines { | ||
| 13 | using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology; | ||
| 14 | using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride; | ||
| 15 | using IndexBuffer = Maxwell3D::Regs::IndexBuffer; | ||
| 16 | using VertexBuffer = Maxwell3D::Regs::VertexBuffer; | ||
| 17 | using IndexBufferSmall = Maxwell3D::Regs::IndexBufferSmall; | ||
| 18 | |||
| 19 | class DrawManager { | ||
| 20 | public: | ||
| 21 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; | ||
| 22 | struct State { | ||
| 23 | PrimitiveTopology topology{}; | ||
| 24 | DrawMode draw_mode{}; | ||
| 25 | bool draw_indexed{}; | ||
| 26 | u32 base_index{}; | ||
| 27 | VertexBuffer vertex_buffer; | ||
| 28 | IndexBuffer index_buffer; | ||
| 29 | u32 base_instance{}; | ||
| 30 | u32 instance_count{}; | ||
| 31 | std::vector<u8> inline_index_draw_indexes; | ||
| 32 | }; | ||
| 33 | |||
| 34 | explicit DrawManager(Maxwell3D* maxwell_3d); | ||
| 35 | |||
| 36 | void ProcessMethodCall(u32 method, u32 argument); | ||
| 37 | |||
| 38 | void Clear(u32 layer_count); | ||
| 39 | |||
| 40 | void DrawDeferred(); | ||
| 41 | |||
| 42 | void DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, | ||
| 43 | u32 base_instance, u32 num_instances); | ||
| 44 | |||
| 45 | void DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, | ||
| 46 | u32 base_instance, u32 num_instances); | ||
| 47 | |||
| 48 | const State& GetDrawState() const { | ||
| 49 | return draw_state; | ||
| 50 | } | ||
| 51 | |||
| 52 | private: | ||
| 53 | void SetInlineIndexBuffer(u32 index); | ||
| 54 | |||
| 55 | void DrawBegin(); | ||
| 56 | |||
| 57 | void DrawEnd(u32 instance_count = 1, bool force_draw = false); | ||
| 58 | |||
| 59 | void DrawIndexSmall(u32 argument); | ||
| 60 | |||
| 61 | void ProcessTopologyOverride(); | ||
| 62 | |||
| 63 | void ProcessDraw(bool draw_indexed, u32 instance_count); | ||
| 64 | |||
| 65 | Maxwell3D* maxwell3d{}; | ||
| 66 | State draw_state{}; | ||
| 67 | bool use_topology_override{}; | ||
| 68 | }; | ||
| 69 | } // namespace Tegra::Engines | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 34bbc72cf..d4ef8d7c5 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "video_core/dirty_flags.h" | 9 | #include "video_core/dirty_flags.h" |
| 10 | #include "video_core/engines/draw_manager.h" | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 11 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |
| 12 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
| @@ -21,8 +22,10 @@ using VideoCore::QueryType; | |||
| 21 | constexpr u32 MacroRegistersStart = 0xE00; | 22 | constexpr u32 MacroRegistersStart = 0xE00; |
| 22 | 23 | ||
| 23 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) | 24 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) |
| 24 | : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, | 25 | : draw_manager{std::make_unique<DrawManager>(this)}, system{system_}, |
| 25 | upload_state{memory_manager, regs.upload} { | 26 | memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, upload_state{ |
| 27 | memory_manager, | ||
| 28 | regs.upload} { | ||
| 26 | dirty.flags.flip(); | 29 | dirty.flags.flip(); |
| 27 | InitializeRegisterDefaults(); | 30 | InitializeRegisterDefaults(); |
| 28 | } | 31 | } |
| @@ -116,16 +119,6 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 116 | regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill; | 119 | regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill; |
| 117 | 120 | ||
| 118 | shadow_state = regs; | 121 | shadow_state = regs; |
| 119 | |||
| 120 | draw_command[MAXWELL3D_REG_INDEX(draw.end)] = true; | ||
| 121 | draw_command[MAXWELL3D_REG_INDEX(draw.begin)] = true; | ||
| 122 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.first)] = true; | ||
| 123 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; | ||
| 124 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; | ||
| 125 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; | ||
| 126 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; | ||
| 127 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; | ||
| 128 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; | ||
| 129 | } | 122 | } |
| 130 | 123 | ||
| 131 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { | 124 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { |
| @@ -213,29 +206,6 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 213 | return ProcessCBBind(3); | 206 | return ProcessCBBind(3); |
| 214 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): | 207 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): |
| 215 | return ProcessCBBind(4); | 208 | return ProcessCBBind(4); |
| 216 | case MAXWELL3D_REG_INDEX(index_buffer32_first): | ||
| 217 | regs.index_buffer.count = regs.index_buffer32_first.count; | ||
| 218 | regs.index_buffer.first = regs.index_buffer32_first.first; | ||
| 219 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 220 | draw_indexed = true; | ||
| 221 | return ProcessDraw(); | ||
| 222 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | ||
| 223 | regs.index_buffer.count = regs.index_buffer16_first.count; | ||
| 224 | regs.index_buffer.first = regs.index_buffer16_first.first; | ||
| 225 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 226 | draw_indexed = true; | ||
| 227 | return ProcessDraw(); | ||
| 228 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | ||
| 229 | regs.index_buffer.count = regs.index_buffer8_first.count; | ||
| 230 | regs.index_buffer.first = regs.index_buffer8_first.first; | ||
| 231 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 232 | draw_indexed = true; | ||
| 233 | return ProcessDraw(); | ||
| 234 | case MAXWELL3D_REG_INDEX(topology_override): | ||
| 235 | use_topology_override = true; | ||
| 236 | return; | ||
| 237 | case MAXWELL3D_REG_INDEX(clear_surface): | ||
| 238 | return ProcessClearBuffers(1); | ||
| 239 | case MAXWELL3D_REG_INDEX(report_semaphore.query): | 209 | case MAXWELL3D_REG_INDEX(report_semaphore.query): |
| 240 | return ProcessQueryGet(); | 210 | return ProcessQueryGet(); |
| 241 | case MAXWELL3D_REG_INDEX(render_enable.mode): | 211 | case MAXWELL3D_REG_INDEX(render_enable.mode): |
| @@ -254,6 +224,9 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 254 | return rasterizer->FragmentBarrier(); | 224 | return rasterizer->FragmentBarrier(); |
| 255 | case MAXWELL3D_REG_INDEX(tiled_cache_barrier): | 225 | case MAXWELL3D_REG_INDEX(tiled_cache_barrier): |
| 256 | return rasterizer->TiledCacheBarrier(); | 226 | return rasterizer->TiledCacheBarrier(); |
| 227 | default: | ||
| 228 | draw_manager->ProcessMethodCall(method, argument); | ||
| 229 | break; | ||
| 257 | } | 230 | } |
| 258 | } | 231 | } |
| 259 | 232 | ||
| @@ -268,7 +241,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) | |||
| 268 | // Execute the current macro. | 241 | // Execute the current macro. |
| 269 | macro_engine->Execute(macro_positions[entry], parameters); | 242 | macro_engine->Execute(macro_positions[entry], parameters); |
| 270 | 243 | ||
| 271 | ProcessDeferredDraw(); | 244 | draw_manager->DrawDeferred(); |
| 272 | } | 245 | } |
| 273 | 246 | ||
| 274 | void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 247 | void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| @@ -291,62 +264,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 291 | const u32 argument = ProcessShadowRam(method, method_argument); | 264 | const u32 argument = ProcessShadowRam(method, method_argument); |
| 292 | ProcessDirtyRegisters(method, argument); | 265 | ProcessDirtyRegisters(method, argument); |
| 293 | 266 | ||
| 294 | if (draw_command[method]) { | 267 | ProcessMethodCall(method, argument, method_argument, is_last_call); |
| 295 | regs.reg_array[method] = method_argument; | ||
| 296 | deferred_draw_method.push_back(method); | ||
| 297 | auto update_inline_index = [&](const u32 index) { | ||
| 298 | inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); | ||
| 299 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); | ||
| 300 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); | ||
| 301 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); | ||
| 302 | draw_mode = DrawMode::InlineIndex; | ||
| 303 | }; | ||
| 304 | switch (method) { | ||
| 305 | case MAXWELL3D_REG_INDEX(draw.begin): { | ||
| 306 | draw_mode = | ||
| 307 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | ||
| 308 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | ||
| 309 | ? DrawMode::Instance | ||
| 310 | : DrawMode::General; | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | case MAXWELL3D_REG_INDEX(draw.end): | ||
| 314 | switch (draw_mode) { | ||
| 315 | case DrawMode::General: | ||
| 316 | ProcessDraw(); | ||
| 317 | break; | ||
| 318 | case DrawMode::InlineIndex: | ||
| 319 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); | ||
| 320 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; | ||
| 321 | draw_indexed = true; | ||
| 322 | ProcessDraw(); | ||
| 323 | inline_index_draw_indexes.clear(); | ||
| 324 | break; | ||
| 325 | case DrawMode::Instance: | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | case MAXWELL3D_REG_INDEX(index_buffer.count): | ||
| 330 | draw_indexed = true; | ||
| 331 | break; | ||
| 332 | case MAXWELL3D_REG_INDEX(draw_inline_index): | ||
| 333 | update_inline_index(method_argument); | ||
| 334 | break; | ||
| 335 | case MAXWELL3D_REG_INDEX(inline_index_2x16.even): | ||
| 336 | update_inline_index(regs.inline_index_2x16.even); | ||
| 337 | update_inline_index(regs.inline_index_2x16.odd); | ||
| 338 | break; | ||
| 339 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): | ||
| 340 | update_inline_index(regs.inline_index_4x8.index0); | ||
| 341 | update_inline_index(regs.inline_index_4x8.index1); | ||
| 342 | update_inline_index(regs.inline_index_4x8.index2); | ||
| 343 | update_inline_index(regs.inline_index_4x8.index3); | ||
| 344 | break; | ||
| 345 | } | ||
| 346 | } else { | ||
| 347 | ProcessDeferredDraw(); | ||
| 348 | ProcessMethodCall(method, argument, method_argument, is_last_call); | ||
| 349 | } | ||
| 350 | } | 268 | } |
| 351 | 269 | ||
| 352 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | 270 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, |
| @@ -387,35 +305,6 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | |||
| 387 | } | 305 | } |
| 388 | } | 306 | } |
| 389 | 307 | ||
| 390 | void Maxwell3D::ProcessTopologyOverride() { | ||
| 391 | using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology; | ||
| 392 | using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride; | ||
| 393 | |||
| 394 | PrimitiveTopology topology{}; | ||
| 395 | |||
| 396 | switch (regs.topology_override) { | ||
| 397 | case PrimitiveTopologyOverride::None: | ||
| 398 | topology = regs.draw.topology; | ||
| 399 | break; | ||
| 400 | case PrimitiveTopologyOverride::Points: | ||
| 401 | topology = PrimitiveTopology::Points; | ||
| 402 | break; | ||
| 403 | case PrimitiveTopologyOverride::Lines: | ||
| 404 | topology = PrimitiveTopology::Lines; | ||
| 405 | break; | ||
| 406 | case PrimitiveTopologyOverride::LineStrip: | ||
| 407 | topology = PrimitiveTopology::LineStrip; | ||
| 408 | break; | ||
| 409 | default: | ||
| 410 | topology = static_cast<PrimitiveTopology>(regs.topology_override); | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (use_topology_override) { | ||
| 415 | regs.draw.topology.Assign(topology); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | void Maxwell3D::ProcessMacroUpload(u32 data) { | 308 | void Maxwell3D::ProcessMacroUpload(u32 data) { |
| 420 | macro_engine->AddCode(regs.load_mme.instruction_ptr++, data); | 309 | macro_engine->AddCode(regs.load_mme.instruction_ptr++, data); |
| 421 | } | 310 | } |
| @@ -625,44 +514,4 @@ u32 Maxwell3D::GetRegisterValue(u32 method) const { | |||
| 625 | return regs.reg_array[method]; | 514 | return regs.reg_array[method]; |
| 626 | } | 515 | } |
| 627 | 516 | ||
| 628 | void Maxwell3D::ProcessClearBuffers(u32 layer_count) { | ||
| 629 | rasterizer->Clear(layer_count); | ||
| 630 | } | ||
| 631 | |||
| 632 | void Maxwell3D::ProcessDraw(u32 instance_count) { | ||
| 633 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), | ||
| 634 | draw_indexed ? regs.index_buffer.count : regs.vertex_buffer.count); | ||
| 635 | |||
| 636 | ProcessTopologyOverride(); | ||
| 637 | |||
| 638 | if (ShouldExecute()) { | ||
| 639 | rasterizer->Draw(draw_indexed, instance_count); | ||
| 640 | } | ||
| 641 | |||
| 642 | draw_indexed = false; | ||
| 643 | deferred_draw_method.clear(); | ||
| 644 | } | ||
| 645 | |||
| 646 | void Maxwell3D::ProcessDeferredDraw() { | ||
| 647 | if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) { | ||
| 648 | return; | ||
| 649 | } | ||
| 650 | |||
| 651 | const auto method_count = deferred_draw_method.size(); | ||
| 652 | u32 instance_count = 1; | ||
| 653 | u32 vertex_buffer_count = 0; | ||
| 654 | u32 index_buffer_count = 0; | ||
| 655 | for (size_t index = 0; index < method_count; ++index) { | ||
| 656 | const u32 method = deferred_draw_method[index]; | ||
| 657 | if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) { | ||
| 658 | instance_count = ++vertex_buffer_count; | ||
| 659 | } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) { | ||
| 660 | instance_count = ++index_buffer_count; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?"); | ||
| 664 | |||
| 665 | ProcessDraw(instance_count); | ||
| 666 | } | ||
| 667 | |||
| 668 | } // namespace Tegra::Engines | 517 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index a541cd95f..22b904319 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -37,6 +37,8 @@ class RasterizerInterface; | |||
| 37 | 37 | ||
| 38 | namespace Tegra::Engines { | 38 | namespace Tegra::Engines { |
| 39 | 39 | ||
| 40 | class DrawManager; | ||
| 41 | |||
| 40 | /** | 42 | /** |
| 41 | * This Engine is known as GF100_3D. Documentation can be found in: | 43 | * This Engine is known as GF100_3D. Documentation can be found in: |
| 42 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h | 44 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h |
| @@ -2223,6 +2225,7 @@ public: | |||
| 2223 | 2225 | ||
| 2224 | struct IndexBufferSmall { | 2226 | struct IndexBufferSmall { |
| 2225 | union { | 2227 | union { |
| 2228 | u32 raw; | ||
| 2226 | BitField<0, 16, u32> first; | 2229 | BitField<0, 16, u32> first; |
| 2227 | BitField<16, 12, u32> count; | 2230 | BitField<16, 12, u32> count; |
| 2228 | BitField<28, 4, PrimitiveTopology> topology; | 2231 | BitField<28, 4, PrimitiveTopology> topology; |
| @@ -3061,10 +3064,8 @@ public: | |||
| 3061 | Tables tables{}; | 3064 | Tables tables{}; |
| 3062 | } dirty; | 3065 | } dirty; |
| 3063 | 3066 | ||
| 3064 | std::vector<u8> inline_index_draw_indexes; | 3067 | std::unique_ptr<DrawManager> draw_manager; |
| 3065 | 3068 | friend class DrawManager; | |
| 3066 | /// Handles a write to the CLEAR_BUFFERS register. | ||
| 3067 | void ProcessClearBuffers(u32 layer_count); | ||
| 3068 | 3069 | ||
| 3069 | private: | 3070 | private: |
| 3070 | void InitializeRegisterDefaults(); | 3071 | void InitializeRegisterDefaults(); |
| @@ -3122,15 +3123,6 @@ private: | |||
| 3122 | /// Handles a write to the CB_BIND register. | 3123 | /// Handles a write to the CB_BIND register. |
| 3123 | void ProcessCBBind(size_t stage_index); | 3124 | void ProcessCBBind(size_t stage_index); |
| 3124 | 3125 | ||
| 3125 | /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) | ||
| 3126 | void ProcessTopologyOverride(); | ||
| 3127 | |||
| 3128 | /// Handles deferred draw(e.g., instance draw). | ||
| 3129 | void ProcessDeferredDraw(); | ||
| 3130 | |||
| 3131 | /// Handles a draw. | ||
| 3132 | void ProcessDraw(u32 instance_count = 1); | ||
| 3133 | |||
| 3134 | /// Returns a query's value or an empty object if the value will be deferred through a cache. | 3126 | /// Returns a query's value or an empty object if the value will be deferred through a cache. |
| 3135 | std::optional<u64> GetQueryResult(); | 3127 | std::optional<u64> GetQueryResult(); |
| 3136 | 3128 | ||
| @@ -3153,13 +3145,6 @@ private: | |||
| 3153 | Upload::State upload_state; | 3145 | Upload::State upload_state; |
| 3154 | 3146 | ||
| 3155 | bool execute_on{true}; | 3147 | bool execute_on{true}; |
| 3156 | bool use_topology_override{false}; | ||
| 3157 | |||
| 3158 | std::array<bool, Regs::NUM_REGS> draw_command{}; | ||
| 3159 | std::vector<u32> deferred_draw_method; | ||
| 3160 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; | ||
| 3161 | DrawMode draw_mode{DrawMode::General}; | ||
| 3162 | bool draw_indexed{}; | ||
| 3163 | }; | 3148 | }; |
| 3164 | 3149 | ||
| 3165 | #define ASSERT_REG_POSITION(field_name, position) \ | 3150 | #define ASSERT_REG_POSITION(field_name, position) \ |
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 0f3262edb..8549db2e4 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | #include "common/scope_exit.h" | 6 | #include "common/scope_exit.h" |
| 7 | #include "video_core/dirty_flags.h" | 7 | #include "video_core/dirty_flags.h" |
| 8 | #include "video_core/engines/draw_manager.h" | ||
| 8 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
| 9 | #include "video_core/macro/macro.h" | 10 | #include "video_core/macro/macro.h" |
| 10 | #include "video_core/macro/macro_hle.h" | 11 | #include "video_core/macro/macro_hle.h" |
| @@ -18,57 +19,33 @@ using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector<u3 | |||
| 18 | // HLE'd functions | 19 | // HLE'd functions |
| 19 | void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 20 | void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { |
| 20 | const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); | 21 | const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); |
| 21 | 22 | maxwell3d.draw_manager->DrawIndex( | |
| 22 | maxwell3d.regs.draw.topology.Assign( | 23 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff), |
| 23 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff)); | 24 | parameters[4], parameters[1], parameters[3], parameters[5], instance_count); |
| 24 | maxwell3d.regs.global_base_instance_index = parameters[5]; | ||
| 25 | maxwell3d.regs.global_base_vertex_index = parameters[3]; | ||
| 26 | maxwell3d.regs.index_buffer.count = parameters[1]; | ||
| 27 | maxwell3d.regs.index_buffer.first = parameters[4]; | ||
| 28 | |||
| 29 | if (maxwell3d.ShouldExecute()) { | ||
| 30 | maxwell3d.Rasterizer().Draw(true, instance_count); | ||
| 31 | } | ||
| 32 | maxwell3d.regs.index_buffer.count = 0; | ||
| 33 | } | 25 | } |
| 34 | 26 | ||
| 35 | void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 27 | void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { |
| 36 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | 28 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); |
| 37 | 29 | maxwell3d.draw_manager->DrawArray( | |
| 38 | maxwell3d.regs.vertex_buffer.first = parameters[3]; | 30 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]), |
| 39 | maxwell3d.regs.vertex_buffer.count = parameters[1]; | 31 | parameters[3], parameters[1], parameters[4], instance_count); |
| 40 | maxwell3d.regs.global_base_instance_index = parameters[4]; | ||
| 41 | maxwell3d.regs.draw.topology.Assign( | ||
| 42 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | ||
| 43 | |||
| 44 | if (maxwell3d.ShouldExecute()) { | ||
| 45 | maxwell3d.Rasterizer().Draw(false, instance_count); | ||
| 46 | } | ||
| 47 | maxwell3d.regs.vertex_buffer.count = 0; | ||
| 48 | } | 32 | } |
| 49 | 33 | ||
| 50 | void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { | 34 | void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { |
| 51 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | 35 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); |
| 52 | const u32 element_base = parameters[4]; | 36 | const u32 element_base = parameters[4]; |
| 53 | const u32 base_instance = parameters[5]; | 37 | const u32 base_instance = parameters[5]; |
| 54 | maxwell3d.regs.index_buffer.first = parameters[3]; | ||
| 55 | maxwell3d.regs.vertex_id_base = element_base; | 38 | maxwell3d.regs.vertex_id_base = element_base; |
| 56 | maxwell3d.regs.index_buffer.count = parameters[1]; | ||
| 57 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 39 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 58 | maxwell3d.regs.global_base_vertex_index = element_base; | ||
| 59 | maxwell3d.regs.global_base_instance_index = base_instance; | ||
| 60 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 40 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 61 | maxwell3d.CallMethod(0x8e4, element_base, true); | 41 | maxwell3d.CallMethod(0x8e4, element_base, true); |
| 62 | maxwell3d.CallMethod(0x8e5, base_instance, true); | 42 | maxwell3d.CallMethod(0x8e5, base_instance, true); |
| 63 | maxwell3d.regs.draw.topology.Assign( | 43 | |
| 64 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | 44 | maxwell3d.draw_manager->DrawIndex( |
| 65 | if (maxwell3d.ShouldExecute()) { | 45 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]), |
| 66 | maxwell3d.Rasterizer().Draw(true, instance_count); | 46 | parameters[3], parameters[1], element_base, base_instance, instance_count); |
| 67 | } | 47 | |
| 68 | maxwell3d.regs.vertex_id_base = 0x0; | 48 | maxwell3d.regs.vertex_id_base = 0x0; |
| 69 | maxwell3d.regs.index_buffer.count = 0; | ||
| 70 | maxwell3d.regs.global_base_vertex_index = 0x0; | ||
| 71 | maxwell3d.regs.global_base_instance_index = 0x0; | ||
| 72 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 49 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 73 | maxwell3d.CallMethod(0x8e4, 0x0, true); | 50 | maxwell3d.CallMethod(0x8e4, 0x0, true); |
| 74 | maxwell3d.CallMethod(0x8e5, 0x0, true); | 51 | maxwell3d.CallMethod(0x8e5, 0x0, true); |
| @@ -79,9 +56,6 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 79 | SCOPE_EXIT({ | 56 | SCOPE_EXIT({ |
| 80 | // Clean everything. | 57 | // Clean everything. |
| 81 | maxwell3d.regs.vertex_id_base = 0x0; | 58 | maxwell3d.regs.vertex_id_base = 0x0; |
| 82 | maxwell3d.regs.index_buffer.count = 0; | ||
| 83 | maxwell3d.regs.global_base_vertex_index = 0x0; | ||
| 84 | maxwell3d.regs.global_base_instance_index = 0x0; | ||
| 85 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 59 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 86 | maxwell3d.CallMethod(0x8e4, 0x0, true); | 60 | maxwell3d.CallMethod(0x8e4, 0x0, true); |
| 87 | maxwell3d.CallMethod(0x8e5, 0x0, true); | 61 | maxwell3d.CallMethod(0x8e5, 0x0, true); |
| @@ -93,9 +67,6 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 93 | // Nothing to do. | 67 | // Nothing to do. |
| 94 | return; | 68 | return; |
| 95 | } | 69 | } |
| 96 | const auto topology = | ||
| 97 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]); | ||
| 98 | maxwell3d.regs.draw.topology.Assign(topology); | ||
| 99 | const u32 padding = parameters[3]; | 70 | const u32 padding = parameters[3]; |
| 100 | const std::size_t max_draws = parameters[4]; | 71 | const std::size_t max_draws = parameters[4]; |
| 101 | 72 | ||
| @@ -106,23 +77,17 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 106 | 77 | ||
| 107 | for (std::size_t index = first_draw; index < last_draw; index++) { | 78 | for (std::size_t index = first_draw; index < last_draw; index++) { |
| 108 | const std::size_t base = index * indirect_words + 5; | 79 | const std::size_t base = index * indirect_words + 5; |
| 109 | const u32 num_vertices = parameters[base]; | ||
| 110 | const u32 instance_count = parameters[base + 1]; | ||
| 111 | const u32 first_index = parameters[base + 2]; | ||
| 112 | const u32 base_vertex = parameters[base + 3]; | 80 | const u32 base_vertex = parameters[base + 3]; |
| 113 | const u32 base_instance = parameters[base + 4]; | 81 | const u32 base_instance = parameters[base + 4]; |
| 114 | maxwell3d.regs.index_buffer.first = first_index; | ||
| 115 | maxwell3d.regs.vertex_id_base = base_vertex; | 82 | maxwell3d.regs.vertex_id_base = base_vertex; |
| 116 | maxwell3d.regs.index_buffer.count = num_vertices; | ||
| 117 | maxwell3d.regs.global_base_vertex_index = base_vertex; | ||
| 118 | maxwell3d.regs.global_base_instance_index = base_instance; | ||
| 119 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 83 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 120 | maxwell3d.CallMethod(0x8e4, base_vertex, true); | 84 | maxwell3d.CallMethod(0x8e4, base_vertex, true); |
| 121 | maxwell3d.CallMethod(0x8e5, base_instance, true); | 85 | maxwell3d.CallMethod(0x8e5, base_instance, true); |
| 122 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 86 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 123 | if (maxwell3d.ShouldExecute()) { | 87 | maxwell3d.draw_manager->DrawIndex( |
| 124 | maxwell3d.Rasterizer().Draw(true, instance_count); | 88 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]), |
| 125 | } | 89 | parameters[base + 2], parameters[base], base_vertex, base_instance, |
| 90 | parameters[base + 1]); | ||
| 126 | } | 91 | } |
| 127 | } | 92 | } |
| 128 | 93 | ||
| @@ -136,7 +101,7 @@ void HLE_EAD26C3E2109B06B(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& | |||
| 136 | ASSERT(clear_params.layer == 0); | 101 | ASSERT(clear_params.layer == 0); |
| 137 | 102 | ||
| 138 | maxwell3d.regs.clear_surface.raw = clear_params.raw; | 103 | maxwell3d.regs.clear_surface.raw = clear_params.raw; |
| 139 | maxwell3d.ProcessClearBuffers(num_layers); | 104 | maxwell3d.draw_manager->Clear(num_layers); |
| 140 | } | 105 | } |
| 141 | 106 | ||
| 142 | constexpr std::array<std::pair<u64, HLEFunction>, 5> hle_funcs{{ | 107 | constexpr std::array<std::pair<u64, HLEFunction>, 5> hle_funcs{{ |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index f71a316b6..64ed6f628 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -224,16 +224,18 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { | |||
| 224 | 224 | ||
| 225 | SyncState(); | 225 | SyncState(); |
| 226 | 226 | ||
| 227 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology); | 227 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 228 | |||
| 229 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology); | ||
| 228 | BeginTransformFeedback(pipeline, primitive_mode); | 230 | BeginTransformFeedback(pipeline, primitive_mode); |
| 229 | 231 | ||
| 230 | const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.global_base_instance_index); | 232 | const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance); |
| 231 | const GLsizei num_instances = static_cast<GLsizei>(instance_count); | 233 | const GLsizei num_instances = static_cast<GLsizei>(instance_count); |
| 232 | if (is_indexed) { | 234 | if (is_indexed) { |
| 233 | const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.global_base_vertex_index); | 235 | const GLint base_vertex = static_cast<GLint>(draw_state.base_index); |
| 234 | const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count); | 236 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count); |
| 235 | const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); | 237 | const GLvoid* const offset = buffer_cache_runtime.IndexOffset(); |
| 236 | const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); | 238 | const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format); |
| 237 | if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { | 239 | if (num_instances == 1 && base_instance == 0 && base_vertex == 0) { |
| 238 | glDrawElements(primitive_mode, num_vertices, format, offset); | 240 | glDrawElements(primitive_mode, num_vertices, format, offset); |
| 239 | } else if (num_instances == 1 && base_instance == 0) { | 241 | } else if (num_instances == 1 && base_instance == 0) { |
| @@ -252,8 +254,8 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) { | |||
| 252 | base_instance); | 254 | base_instance); |
| 253 | } | 255 | } |
| 254 | } else { | 256 | } else { |
| 255 | const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.vertex_buffer.first); | 257 | const GLint base_vertex = static_cast<GLint>(draw_state.vertex_buffer.first); |
| 256 | const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.vertex_buffer.count); | 258 | const GLsizei num_vertices = static_cast<GLsizei>(draw_state.vertex_buffer.count); |
| 257 | if (num_instances == 1 && base_instance == 0) { | 259 | if (num_instances == 1 && base_instance == 0) { |
| 258 | glDrawArrays(primitive_mode, base_vertex, num_vertices); | 260 | glDrawArrays(primitive_mode, base_vertex, num_vertices); |
| 259 | } else if (base_instance == 0) { | 261 | } else if (base_instance == 0) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index a38060100..a59d0d24e 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | 22 | #include "shader_recompiler/frontend/maxwell/control_flow.h" |
| 23 | #include "shader_recompiler/frontend/maxwell/translate_program.h" | 23 | #include "shader_recompiler/frontend/maxwell/translate_program.h" |
| 24 | #include "shader_recompiler/profile.h" | 24 | #include "shader_recompiler/profile.h" |
| 25 | #include "video_core/engines/draw_manager.h" | ||
| 25 | #include "video_core/engines/kepler_compute.h" | 26 | #include "video_core/engines/kepler_compute.h" |
| 26 | #include "video_core/engines/maxwell_3d.h" | 27 | #include "video_core/engines/maxwell_3d.h" |
| 27 | #include "video_core/memory_manager.h" | 28 | #include "video_core/memory_manager.h" |
| @@ -327,7 +328,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | |||
| 327 | const auto& regs{maxwell3d->regs}; | 328 | const auto& regs{maxwell3d->regs}; |
| 328 | graphics_key.raw = 0; | 329 | graphics_key.raw = 0; |
| 329 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); | 330 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); |
| 330 | graphics_key.gs_input_topology.Assign(regs.draw.topology.Value()); | 331 | graphics_key.gs_input_topology.Assign(maxwell3d->draw_manager->GetDrawState().topology); |
| 331 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); | 332 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); |
| 332 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); | 333 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); |
| 333 | graphics_key.tessellation_clockwise.Assign( | 334 | graphics_key.tessellation_clockwise.Assign( |
| @@ -371,7 +372,8 @@ GraphicsPipeline* ShaderCache::BuiltPipeline(GraphicsPipeline* pipeline) const n | |||
| 371 | // If games are using a small index count, we can assume these are full screen quads. | 372 | // If games are using a small index count, we can assume these are full screen quads. |
| 372 | // Usually these shaders are only used once for building textures so we can assume they | 373 | // Usually these shaders are only used once for building textures so we can assume they |
| 373 | // can't be built async | 374 | // can't be built async |
| 374 | if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) { | 375 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 376 | if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) { | ||
| 375 | return pipeline; | 377 | return pipeline; |
| 376 | } | 378 | } |
| 377 | return nullptr; | 379 | return nullptr; |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index f3f08b42c..24529c80f 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/cityhash.h" | 8 | #include "common/cityhash.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_ranges.h" | 10 | #include "common/polyfill_ranges.h" |
| 11 | #include "video_core/engines/draw_manager.h" | ||
| 11 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 12 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 12 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | 13 | #include "video_core/renderer_vulkan/vk_state_tracker.h" |
| 13 | 14 | ||
| @@ -50,12 +51,13 @@ void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& | |||
| 50 | void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, | 51 | void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, |
| 51 | bool has_extended_dynamic_state, bool has_dynamic_vertex_input) { | 52 | bool has_extended_dynamic_state, bool has_dynamic_vertex_input) { |
| 52 | const Maxwell& regs = maxwell3d.regs; | 53 | const Maxwell& regs = maxwell3d.regs; |
| 54 | const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology; | ||
| 53 | const std::array enabled_lut{ | 55 | const std::array enabled_lut{ |
| 54 | regs.polygon_offset_point_enable, | 56 | regs.polygon_offset_point_enable, |
| 55 | regs.polygon_offset_line_enable, | 57 | regs.polygon_offset_line_enable, |
| 56 | regs.polygon_offset_fill_enable, | 58 | regs.polygon_offset_fill_enable, |
| 57 | }; | 59 | }; |
| 58 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); | 60 | const u32 topology_index = static_cast<u32>(topology_); |
| 59 | 61 | ||
| 60 | raw1 = 0; | 62 | raw1 = 0; |
| 61 | extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0); | 63 | extended_dynamic_state.Assign(has_extended_dynamic_state ? 1 : 0); |
| @@ -78,7 +80,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, | |||
| 78 | Maxwell::Tessellation::OutputPrimitives::Triangles_CW); | 80 | Maxwell::Tessellation::OutputPrimitives::Triangles_CW); |
| 79 | logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0); | 81 | logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0); |
| 80 | logic_op.Assign(PackLogicOp(regs.logic_op.op)); | 82 | logic_op.Assign(PackLogicOp(regs.logic_op.op)); |
| 81 | topology.Assign(regs.draw.topology); | 83 | topology.Assign(topology_); |
| 82 | msaa_mode.Assign(regs.anti_alias_samples_mode); | 84 | msaa_mode.Assign(regs.anti_alias_samples_mode); |
| 83 | 85 | ||
| 84 | raw2 = 0; | 86 | raw2 = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 38a6b7488..81f5f3e11 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -507,7 +507,8 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const | |||
| 507 | // If games are using a small index count, we can assume these are full screen quads. | 507 | // If games are using a small index count, we can assume these are full screen quads. |
| 508 | // Usually these shaders are only used once for building textures so we can assume they | 508 | // Usually these shaders are only used once for building textures so we can assume they |
| 509 | // can't be built async | 509 | // can't be built async |
| 510 | if (maxwell3d->regs.index_buffer.count <= 6 || maxwell3d->regs.vertex_buffer.count <= 6) { | 510 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 511 | if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) { | ||
| 511 | return pipeline; | 512 | return pipeline; |
| 512 | } | 513 | } |
| 513 | return nullptr; | 514 | return nullptr; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d8ad8815c..8d7a5e400 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/scope_exit.h" | 12 | #include "common/scope_exit.h" |
| 13 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 14 | #include "video_core/control/channel_state.h" | 14 | #include "video_core/control/channel_state.h" |
| 15 | #include "video_core/engines/draw_manager.h" | ||
| 15 | #include "video_core/engines/kepler_compute.h" | 16 | #include "video_core/engines/kepler_compute.h" |
| 16 | #include "video_core/engines/maxwell_3d.h" | 17 | #include "video_core/engines/maxwell_3d.h" |
| 17 | #include "video_core/renderer_vulkan/blit_image.h" | 18 | #include "video_core/renderer_vulkan/blit_image.h" |
| @@ -36,6 +37,7 @@ | |||
| 36 | namespace Vulkan { | 37 | namespace Vulkan { |
| 37 | 38 | ||
| 38 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 39 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 40 | using MaxwellDrawState = Tegra::Engines::DrawManager::State; | ||
| 39 | using VideoCommon::ImageViewId; | 41 | using VideoCommon::ImageViewId; |
| 40 | using VideoCommon::ImageViewType; | 42 | using VideoCommon::ImageViewType; |
| 41 | 43 | ||
| @@ -127,16 +129,16 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 | |||
| 127 | return scissor; | 129 | return scissor; |
| 128 | } | 130 | } |
| 129 | 131 | ||
| 130 | DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_indexed) { | 132 | DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, bool is_indexed) { |
| 131 | DrawParams params{ | 133 | DrawParams params{ |
| 132 | .base_instance = regs.global_base_instance_index, | 134 | .base_instance = draw_state.base_instance, |
| 133 | .num_instances = num_instances, | 135 | .num_instances = num_instances, |
| 134 | .base_vertex = is_indexed ? regs.global_base_vertex_index : regs.vertex_buffer.first, | 136 | .base_vertex = is_indexed ? draw_state.base_index : draw_state.vertex_buffer.first, |
| 135 | .num_vertices = is_indexed ? regs.index_buffer.count : regs.vertex_buffer.count, | 137 | .num_vertices = is_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count, |
| 136 | .first_index = is_indexed ? regs.index_buffer.first : 0, | 138 | .first_index = is_indexed ? draw_state.index_buffer.first : 0, |
| 137 | .is_indexed = is_indexed, | 139 | .is_indexed = is_indexed, |
| 138 | }; | 140 | }; |
| 139 | if (regs.draw.topology == Maxwell::PrimitiveTopology::Quads) { | 141 | if (draw_state.topology == Maxwell::PrimitiveTopology::Quads) { |
| 140 | // 6 triangle vertices per quad, base vertex is part of the index | 142 | // 6 triangle vertices per quad, base vertex is part of the index |
| 141 | // See BindQuadArrayIndexBuffer for more details | 143 | // See BindQuadArrayIndexBuffer for more details |
| 142 | params.num_vertices = (params.num_vertices / 4) * 6; | 144 | params.num_vertices = (params.num_vertices / 4) * 6; |
| @@ -195,9 +197,9 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) { | |||
| 195 | 197 | ||
| 196 | UpdateDynamicStates(); | 198 | UpdateDynamicStates(); |
| 197 | 199 | ||
| 198 | const auto& regs{maxwell3d->regs}; | 200 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 199 | const u32 num_instances{instance_count}; | 201 | const u32 num_instances{instance_count}; |
| 200 | const DrawParams draw_params{MakeDrawParams(regs, num_instances, is_indexed)}; | 202 | const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)}; |
| 201 | scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { | 203 | scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { |
| 202 | if (draw_params.is_indexed) { | 204 | if (draw_params.is_indexed) { |
| 203 | cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, | 205 | cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, |