diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 78005a1126..8545115e86 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -206,7 +206,7 @@ public: return vfb; } } - virtual void RebindFramebuffer(); + void RebindFramebuffer(); std::vector GetFramebufferList(); void CopyDisplayToOutput(); diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 508e995e52..1bc40e960e 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -58,8 +58,7 @@ public: void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags); virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - - virtual void RebindFramebuffer() override; + void RebindFramebuffer(); // TODO: Remove ID3D11Buffer *GetDynamicQuadBuffer() { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index b7303b05dc..aacc8f7f31 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -91,7 +91,7 @@ #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/GPU_GLES.h" -extern const GLuint glprim[8] = { +const GLuint glprim[8] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, @@ -146,17 +146,6 @@ DrawEngineGLES::~DrawEngineGLES() { delete tessDataTransfer; } -void DrawEngineGLES::RestoreVAO() { - if (sharedVao_ != 0) { - glBindVertexArray(sharedVao_); - } else if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - // Note: this is here because, InitDeviceObjects() is called before GPU_SUPPORTS_VAO is setup. - // So, this establishes it if Supports() returns true and there isn't one yet. - glGenVertexArrays(1, &sharedVao_); - glBindVertexArray(sharedVao_); - } -} - void DrawEngineGLES::DeviceLost() { DestroyDeviceObjects(); } @@ -166,20 +155,6 @@ void DrawEngineGLES::DeviceRestore() { } void DrawEngineGLES::InitDeviceObjects() { - if (bufferNameCache_.empty()) { - bufferNameCache_.resize(VERTEXCACHE_NAME_CACHE_SIZE); - glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[0]); - bufferNameCacheSize_ = 0; - - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - glGenVertexArrays(1, &sharedVao_); - } else { - sharedVao_ = 0; - } - } else { - ERROR_LOG(G3D, "Device objects already initialized!"); - } - 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, 512 * 1024); @@ -203,18 +178,6 @@ void DrawEngineGLES::DestroyDeviceObjects() { } ClearTrackedVertexArrays(); - if (!bufferNameCache_.empty()) { - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glDeleteBuffers((GLsizei)bufferNameCache_.size(), &bufferNameCache_[0]); - bufferNameCache_.clear(); - bufferNameInfo_.clear(); - freeSizedBuffers_.clear(); - bufferNameCacheSize_ = 0; - if (sharedVao_ != 0) { - glDeleteVertexArrays(1, &sharedVao_); - } - } render_->DeleteInputLayout(softwareInputLayout_); } @@ -376,11 +339,11 @@ void DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindO void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) { vai->status = VertexArrayInfo::VAI_UNRELIABLE; if (vai->vbo) { - FreeBuffer(vai->vbo); + render_->DeleteBuffer(vai->vbo); vai->vbo = 0; } if (vai->ebo) { - FreeBuffer(vai->ebo); + render_->DeleteBuffer(vai->ebo); vai->ebo = 0; } } @@ -420,80 +383,14 @@ void DrawEngineGLES::DecimateTrackedVertexArrays() { vai_.Maintain(); } -GLuint DrawEngineGLES::AllocateBuffer(size_t sz) { - GLuint unused = 0; - - auto freeMatch = freeSizedBuffers_.find(sz); - if (freeMatch != freeSizedBuffers_.end()) { - unused = freeMatch->second; - _assert_(!bufferNameInfo_[unused].used); - - freeSizedBuffers_.erase(freeMatch); - } else { - for (GLuint buf : bufferNameCache_) { - const BufferNameInfo &info = bufferNameInfo_[buf]; - if (info.used) { - continue; - } - - // Just pick the first unused one, we'll have to resize it. - unused = buf; - - // Let's also remove from the free list, if it's there. - if (info.sz != 0) { - auto range = freeSizedBuffers_.equal_range(info.sz); - for (auto it = range.first; it != range.second; ++it) { - if (it->second == buf) { - // It will only be once, so remove and bail. - freeSizedBuffers_.erase(it); - break; - } - } - } - break; - } - } - - if (unused == 0) { - size_t oldSize = bufferNameCache_.size(); - bufferNameCache_.resize(oldSize + VERTEXCACHE_NAME_CACHE_SIZE); - glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[oldSize]); - - unused = bufferNameCache_[oldSize]; - } - - BufferNameInfo &info = bufferNameInfo_[unused]; - - // Record the change in size. - bufferNameCacheSize_ += sz - info.sz; - info.sz = sz; - info.used = true; - return unused; -} - -void DrawEngineGLES::FreeBuffer(GLuint buf) { - // We can reuse buffers by setting new data on them, so let's actually keep it. - auto it = bufferNameInfo_.find(buf); - if (it != bufferNameInfo_.end()) { - it->second.used = false; - it->second.lastFrame = gpuStats.numFlips; - - if (it->second.sz != 0) { - freeSizedBuffers_.insert(std::make_pair(it->second.sz, buf)); - } - } else { - ERROR_LOG(G3D, "Unexpected buffer freed (%d) but not tracked", buf); - } -} - void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) { if (vai->vbo) { - FreeBuffer(vai->vbo); - vai->vbo = 0; + render_->DeleteBuffer(vai->vbo); + vai->vbo = nullptr; } if (vai->ebo) { - FreeBuffer(vai->ebo); - vai->ebo = 0; + render_->DeleteBuffer(vai->ebo); + vai->ebo = nullptr; } } @@ -517,7 +414,6 @@ void DrawEngineGLES::DoFlush() { uint32_t indexBufferOffset = 0; if (vshader->UseHWTransform()) { - GLuint vbo = 0, ebo = 0; int vertexCount = 0; bool useElements = true; @@ -611,31 +507,28 @@ void DrawEngineGLES::DoFlush() { _dbg_assert_msg_(G3D, gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); size_t vsz = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex(); - vai->vbo = AllocateBuffer(vsz); - glstate.arrayBuffer.bind(vai->vbo); - glBufferData(GL_ARRAY_BUFFER, vsz, decoded, GL_STATIC_DRAW); + vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, vsz, GL_STATIC_DRAW); + render_->BufferSubdata(vai->vbo, 0, vsz, decoded); + render_->BindVertexBuffer(vai->vbo); // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, // there is no need for the index buffer we built. We can then use glDrawArrays instead // for a very minor speed boost. if (useElements) { size_t esz = sizeof(short) * indexGen.VertexCount(); - vai->ebo = AllocateBuffer(esz); - glstate.elementArrayBuffer.bind(vai->ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, esz, (GLvoid *)decIndex, GL_STATIC_DRAW); + vai->ebo = render_->CreateBuffer(GL_ARRAY_BUFFER, esz, GL_STATIC_DRAW); + render_->BufferSubdata(vai->ebo, 0, esz, (uint8_t *)decIndex, false); } else { vai->ebo = 0; - glstate.elementArrayBuffer.bind(vai->ebo); + render_->BindIndexBuffer(vai->ebo); } } else { gpuStats.numCachedDrawCalls++; - glstate.arrayBuffer.bind(vai->vbo); - glstate.elementArrayBuffer.bind(vai->ebo); useElements = vai->ebo ? true : false; gpuStats.numCachedVertsDrawn += vai->numVerts; gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; } - vbo = vai->vbo; - ebo = vai->ebo; + vertexBuffer = vai->vbo; + indexBuffer = vai->ebo; vertexCount = vai->numVerts; prim = static_cast(vai->prim); break; @@ -650,10 +543,8 @@ void DrawEngineGLES::DoFlush() { } gpuStats.numCachedDrawCalls++; gpuStats.numCachedVertsDrawn += vai->numVerts; - vbo = vai->vbo; - ebo = vai->ebo; - glstate.arrayBuffer.bind(vbo); - glstate.elementArrayBuffer.bind(ebo); + vertexBuffer = vai->vbo; + indexBuffer = vai->ebo; vertexCount = vai->numVerts; prim = static_cast(vai->prim); @@ -843,108 +734,12 @@ rotateVBO: CHECK_GL_ERROR_IF_DEBUG(); } -GLuint DrawEngineGLES::BindBuffer(const void *p, size_t sz) { - // Get a new buffer each time we need one. - GLuint buf = AllocateBuffer(sz); - glstate.arrayBuffer.bind(buf); - - // These aren't used more than once per frame, so let's use GL_STREAM_DRAW. - glBufferData(GL_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW); - buffersThisFrame_.push_back(buf); - - return buf; -} - -GLuint DrawEngineGLES::BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2) { - GLuint buf = AllocateBuffer(sz1 + sz2); - glstate.arrayBuffer.bind(buf); - - glBufferData(GL_ARRAY_BUFFER, sz1 + sz2, nullptr, GL_STREAM_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, sz1, p1); - glBufferSubData(GL_ARRAY_BUFFER, sz1, sz2, p2); - buffersThisFrame_.push_back(buf); - - return buf; -} - -GLuint DrawEngineGLES::BindElementBuffer(const void *p, size_t sz) { - GLuint buf = AllocateBuffer(sz); - glstate.elementArrayBuffer.bind(buf); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW); - buffersThisFrame_.push_back(buf); - - return buf; -} - -void DrawEngineGLES::DecimateBuffers() { - for (GLuint buf : buffersThisFrame_) { - FreeBuffer(buf); - } - buffersThisFrame_.clear(); - - if (--bufferDecimationCounter_ <= 0) { - bufferDecimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - // Let's not keep too many around, will eat up memory. - // First check if there's any to free, and only check if it seems somewhat full. - bool hasOld = false; - if (bufferNameCacheSize_ > VERTEXCACHE_NAME_CACHE_FULL_BYTES) { - for (GLuint buf : bufferNameCache_) { - const BufferNameInfo &info = bufferNameInfo_[buf]; - const int age = gpuStats.numFlips - info.lastFrame; - if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) { - hasOld = true; - break; - } - } - } - - if (hasOld) { - // Okay, it is. Let's rebuild the array. - std::vector toFree; - std::vector toKeep; - - toKeep.reserve(bufferNameCache_.size()); - - for (size_t i = 0, n = bufferNameCache_.size(); i < n; ++i) { - const GLuint buf = bufferNameCache_[i]; - const BufferNameInfo &info = bufferNameInfo_[buf]; - const int age = gpuStats.numFlips - info.lastFrame; - if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) { - toFree.push_back(buf); - bufferNameCacheSize_ -= bufferNameInfo_[buf].sz; - bufferNameInfo_.erase(buf); - - // If we've removed all we want to this round, keep the rest and abort. - if (toFree.size() >= VERTEXCACHE_NAME_DECIMATION_MAX && i + 1 < bufferNameCache_.size()) { - toKeep.insert(toKeep.end(), bufferNameCache_.begin() + i + 1, bufferNameCache_.end()); - break; - } - } else { - toKeep.push_back(buf); - } - } - - if (!toFree.empty()) { - bufferNameCache_ = toKeep; - // TODO: Rebuild? - freeSizedBuffers_.clear(); - - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glDeleteBuffers((GLsizei)toFree.size(), &toFree[0]); - } - } -} - bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); } void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) { + /* #ifndef USING_GLES2 if (isAllowTexture1D_) { // Position @@ -1041,4 +836,5 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR_IF_DEBUG(); + */ } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 2ed6046b96..9fd2a6080d 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -61,8 +61,8 @@ class VertexArrayInfo { public: VertexArrayInfo() { status = VAI_NEW; - vbo = 0; - ebo = 0; + vbo = nullptr; + ebo = nullptr; prim = GE_PRIM_INVALID; numDraws = 0; numFrames = 0; @@ -82,8 +82,8 @@ public: ReliableHashType hash; u32 minihash; - u32 vbo; - u32 ebo; + GLRBuffer *vbo; + GLRBuffer *ebo; // Precalculated parameter for drawRangeElements u16 numVerts; @@ -119,7 +119,6 @@ public: void SetFragmentTestCache(FragmentTestCacheGLES *testCache) { fragmentTestCache_ = testCache; } - void RestoreVAO(); void DeviceLost(); void DeviceRestore(); @@ -151,10 +150,12 @@ public: SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead); } - GLuint BindBuffer(const void *p, size_t sz); - GLuint BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2); - GLuint BindElementBuffer(const void *p, size_t sz); - void DecimateBuffers(); + GLPushBuffer *GetPushVertexBuffer() { + return frameData_[render_->GetCurFrame()].pushVertex; + } + GLPushBuffer *GetPushIndexBuffer() { + return frameData_[render_->GetCurFrame()].pushIndex; + } void ClearInputLayoutMap(); @@ -171,8 +172,6 @@ private: void DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf); - GLuint AllocateBuffer(size_t sz); - void FreeBuffer(GLuint buf); void FreeVertexArray(VertexArrayInfo *vai); void MarkUnreliable(VertexArrayInfo *vai); @@ -188,23 +187,7 @@ private: DenseHashMap inputLayoutMap_; GLRInputLayout *softwareInputLayout_ = nullptr; - - // Vertex buffer objects - // Element buffer objects - struct BufferNameInfo { - BufferNameInfo() : sz(0), used(false), lastFrame(0) {} - - size_t sz; - bool used; - int lastFrame; - }; GLRenderManager *render_; - std::vector bufferNameCache_; - std::multimap freeSizedBuffers_; - std::unordered_map bufferNameInfo_; - std::vector buffersThisFrame_; - size_t bufferNameCacheSize_ = 0; - GLuint sharedVao_ = 0; // Other ShaderManagerGLES *shaderManager_ = nullptr; @@ -218,15 +201,11 @@ private: // Hardware tessellation class TessellationDataTransferGLES : public TessellationDataTransfer { private: - int data_tex[3]; + GLRTexture *data_tex[3]{}; bool isAllowTexture1D_; public: - TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), data_tex(), isAllowTexture1D_(isAllowTexture1D) { - glGenTextures(3, (GLuint*)data_tex); - } - ~TessellationDataTransferGLES() { - glDeleteTextures(3, (GLuint*)data_tex); - } + TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), isAllowTexture1D_(isAllowTexture1D) { } + ~TessellationDataTransferGLES() { } void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override; }; }; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 854a91e46c..52c2d4390f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -42,7 +42,6 @@ #include "GPU/Common/TextureDecoder.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Debugger/Stepping.h" -#include "ext/native/gfx/GLStateCache.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/DrawEngineGLES.h" @@ -103,13 +102,14 @@ void FramebufferManagerGLES::CompileDraw2DProgram() { static std::string vs_code, fs_code; vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER); - draw2dprogram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString); - if (!draw2dprogram_) { - ERROR_LOG_REPORT(G3D, "Failed to compile draw2dprogram! This shouldn't happen.\n%s", errorString.c_str()); - } else { - glsl_bind(draw2dprogram_); - glUniform1i(draw2dprogram_->sampler0, 0); - } + std::vector shaders; + GLRShader *vs = render_->CreateShader(GL_VERTEX_SHADER, vs_code); + GLRShader *fs = render_->CreateShader(GL_FRAGMENT_SHADER, fs_code); + std::vector queries; + queries.push_back({ &u_draw2d_tex, "u_tex" }); + std::vector initializers; + initializers.push_back({ &u_draw2d_tex, 0 }); + draw2dprogram_ = render_->CreateProgram(shaders, {}, queries, initializers, false); CompilePostShader(); } } @@ -156,7 +156,26 @@ void FramebufferManagerGLES::CompilePostShader() { } if (!translationFailed) { - postShaderProgram_ = glsl_create_source(vshader.c_str(), fshader.c_str(), &errorString); + SetNumExtraFBOs(1); + + std::vector shaders; + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader)); + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader)); + std::vector queries; + queries.push_back({ &u_postShaderTex, "tex" }); + queries.push_back({ &deltaLoc_, "u_texelDelta" }); + queries.push_back({ &pixelDeltaLoc_, "u_pixelDelta" }); + queries.push_back({ &timeLoc_, "u_time" }); + queries.push_back({ &videoLoc_, "u_video" }); + + std::vector inits; + inits.push_back({ &u_postShaderTex, 0, 0 }); + postShaderProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); + render_->SetUniformI1(&u_postShaderTex, 0); + + for (auto iter : shaders) { + render_->DeleteShader(iter); + } } else { ERROR_LOG(FRAMEBUF, "Failed to translate post shader!"); } @@ -194,13 +213,6 @@ void FramebufferManagerGLES::CompilePostShader() { } usePostShader_ = false; } else { - glsl_bind(postShaderProgram_); - glUniform1i(postShaderProgram_->sampler0, 0); - SetNumExtraFBOs(1); - deltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_texelDelta"); - pixelDeltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); - timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); - videoLoc_ = glsl_uniform_loc(postShaderProgram_, "u_video"); usePostShader_ = true; } } else { @@ -211,7 +223,7 @@ void FramebufferManagerGLES::CompilePostShader() { } void FramebufferManagerGLES::Bind2DShader() { - glsl_bind(draw2dprogram_); + render_->BindProgram(draw2dprogram_); } void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) { @@ -219,20 +231,20 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) if (!postShaderProgram_) { CompileDraw2DProgram(); } - - glsl_bind(postShaderProgram_); + render_->BindProgram(postShaderProgram_); if (deltaLoc_ != -1) - glUniform2f(deltaLoc_, uniforms.texelDelta[0], uniforms.texelDelta[1]); + render_->SetUniformF(&deltaLoc_, 2, uniforms.texelDelta); if (pixelDeltaLoc_ != -1) - glUniform2f(pixelDeltaLoc_, uniforms.pixelDelta[0], uniforms.pixelDelta[1]); + render_->SetUniformF(&pixelDeltaLoc_, 2, uniforms.pixelDelta); if (timeLoc_ != -1) - glUniform4fv(timeLoc_, 1, uniforms.time); + render_->SetUniformF(&timeLoc_, 4, uniforms.time); if (videoLoc_ != -1) - glUniform1f(videoLoc_, uniforms.video); + render_->SetUniformF(&videoLoc_, 1, &uniforms.video); } -FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : +FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : FramebufferManagerCommon(draw), + render_(render), drawPixelsTex_(0), drawPixelsTexFormat_(GE_FORMAT_INVALID), convBuf_(nullptr), @@ -275,15 +287,25 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) { void FramebufferManagerGLES::CreateDeviceObjects() { CompileDraw2DProgram(); + + std::vector entries; + entries.push_back({ 0, 3, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, pos) }); + entries.push_back({ 0, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, uv) }); + simple2DInputLayout_ = render_->CreateInputLayout(entries); } void FramebufferManagerGLES::DestroyDeviceObjects() { + if (simple2DInputLayout_) { + render_->DeleteInputLayout(simple2DInputLayout_); + simple2DInputLayout_ = nullptr; + } + if (draw2dprogram_) { - glsl_destroy(draw2dprogram_); + render_->DeleteProgram(draw2dprogram_); draw2dprogram_ = nullptr; } if (postShaderProgram_) { - glsl_destroy(postShaderProgram_); + render_->DeleteProgram(postShaderProgram_); postShaderProgram_ = nullptr; } if (drawPixelsTex_) { @@ -291,7 +313,7 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { drawPixelsTex_ = 0; } if (stencilUploadProgram_) { - glsl_destroy(stencilUploadProgram_); + render_->DeleteProgram(stencilUploadProgram_); stencilUploadProgram_ = nullptr; } } @@ -329,15 +351,10 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma drawPixelsTexW_ = texWidth; drawPixelsTexH_ = height; - /* - // Initialize backbuffer texture for DrawPixels - glBindTexture(GL_TEXTURE_2D, drawPixelsTex_); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + render_->BindTexture(0, drawPixelsTex_); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); + /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); */ drawPixelsTexFormat_ = srcPixelFormat; @@ -392,7 +409,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) { - glstate.viewport.set(x, y, w, h); + render_->SetViewport({ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f }); } // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. @@ -405,7 +422,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float u0,v1, }; - static const GLushort indices[4] = {0,1,3,2}; + static const GLushort indices[4] = { 0,1,3,2 }; if (uvRotation != ROTATION_LOCKED_HORIZONTAL) { float temp[8]; @@ -424,9 +441,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float float pos[12] = { x,y,0, - x+w,y,0, - x+w,y+h,0, - x,y+h,0 + x + w,y,0, + x + w,y + h,0, + x,y + h,0 }; float invDestW = 1.0f / (destW * 0.5f); @@ -438,11 +455,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float // Upscaling postshaders doesn't look well with linear if (flags & DRAWTEX_LINEAR) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); } const GLSLProgram *program = glsl_get_program(); @@ -450,30 +465,23 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float ERROR_LOG(FRAMEBUF, "Trying to DrawActiveTexture() without a program"); return; } + Simple2DVertex verts[4]; + memcpy(verts[0].pos, &pos[0], 12); + memcpy(verts[1].pos, &pos[3], 12); + memcpy(verts[3].pos, &pos[6], 12); + memcpy(verts[2].pos, &pos[9], 12); + memcpy(verts[0].uv, &texCoords[0], 8); + memcpy(verts[1].uv, &texCoords[2], 8); + memcpy(verts[3].uv, &texCoords[4], 8); + memcpy(verts[2].uv, &texCoords[6], 8); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_texcoord0); - if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { - drawEngineGL_->BindBuffer(pos, sizeof(pos), texCoords, sizeof(texCoords)); - drawEngineGL_->BindElementBuffer(indices, sizeof(indices)); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos)); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); - } else { - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices); - } - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_texcoord0); -} - -void FramebufferManagerGLES::RebindFramebuffer() { - FramebufferManagerCommon::RebindFramebuffer(); - if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) - glstate.viewport.restore(); + uint32_t bindOffset; + GLRBuffer *buffer; + void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer); + memcpy(dest, verts, sizeof(verts)); + render_->BindVertexBuffer(buffer); + render_->BindInputLayout(simple2DInputLayout_, (void *)(intptr_t)bindOffset); + render_->Draw(GL_TRIANGLE_STRIP, 0, 4); } void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) { @@ -514,17 +522,15 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu if (gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT)) { // Let's only do this if not clearing depth. - glstate.scissorTest.force(false); draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST); dst->last_frame_depth_updated = gpuStats.numFlips; - glstate.scissorTest.restore(); } } } void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) { if (!framebuffer->fbo || !useBufferedRendering_) { - glBindTexture(GL_TEXTURE_2D, 0); + render_->BindTexture(0, nullptr); gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; return; } @@ -691,7 +697,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, } } - glstate.scissorTest.force(false); if (useBlit) { draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST); } else { @@ -701,38 +706,21 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, // Make sure our 2D drawing program is ready. Compiles only if not already compiled. CompileDraw2DProgram(); - glstate.viewport.force(0, 0, dst->renderWidth, dst->renderHeight); - glstate.blend.force(false); - glstate.cullFace.force(false); - glstate.depthTest.force(false); - glstate.stencilTest.force(false); -#if !defined(USING_GLES2) - glstate.colorLogicOp.force(false); -#endif - glstate.colorMask.force(true, true, true, true); - glstate.stencilMask.force(0xFF); + render_->SetViewport({ 0, 0, (float)dst->renderWidth, (float)dst->renderHeight, 0, 1.0f }); + render_->SetStencilDisabled(); + render_->SetDepth(false, false, GL_ALWAYS); + render_->SetNoBlendAndMask(0xF); // The first four coordinates are relative to the 6th and 7th arguments of DrawActiveTexture. // Should maybe revamp that interface. float srcW = src->bufferWidth; float srcH = src->bufferHeight; - glsl_bind(draw2dprogram_); + render_->BindProgram(draw2dprogram_); DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); textureCacheGL_->ForgetLastTexture(); - glstate.viewport.restore(); - glstate.blend.restore(); - glstate.cullFace.restore(); - glstate.depthTest.restore(); - glstate.stencilTest.restore(); -#if !defined(USING_GLES2) - glstate.colorLogicOp.restore(); -#endif - glstate.colorMask.restore(); - glstate.stencilMask.restore(); } - glstate.scissorTest.restore(); + gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 42d675ebe9..57111e3fa2 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -51,7 +51,7 @@ struct AsyncPBO { class FramebufferManagerGLES : public FramebufferManagerCommon { public: - FramebufferManagerGLES(Draw::DrawContext *draw); + FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render); ~FramebufferManagerGLES(); void SetTextureCache(TextureCacheGLES *tc); @@ -82,7 +82,6 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; - virtual void RebindFramebuffer() override; void DeviceRestore(Draw::DrawContext *draw); @@ -104,7 +103,6 @@ private: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void CompileDraw2DProgram(); - void DestroyDraw2DProgram(); void CompilePostShader(); void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently @@ -121,19 +119,34 @@ private: u8 *convBuf_; u32 convBufSize_; - GLSLProgram *draw2dprogram_ = nullptr; - GLSLProgram *postShaderProgram_ = nullptr; - GLSLProgram *stencilUploadProgram_ = nullptr; - int plainColorLoc_; - int videoLoc_; - int timeLoc_; - int pixelDeltaLoc_; - int deltaLoc_; + GLRProgram *draw2dprogram_ = nullptr; + GLRProgram *postShaderProgram_ = nullptr; + + + GLRProgram *stencilUploadProgram_ = nullptr; + int u_stencilUploadTex = -1; + int u_stencilValue = -1; + int u_postShaderTex = -1; + + // Cached uniform locs + int u_draw2d_tex = -1; + + int plainColorLoc_ = -1; + int videoLoc_ = -1; + int timeLoc_ = -1; + int pixelDeltaLoc_ = -1; + int deltaLoc_ = -1; TextureCacheGLES *textureCacheGL_; ShaderManagerGLES *shaderManagerGL_; DrawEngineGLES *drawEngineGL_; + struct Simple2DVertex { + float pos[3]; + float uv[2]; + }; + GLRInputLayout *simple2DInputLayout_; + // Not used under ES currently. AsyncPBO *pixelBufObj_; //this isn't that large u8 currentPBO_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 8139f142ac..be88cda194 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -86,7 +86,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) GLRenderManager *render = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); shaderManagerGL_ = new ShaderManagerGLES(render); - framebufferManagerGL_ = new FramebufferManagerGLES(draw); + framebufferManagerGL_ = new FramebufferManagerGLES(draw, render); framebufferManager_ = framebufferManagerGL_; textureCacheGL_ = new TextureCacheGLES(draw); textureCache_ = textureCacheGL_; @@ -163,7 +163,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. glstate.Restore(); - drawEngine_.RestoreVAO(); textureCacheGL_->NotifyConfigChanged(); // Load shader cache. @@ -498,7 +497,6 @@ void GPU_GLES::UpdateCmdInfo() { } void GPU_GLES::ReapplyGfxState() { - drawEngine_.RestoreVAO(); glstate.Restore(); GPUCommon::ReapplyGfxState(); } @@ -509,7 +507,6 @@ void GPU_GLES::BeginFrame() { textureCacheGL_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); - drawEngine_.DecimateBuffers(); depalShaderCache_.Decimate(); fragmentTestCache_.Decimate(); diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 01dfcf254e..15da119330 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -126,26 +126,32 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe static std::string vs_code, fs_code; vs_code = ApplyGLSLPrelude(stencil_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(stencil_fs, GL_FRAGMENT_SHADER); - stencilUploadProgram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString); + std::vector shaders; + shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code)); + shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code)); + std::vector queries; + queries.push_back({ &u_stencilUploadTex, "tex" }); + std::vector inits; + inits.push_back({ &u_stencilUploadTex, 0, 0 }); + stencilUploadProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false); + for (auto iter : shaders) { + render_->DeleteShader(iter); + } if (!stencilUploadProgram_) { ERROR_LOG_REPORT(G3D, "Failed to compile stencilUploadProgram! This shouldn't happen.\n%s", errorString.c_str()); } else { - glsl_bind(stencilUploadProgram_); + render_->BindProgram(stencilUploadProgram_); } - - GLint u_tex = glsl_uniform_loc(stencilUploadProgram_, "tex"); - glUniform1i(u_tex, 0); } else { - glsl_bind(stencilUploadProgram_); + render_->BindProgram(stencilUploadProgram_); } shaderManagerGL_->DirtyLastShader(); DisableState(); - glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + render_->SetNoBlendAndMask(0x8); glstate.stencilTest.enable(); glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE); bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); @@ -164,43 +170,41 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe } else if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } - glViewport(0, 0, w, h); - gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE); + render_->SetViewport({ 0, 0, (float)w, (float)h, 0.0f, 1.0f }); float u1 = 1.0f; float v1 = 1.0f; MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); textureCacheGL_->ForgetLastTexture(); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); - glstate.stencilFunc.set(GL_ALWAYS, 0xFF, 0xFF); - - GLint u_stencilValue = glsl_uniform_loc(stencilUploadProgram_, "u_stencilValue"); for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { // It's already zero, let's skip it. continue; } if (dstBuffer->format == GE_FORMAT_4444) { - glstate.stencilMask.set((i << 4) | i); - glUniform1f(u_stencilValue, i * (16.0f / 255.0f)); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF); + render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f)); } else if (dstBuffer->format == GE_FORMAT_5551) { glstate.stencilMask.set(0xFF); - glUniform1f(u_stencilValue, i * (128.0f / 255.0f)); + render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f)); } else { - glstate.stencilMask.set(i); - glUniform1f(u_stencilValue, i * (1.0f / 255.0f)); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF); + render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); } - glstate.stencilMask.set(0xFF); + render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF); if (useBlit) { draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); + RebindFramebuffer(); return true; } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 43cbc96914..307b208342 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -401,6 +401,7 @@ public: void Use(GLRenderManager *render, DrawEngineGLES *transformDraw) { render->BindProgram(shader_->program); + /* // Restore will rebind all of the state below. if (gstate_c.Supports(GPU_SUPPORTS_VAO)) { static const GLubyte indices[4] = { 0, 1, 3, 2 }; @@ -412,11 +413,12 @@ public: } glEnableVertexAttribArray(shader_->a_position); glEnableVertexAttribArray(shader_->a_texcoord0); + */ } void Shade() { static const GLubyte indices[4] = { 0, 1, 3, 2 }; - + /* glstate.blend.force(false); glstate.colorMask.force(true, true, true, true); glstate.scissorTest.force(false); @@ -441,6 +443,7 @@ public: glDisableVertexAttribArray(shader_->a_texcoord0); glstate.Restore(); + */ } protected: @@ -473,8 +476,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram render_->BindTexture(3, clutTexture); framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); shaderApply.Shade(); @@ -496,8 +498,6 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram framebufferManagerGL_->RebindFramebuffer(); SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); - CHECK_GL_ERROR_IF_DEBUG(); - InvalidateLastTexture(); } diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 37084abb05..42b25e040f 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -99,16 +99,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { break; } - // Auto-initialize samplers. glUseProgram(program->program); - for (int i = 0; i < 4; i++) { - char temp[256]; - sprintf(temp, "Sampler%i", i); - int samplerLoc = glGetUniformLocation(program->program, temp); - if (samplerLoc != -1) { - glUniform1i(samplerLoc, i); - } - } // Query all the uniforms. for (int i = 0; i < program->queries_.size(); i++) { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 2d96cf0fae..f6ddf68ef9 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -318,6 +318,8 @@ private: GLuint globalVAO_; GLint curFramebuffer_ = 0; + int curFBWidth_; + int curFBHeight_; // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 616f932986..19c82ee043 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -122,7 +122,7 @@ public: glDeleteBuffers(1, &buffer); } } - GLuint buffer; + GLuint buffer = 0; GLuint target_; private: }; @@ -216,6 +216,8 @@ public: return step.create_framebuffer.framebuffer; } + // Can't replace uniform initializers with direct calls to SetUniform() etc because there might + // not be an active render pass. GLRProgram *CreateProgram( std::vector shaders, std::vector semantics, std::vector queries, std::vector initalizers, bool supportDualSource) { @@ -398,6 +400,15 @@ public: curRenderStep_->commands.push_back(data); } + void SetUniformF1(GLint *loc, const float udata) { + _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); + GLRRenderData data{ GLRRenderCommand::UNIFORM4F }; + data.uniform4.loc = loc; + data.uniform4.count = 1; + memcpy(data.uniform4.v, &udata, sizeof(float)); + curRenderStep_->commands.push_back(data); + } + void SetUniformF(const char *name, int count, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::UNIFORM4F };