diff options
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 96 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 8 |
3 files changed, 60 insertions, 53 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 92bfda053..f59d01738 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -127,6 +127,7 @@ public: | |||
| 127 | BitField<21, 6, Size> size; | 127 | BitField<21, 6, Size> size; |
| 128 | BitField<27, 3, Type> type; | 128 | BitField<27, 3, Type> type; |
| 129 | BitField<31, 1, u32> bgra; | 129 | BitField<31, 1, u32> bgra; |
| 130 | u32 hex; | ||
| 130 | }; | 131 | }; |
| 131 | 132 | ||
| 132 | u32 ComponentCount() const { | 133 | u32 ComponentCount() const { |
| @@ -262,6 +263,10 @@ public: | |||
| 262 | bool IsValid() const { | 263 | bool IsValid() const { |
| 263 | return size != Size::Invalid; | 264 | return size != Size::Invalid; |
| 264 | } | 265 | } |
| 266 | |||
| 267 | bool operator<(const VertexAttribute& other) const { | ||
| 268 | return hex < other.hex; | ||
| 269 | } | ||
| 265 | }; | 270 | }; |
| 266 | 271 | ||
| 267 | enum class PrimitiveTopology : u32 { | 272 | enum class PrimitiveTopology : u32 { |
| @@ -545,7 +550,7 @@ public: | |||
| 545 | 550 | ||
| 546 | INSERT_PADDING_WORDS(0x5B); | 551 | INSERT_PADDING_WORDS(0x5B); |
| 547 | 552 | ||
| 548 | VertexAttribute vertex_attrib_format[NumVertexAttributes]; | 553 | std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; |
| 549 | 554 | ||
| 550 | INSERT_PADDING_WORDS(0xF); | 555 | INSERT_PADDING_WORDS(0xF); |
| 551 | 556 | ||
| @@ -964,7 +969,7 @@ ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5); | |||
| 964 | ASSERT_REG_POSITION(stencil_back_mask, 0x3D6); | 969 | ASSERT_REG_POSITION(stencil_back_mask, 0x3D6); |
| 965 | ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7); | 970 | ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7); |
| 966 | ASSERT_REG_POSITION(zeta, 0x3F8); | 971 | ASSERT_REG_POSITION(zeta, 0x3F8); |
| 967 | ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); | 972 | ASSERT_REG_POSITION(vertex_attrib_format, 0x458); |
| 968 | ASSERT_REG_POSITION(rt_control, 0x487); | 973 | ASSERT_REG_POSITION(rt_control, 0x487); |
| 969 | ASSERT_REG_POSITION(zeta_width, 0x48a); | 974 | ASSERT_REG_POSITION(zeta_width, 0x48a); |
| 970 | ASSERT_REG_POSITION(zeta_height, 0x48b); | 975 | ASSERT_REG_POSITION(zeta_height, 0x48b); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c66a18155..5d493a2b2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -70,28 +70,13 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo | |||
| 70 | // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 | 70 | // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 |
| 71 | state.clip_distance[0] = true; | 71 | state.clip_distance[0] = true; |
| 72 | 72 | ||
| 73 | // Generate VAO and UBO | ||
| 74 | sw_vao.Create(); | ||
| 75 | uniform_buffer.Create(); | ||
| 76 | |||
| 77 | state.draw.vertex_array = sw_vao.handle; | ||
| 78 | state.draw.uniform_buffer = uniform_buffer.handle; | ||
| 79 | state.Apply(); | ||
| 80 | |||
| 81 | // Create render framebuffer | 73 | // Create render framebuffer |
| 82 | framebuffer.Create(); | 74 | framebuffer.Create(); |
| 83 | 75 | ||
| 84 | hw_vao.Create(); | ||
| 85 | |||
| 86 | state.draw.vertex_buffer = buffer_cache.GetHandle(); | ||
| 87 | |||
| 88 | shader_program_manager = std::make_unique<GLShader::ProgramManager>(); | 76 | shader_program_manager = std::make_unique<GLShader::ProgramManager>(); |
| 89 | state.draw.shader_program = 0; | 77 | state.draw.shader_program = 0; |
| 90 | state.draw.vertex_array = hw_vao.handle; | ||
| 91 | state.Apply(); | 78 | state.Apply(); |
| 92 | 79 | ||
| 93 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_cache.GetHandle()); | ||
| 94 | |||
| 95 | glEnable(GL_BLEND); | 80 | glEnable(GL_BLEND); |
| 96 | 81 | ||
| 97 | glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment); | 82 | glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment); |
| @@ -106,7 +91,54 @@ void RasterizerOpenGL::SetupVertexArrays() { | |||
| 106 | const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 91 | const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); |
| 107 | const auto& regs = gpu.regs; | 92 | const auto& regs = gpu.regs; |
| 108 | 93 | ||
| 109 | state.draw.vertex_array = hw_vao.handle; | 94 | auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format); |
| 95 | auto& VAO = iter->second; | ||
| 96 | |||
| 97 | if (is_cache_miss) { | ||
| 98 | VAO.Create(); | ||
| 99 | state.draw.vertex_array = VAO.handle; | ||
| 100 | state.Apply(); | ||
| 101 | |||
| 102 | // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work | ||
| 103 | // around. | ||
| 104 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_cache.GetHandle()); | ||
| 105 | |||
| 106 | // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. | ||
| 107 | // Enables the first 16 vertex attributes always, as we don't know which ones are actually | ||
| 108 | // used until shader time. Note, Tegra technically supports 32, but we're capping this to 16 | ||
| 109 | // for now to avoid OpenGL errors. | ||
| 110 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't | ||
| 111 | // assume every shader uses them all. | ||
| 112 | for (unsigned index = 0; index < 16; ++index) { | ||
| 113 | const auto& attrib = regs.vertex_attrib_format[index]; | ||
| 114 | |||
| 115 | // Ignore invalid attributes. | ||
| 116 | if (!attrib.IsValid()) | ||
| 117 | continue; | ||
| 118 | |||
| 119 | const auto& buffer = regs.vertex_array[attrib.buffer]; | ||
| 120 | LOG_TRACE(HW_GPU, | ||
| 121 | "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", | ||
| 122 | index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), | ||
| 123 | attrib.offset.Value(), attrib.IsNormalized()); | ||
| 124 | |||
| 125 | ASSERT(buffer.IsEnabled()); | ||
| 126 | |||
| 127 | glEnableVertexAttribArray(index); | ||
| 128 | if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt || | ||
| 129 | attrib.type == | ||
| 130 | Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) { | ||
| 131 | glVertexAttribIFormat(index, attrib.ComponentCount(), | ||
| 132 | MaxwellToGL::VertexType(attrib), attrib.offset); | ||
| 133 | } else { | ||
| 134 | glVertexAttribFormat(index, attrib.ComponentCount(), | ||
| 135 | MaxwellToGL::VertexType(attrib), | ||
| 136 | attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset); | ||
| 137 | } | ||
| 138 | glVertexAttribBinding(index, attrib.buffer); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | state.draw.vertex_array = VAO.handle; | ||
| 110 | state.draw.vertex_buffer = buffer_cache.GetHandle(); | 142 | state.draw.vertex_buffer = buffer_cache.GetHandle(); |
| 111 | state.Apply(); | 143 | state.Apply(); |
| 112 | 144 | ||
| @@ -142,38 +174,6 @@ void RasterizerOpenGL::SetupVertexArrays() { | |||
| 142 | glVertexBindingDivisor(index, 0); | 174 | glVertexBindingDivisor(index, 0); |
| 143 | } | 175 | } |
| 144 | } | 176 | } |
| 145 | |||
| 146 | // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. | ||
| 147 | // Enables the first 16 vertex attributes always, as we don't know which ones are actually used | ||
| 148 | // until shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now | ||
| 149 | // to avoid OpenGL errors. | ||
| 150 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't | ||
| 151 | // assume every shader uses them all. | ||
| 152 | for (unsigned index = 0; index < 16; ++index) { | ||
| 153 | auto& attrib = regs.vertex_attrib_format[index]; | ||
| 154 | |||
| 155 | // Ignore invalid attributes. | ||
| 156 | if (!attrib.IsValid()) | ||
| 157 | continue; | ||
| 158 | |||
| 159 | auto& buffer = regs.vertex_array[attrib.buffer]; | ||
| 160 | LOG_TRACE(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", | ||
| 161 | index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), | ||
| 162 | attrib.offset.Value(), attrib.IsNormalized()); | ||
| 163 | |||
| 164 | ASSERT(buffer.IsEnabled()); | ||
| 165 | |||
| 166 | glEnableVertexAttribArray(index); | ||
| 167 | if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt || | ||
| 168 | attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) { | ||
| 169 | glVertexAttribIFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), | ||
| 170 | attrib.offset); | ||
| 171 | } else { | ||
| 172 | glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), | ||
| 173 | attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset); | ||
| 174 | } | ||
| 175 | glVertexAttribBinding(index, attrib.buffer); | ||
| 176 | } | ||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | void RasterizerOpenGL::SetupShaders() { | 179 | void RasterizerOpenGL::SetupShaders() { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 4c4b084b8..9c30dc0e8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | 8 | #include <cstddef> |
| 9 | #include <map> | ||
| 9 | #include <memory> | 10 | #include <memory> |
| 10 | #include <tuple> | 11 | #include <tuple> |
| 11 | #include <utility> | 12 | #include <utility> |
| @@ -168,14 +169,15 @@ private: | |||
| 168 | ScreenInfo& screen_info; | 169 | ScreenInfo& screen_info; |
| 169 | 170 | ||
| 170 | std::unique_ptr<GLShader::ProgramManager> shader_program_manager; | 171 | std::unique_ptr<GLShader::ProgramManager> shader_program_manager; |
| 171 | OGLVertexArray sw_vao; | 172 | std::map<std::array<Tegra::Engines::Maxwell3D::Regs::VertexAttribute, |
| 172 | OGLVertexArray hw_vao; | 173 | Tegra::Engines::Maxwell3D::Regs::NumVertexAttributes>, |
| 174 | OGLVertexArray> | ||
| 175 | vertex_array_cache; | ||
| 173 | 176 | ||
| 174 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; | 177 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; |
| 175 | 178 | ||
| 176 | static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | 179 | static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; |
| 177 | OGLBufferCache buffer_cache; | 180 | OGLBufferCache buffer_cache; |
| 178 | OGLBuffer uniform_buffer; | ||
| 179 | OGLFramebuffer framebuffer; | 181 | OGLFramebuffer framebuffer; |
| 180 | GLint uniform_buffer_alignment; | 182 | GLint uniform_buffer_alignment; |
| 181 | 183 | ||