Commit ff2ebce4 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: allow texture copies from one mip to another

As a first implementation, this makes the copy go through the staging buffer. Once anglebug.com/4719 is implemented, this can be optimized to perform the copy directly. Bug: angleproject:2914 Bug: angleproject:4274 Change-Id: I2c9863381f54c3467ca939d049336960c21f60b0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2240671 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ac44f8c5
...@@ -671,8 +671,12 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk, ...@@ -671,8 +671,12 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
Set3DBaseArrayLayerAndLayerCount(&srcSubresource); Set3DBaseArrayLayerAndLayerCount(&srcSubresource);
} }
// Perform self-copies through a staging buffer.
// TODO: optimize to copy directly if possible. http://anglebug.com/4719
bool isSelfCopy = mImage == srcImage;
// If destination is valid, copy the source directly into it. // If destination is valid, copy the source directly into it.
if (mImage->valid() && !shouldUpdateBeStaged(level)) if (mImage->valid() && !shouldUpdateBeStaged(level) && !isSelfCopy)
{ {
// Make sure any updates to the image are already flushed. // Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
...@@ -761,8 +765,12 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk, ...@@ -761,8 +765,12 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
uint32_t baseLayer = index.hasLayer() ? index.getLayerIndex() : 0; uint32_t baseLayer = index.hasLayer() ? index.getLayerIndex() : 0;
uint32_t layerCount = index.getLayerCount(); uint32_t layerCount = index.getLayerCount();
// Perform self-copies through a staging buffer.
// TODO: optimize to copy directly if possible. http://anglebug.com/4719
bool isSelfCopy = mImage == srcImage;
// If destination is valid, copy the source directly into it. // If destination is valid, copy the source directly into it.
if (mImage->valid() && !shouldUpdateBeStaged(level)) if (mImage->valid() && !shouldUpdateBeStaged(level) && !isSelfCopy)
{ {
// Make sure any updates to the image are already flushed. // Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
......
...@@ -485,9 +485,6 @@ TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination) ...@@ -485,9 +485,6 @@ TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination)
// Deleting textures after copying to them. http://anglebug.com/4267 // Deleting textures after copying to them. http://anglebug.com/4267
TEST_P(CopyTexImageTest, DeleteAfterCopyingToTextures) TEST_P(CopyTexImageTest, DeleteAfterCopyingToTextures)
{ {
// Vulkan does not support copying from a texture to itself. http://anglebug.com/2914
ANGLE_SKIP_TEST_IF(IsVulkan());
GLTexture texture; GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
......
...@@ -2204,6 +2204,102 @@ TEST_P(CopyTextureTestES3, CopySubTextureOffsetNonRenderableFloat) ...@@ -2204,6 +2204,102 @@ TEST_P(CopyTextureTestES3, CopySubTextureOffsetNonRenderableFloat)
testCopy(GL_RGB9_E5, GL_RGB, GL_FLOAT); testCopy(GL_RGB9_E5, GL_RGB, GL_FLOAT);
} }
// Test that copying from one mip to another works
TEST_P(CopyTextureTestES3, CopyBetweenMips)
{
if (!checkExtensions())
{
return;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
glUseProgram(program);
GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
GLint lodLoc = glGetUniformLocation(program, essl3_shaders::LodUniform());
ASSERT_NE(-1, textureLoc);
ASSERT_NE(-1, lodLoc);
glUniform1i(textureLoc, 0);
glUniform1f(lodLoc, 0);
GLTexture texture;
// Create a texture with 3 mips. Mip0 will contain an image as follows:
//
// G G B G
// G R R G
// G R R G
// G G G G
//
// The 2x2 red square and 1x1 blue square will be copied to the other mips.
const GLColor kMip0InitColor[4 * 4] = {
GLColor::green, GLColor::green, GLColor::blue, GLColor::green,
GLColor::green, GLColor::red, GLColor::red, GLColor::green,
GLColor::green, GLColor::red, GLColor::red, GLColor::green,
GLColor::green, GLColor::green, GLColor::green, GLColor::green,
};
const GLColor kMipOtherInitColor[4] = {
GLColor::black,
GLColor::black,
GLColor::black,
GLColor::black,
};
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0InitColor);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMipOtherInitColor);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMipOtherInitColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Commit texture
glUniform1f(lodLoc, 0);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMip0InitColor[0]);
glUniform1f(lodLoc, 1);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMipOtherInitColor[0]);
glUniform1f(lodLoc, 2);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMipOtherInitColor[0]);
ASSERT_GL_NO_ERROR();
// Copy from mip 0 to mip 1. The level is not redefined, so a direct copy can potentially be
// done.
glCopySubTextureCHROMIUM(texture, 0, GL_TEXTURE_2D, texture, 1, 0, 0, 1, 1, 2, 2, false, false,
false);
EXPECT_GL_NO_ERROR();
// Copy from mip 0 to mip 2. Again, the level is not redefined.
glCopySubTextureCHROMIUM(texture, 0, GL_TEXTURE_2D, texture, 2, 0, 0, 2, 0, 1, 1, false, false,
false);
EXPECT_GL_NO_ERROR();
// Verify mips 1 and 2.
int w = getWindowWidth() - 1;
int h = getWindowHeight() - 1;
glUniform1f(lodLoc, 1);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMip0InitColor[4 * 1 + 1]);
EXPECT_PIXEL_COLOR_EQ(w, 0, kMip0InitColor[4 * 1 + 2]);
EXPECT_PIXEL_COLOR_EQ(0, h, kMip0InitColor[4 * 2 + 1]);
EXPECT_PIXEL_COLOR_EQ(w, h, kMip0InitColor[4 * 2 + 2]);
glUniform1f(lodLoc, 2);
drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, kMip0InitColor[4 * 0 + 2]);
EXPECT_PIXEL_COLOR_EQ(w, 0, kMip0InitColor[4 * 0 + 2]);
EXPECT_PIXEL_COLOR_EQ(0, h, kMip0InitColor[4 * 0 + 2]);
EXPECT_PIXEL_COLOR_EQ(w, h, kMip0InitColor[4 * 0 + 2]);
}
#ifdef Bool #ifdef Bool
// X11 craziness. // X11 craziness.
# undef Bool # undef Bool
......
...@@ -2721,9 +2721,6 @@ void main() { ...@@ -2721,9 +2721,6 @@ void main() {
// Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html // Based on the WebGL test conformance/textures/misc/texture-copying-feedback-loops.html
TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops) TEST_P(WebGLCompatibilityTest, TextureCopyingFeedbackLoops)
{ {
// Vulkan does not support copying from a texture to itself. http://anglebug.com/2914
ANGLE_SKIP_TEST_IF(IsVulkan());
GLTexture texture; GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture.get()); glBindTexture(GL_TEXTURE_2D, texture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment