Sprinkle calls to CHECK_GL_ERROR_IF_DEBUG all over the place, disabled by default.

This commit is contained in:
Henrik Rydgard 2017-03-03 14:15:27 +01:00
parent b0eab68760
commit 5d4700ae7e
10 changed files with 128 additions and 75 deletions

View File

@ -72,6 +72,7 @@
#include "Core/Config.h"
#include "Core/CoreTiming.h"
#include "gfx/gl_debug_log.h"
#include "profiler/profiler.h"
#include "GPU/Math3D.h"
@ -256,6 +257,7 @@ static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) {
// TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets
static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) {
CHECK_GL_ERROR_IF_DEBUG();
VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off);
VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off);
VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff);
@ -263,6 +265,7 @@ static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt
VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off);
VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff);
VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff);
CHECK_GL_ERROR_IF_DEBUG();
}
void DrawEngineGLES::SetupVertexDecoder(u32 vertType) {
@ -643,14 +646,14 @@ void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) {
void DrawEngineGLES::DoFlush() {
PROFILE_THIS_SCOPE("flush");
CHECK_GL_ERROR_IF_DEBUG();
gpuStats.numFlushes++;
gpuStats.numTrackedVertexArrays = (int)vai_.size();
// This is not done on every drawcall, we should collect vertex data
// until critical state changes. That's when we draw (flush).
GEPrimitiveType prim = prevPrim_;
ApplyDrawState(prim);
CHECK_GL_ERROR_IF_DEBUG();
ShaderID vsid;
Shader *vshader = shaderManager_->ApplyVertexShader(prim, lastVType_, &vsid);
@ -1003,6 +1006,7 @@ rotateVBO:
#ifndef MOBILE_DEVICE
host->GPUNotifyDraw();
#endif
CHECK_GL_ERROR_IF_DEBUG();
}
void DrawEngineGLES::Resized() {
@ -1212,4 +1216,5 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float
}
}
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR_IF_DEBUG();
}

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "gfx/gl_debug_log.h"
#include "Core/Config.h"
#include "GPU/GLES/FragmentTestCacheGLES.h"
#include "GPU/GPUState.h"
@ -55,10 +56,12 @@ void FragmentTestCacheGLES::BindTestTexture(GLenum unit) {
// Already bound, hurray.
return;
}
CHECK_GL_ERROR_IF_DEBUG();
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, tex);
// Always return to the default.
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR_IF_DEBUG();
lastTexture_ = tex;
return;
}

View File

@ -20,6 +20,7 @@
#include "profiler/profiler.h"
#include "gfx/gl_common.h"
#include "gfx/gl_debug_log.h"
#include "gfx_es2/glsl_program.h"
#include "thin3d/thin3d.h"
@ -347,6 +348,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, useConvBuf ? convBuf_ : srcPixels);
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) {
@ -670,6 +672,7 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb)
draw_->BindFramebufferAsRenderTarget(nvfb->fbo);
ClearBuffer();
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) {
@ -721,6 +724,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2;
if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) {
draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1, Draw::FB_COLOR_BIT);
CHECK_GL_ERROR_IF_DEBUG();
return;
}
}
@ -767,6 +771,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
}
glstate.scissorTest.restore();
CHECK_GL_ERROR_IF_DEBUG();
}
// TODO: SSE/NEON
@ -887,6 +892,7 @@ static void LogReadPixelsError(GLenum error) {
#endif
static void SafeGLReadPixels(GLint x, GLint y, GLsizei w, GLsizei h, GLenum fmt, GLenum type, void *pixels) {
CHECK_GL_ERROR_IF_DEBUG();
if (!gl_extensions.IsGLES || (gl_extensions.GLES3 && gl_extensions.gpuVendor != GPU_VENDOR_NVIDIA)) {
// Some drivers seem to require we specify this. See #8254.
glPixelStorei(GL_PACK_ROW_LENGTH, w);
@ -900,9 +906,11 @@ static void SafeGLReadPixels(GLint x, GLint y, GLsizei w, GLsizei h, GLenum fmt,
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
CHECK_GL_ERROR_IF_DEBUG();
const int MAX_PBO = 2;
GLubyte *packed = 0;
bool unbind = false;
@ -1050,6 +1058,7 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
if (unbind) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
@ -1097,6 +1106,7 @@ void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x
if (UseBGRA8888()) {
glfmt = GL_BGRA_EXT;
}
CHECK_GL_ERROR_IF_DEBUG();
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed);
@ -1116,6 +1126,7 @@ void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(target, 3, attachments);
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
@ -1157,9 +1168,11 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int
depth[i] = (int)scaled;
}
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::EndFrame() {
CHECK_GL_ERROR_IF_DEBUG();
if (resized_) {
// TODO: Only do this if the new size actually changed the renderwidth/height.
DestroyAllFBOs(false);
@ -1230,6 +1243,7 @@ void FramebufferManagerGLES::EndFrame() {
}
draw_->BindBackbufferAsRenderTarget();
}
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::DeviceLost() {
@ -1258,6 +1272,7 @@ std::vector<FramebufferInfo> FramebufferManagerGLES::GetFramebufferList() {
}
void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) {
CHECK_GL_ERROR_IF_DEBUG();
draw_->BindBackbufferAsRenderTarget();
currentRenderVfb_ = 0;
displayFramebuf_ = 0;
@ -1284,6 +1299,7 @@ void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) {
draw_->BindBackbufferAsRenderTarget();
DisableState();
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::FlushBeforeCopy() {
@ -1295,6 +1311,7 @@ void FramebufferManagerGLES::FlushBeforeCopy() {
// do something more focused here.
SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
drawEngine_->Flush();
CHECK_GL_ERROR_IF_DEBUG();
}
void FramebufferManagerGLES::Resized() {
@ -1343,6 +1360,7 @@ bool FramebufferManagerGLES::GetFramebuffer(u32 fb_address, int fb_stride, GEBuf
// We may have blitted to a temp FBO.
RebindFramebuffer();
CHECK_GL_ERROR_IF_DEBUG();
return true;
}
@ -1354,6 +1372,7 @@ bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
buffer.Allocate(pw, ph, GPU_DBG_FORMAT_888_RGB, true);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
SafeGLReadPixels(0, 0, pw, ph, GL_RGB, GL_UNSIGNED_BYTE, buffer.GetData());
CHECK_GL_ERROR_IF_DEBUG();
return true;
}
@ -1384,7 +1403,7 @@ bool FramebufferManagerGLES::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z
glReadBuffer(GL_COLOR_ATTACHMENT0);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
SafeGLReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_DEPTH_COMPONENT, GL_FLOAT, buffer.GetData());
CHECK_GL_ERROR_IF_DEBUG();
return true;
}
@ -1409,7 +1428,7 @@ bool FramebufferManagerGLES::GetStencilbuffer(u32 fb_address, int fb_stride, GPU
glReadBuffer(GL_COLOR_ATTACHMENT0);
glPixelStorei(GL_PACK_ALIGNMENT, 2);
SafeGLReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buffer.GetData());
CHECK_GL_ERROR_IF_DEBUG();
return true;
#else
return false;

View File

@ -24,6 +24,7 @@
#include "base/logging.h"
#include "base/timeutil.h"
#include "gfx/gl_debug_log.h"
#include "i18n/i18n.h"
#include "math/math_util.h"
#include "math/lin/matrix4x4.h"
@ -80,6 +81,7 @@ Shader::Shader(const char *code, uint32_t glShaderType, bool useHWTransform)
} else {
DEBUG_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code);
}
CHECK_GL_ERROR_IF_DEBUG();
}
Shader::~Shader() {
@ -313,6 +315,7 @@ LinkedShader::LinkedShader(ShaderID VSID, Shader *vs, ShaderID FSID, Shader *fs,
// The rest, use the "dirty" mechanism.
dirtyUniforms = DIRTY_ALL_UNIFORMS;
CHECK_GL_ERROR_IF_DEBUG();
}
LinkedShader::~LinkedShader() {
@ -435,6 +438,8 @@ void LinkedShader::stop() {
}
void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
CHECK_GL_ERROR_IF_DEBUG();
u64 dirty = dirtyUniforms & availableUniforms;
dirtyUniforms = 0;
if (!dirty)
@ -743,6 +748,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
if (dirty & DIRTY_SPLINETYPEV)
glUniform1i(u_spline_type_v, gstate_c.spline_type_v);
}
CHECK_GL_ERROR_IF_DEBUG();
}
ShaderManagerGLES::ShaderManagerGLES()

View File

@ -22,6 +22,7 @@
#include "StateMappingGLES.h"
#include "profiler/profiler.h"
#include "gfx/gl_debug_log.h"
#include "GPU/Math3D.h"
#include "GPU/GPUState.h"
@ -344,6 +345,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
CHECK_GL_ERROR_IF_DEBUG();
}
void DrawEngineGLES::ApplyDrawStateLate() {
@ -351,9 +353,11 @@ void DrawEngineGLES::ApplyDrawStateLate() {
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
if (!gstate.isModeClear()) {
if (fboTexNeedBind_) {
CHECK_GL_ERROR_IF_DEBUG();
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
framebufferManager_->RebindFramebuffer();
CHECK_GL_ERROR_IF_DEBUG();
glActiveTexture(GL_TEXTURE1);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
@ -362,15 +366,19 @@ void DrawEngineGLES::ApplyDrawStateLate() {
glActiveTexture(GL_TEXTURE0);
fboTexBound_ = true;
fboTexNeedBind_ = false;
CHECK_GL_ERROR_IF_DEBUG();
}
CHECK_GL_ERROR_IF_DEBUG();
// Apply the texture after the FBO tex, since it might unbind the texture.
// TODO: Could use a separate texture unit to be safer?
textureCache_->ApplyTexture();
CHECK_GL_ERROR_IF_DEBUG();
// Apply last, once we know the alpha params of the texture.
if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) {
fragmentTestCache_->BindTestTexture(GL_TEXTURE2);
}
CHECK_GL_ERROR_IF_DEBUG();
}
}

View File

@ -19,6 +19,7 @@
#include <cstring>
#include "ext/xxhash.h"
#include "gfx/gl_debug_log.h"
#include "i18n/i18n.h"
#include "math/math_util.h"
#include "profiler/profiler.h"
@ -121,6 +122,7 @@ static const GLuint MagFiltGL[2] = {
// This should not have to be done per texture! OpenGL is silly yo
void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
CHECK_GL_ERROR_IF_DEBUG();
int minFilt;
int magFilt;
bool sClamp;
@ -172,6 +174,7 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
entry.tClamp = tClamp;
}
CHECK_GL_ERROR_IF_DEBUG();
}
void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) {
@ -325,11 +328,14 @@ bool SetDebugTexture() {
#endif
void TextureCacheGLES::BindTexture(TexCacheEntry *entry) {
CHECK_GL_ERROR_IF_DEBUG();
if (entry->textureName != lastBoundTexture) {
glBindTexture(GL_TEXTURE_2D, entry->textureName);
lastBoundTexture = entry->textureName;
}
CHECK_GL_ERROR_IF_DEBUG();
UpdateSamplingParams(*entry, false);
CHECK_GL_ERROR_IF_DEBUG();
}
void TextureCacheGLES::Unbind() {
@ -514,6 +520,8 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram
framebufferManagerGL_->RebindFramebuffer();
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
CHECK_GL_ERROR_IF_DEBUG();
lastBoundTexture = INVALID_TEX;
}
@ -675,7 +683,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
LoadTextureLevel(*entry, replaced, level, replaceImages, scaleFactor, dstFmt);
} else
LoadTextureLevel(*entry, replaced, 0, replaceImages, scaleFactor, dstFmt);
// Mipmapping only enable when texture scaling disable
if (maxLevel > 0 && scaleFactor == 1) {
if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
@ -721,6 +729,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
CHECK_GL_ERROR_IF_DEBUG();
}
u32 TextureCacheGLES::AllocTextureName() {
@ -806,6 +815,8 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
bool useBGRA;
u32 *pixelData;
CHECK_GL_ERROR_IF_DEBUG();
// TODO: only do this once
u32 texByteAlign = 1;
@ -871,6 +882,8 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign);
CHECK_GL_ERROR_IF_DEBUG();
GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA;
GLuint components2 = components;
@ -888,6 +901,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
else
glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components2, dstFmt, pixelData);
if (!lowMemoryMode_) {
// TODO: We really, really should avoid calling glGetError.
GLenum err = glGetError();
if (err == GL_OUT_OF_MEMORY) {
WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode");
@ -911,7 +925,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
case GL_INVALID_VALUE: str = "invalid_value"; break;
}
// We checked the err anyway, might as well log if there is one.
WARN_LOG(G3D, "Got an error in texture upload: %08x (%s) (components=%04x components2=%04x dstFmt=%04x w=%d h=%d level=%d)", err, str, components, components2, dstFmt, w, h, level);
WARN_LOG(G3D, "Got an error in texture upload: %08x (%s) (components=%s components2=%s dstFmt=%s w=%d h=%d level=%d)",
err, str, GLEnumToString(components).c_str(), GLEnumToString(components2).c_str(), GLEnumToString(dstFmt).c_str(),
w, h, level);
}
}
}

View File

@ -86,7 +86,7 @@ VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
samp.addressModeU = key.sClamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
samp.addressModeV = key.tClamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
samp.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samp.addressModeW = samp.addressModeU; // irrelevant, but Mali recommends that all clamp modes are the same if possible.
samp.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
samp.compareOp = VK_COMPARE_OP_ALWAYS;
samp.flags = 0;

View File

@ -1,54 +1,40 @@
#include "gfx/gl_common.h"
#include "base/logging.h"
#include <cstdlib>
void glCheckzor(const char *file, int line) {
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err);
#include "base/logging.h"
#include "gfx/gl_common.h"
#include "gfx/gl_debug_log.h"
// This we can expand as needed.
std::string GLEnumToString(uint16_t value) {
char str[64];
switch (value) {
case GL_UNSIGNED_SHORT_4_4_4_4: return "GL_UNSIGNED_SHORT_4_4_4_4";
case GL_UNSIGNED_SHORT_5_5_5_1: return "GL_UNSIGNED_SHORT_5_5_5_1";
case GL_UNSIGNED_SHORT_5_6_5: return "GL_UNSIGNED_SHORT_5_6_5";
case GL_RGBA: return "GL_RGBA";
case GL_RGB: return "GL_RGB";
#if !defined(USING_GLES2)
case GL_BGRA: return "GL_BGRA";
case GL_UNSIGNED_SHORT_4_4_4_4_REV: return "GL_UNSIGNED_SHORT_4_4_4_4_REV";
case GL_UNSIGNED_SHORT_5_6_5_REV: return "GL_UNSIGNED_SHORT_5_6_5_REV";
case GL_UNSIGNED_SHORT_1_5_5_5_REV: return "GL_UNSIGNED_SHORT_1_5_5_5_REV";
case GL_UNSIGNED_INT_8_8_8_8_REV: return "GL_UNSIGNED_INT_8_8_8_8_REV";
#endif
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_PACK_ALIGNMENT: return "GL_PACK_ALIGNMENT";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
default: {
snprintf(str, sizeof(str), "(unk:%04x)", value);
return str;
}
}
}
#if !defined(USING_GLES2)
#if 0
void log_callback(GLenum source, GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam) {
const char *src = "unknown";
switch (source) {
case GL_DEBUG_SOURCE_API_GL_ARB:
src = "GL";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
src = "GLSL";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
src = "X";
break;
default:
break;
}
switch (type) {
case GL_DEBUG_TYPE_ERROR_ARB:
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
ELOG("%s: %s", src, message);
break;
default:
ILOG("%s: %s", src, message);
break;
}
}
#endif
#endif
void gl_log_enable() {
#if !defined(USING_GLES2)
#if 0
glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf
glDebugMessageCallback(&log_callback, 0);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
#endif
#endif
void CheckGLError(const char *file, int line) {
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
ELOG("GL error %s on %s:%d", GLEnumToString(err).c_str(), file, line);
}
}

View File

@ -1,25 +1,22 @@
#pragma once
#include <string>
#include <cstdint>
// Utility to be able to liberally sprinkle GL error checks around your code
// and easily disable them all in release builds - just undefine DEBUG_OPENGL.
void gl_log_enable();
#if !defined(USING_GLES2)
//#define DEBUG_OPENGL
#endif
// #define DEBUG_OPENGL
#if defined(DEBUG_OPENGL)
void glCheckzor(const char *file, int line);
#define GL_CHECK() glCheckzor(__FILE__, __LINE__)
void CheckGLError(const char *file, int line);
#define CHECK_GL_ERROR_IF_DEBUG() CheckGLError(__FILE__, __LINE__)
#else
#define GL_CHECK()
#define CHECK_GL_ERROR_IF_DEBUG()
#endif
std::string GLEnumToString(uint16_t value);

View File

@ -9,6 +9,7 @@
#include "math/lin/matrix4x4.h"
#include "thin3d/thin3d.h"
#include "gfx/gl_common.h"
#include "gfx/gl_debug_log.h"
#include "gfx/GLStateCache.h"
#include "gfx_es2/gpu_features.h"
#include "gfx/gl_lost_manager.h"
@ -754,6 +755,7 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
return;
}
CHECK_GL_ERROR_IF_DEBUG();
switch (target_) {
case GL_TEXTURE_2D:
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data);
@ -762,11 +764,7 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
ELOG("Thin3D GL: Targets other than GL_TEXTURE_2D not yet supported");
break;
}
GLenum err2 = glGetError();
if (err2) {
ELOG("Thin3D GL: Error loading texture: %08x", err2);
}
CHECK_GL_ERROR_IF_DEBUG();
}
Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) {
@ -1336,6 +1334,7 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
}
// If GLES2, we have basic FBO support and can just proceed.
#endif
CHECK_GL_ERROR_IF_DEBUG();
OpenGLFramebuffer *fbo = new OpenGLFramebuffer();
fbo->width = desc.width;
@ -1444,6 +1443,7 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
// Unbind state we don't need
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
CHECK_GL_ERROR_IF_DEBUG();
currentDrawHandle_ = fbo->handle;
currentReadHandle_ = fbo->handle;
@ -1512,16 +1512,20 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) {
fbo_bind_fb_target(false, fb->handle);
// Always restore viewport after render target binding
glstate.viewport.restore();
CHECK_GL_ERROR_IF_DEBUG();
}
void OpenGLContext::BindBackbufferAsRenderTarget() {
CHECK_GL_ERROR_IF_DEBUG();
fbo_unbind();
CHECK_GL_ERROR_IF_DEBUG();
}
// For GL_EXT_FRAMEBUFFER_BLIT and similar.
void OpenGLContext::BindFramebufferForRead(Framebuffer *fbo) {
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
fbo_bind_fb_target(true, fb->handle);
CHECK_GL_ERROR_IF_DEBUG();
}
void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) {
@ -1562,6 +1566,7 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s
width, height, depth);
}
#endif
CHECK_GL_ERROR_IF_DEBUG();
}
bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter) {
@ -1578,10 +1583,12 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in
BindFramebufferForRead(src);
if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) {
glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST);
CHECK_GL_ERROR_IF_DEBUG();
#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC.
return true;
} else if (gl_extensions.NV_framebuffer_blit) {
glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST);
CHECK_GL_ERROR_IF_DEBUG();
#endif // defined(USING_GLES2) && defined(__ANDROID__)
return true;
} else {
@ -1590,8 +1597,13 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in
}
uintptr_t OpenGLContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) {
// Unimplemented
return 0;
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
switch (channelBits) {
case FB_COLOR_BIT: return (uintptr_t)fb->color_texture;
case FB_DEPTH_BIT: return (uintptr_t)(fb->z_buffer ? fb->z_buffer : fb->z_stencil_buffer);
default:
return 0;
}
}
void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int color) {
@ -1612,6 +1624,7 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh
}
OpenGLFramebuffer::~OpenGLFramebuffer() {
CHECK_GL_ERROR_IF_DEBUG();
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
glBindFramebuffer(GL_FRAMEBUFFER, handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);