gl_rasterizer: Fix vertex and index data invalidations
This commit is contained in:
		| @@ -198,9 +198,8 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) { | ||||
|         const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); | ||||
|  | ||||
|         // Bind the vertex array to the buffer at the current offset. | ||||
|         // FIXME(Rodrigo): This dereferenced pointer might be invalidated in future uploads. | ||||
|         glVertexArrayVertexBuffer(vao, index, *vertex_buffer, vertex_buffer_offset, | ||||
|                                   vertex_array.stride); | ||||
|         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. | ||||
| @@ -214,7 +213,7 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) { | ||||
|     gpu.dirty_flags.vertex_array.reset(); | ||||
| } | ||||
|  | ||||
| GLintptr RasterizerOpenGL::SetupIndexBuffer(GLuint vao) { | ||||
| GLintptr RasterizerOpenGL::SetupIndexBuffer() { | ||||
|     if (accelerate_draw != AccelDraw::Indexed) { | ||||
|         return 0; | ||||
|     } | ||||
| @@ -222,8 +221,7 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer(GLuint vao) { | ||||
|     const auto& regs = system.GPU().Maxwell3D().regs; | ||||
|     const std::size_t size = CalculateIndexBufferSize(); | ||||
|     const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); | ||||
|     // FIXME(Rodrigo): This dereferenced pointer might be invalidated in future uploads. | ||||
|     glVertexArrayElementBuffer(vao, *buffer); | ||||
|     vertex_array_pushbuffer.SetIndexBuffer(buffer); | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| @@ -644,10 +642,11 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|  | ||||
|     // Prepare vertex array format. | ||||
|     const GLuint vao = SetupVertexFormat(); | ||||
|     vertex_array_pushbuffer.Setup(vao); | ||||
|  | ||||
|     // Upload vertex and index data. | ||||
|     SetupVertexBuffer(vao); | ||||
|     const GLintptr index_buffer_offset = SetupIndexBuffer(vao); | ||||
|     const GLintptr index_buffer_offset = SetupIndexBuffer(); | ||||
|  | ||||
|     // Setup draw parameters. It will automatically choose what glDraw* method to use. | ||||
|     const DrawParameters params = SetupDraw(index_buffer_offset); | ||||
| @@ -667,6 +666,7 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|     const bool invalidate = buffer_cache.Unmap(); | ||||
|  | ||||
|     // Now that we are no longer uploading data, we can safely bind the buffers to OpenGL. | ||||
|     vertex_array_pushbuffer.Bind(); | ||||
|     bind_ubo_pushbuffer.Bind(); | ||||
|     bind_ssbo_pushbuffer.Bind(); | ||||
|  | ||||
|   | ||||
| @@ -207,6 +207,7 @@ private: | ||||
|     static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | ||||
|     OGLBufferCache buffer_cache; | ||||
|  | ||||
|     VertexArrayPushBuffer vertex_array_pushbuffer; | ||||
|     BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; | ||||
|     BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; | ||||
|  | ||||
| @@ -219,7 +220,7 @@ private: | ||||
|  | ||||
|     void SetupVertexBuffer(GLuint vao); | ||||
|  | ||||
|     GLintptr SetupIndexBuffer(GLuint vao); | ||||
|     GLintptr SetupIndexBuffer(); | ||||
|  | ||||
|     DrawParameters SetupDraw(GLintptr index_buffer_offset); | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,37 @@ | ||||
|  | ||||
| namespace OpenGL { | ||||
|  | ||||
| VertexArrayPushBuffer::VertexArrayPushBuffer() = default; | ||||
|  | ||||
| VertexArrayPushBuffer::~VertexArrayPushBuffer() = default; | ||||
|  | ||||
| void VertexArrayPushBuffer::Setup(GLuint vao_) { | ||||
|     vao = vao_; | ||||
|     index_buffer = nullptr; | ||||
|     vertex_buffers.clear(); | ||||
| } | ||||
|  | ||||
| void VertexArrayPushBuffer::SetIndexBuffer(const GLuint* buffer) { | ||||
|     index_buffer = buffer; | ||||
| } | ||||
|  | ||||
| void VertexArrayPushBuffer::SetVertexBuffer(GLuint binding_index, const GLuint* buffer, | ||||
|                                             GLintptr offset, GLsizei stride) { | ||||
|     vertex_buffers.push_back(Entry{binding_index, buffer, offset, stride}); | ||||
| } | ||||
|  | ||||
| void VertexArrayPushBuffer::Bind() { | ||||
|     if (index_buffer) { | ||||
|         glVertexArrayElementBuffer(vao, *index_buffer); | ||||
|     } | ||||
|  | ||||
|     // TODO(Rodrigo): Find a way to ARB_multi_bind this | ||||
|     for (const auto& entry : vertex_buffers) { | ||||
|         glVertexArrayVertexBuffer(vao, entry.binding_index, *entry.buffer, entry.offset, | ||||
|                                   entry.stride); | ||||
|     } | ||||
| } | ||||
|  | ||||
| BindBuffersRangePushBuffer::BindBuffersRangePushBuffer(GLenum target) : target{target} {} | ||||
|  | ||||
| BindBuffersRangePushBuffer::~BindBuffersRangePushBuffer() = default; | ||||
|   | ||||
| @@ -11,6 +11,33 @@ | ||||
|  | ||||
| namespace OpenGL { | ||||
|  | ||||
| class VertexArrayPushBuffer final { | ||||
| public: | ||||
|     explicit VertexArrayPushBuffer(); | ||||
|     ~VertexArrayPushBuffer(); | ||||
|  | ||||
|     void Setup(GLuint vao_); | ||||
|  | ||||
|     void SetIndexBuffer(const GLuint* buffer); | ||||
|  | ||||
|     void SetVertexBuffer(GLuint binding_index, const GLuint* buffer, GLintptr offset, | ||||
|                          GLsizei stride); | ||||
|  | ||||
|     void Bind(); | ||||
|  | ||||
| private: | ||||
|     struct Entry { | ||||
|         GLuint binding_index{}; | ||||
|         const GLuint* buffer{}; | ||||
|         GLintptr offset{}; | ||||
|         GLsizei stride{}; | ||||
|     }; | ||||
|  | ||||
|     GLuint vao{}; | ||||
|     const GLuint* index_buffer{}; | ||||
|     std::vector<Entry> vertex_buffers; | ||||
| }; | ||||
|  | ||||
| class BindBuffersRangePushBuffer final { | ||||
| public: | ||||
|     explicit BindBuffersRangePushBuffer(GLenum target); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp