From 932995da56a276a144b5aee4a41ec9cd870029c3 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 1 Jun 2014 10:01:10 +0100 Subject: [PATCH] First attempt to implement Map/Unmap --- renderdoc/driver/gl/gl_common.h | 1 + renderdoc/driver/gl/gl_device_driver.cpp | 210 ++++++++++++++++++++++- renderdoc/driver/gl/gl_driver.cpp | 4 + renderdoc/driver/gl/gl_hookset.h | 4 +- renderdoc/driver/gl/gl_hookset_defs.h | 16 +- renderdoc/driver/gl/gl_resources.h | 21 ++- 6 files changed, 242 insertions(+), 14 deletions(-) diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index ca59edf2e..935d9983c 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -177,6 +177,7 @@ enum GLChunkType BIND_BUFFER_BASE, BIND_BUFFER_RANGE, BUFFERDATA, + UNMAP, GEN_VERTEXARRAY, BIND_VERTEXARRAY, VERTEXATTRIBPOINTER, diff --git a/renderdoc/driver/gl/gl_device_driver.cpp b/renderdoc/driver/gl/gl_device_driver.cpp index 866a1d50a..290fe94fc 100644 --- a/renderdoc/driver/gl/gl_device_driver.cpp +++ b/renderdoc/driver/gl/gl_device_driver.cpp @@ -1621,7 +1621,19 @@ bool WrappedOpenGL::Serialise_glBufferData(GLenum target, GLsizeiptr size, const { SERIALISE_ELEMENT(GLenum, Target, target); SERIALISE_ELEMENT(uint64_t, Bytesize, (uint64_t)size); + + byte *dummy = NULL; + + if(m_State >= WRITING && data == NULL) + { + dummy = new byte[size]; + data = dummy; + } + SERIALISE_ELEMENT_BUF(byte *, bytes, data, (size_t)Bytesize); + + uint64_t offs = m_pSerialiser->GetOffset(); + SERIALISE_ELEMENT(GLenum, Usage, usage); SERIALISE_ELEMENT(ResourceId, id, m_BufferRecord[BufferIdx(target)]->GetResourceID()); @@ -1635,6 +1647,13 @@ bool WrappedOpenGL::Serialise_glBufferData(GLenum target, GLsizeiptr size, const SAFE_DELETE_ARRAY(bytes); } + else if(m_State >= WRITING) + { + m_BufferRecord[BufferIdx(target)]->SetDataOffset(offs - Bytesize); + } + + if(dummy) + delete[] dummy; return true; } @@ -1652,7 +1671,11 @@ void WrappedOpenGL::glBufferData(GLenum target, GLsizeiptr size, const void *dat SCOPED_SERIALISE_CONTEXT(BUFFERDATA); Serialise_glBufferData(target, size, data, usage); - m_BufferRecord[idx]->AddChunk(scope.Get()); + Chunk *chunk = scope.Get(); + + m_BufferRecord[idx]->AddChunk(chunk); + m_BufferRecord[idx]->SetDataPtr(chunk->GetData()); + m_BufferRecord[idx]->Length = size; } } @@ -1718,17 +1741,198 @@ void *WrappedOpenGL::glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr { if(m_State >= WRITING) { - RDCUNIMPLEMENTED(); + // haven't implemented non-invalidating write maps + if((access & (GL_MAP_INVALIDATE_BUFFER_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_READ_BIT)) == 0) + RDCUNIMPLEMENTED(); + + // haven't implemented coherent/persistent bits + if((access & (GL_MAP_COHERENT_BIT|GL_MAP_PERSISTENT_BIT)) != 0) + RDCUNIMPLEMENTED(); + + m_BufferRecord[BufferIdx(target)]->Map.offset = offset; + m_BufferRecord[BufferIdx(target)]->Map.length = length; + m_BufferRecord[BufferIdx(target)]->Map.access = access; + + if((access & GL_MAP_READ_BIT) != 0) + { + byte *ptr = m_BufferRecord[BufferIdx(target)]->GetDataPtr(); + + if(ptr == NULL) + { + RDCWARN("Mapping buffer that hasn't been allocated"); + + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Mapped_Read_Real; + return m_Real.glMapBufferRange(target, offset, length, access); + } + + ptr += offset; + + m_Real.glGetBufferSubData(target, offset, length, ptr); + + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Mapped_Read; + + return ptr; + } + + byte *ptr = m_BufferRecord[BufferIdx(target)]->GetDataPtr(); + + if(ptr == NULL) + { + RDCWARN("Mapping buffer that hasn't been allocated"); + + ptr = (byte *)m_Real.glMapBufferRange(target, offset, length, access); + + m_BufferRecord[BufferIdx(target)]->Map.ptr = ptr; + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Mapped_Write_Real; + } + else + { + if(m_State == WRITING_CAPFRAME) + { + ptr = new byte[length]; + + m_BufferRecord[BufferIdx(target)]->Map.ptr = ptr; + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Mapped_Write_Alloc; + } + else + { + ptr += offset; + + m_BufferRecord[BufferIdx(target)]->Map.ptr = ptr; + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Mapped_Write; + } + } + + return ptr; } return m_Real.glMapBufferRange(target, offset, length, access); } +bool WrappedOpenGL::Serialise_glUnmapBuffer(GLenum target) +{ + GLResourceRecord *record = NULL; + + if(m_State >= WRITING) + record = m_BufferRecord[BufferIdx(target)]; + + SERIALISE_ELEMENT(GLenum, Target, target); + SERIALISE_ELEMENT(ResourceId, bufID, record->GetResourceID()); + SERIALISE_ELEMENT(uint64_t, offs, record->Map.offset); + SERIALISE_ELEMENT(uint64_t, len, record->Map.length); + + uint64_t bufBindStart = 0; + + if(m_State >= WRITING) + { + if(Target == eGL_ATOMIC_COUNTER_BUFFER) + m_Real.glGetInteger64i_v(eGL_ATOMIC_COUNTER_BUFFER_START, 0, (GLint64 *)&bufBindStart); + if(Target == eGL_SHADER_STORAGE_BUFFER) + m_Real.glGetInteger64i_v(eGL_SHADER_STORAGE_BUFFER_START, 0, (GLint64 *)&bufBindStart); + if(Target == eGL_TRANSFORM_FEEDBACK_BUFFER) + m_Real.glGetInteger64i_v(eGL_TRANSFORM_FEEDBACK_BUFFER_START, 0, (GLint64 *)&bufBindStart); + if(Target == eGL_UNIFORM_BUFFER) + m_Real.glGetInteger64i_v(eGL_UNIFORM_BUFFER_START, 0, (GLint64 *)&bufBindStart); + } + + SERIALISE_ELEMENT(uint64_t, bufOffs, bufBindStart); + + SERIALISE_ELEMENT_BUF(byte *, data, record->Map.ptr, (size_t)len); + + if(m_State < WRITING || + (m_State >= WRITING && + (record->Map.status == GLResourceRecord::Mapped_Write || record->Map.status == GLResourceRecord::Mapped_Write_Alloc) + ) + ) + { + GLuint oldBuf = 0; + GLuint64 oldBufBase = 0; + GLuint64 oldBufSize = 0; + + if(m_State == READING) + { + GLResource res = GetResourceManager()->GetLiveResource(bufID); + m_Real.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 0, (GLint *)&oldBuf); + m_Real.glGetInteger64i_v(eGL_UNIFORM_BUFFER_START, 0, (GLint64 *)&oldBufBase); + m_Real.glGetInteger64i_v(eGL_UNIFORM_BUFFER_SIZE, 0, (GLint64 *)&oldBufSize); + m_Real.glBindBufferRange(eGL_UNIFORM_BUFFER, 0, res.name, (GLintptr)bufOffs, (GLsizeiptr)len); + } + + void *ptr = m_Real.glMapBufferRange(Target, (GLintptr)offs, (GLsizeiptr)len, GL_MAP_WRITE_BIT); + memcpy(ptr, data, (size_t)len); + m_Real.glUnmapBuffer(Target); + + if(m_State == READING) + { + m_Real.glBindBufferRange(eGL_UNIFORM_BUFFER, 0, oldBuf, (GLintptr)oldBufBase, (GLsizeiptr)oldBufSize); + } + } + + if(m_State < WRITING) + delete[] data; + + return true; +} + GLboolean WrappedOpenGL::glUnmapBuffer(GLenum target) { if(m_State >= WRITING) { - RDCUNIMPLEMENTED(); + RDCASSERT(m_BufferRecord[BufferIdx(target)]); + + auto status = m_BufferRecord[BufferIdx(target)]->Map.status; + + GLboolean ret = GL_TRUE; + + switch(status) + { + case GLResourceRecord::Unmapped: + RDCERR("Unmapped buffer being passed to glUnmapBuffer"); + break; + case GLResourceRecord::Mapped_Read: + // can ignore + break; + case GLResourceRecord::Mapped_Read_Real: + // need to do real unmap + ret = m_Real.glUnmapBuffer(target); + break; + case GLResourceRecord::Mapped_Write: + { + if(m_State == WRITING_CAPFRAME) + RDCWARN("Failed to cap frame - uncapped Map/Unmap"); + + SCOPED_SERIALISE_CONTEXT(UNMAP); + Serialise_glUnmapBuffer(target); + + if(m_State == WRITING_CAPFRAME) + m_ContextRecord->AddChunk(scope.Get()); + else + m_BufferRecord[BufferIdx(target)]->AddChunk(scope.Get()); + + break; + } + case GLResourceRecord::Mapped_Write_Alloc: + { + SCOPED_SERIALISE_CONTEXT(UNMAP); + Serialise_glUnmapBuffer(target); + + if(m_State == WRITING_CAPFRAME) + m_ContextRecord->AddChunk(scope.Get()); + + delete[] m_BufferRecord[BufferIdx(target)]->Map.ptr; + + break; + } + case GLResourceRecord::Mapped_Write_Real: + RDCWARN("Throwing away map contents as we don't have datastore allocated"); + RDCWARN("Could init chunk here using known data (although maybe it's only partial)"); + ret = m_Real.glUnmapBuffer(target); + break; + } + + m_BufferRecord[BufferIdx(target)]->Map.status = GLResourceRecord::Unmapped; + + return ret; } return m_Real.glUnmapBuffer(target); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 35084bafa..1b1797bdb 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -134,6 +134,7 @@ const char *GLChunkNames[] = "glBindBufferBase", "glBindBufferRange", "glBufferData", + "glUnmapBuffer", "glGenVertexArrays", "glBindVertexArray", "glVertexAttribPointer", @@ -1156,6 +1157,9 @@ void WrappedOpenGL::ProcessChunk(uint64_t offset, GLChunkType context) case BUFFERDATA: Serialise_glBufferData(eGL_UNKNOWN_ENUM, 0, NULL, eGL_UNKNOWN_ENUM); break; + case UNMAP: + Serialise_glUnmapBuffer(eGL_UNKNOWN_ENUM); + break; case GEN_VERTEXARRAY: Serialise_glGenVertexArrays(0, NULL); break; diff --git a/renderdoc/driver/gl/gl_hookset.h b/renderdoc/driver/gl/gl_hookset.h index 08cb24560..f683c9e0f 100644 --- a/renderdoc/driver/gl/gl_hookset.h +++ b/renderdoc/driver/gl/gl_hookset.h @@ -33,13 +33,13 @@ struct GLHookSet // ++ dllexport PFNGLBINDTEXTUREPROC glBindTexture; PFNGLBLENDFUNCPROC glBlendFunc; - PFNGLBLENDCOLORPROC glBlendColor; PFNGLCLEARPROC glClear; PFNGLCLEARCOLORPROC glClearColor; PFNGLCLEARDEPTHPROC glClearDepth; PFNGLCOLORMASKPROC glColorMask; PFNGLCULLFACEPROC glCullFace; PFNGLDEPTHFUNCPROC glDepthFunc; + PFNGLDEPTHMASKPROC glDepthMask; PFNGLDISABLEPROC glDisable; PFNGLDRAWARRAYSPROC glDrawArrays; PFNGLENABLEPROC glEnable; @@ -105,13 +105,13 @@ struct GLHookSet PFNGLGETFLOATI_VPROC glGetFloati_v; PFNGLGETINTEGER64I_VPROC glGetInteger64i_v; PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; + PFNGLBLENDCOLORPROC glBlendColor; PFNGLBLENDFUNCIPROC glBlendFunci; PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei; PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate; PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei; PFNGLCOLORMASKIPROC glColorMaski; - PFNGLDEPTHMASKPROC glDepthMask; PFNGLDEPTHRANGEARRAYVPROC glDepthRangeArrayv; PFNGLCREATESHADERPROC glCreateShader; PFNGLDELETESHADERPROC glDeleteShader; diff --git a/renderdoc/driver/gl/gl_hookset_defs.h b/renderdoc/driver/gl/gl_hookset_defs.h index 47882a700..5b359fa0f 100644 --- a/renderdoc/driver/gl/gl_hookset_defs.h +++ b/renderdoc/driver/gl/gl_hookset_defs.h @@ -33,13 +33,13 @@ #define DLLExportHooks() \ HookInit(glBindTexture); \ HookInit(glBlendFunc); \ - HookInit(glBlendColor); \ HookInit(glClear); \ HookInit(glClearColor); \ HookInit(glClearDepth); \ HookInit(glColorMask); \ HookInit(glCullFace); \ HookInit(glDepthFunc); \ + HookInit(glDepthMask); \ HookInit(glDisable); \ HookInit(glDrawArrays); \ HookInit(glEnable); \ @@ -116,13 +116,13 @@ HookExtension(PFNGLGETFLOATI_VPROC, glGetFloati_v); \ HookExtension(PFNGLGETINTEGER64I_VPROC, glGetInteger64i_v); \ HookExtension(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus); \ + HookExtension(PFNGLBLENDCOLORPROC, glBlendColor); \ HookExtension(PFNGLBLENDFUNCIPROC, glBlendFunci); \ HookExtension(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); \ HookExtension(PFNGLBLENDFUNCSEPARATEIPROC, glBlendFuncSeparatei); \ HookExtension(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); \ HookExtension(PFNGLBLENDEQUATIONSEPARATEIPROC, glBlendEquationSeparatei); \ HookExtension(PFNGLCOLORMASKIPROC, glColorMaski); \ - HookExtension(PFNGLDEPTHMASKPROC, glDepthMask); \ HookExtension(PFNGLDEPTHRANGEARRAYVPROC, glDepthRangeArrayv); \ HookExtension(PFNGLCREATESHADERPROC, glCreateShader); \ HookExtension(PFNGLDELETESHADERPROC, glDeleteShader); \ @@ -210,13 +210,13 @@ HookExtension(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); \ HookExtension(PFNGLBINDTEXTUREPROC, glBindTexture); \ HookExtension(PFNGLBLENDFUNCPROC, glBlendFunc); \ - HookExtension(PFNGLBLENDCOLORPROC, glBlendColor); \ HookExtension(PFNGLCLEARPROC, glClear); \ HookExtension(PFNGLCLEARCOLORPROC, glClearColor); \ HookExtension(PFNGLCLEARDEPTHPROC, glClearDepth); \ HookExtension(PFNGLCOLORMASKPROC, glColorMask); \ HookExtension(PFNGLCULLFACEPROC, glCullFace); \ HookExtension(PFNGLDEPTHFUNCPROC, glDepthFunc); \ + HookExtension(PFNGLDEPTHMASKPROC, glDepthMask); \ HookExtension(PFNGLDISABLEPROC, glDisable); \ HookExtension(PFNGLDRAWARRAYSPROC, glDrawArrays); \ HookExtension(PFNGLENABLEPROC, glEnable); \ @@ -272,13 +272,13 @@ #define DefineDLLExportHooks() \ HookWrapper2(void, glBindTexture, GLenum, target, GLuint, texture); \ HookWrapper2(void, glBlendFunc, GLenum, sfactor, GLenum, dfactor); \ - HookWrapper4(void, glBlendColor, GLfloat, red, GLfloat, green, GLfloat, blue, GLfloat, alpha); \ HookWrapper1(void, glClear, GLbitfield, mask); \ HookWrapper4(void, glClearColor, GLfloat, red, GLfloat, green, GLfloat, blue, GLfloat, alpha); \ HookWrapper1(void, glClearDepth, GLdouble, depth); \ HookWrapper4(void, glColorMask, GLboolean, red, GLboolean, green, GLboolean, blue, GLboolean, alpha); \ HookWrapper1(void, glCullFace, GLenum, mode); \ HookWrapper1(void, glDepthFunc, GLenum, func); \ + HookWrapper1(void, glDepthMask, GLboolean, flag); \ HookWrapper1(void, glDisable, GLenum, cap); \ HookWrapper3(void, glDrawArrays, GLenum, mode, GLint, first, GLsizei, count); \ HookWrapper1(void, glEnable, GLenum, cap); \ @@ -355,13 +355,13 @@ HookWrapper3(void, glGetFloati_v, GLenum, target, GLuint, index, GLfloat *, data); \ HookWrapper3(void, glGetInteger64i_v, GLenum, target, GLuint, index, GLint64 *, data); \ HookWrapper1(GLenum, glCheckFramebufferStatus, GLenum, target); \ + HookWrapper4(void, glBlendColor, GLfloat, red, GLfloat, green, GLfloat, blue, GLfloat, alpha); \ HookWrapper3(void, glBlendFunci, GLuint, buf, GLenum, src, GLenum, dst); \ HookWrapper4(void, glBlendFuncSeparate, GLenum, sfactorRGB, GLenum, dfactorRGB, GLenum, sfactorAlpha, GLenum, dfactorAlpha); \ HookWrapper5(void, glBlendFuncSeparatei, GLuint, buf, GLenum, srcRGB, GLenum, dstRGB, GLenum, srcAlpha, GLenum, dstAlpha); \ HookWrapper2(void, glBlendEquationSeparate, GLenum, modeRGB, GLenum, modeAlpha); \ HookWrapper3(void, glBlendEquationSeparatei, GLuint, buf, GLenum, modeRGB, GLenum, modeAlpha); \ HookWrapper5(void, glColorMaski, GLuint, index, GLboolean, r, GLboolean, g, GLboolean, b, GLboolean, a); \ - HookWrapper1(void, glDepthMask, GLboolean, flag); \ HookWrapper3(void, glDepthRangeArrayv, GLuint, first, GLsizei, count, const GLdouble *, v); \ HookWrapper1(GLuint, glCreateShader, GLenum, type); \ HookWrapper1(void, glDeleteShader, GLuint, shader); \ @@ -435,9 +435,9 @@ HookWrapper3(void, glGetUniformfv, GLuint, program, GLint, location, GLfloat *, params); \ HookWrapper3(void, glGetUniformiv, GLuint, program, GLint, location, GLint *, params); \ HookWrapper4(void, glUniformMatrix4fv, GLint, location, GLsizei, count, GLboolean, transpose, const GLfloat *, value); \ - HookWrapper2(void, glUniform1f, GLint, location, GLfloat, value); \ - HookWrapper2(void, glUniform1i, GLint, location, GLint, value); \ - HookWrapper2(void, glUniform1ui, GLint, location, GLuint, value); \ + HookWrapper2(void, glUniform1f, GLint, location, GLfloat, v0); \ + HookWrapper2(void, glUniform1i, GLint, location, GLint, v0); \ + HookWrapper2(void, glUniform1ui, GLint, location, GLuint, v0); \ HookWrapper3(void, glUniform1fv, GLint, location, GLsizei, count, const GLfloat *, value); \ HookWrapper3(void, glUniform1iv, GLint, location, GLsizei, count, const GLint *, value); \ HookWrapper3(void, glUniform1uiv, GLint, location, GLsizei, count, const GLuint *, value); \ diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index 83be9b5b9..67fc76e6e 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -92,11 +92,30 @@ struct GLResourceRecord : public ResourceRecord static const NullInitialiser NullResource = MakeNullResource; GLResourceRecord(ResourceId id) : - ResourceRecord(id, true), + ResourceRecord(id, true), datatype(eGL_UNKNOWN_ENUM) { } + enum MapStatus + { + Unmapped, + Mapped_Read, + Mapped_Read_Real, + Mapped_Write, + Mapped_Write_Real, + Mapped_Write_Alloc, + }; + + struct + { + GLintptr offset; + GLsizeiptr length; + GLbitfield access; + MapStatus status; + byte *ptr; + } Map; + // pointer into binding chunk where datatype enum lives for this resource GLenum datatype; };