Commit df415528 by Sunny Sun Committed by Commit Bot

Vulkan: Enable VK_IMAGE_USAGE_STORAGE_BIT when it is needed

VK_IMAGE_USAGE_STORAGE_BIT is always enabled for vkImage, this increases memory bandwidth in some platforms. This CL changes the behavior to enable VK_IMAGE_USAGE_STORAGE_BIT when necessary. Bug: angleproject:3904 Test: angle_end2end_tests Test: angle_deqp_gles2_tests Change-Id: I8ffd37efa8d99d04328fa6232de0755be3273d9e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1857799 Commit-Queue: Sunny Sun <sunny.sun@arm.com> Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 67527cb4
......@@ -165,3 +165,4 @@ Samsung Electronics, Inc.
Arm Ltd.
Fei Yang
Xinyi He
Sunny Sun
......@@ -486,6 +486,7 @@ void Context::initialize()
mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
......
......@@ -2881,6 +2881,10 @@ void State::setImageUnit(const Context *context,
mImageUnits[unit].format = format;
mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS);
if (texture)
{
texture->onBindImageTexture();
}
onImageStateChange(context, unit);
}
......
......@@ -99,6 +99,7 @@ TextureState::TextureState(TextureType type)
mBaseLevel(0),
mMaxLevel(1000),
mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
mBoundAsImageTexture(false),
mImmutableFormat(false),
mImmutableLevels(0),
mUsage(GL_NONE),
......@@ -1908,4 +1909,14 @@ angle::Result Texture::getTexImage(const Context *context,
return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
pixels);
}
void Texture::onBindImageTexture()
{
if (!mState.mBoundAsImageTexture)
{
mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
mState.mBoundAsImageTexture = true;
}
}
} // namespace gl
......@@ -190,6 +190,7 @@ class TextureState final : private angle::NonCopyable
GLenum mDepthStencilTextureMode;
bool mBoundAsImageTexture;
bool mImmutableFormat;
GLuint mImmutableLevels;
......@@ -412,6 +413,7 @@ class Texture final : public RefCountObject<TextureID>,
angle::Result setEGLImageTarget(Context *context, TextureType type, egl::Image *imageTarget);
angle::Result generateMipmap(Context *context);
void onBindImageTexture();
egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const;
......@@ -493,6 +495,9 @@ class Texture final : public RefCountObject<TextureID>,
DIRTY_BIT_MAX_LEVEL,
DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE,
// Image state
DIRTY_BIT_BOUND_AS_IMAGE,
// Misc
DIRTY_BIT_LABEL,
DIRTY_BIT_USAGE,
......
......@@ -1462,6 +1462,9 @@ angle::Result TextureGL::syncState(const gl::Context *context,
// This special dirty bit is used to signal the front-end that the implementation
// has local dirty bits. The real dirty bits are in mLocalDirty bits.
break;
case gl::Texture::DIRTY_BIT_BOUND_AS_IMAGE:
// Only used for Vulkan.
break;
default:
UNREACHABLE();
......
......@@ -322,7 +322,8 @@ class TextureVk : public TextureImpl
bool ignoreLayerCount,
uint32_t currentLayer,
uint32_t sourceLevel,
uint32_t stagingDstMipLevel);
uint32_t stagingDstMipLevel,
vk::BufferHelper **stagingBuffer);
angle::Result initImageViews(ContextVk *contextVk,
const vk::Format &format,
const bool sized,
......@@ -341,9 +342,20 @@ class TextureVk : public TextureImpl
void onStagingBufferChange() { onStateChange(angle::SubjectMessage::SubjectChanged); }
angle::Result changeLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel);
const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
const vk::Format &getBaseLevelFormat(RendererVk *renderer) const;
// Re-create the image.
angle::Result changeLevels(ContextVk *contextVk,
GLuint previousBaseLevel,
GLuint baseLevel,
GLuint maxLevel,
vk::BufferHelper **stagingBuffer);
// Update base and max levels, and re-create image if needed.
angle::Result updateBaseMaxLevels(ContextVk *contextVk,
GLuint baseLevel,
GLuint maxLevel,
vk::BufferHelper **stagingBuffer);
bool mOwnsImage;
......@@ -380,6 +392,9 @@ class TextureVk : public TextureImpl
// Overridden in some tests.
size_t mStagingBufferInitialSize;
// The created vkImage usage flag.
VkImageUsageFlags mImageUsageFlags;
};
} // namespace rx
......
......@@ -574,6 +574,10 @@
// Fixed in later driver versions.
2727 VULKAN ANDROID : dEQP-GLES3.functional.shaders.builtin_variable.pointcoord = FAIL
// New or broken formats in ES 3.0, may be it relates to VK_IMAGE_USAGE_STORAGE_BIT
3816 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.texture.specification.texstorage3d.format.rgba16* = FAIL
3816 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.texture.specification.texstorage3d.format.rgb16* = FAIL
3816 VULKAN PIXEL2ORXL : dEQP-GLES3.functional.texture.specification.texstorage3d.format.rg32* = FAIL
// Fails only with SwiftShader:
......
......@@ -3508,6 +3508,117 @@ void main()
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
// Test that render pipeline and compute pipeline access to the same texture.
// Steps:
// 1. Clear the texture and DrawArrays.
// 2. DispatchCompute to set the image's first pixel to a specific color.
// 3. DrawArrays and check data.
TEST_P(ComputeShaderTest, DrawDispatchDrawPreserve)
{
const char kCSSource[] = R"(#version 310 es
layout(local_size_x=1, local_size_y=1) in;
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
void main()
{
imageStore(image, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0));
})";
const char kVSSource[] = R"(#version 310 es
layout (location = 0) in vec2 pos;
in vec4 inTex;
out vec4 texCoord;
void main(void) {
texCoord = inTex;
gl_Position = vec4(pos, 0.0, 1.0);
})";
const char kFSSource[] = R"(#version 310 es
precision highp float;
uniform sampler2D tex;
in vec4 texCoord;
out vec4 fragColor;
void main(void) {
fragColor = texture(tex, texCoord.xy);
})";
GLuint aPosLoc = 0;
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
glBindAttribLocation(program, aPosLoc, "pos");
unsigned char *data = new unsigned char[4 * getWindowWidth() * getWindowHeight()];
for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
{
data[i * 4] = 0xff;
data[i * 4 + 1] = 0;
data[i * 4 + 2] = 0;
data[i * 4 + 3] = 0xff;
}
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth(), getWindowHeight());
// Clear the texture level 0 to Red.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA,
GL_UNSIGNED_BYTE, data);
for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
{
data[i * 4] = 0;
data[i * 4 + 1] = 0xff;
data[i * 4 + 2] = 0;
data[i * 4 + 3] = 0xff;
}
// Clear the texture level 1 to Green.
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
GL_UNSIGNED_BYTE, data);
delete[] data;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glUseProgram(program);
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
GLfloat texCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
GLint pos = glGetAttribLocation(program, "pos");
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
GLint posTex = glGetAttribLocation(program, "inTex");
glEnableVertexAttribArray(posTex);
glVertexAttribPointer(posTex, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
// Draw with level 0, the whole frame buffer should be Red.
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
// Draw with level 1, the whole frame buffer should be Green.
glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
// Clear the texture level 0's (0, 0) position to Blue.
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
glUseProgram(csProgram);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
EXPECT_GL_NO_ERROR();
glFinish();
glUseProgram(program);
// Draw with level 0, the first position should be Blue.
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
// Draw with level 1, the whole frame buffer should be Green.
glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
}
ANGLE_INSTANTIATE_TEST(ComputeShaderTest,
ES31_OPENGL(),
ES31_OPENGLES(),
......
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