gl_state_tracker: Add dirty flags for buffers and divisors
This commit is contained in:
		| @@ -164,12 +164,22 @@ void RasterizerOpenGL::SetupVertexFormat() { | ||||
|  | ||||
| void RasterizerOpenGL::SetupVertexBuffer() { | ||||
|     auto& gpu = system.GPU().Maxwell3D(); | ||||
|     const auto& regs = gpu.regs; | ||||
|     auto& flags = gpu.dirty.flags; | ||||
|     if (!flags[Dirty::VertexBuffers]) { | ||||
|         return; | ||||
|     } | ||||
|     flags[Dirty::VertexBuffers] = false; | ||||
|  | ||||
|     MICROPROFILE_SCOPE(OpenGL_VB); | ||||
|  | ||||
|     // Upload all guest vertex arrays sequentially to our buffer | ||||
|     for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) { | ||||
|     const auto& regs = gpu.regs; | ||||
|     for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | ||||
|         if (!flags[Dirty::VertexBuffer0 + index]) { | ||||
|             continue; | ||||
|         } | ||||
|         flags[Dirty::VertexBuffer0 + index] = false; | ||||
|  | ||||
|         const auto& vertex_array = regs.vertex_array[index]; | ||||
|         if (!vertex_array.IsEnabled()) { | ||||
|             continue; | ||||
| @@ -183,33 +193,30 @@ void RasterizerOpenGL::SetupVertexBuffer() { | ||||
|         const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); | ||||
|  | ||||
|         // Bind the vertex array to the buffer at the current offset. | ||||
|         vertex_array_pushbuffer.SetVertexBuffer(index, vertex_buffer, vertex_buffer_offset, | ||||
|                                                 vertex_array.stride); | ||||
|  | ||||
|         if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) { | ||||
|             // Enable vertex buffer instancing with the specified divisor. | ||||
|             glVertexBindingDivisor(index, vertex_array.divisor); | ||||
|         } else { | ||||
|             // Disable the vertex buffer instancing. | ||||
|             glVertexBindingDivisor(index, 0); | ||||
|         } | ||||
|         vertex_array_pushbuffer.SetVertexBuffer(static_cast<GLuint>(index), vertex_buffer, | ||||
|                                                 vertex_buffer_offset, vertex_array.stride); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void RasterizerOpenGL::SetupVertexInstances() { | ||||
|     auto& gpu = system.GPU().Maxwell3D(); | ||||
|     const auto& regs = gpu.regs; | ||||
|     auto& flags = gpu.dirty.flags; | ||||
|     if (!flags[Dirty::VertexInstances]) { | ||||
|         return; | ||||
|     } | ||||
|     flags[Dirty::VertexInstances] = false; | ||||
|  | ||||
|     // Upload all guest vertex arrays sequentially to our buffer | ||||
|     for (u32 index = 0; index < 16; ++index) { | ||||
|         if (regs.instanced_arrays.IsInstancingEnabled(index) && | ||||
|             regs.vertex_array[index].divisor != 0) { | ||||
|             // Enable vertex buffer instancing with the specified divisor. | ||||
|             glVertexBindingDivisor(index, regs.vertex_array[index].divisor); | ||||
|         } else { | ||||
|             // Disable the vertex buffer instancing. | ||||
|             glVertexBindingDivisor(index, 0); | ||||
|     const auto& regs = gpu.regs; | ||||
|     for (std::size_t index = 0; index < 16; ++index) { | ||||
|         if (!flags[Dirty::VertexInstance0 + index]) { | ||||
|             continue; | ||||
|         } | ||||
|         flags[Dirty::VertexInstance0 + index] = false; | ||||
|  | ||||
|         const auto gl_index = static_cast<GLuint>(index); | ||||
|         const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index); | ||||
|         const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0; | ||||
|         glVertexBindingDivisor(gl_index, divisor); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -71,6 +71,26 @@ void SetupDirtyColorMasks(Tables& tables) { | ||||
|     FillBlock(tables[1], OFF(color_mask), NUM(color_mask), ColorMasks); | ||||
| } | ||||
|  | ||||
| void SetupDirtyVertexArrays(Tables& tables) { | ||||
|     static constexpr std::size_t num_array = 3; | ||||
|     static constexpr std::size_t instance_base_offset = 3; | ||||
|     for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) { | ||||
|         const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]); | ||||
|         const std::size_t limit_offset = OFF(vertex_array_limit) + i * NUM(vertex_array_limit[0]); | ||||
|  | ||||
|         FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers); | ||||
|         FillBlock(tables, limit_offset, NUM(vertex_array_limit), VertexBuffer0 + i, VertexBuffers); | ||||
|  | ||||
|         const std::size_t instance_array_offset = array_offset + instance_base_offset; | ||||
|         tables[0][instance_array_offset] = static_cast<u8>(VertexInstance0 + i); | ||||
|         tables[1][instance_array_offset] = VertexInstances; | ||||
|  | ||||
|         const std::size_t instance_offset = OFF(instanced_arrays) + i; | ||||
|         tables[0][instance_offset] = static_cast<u8>(VertexInstance0 + i); | ||||
|         tables[1][instance_offset] = VertexInstances; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void SetupDirtyVertexFormat(Tables& tables) { | ||||
|     for (std::size_t i = 0; i < Regs::NumVertexAttributes; ++i) { | ||||
|         const std::size_t offset = OFF(vertex_attrib_format) + i * NUM(vertex_attrib_format[0]); | ||||
| @@ -115,6 +135,7 @@ void StateTracker::Initialize() { | ||||
|     SetupDirtyColorMasks(tables); | ||||
|     SetupDirtyViewports(tables); | ||||
|     SetupDirtyScissors(tables); | ||||
|     SetupDirtyVertexArrays(tables); | ||||
|     SetupDirtyVertexFormat(tables); | ||||
|  | ||||
|     auto& store = dirty.on_write_stores; | ||||
|   | ||||
| @@ -78,6 +78,10 @@ public: | ||||
|  | ||||
|         flags[OpenGL::Dirty::VertexBuffers] = true; | ||||
|         flags[OpenGL::Dirty::VertexBuffer0] = true; | ||||
|  | ||||
|         flags[OpenGL::Dirty::VertexInstances] = true; | ||||
|         flags[OpenGL::Dirty::VertexInstance0 + 0] = true; | ||||
|         flags[OpenGL::Dirty::VertexInstance0 + 1] = true; | ||||
|     } | ||||
|  | ||||
|     void NotifyViewport0() { | ||||
|   | ||||
| @@ -611,6 +611,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | ||||
|  | ||||
|     glEnableVertexAttribArray(PositionLocation); | ||||
|     glEnableVertexAttribArray(TexCoordLocation); | ||||
|     glVertexAttribDivisor(PositionLocation, 0); | ||||
|     glVertexAttribDivisor(TexCoordLocation, 0); | ||||
|     glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE, | ||||
|                          offsetof(ScreenRectVertex, position)); | ||||
|     glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user