diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 225ad05ce7..d6d803ed12 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -157,6 +157,9 @@ void DrawEngineGLES::InitDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024); frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 256 * 1024); + + render_->RegisterPushBuffer(i, frameData_[i].pushVertex); + render_->RegisterPushBuffer(i, frameData_[i].pushIndex); } int vertexSize = sizeof(TransformedVertex); @@ -170,6 +173,8 @@ void DrawEngineGLES::InitDeviceObjects() { void DrawEngineGLES::DestroyDeviceObjects() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + render_->UnregisterPushBuffer(i, frameData_[i].pushVertex); + render_->UnregisterPushBuffer(i, frameData_[i].pushIndex); frameData_[i].pushVertex->Destroy(); frameData_[i].pushIndex->Destroy(); delete frameData_[i].pushVertex; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index c78dc26a66..452497d3e2 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -379,6 +379,11 @@ void GLRenderManager::Run(int frame) { } void GLRenderManager::FlushSync() { + // Need to flush any pushbuffers to VRAM before submitting draw calls. + for (auto iter : frameData_[curFrame_].activePushBuffers) { + iter->Flush(); + } + // TODO: Reset curRenderStep_? int curFrame = curFrame_; FrameData &frameData = frameData_[curFrame]; @@ -465,6 +470,14 @@ void GLPushBuffer::Unmap() { writePtr_ = nullptr; } +void GLPushBuffer::Flush() { + render_->BufferSubdata(buffers_[buf_].buffer, 0, offset_, buffers_[buf_].deviceMemory, false); + // Here we will submit all the draw calls, with the already known buffer and offsets. + // Might as well reset the write pointer here and start over the current buffer. + writePtr_ = buffers_[buf_].deviceMemory; + offset_ = 0; +} + bool GLPushBuffer::AddBuffer() { BufInfo info; info.deviceMemory = new uint8_t[size_]; @@ -527,4 +540,4 @@ size_t GLPushBuffer::GetTotalSize() const { sum += size_ * (buffers_.size() - 1); sum += offset_; return sum; -} +} \ No newline at end of file diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index de559fcc31..59d753537e 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include "GLQueueRunner.h" class GLRInputLayout; +class GLPushBuffer; class GLRFramebuffer { public: @@ -596,6 +598,17 @@ public: queueRunner_.Resize(width, height); } + // When using legacy functionality for push buffers (glBufferData), we need to flush them + // before actually making the glDraw* calls. It's best if the render manager handles that. + void RegisterPushBuffer(int frame, GLPushBuffer *buffer) { + frameData_[frame].activePushBuffers.insert(buffer); + } + void UnregisterPushBuffer(int frame, GLPushBuffer *buffer) { + auto iter = frameData_[frame].activePushBuffers.find(buffer); + _assert_(iter != frameData_[frame].activePushBuffers.end()); + frameData_[frame].activePushBuffers.erase(iter); + } + private: void BeginSubmitFrame(int frame); void EndSubmitFrame(int frame); @@ -629,6 +642,7 @@ private: uint32_t curSwapchainImage = -1; GLDeleter deleter; + std::set activePushBuffers; }; FrameData frameData_[MAX_INFLIGHT_FRAMES]; @@ -749,6 +763,8 @@ public: size_t GetTotalSize() const; + void Flush(); + private: bool AddBuffer(); void NextBuffer(size_t minSize); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 194d065ec0..cf05ae4b75 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -526,11 +526,13 @@ OpenGLContext::OpenGLContext() { } for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { frameData_[i].push = new GLPushBuffer(&renderManager_, GL_ARRAY_BUFFER, 64 * 1024); + renderManager_.RegisterPushBuffer(i, frameData_[i].push); } } OpenGLContext::~OpenGLContext() { for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) { + renderManager_.UnregisterPushBuffer(i, frameData_[i].push); frameData_[i].push->Destroy(); delete frameData_[i].push; }