Просмотр исходного кода

gl_rasterizer: Implement SetupVertexArray.

bunnei 8 лет назад
Родитель
Сommit
c2dbdefedf
1 измененных файлов с 38 добавлено и 20 удалено
  1. 38 20
      src/video_core/renderer_opengl/gl_rasterizer.cpp

+ 38 - 20
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -142,37 +142,55 @@ RasterizerOpenGL::~RasterizerOpenGL() {
     }
 }
 
-static constexpr std::array<GLenum, 4> vs_attrib_types{
-    GL_BYTE,          // VertexAttributeFormat::BYTE
-    GL_UNSIGNED_BYTE, // VertexAttributeFormat::UBYTE
-    GL_SHORT,         // VertexAttributeFormat::SHORT
-    GL_FLOAT          // VertexAttributeFormat::FLOAT
-};
-
 void RasterizerOpenGL::AnalyzeVertexArray(bool is_indexed) {
     const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
-    const auto& vertex_attributes = regs.vertex_attrib_format;
 
     if (is_indexed) {
         UNREACHABLE();
     }
-    const u32 vertex_num = regs.vertex_buffer.count;
 
-    vs_input_size = 0;
-    u32 max_offset{};
-    for (const auto& attrib : vertex_attributes) {
-        if (max_offset >= attrib.offset) {
-            continue;
-        }
-        max_offset = attrib.offset;
-        vs_input_size = max_offset + attrib.SizeInBytes();
-    }
-    vs_input_size *= vertex_num;
+    // TODO(bunnei): Add support for 1+ vertex arrays
+    vs_input_size = regs.vertex_buffer.count * regs.vertex_array[0].stride;
 }
 
 void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
     MICROPROFILE_SCOPE(OpenGL_VAO);
-    UNIMPLEMENTED();
+    const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
+    const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
+
+    state.draw.vertex_array = hw_vao.handle;
+    state.draw.vertex_buffer = stream_buffer->GetHandle();
+    state.Apply();
+
+    // TODO(bunnei): Add support for 1+ vertex arrays
+    const auto& vertex_array{regs.vertex_array[0]};
+    ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?");
+    ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!");
+    for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) {
+        ASSERT_MSG(!regs.vertex_array[index].enable, "vertex array %d is unimplemented!", index);
+    }
+
+    // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
+    // Enables the first 16 vertex attributes always, as we don't know which ones are actually used
+    // until shader time. Note, Tegra technically supports 32, but we're cappinig this to 16 for now
+    // to avoid OpenGL errors.
+    for (unsigned index = 0; index < 16; ++index) {
+        auto& attrib = regs.vertex_attrib_format[index];
+        glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
+                              GL_FALSE, vertex_array.stride,
+                              reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset));
+        glEnableVertexAttribArray(index);
+        hw_vao_enabled_attributes[index] = true;
+    }
+
+    // Copy vertex array data
+    const u32 data_size{vertex_array.stride * regs.vertex_buffer.count};
+    const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
+    res_cache.FlushRegion(data_addr, data_size, nullptr);
+    std::memcpy(array_ptr, Memory::GetPointer(data_addr), data_size);
+
+    array_ptr += data_size;
+    buffer_offset += data_size;
 }
 
 void RasterizerOpenGL::SetupVertexShader(VSUniformData* ub_ptr, GLintptr buffer_offset) {