diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index d7328ff39b..1d973c4f8a 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -102,6 +102,26 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { ProcessCBData(value); break; } + case MAXWELL3D_REG_INDEX(vertex_attrib_format[0]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[1]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[2]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[3]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[4]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[5]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[6]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[7]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[8]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[9]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[10]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[11]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[12]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[13]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[14]): + case MAXWELL3D_REG_INDEX(vertex_attrib_format[15]): { + state.MaxAttribs = + std::max(state.MaxAttribs, method - MAXWELL3D_REG_INDEX(vertex_attrib_format[0]) + 1); + break; + } case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { ProcessCBBind(Regs::ShaderStage::Vertex); break; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 3c32f10671..9ad3e601a0 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -800,6 +800,7 @@ public: }; std::array shader_stages; + size_t MaxAttribs; }; State state{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 5d5ad84b7d..6882e1129b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -128,6 +128,7 @@ RasterizerOpenGL::~RasterizerOpenGL() { std::pair RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, GLintptr buffer_offset) { MICROPROFILE_SCOPE(OpenGL_VAO); + const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; const auto& memory_manager = Core::System::GetInstance().GPU().memory_manager; @@ -160,12 +161,12 @@ std::pair RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, } // 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 capping this to 16 for now - // to avoid OpenGL errors. + // Enables the all vertex attributes that have been written to, as we don't know which ones are + // actually used until shader time. Note: Tegra technically supports 32. // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't // assume every shader uses them all. - for (unsigned index = 0; index < 16; ++index) { + const auto& max_attribs = Core::System::GetInstance().GPU().Maxwell3D().state.MaxAttribs; + for (unsigned index = 0; index < max_attribs; ++index) { auto& attrib = regs.vertex_attrib_format[index]; LOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),