Commit 5850c748 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Emulated RGB copies in compute

The copy between emulated RGB formats can take a number of paths: - Sample from src (reinterpreted as UINT), output to dst - Sample from src, output to temp buffer, copy to dst - Copy src to temp buffer, output to dst - Copy src to temp buffer, convert to another temp buffer, copy to dst While directly sampling from src and outputting to dst is more efficient, these are not always possible. The former may not have SAMPLED_IMAGE usage bit for the reinterpreted UINT format, and the latter may not have STORAGE_IMAGE usage at all. This change takes the universal approach of using two temp buffers. The ConvertVertex shader is used to transform between RGB and RGBA when copying from the first temp buffer to the second. Bug: angleproject:5278 Change-Id: I63d916cfdb4c389f5b817d89cd7348fdea703ce5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2556467 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarBrandon Schade <b.schade@samsung.com>
parent 113b7e63
......@@ -14,6 +14,8 @@
// unsupported formats to their fallbacks.
// - Image clear: Used by FramebufferVk::clearWithDraw().
// - Image copy: Used by TextureVk::copySubImageImplWithDraw().
// - Image copy bits: Used by ImageHelper::CopyImageSubData() to perform bitwise copies between
// RGB formats where at least one of src and dest use RGBA as fallback.
// - Color blit/resolve: Used by FramebufferVk::blit() to implement blit or multisample resolve
// on color images.
// - Depth/Stencil blit/resolve: Used by FramebufferVk::blit() to implement blit or multisample
......@@ -141,6 +143,15 @@ class UtilsVk : angle::NonCopyable
SurfaceRotation srcRotation;
};
struct CopyImageBitsParameters
{
int srcOffset[3];
gl::LevelIndex srcLevel;
int dstOffset[3];
gl::LevelIndex dstLevel;
uint32_t copyExtents[3];
};
struct OverlayCullParameters
{
uint32_t subgroupSize[2];
......@@ -236,6 +247,11 @@ class UtilsVk : angle::NonCopyable
const vk::ImageView *srcView,
const CopyImageParameters &params);
angle::Result copyImageBits(ContextVk *contextVk,
vk::ImageHelper *dest,
vk::ImageHelper *src,
const CopyImageBitsParameters &params);
using GenerateMipmapDestLevelViews =
std::array<const vk::ImageView *, kGenerateMipmapMaxLevels>;
angle::Result generateMipmap(ContextVk *contextVk,
......@@ -496,6 +512,14 @@ class UtilsVk : angle::NonCopyable
const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut);
// Set up descriptor set and call dispatch.
angle::Result convertVertexBufferImpl(ContextVk *contextVk,
vk::BufferHelper *dest,
vk::BufferHelper *src,
uint32_t flags,
vk::CommandBuffer *commandBuffer,
const ConvertVertexShaderParams &shaderParams);
// Blits or resolves either color or depth/stencil, based on which view is given.
angle::Result blitResolveImpl(ContextVk *contextVk,
FramebufferVk *framebuffer,
......
......@@ -1339,17 +1339,17 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount) const;
angle::Result initAliasedLayerImageView(Context *context,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut,
LevelIndex baseMipLevelVk,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
VkImageUsageFlags imageUsageFlags,
VkFormat imageViewFormat) const;
angle::Result initReinterpretedLayerImageView(Context *context,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut,
LevelIndex baseMipLevelVk,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
VkImageUsageFlags imageUsageFlags,
VkFormat imageViewFormat) const;
angle::Result initImageView(Context *context,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
......
......@@ -8619,6 +8619,79 @@ TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
}
}
class CopyImageTestES31 : public ANGLETest
{
protected:
CopyImageTestES31() {}
};
// Test that copies between RGB formats doesn't affect the emulated alpha channel, if any.
TEST_P(CopyImageTestES31, PreserveEmulatedAlpha)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
constexpr GLsizei kSize = 1;
GLTexture src, dst;
// Set up the textures
glBindTexture(GL_TEXTURE_2D, src);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, kSize, kSize);
const GLColor kInitColor(50, 100, 150, 200);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGB, GL_UNSIGNED_BYTE, &kInitColor);
glBindTexture(GL_TEXTURE_2D, dst);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8UI, kSize, kSize);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Copy from src to dst
glCopyImageSubDataEXT(src, GL_TEXTURE_2D, 0, 0, 0, 0, dst, GL_TEXTURE_2D, 0, 0, 0, 0, kSize,
kSize, 1);
// Bind dst as image
glBindImageTexture(0, dst, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
// Create a buffer for output
constexpr GLsizei kBufferSize = kSize * kSize * sizeof(uint32_t) * 4;
GLBuffer buffer;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
constexpr char kCS[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(rgba8ui, binding = 0) readonly uniform highp uimage2D imageIn;
layout(std140, binding = 1) buffer dataOut {
uvec4 data[];
};
void main()
{
uvec4 color = imageLoad(imageIn, ivec2(0));
data[0] = color;
})";
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
glUseProgram(program);
glDispatchCompute(1, 1, 1);
EXPECT_GL_NO_ERROR();
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
const uint32_t *ptr = reinterpret_cast<uint32_t *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
EXPECT_EQ(ptr[0], kInitColor.R);
EXPECT_EQ(ptr[1], kInitColor.G);
EXPECT_EQ(ptr[2], kInitColor.B);
// Expect alpha to be 1, even if the RGB format is emulated with RGBA.
EXPECT_EQ(ptr[3], 1u);
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
#define ES2_EMULATE_COPY_TEX_IMAGE() \
......@@ -8673,5 +8746,6 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
} // anonymous namespace
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