diff --git a/renderdoc/common/common.h b/renderdoc/common/common.h index b312426e1..1c10a7edc 100644 --- a/renderdoc/common/common.h +++ b/renderdoc/common/common.h @@ -82,6 +82,9 @@ inline T AlignUp4(T x) { return (x+0x3) & (~0x3); } template inline T AlignUp16(T x) { return (x+0xf) & (~0xf); } +template +inline T AlignUp(T x, T a) { return (x+(a-1)) & (~(a-1)); } + #define MAKE_FOURCC(a, b, c, d) (((uint32_t)(d) << 24) | ((uint32_t)(c) << 16) | ((uint32_t)(b) << 8) | (uint32_t)(a)) bool FindDiffRange(void *a, void *b, size_t bufSize, size_t &diffStart, size_t &diffEnd); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 0af8eaed8..03e9ed0e6 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -387,6 +387,7 @@ WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs) globalExts.push_back("GL_ARB_internalformat_query"); globalExts.push_back("GL_ARB_internalformat_query2"); globalExts.push_back("GL_ARB_invalidate_subdata"); + globalExts.push_back("GL_ARB_map_buffer_alignment"); globalExts.push_back("GL_ARB_map_buffer_range"); globalExts.push_back("GL_ARB_multi_bind"); globalExts.push_back("GL_ARB_multi_draw_indirect"); diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index 1f4400f88..bced6ab99 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -180,12 +180,12 @@ struct GLResourceRecord : public ResourceRecord GLResource Resource; - void AllocShadowStorage(size_t size) + void AllocShadowStorage(size_t size, size_t alignment = 16) { if(ShadowPtr[0] == NULL) { - ShadowPtr[0] = Serialiser::AllocAlignedBuffer(size); - ShadowPtr[1] = Serialiser::AllocAlignedBuffer(size); + ShadowPtr[0] = Serialiser::AllocAlignedBuffer(size, alignment); + ShadowPtr[1] = Serialiser::AllocAlignedBuffer(size, alignment); } } diff --git a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp index 052ab40d4..47553ecfe 100644 --- a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp @@ -294,6 +294,9 @@ void WrappedOpenGL::glNamedBufferStorageEXT(GLuint buffer, GLsizeiptr size, cons SCOPED_SERIALISE_CONTEXT(BUFFERSTORAGE); Serialise_glNamedBufferStorageEXT(buffer, size, data, flags); + // for satisfying GL_MIN_MAP_BUFFER_ALIGNMENT + scope.SetAlignment(64); + Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) @@ -324,6 +327,9 @@ void WrappedOpenGL::glBufferStorage(GLenum target, GLsizeiptr size, const void * Serialise_glNamedBufferStorageEXT(record->Resource.name, size, data, flags); + // for satisfying GL_MIN_MAP_BUFFER_ALIGNMENT + scope.SetAlignment(64); + Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) @@ -455,6 +461,9 @@ void WrappedOpenGL::glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const v SCOPED_SERIALISE_CONTEXT(BUFFERDATA); Serialise_glNamedBufferDataEXT(buffer, size, data, usage); + // for satisfying GL_MIN_MAP_BUFFER_ALIGNMENT + scope.SetAlignment(64); + Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) @@ -552,6 +561,9 @@ void WrappedOpenGL::glBufferData(GLenum target, GLsizeiptr size, const void *dat SCOPED_SERIALISE_CONTEXT(BUFFERDATA); Serialise_glNamedBufferDataEXT(buffer, size, data, usage); + // for satisfying GL_MIN_MAP_BUFFER_ALIGNMENT + scope.SetAlignment(64); + Chunk *chunk = scope.Get(); if(m_State == WRITING_CAPFRAME) @@ -1301,7 +1313,7 @@ void *WrappedOpenGL::glMapNamedBufferEXT(GLuint buffer, GLenum access) if(shadow == NULL) { - record->AllocShadowStorage(length); + record->AllocShadowStorage(length, 64); shadow = (byte *)record->GetShadowPtr(0); if(GetResourceManager()->IsResourceDirty(record->GetResourceID())) @@ -1397,8 +1409,6 @@ void *WrappedOpenGL::glMapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GL return record->Map.ptr; } - // TODO align return pointer to GL_MIN_MAP_BUFFER_ALIGNMENT (min 64) - if((access & GL_MAP_READ_BIT) != 0) { byte *ptr = record->GetDataPtr(); @@ -1455,7 +1465,7 @@ void *WrappedOpenGL::glMapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GL GLint buflength; m_Real.glGetNamedBufferParameterivEXT(buffer, eGL_BUFFER_SIZE, &buflength); - record->AllocShadowStorage(buflength); + record->AllocShadowStorage(buflength, 64); shadow = (byte *)record->GetShadowPtr(0); if(!invalidateMap) diff --git a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp index d1a102605..cdff0090f 100644 --- a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp @@ -145,6 +145,12 @@ void WrappedOpenGL::glGetPointerv(GLenum pname, void **params) void WrappedOpenGL::glGetIntegerv(GLenum pname, GLint *params) { + if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) + { + if(params) + *params = (GLint)64; + return; + } if(pname == eGL_NUM_EXTENSIONS) { if(params) @@ -162,6 +168,12 @@ void WrappedOpenGL::glGetBooleanv(GLenum pname, GLboolean *data) void WrappedOpenGL::glGetInteger64v(GLenum pname, GLint64 *data) { + if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) + { + if(data) + *data = (GLint)64; + return; + } m_Real.glGetInteger64v(pname, data); } @@ -172,6 +184,12 @@ void WrappedOpenGL::glGetBooleani_v(GLenum pname, GLuint index, GLboolean *data) void WrappedOpenGL::glGetIntegeri_v(GLenum pname, GLuint index, GLint *data) { + if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) + { + if(data) + *data = (GLint)64; + return; + } m_Real.glGetIntegeri_v(pname, index, data); } @@ -187,6 +205,12 @@ void WrappedOpenGL::glGetDoublei_v(GLenum pname, GLuint index, GLdouble *data) void WrappedOpenGL::glGetInteger64i_v(GLenum pname, GLuint index, GLint64 *data) { + if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) + { + if(data) + *data = (GLint)64; + return; + } m_Real.glGetInteger64i_v(pname, index, data); } diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index 87907665c..8d8f3c4cf 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -40,7 +40,7 @@ int64_t Chunk::m_MaxChunks = 0; const uint32_t Serialiser::MAGIC_HEADER = MAKE_FOURCC('R', 'D', 'O', 'C'); const size_t Serialiser::BufferAlignment = 16; -Chunk::Chunk(Serialiser *ser, uint32_t chunkType, bool temporary) +Chunk::Chunk(Serialiser *ser, uint32_t chunkType, size_t alignment, bool temporary) { m_Length = (uint32_t)ser->GetOffset(); @@ -50,7 +50,12 @@ Chunk::Chunk(Serialiser *ser, uint32_t chunkType, bool temporary) m_Temporary = temporary; - if(ser->HasAlignedData()) + if(alignment) + { + m_Data = Serialiser::AllocAlignedBuffer(m_Length, alignment); + m_AlignedData = true; + } + else if(ser->HasAlignedData()) { m_Data = Serialiser::AllocAlignedBuffer(m_Length); m_AlignedData = true; @@ -331,7 +336,7 @@ void Serialiser::ReadFromFile(uint64_t destOffs, size_t chunkLen) FileIO::fread(m_Buffer + destOffs - m_ReadOffset, 1, chunkLen, m_ReadFileHandle); } -byte *Serialiser::AllocAlignedBuffer(size_t size) +byte *Serialiser::AllocAlignedBuffer(size_t size, size_t alignment) { byte *rawAlloc = NULL; @@ -339,7 +344,7 @@ byte *Serialiser::AllocAlignedBuffer(size_t size) try #endif { - rawAlloc = new byte[size+sizeof(byte*)+16]; + rawAlloc = new byte[size+sizeof(byte*)+alignment]; } #if defined(__EXCEPTIONS) || defined(_CPPUNWIND) catch(std::bad_alloc&) @@ -353,7 +358,7 @@ byte *Serialiser::AllocAlignedBuffer(size_t size) RDCASSERT(rawAlloc); - byte *alignedAlloc = (byte *)AlignUp16((size_t)(rawAlloc+sizeof(byte*))); + byte *alignedAlloc = (byte *)AlignUp((size_t)(rawAlloc+sizeof(byte*)), alignment); byte **realPointer = (byte **)alignedAlloc; realPointer[-1] = rawAlloc; diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 2b6b992e3..019ba2fb9 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -105,7 +105,7 @@ class Chunk #endif // grab current contents of the serialiser into this chunk - Chunk(Serialiser *ser, uint32_t chunkType, bool temp); + Chunk(Serialiser *ser, uint32_t chunkType, size_t alignment, bool temp); private: // no copy semantics @@ -505,7 +505,7 @@ class Serialiser // prints to the debug output log void DebugPrint(const char *fmt, ...); - static byte *AllocAlignedBuffer(size_t size); + static byte *AllocAlignedBuffer(size_t size, size_t align = 16); static void FreeAlignedBuffer(byte *buf); uint64_t FlushToDisk(); @@ -753,6 +753,7 @@ class ScopedContext , m_DebugSer(debugser) #endif { + m_Alignment = 0; m_Name = string(n) + " = " + t; m_Ser->PushContext(m_Name.c_str(), m_Idx, smallChunk); @@ -770,6 +771,7 @@ class ScopedContext , m_DebugSer(debugser) #endif { + m_Alignment = 0; m_Name = n; m_Ser->PushContext(m_Name.c_str(), m_Idx, smallChunk); @@ -787,14 +789,20 @@ class ScopedContext End(); } + void SetAlignment(size_t align) + { + m_Alignment = align; + } + Chunk *Get(bool temporary = false) { End(); - return new Chunk(m_Ser, m_Idx, temporary); + return new Chunk(m_Ser, m_Idx, m_Alignment, temporary); } private: std::string m_Name; uint32_t m_Idx; + size_t m_Alignment; Serialiser *m_Ser; #ifdef DEBUG_TEXT_SERIALISER Serialiser *m_DebugSer;