mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +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
|
||||
auto version = QOpenGLContextWrapper::currentContextVersion();
|
||||
std::shared_ptr<GLBackend> result;
|
||||
if (false && !disableOpenGL45 && version >= 0x0405) {
|
||||
if (!disableOpenGL45 && version >= 0x0405) {
|
||||
qCDebug(gpugllogging) << "Using OpenGL 4.5 backend";
|
||||
result = std::make_shared<gpu::gl45::GL45Backend>();
|
||||
} 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) :
|
||||
GLObject(backend, texture, id),
|
||||
_source(texture.source()),
|
||||
_target(getGLTextureType(texture))
|
||||
_target(getGLTextureType(texture)),
|
||||
_texelFormat(GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), texture.getStoredMipFormat()))
|
||||
{
|
||||
Backend::setGPUObject(texture, this);
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
const GLuint& _texture { _id };
|
||||
const std::string _source;
|
||||
const GLenum _target;
|
||||
GLTexelFormat _texelFormat;
|
||||
|
||||
static const std::vector<GLenum>& getFaceTargets(GLenum textureType);
|
||||
static uint8_t getFaceCount(GLenum textureType);
|
||||
|
|
|
@ -110,7 +110,6 @@ public:
|
|||
|
||||
Size size() const override { return _size; }
|
||||
Size _size { 0 };
|
||||
GLTexelFormat _texelFormat;
|
||||
};
|
||||
|
||||
class GL41ResourceTexture : public GL41VariableAllocationTexture {
|
||||
|
|
|
@ -241,8 +241,7 @@ GL41StrictResourceTexture::GL41StrictResourceTexture(const std::weak_ptr<GLBacke
|
|||
using GL41VariableAllocationTexture = GL41Backend::GL41VariableAllocationTexture;
|
||||
|
||||
GL41VariableAllocationTexture::GL41VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) :
|
||||
GL41Texture(backend, texture),
|
||||
_texelFormat(GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), texture.getStoredMipFormat()))
|
||||
GL41Texture(backend, texture)
|
||||
{
|
||||
auto mipLevels = texture.getNumMips();
|
||||
_allocatedMip = mipLevels;
|
||||
|
@ -325,25 +324,87 @@ void GL41VariableAllocationTexture::promote() {
|
|||
// allocate storage for new level
|
||||
allocateStorage(targetAllocatedMip);
|
||||
|
||||
withPreservedTexture([&] {
|
||||
if (false && _texelFormat.isCompressed()) {
|
||||
uint16_t mips = _gpuObject.getNumMips();
|
||||
// copy pre-existing mips
|
||||
for (uint16_t mip = _populatedMip; mip < mips; ++mip) {
|
||||
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
||||
uint16_t targetMip = mip - _allocatedMip;
|
||||
uint16_t sourceMip = mip - oldAllocatedMip;
|
||||
auto faces = getFaceCount(_target);
|
||||
for (uint8_t face = 0; face < faces; ++face) {
|
||||
glCopyImageSubData(
|
||||
oldId, _target, sourceMip, 0, 0, face,
|
||||
_id, _target, targetMip, 0, 0, face,
|
||||
mipDimensions.x, mipDimensions.y, 1
|
||||
);
|
||||
(void)CHECK_GL_ERROR();
|
||||
if (_texelFormat.isCompressed()) {
|
||||
GLuint pbo { 0 };
|
||||
glGenBuffers(1, &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);
|
||||
glBindTexture(_target, oldId);
|
||||
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 };
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
|
@ -365,9 +426,10 @@ void GL41VariableAllocationTexture::promote() {
|
|||
// destroy the transfer framebuffer
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
syncSampler();
|
||||
});
|
||||
|
||||
syncSampler();
|
||||
});
|
||||
}
|
||||
|
||||
// destroy the old texture
|
||||
glDeleteTextures(1, &oldId);
|
||||
|
@ -383,44 +445,86 @@ void GL41VariableAllocationTexture::demote() {
|
|||
auto oldSize = _size;
|
||||
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
||||
uint16_t oldAllocatedMip = _allocatedMip;
|
||||
uint16_t oldPopulatedMip = _populatedMip;
|
||||
allocateStorage(_allocatedMip + 1);
|
||||
_populatedMip = std::max(_populatedMip, _allocatedMip);
|
||||
|
||||
if (_texelFormat.isCompressed()) {
|
||||
GLuint pbo { 0 };
|
||||
glGenBuffers(1, &pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_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);
|
||||
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 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);
|
||||
uint16_t sourceLevel = mip - oldAllocatedMip;
|
||||
|
||||
auto faces = getFaceCount(_target);
|
||||
for (uint8_t face = 0; face < faces; ++face) {
|
||||
glCopyImageSubData(
|
||||
oldId, _target, sourceMip, 0, 0, face,
|
||||
_id, _target, targetMip, 0, 0, face,
|
||||
mipDimensions.x, mipDimensions.y, 1
|
||||
);
|
||||
(void)CHECK_GL_ERROR();
|
||||
// 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 = 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_PACK_BUFFER, 0);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
|
||||
} else {
|
||||
|
@ -429,9 +533,9 @@ void GL41VariableAllocationTexture::demote() {
|
|||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
|
||||
uint16_t mips = _gpuObject.getNumMips();
|
||||
uint16_t numMips = _gpuObject.getNumMips();
|
||||
// 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);
|
||||
uint16_t targetMip = mip - _allocatedMip;
|
||||
uint16_t sourceMip = targetMip + 1;
|
||||
|
|
|
@ -407,8 +407,12 @@ void Texture::setStoredMipFormat(const Element& format) {
|
|||
_storage->setFormat(format);
|
||||
}
|
||||
|
||||
const Element& Texture::getStoredMipFormat() const {
|
||||
return _storage->getFormat();
|
||||
const Element Texture::getStoredMipFormat() const {
|
||||
if (_storage) {
|
||||
return _storage->getFormat();
|
||||
} else {
|
||||
return Element();
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::assignStoredMip(uint16 level, Size size, const Byte* bytes) {
|
||||
|
|
|
@ -372,7 +372,7 @@ public:
|
|||
bool isColorRenderTarget() const;
|
||||
bool isDepthStencilRenderTarget() const;
|
||||
|
||||
const Element& getTexelFormat() const { return _texelFormat; }
|
||||
const Element getTexelFormat() const { return _texelFormat; }
|
||||
|
||||
Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); }
|
||||
uint16 getWidth() const { return _width; }
|
||||
|
@ -468,7 +468,7 @@ public:
|
|||
|
||||
// Mip storage format is constant across all mips
|
||||
void setStoredMipFormat(const Element& format);
|
||||
const Element& getStoredMipFormat() const;
|
||||
const Element getStoredMipFormat() const;
|
||||
|
||||
// Manually allocate the mips down until the specified maxMip
|
||||
// this is just allocating the sysmem version of it
|
||||
|
|
Loading…
Reference in a new issue