summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Subv2018-08-18 14:42:26 -0500
committerGravatar Subv2018-08-18 14:42:26 -0500
commite0f66c1fbfa7874df9970c2d269bd61e05758309 (patch)
treeadeffbdf54c36072ed820d56b9d55c073da3bd08
parentMerge pull request #1100 from ogniK5377/missing-pred (diff)
downloadyuzu-e0f66c1fbfa7874df9970c2d269bd61e05758309.tar.gz
yuzu-e0f66c1fbfa7874df9970c2d269bd61e05758309.tar.xz
yuzu-e0f66c1fbfa7874df9970c2d269bd61e05758309.zip
GLRasterizer: Implemented instanced vertex arrays.
Before each draw call, for every enabled vertex array configured as instanced, we take the current instance id and divide it by its configured divisor, then we multiply that by the corresponding stride and increment the start address by the resulting amount. This way we can simulate the vertex array being incremented once per instance without actually using OpenGL's instancing functions.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.h15
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp19
2 files changed, 30 insertions, 4 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 771eb5abc..3c869d3a1 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -679,7 +679,19 @@ public:
679 679
680 INSERT_PADDING_WORDS(0x7); 680 INSERT_PADDING_WORDS(0x7);
681 681
682 INSERT_PADDING_WORDS(0x46); 682 INSERT_PADDING_WORDS(0x20);
683
684 struct {
685 u32 is_instanced[NumVertexArrays];
686
687 /// Returns whether the vertex array specified by index is supposed to be
688 /// accessed per instance or not.
689 bool IsInstancingEnabled(u32 index) const {
690 return is_instanced[index];
691 }
692 } instanced_arrays;
693
694 INSERT_PADDING_WORDS(0x6);
683 695
684 Cull cull; 696 Cull cull;
685 697
@@ -928,6 +940,7 @@ ASSERT_REG_POSITION(point_coord_replace, 0x581);
928ASSERT_REG_POSITION(code_address, 0x582); 940ASSERT_REG_POSITION(code_address, 0x582);
929ASSERT_REG_POSITION(draw, 0x585); 941ASSERT_REG_POSITION(draw, 0x585);
930ASSERT_REG_POSITION(index_array, 0x5F2); 942ASSERT_REG_POSITION(index_array, 0x5F2);
943ASSERT_REG_POSITION(instanced_arrays, 0x620);
931ASSERT_REG_POSITION(cull, 0x646); 944ASSERT_REG_POSITION(cull, 0x646);
932ASSERT_REG_POSITION(clear_buffers, 0x674); 945ASSERT_REG_POSITION(clear_buffers, 0x674);
933ASSERT_REG_POSITION(query, 0x6C0); 946ASSERT_REG_POSITION(query, 0x6C0);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 93eadde7a..fe1f55e85 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -98,7 +98,8 @@ RasterizerOpenGL::~RasterizerOpenGL() {}
98std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, 98std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
99 GLintptr buffer_offset) { 99 GLintptr buffer_offset) {
100 MICROPROFILE_SCOPE(OpenGL_VAO); 100 MICROPROFILE_SCOPE(OpenGL_VAO);
101 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 101 const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
102 const auto& regs = gpu.regs;
102 103
103 state.draw.vertex_array = hw_vao.handle; 104 state.draw.vertex_array = hw_vao.handle;
104 state.draw.vertex_buffer = stream_buffer.GetHandle(); 105 state.draw.vertex_buffer = stream_buffer.GetHandle();
@@ -110,9 +111,13 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
110 if (!vertex_array.IsEnabled()) 111 if (!vertex_array.IsEnabled())
111 continue; 112 continue;
112 113
113 const Tegra::GPUVAddr start = vertex_array.StartAddress(); 114 Tegra::GPUVAddr start = vertex_array.StartAddress();
114 const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); 115 const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
115 116
117 if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
118 start += vertex_array.stride * (gpu.state.current_instance / vertex_array.divisor);
119 }
120
116 ASSERT(end > start); 121 ASSERT(end > start);
117 u64 size = end - start + 1; 122 u64 size = end - start + 1;
118 123
@@ -124,7 +129,15 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
124 glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset, 129 glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset,
125 vertex_array.stride); 130 vertex_array.stride);
126 131
127 ASSERT_MSG(vertex_array.divisor == 0, "Instanced vertex arrays are not supported"); 132 if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
133 // Tell OpenGL that this is an instanced vertex buffer to prevent accessing different
134 // indexes on each vertex. We do the instance indexing manually by incrementing the
135 // start address of the vertex buffer.
136 glVertexBindingDivisor(index, 1);
137 } else {
138 // Disable the vertex buffer instancing.
139 glVertexBindingDivisor(index, 0);
140 }
128 } 141 }
129 142
130 // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. 143 // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.