summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.cpp4
-rw-r--r--src/video_core/engines/maxwell_3d.h44
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp50
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h1
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h27
5 files changed, 98 insertions, 28 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 98ed11ec5..0e1d6d785 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -165,6 +165,7 @@ void Maxwell3D::ProcessQueryGet() {
165void Maxwell3D::DrawArrays() { 165void Maxwell3D::DrawArrays() {
166 LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(), 166 LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(),
167 regs.vertex_buffer.count); 167 regs.vertex_buffer.count);
168 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
168 169
169 auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); 170 auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
170 171
@@ -176,7 +177,8 @@ void Maxwell3D::DrawArrays() {
176 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr); 177 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
177 } 178 }
178 179
179 VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/); 180 const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
181 VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(is_indexed);
180} 182}
181 183
182void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { 184void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 1fae41cb2..2b45ffed7 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -248,6 +248,12 @@ public:
248 Patches = 0xe, 248 Patches = 0xe,
249 }; 249 };
250 250
251 enum class IndexFormat : u32 {
252 UnsignedByte = 0x0,
253 UnsignedShort = 0x1,
254 UnsignedInt = 0x2,
255 };
256
251 union { 257 union {
252 struct { 258 struct {
253 INSERT_PADDING_WORDS(0x200); 259 INSERT_PADDING_WORDS(0x200);
@@ -375,7 +381,42 @@ public:
375 }; 381 };
376 } draw; 382 } draw;
377 383
378 INSERT_PADDING_WORDS(0x139); 384 INSERT_PADDING_WORDS(0x6B);
385
386 struct {
387 u32 start_addr_high;
388 u32 start_addr_low;
389 u32 end_addr_high;
390 u32 end_addr_low;
391 IndexFormat format;
392 u32 first;
393 u32 count;
394
395 unsigned FormatSizeInBytes() const {
396 switch (format) {
397 case IndexFormat::UnsignedByte:
398 return 1;
399 case IndexFormat::UnsignedShort:
400 return 2;
401 case IndexFormat::UnsignedInt:
402 return 4;
403 }
404 UNREACHABLE();
405 }
406
407 GPUVAddr StartAddress() const {
408 return static_cast<GPUVAddr>(
409 (static_cast<GPUVAddr>(start_addr_high) << 32) | start_addr_low);
410 }
411
412 GPUVAddr EndAddress() const {
413 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(end_addr_high) << 32) |
414 end_addr_low);
415 }
416 } index_array;
417
418 INSERT_PADDING_WORDS(0xC7);
419
379 struct { 420 struct {
380 u32 query_address_high; 421 u32 query_address_high;
381 u32 query_address_low; 422 u32 query_address_low;
@@ -572,6 +613,7 @@ ASSERT_REG_POSITION(tsc, 0x557);
572ASSERT_REG_POSITION(tic, 0x55D); 613ASSERT_REG_POSITION(tic, 0x55D);
573ASSERT_REG_POSITION(code_address, 0x582); 614ASSERT_REG_POSITION(code_address, 0x582);
574ASSERT_REG_POSITION(draw, 0x585); 615ASSERT_REG_POSITION(draw, 0x585);
616ASSERT_REG_POSITION(index_array, 0x5F2);
575ASSERT_REG_POSITION(query, 0x6C0); 617ASSERT_REG_POSITION(query, 0x6C0);
576ASSERT_REG_POSITION(vertex_array[0], 0x700); 618ASSERT_REG_POSITION(vertex_array[0], 0x700);
577ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); 619ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 28abc563a..75b4031a7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -97,7 +97,6 @@ RasterizerOpenGL::RasterizerOpenGL() {
97 state.draw.vertex_buffer = stream_buffer->GetHandle(); 97 state.draw.vertex_buffer = stream_buffer->GetHandle();
98 98
99 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 99 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
100
101 state.draw.shader_program = 0; 100 state.draw.shader_program = 0;
102 state.draw.vertex_array = hw_vao.handle; 101 state.draw.vertex_array = hw_vao.handle;
103 state.Apply(); 102 state.Apply();
@@ -128,17 +127,6 @@ RasterizerOpenGL::~RasterizerOpenGL() {
128 } 127 }
129} 128}
130 129
131void RasterizerOpenGL::AnalyzeVertexArray(bool is_indexed) {
132 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
133
134 if (is_indexed) {
135 UNREACHABLE();
136 }
137
138 // TODO(bunnei): Add support for 1+ vertex arrays
139 vs_input_size = regs.vertex_buffer.count * regs.vertex_array[0].stride;
140}
141
142void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { 130void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
143 MICROPROFILE_SCOPE(OpenGL_VAO); 131 MICROPROFILE_SCOPE(OpenGL_VAO);
144 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 132 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
@@ -150,6 +138,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
150 138
151 // TODO(bunnei): Add support for 1+ vertex arrays 139 // TODO(bunnei): Add support for 1+ vertex arrays
152 const auto& vertex_array{regs.vertex_array[0]}; 140 const auto& vertex_array{regs.vertex_array[0]};
141 const auto& vertex_array_limit{regs.vertex_array_limit[0]};
153 ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?"); 142 ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?");
154 ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!"); 143 ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!");
155 for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) { 144 for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) {
@@ -162,6 +151,10 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
162 // to avoid OpenGL errors. 151 // to avoid OpenGL errors.
163 for (unsigned index = 0; index < 16; ++index) { 152 for (unsigned index = 0; index < 16; ++index) {
164 auto& attrib = regs.vertex_attrib_format[index]; 153 auto& attrib = regs.vertex_attrib_format[index];
154 NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
155 index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
156 attrib.offset.Value(), attrib.IsNormalized());
157
165 glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), 158 glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
166 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride, 159 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride,
167 reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset)); 160 reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset));
@@ -170,7 +163,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
170 } 163 }
171 164
172 // Copy vertex array data 165 // Copy vertex array data
173 const u32 data_size{vertex_array.stride * regs.vertex_buffer.count}; 166 const u64 data_size{vertex_array_limit.LimitAddress() - vertex_array.StartAddress() + 1};
174 const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())}; 167 const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
175 res_cache.FlushRegion(data_addr, data_size, nullptr); 168 res_cache.FlushRegion(data_addr, data_size, nullptr);
176 Memory::ReadBlock(data_addr, array_ptr, data_size); 169 Memory::ReadBlock(data_addr, array_ptr, data_size);
@@ -333,13 +326,18 @@ void RasterizerOpenGL::DrawArrays() {
333 326
334 // Draw the vertex batch 327 // Draw the vertex batch
335 const bool is_indexed = accelerate_draw == AccelDraw::Indexed; 328 const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
336 AnalyzeVertexArray(is_indexed); 329 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
330 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
331
332 // TODO(bunnei): Add support for 1+ vertex arrays
333 vs_input_size = vertex_num * regs.vertex_array[0].stride;
334
337 state.draw.vertex_buffer = stream_buffer->GetHandle(); 335 state.draw.vertex_buffer = stream_buffer->GetHandle();
338 state.Apply(); 336 state.Apply();
339 337
340 size_t buffer_size = static_cast<size_t>(vs_input_size); 338 size_t buffer_size = static_cast<size_t>(vs_input_size);
341 if (is_indexed) { 339 if (is_indexed) {
342 UNREACHABLE(); 340 buffer_size = Common::AlignUp(buffer_size, 4) + index_buffer_size;
343 } 341 }
344 342
345 // Uniform space for the 5 shader stages 343 // Uniform space for the 5 shader stages
@@ -354,9 +352,18 @@ void RasterizerOpenGL::DrawArrays() {
354 SetupVertexArray(buffer_ptr, buffer_offset); 352 SetupVertexArray(buffer_ptr, buffer_offset);
355 ptr_pos += vs_input_size; 353 ptr_pos += vs_input_size;
356 354
355 // If indexed mode, copy the index buffer
357 GLintptr index_buffer_offset = 0; 356 GLintptr index_buffer_offset = 0;
358 if (is_indexed) { 357 if (is_indexed) {
359 UNREACHABLE(); 358 ptr_pos = Common::AlignUp(ptr_pos, 4);
359
360 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
361 const VAddr index_data_addr{
362 memory_manager->PhysicalToVirtualAddress(regs.index_array.StartAddress())};
363 Memory::ReadBlock(index_data_addr, &buffer_ptr[ptr_pos], index_buffer_size);
364
365 index_buffer_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
366 ptr_pos += index_buffer_size;
360 } 367 }
361 368
362 SetupShaders(buffer_ptr, buffer_offset, ptr_pos); 369 SetupShaders(buffer_ptr, buffer_offset, ptr_pos);
@@ -366,11 +373,16 @@ void RasterizerOpenGL::DrawArrays() {
366 shader_program_manager->ApplyTo(state); 373 shader_program_manager->ApplyTo(state);
367 state.Apply(); 374 state.Apply();
368 375
376 const GLenum primitive_mode{MaxwellToGL::PrimitiveTopology(regs.draw.topology)};
369 if (is_indexed) { 377 if (is_indexed) {
370 UNREACHABLE(); 378 const GLint index_min{static_cast<GLint>(regs.index_array.first)};
379 const GLint index_max{static_cast<GLint>(regs.index_array.first + regs.index_array.count)};
380 glDrawRangeElementsBaseVertex(primitive_mode, index_min, index_max, regs.index_array.count,
381 MaxwellToGL::IndexFormat(regs.index_array.format),
382 reinterpret_cast<const void*>(index_buffer_offset),
383 -index_min);
371 } else { 384 } else {
372 glDrawArrays(MaxwellToGL::PrimitiveTopology(regs.draw.topology), 0, 385 glDrawArrays(primitive_mode, 0, regs.vertex_buffer.count);
373 regs.vertex_buffer.count);
374 } 386 }
375 387
376 // Disable scissor test 388 // Disable scissor test
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 548ce0453..fb5d99ba2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -155,7 +155,6 @@ private:
155 155
156 GLsizeiptr vs_input_size; 156 GLsizeiptr vs_input_size;
157 157
158 void AnalyzeVertexArray(bool is_indexed);
159 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); 158 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset);
160 159
161 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers; 160 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 7909dcfc3..632d14b78 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -31,7 +31,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
31 return GL_UNSIGNED_BYTE; 31 return GL_UNSIGNED_BYTE;
32 } 32 }
33 33
34 LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size=%s", attrib.SizeString().c_str()); 34 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString());
35 UNREACHABLE(); 35 UNREACHABLE();
36 return {}; 36 return {};
37 } 37 }
@@ -40,7 +40,21 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
40 return GL_FLOAT; 40 return GL_FLOAT;
41 } 41 }
42 42
43 LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type=%s", attrib.TypeString().c_str()); 43 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString());
44 UNREACHABLE();
45 return {};
46}
47
48inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
49 switch (index_format) {
50 case Maxwell::IndexFormat::UnsignedByte:
51 return GL_UNSIGNED_BYTE;
52 case Maxwell::IndexFormat::UnsignedShort:
53 return GL_UNSIGNED_SHORT;
54 case Maxwell::IndexFormat::UnsignedInt:
55 return GL_UNSIGNED_INT;
56 }
57 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented index_format={}", static_cast<u32>(index_format));
44 UNREACHABLE(); 58 UNREACHABLE();
45 return {}; 59 return {};
46} 60}
@@ -52,7 +66,7 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
52 case Maxwell::PrimitiveTopology::TriangleStrip: 66 case Maxwell::PrimitiveTopology::TriangleStrip:
53 return GL_TRIANGLE_STRIP; 67 return GL_TRIANGLE_STRIP;
54 } 68 }
55 LOG_CRITICAL(Render_OpenGL, "Unimplemented primitive topology=%d", topology); 69 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
56 UNREACHABLE(); 70 UNREACHABLE();
57 return {}; 71 return {};
58} 72}
@@ -64,8 +78,8 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) {
64 case Tegra::Texture::TextureFilter::Nearest: 78 case Tegra::Texture::TextureFilter::Nearest:
65 return GL_NEAREST; 79 return GL_NEAREST;
66 } 80 }
67 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode=%u", 81 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
68 static_cast<u32>(filter_mode)); 82 static_cast<u32>(filter_mode));
69 UNREACHABLE(); 83 UNREACHABLE();
70 return {}; 84 return {};
71} 85}
@@ -75,7 +89,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
75 case Tegra::Texture::WrapMode::ClampToEdge: 89 case Tegra::Texture::WrapMode::ClampToEdge:
76 return GL_CLAMP_TO_EDGE; 90 return GL_CLAMP_TO_EDGE;
77 } 91 }
78 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode=%u", static_cast<u32>(wrap_mode)); 92 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}",
93 static_cast<u32>(wrap_mode));
79 UNREACHABLE(); 94 UNREACHABLE();
80 return {}; 95 return {};
81} 96}