bool WrappedOpenGL::Serialise_glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) { SERIALISE_ELEMENT(ResourceId, srcid, GetResourceManager()->GetID(TextureRes(GetCtx(), srcName))); SERIALISE_ELEMENT(ResourceId, dstid, GetResourceManager()->GetID(TextureRes(GetCtx(), dstName))); SERIALISE_ELEMENT(GLenum, SourceTarget, srcTarget); SERIALISE_ELEMENT(GLenum, DestTarget, dstTarget); SERIALISE_ELEMENT(uint32_t, SourceLevel, srcLevel); SERIALISE_ELEMENT(uint32_t, SourceX, srcX); SERIALISE_ELEMENT(uint32_t, SourceY, srcY); SERIALISE_ELEMENT(uint32_t, SourceZ, srcZ); SERIALISE_ELEMENT(uint32_t, SourceWidth, srcWidth); SERIALISE_ELEMENT(uint32_t, SourceHeight, srcHeight); SERIALISE_ELEMENT(uint32_t, SourceDepth, srcDepth); SERIALISE_ELEMENT(uint32_t, DestLevel, dstLevel); SERIALISE_ELEMENT(uint32_t, DestX, dstX); SERIALISE_ELEMENT(uint32_t, DestY, dstY); SERIALISE_ELEMENT(uint32_t, DestZ, dstZ); if(m_State < WRITING) { GLResource srcres = GetResourceManager()->GetLiveResource(srcid); GLResource dstres = GetResourceManager()->GetLiveResource(dstid); m_Real.glCopyImageSubData(srcres.name, SourceTarget, SourceLevel, SourceX, SourceY, SourceZ, dstres.name, DestTarget, DestLevel, DestX, DestY, DestZ, SourceWidth, SourceHeight, SourceDepth); } return true; }
void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) { m_Real.glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); if(m_State >= WRITING) { GLResourceRecord *srcrecord = GetResourceManager()->GetResourceRecord(TextureRes(srcName)); GLResourceRecord *dstrecord = GetResourceManager()->GetResourceRecord(TextureRes(dstName)); RDCASSERT(srcrecord && dstrecord); SCOPED_SERIALISE_CONTEXT(COPY_SUBIMAGE); Serialise_glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth); Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) { m_ContextRecord->AddChunk(chunk); } else { dstrecord->AddChunk(chunk); dstrecord->AddParent(srcrecord); } } }
bool WrappedOpenGL::Serialise_glCompressedTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(int32_t, Level, level); SERIALISE_ELEMENT(int32_t, xoff, xoffset); SERIALISE_ELEMENT(int32_t, yoff, yoffset); SERIALISE_ELEMENT(int32_t, zoff, zoffset); SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(uint32_t, Height, height); SERIALISE_ELEMENT(uint32_t, Depth, depth); SERIALISE_ELEMENT(GLenum, fmt, format); SERIALISE_ELEMENT(uint32_t, byteSize, imageSize); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); SERIALISE_ELEMENT_BUF(byte *, buf, pixels, byteSize); if(m_State == READING) { m_Real.glCompressedTextureSubImage3DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Level, xoff, yoff, zoff, Width, Height, Depth, fmt, byteSize, buf); delete[] buf; } return true; }
bool WrappedOpenGL::Serialise_glNamedFramebufferTextureEXT(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) { SERIALISE_ELEMENT(GLenum, Attach, attachment); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(GetCtx(), texture))); SERIALISE_ELEMENT(int32_t, Level, level); SERIALISE_ELEMENT(ResourceId, fbid, (framebuffer == 0 ? ResourceId() : GetResourceManager()->GetID(FramebufferRes(GetCtx(), framebuffer)))); if(m_State < WRITING) { GLResource res = GetResourceManager()->GetLiveResource(id); if(fbid == ResourceId()) { glNamedFramebufferTextureEXT(0, Attach, res.name, Level); } else { GLResource fbres = GetResourceManager()->GetLiveResource(fbid); glNamedFramebufferTextureEXT(fbres.name, Attach, res.name, Level); } if(m_State == READING) { m_Textures[GetResourceManager()->GetLiveID(id)].creationFlags |= eTextureCreate_RTV; } } return true; }
void WrappedOpenGL::glGenTextures(GLsizei n, GLuint* textures) { m_Real.glGenTextures(n, textures); for(GLsizei i=0; i < n; i++) { GLResource res = TextureRes(textures[i]); ResourceId id = GetResourceManager()->RegisterResource(res); if(m_State >= WRITING) { Chunk *chunk = NULL; { SCOPED_SERIALISE_CONTEXT(GEN_TEXTURE); Serialise_glGenTextures(1, textures+i); chunk = scope.Get(); } GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); RDCASSERT(record); record->AddChunk(chunk); } else { GetResourceManager()->AddLiveResource(id, res); m_Textures[id].resource = res; m_Textures[id].curType = eGL_UNKNOWN_ENUM; } } }
void WrappedOpenGL::glDeleteTextures(GLsizei n, const GLuint *textures) { m_Real.glDeleteTextures(n, textures); for(GLsizei i=0; i < n; i++) GetResourceManager()->UnregisterResource(TextureRes(textures[i])); }
bool WrappedOpenGL::Serialise_glBindTexture(GLenum target, GLuint texture) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(ResourceId, Id, GetResourceManager()->GetID(TextureRes(texture))); if(m_State == WRITING_IDLE) { m_TextureRecord[m_TextureUnit]->datatype = Target; } else if(m_State < WRITING) { if(Id == ResourceId()) { m_Real.glBindTexture(Target, 0); } else { GLResource res = GetResourceManager()->GetLiveResource(Id); m_Real.glBindTexture(Target, res.name); m_Textures[GetResourceManager()->GetLiveID(Id)].curType = Target; } } return true; }
bool WrappedOpenGL::Serialise_glTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(int32_t, Level, level); SERIALISE_ELEMENT(int32_t, xoff, xoffset); SERIALISE_ELEMENT(int32_t, yoff, yoffset); SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(uint32_t, Height, height); SERIALISE_ELEMENT(GLenum, Format, format); SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); GLint align = 1; m_Real.glGetIntegerv(eGL_UNPACK_ALIGNMENT, &align); size_t subimageSize = GetByteSize(Width, Height, 1, Format, Type, Level, align); SERIALISE_ELEMENT_BUF(byte *, buf, pixels, subimageSize); if(m_State == READING) { m_Real.glTextureSubImage2DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Level, xoff, yoff, Width, Height, Format, Type, buf); delete[] buf; } return true; }
void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) { m_Real.glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); if(m_State >= WRITING) { ResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); ResourceRecord *origrecord = GetResourceManager()->GetResourceRecord(TextureRes(origtexture)); RDCASSERT(record && origrecord); SCOPED_SERIALISE_CONTEXT(TEXTURE_VIEW); Serialise_glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); record->AddChunk(scope.Get()); record->AddParent(origrecord); } }
bool WrappedOpenGL::Serialise_glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(uint64_t, offs, (uint64_t)offset); SERIALISE_ELEMENT(uint64_t, Size, (uint64_t)size); SERIALISE_ELEMENT(GLenum, fmt, internalformat); SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture))); SERIALISE_ELEMENT(ResourceId, bufid, GetResourceManager()->GetID(TextureRes(buffer))); if(m_State == READING) { m_Real.glTextureBufferRangeEXT(GetResourceManager()->GetLiveResource(texid).name, Target, fmt, GetResourceManager()->GetLiveResource(bufid).name, (GLintptr)offs, (GLsizeiptr)Size); } return true; }
bool WrappedOpenGL::Serialise_glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(GLenum, InternalFormat, internalformat); SERIALISE_ELEMENT(uint32_t, MinLevel, minlevel); SERIALISE_ELEMENT(uint32_t, NumLevels, numlevels); SERIALISE_ELEMENT(uint32_t, MinLayer, minlayer); SERIALISE_ELEMENT(uint32_t, NumLayers, numlayers); SERIALISE_ELEMENT(ResourceId, texid, GetResourceManager()->GetID(TextureRes(texture))); SERIALISE_ELEMENT(ResourceId, origid, GetResourceManager()->GetID(TextureRes(origtexture))); if(m_State == READING) { GLResource tex = GetResourceManager()->GetLiveResource(texid); GLResource origtex = GetResourceManager()->GetLiveResource(origid); m_Real.glTextureView(tex.name, Target, origtex.name, InternalFormat, MinLevel, NumLevels, MinLayer, NumLayers); } return true; }
bool WrappedOpenGL::Serialise_glGenTextures(GLsizei n, GLuint* textures) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(*textures))); if(m_State == READING) { GLuint real = 0; m_Real.glGenTextures(1, &real); GLResource res = TextureRes(real); ResourceId live = m_ResourceManager->RegisterResource(res); GetResourceManager()->AddLiveResource(id, res); m_Textures[live].resource = res; m_Textures[live].curType = eGL_UNKNOWN_ENUM; } return true; }
bool WrappedOpenGL::Serialise_glGenerateTextureMipmapEXT(GLuint texture, GLenum target) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); if(m_State == READING) { m_Real.glGenerateTextureMipmapEXT(GetResourceManager()->GetLiveResource(id).name, Target); } return true; }
void WrappedOpenGL::glBindTexture(GLenum target, GLuint texture) { m_Real.glBindTexture(target, texture); if(m_State == WRITING_CAPFRAME) { Chunk *chunk = NULL; { SCOPED_SERIALISE_CONTEXT(BIND_TEXTURE); Serialise_glBindTexture(target, texture); chunk = scope.Get(); } m_ContextRecord->AddChunk(chunk); } else if(m_State < WRITING) { m_Textures[GetResourceManager()->GetID(TextureRes(texture))].curType = target; } if(texture == 0) { m_TextureRecord[m_TextureUnit] = NULL; return; } if(m_State >= WRITING) { GLResourceRecord *r = m_TextureRecord[m_TextureUnit] = GetResourceManager()->GetResourceRecord(TextureRes(texture)); if(r->datatype) { // it's illegal to retype a texture RDCASSERT(r->datatype == target); } else { Chunk *chunk = NULL; { SCOPED_SERIALISE_CONTEXT(BIND_TEXTURE); Serialise_glBindTexture(target, texture); chunk = scope.Get(); } r->AddChunk(chunk); } } }
void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) { m_Real.glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture)); GLResourceRecord *origrecord = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), origtexture)); RDCASSERT(record && origrecord); SCOPED_SERIALISE_CONTEXT(TEXTURE_VIEW); Serialise_glTextureView(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers); record->AddChunk(scope.Get()); record->AddParent(origrecord); // illegal to re-type textures if(record->datatype == eGL_UNKNOWN_ENUM) record->datatype = target; else RDCASSERT(record->datatype == target); } }
bool WrappedOpenGL::Serialise_glTextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(GLenum, PName, pname); SERIALISE_ELEMENT(float, Param, param); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); if(m_State < WRITING) { m_Real.glTextureParameterfEXT(GetResourceManager()->GetLiveResource(id).name, Target, PName, Param); } return true; }
void WrappedOpenGL::glTextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) { m_Real.glTextureBufferRangeEXT(texture, target, internalformat, buffer, offset, size); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); RDCASSERT(record); SCOPED_SERIALISE_CONTEXT(TEXBUFFER_RANGE); Serialise_glTextureBufferRangeEXT(texture, target, internalformat, buffer, offset, size); record->AddChunk(scope.Get()); } }
bool WrappedOpenGL::Serialise_glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(GLenum, PName, pname); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); const size_t nParams = (PName == eGL_TEXTURE_BORDER_COLOR ? 4U : 1U); SERIALISE_ELEMENT_ARR(float, Params, params, nParams); if(m_State < WRITING) { m_Real.glTextureParameterfvEXT(GetResourceManager()->GetLiveResource(id).name, Target, PName, Params); } delete[] Params; return true; }
void WrappedOpenGL::glTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) { m_Real.glTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); RDCASSERT(record); SCOPED_SERIALISE_CONTEXT(TEXSUBIMAGE2D); Serialise_glTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels); if(m_State == WRITING_CAPFRAME) m_ContextRecord->AddChunk(scope.Get()); else record->AddChunk(scope.Get()); } }
void WrappedOpenGL::glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { m_Real.glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); RDCASSERT(record); SCOPED_SERIALISE_CONTEXT(TEXSTORAGE3D); Serialise_glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth); if(m_State == WRITING_CAPFRAME) m_ContextRecord->AddChunk(scope.Get()); else record->AddChunk(scope.Get()); } }
void WrappedOpenGL::glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params) { m_Real.glTextureParameterfvEXT(texture, target, pname, params); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); RDCASSERT(record); SCOPED_SERIALISE_CONTEXT(TEXPARAMETERFV); Serialise_glTextureParameterfvEXT(texture, target, pname, params); if(m_State == WRITING_IDLE) record->AddChunk(scope.Get()); else m_ContextRecord->AddChunk(scope.Get()); } }
bool WrappedOpenGL::Serialise_glTextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(uint32_t, Levels, levels); SERIALISE_ELEMENT(GLenum, Format, internalformat); SERIALISE_ELEMENT(uint32_t, Width, width); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(TextureRes(texture))); if(m_State == READING) { ResourceId liveId = GetResourceManager()->GetLiveID(id); m_Textures[liveId].width = Width; m_Textures[liveId].height = 1; m_Textures[liveId].depth = 1; m_Real.glTextureStorage1DEXT(GetResourceManager()->GetLiveResource(id).name, Target, Levels, Format, Width); } return true; }
void WrappedOpenGL::glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { m_Real.glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(GetCtx(), texture)); RDCASSERT(record); SCOPED_SERIALISE_CONTEXT(TEXSTORAGE3D); Serialise_glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth); record->AddChunk(scope.Get()); // illegal to re-type textures if(record->datatype == eGL_UNKNOWN_ENUM) record->datatype = target; else RDCASSERT(record->datatype == target); } }
void WrappedOpenGL::glGenerateTextureMipmapEXT(GLuint texture, GLenum target) { m_Real.glGenerateTextureMipmapEXT(texture, target); if(m_State == WRITING_CAPFRAME) { SCOPED_SERIALISE_CONTEXT(GENERATE_MIPMAP); Serialise_glGenerateTextureMipmapEXT(texture, target); m_ContextRecord->AddChunk(scope.Get()); } else if(m_State == WRITING_IDLE) { SCOPED_SERIALISE_CONTEXT(GENERATE_MIPMAP); Serialise_glGenerateTextureMipmapEXT(texture, target); ResourceRecord *record = GetResourceManager()->GetResourceRecord(TextureRes(texture)); RDCASSERT(record); if(record) record->AddChunk(scope.Get()); } }
ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) { WrappedOpenGL &gl = *m_pDriver; MakeCurrentReplayContext(&m_ReplayCtx); GLuint curProg = 0; gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg); GLuint curDrawFBO = 0; GLuint curReadFBO = 0; gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curDrawFBO); gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curReadFBO); auto &progDetails = m_pDriver->m_Programs[m_pDriver->GetResourceManager()->GetID(ProgramRes(curProg))]; if(progDetails.colOutProg == 0) { progDetails.colOutProg = gl.glCreateProgram(); GLuint shad = gl.glCreateShader(eGL_FRAGMENT_SHADER); const char *src = DebugData.genericfsSource.c_str(); gl.glShaderSource(shad, 1, &src, NULL); gl.glCompileShader(shad); gl.glAttachShader(progDetails.colOutProg, shad); gl.glDeleteShader(shad); for(size_t i=0; i < progDetails.shaders.size(); i++) { const auto &shadDetails = m_pDriver->m_Shaders[progDetails.shaders[i]]; if(shadDetails.type != eGL_FRAGMENT_SHADER) { shad = gl.glCreateShader(shadDetails.type); for(size_t s=0; s < shadDetails.sources.size(); s++) { src = shadDetails.sources[s].c_str(); gl.glShaderSource(shad, 1, &src, NULL); } gl.glCompileShader(shad); gl.glAttachShader(progDetails.colOutProg, shad); gl.glDeleteShader(shad); } } gl.glLinkProgram(progDetails.colOutProg); } auto &texDetails = m_pDriver->m_Textures[texid]; if(DebugData.overlayTexWidth != texDetails.width || DebugData.overlayTexHeight != texDetails.height) { if(DebugData.overlayFBO) { gl.glDeleteFramebuffers(1, &DebugData.overlayFBO); gl.glDeleteTextures(1, &DebugData.overlayTex); } gl.glGenFramebuffers(1, &DebugData.overlayFBO); gl.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.overlayFBO); GLuint curTex = 0; gl.glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint*)&curTex); gl.glGenTextures(1, &DebugData.overlayTex); gl.glBindTexture(eGL_TEXTURE_2D, DebugData.overlayTex); DebugData.overlayTexWidth = texDetails.width; DebugData.overlayTexHeight = texDetails.height; gl.glTexStorage2D(eGL_TEXTURE_2D, 1, eGL_RGBA8, texDetails.width, texDetails.height); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE); gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, DebugData.overlayTex, 0); gl.glBindTexture(eGL_TEXTURE_2D, curTex); } gl.glBindFramebuffer(eGL_FRAMEBUFFER, DebugData.overlayFBO); if(overlay == eTexOverlay_NaN || overlay == eTexOverlay_Clipping) { // just need the basic texture float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; gl.glClearBufferfv(eGL_COLOR, 0, black); } else if(overlay == eTexOverlay_Drawcall) { gl.glUseProgram(progDetails.colOutProg); { // copy across uniforms GLint numUniforms = 0; gl.glGetProgramiv(curProg, eGL_ACTIVE_UNIFORMS, &numUniforms); for(GLint i=0; i < numUniforms; i++) { char uniName[1024] = {}; GLint uniSize = 0; GLenum uniType = eGL_UNKNOWN_ENUM; gl.glGetActiveUniform(curProg, i, 1024, NULL, &uniSize, &uniType, uniName); GLint origloc = gl.glGetUniformLocation(curProg, uniName); GLint newloc = gl.glGetUniformLocation(progDetails.colOutProg, uniName); double dv[16]; float *fv = (float *)dv; if(uniSize > 1) { RDCERR("Array elements beyond [0] not being copied to new program"); } if(origloc != -1 && newloc != -1) { if(uniType == eGL_FLOAT_MAT4) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniformMatrix4fv(newloc, 1, false, fv); } else if(uniType == eGL_FLOAT_VEC3) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniform3fv(newloc, 1, fv); } else if(uniType == eGL_FLOAT_VEC4) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniform4fv(newloc, 1, fv); } else { RDCERR("Uniform type '%s' not being copied to new program", ToStr::Get(uniType).c_str()); } } } } float black[] = { 0.0f, 0.0f, 0.0f, 0.5f }; gl.glClearBufferfv(eGL_COLOR, 0, black); GLint colLoc = gl.glGetUniformLocation(progDetails.colOutProg, "RENDERDOC_GenericFS_Color"); float colVal[] = { 0.8f, 0.1f, 0.8f, 1.0f }; gl.glUniform4fv(colLoc, 1, colVal); ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw); gl.glUseProgram(curProg); } else if(overlay == eTexOverlay_Wireframe) { gl.glUseProgram(progDetails.colOutProg); { // copy across uniforms GLint numUniforms = 0; gl.glGetProgramiv(curProg, eGL_ACTIVE_UNIFORMS, &numUniforms); for(GLint i=0; i < numUniforms; i++) { char uniName[1024] = {}; GLint uniSize = 0; GLenum uniType = eGL_UNKNOWN_ENUM; gl.glGetActiveUniform(curProg, i, 1024, NULL, &uniSize, &uniType, uniName); GLint origloc = gl.glGetUniformLocation(curProg, uniName); GLint newloc = gl.glGetUniformLocation(progDetails.colOutProg, uniName); double dv[16]; float *fv = (float *)dv; if(uniSize > 1) { RDCERR("Array elements beyond [0] not being copied to new program"); } if(origloc != -1 && newloc != -1) { if(uniType == eGL_FLOAT_MAT4) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniformMatrix4fv(newloc, 1, false, fv); } else if(uniType == eGL_FLOAT_VEC3) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniform3fv(newloc, 1, fv); } else if(uniType == eGL_FLOAT_VEC4) { gl.glGetUniformfv(curProg, origloc, fv); gl.glUniform4fv(newloc, 1, fv); } else { RDCERR("Uniform type '%s' not being copied to new program", ToStr::Get(uniType).c_str()); } } } } float wireCol[] = { 200.0f/255.0f, 255.0f/255.0f, 0.0f/255.0f, 0.0f }; gl.glClearBufferfv(eGL_COLOR, 0, wireCol); GLint colLoc = gl.glGetUniformLocation(progDetails.colOutProg, "RENDERDOC_GenericFS_Color"); wireCol[3] = 1.0f; gl.glUniform4fv(colLoc, 1, wireCol); GLint depthTest = GL_FALSE; gl.glGetIntegerv(eGL_DEPTH_TEST, (GLint*)&depthTest); GLenum polyMode = eGL_FILL; gl.glGetIntegerv(eGL_POLYGON_MODE, (GLint*)&polyMode); gl.glDisable(eGL_DEPTH_TEST); gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE); ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw); if(depthTest) gl.glEnable(eGL_DEPTH_TEST); if(polyMode != eGL_LINE) gl.glPolygonMode(eGL_FRONT_AND_BACK, polyMode); gl.glUseProgram(curProg); } gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, curDrawFBO); gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curReadFBO); return m_pDriver->GetResourceManager()->GetID(TextureRes(DebugData.overlayTex)); }
void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl) { GLResourceManager *rm = gl->GetResourceManager(); // TODO check GL_MAX_* m_pSerialiser->Serialise<eEnabled_Count>("GL_ENABLED", Enabled); for(size_t i=0; i < ARRAY_COUNT(Tex2D); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(TextureRes(ctx, Tex2D[i])); m_pSerialiser->Serialise("GL_TEXTURE_BINDING_2D", ID); if(state < WRITING && ID != ResourceId()) Tex2D[i] = rm->GetLiveResource(ID).name; } for(size_t i=0; i < ARRAY_COUNT(Samplers); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(SamplerRes(ctx, Samplers[i])); m_pSerialiser->Serialise("GL_SAMPLER_BINDING", ID); if(state < WRITING && ID != ResourceId()) Samplers[i] = rm->GetLiveResource(ID).name; } m_pSerialiser->Serialise("GL_ACTIVE_TEXTURE", ActiveTexture); { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(VertexArrayRes(ctx, VAO)); m_pSerialiser->Serialise("GL_VERTEX_ARRAY_BINDING", ID); if(state < WRITING && ID != ResourceId()) VAO = rm->GetLiveResource(ID).name; if(VAO == 0) VAO = gl->GetFakeVAO(); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FeedbackRes(ctx, FeedbackObj)); m_pSerialiser->Serialise("GL_TRANSFORM_FEEDBACK_BINDING", ID); if(state < WRITING && ID != ResourceId()) FeedbackObj = rm->GetLiveResource(ID).name; } for(size_t i=0; i < ARRAY_COUNT(GenericVertexAttribs); i++) { m_pSerialiser->Serialise<4>("GL_CURRENT_VERTEX_ATTRIB", &GenericVertexAttribs[i].x); } m_pSerialiser->Serialise("GL_POINT_FADE_THRESHOLD_SIZE", PointFadeThresholdSize); m_pSerialiser->Serialise("GL_POINT_SPRITE_COORD_ORIGIN", PointSpriteOrigin); m_pSerialiser->Serialise("GL_LINE_WIDTH", LineWidth); m_pSerialiser->Serialise("GL_POINT_SIZE", PointSize); m_pSerialiser->Serialise("GL_PRIMITIVE_RESTART_INDEX", PrimitiveRestartIndex); m_pSerialiser->Serialise("GL_CLIP_ORIGIN", ClipOrigin); m_pSerialiser->Serialise("GL_CLIP_DEPTH_MODE", ClipDepth); m_pSerialiser->Serialise("GL_PROVOKING_VERTEX", ProvokingVertex); for(size_t i=0; i < ARRAY_COUNT(BufferBindings); i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, BufferBindings[i])); m_pSerialiser->Serialise("GL_BUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) BufferBindings[i] = rm->GetLiveResource(ID).name; } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(ProgramRes(ctx, Program)); m_pSerialiser->Serialise("GL_CURRENT_PROGRAM", ID); if(state < WRITING && ID != ResourceId()) Program = rm->GetLiveResource(ID).name; } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(ProgramPipeRes(ctx, Pipeline)); m_pSerialiser->Serialise("GL_PROGRAM_PIPELINE_BINDING", ID); if(state < WRITING && ID != ResourceId()) Pipeline = rm->GetLiveResource(ID).name; } for(size_t s=0; s < ARRAY_COUNT(Subroutines); s++) { m_pSerialiser->Serialise("GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS", Subroutines[s].numSubroutines); m_pSerialiser->Serialise<128>("GL_SUBROUTINE_UNIFORMS", Subroutines[s].Values); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, DrawFBO)); m_pSerialiser->Serialise("GL_DRAW_FRAMEBUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) DrawFBO = rm->GetLiveResource(ID).name; if(DrawFBO == 0) DrawFBO = gl->GetFakeBBFBO(); } { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(FramebufferRes(ctx, ReadFBO)); m_pSerialiser->Serialise("GL_READ_FRAMEBUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) ReadFBO = rm->GetLiveResource(ID).name; if(ReadFBO == 0) ReadFBO = gl->GetFakeBBFBO(); } struct { IdxRangeBuffer *bufs; int count; } idxBufs[] = { { AtomicCounter, ARRAY_COUNT(AtomicCounter), }, { ShaderStorage, ARRAY_COUNT(ShaderStorage), }, { TransformFeedback, ARRAY_COUNT(TransformFeedback), }, { UniformBinding, ARRAY_COUNT(UniformBinding), }, }; for(size_t b=0; b < ARRAY_COUNT(idxBufs); b++) { for(int i=0; i < idxBufs[b].count; i++) { ResourceId ID = ResourceId(); if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, idxBufs[b].bufs[i].name)); m_pSerialiser->Serialise("BUFFER_BINDING", ID); if(state < WRITING && ID != ResourceId()) idxBufs[b].bufs[i].name = rm->GetLiveResource(ID).name; m_pSerialiser->Serialise("BUFFER_START", idxBufs[b].bufs[i].start); m_pSerialiser->Serialise("BUFFER_SIZE", idxBufs[b].bufs[i].size); } } for(size_t i=0; i < ARRAY_COUNT(Blends); i++) { m_pSerialiser->Serialise("GL_BLEND_EQUATION_RGB", Blends[i].EquationRGB); m_pSerialiser->Serialise("GL_BLEND_EQUATION_ALPHA", Blends[i].EquationAlpha); m_pSerialiser->Serialise("GL_BLEND_SRC_RGB", Blends[i].SourceRGB); m_pSerialiser->Serialise("GL_BLEND_SRC_ALPHA", Blends[i].SourceAlpha); m_pSerialiser->Serialise("GL_BLEND_DST_RGB", Blends[i].DestinationRGB); m_pSerialiser->Serialise("GL_BLEND_DST_ALPHA", Blends[i].DestinationAlpha); m_pSerialiser->Serialise("GL_BLEND", Blends[i].Enabled); } m_pSerialiser->Serialise<4>("GL_BLEND_COLOR", BlendColor); for(size_t i=0; i < ARRAY_COUNT(Viewports); i++) { m_pSerialiser->Serialise("GL_VIEWPORT.x", Viewports[i].x); m_pSerialiser->Serialise("GL_VIEWPORT.y", Viewports[i].y); m_pSerialiser->Serialise("GL_VIEWPORT.w", Viewports[i].width); m_pSerialiser->Serialise("GL_VIEWPORT.h", Viewports[i].height); } for(size_t i=0; i < ARRAY_COUNT(Scissors); i++) { m_pSerialiser->Serialise("GL_SCISSOR.x", Scissors[i].x); m_pSerialiser->Serialise("GL_SCISSOR.y", Scissors[i].y); m_pSerialiser->Serialise("GL_SCISSOR.w", Scissors[i].width); m_pSerialiser->Serialise("GL_SCISSOR.h", Scissors[i].height); m_pSerialiser->Serialise("GL_SCISSOR.enabled", Scissors[i].enabled); } m_pSerialiser->Serialise<8>("GL_DRAW_BUFFERS", DrawBuffers); m_pSerialiser->Serialise("GL_READ_BUFFER", ReadBuffer); m_pSerialiser->Serialise("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", Hints.Derivatives); m_pSerialiser->Serialise("GL_LINE_SMOOTH_HINT", Hints.LineSmooth); m_pSerialiser->Serialise("GL_POLYGON_SMOOTH_HINT", Hints.PolySmooth); m_pSerialiser->Serialise("GL_TEXTURE_COMPRESSION_HINT", Hints.TexCompression); m_pSerialiser->Serialise("GL_DEPTH_WRITEMASK", DepthWriteMask); m_pSerialiser->Serialise("GL_DEPTH_CLEAR_VALUE", DepthClearValue); m_pSerialiser->Serialise("GL_DEPTH_FUNC", DepthFunc); for(size_t i=0; i < ARRAY_COUNT(DepthRanges); i++) { m_pSerialiser->Serialise("GL_DEPTH_RANGE.near", DepthRanges[i].nearZ); m_pSerialiser->Serialise("GL_DEPTH_RANGE.far", DepthRanges[i].farZ); } { m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.near", DepthBounds.nearZ); m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.far", DepthBounds.farZ); } { m_pSerialiser->Serialise("GL_STENCIL_FUNC", StencilFront.func); m_pSerialiser->Serialise("GL_STENCIL_BACK_FUNC", StencilBack.func); m_pSerialiser->Serialise("GL_STENCIL_REF", StencilFront.ref); m_pSerialiser->Serialise("GL_STENCIL_BACK_REF", StencilBack.ref); m_pSerialiser->Serialise("GL_STENCIL_VALUE_MASK", StencilFront.valuemask); m_pSerialiser->Serialise("GL_STENCIL_BACK_VALUE_MASK", StencilBack.valuemask); m_pSerialiser->Serialise("GL_STENCIL_WRITEMASK", StencilFront.writemask); m_pSerialiser->Serialise("GL_STENCIL_BACK_WRITEMASK", StencilBack.writemask); m_pSerialiser->Serialise("GL_STENCIL_FAIL", StencilFront.stencilFail); m_pSerialiser->Serialise("GL_STENCIL_BACK_FAIL", StencilBack.stencilFail); m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_FAIL", StencilFront.depthFail); m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_FAIL", StencilBack.depthFail); m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_PASS", StencilFront.pass); m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_PASS", StencilBack.pass); } m_pSerialiser->Serialise("GL_STENCIL_CLEAR_VALUE", StencilClearValue); for(size_t i=0; i < ARRAY_COUNT(ColorMasks); i++) m_pSerialiser->Serialise<4>("GL_COLOR_WRITEMASK", &ColorMasks[i].red); m_pSerialiser->Serialise<2>("GL_SAMPLE_MASK_VALUE", &SampleMask[0]); m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_VALUE", SampleCoverage); m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_INVERT", SampleCoverageInvert); m_pSerialiser->Serialise("GL_MIN_SAMPLE_SHADING", MinSampleShading); m_pSerialiser->Serialise("GL_RASTER_SAMPLES_EXT", RasterSamples); m_pSerialiser->Serialise("GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", RasterFixed); m_pSerialiser->Serialise("GL_LOGIC_OP_MODE", LogicOp); m_pSerialiser->Serialise<4>("GL_COLOR_CLEAR_VALUE", &ColorClearValue.red); { m_pSerialiser->Serialise("GL_PATCH_VERTICES", PatchParams.numVerts); m_pSerialiser->Serialise<2>("GL_PATCH_DEFAULT_INNER_LEVEL", &PatchParams.defaultInnerLevel[0]); m_pSerialiser->Serialise<4>("GL_PATCH_DEFAULT_OUTER_LEVEL", &PatchParams.defaultOuterLevel[0]); } m_pSerialiser->Serialise("GL_POLYGON_MODE", PolygonMode); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_FACTOR", PolygonOffset[0]); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_UNITS", PolygonOffset[1]); m_pSerialiser->Serialise("GL_POLYGON_OFFSET_CLAMP_EXT", PolygonOffset[2]); m_pSerialiser->Serialise("GL_FRONT_FACE", FrontFace); m_pSerialiser->Serialise("GL_CULL_FACE_MODE", CullFace); }
void GLReplay::SavePipelineState() { GLPipelineState &pipe = m_CurPipelineState; WrappedOpenGL &gl = *m_pDriver; GLResourceManager *rm = m_pDriver->GetResourceManager(); MakeCurrentReplayContext(&m_ReplayCtx); // Index buffer pipe.m_VtxIn.ibuffer.Offset = m_pDriver->m_LastIndexOffset; pipe.m_VtxIn.ibuffer.Format = ResourceFormat(); pipe.m_VtxIn.ibuffer.Format.special = false; pipe.m_VtxIn.ibuffer.Format.compCount = 1; pipe.m_VtxIn.ibuffer.Format.compType = eCompType_UInt; switch(m_pDriver->m_LastIndexSize) { default: break; case eGL_UNSIGNED_BYTE: pipe.m_VtxIn.ibuffer.Format.compByteWidth = 1; pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_BYTE"; break; case eGL_UNSIGNED_SHORT: pipe.m_VtxIn.ibuffer.Format.compByteWidth = 2; pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_SHORT"; break; case eGL_UNSIGNED_INT: pipe.m_VtxIn.ibuffer.Format.compByteWidth = 4; pipe.m_VtxIn.ibuffer.Format.strname = L"GL_UNSIGNED_INT"; break; } GLint curIdxBuf = 0; gl.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, &curIdxBuf); pipe.m_VtxIn.ibuffer.Buffer = rm->GetOriginalID(rm->GetID(BufferRes(curIdxBuf))); // Vertex buffers and attributes GLint numVBufferBindings = 16; gl.glGetIntegerv(eGL_MAX_VERTEX_ATTRIB_BINDINGS, &numVBufferBindings); GLint numVAttribBindings = 16; gl.glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, &numVAttribBindings); create_array_uninit(pipe.m_VtxIn.vbuffers, numVBufferBindings); create_array_uninit(pipe.m_VtxIn.attributes, numVAttribBindings); for(GLuint i=0; i < (GLuint)numVBufferBindings; i++) { GLint vb = 0; gl.glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, i, &vb); pipe.m_VtxIn.vbuffers[i].Buffer = rm->GetOriginalID(rm->GetID(BufferRes(vb))); gl.glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Stride); gl.glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Offset); gl.glGetIntegeri_v(eGL_VERTEX_BINDING_DIVISOR, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Divisor); pipe.m_VtxIn.vbuffers[i].PerInstance = (pipe.m_VtxIn.vbuffers[i].Divisor != 0); } for(GLuint i=0; i < (GLuint)numVAttribBindings; i++) { gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&pipe.m_VtxIn.attributes[i].Enabled); gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&pipe.m_VtxIn.attributes[i].BufferSlot); gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&pipe.m_VtxIn.attributes[i].RelativeOffset); GLenum type = eGL_FLOAT; GLint normalized = 0; gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&type); gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized); ResourceFormat fmt; fmt.special = false; fmt.compCount = 4; gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&fmt.compCount); switch(type) { default: case eGL_BYTE: fmt.compByteWidth = 1; fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm; fmt.strname = StringFormat::WFmt(L"GL_BYTE%d", fmt.compCount) + (normalized ? L"" : L"_SNORM"); break; case eGL_UNSIGNED_BYTE: fmt.compByteWidth = 1; fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm; fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_BYTE%d", fmt.compCount) + (normalized ? L"" : L"_UNORM"); break; case eGL_SHORT: fmt.compByteWidth = 2; fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm; fmt.strname = StringFormat::WFmt(L"GL_SHORT%d", fmt.compCount) + (normalized ? L"" : L"_SNORM"); break; case eGL_UNSIGNED_SHORT: fmt.compByteWidth = 2; fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm; fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_SHORT%d", fmt.compCount) + (normalized ? L"" : L"_UNORM"); break; case eGL_INT: fmt.compByteWidth = 4; fmt.compType = normalized ? eCompType_SInt : eCompType_SNorm; fmt.strname = StringFormat::WFmt(L"GL_INT%d", fmt.compCount) + (normalized ? L"" : L"_SNORM"); break; case eGL_UNSIGNED_INT: fmt.compByteWidth = 4; fmt.compType = normalized ? eCompType_UInt : eCompType_UNorm; fmt.strname = StringFormat::WFmt(L"GL_UNSIGNED_INT%d", fmt.compCount) + (normalized ? L"" : L"_UNORM"); break; case eGL_FLOAT: fmt.compByteWidth = 4; fmt.compType = eCompType_Float; fmt.strname = StringFormat::WFmt(L"GL_FLOAT%d", fmt.compCount); break; case eGL_DOUBLE: fmt.compByteWidth = 8; fmt.compType = eCompType_Double; fmt.strname = StringFormat::WFmt(L"GL_DOUBLE%d", fmt.compCount); break; case eGL_HALF_FLOAT: fmt.compByteWidth = 2; fmt.compType = eCompType_Float; fmt.strname = StringFormat::WFmt(L"GL_HALF_FLOAT%d", fmt.compCount); break; case eGL_INT_2_10_10_10_REV: fmt.special = true; fmt.specialFormat = eSpecial_R10G10B10A2; fmt.compCount = 4; fmt.compType = eCompType_UInt; fmt.strname = L"GL_INT_2_10_10_10_REV"; break; case eGL_UNSIGNED_INT_2_10_10_10_REV: fmt.special = true; fmt.specialFormat = eSpecial_R10G10B10A2; fmt.compCount = 4; fmt.compType = eCompType_SInt; fmt.strname = L"eGL_UNSIGNED_INT_2_10_10_10_REV"; break; case eGL_UNSIGNED_INT_10F_11F_11F_REV: fmt.special = true; fmt.specialFormat = eSpecial_R11G11B10; fmt.compCount = 3; fmt.compType = eCompType_SInt; fmt.strname = L"eGL_UNSIGNED_INT_10F_11F_11F_REV"; break; } pipe.m_VtxIn.attributes[i].Format = fmt; } switch(m_pDriver->m_LastDrawMode) { default: pipe.m_VtxIn.Topology = eTopology_Unknown; break; case GL_POINTS: pipe.m_VtxIn.Topology = eTopology_PointList; break; case GL_LINE_STRIP: pipe.m_VtxIn.Topology = eTopology_LineStrip; break; case GL_LINE_LOOP: pipe.m_VtxIn.Topology = eTopology_LineLoop; break; case GL_LINES: pipe.m_VtxIn.Topology = eTopology_LineList; break; case GL_LINE_STRIP_ADJACENCY: pipe.m_VtxIn.Topology = eTopology_LineStrip_Adj; break; case GL_LINES_ADJACENCY: pipe.m_VtxIn.Topology = eTopology_LineList_Adj; break; case GL_TRIANGLE_STRIP: pipe.m_VtxIn.Topology = eTopology_TriangleStrip; break; case GL_TRIANGLE_FAN: pipe.m_VtxIn.Topology = eTopology_TriangleFan; break; case GL_TRIANGLES: pipe.m_VtxIn.Topology = eTopology_TriangleList; break; case GL_TRIANGLE_STRIP_ADJACENCY: pipe.m_VtxIn.Topology = eTopology_TriangleStrip_Adj; break; case GL_TRIANGLES_ADJACENCY: pipe.m_VtxIn.Topology = eTopology_TriangleList_Adj; break; case GL_PATCHES: { GLint patchCount = 3; gl.glGetIntegerv(eGL_PATCH_VERTICES, &patchCount); pipe.m_VtxIn.Topology = PrimitiveTopology(eTopology_PatchList_1CPs+patchCount); break; } } // Shader stages GLuint curProg = 0; gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg); auto &progDetails = m_pDriver->m_Programs[rm->GetID(ProgramRes(curProg))]; RDCASSERT(progDetails.shaders.size()); for(size_t i=0; i < progDetails.shaders.size(); i++) { if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_VERTEX_SHADER) pipe.m_VS.Shader = rm->GetOriginalID(progDetails.shaders[i]); else if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_FRAGMENT_SHADER) pipe.m_FS.Shader = rm->GetOriginalID(progDetails.shaders[i]); } pipe.m_VS.stage = eShaderStage_Vertex; pipe.m_TCS.stage = eShaderStage_Tess_Control; pipe.m_TES.stage = eShaderStage_Tess_Eval; pipe.m_GS.stage = eShaderStage_Geometry; pipe.m_FS.stage = eShaderStage_Fragment; pipe.m_CS.stage = eShaderStage_Compute; // Textures GLint numTexUnits = 8; gl.glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numTexUnits); create_array_uninit(pipe.Textures, numTexUnits); GLenum activeTexture = eGL_TEXTURE0; gl.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint*)&activeTexture); // GL is ass-backwards in its handling of texture units. When a shader is active // the types in the glsl samplers inform which targets are used from which texture units // // So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77). // * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52 // * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77 // It's illegal for both a sampler2D and samplerCube to both have the same value (or any two // different types). It makes it all rather pointless and needlessly complex. // // What we have to do then, is consider the program, look at the values of the uniforms, and // then get the appropriate current binding based on the uniform type. We can warn/alert the // user if we hit the illegal case of two uniforms with different types but the same value // // Handling is different if no shaders are active, but we don't consider that case. // prefetch uniform values in GetShader() ShaderReflection *refls[6]; for(size_t s=0; s < progDetails.shaders.size(); s++) refls[s] = GetShader(progDetails.shaders[s]); for(GLint unit=0; unit < numTexUnits; unit++) { GLenum binding = eGL_UNKNOWN_ENUM; GLenum target = eGL_UNKNOWN_ENUM; for(size_t s=0; s < progDetails.shaders.size(); s++) { if(refls[s] == NULL) continue; for(int32_t r=0; r < refls[s]->Resources.count; r++) { // bindPoint is the uniform value for this sampler if(refls[s]->Resources[r].bindPoint == (uint32_t)unit) { GLenum t = eGL_UNKNOWN_ENUM; switch(refls[s]->Resources[r].resType) { case eResType_None: t = eGL_UNKNOWN_ENUM; break; case eResType_Buffer: t = eGL_TEXTURE_BINDING_BUFFER; break; case eResType_Texture1D: t = eGL_TEXTURE_BINDING_1D; target = eGL_TEXTURE_1D; break; case eResType_Texture1DArray: t = eGL_TEXTURE_BINDING_1D_ARRAY; target = eGL_TEXTURE_1D_ARRAY; break; case eResType_Texture2D: t = eGL_TEXTURE_BINDING_2D; target = eGL_TEXTURE_2D; break; case eResType_Texture2DArray: t = eGL_TEXTURE_BINDING_2D_ARRAY; target = eGL_TEXTURE_2D_ARRAY; break; case eResType_Texture2DMS: t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE; target = eGL_TEXTURE_2D_MULTISAMPLE; break; case eResType_Texture2DMSArray: t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; break; case eResType_Texture3D: t = eGL_TEXTURE_BINDING_3D; target = eGL_TEXTURE_3D; break; case eResType_TextureCube: t = eGL_TEXTURE_BINDING_CUBE_MAP; target = eGL_TEXTURE_CUBE_MAP; break; case eResType_TextureCubeArray: t = eGL_TEXTURE_BINDING_CUBE_MAP_ARRAY; target = eGL_TEXTURE_CUBE_MAP_ARRAY; break; } if(binding == eGL_UNKNOWN_ENUM) { binding = t; } else if(binding == t) { // two uniforms with the same type pointing to the same slot is fine binding = t; } else if(binding != t) { RDCWARN("Two uniforms pointing to texture unit %d with types %s and %s", unit, ToStr::Get(binding).c_str(), ToStr::Get(t).c_str()); } } } } if(binding != eGL_UNKNOWN_ENUM) { gl.glActiveTexture(GLenum(eGL_TEXTURE0+unit)); GLuint tex; gl.glGetIntegerv(binding, (GLint *)&tex); // very bespoke/specific GLint firstSlice = 0; gl.glGetTexParameteriv(target, eGL_TEXTURE_VIEW_MIN_LEVEL, &firstSlice); pipe.Textures[unit].Resource = rm->GetOriginalID(rm->GetID(TextureRes(tex))); pipe.Textures[unit].FirstSlice = (uint32_t)firstSlice; } else { // what should we do in this case? there could be something bound just not used, // it'd be nice to return that } } gl.glActiveTexture(activeTexture); GLuint curFBO = 0; gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&curFBO); GLint numCols = 8; gl.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols); GLuint curCol[32] = { 0 }; GLuint curDepth = 0; GLuint curStencil = 0; RDCASSERT(numCols <= 32); // we should never bind the true default framebuffer - if the app did, we will have our fake bound RDCASSERT(curFBO != 0); { for(GLint i=0; i < numCols; i++) gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0+i), eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curCol[i]); gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curDepth); gl.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)&curStencil); } pipe.m_FB.FBO = rm->GetOriginalID(rm->GetID(FramebufferRes(curFBO))); create_array_uninit(pipe.m_FB.Color, numCols); for(GLint i=0; i < numCols; i++) pipe.m_FB.Color[i] = rm->GetOriginalID(rm->GetID(TextureRes(curCol[i]))); pipe.m_FB.Depth = rm->GetOriginalID(rm->GetID(TextureRes(curDepth))); pipe.m_FB.Stencil = rm->GetOriginalID(rm->GetID(TextureRes(curStencil))); }
bool WrappedOpenGL::Serialise_glObjectLabel(SerialiserType &ser, GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { GLResource Resource; std::string Label; if(ser.IsWriting()) { // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that. GLsizei realLength = length; if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0) realLength = -1; // if length is negative (after above twiddling), it's taken from strlen and the label must be // NULL-terminated if(realLength < 0) realLength = label ? (GLsizei)strlen(label) : 0; if(realLength == 0 || label == NULL) Label = ""; else Label = std::string(label, label + realLength); switch(identifier) { case eGL_TEXTURE: Resource = TextureRes(GetCtx(), name); break; case eGL_BUFFER_OBJECT_EXT: case eGL_BUFFER: Resource = BufferRes(GetCtx(), name); break; case eGL_PROGRAM_OBJECT_EXT: case eGL_PROGRAM: Resource = ProgramRes(GetCtx(), name); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: case eGL_PROGRAM_PIPELINE: Resource = ProgramPipeRes(GetCtx(), name); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: case eGL_VERTEX_ARRAY: Resource = VertexArrayRes(GetCtx(), name); break; case eGL_SHADER_OBJECT_EXT: case eGL_SHADER: Resource = ShaderRes(GetCtx(), name); break; case eGL_QUERY_OBJECT_EXT: case eGL_QUERY: Resource = QueryRes(GetCtx(), name); break; case eGL_TRANSFORM_FEEDBACK: Resource = FeedbackRes(GetCtx(), name); break; case eGL_SAMPLER: Resource = SamplerRes(GetCtx(), name); break; case eGL_RENDERBUFFER: Resource = RenderbufferRes(GetCtx(), name); break; case eGL_FRAMEBUFFER: Resource = FramebufferRes(GetCtx(), name); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(Resource); SERIALISE_ELEMENT(length); SERIALISE_ELEMENT(Label); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading() && Resource.name) { ResourceId origId = GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(Resource)); GetResourceManager()->SetName(origId, Label); ResourceDescription &descr = GetReplay()->GetResourceDesc(origId); descr.SetCustomName(Label); AddResourceCurChunk(descr); } return true; }
bool WrappedOpenGL::Serialise_glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { ResourceId liveid; bool extvariant = false; string Label; if(m_State >= WRITING) { if(length == 0) Label = ""; else Label = string(label, label + (length > 0 ? length : strlen(label))); switch(identifier) { case eGL_TEXTURE: liveid = GetResourceManager()->GetID(TextureRes(GetCtx(), name)); break; case eGL_BUFFER_OBJECT_EXT: extvariant = true; case eGL_BUFFER: liveid = GetResourceManager()->GetID(BufferRes(GetCtx(), name)); break; case eGL_PROGRAM_OBJECT_EXT: extvariant = true; case eGL_PROGRAM: liveid = GetResourceManager()->GetID(ProgramRes(GetCtx(), name)); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: extvariant = true; case eGL_PROGRAM_PIPELINE: liveid = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), name)); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: extvariant = true; case eGL_VERTEX_ARRAY: liveid = GetResourceManager()->GetID(VertexArrayRes(GetCtx(), name)); break; case eGL_SHADER_OBJECT_EXT: extvariant = true; case eGL_SHADER: liveid = GetResourceManager()->GetID(ShaderRes(GetCtx(), name)); break; case eGL_QUERY_OBJECT_EXT: extvariant = true; case eGL_QUERY: liveid = GetResourceManager()->GetID(QueryRes(GetCtx(), name)); break; case eGL_TRANSFORM_FEEDBACK: liveid = GetResourceManager()->GetID(FeedbackRes(GetCtx(), name)); break; case eGL_SAMPLER: liveid = GetResourceManager()->GetID(SamplerRes(GetCtx(), name)); break; case eGL_RENDERBUFFER: liveid = GetResourceManager()->GetID(RenderbufferRes(GetCtx(), name)); break; case eGL_FRAMEBUFFER: liveid = GetResourceManager()->GetID(FramebufferRes(GetCtx(), name)); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(GLenum, Identifier, identifier); SERIALISE_ELEMENT(ResourceId, id, liveid); SERIALISE_ELEMENT(uint32_t, Length, length); SERIALISE_ELEMENT(bool, HasLabel, label != NULL); m_pSerialiser->SerialiseString("label", Label); if(m_State == READING && GetResourceManager()->HasLiveResource(id)) { GLResource res = GetResourceManager()->GetLiveResource(id); if(extvariant && m_Real.glLabelObjectEXT) m_Real.glLabelObjectEXT(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); else m_Real.glObjectLabel(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); } return true; }
HANDLE WrappedOpenGL::wglDXRegisterObjectNV(HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access) { RDCASSERT(IsCaptureMode(m_State)); ID3D11Resource *real = UnwrapDXResource(dxObject); if(real == NULL) { SetLastError(ERROR_OPEN_FAILED); return 0; } WrappedHANDLE *wrapped = new WrappedHANDLE(); if(type == eGL_RENDERBUFFER) wrapped->res = RenderbufferRes(GetCtx(), name); else if(type == eGL_NONE) wrapped->res = BufferRes(GetCtx(), name); else wrapped->res = TextureRes(GetCtx(), name); GLResourceRecord *record = GetResourceManager()->GetResourceRecord(wrapped->res); if(!record) { RDCERR("Unrecognised object with type %x and name %u", type, name); delete wrapped; return NULL; } SERIALISE_TIME_CALL(wrapped->real = m_Real.wglDXRegisterObjectNV(hDevice, real, name, type, access)); { RDCASSERT(record); USE_SCRATCH_SERIALISER(); SCOPED_SERIALISE_CHUNK(gl_CurChunk); Serialise_wglDXRegisterObjectNV(ser, wrapped->res, type, dxObject); record->AddChunk(scope.Get()); } if(type != eGL_NONE) { ResourceFormat fmt; uint32_t width = 0, height = 0, depth = 0, mips = 0, layers = 0, samples = 0; GetDXTextureProperties(dxObject, fmt, width, height, depth, mips, layers, samples); // defined as arrays mostly for Coverity code analysis to stay calm about passing // them to the *TexParameter* functions GLint maxlevel[4] = {GLint(mips - 1), 0, 0, 0}; m_Real.glTextureParameteriEXT(wrapped->res.name, type, eGL_TEXTURE_MAX_LEVEL, GLint(mips - 1)); ResourceId texId = record->GetResourceID(); m_Textures[texId].resource = wrapped->res; m_Textures[texId].curType = type; m_Textures[texId].width = width; m_Textures[texId].height = height; m_Textures[texId].depth = RDCMAX(depth, samples); m_Textures[texId].samples = samples; m_Textures[texId].dimension = 2; if(type == eGL_TEXTURE_1D || type == eGL_TEXTURE_1D_ARRAY) m_Textures[texId].dimension = 1; else if(type == eGL_TEXTURE_3D) m_Textures[texId].dimension = 3; m_Textures[texId].internalFormat = MakeGLFormat(fmt); } return wrapped; }