summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.cpp160
-rw-r--r--src/video_core/engines/maxwell_3d.h13
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h2
6 files changed, 130 insertions, 74 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index b41aa6fc1..25fcdb1e3 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -126,6 +126,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
126 draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true; 126 draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true;
127 draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true; 127 draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true;
128 draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true; 128 draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true;
129 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
130 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
131 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
129} 132}
130 133
131void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { 134void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -271,6 +274,23 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
271 if (draw_command[method]) { 274 if (draw_command[method]) {
272 regs.reg_array[method] = method_argument; 275 regs.reg_array[method] = method_argument;
273 deferred_draw_method.push_back(method); 276 deferred_draw_method.push_back(method);
277 auto u32_to_u8 = [&](const u32 argument) {
278 inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff));
279 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8));
280 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16));
281 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24));
282 };
283 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) {
284 u32_to_u8(method_argument);
285 } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) {
286 u32_to_u8(regs.inline_index_2x16.even);
287 u32_to_u8(regs.inline_index_2x16.odd);
288 } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
289 u32_to_u8(regs.inline_index_4x8.index0);
290 u32_to_u8(regs.inline_index_4x8.index1);
291 u32_to_u8(regs.inline_index_4x8.index2);
292 u32_to_u8(regs.inline_index_4x8.index3);
293 }
274 } else { 294 } else {
275 ProcessDeferredDraw(); 295 ProcessDeferredDraw();
276 296
@@ -567,86 +587,94 @@ void Maxwell3D::ProcessClearBuffers() {
567} 587}
568 588
569void Maxwell3D::ProcessDeferredDraw() { 589void Maxwell3D::ProcessDeferredDraw() {
570 auto method_count = deferred_draw_method.size(); 590 if (deferred_draw_method.empty()) {
571 if (method_count) { 591 return;
572 enum class DrawMode { 592 }
573 Undefined, 593
574 General, 594 enum class DrawMode {
575 Instance, 595 Undefined,
576 }; 596 General,
577 DrawMode draw_mode{DrawMode::Undefined}; 597 Instance,
578 u32 instance_count = 1; 598 };
579 599 DrawMode draw_mode{DrawMode::Undefined};
580 auto first_method = deferred_draw_method[0]; 600 u32 instance_count = 1;
581 if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) {
582 // The minimum number of methods for drawing must be greater than or equal to
583 // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing
584 if (method_count < 3) {
585 return;
586 }
587 draw_mode =
588 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
589 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
590 ? DrawMode::Instance
591 : DrawMode::General;
592 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
593 MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
594 MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
595 draw_mode = DrawMode::General;
596 }
597 601
598 // Drawing will only begin with draw.begin or index_buffer method, other methods directly 602 auto first_method = deferred_draw_method[0];
599 // clear 603 if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) {
600 if (draw_mode == DrawMode::Undefined) { 604 // The minimum number of methods for drawing must be greater than or equal to
601 deferred_draw_method.clear(); 605 // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing
606 if (deferred_draw_method.size() < 3) {
602 return; 607 return;
603 } 608 }
609 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
610 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
611 ? DrawMode::Instance
612 : DrawMode::General;
613 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
614 MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
615 MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
616 draw_mode = DrawMode::General;
617 }
618
619 // Drawing will only begin with draw.begin or index_buffer method, other methods directly
620 // clear
621 if (draw_mode == DrawMode::Undefined) {
622 deferred_draw_method.clear();
623 return;
624 }
604 625
605 if (draw_mode == DrawMode::Instance) { 626 if (draw_mode == DrawMode::Instance) {
606 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error"); 627 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
607 instance_count = static_cast<u32>(deferred_draw_method.size()) / 4; 628 instance_count = static_cast<u32>(deferred_draw_method.size()) / 4;
629 } else {
630 if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
631 regs.index_buffer.count = regs.index_buffer32_first.count;
632 regs.index_buffer.first = regs.index_buffer32_first.first;
633 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
634 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
635 regs.index_buffer.count = regs.index_buffer16_first.count;
636 regs.index_buffer.first = regs.index_buffer16_first.first;
637 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
638 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
639 regs.index_buffer.count = regs.index_buffer8_first.count;
640 regs.index_buffer.first = regs.index_buffer8_first.first;
641 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
608 } else { 642 } else {
609 if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 643 auto second_method = deferred_draw_method[1];
610 regs.index_buffer.count = regs.index_buffer32_first.count; 644 if (MAXWELL3D_REG_INDEX(draw_inline_index) == second_method ||
611 regs.index_buffer.first = regs.index_buffer32_first.first; 645 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == second_method ||
612 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 646 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == second_method) {
613 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { 647 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
614 regs.index_buffer.count = regs.index_buffer16_first.count; 648 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
615 regs.index_buffer.first = regs.index_buffer16_first.first;
616 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
617 } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
618 regs.index_buffer.count = regs.index_buffer8_first.count;
619 regs.index_buffer.first = regs.index_buffer8_first.first;
620 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
621 } 649 }
622 } 650 }
651 }
623 652
624 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), 653 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
625 regs.vertex_buffer.count); 654 regs.vertex_buffer.count);
626 655
627 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), 656 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
628 "Both indexed and direct?");
629 657
630 // Both instance configuration registers can not be set at the same time. 658 // Both instance configuration registers can not be set at the same time.
631 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First || 659 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
632 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged, 660 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
633 "Illegal combination of instancing parameters"); 661 "Illegal combination of instancing parameters");
634 662
635 ProcessTopologyOverride(); 663 ProcessTopologyOverride();
636 664
637 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count; 665 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
638 if (ShouldExecute()) { 666 if (ShouldExecute()) {
639 rasterizer->Draw(is_indexed, instance_count); 667 rasterizer->Draw(is_indexed, instance_count);
640 } 668 }
641
642 if (is_indexed) {
643 regs.index_buffer.count = 0;
644 } else {
645 regs.vertex_buffer.count = 0;
646 }
647 669
648 deferred_draw_method.clear(); 670 if (is_indexed) {
671 regs.index_buffer.count = 0;
672 } else {
673 regs.vertex_buffer.count = 0;
649 } 674 }
675
676 deferred_draw_method.clear();
677 inline_index_draw_indexes.clear();
650} 678}
651 679
652} // namespace Tegra::Engines 680} // namespace Tegra::Engines
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 1472e8871..bd23ebc12 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1739,14 +1739,11 @@ public:
1739 Footprint_1x1_Virtual = 2, 1739 Footprint_1x1_Virtual = 2,
1740 }; 1740 };
1741 1741
1742 struct InlineIndex4x8Align { 1742 struct InlineIndex4x8 {
1743 union { 1743 union {
1744 BitField<0, 30, u32> count; 1744 BitField<0, 30, u32> count;
1745 BitField<30, 2, u32> start; 1745 BitField<30, 2, u32> start;
1746 }; 1746 };
1747 };
1748
1749 struct InlineIndex4x8Index {
1750 union { 1747 union {
1751 BitField<0, 8, u32> index0; 1748 BitField<0, 8, u32> index0;
1752 BitField<8, 8, u32> index1; 1749 BitField<8, 8, u32> index1;
@@ -2836,8 +2833,7 @@ public:
2836 u32 depth_write_enabled; ///< 0x12E8 2833 u32 depth_write_enabled; ///< 0x12E8
2837 u32 alpha_test_enabled; ///< 0x12EC 2834 u32 alpha_test_enabled; ///< 0x12EC
2838 INSERT_PADDING_BYTES_NOINIT(0x10); 2835 INSERT_PADDING_BYTES_NOINIT(0x10);
2839 InlineIndex4x8Align inline_index_4x8_align; ///< 0x1300 2836 InlineIndex4x8 inline_index_4x8; ///< 0x1300
2840 InlineIndex4x8Index inline_index_4x8_index; ///< 0x1304
2841 D3DCullMode d3d_cull_mode; ///< 0x1308 2837 D3DCullMode d3d_cull_mode; ///< 0x1308
2842 ComparisonOp depth_test_func; ///< 0x130C 2838 ComparisonOp depth_test_func; ///< 0x130C
2843 f32 alpha_test_ref; ///< 0x1310 2839 f32 alpha_test_ref; ///< 0x1310
@@ -3083,6 +3079,8 @@ public:
3083 Tables tables{}; 3079 Tables tables{};
3084 } dirty; 3080 } dirty;
3085 3081
3082 std::vector<u8> inline_index_draw_indexes;
3083
3086private: 3084private:
3087 void InitializeRegisterDefaults(); 3085 void InitializeRegisterDefaults();
3088 3086
@@ -3377,8 +3375,7 @@ ASSERT_REG_POSITION(alpha_to_coverage_dither, 0x12E0);
3377ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4); 3375ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4);
3378ASSERT_REG_POSITION(depth_write_enabled, 0x12E8); 3376ASSERT_REG_POSITION(depth_write_enabled, 0x12E8);
3379ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC); 3377ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC);
3380ASSERT_REG_POSITION(inline_index_4x8_align, 0x1300); 3378ASSERT_REG_POSITION(inline_index_4x8, 0x1300);
3381ASSERT_REG_POSITION(inline_index_4x8_index, 0x1304);
3382ASSERT_REG_POSITION(d3d_cull_mode, 0x1308); 3379ASSERT_REG_POSITION(d3d_cull_mode, 0x1308);
3383ASSERT_REG_POSITION(depth_test_func, 0x130C); 3380ASSERT_REG_POSITION(depth_test_func, 0x130C);
3384ASSERT_REG_POSITION(alpha_test_ref, 0x1310); 3381ASSERT_REG_POSITION(alpha_test_ref, 0x1310);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 21bac6ebf..1590b21de 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -222,6 +222,8 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
222 pipeline->SetEngine(maxwell3d, gpu_memory); 222 pipeline->SetEngine(maxwell3d, gpu_memory);
223 pipeline->Configure(is_indexed); 223 pipeline->Configure(is_indexed);
224 224
225 BindInlineIndexBuffer();
226
225 SyncState(); 227 SyncState();
226 228
227 const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology); 229 const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
@@ -1128,6 +1130,16 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
1128 query_cache.EraseChannel(channel_id); 1130 query_cache.EraseChannel(channel_id);
1129} 1131}
1130 1132
1133void RasterizerOpenGL::BindInlineIndexBuffer() {
1134 if (maxwell3d->inline_index_draw_indexes.empty()) {
1135 return;
1136 }
1137 const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
1138 auto buffer = Buffer(buffer_cache_runtime, *this, 0, data_count);
1139 buffer.ImmediateUpload(0, maxwell3d->inline_index_draw_indexes);
1140 buffer_cache_runtime.BindIndexBuffer(buffer, 0, data_count);
1141}
1142
1131AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} 1143AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
1132 1144
1133bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { 1145bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index c93ba3b42..793e0d608 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -199,6 +199,8 @@ private:
199 /// End a transform feedback 199 /// End a transform feedback
200 void EndTransformFeedback(); 200 void EndTransformFeedback();
201 201
202 void BindInlineIndexBuffer();
203
202 Tegra::GPU& gpu; 204 Tegra::GPU& gpu;
203 205
204 const Device& device; 206 const Device& device;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 9a7d90b2a..9f05a7a18 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -193,6 +193,8 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
193 pipeline->SetEngine(maxwell3d, gpu_memory); 193 pipeline->SetEngine(maxwell3d, gpu_memory);
194 pipeline->Configure(is_indexed); 194 pipeline->Configure(is_indexed);
195 195
196 BindInlineIndexBuffer();
197
196 BeginTransformFeedback(); 198 BeginTransformFeedback();
197 199
198 UpdateDynamicStates(); 200 UpdateDynamicStates();
@@ -1008,4 +1010,17 @@ void RasterizerVulkan::ReleaseChannel(s32 channel_id) {
1008 query_cache.EraseChannel(channel_id); 1010 query_cache.EraseChannel(channel_id);
1009} 1011}
1010 1012
1013void RasterizerVulkan::BindInlineIndexBuffer() {
1014 if (maxwell3d->inline_index_draw_indexes.empty()) {
1015 return;
1016 }
1017 const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
1018 auto buffer = buffer_cache_runtime.UploadStagingBuffer(data_count);
1019 std::memcpy(buffer.mapped_span.data(), maxwell3d->inline_index_draw_indexes.data(), data_count);
1020 buffer_cache_runtime.BindIndexBuffer(
1021 maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
1022 maxwell3d->regs.index_buffer.first, maxwell3d->regs.index_buffer.count, buffer.buffer,
1023 static_cast<u32>(buffer.offset), data_count);
1024}
1025
1011} // namespace Vulkan 1026} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index b3a182588..e2fdc7611 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -141,6 +141,8 @@ private:
141 141
142 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); 142 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
143 143
144 void BindInlineIndexBuffer();
145
144 Tegra::GPU& gpu; 146 Tegra::GPU& gpu;
145 147
146 ScreenInfo& screen_info; 148 ScreenInfo& screen_info;