Commit 3fcf17e6 by Mohan Maiya Committed by Commit Bot

Vulkan: Bug fix in sRGBDecode logic

When a sampler's GL_TEXTURE_SRGB_DECODE_EXT state was toggled between GL_DECODE_EXT and GL_SKIP_DECODE_EXT VkImageViews of the TextureVk object were not being updated. Add sRGB_decode state as part of ImageViewSubresourceSerial so we retrieve the correct VkImageView from the texture cache. Bug: angleproject:3609 Tests: angle_end2end_tests --gtest_filter=SRGBTextureTestES3.SRGBDecodeSamplerParameterToggle*Vulkan Change-Id: I897e461957d408b5a5b4f03fefc05f2e9684c7b7 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2514900 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 59fbb989
...@@ -4265,7 +4265,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4265,7 +4265,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
ANGLE_TRY(textureVk->ensureMutable(this)); ANGLE_TRY(textureVk->ensureMutable(this));
} }
vk::ImageViewSubresourceSerial imageViewSerial = textureVk->getImageViewSubresourceSerial(); vk::ImageViewSubresourceSerial imageViewSerial =
textureVk->getImageViewSubresourceSerial(samplerState);
mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerHelper.getSamplerSerial()); mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerHelper.getSamplerSerial());
if (textureVk->getImage().hasImmutableSampler()) if (textureVk->getImage().hasImmutableSampler())
......
...@@ -71,8 +71,8 @@ vk::ImageViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl( ...@@ -71,8 +71,8 @@ vk::ImageViewSubresourceSerial RenderTargetVk::getSubresourceSerialImpl(
ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max()); ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max());
ASSERT(mLevelIndexGL.get() < std::numeric_limits<uint16_t>::max()); ASSERT(mLevelIndexGL.get() < std::numeric_limits<uint16_t>::max());
vk::ImageViewSubresourceSerial imageViewSerial = vk::ImageViewSubresourceSerial imageViewSerial = imageViews->getSubresourceSerial(
imageViews->getSubresourceSerial(mLevelIndexGL, 1, mLayerIndex, vk::LayerMode::Single); mLevelIndexGL, 1, mLayerIndex, vk::LayerMode::Single, vk::SrgbDecodeMode::SkipDecode);
return imageViewSerial; return imageViewSerial;
} }
......
...@@ -2631,12 +2631,18 @@ void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMe ...@@ -2631,12 +2631,18 @@ void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMe
onStateChange(angle::SubjectMessage::SubjectChanged); onStateChange(angle::SubjectMessage::SubjectChanged);
} }
vk::ImageViewSubresourceSerial TextureVk::getImageViewSubresourceSerial() const vk::ImageViewSubresourceSerial TextureVk::getImageViewSubresourceSerial(
const gl::SamplerState &samplerState) const
{ {
gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel()); gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
// getMipmapMaxLevel will clamp to the max level if it is smaller than the number of mips. // getMipmapMaxLevel will clamp to the max level if it is smaller than the number of mips.
uint32_t levelCount = gl::LevelIndex(mState.getMipmapMaxLevel()) - baseLevel + 1; uint32_t levelCount = gl::LevelIndex(mState.getMipmapMaxLevel()) - baseLevel + 1;
return getImageViews().getSubresourceSerial(baseLevel, levelCount, 0, vk::LayerMode::All); vk::SrgbDecodeMode srgbDecodeMode = (samplerState.getSRGBDecode() == GL_DECODE_EXT)
? vk::SrgbDecodeMode::SrgbDecode
: vk::SrgbDecodeMode::SkipDecode;
return getImageViews().getSubresourceSerial(baseLevel, levelCount, 0, vk::LayerMode::All,
srgbDecodeMode);
} }
angle::Result TextureVk::refreshImageViews(ContextVk *contextVk) angle::Result TextureVk::refreshImageViews(ContextVk *contextVk)
......
...@@ -199,7 +199,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -199,7 +199,8 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// Normally, initialize the image with enabled mipmap level counts. // Normally, initialize the image with enabled mipmap level counts.
angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels); angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels);
vk::ImageViewSubresourceSerial getImageViewSubresourceSerial() const; vk::ImageViewSubresourceSerial getImageViewSubresourceSerial(
const gl::SamplerState &samplerState) const;
void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting) void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)
{ {
......
...@@ -988,15 +988,16 @@ ANGLE_INLINE PipelineHelper::PipelineHelper(Pipeline &&pipeline) : mPipeline(std ...@@ -988,15 +988,16 @@ ANGLE_INLINE PipelineHelper::PipelineHelper(Pipeline &&pipeline) : mPipeline(std
struct ImageSubresourceRange struct ImageSubresourceRange
{ {
uint16_t level : 10; // GL max is 1000 (fits in 10 bits). uint16_t level : 10; // GL max is 1000 (fits in 10 bits).
uint16_t levelCount : 6; // Max 63 levels (2 ** 6 - 1). If we need more, take from layer. uint16_t levelCount : 6; // Max 63 levels (2 ** 6 - 1). If we need more, take from layer.
uint16_t layer : 15; // Implementation max is 2048 (11 bits). uint16_t layer : 14; // Implementation max is 2048 (11 bits).
uint16_t singleLayer : 1; // true/false only. Not possible to use sub-slices of levels. uint16_t singleLayer : 1; // true/false only. Not possible to use sub-slices of levels.
uint16_t srgbDecodeMode : 1; // Values from vk::SrgbDecodeMode.
}; };
static_assert(sizeof(ImageSubresourceRange) == sizeof(uint32_t), "Size mismatch"); static_assert(sizeof(ImageSubresourceRange) == sizeof(uint32_t), "Size mismatch");
constexpr ImageSubresourceRange kInvalidImageSubresourceRange = {0, 0, 0, 0}; constexpr ImageSubresourceRange kInvalidImageSubresourceRange = {0, 0, 0, 0, 0};
struct ImageViewSubresourceSerial struct ImageViewSubresourceSerial
{ {
......
...@@ -6171,10 +6171,12 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk, ...@@ -6171,10 +6171,12 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk,
imageView, levelVk, 1, layer, 1); imageView, levelVk, 1, layer, 1);
} }
ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(gl::LevelIndex levelGL, ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(
uint32_t levelCount, gl::LevelIndex levelGL,
uint32_t layer, uint32_t levelCount,
LayerMode layerMode) const uint32_t layer,
LayerMode layerMode,
SrgbDecodeMode srgbDecodeMode) const
{ {
ASSERT(mImageViewSerial.valid()); ASSERT(mImageViewSerial.valid());
...@@ -6184,6 +6186,7 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(gl::LevelIndex ...@@ -6184,6 +6186,7 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(gl::LevelIndex
SetBitField(serial.subresource.levelCount, levelCount); SetBitField(serial.subresource.levelCount, levelCount);
SetBitField(serial.subresource.layer, layer); SetBitField(serial.subresource.layer, layer);
SetBitField(serial.subresource.singleLayer, layerMode == LayerMode::Single ? 1 : 0); SetBitField(serial.subresource.singleLayer, layerMode == LayerMode::Single ? 1 : 0);
SetBitField(serial.subresource.srgbDecodeMode, srgbDecodeMode);
return serial; return serial;
} }
......
...@@ -1867,6 +1867,13 @@ enum LayerMode ...@@ -1867,6 +1867,13 @@ enum LayerMode
All All
}; };
// Sampler decode mode indicating if an attachment needs to be decoded in linear colorspace or sRGB
enum class SrgbDecodeMode
{
SkipDecode,
SrgbDecode
};
class ImageViewHelper : angle::NonCopyable class ImageViewHelper : angle::NonCopyable
{ {
public: public:
...@@ -1999,7 +2006,8 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1999,7 +2006,8 @@ class ImageViewHelper : angle::NonCopyable
ImageViewSubresourceSerial getSubresourceSerial(gl::LevelIndex levelGL, ImageViewSubresourceSerial getSubresourceSerial(gl::LevelIndex levelGL,
uint32_t levelCount, uint32_t levelCount,
uint32_t layer, uint32_t layer,
LayerMode layerMode) const; LayerMode layerMode,
SrgbDecodeMode srgbDecodeMode) const;
private: private:
ImageView &getReadImageView() ImageView &getReadImageView()
......
...@@ -470,6 +470,40 @@ TEST_P(SRGBTextureTestES3, SRGBDecodeSamplerParameter) ...@@ -470,6 +470,40 @@ TEST_P(SRGBTextureTestES3, SRGBDecodeSamplerParameter)
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0); EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
} }
// Toggle between GL_DECODE_EXT and GL_SKIP_DECODE_EXT of sampler parameter
// GL_TEXTURE_SRGB_DECODE_EXT
TEST_P(SRGBTextureTestES3, SRGBDecodeSamplerParameterToggle)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_sRGB_decode"));
GLColor linearColor = kLinearColor;
GLColor srgbColor = kNonlinearColor;
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, &linearColor);
ASSERT_GL_NO_ERROR();
GLSampler sampler;
glBindSampler(0, sampler.get());
glUseProgram(mProgram);
glUniform1i(mTextureLocation, 0);
glDisable(GL_DEPTH_TEST);
for (int i = 0; i < 4; i++)
{
// Toggle betwee decode and skip decode and verify pixel value
GLint decode = ((i & 1) == 0) ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT;
angle::GLColor &expectedColor = ((i & 1) == 0) ? srgbColor : linearColor;
glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, decode);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 1.0);
}
}
// Test that sampler state overrides texture state for srgb decode // Test that sampler state overrides texture state for srgb decode
TEST_P(SRGBTextureTestES3, SRGBDecodeTextureAndSamplerParameter) TEST_P(SRGBTextureTestES3, SRGBDecodeTextureAndSamplerParameter)
{ {
......
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