Commit 172e5d37 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Implement universal stencil resolve

This is done by resolving stencil into a temporary buffer and copying that into the stencil aspect of the resolved image. Bug: angleproject:3200 Change-Id: I29111b44db2cb093acc4544034fbe61178f055a1 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1635709 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent ab6a59b2
...@@ -359,6 +359,10 @@ ...@@ -359,6 +359,10 @@
"69e0611ce405ee7525af2a59fe3dce02", "69e0611ce405ee7525af2a59fe3dce02",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000005.inc": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000005.inc":
"ba039e31d7c2259337f80ed6038aafd5", "ba039e31d7c2259337f80ed6038aafd5",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ResolveStencilNoExport.comp.00000000.inc":
"46e731194edd3eca95a8aeade5fea543",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/gen/ResolveStencilNoExport.comp.00000001.inc":
"5f9bbc046387b04be58dbd71988abfc2",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/BufferUtils.comp": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/BufferUtils.comp":
"0c8c050841543da0d7faca2559212aa8", "0c8c050841543da0d7faca2559212aa8",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ConvertVertex.comp":
...@@ -373,10 +377,12 @@ ...@@ -373,10 +377,12 @@
"8279b03e2a8b9a495167bf7fe2567716", "8279b03e2a8b9a495167bf7fe2567716",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ResolveDepthStencil.frag": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ResolveDepthStencil.frag":
"59a1e12ffdb34a4aacf92f96a4fe9c5a", "59a1e12ffdb34a4aacf92f96a4fe9c5a",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/shaders/src/ResolveStencilNoExport.comp":
"645d157257fd8b5315ed56cc12bc94b9",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.cpp":
"50608a69c5126b000ab57d3ea4f1ee18", "0826fbfe8c7282b0c99739f75f32f3ed",
"Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h": "Vulkan internal shader programs:src/libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h":
"719c05d2beed281df2227626a44de35f", "c2fe4b6694f433e53177ab9377e4f487",
"Vulkan internal shader programs:tools/glslang/glslang_validator.exe.sha1": "Vulkan internal shader programs:tools/glslang/glslang_validator.exe.sha1":
"9f1f0fc61116a657e065c40f9296e5ab", "9f1f0fc61116a657e065c40f9296e5ab",
"Vulkan internal shader programs:tools/glslang/glslang_validator.sha1": "Vulkan internal shader programs:tools/glslang/glslang_validator.sha1":
......
...@@ -956,8 +956,26 @@ angle::Result FramebufferVk::resolve(ContextVk *contextVk, ...@@ -956,8 +956,26 @@ angle::Result FramebufferVk::resolve(ContextVk *contextVk,
&stencilView.get(), levelIndex, 1, layerIndex, 1)); &stencilView.get(), levelIndex, 1, layerIndex, 1));
} }
ANGLE_TRY(utilsVk.depthStencilResolve(contextVk, this, depthStencilImage, &depthView.get(), // If shader stencil export is not possible, defer stencil resolve to another pass.
&stencilView.get(), params)); bool hasShaderStencilExport =
contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled;
vk::ImageView noStencilView;
// Resolve depth. If shader stencil export is present, resolve stencil as well.
if (resolveDepthBuffer || (resolveStencilBuffer && hasShaderStencilExport))
{
ANGLE_TRY(utilsVk.depthStencilResolve(
contextVk, this, depthStencilImage, &depthView.get(),
hasShaderStencilExport ? &stencilView.get() : &noStencilView, params));
}
// If shader stencil export is not present, resolve stencil through a different path.
if (resolveStencilBuffer && !hasShaderStencilExport)
{
ANGLE_TRY(utilsVk.stencilResolveNoShaderExport(contextVk, this, depthStencilImage,
&stencilView.get(), params));
}
vk::ImageView depthViewObject = depthView.release(); vk::ImageView depthViewObject = depthView.release();
vk::ImageView stencilViewObject = stencilView.release(); vk::ImageView stencilViewObject = stencilView.release();
......
...@@ -138,6 +138,11 @@ class UtilsVk : angle::NonCopyable ...@@ -138,6 +138,11 @@ class UtilsVk : angle::NonCopyable
const vk::ImageView *srcDepthView, const vk::ImageView *srcDepthView,
const vk::ImageView *srcStencilView, const vk::ImageView *srcStencilView,
const ResolveParameters &params); const ResolveParameters &params);
angle::Result stencilResolveNoShaderExport(ContextVk *contextVk,
FramebufferVk *framebuffer,
vk::ImageHelper *src,
const vk::ImageView *srcStencilView,
const ResolveParameters &params);
angle::Result copyImage(ContextVk *contextVk, angle::Result copyImage(ContextVk *contextVk,
vk::ImageHelper *dest, vk::ImageHelper *dest,
...@@ -215,7 +220,7 @@ class UtilsVk : angle::NonCopyable ...@@ -215,7 +220,7 @@ class UtilsVk : angle::NonCopyable
struct ResolveDepthStencilShaderParams struct ResolveDepthStencilShaderParams
{ {
// Structure matching PushConstants in ResolvedDepthStencil.frag // Structure matching PushConstants in ResolveDepthStencil.frag
int32_t srcExtent[2] = {}; int32_t srcExtent[2] = {};
int32_t srcOffset[2] = {}; int32_t srcOffset[2] = {};
int32_t destOffset[2] = {}; int32_t destOffset[2] = {};
...@@ -224,6 +229,18 @@ class UtilsVk : angle::NonCopyable ...@@ -224,6 +229,18 @@ class UtilsVk : angle::NonCopyable
uint32_t flipY = 0; uint32_t flipY = 0;
}; };
struct ResolveStencilNoExportShaderParams
{
// Structure matching PushConstants in ResolveStencilNoExport.comp
int32_t srcExtent[2] = {};
int32_t srcOffset[2] = {};
int32_t srcLayer = 0;
int32_t destPitch = 0;
int32_t destExtent[2] = {};
uint32_t flipX = 0;
uint32_t flipY = 0;
};
// Functions implemented by the class: // Functions implemented by the class:
enum class Function enum class Function
{ {
...@@ -234,13 +251,14 @@ class UtilsVk : angle::NonCopyable ...@@ -234,13 +251,14 @@ class UtilsVk : angle::NonCopyable
ResolveDepthStencil = 3, ResolveDepthStencil = 3,
// Functions implemented in compute // Functions implemented in compute
ComputeStartIndex = 4, // Special value to separate draw and dispatch functions. ComputeStartIndex = 4, // Special value to separate draw and dispatch functions.
BufferClear = 4, BufferClear = 4,
BufferCopy = 5, BufferCopy = 5,
ConvertVertexBuffer = 6, ConvertVertexBuffer = 6,
ResolveStencilNoExport = 7,
InvalidEnum = 7,
EnumCount = 7, InvalidEnum = 8,
EnumCount = 8,
}; };
// Common function that creates the pipeline for the specified function, binds it and prepares // Common function that creates the pipeline for the specified function, binds it and prepares
...@@ -279,6 +297,7 @@ class UtilsVk : angle::NonCopyable ...@@ -279,6 +297,7 @@ class UtilsVk : angle::NonCopyable
angle::Result ensureImageCopyResourcesInitialized(ContextVk *context); angle::Result ensureImageCopyResourcesInitialized(ContextVk *context);
angle::Result ensureResolveColorResourcesInitialized(ContextVk *context); angle::Result ensureResolveColorResourcesInitialized(ContextVk *context);
angle::Result ensureResolveDepthStencilResourcesInitialized(ContextVk *context); angle::Result ensureResolveDepthStencilResourcesInitialized(ContextVk *context);
angle::Result ensureResolveStencilNoExportResourcesInitialized(ContextVk *context);
angle::Result startRenderPass(ContextVk *contextVk, angle::Result startRenderPass(ContextVk *contextVk,
vk::ImageHelper *image, vk::ImageHelper *image,
...@@ -311,6 +330,8 @@ class UtilsVk : angle::NonCopyable ...@@ -311,6 +330,8 @@ class UtilsVk : angle::NonCopyable
vk::ShaderProgramHelper vk::ShaderProgramHelper
mResolveDepthStencilPrograms[vk::InternalShader::ResolveDepthStencil_frag::kFlagsMask | mResolveDepthStencilPrograms[vk::InternalShader::ResolveDepthStencil_frag::kFlagsMask |
vk::InternalShader::ResolveDepthStencil_frag::kResolveMask]; vk::InternalShader::ResolveDepthStencil_frag::kResolveMask];
vk::ShaderProgramHelper mResolveStencilNoExportPrograms
[vk::InternalShader::ResolveStencilNoExport_comp::kFlagsMask];
}; };
} // namespace rx } // namespace rx
......
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ResolveStencilNoExport.comp: Resolve multisampled stencil images into a buffer. This is used
// where VK_EXT_shader_stencil_export is not available, to output the resolved stencil into a
// temporary buffer, which is then copied into the stencil aspect of the final image.
#version 450 core
#extension GL_EXT_samplerless_texture_functions : require
#define MAKE_SRC_RESOURCE(prefix, type) prefix ## type
#define STENCIL_SRC_RESOURCE(type) MAKE_SRC_RESOURCE(u, type)
#if SrcIsArray
#define SRC_RESOURCE_NAME texture2DMSArray
#else
#define SRC_RESOURCE_NAME texture2DMS
#endif
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout (set = 0, binding = 0) buffer dest
{
// Note: every invocation handles 4 stencil value and output one value here.
uint destData[];
};
layout(push_constant) uniform PushConstants {
// Robust access.
ivec2 srcExtent;
// Translation from source to destination coordinates.
ivec2 srcOffset;
int srcLayer;
// Output.
int destPitch;
ivec2 destExtent;
// Flip control.
bool flipX;
bool flipY;
} params;
layout(set = 0, binding = 1) uniform STENCIL_SRC_RESOURCE(SRC_RESOURCE_NAME) stencil;
void main()
{
ivec2 destSubImageCoords = ivec2(gl_GlobalInvocationID.x * 4, gl_GlobalInvocationID.y);
if (any(lessThanEqual(params.destExtent, destSubImageCoords)))
{
return;
}
ivec2 srcSubImageCoords = destSubImageCoords;
// If flipping, srcOffset would contain the opposite coordinates, so we can
// simply reverse the direction in which x/y grows.
if (params.flipX)
srcSubImageCoords.x = -srcSubImageCoords.x;
if (params.flipY)
srcSubImageCoords.y = -srcSubImageCoords.y;
ivec2 srcImageCoords = params.srcOffset + srcSubImageCoords;
int xDir = params.flipX ? -1 : 1;
uint outStencils = 0;
// Bounds check on Y:
if (srcImageCoords.y >= 0 && srcImageCoords.y < params.srcExtent.y)
{
for (int i = 0; i < 4; ++i)
{
// Bounds check on X:
uint stencilValue = 0;
if (srcImageCoords.x >= 0 && srcImageCoords.x < params.srcExtent.x)
{
// Note: always resolve using sample 0. GLES3 gives us freedom in choosing how to resolve
// depth/stencil images.
#if SrcIsArray
stencilValue = texelFetch(stencil, ivec3(srcImageCoords, params.srcLayer), 0).x;
#else
stencilValue = texelFetch(stencil, srcImageCoords, 0).x;
#endif
#if IsBigEndian
outStencils |= (stencilValue & 0xFF) << ((3 - i) * 8);
#else
outStencils |= (stencilValue & 0xFF) << (i * 8);
#endif
}
srcImageCoords.x += xDir;
}
}
destData[gl_GlobalInvocationID.y * params.destPitch + gl_GlobalInvocationID.x] = outStencils;
}
{
"Description": [
"Copyright 2019 The ANGLE Project Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file.",
"",
"ResolveStencilNoExport.frag.comp: Build parameters for ResolveStencilNoExport.comp."
],
"Flags": [
"SrcIsArray"
]
}
...@@ -99,6 +99,8 @@ namespace ...@@ -99,6 +99,8 @@ namespace
#include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000003.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000003.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000004.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000004.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000005.inc" #include "libANGLE/renderer/vulkan/shaders/gen/ResolveDepthStencil.frag.00000005.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ResolveStencilNoExport.comp.00000000.inc"
#include "libANGLE/renderer/vulkan/shaders/gen/ResolveStencilNoExport.comp.00000001.inc"
// This is SPIR-V binary blob and the size. // This is SPIR-V binary blob and the size.
struct ShaderBlob struct ShaderBlob
...@@ -208,6 +210,10 @@ constexpr ShaderBlob kResolveDepthStencil_frag_shaders[] = { ...@@ -208,6 +210,10 @@ constexpr ShaderBlob kResolveDepthStencil_frag_shaders[] = {
{kResolveDepthStencil_frag_00000004, sizeof(kResolveDepthStencil_frag_00000004)}, {kResolveDepthStencil_frag_00000004, sizeof(kResolveDepthStencil_frag_00000004)},
{kResolveDepthStencil_frag_00000005, sizeof(kResolveDepthStencil_frag_00000005)}, {kResolveDepthStencil_frag_00000005, sizeof(kResolveDepthStencil_frag_00000005)},
}; };
constexpr ShaderBlob kResolveStencilNoExport_comp_shaders[] = {
{kResolveStencilNoExport_comp_00000000, sizeof(kResolveStencilNoExport_comp_00000000)},
{kResolveStencilNoExport_comp_00000001, sizeof(kResolveStencilNoExport_comp_00000001)},
};
angle::Result GetShader(Context *context, angle::Result GetShader(Context *context,
RefCounted<ShaderAndSerial> *shaders, RefCounted<ShaderAndSerial> *shaders,
...@@ -267,6 +273,10 @@ void ShaderLibrary::destroy(VkDevice device) ...@@ -267,6 +273,10 @@ void ShaderLibrary::destroy(VkDevice device)
{ {
shader.get().destroy(device); shader.get().destroy(device);
} }
for (RefCounted<ShaderAndSerial> &shader : mResolveStencilNoExport_comp_shaders)
{
shader.get().destroy(device);
}
} }
angle::Result ShaderLibrary::getBufferUtils_comp(Context *context, angle::Result ShaderLibrary::getBufferUtils_comp(Context *context,
...@@ -325,5 +335,14 @@ angle::Result ShaderLibrary::getResolveDepthStencil_frag(Context *context, ...@@ -325,5 +335,14 @@ angle::Result ShaderLibrary::getResolveDepthStencil_frag(Context *context,
ArraySize(kResolveDepthStencil_frag_shaders), shaderFlags, shaderOut); ArraySize(kResolveDepthStencil_frag_shaders), shaderFlags, shaderOut);
} }
angle::Result ShaderLibrary::getResolveStencilNoExport_comp(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut)
{
return GetShader(context, mResolveStencilNoExport_comp_shaders,
kResolveStencilNoExport_comp_shaders,
ArraySize(kResolveStencilNoExport_comp_shaders), shaderFlags, shaderOut);
}
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -92,4 +92,6 @@ angle_vulkan_internal_shaders = [ ...@@ -92,4 +92,6 @@ angle_vulkan_internal_shaders = [
"shaders/gen/ResolveDepthStencil.frag.00000003.inc", "shaders/gen/ResolveDepthStencil.frag.00000003.inc",
"shaders/gen/ResolveDepthStencil.frag.00000004.inc", "shaders/gen/ResolveDepthStencil.frag.00000004.inc",
"shaders/gen/ResolveDepthStencil.frag.00000005.inc", "shaders/gen/ResolveDepthStencil.frag.00000005.inc",
"shaders/gen/ResolveStencilNoExport.comp.00000000.inc",
"shaders/gen/ResolveStencilNoExport.comp.00000001.inc",
] ]
...@@ -143,6 +143,15 @@ enum Resolve ...@@ -143,6 +143,15 @@ enum Resolve
}; };
} // namespace ResolveDepthStencil_frag } // namespace ResolveDepthStencil_frag
namespace ResolveStencilNoExport_comp
{
enum flags
{
kSrcIsArray = 0x00000001,
kFlagsMask = 0x00000001,
};
} // namespace ResolveStencilNoExport_comp
} // namespace InternalShader } // namespace InternalShader
class ShaderLibrary final : angle::NonCopyable class ShaderLibrary final : angle::NonCopyable
...@@ -174,6 +183,9 @@ class ShaderLibrary final : angle::NonCopyable ...@@ -174,6 +183,9 @@ class ShaderLibrary final : angle::NonCopyable
angle::Result getResolveDepthStencil_frag(Context *context, angle::Result getResolveDepthStencil_frag(Context *context,
uint32_t shaderFlags, uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut); RefCounted<ShaderAndSerial> **shaderOut);
angle::Result getResolveStencilNoExport_comp(Context *context,
uint32_t shaderFlags,
RefCounted<ShaderAndSerial> **shaderOut);
private: private:
RefCounted<ShaderAndSerial> RefCounted<ShaderAndSerial>
...@@ -197,6 +209,8 @@ class ShaderLibrary final : angle::NonCopyable ...@@ -197,6 +209,8 @@ class ShaderLibrary final : angle::NonCopyable
RefCounted<ShaderAndSerial> RefCounted<ShaderAndSerial>
mResolveDepthStencil_frag_shaders[InternalShader::ResolveDepthStencil_frag::kFlagsMask | mResolveDepthStencil_frag_shaders[InternalShader::ResolveDepthStencil_frag::kFlagsMask |
InternalShader::ResolveDepthStencil_frag::kResolveMask]; InternalShader::ResolveDepthStencil_frag::kResolveMask];
RefCounted<ShaderAndSerial> mResolveStencilNoExport_comp_shaders
[InternalShader::ResolveStencilNoExport_comp::kFlagsMask];
}; };
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -545,15 +545,6 @@ ...@@ -545,15 +545,6 @@
3189 VULKAN : dEQP-GLES3.functional.shaders.texture_functions.* = SKIP 3189 VULKAN : dEQP-GLES3.functional.shaders.texture_functions.* = SKIP
// Multisampling: // Multisampling:
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.2_samples.depth32f_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.2_samples.depth24_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.2_samples.stencil_index8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.4_samples.depth32f_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.4_samples.depth24_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.4_samples.stencil_index8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.8_samples.depth32f_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.8_samples.depth24_stencil8 = FAIL
3200 VULKAN : dEQP-GLES3.functional.fbo.msaa.8_samples.stencil_index8 = FAIL
3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.sample_coverage_invert = FAIL 3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.sample_coverage_invert = FAIL
3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.proportionality_sample_coverage = FAIL 3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.proportionality_sample_coverage = FAIL
3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.proportionality_sample_coverage_inverted = FAIL 3204 VULKAN : dEQP-GLES3.functional.multisample.default_framebuffer.proportionality_sample_coverage_inverted = FAIL
......
...@@ -1287,10 +1287,6 @@ TEST_P(BlitFramebufferTest, MultisampleStencil) ...@@ -1287,10 +1287,6 @@ TEST_P(BlitFramebufferTest, MultisampleStencil)
// Incorrect rendering results seen on AMD Windows OpenGL. http://anglebug.com/2486 // Incorrect rendering results seen on AMD Windows OpenGL. http://anglebug.com/2486
ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsWindows()); ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && IsWindows());
// TODO(syoussefi): Multisampled stencil resolve requires workaround where
// VK_EXT_shader_stencil_export is not supported. http://anglebug.com/3200
ANGLE_SKIP_TEST_IF(IsVulkan() && !IsAMD());
GLRenderbuffer renderbuf; GLRenderbuffer renderbuf;
glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get()); glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_STENCIL_INDEX8, 256, 256); glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_STENCIL_INDEX8, 256, 256);
......
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