Support 2D array texture copying on D3D12, Metal and OpenGL

This patch implements the creation of 2D array textures and copying
between a buffer and a layer of a 2D array texture on D3D12, Metal
and OpenGL back-ends.

TEST=dawn_end2end_tests
This commit is contained in:
Jiawei Shao
2018-08-30 17:32:35 -07:00
committed by Corentin Wallez
parent d8597b2e1f
commit 4ccf4e3fdd
9 changed files with 79 additions and 29 deletions

View File

@@ -331,13 +331,28 @@ namespace dawn_native { namespace opengl {
glActiveTexture(GL_TEXTURE0);
glBindTexture(target, texture->GetHandle());
ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D);
glPixelStorei(GL_UNPACK_ROW_LENGTH,
copy->rowPitch / TextureFormatPixelSize(texture->GetFormat()));
glTexSubImage2D(target, dst.level, dst.x, dst.y, dst.width, dst.height,
switch (texture->GetDimension()) {
case dawn::TextureDimension::e2D:
if (texture->GetArrayLayers() > 1) {
glTexSubImage3D(
target, dst.level, dst.x, dst.y, dst.slice, dst.width,
dst.height, 1, format.format, format.type,
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
} else {
glTexSubImage2D(
target, dst.level, dst.x, dst.y, dst.width, dst.height,
format.format, format.type,
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
}
break;
default:
UNREACHABLE();
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} break;
@@ -348,18 +363,31 @@ namespace dawn_native { namespace opengl {
Texture* texture = ToBackend(src.texture.Get());
Buffer* buffer = ToBackend(dst.buffer.Get());
auto format = texture->GetGLFormat();
GLenum target = texture->GetGLTarget();
// The only way to move data from a texture to a buffer in GL is via
// glReadPixels with a pack buffer. Create a temporary FBO for the copy.
ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D);
glBindTexture(GL_TEXTURE_2D, texture->GetHandle());
glBindTexture(target, texture->GetHandle());
GLuint readFBO = 0;
glGenFramebuffers(1, &readFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
switch (texture->GetDimension()) {
case dawn::TextureDimension::e2D:
if (texture->GetArrayLayers() > 1) {
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture->GetHandle(), src.level,
src.slice);
} else {
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture->GetHandle(),
src.level);
}
break;
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
texture->GetHandle(), src.level);
default:
UNREACHABLE();
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
glPixelStorei(GL_PACK_ROW_LENGTH,

View File

@@ -24,10 +24,11 @@ namespace dawn_native { namespace opengl {
namespace {
GLenum TargetForDimension(dawn::TextureDimension dimension) {
GLenum TargetForDimensionAndArrayLayers(dawn::TextureDimension dimension,
uint32_t arrayLayer) {
switch (dimension) {
case dawn::TextureDimension::e2D:
return GL_TEXTURE_2D;
return (arrayLayer > 1) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
default:
UNREACHABLE();
}
@@ -74,19 +75,32 @@ namespace dawn_native { namespace opengl {
Texture::Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle)
: TextureBase(device, descriptor), mHandle(handle) {
mTarget = TargetForDimension(GetDimension());
mTarget = TargetForDimensionAndArrayLayers(GetDimension(), GetArrayLayers());
uint32_t width = GetWidth();
uint32_t height = GetHeight();
uint32_t levels = GetNumMipLevels();
uint32_t arrayLayers = GetArrayLayers();
auto formatInfo = GetGLFormatInfo(GetFormat());
glBindTexture(mTarget, handle);
for (uint32_t i = 0; i < levels; ++i) {
glTexImage2D(mTarget, i, formatInfo.internalFormat, width, height, 0, formatInfo.format,
formatInfo.type, nullptr);
switch (GetDimension()) {
case dawn::TextureDimension::e2D:
if (arrayLayers > 1) {
glTexImage3D(mTarget, i, formatInfo.internalFormat, width, height,
arrayLayers, 0, formatInfo.format, formatInfo.type, nullptr);
} else {
glTexImage2D(mTarget, i, formatInfo.internalFormat, width, height, 0,
formatInfo.format, formatInfo.type, nullptr);
}
break;
default:
UNREACHABLE();
}
width = std::max(uint32_t(1), width / 2);
height = std::max(uint32_t(1), height / 2);
}