mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 07:27:17 +02:00
variable texture support
This commit is contained in:
parent
44a9b1df0e
commit
a0dfd76f06
1 changed files with 23 additions and 134 deletions
|
@ -65,20 +65,24 @@ GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
object = new GLESAttachmentTexture(shared_from_this(), texture);
|
object = new GLESAttachmentTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureUsageType::RESOURCE:
|
|
||||||
// FIXME disabling variable allocation textures for now, while debugging android rendering
|
|
||||||
// and crashes
|
|
||||||
#if 0
|
|
||||||
qCDebug(gpugllogging) << "variable / Strict texture " << texture.source().c_str();
|
|
||||||
object = new GLESResourceTexture(shared_from_this(), texture);
|
|
||||||
GLVariableAllocationSupport::addMemoryManagedTexture(texturePointer);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case TextureUsageType::STRICT_RESOURCE:
|
case TextureUsageType::STRICT_RESOURCE:
|
||||||
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
||||||
object = new GLESStrictResourceTexture(shared_from_this(), texture);
|
object = new GLESStrictResourceTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TextureUsageType::RESOURCE: {
|
||||||
|
auto &transferEngine = _textureManagement._transferEngine;
|
||||||
|
if (transferEngine->allowCreate()) {
|
||||||
|
object = new GLESResourceTexture(shared_from_this(), texture);
|
||||||
|
transferEngine->addMemoryManagedTexture(texturePointer);
|
||||||
|
} else {
|
||||||
|
auto fallback = texturePointer->getFallbackTexture();
|
||||||
|
if (fallback) {
|
||||||
|
object = static_cast<GLESTexture *>(syncGPUObject(fallback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -195,7 +199,6 @@ Size GLESTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
||||||
glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
glTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: implement for android
|
|
||||||
assert(false);
|
assert(false);
|
||||||
amountCopied = 0;
|
amountCopied = 0;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +388,6 @@ void GLESVariableAllocationTexture::allocateStorage(uint16 allocatedMip) {
|
||||||
const auto totalMips = _gpuObject.getNumMips();
|
const auto totalMips = _gpuObject.getNumMips();
|
||||||
const auto mips = totalMips - _allocatedMip;
|
const auto mips = totalMips - _allocatedMip;
|
||||||
withPreservedTexture([&] {
|
withPreservedTexture([&] {
|
||||||
// FIXME technically GL 4.2, but OSX includes the ARB_texture_storage extension
|
|
||||||
glTexStorage2D(_target, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); CHECK_GL_ERROR();
|
glTexStorage2D(_target, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); CHECK_GL_ERROR();
|
||||||
});
|
});
|
||||||
auto mipLevels = _gpuObject.getNumMips();
|
auto mipLevels = _gpuObject.getNumMips();
|
||||||
|
@ -426,139 +428,26 @@ void GLESVariableAllocationTexture::syncSampler() const {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copyTexGPUMem(const gpu::Texture& texture, GLenum texTarget, GLuint srcId, GLuint destId, uint16_t numMips, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) {
|
||||||
void copyUncompressedTexGPUMem(const gpu::Texture& texture, GLenum texTarget, GLuint srcId, GLuint destId, uint16_t numMips, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) {
|
for (uint16_t mip = populatedMips; mip < numMips; ++mip) {
|
||||||
// DestID must be bound to the GLESBackend::RESOURCE_TRANSFER_TEX_UNIT
|
|
||||||
|
|
||||||
GLuint fbo { 0 };
|
|
||||||
glGenFramebuffers(1, &fbo);
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
|
||||||
|
|
||||||
uint16_t mips = numMips;
|
|
||||||
// copy pre-existing mips
|
|
||||||
for (uint16_t mip = populatedMips; mip < mips; ++mip) {
|
|
||||||
auto mipDimensions = texture.evalMipDimensions(mip);
|
auto mipDimensions = texture.evalMipDimensions(mip);
|
||||||
uint16_t targetMip = mip - destMipOffset;
|
uint16_t targetMip = mip - destMipOffset;
|
||||||
uint16_t sourceMip = mip - srcMipOffset;
|
uint16_t sourceMip = mip - srcMipOffset;
|
||||||
for (GLenum target : GLTexture::getFaceTargets(texTarget)) {
|
auto faces = GLTexture::getFaceCount(texTarget);
|
||||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, srcId, sourceMip);
|
for (uint8_t face = 0; face < faces; ++face) {
|
||||||
(void)CHECK_GL_ERROR();
|
glCopyImageSubData(
|
||||||
glCopyTexSubImage2D(target, targetMip, 0, 0, 0, 0, mipDimensions.x, mipDimensions.y);
|
srcId, texTarget, sourceMip, 0, 0, face,
|
||||||
|
destId, texTarget, targetMip, 0, 0, face,
|
||||||
|
mipDimensions.x, mipDimensions.y, 1
|
||||||
|
);
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy the transfer framebuffer
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
|
||||||
glDeleteFramebuffers(1, &fbo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyCompressedTexGPUMem(const gpu::Texture& texture, GLenum texTarget, GLuint srcId, GLuint destId, uint16_t numMips, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) {
|
|
||||||
// DestID must be bound to the GLESBackend::RESOURCE_TRANSFER_TEX_UNIT
|
|
||||||
|
|
||||||
struct MipDesc {
|
|
||||||
GLint _faceSize;
|
|
||||||
GLint _size;
|
|
||||||
GLint _offset;
|
|
||||||
GLint _width;
|
|
||||||
GLint _height;
|
|
||||||
};
|
|
||||||
std::vector<MipDesc> sourceMips(numMips);
|
|
||||||
|
|
||||||
std::vector<GLubyte> bytes;
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + GLESBackend::RESOURCE_TRANSFER_EXTRA_TEX_UNIT);
|
|
||||||
glBindTexture(texTarget, srcId);
|
|
||||||
const auto& faceTargets = GLTexture::getFaceTargets(texTarget);
|
|
||||||
GLint internalFormat { 0 };
|
|
||||||
|
|
||||||
// Collect the mip description from the source texture
|
|
||||||
GLint bufferOffset { 0 };
|
|
||||||
for (uint16_t mip = populatedMips; mip < numMips; ++mip) {
|
|
||||||
auto& sourceMip = sourceMips[mip];
|
|
||||||
|
|
||||||
uint16_t sourceLevel = mip - srcMipOffset;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
auto mipDimensions = texture.evalMipDimensions(mip);
|
|
||||||
sourceMip._width = mipDimensions.x;
|
|
||||||
sourceMip._height = mipDimensions.y;
|
|
||||||
#ifdef DEBUG_COPY
|
|
||||||
glGetTexLevelParameteriv(faceTargets.front(), sourceLevel, GL_TEXTURE_WIDTH, &sourceMip._width);
|
|
||||||
glGetTexLevelParameteriv(faceTargets.front(), sourceLevel, GL_TEXTURE_HEIGHT, &sourceMip._height);
|
|
||||||
#endif
|
|
||||||
// TODO: retrieve the size of a compressed image
|
|
||||||
assert(false);
|
|
||||||
//glGetTexLevelParameteriv(faceTargets.front(), sourceLevel, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &sourceMip._faceSize);
|
|
||||||
sourceMip._size = (GLint)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
|
|
||||||
GLuint pbo { 0 };
|
|
||||||
glGenBuffers(1, &pbo);
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
|
||||||
glBufferData(GL_PIXEL_PACK_BUFFER, bufferOffset, nullptr, GL_STATIC_COPY);
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
// Transfer from source texture to pbo
|
|
||||||
for (uint16_t mip = populatedMips; mip < numMips; ++mip) {
|
|
||||||
auto& sourceMip = sourceMips[mip];
|
|
||||||
|
|
||||||
uint16_t sourceLevel = mip - srcMipOffset;
|
|
||||||
|
|
||||||
for (GLint f = 0; f < (GLint)faceTargets.size(); f++) {
|
|
||||||
// TODO: implement for android
|
|
||||||
//glGetCompressedTexImage(faceTargets[f], sourceLevel, BUFFER_OFFSET(sourceMip._offset + f * sourceMip._faceSize));
|
|
||||||
}
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now populate the new texture from the pbo
|
|
||||||
glBindTexture(texTarget, 0);
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + GLESBackend::RESOURCE_TRANSFER_TEX_UNIT);
|
|
||||||
|
|
||||||
// Transfer from pbo to new texture
|
|
||||||
for (uint16_t mip = populatedMips; mip < numMips; ++mip) {
|
|
||||||
auto& sourceMip = sourceMips[mip];
|
|
||||||
|
|
||||||
uint16_t destLevel = mip - destMipOffset;
|
|
||||||
|
|
||||||
for (GLint f = 0; f < (GLint)faceTargets.size(); f++) {
|
|
||||||
#ifdef DEBUG_COPY
|
|
||||||
GLint destWidth, destHeight, destSize;
|
|
||||||
glGetTexLevelParameteriv(faceTargets.front(), destLevel, GL_TEXTURE_WIDTH, &destWidth);
|
|
||||||
glGetTexLevelParameteriv(faceTargets.front(), destLevel, GL_TEXTURE_HEIGHT, &destHeight);
|
|
||||||
glGetTexLevelParameteriv(faceTargets.front(), destLevel, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &destSize);
|
|
||||||
#endif
|
|
||||||
glCompressedTexSubImage2D(faceTargets[f], destLevel, 0, 0, sourceMip._width, sourceMip._height, internalFormat,
|
|
||||||
sourceMip._faceSize, BUFFER_OFFSET(sourceMip._offset + f * sourceMip._faceSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
glDeleteBuffers(1, &pbo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLESVariableAllocationTexture::copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) {
|
void GLESVariableAllocationTexture::copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) {
|
||||||
uint16_t numMips = _gpuObject.getNumMips();
|
uint16_t numMips = _gpuObject.getNumMips();
|
||||||
withPreservedTexture([&] {
|
copyTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
|
||||||
if (_texelFormat.isCompressed()) {
|
|
||||||
copyCompressedTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
|
|
||||||
} else {
|
|
||||||
copyUncompressedTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GLESVariableAllocationTexture::promote() {
|
size_t GLESVariableAllocationTexture::promote() {
|
||||||
|
|
Loading…
Reference in a new issue