From f73a7a4a0cf6ccdeb5073544666254b1b914349c Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 26 Dec 2014 16:04:22 +0000 Subject: [PATCH] Support ARB_map_buffer_alignment on 64byte boundaries * The real implementation can do more if it wants, and align to a larger alignment, but we just return 64 to the program and align to that, which satisfies the extension minimum requirements (and chances are no program takes advantage of wider alignment anyway). --- renderdoc/common/common.h | 3 +++ renderdoc/driver/gl/gl_driver.cpp | 1 + renderdoc/driver/gl/gl_resources.h | 6 ++--- .../driver/gl/wrappers/gl_buffer_funcs.cpp | 18 ++++++++++---- renderdoc/driver/gl/wrappers/gl_get_funcs.cpp | 24 +++++++++++++++++++ renderdoc/serialise/serialiser.cpp | 15 ++++++++---- renderdoc/serialise/serialiser.h | 14 ++++++++--- 7 files changed, 66 insertions(+), 15 deletions(-) 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;