variable texture support

This commit is contained in:
SamGondelman 2018-08-06 15:13:00 -07:00 committed by Ryan Huffman
parent 44a9b1df0e
commit a0dfd76f06

View file

@ -65,20 +65,24 @@ GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) {
object = new GLESAttachmentTexture(shared_from_this(), texture);
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:
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
object = new GLESStrictResourceTexture(shared_from_this(), texture);
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:
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);
}
} else {
// TODO: implement for android
assert(false);
amountCopied = 0;
}
@ -385,7 +388,6 @@ void GLESVariableAllocationTexture::allocateStorage(uint16 allocatedMip) {
const auto totalMips = _gpuObject.getNumMips();
const auto mips = totalMips - _allocatedMip;
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();
});
auto mipLevels = _gpuObject.getNumMips();
@ -426,139 +428,26 @@ void GLESVariableAllocationTexture::syncSampler() const {
});
}
void copyUncompressedTexGPUMem(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
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) {
void copyTexGPUMem(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) {
auto mipDimensions = texture.evalMipDimensions(mip);
uint16_t targetMip = mip - destMipOffset;
uint16_t sourceMip = mip - srcMipOffset;
for (GLenum target : GLTexture::getFaceTargets(texTarget)) {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, srcId, sourceMip);
(void)CHECK_GL_ERROR();
glCopyTexSubImage2D(target, targetMip, 0, 0, 0, 0, mipDimensions.x, mipDimensions.y);
auto faces = GLTexture::getFaceCount(texTarget);
for (uint8_t face = 0; face < faces; ++face) {
glCopyImageSubData(
srcId, texTarget, sourceMip, 0, 0, face,
destId, texTarget, targetMip, 0, 0, face,
mipDimensions.x, mipDimensions.y, 1
);
(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) {
uint16_t numMips = _gpuObject.getNumMips();
withPreservedTexture([&] {
if (_texelFormat.isCompressed()) {
copyCompressedTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
} else {
copyUncompressedTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
}
});
copyTexGPUMem(_gpuObject, _target, srcId, destId, numMips, srcMipOffset, destMipOffset, populatedMips);
}
size_t GLESVariableAllocationTexture::promote() {