From 47c7b38f93512c7a74c8decf6311692af2933620 Mon Sep 17 00:00:00 2001 From: Kanglai Qian Date: Thu, 24 Dec 2020 16:31:00 +0800 Subject: [PATCH] supporting full glCopyImageSubData --- renderdoc/driver/gl/gl_resources.cpp | 180 ++++++++++++++++++ renderdoc/driver/gl/gl_resources.h | 1 + .../driver/gl/wrappers/gl_texture_funcs.cpp | 73 +++++-- 3 files changed, 241 insertions(+), 13 deletions(-) diff --git a/renderdoc/driver/gl/gl_resources.cpp b/renderdoc/driver/gl/gl_resources.cpp index a75b0aafc..2cbd21fb1 100644 --- a/renderdoc/driver/gl/gl_resources.cpp +++ b/renderdoc/driver/gl/gl_resources.cpp @@ -278,6 +278,186 @@ size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalfor return GetByteSize(w, h, d, GetBaseFormat(internalformat), GetDataType(internalformat)); } +rdcpair GetCompressedBlockSize(GLenum internalformat) +{ + if(!IsCompressedFormat(internalformat)) + { + RDCERR("Not compressed format %s", ToStr(internalformat).c_str()); + return make_rdcpair(1u, 1u); + } + + uint32_t astc[2] = {0, 0}; + + switch(internalformat) + { + // BC1 + case eGL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case eGL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case eGL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + // BC2 + case eGL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + // BC3 + case eGL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + // BC4 + case eGL_COMPRESSED_RED_RGTC1: + case eGL_COMPRESSED_SIGNED_RED_RGTC1: + // BC5 + case eGL_COMPRESSED_RG_RGTC2: + case eGL_COMPRESSED_SIGNED_RG_RGTC2: + // BC6 + case eGL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: + case eGL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: + // BC7 + case eGL_COMPRESSED_RGBA_BPTC_UNORM_ARB: + case eGL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: + // ETC1 + case eGL_ETC1_RGB8_OES: + // ETC2 + case eGL_COMPRESSED_RGB8_ETC2: + case eGL_COMPRESSED_SRGB8_ETC2: + case eGL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case eGL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + // EAC + case eGL_COMPRESSED_RGBA8_ETC2_EAC: + case eGL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case eGL_COMPRESSED_R11_EAC: + case eGL_COMPRESSED_SIGNED_R11_EAC: + case eGL_COMPRESSED_RG11_EAC: + case eGL_COMPRESSED_SIGNED_RG11_EAC: + return make_rdcpair(4u, 4u); + // ASTC + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: + astc[0] = 4; + astc[1] = 4; + break; + case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: + astc[0] = 5; + astc[1] = 4; + break; + case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: + astc[0] = 5; + astc[1] = 5; + break; + case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: + astc[0] = 6; + astc[1] = 5; + break; + case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: + astc[0] = 6; + astc[1] = 6; + break; + case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: + astc[0] = 8; + astc[1] = 5; + break; + case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: + astc[0] = 8; + astc[1] = 6; + break; + case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: + astc[0] = 8; + astc[1] = 8; + break; + case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: + astc[0] = 10; + astc[1] = 5; + break; + case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: + astc[0] = 10; + astc[1] = 6; + break; + case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: + astc[0] = 10; + astc[1] = 8; + break; + case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: + astc[0] = 10; + astc[1] = 10; + break; + case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: + astc[0] = 12; + astc[1] = 10; + break; + case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: + astc[0] = 12; + astc[1] = 12; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: + astc[0] = 4; + astc[1] = 4; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: + astc[0] = 5; + astc[1] = 4; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: + astc[0] = 5; + astc[1] = 5; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: + astc[0] = 6; + astc[1] = 5; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: + astc[0] = 6; + astc[1] = 6; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: + astc[0] = 8; + astc[1] = 5; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: + astc[0] = 8; + astc[1] = 6; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: + astc[0] = 8; + astc[1] = 8; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: + astc[0] = 10; + astc[1] = 5; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: + astc[0] = 10; + astc[1] = 6; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: + astc[0] = 10; + astc[1] = 8; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: + astc[0] = 10; + astc[1] = 10; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: + astc[0] = 12; + astc[1] = 10; + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: + astc[0] = 12; + astc[1] = 12; + break; + // PVRTC + case eGL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT: + case eGL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT: + case eGL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT: return make_rdcpair(4u, 4u); + default: break; + } + + if(astc[0] > 0 && astc[1] > 0) + { + return make_rdcpair(astc[0], astc[1]); + } + + RDCERR("Unrecognised compressed format %s", ToStr(internalformat).c_str()); + return make_rdcpair(1u, 1u); +} + size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type) { size_t elemSize = 1; diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index 00689fd0a..a061599f4 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -29,6 +29,7 @@ #include "gl_common.h" size_t GetCompressedByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum internalformat); +rdcpair GetCompressedBlockSize(GLenum internalformat); size_t GetByteSize(GLsizei w, GLsizei h, GLsizei d, GLenum format, GLenum type); GLenum GetBaseFormat(GLenum internalFormat); GLenum GetDataType(GLenum internalFormat); diff --git a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp index 1de136693..300d55cda 100644 --- a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp @@ -1324,7 +1324,7 @@ void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint s if(dstrecord) GetResourceManager()->MarkResourceFrameReferenced(dstrecord->GetResourceID(), - eFrameRef_CompleteWrite); + eFrameRef_PartialWrite); } SERIALISE_TIME_CALL(GL.glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, @@ -1352,7 +1352,7 @@ void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint s GetContextRecord()->AddChunk(scope.Get()); GetResourceManager()->MarkDirtyResource(dstrecord->GetResourceID()); GetResourceManager()->MarkResourceFrameReferenced(dstrecord->GetResourceID(), - eFrameRef_CompleteWrite); + eFrameRef_PartialWrite); GetResourceManager()->MarkResourceFrameReferenced(srcrecord->GetResourceID(), eFrameRef_Read); } else if(IsBackgroundCapturing(m_State)) @@ -1372,22 +1372,69 @@ void WrappedOpenGL::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint s { TextureData &dstData = m_Textures[dstrecord->GetResourceID()]; - if(srcX == 0 || srcY == 0 || srcZ == 0 || dstX == 0 || dstY == 0 || dstZ == 0) + GLsizei srcLevelWidth = RDCMAX(1, srcData.width >> srcLevel); + GLsizei srcLevelHeight = (srcData.curType != eGL_TEXTURE_1D_ARRAY) + ? RDCMAX(1, srcData.height >> srcLevel) + : srcData.height; + GLsizei srcLevelDepth = (srcData.curType != eGL_TEXTURE_2D_ARRAY && + srcData.curType != eGL_TEXTURE_CUBE_MAP_ARRAY) + ? RDCMAX(1, srcData.depth >> srcLevel) + : srcData.depth; + + GLsizei dstLevelWidth = RDCMAX(1, dstData.width >> dstLevel); + GLsizei dstLevelHeight = (dstData.curType != eGL_TEXTURE_1D_ARRAY) + ? RDCMAX(1, dstData.height >> dstLevel) + : dstData.height; + GLsizei dstLevelDepth = (dstData.curType != eGL_TEXTURE_2D_ARRAY && + dstData.curType != eGL_TEXTURE_CUBE_MAP_ARRAY) + ? RDCMAX(1, dstData.depth >> dstLevel) + : dstData.depth; + if(srcX == 0 && srcY == 0 && srcZ == 0 && dstX == 0 && dstY == 0 && dstZ == 0 && + srcLevelWidth == dstLevelWidth && srcLevelHeight == dstLevelHeight && + srcLevelDepth == dstLevelDepth) { - // we only support whole copies - sub-copies will not work correctly. - RDCASSERT(srcWidth == RDCMAX(1, srcData.width >> srcLevel)); - RDCASSERT(srcHeight == RDCMAX(1, srcData.height >> srcLevel)); - RDCASSERT(srcDepth == RDCMAX(1, srcData.depth >> srcLevel)); - - RDCASSERT(srcWidth == RDCMAX(1, dstData.width >> dstLevel)); - RDCASSERT(srcHeight == RDCMAX(1, dstData.height >> dstLevel)); - RDCASSERT(srcDepth == RDCMAX(1, dstData.depth >> dstLevel)); - dstData.compressedData[dstLevel] = srcData.compressedData[srcLevel]; } else { - RDCWARN("glCopyImageSubData doesn't support offsetted copies of compressed data"); + size_t srcSliceSize = + GetCompressedByteSize(srcLevelWidth, srcLevelHeight, 1, srcData.internalFormat); + size_t dstSliceSize = + GetCompressedByteSize(dstLevelWidth, dstLevelHeight, 1, dstData.internalFormat); + rdcpair srcBlockSize = GetCompressedBlockSize(srcData.internalFormat); + rdcpair dstBlockSize = GetCompressedBlockSize(dstData.internalFormat); + + RDCASSERT(srcWidth % srcBlockSize.first == 0); + RDCASSERT(srcWidth % dstBlockSize.first == 0); + RDCASSERT(srcHeight % srcBlockSize.second == 0); + RDCASSERT(srcHeight % dstBlockSize.second == 0); + for(size_t z = 0; z < (size_t)srcDepth; z++) + { + size_t srcLineSize = GetCompressedByteSize(srcLevelWidth, (GLsizei)srcBlockSize.second, + 1, srcData.internalFormat); + size_t dstLineSize = GetCompressedByteSize(dstLevelWidth, (GLsizei)dstBlockSize.second, + 1, dstData.internalFormat); + size_t srcOffset = + srcSliceSize * (srcZ + z) + srcLineSize * (srcY / (GLsizei)srcBlockSize.second); + srcOffset += + GetCompressedByteSize(srcX, (GLsizei)srcBlockSize.second, 1, srcData.internalFormat); + size_t dstOffset = + dstSliceSize * (dstZ + z) + dstLineSize * (dstY / (GLsizei)dstBlockSize.second); + dstOffset += + GetCompressedByteSize(dstX, (GLsizei)dstBlockSize.second, 1, dstData.internalFormat); + size_t blockSize = GetCompressedByteSize(srcWidth, (GLsizei)dstBlockSize.second, 1, + srcData.internalFormat); + bytebuf &srcCd = srcData.compressedData[srcLevel]; + bytebuf &dstCd = dstData.compressedData[dstLevel]; + for(size_t y = 0; y < (size_t)srcHeight; y += srcBlockSize.second) + { + if(dstCd.size() < dstOffset + blockSize || srcCd.size() < srcOffset + blockSize) + break; + memcpy(dstCd.data() + dstOffset, srcCd.data() + srcOffset, blockSize); + srcOffset += srcLineSize; + dstOffset += dstLineSize; + } + } } } }