mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 04:53:25 +02:00
Fixing the broken texture copy (during texture streaming) for compressed format in GL41Backend
This commit is contained in:
parent
69a90d6f86
commit
7c15609136
7 changed files with 160 additions and 51 deletions
|
@ -48,7 +48,7 @@ BackendPointer GLBackend::createBackend() {
|
||||||
// Where the gpuContext is initialized and where the TRUE Backend is created and assigned
|
// Where the gpuContext is initialized and where the TRUE Backend is created and assigned
|
||||||
auto version = QOpenGLContextWrapper::currentContextVersion();
|
auto version = QOpenGLContextWrapper::currentContextVersion();
|
||||||
std::shared_ptr<GLBackend> result;
|
std::shared_ptr<GLBackend> result;
|
||||||
if (false && !disableOpenGL45 && version >= 0x0405) {
|
if (!disableOpenGL45 && version >= 0x0405) {
|
||||||
qCDebug(gpugllogging) << "Using OpenGL 4.5 backend";
|
qCDebug(gpugllogging) << "Using OpenGL 4.5 backend";
|
||||||
result = std::make_shared<gpu::gl45::GL45Backend>();
|
result = std::make_shared<gpu::gl45::GL45Backend>();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -102,7 +102,8 @@ const std::vector<GLenum>& GLTexture::getFaceTargets(GLenum target) {
|
||||||
GLTexture::GLTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLuint id) :
|
GLTexture::GLTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLuint id) :
|
||||||
GLObject(backend, texture, id),
|
GLObject(backend, texture, id),
|
||||||
_source(texture.source()),
|
_source(texture.source()),
|
||||||
_target(getGLTextureType(texture))
|
_target(getGLTextureType(texture)),
|
||||||
|
_texelFormat(GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), texture.getStoredMipFormat()))
|
||||||
{
|
{
|
||||||
Backend::setGPUObject(texture, this);
|
Backend::setGPUObject(texture, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,7 @@ public:
|
||||||
const GLuint& _texture { _id };
|
const GLuint& _texture { _id };
|
||||||
const std::string _source;
|
const std::string _source;
|
||||||
const GLenum _target;
|
const GLenum _target;
|
||||||
|
GLTexelFormat _texelFormat;
|
||||||
|
|
||||||
static const std::vector<GLenum>& getFaceTargets(GLenum textureType);
|
static const std::vector<GLenum>& getFaceTargets(GLenum textureType);
|
||||||
static uint8_t getFaceCount(GLenum textureType);
|
static uint8_t getFaceCount(GLenum textureType);
|
||||||
|
|
|
@ -110,7 +110,6 @@ public:
|
||||||
|
|
||||||
Size size() const override { return _size; }
|
Size size() const override { return _size; }
|
||||||
Size _size { 0 };
|
Size _size { 0 };
|
||||||
GLTexelFormat _texelFormat;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GL41ResourceTexture : public GL41VariableAllocationTexture {
|
class GL41ResourceTexture : public GL41VariableAllocationTexture {
|
||||||
|
|
|
@ -241,8 +241,7 @@ GL41StrictResourceTexture::GL41StrictResourceTexture(const std::weak_ptr<GLBacke
|
||||||
using GL41VariableAllocationTexture = GL41Backend::GL41VariableAllocationTexture;
|
using GL41VariableAllocationTexture = GL41Backend::GL41VariableAllocationTexture;
|
||||||
|
|
||||||
GL41VariableAllocationTexture::GL41VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) :
|
GL41VariableAllocationTexture::GL41VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) :
|
||||||
GL41Texture(backend, texture),
|
GL41Texture(backend, texture)
|
||||||
_texelFormat(GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), texture.getStoredMipFormat()))
|
|
||||||
{
|
{
|
||||||
auto mipLevels = texture.getNumMips();
|
auto mipLevels = texture.getNumMips();
|
||||||
_allocatedMip = mipLevels;
|
_allocatedMip = mipLevels;
|
||||||
|
@ -325,25 +324,87 @@ void GL41VariableAllocationTexture::promote() {
|
||||||
// allocate storage for new level
|
// allocate storage for new level
|
||||||
allocateStorage(targetAllocatedMip);
|
allocateStorage(targetAllocatedMip);
|
||||||
|
|
||||||
withPreservedTexture([&] {
|
if (_texelFormat.isCompressed()) {
|
||||||
if (false && _texelFormat.isCompressed()) {
|
GLuint pbo { 0 };
|
||||||
uint16_t mips = _gpuObject.getNumMips();
|
glGenBuffers(1, &pbo);
|
||||||
// copy pre-existing mips
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||||
for (uint16_t mip = _populatedMip; mip < mips; ++mip) {
|
uint16_t numMips = _gpuObject.getNumMips();
|
||||||
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
struct MipDesc {
|
||||||
uint16_t targetMip = mip - _allocatedMip;
|
GLint _faceSize;
|
||||||
uint16_t sourceMip = mip - oldAllocatedMip;
|
GLint _size;
|
||||||
auto faces = getFaceCount(_target);
|
GLint _offset;
|
||||||
for (uint8_t face = 0; face < faces; ++face) {
|
gpu::Vec3u _dims;
|
||||||
glCopyImageSubData(
|
};
|
||||||
oldId, _target, sourceMip, 0, 0, face,
|
std::vector<MipDesc> sourceMips(numMips);
|
||||||
_id, _target, targetMip, 0, 0, face,
|
|
||||||
mipDimensions.x, mipDimensions.y, 1
|
glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_TRANSFER_EXTRA_TEX_UNIT);
|
||||||
);
|
glBindTexture(_target, oldId);
|
||||||
(void)CHECK_GL_ERROR();
|
const auto& faceTargets = getFaceTargets(_target);
|
||||||
|
GLint internalFormat { 0 };
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Collect the mip description from the source texture
|
||||||
|
GLint bufferOffset { 0 };
|
||||||
|
for (uint16_t mip = _populatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
sourceMip._dims = _gpuObject.evalMipDimensions(mip);
|
||||||
|
|
||||||
|
uint16_t sourceLevel = mip - oldAllocatedMip;
|
||||||
|
|
||||||
|
// Grab internal format once
|
||||||
|
if (internalFormat == 0) {
|
||||||
|
glGetTexLevelParameteriv(faceTargets[0], sourceLevel, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect the size of the first face, and then compute the total size offset needed for this mip level
|
||||||
|
glGetTexLevelParameteriv(faceTargets.front(), sourceLevel, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sourceMip._faceSize);
|
||||||
|
sourceMip._size = faceTargets.size() * sourceMip._faceSize;
|
||||||
|
sourceMip._offset = bufferOffset;
|
||||||
|
bufferOffset += sourceMip._size;
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Allocate the PBO to accomodate for all the mips to copy
|
||||||
|
glBufferData(GL_PIXEL_PACK_BUFFER, bufferOffset, nullptr, GL_STREAM_COPY);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Transfer from source texture to pbo
|
||||||
|
for (uint16_t mip = _populatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
|
||||||
|
uint16_t sourceLevel = mip - oldAllocatedMip;
|
||||||
|
|
||||||
|
for (GLint f = 0; f < faceTargets.size(); f++) {
|
||||||
|
glGetCompressedTexImage(faceTargets[f], sourceLevel, (void*)(sourceMip._offset + f * sourceMip._faceSize));
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now populate the new texture from the pbo
|
||||||
|
glBindTexture(_target, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
|
|
||||||
|
withPreservedTexture([&] {
|
||||||
|
// Transfer from pbo to new texture
|
||||||
|
for (uint16_t mip = _populatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
|
||||||
|
uint16_t destLevel = mip - _allocatedMip;
|
||||||
|
|
||||||
|
for (GLint f = 0; f < faceTargets.size(); f++) {
|
||||||
|
glCompressedTexSubImage2D(faceTargets[f], destLevel, 0, 0, sourceMip._dims.x, sourceMip._dims.y, internalFormat,
|
||||||
|
sourceMip._faceSize, (void*)(sourceMip._offset + f * sourceMip._faceSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
syncSampler();
|
||||||
|
});
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
glDeleteBuffers(1, &pbo);
|
||||||
|
} else {
|
||||||
|
withPreservedTexture([&] {
|
||||||
GLuint fbo { 0 };
|
GLuint fbo { 0 };
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||||
|
@ -365,9 +426,10 @@ void GL41VariableAllocationTexture::promote() {
|
||||||
// destroy the transfer framebuffer
|
// destroy the transfer framebuffer
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
glDeleteFramebuffers(1, &fbo);
|
glDeleteFramebuffers(1, &fbo);
|
||||||
}
|
|
||||||
syncSampler();
|
syncSampler();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// destroy the old texture
|
// destroy the old texture
|
||||||
glDeleteTextures(1, &oldId);
|
glDeleteTextures(1, &oldId);
|
||||||
|
@ -383,44 +445,86 @@ void GL41VariableAllocationTexture::demote() {
|
||||||
auto oldSize = _size;
|
auto oldSize = _size;
|
||||||
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
||||||
uint16_t oldAllocatedMip = _allocatedMip;
|
uint16_t oldAllocatedMip = _allocatedMip;
|
||||||
|
uint16_t oldPopulatedMip = _populatedMip;
|
||||||
allocateStorage(_allocatedMip + 1);
|
allocateStorage(_allocatedMip + 1);
|
||||||
_populatedMip = std::max(_populatedMip, _allocatedMip);
|
_populatedMip = std::max(_populatedMip, _allocatedMip);
|
||||||
|
|
||||||
if (_texelFormat.isCompressed()) {
|
if (_texelFormat.isCompressed()) {
|
||||||
GLuint pbo { 0 };
|
GLuint pbo { 0 };
|
||||||
glGenBuffers(1, &pbo);
|
glGenBuffers(1, &pbo);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||||
|
uint16_t numMips = _gpuObject.getNumMips();
|
||||||
|
struct MipDesc {
|
||||||
|
GLint _faceSize;
|
||||||
|
GLint _size;
|
||||||
|
GLint _offset;
|
||||||
|
gpu::Vec3u _dims;
|
||||||
|
};
|
||||||
|
std::vector<MipDesc> sourceMips(numMips);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_TRANSFER_EXTRA_TEX_UNIT);
|
glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_TRANSFER_EXTRA_TEX_UNIT);
|
||||||
glBindTexture(_target, oldId);
|
glBindTexture(_target, oldId);
|
||||||
|
const auto& faceTargets = getFaceTargets(_target);
|
||||||
|
GLint internalFormat { 0 };
|
||||||
|
|
||||||
glGetTexLevelParameteriv(_target, sourceMip, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
|
// Collect the mip description from the source texture
|
||||||
|
GLint bufferOffset { 0 };
|
||||||
|
for (uint16_t mip = oldPopulatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
sourceMip._dims = _gpuObject.evalMipDimensions(mip);
|
||||||
|
|
||||||
// copy pre-existing mips
|
uint16_t sourceLevel = mip - oldAllocatedMip;
|
||||||
uint16_t mips = _gpuObject.getNumMips();
|
|
||||||
for (uint16_t mip = _populatedMip; mip < mips; ++mip) {
|
|
||||||
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
|
||||||
uint16_t targetMip = mip - _allocatedMip;
|
|
||||||
uint16_t sourceMip = targetMip + 1;
|
|
||||||
GLint size { 0 };
|
|
||||||
GLint internalFormat;
|
|
||||||
glGetTexLevelParameteriv(_target, sourceMip, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
|
|
||||||
|
|
||||||
auto faces = getFaceCount(_target);
|
// Grab internal format once
|
||||||
for (uint8_t face = 0; face < faces; ++face) {
|
if (internalFormat != 0) {
|
||||||
glCopyImageSubData(
|
glGetTexLevelParameteriv(faceTargets[0], sourceLevel, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
||||||
oldId, _target, sourceMip, 0, 0, face,
|
|
||||||
_id, _target, targetMip, 0, 0, face,
|
|
||||||
mipDimensions.x, mipDimensions.y, 1
|
|
||||||
);
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect the size of the first face, and then compute the total size offset needed for this mip level
|
||||||
|
glGetTexLevelParameteriv(faceTargets.front(), sourceLevel, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sourceMip._faceSize);
|
||||||
|
sourceMip._size = faceTargets.size() * sourceMip._faceSize;
|
||||||
|
sourceMip._offset = bufferOffset;
|
||||||
|
bufferOffset += sourceMip._size;
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Allocate the PBO to accomodate for all the mips to copy
|
||||||
|
glBufferData(GL_PIXEL_PACK_BUFFER, bufferOffset, nullptr, GL_STREAM_COPY);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Transfer from source texture to pbo
|
||||||
|
for (uint16_t mip = oldPopulatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
|
||||||
|
uint16_t sourceLevel = mip - oldAllocatedMip;
|
||||||
|
|
||||||
|
for (GLint f = 0; f < faceTargets.size(); f++) {
|
||||||
|
glGetCompressedTexImage(faceTargets[f], sourceLevel, (void*) (sourceMip._offset + f * sourceMip._faceSize));
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now populate the new texture from the pbo
|
||||||
|
glBindTexture(_target, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
|
|
||||||
|
withPreservedTexture([&] {
|
||||||
|
// Transfer from pbo to new texture
|
||||||
|
for (uint16_t mip = _populatedMip; mip < numMips; ++mip) {
|
||||||
|
auto& sourceMip = sourceMips[mip];
|
||||||
|
|
||||||
|
uint16_t destLevel = mip - _allocatedMip;
|
||||||
|
|
||||||
|
for (GLint f = 0; f < faceTargets.size(); f++) {
|
||||||
|
glCompressedTexSubImage2D(faceTargets[f], destLevel, 0, 0, sourceMip._dims.x, sourceMip._dims.y, internalFormat,
|
||||||
|
sourceMip._faceSize, (void*)(sourceMip._offset + f * sourceMip._faceSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syncSampler();
|
||||||
|
});
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
||||||
glDeleteBuffers(1, &pbo);
|
glDeleteBuffers(1, &pbo);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -429,9 +533,9 @@ void GL41VariableAllocationTexture::demote() {
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
uint16_t mips = _gpuObject.getNumMips();
|
uint16_t numMips = _gpuObject.getNumMips();
|
||||||
// copy pre-existing mips
|
// copy pre-existing mips
|
||||||
for (uint16_t mip = _populatedMip; mip < mips; ++mip) {
|
for (uint16_t mip = _populatedMip; mip < numMips; ++mip) {
|
||||||
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
||||||
uint16_t targetMip = mip - _allocatedMip;
|
uint16_t targetMip = mip - _allocatedMip;
|
||||||
uint16_t sourceMip = targetMip + 1;
|
uint16_t sourceMip = targetMip + 1;
|
||||||
|
|
|
@ -407,8 +407,12 @@ void Texture::setStoredMipFormat(const Element& format) {
|
||||||
_storage->setFormat(format);
|
_storage->setFormat(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Element& Texture::getStoredMipFormat() const {
|
const Element Texture::getStoredMipFormat() const {
|
||||||
return _storage->getFormat();
|
if (_storage) {
|
||||||
|
return _storage->getFormat();
|
||||||
|
} else {
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::assignStoredMip(uint16 level, Size size, const Byte* bytes) {
|
void Texture::assignStoredMip(uint16 level, Size size, const Byte* bytes) {
|
||||||
|
|
|
@ -372,7 +372,7 @@ public:
|
||||||
bool isColorRenderTarget() const;
|
bool isColorRenderTarget() const;
|
||||||
bool isDepthStencilRenderTarget() const;
|
bool isDepthStencilRenderTarget() const;
|
||||||
|
|
||||||
const Element& getTexelFormat() const { return _texelFormat; }
|
const Element getTexelFormat() const { return _texelFormat; }
|
||||||
|
|
||||||
Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); }
|
Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); }
|
||||||
uint16 getWidth() const { return _width; }
|
uint16 getWidth() const { return _width; }
|
||||||
|
@ -468,7 +468,7 @@ public:
|
||||||
|
|
||||||
// Mip storage format is constant across all mips
|
// Mip storage format is constant across all mips
|
||||||
void setStoredMipFormat(const Element& format);
|
void setStoredMipFormat(const Element& format);
|
||||||
const Element& getStoredMipFormat() const;
|
const Element getStoredMipFormat() const;
|
||||||
|
|
||||||
// Manually allocate the mips down until the specified maxMip
|
// Manually allocate the mips down until the specified maxMip
|
||||||
// this is just allocating the sysmem version of it
|
// this is just allocating the sysmem version of it
|
||||||
|
|
Loading…
Reference in a new issue