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. ...@@ -165,3 +165,4 @@ Samsung Electronics, Inc.
Arm Ltd. Arm Ltd.
Fei Yang Fei Yang
Xinyi He Xinyi He
Sunny Sun
...@@ -486,6 +486,7 @@ void Context::initialize() ...@@ -486,6 +486,7 @@ void Context::initialize()
mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES); mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM); mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS); mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER); mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY); mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
......
...@@ -2881,6 +2881,10 @@ void State::setImageUnit(const Context *context, ...@@ -2881,6 +2881,10 @@ void State::setImageUnit(const Context *context,
mImageUnits[unit].format = format; mImageUnits[unit].format = format;
mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS); mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS);
if (texture)
{
texture->onBindImageTexture();
}
onImageStateChange(context, unit); onImageStateChange(context, unit);
} }
......
...@@ -99,6 +99,7 @@ TextureState::TextureState(TextureType type) ...@@ -99,6 +99,7 @@ TextureState::TextureState(TextureType type)
mBaseLevel(0), mBaseLevel(0),
mMaxLevel(1000), mMaxLevel(1000),
mDepthStencilTextureMode(GL_DEPTH_COMPONENT), mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
mBoundAsImageTexture(false),
mImmutableFormat(false), mImmutableFormat(false),
mImmutableLevels(0), mImmutableLevels(0),
mUsage(GL_NONE), mUsage(GL_NONE),
...@@ -1908,4 +1909,14 @@ angle::Result Texture::getTexImage(const Context *context, ...@@ -1908,4 +1909,14 @@ angle::Result Texture::getTexImage(const Context *context,
return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type, return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
pixels); pixels);
} }
void Texture::onBindImageTexture()
{
if (!mState.mBoundAsImageTexture)
{
mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
mState.mBoundAsImageTexture = true;
}
}
} // namespace gl } // namespace gl
...@@ -190,6 +190,7 @@ class TextureState final : private angle::NonCopyable ...@@ -190,6 +190,7 @@ class TextureState final : private angle::NonCopyable
GLenum mDepthStencilTextureMode; GLenum mDepthStencilTextureMode;
bool mBoundAsImageTexture;
bool mImmutableFormat; bool mImmutableFormat;
GLuint mImmutableLevels; GLuint mImmutableLevels;
...@@ -412,6 +413,7 @@ class Texture final : public RefCountObject<TextureID>, ...@@ -412,6 +413,7 @@ class Texture final : public RefCountObject<TextureID>,
angle::Result setEGLImageTarget(Context *context, TextureType type, egl::Image *imageTarget); angle::Result setEGLImageTarget(Context *context, TextureType type, egl::Image *imageTarget);
angle::Result generateMipmap(Context *context); angle::Result generateMipmap(Context *context);
void onBindImageTexture();
egl::Surface *getBoundSurface() const; egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const; egl::Stream *getBoundStream() const;
...@@ -493,6 +495,9 @@ class Texture final : public RefCountObject<TextureID>, ...@@ -493,6 +495,9 @@ class Texture final : public RefCountObject<TextureID>,
DIRTY_BIT_MAX_LEVEL, DIRTY_BIT_MAX_LEVEL,
DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE, DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE,
// Image state
DIRTY_BIT_BOUND_AS_IMAGE,
// Misc // Misc
DIRTY_BIT_LABEL, DIRTY_BIT_LABEL,
DIRTY_BIT_USAGE, DIRTY_BIT_USAGE,
......
...@@ -1462,6 +1462,9 @@ angle::Result TextureGL::syncState(const gl::Context *context, ...@@ -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 // 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. // has local dirty bits. The real dirty bits are in mLocalDirty bits.
break; break;
case gl::Texture::DIRTY_BIT_BOUND_AS_IMAGE:
// Only used for Vulkan.
break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -322,7 +322,8 @@ class TextureVk : public TextureImpl ...@@ -322,7 +322,8 @@ class TextureVk : public TextureImpl
bool ignoreLayerCount, bool ignoreLayerCount,
uint32_t currentLayer, uint32_t currentLayer,
uint32_t sourceLevel, uint32_t sourceLevel,
uint32_t stagingDstMipLevel); uint32_t stagingDstMipLevel,
vk::BufferHelper **stagingBuffer);
angle::Result initImageViews(ContextVk *contextVk, angle::Result initImageViews(ContextVk *contextVk,
const vk::Format &format, const vk::Format &format,
const bool sized, const bool sized,
...@@ -341,9 +342,20 @@ class TextureVk : public TextureImpl ...@@ -341,9 +342,20 @@ class TextureVk : public TextureImpl
void onStagingBufferChange() { onStateChange(angle::SubjectMessage::SubjectChanged); } 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 gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
const vk::Format &getBaseLevelFormat(RendererVk *renderer) 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; bool mOwnsImage;
...@@ -380,6 +392,9 @@ class TextureVk : public TextureImpl ...@@ -380,6 +392,9 @@ class TextureVk : public TextureImpl
// Overridden in some tests. // Overridden in some tests.
size_t mStagingBufferInitialSize; size_t mStagingBufferInitialSize;
// The created vkImage usage flag.
VkImageUsageFlags mImageUsageFlags;
}; };
} // namespace rx } // namespace rx
......
...@@ -574,6 +574,10 @@ ...@@ -574,6 +574,10 @@
// Fixed in later driver versions. // Fixed in later driver versions.
2727 VULKAN ANDROID : dEQP-GLES3.functional.shaders.builtin_variable.pointcoord = FAIL 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: // Fails only with SwiftShader:
......
...@@ -3508,6 +3508,117 @@ void main() ...@@ -3508,6 +3508,117 @@ void main()
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 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, ANGLE_INSTANTIATE_TEST(ComputeShaderTest,
ES31_OPENGL(), ES31_OPENGL(),
ES31_OPENGLES(), 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