Commit abc8f277 by Ian Elliott Committed by Commit Bot

Vulkan: Disallow multisampling with a sample count of 1

GLES uses a sample count of 0 to indicate non-multisampling, and a sample count of 1 or greater to indicate multisampling.  While the Vulkan specification seems to support multisampling with a sample count of 1, the following spec language effectively disallows it (even when the underlying Vulkan driver supports it): If the image was created with VkImageCreateInfo::samples equal to VK_SAMPLE_COUNT_1_BIT, the instruction must have MS = 0. The following GLES 3.1 dEQP tests use shaders that look for the sample position, with a sample count of 1: dEQP-GLES31.functional.texture.multisample.samples_1.* For Vulkan drivers that fully support multisampling with a sample count of 1, these tests pass, but get Vulkan validation errors because of the above spec language. This was discussed in the Khronos-private issue tracker (see: https://gitlab.khronos.org/vulkan/vulkan/issues/1925).  The Vulkan working group wondered if ANGLE could live with not supporting a sample count of 1 (but upgrading such requests to the next-largest supported sample count, per the GLES specification).  This change implements that approach. Bug: angleproject:4197 Bug: angleproject:4212 Change-Id: I009ba47b48efe5af464011c7c15022fc01f45e76 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1974842Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>
parent 9d03c297
......@@ -160,15 +160,21 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.maxDrawBuffers =
std::min(limitsVk.maxColorAttachments, limitsVk.maxFragmentOutputAttachments);
mNativeCaps.maxFramebufferWidth = LimitToInt(limitsVk.maxFramebufferWidth);
mNativeCaps.maxFramebufferHeight = LimitToInt(limitsVk.maxFramebufferHeight);
mNativeCaps.maxColorAttachments = LimitToInt(limitsVk.maxColorAttachments);
mNativeCaps.maxViewportWidth = LimitToInt(limitsVk.maxViewportDimensions[0]);
mNativeCaps.maxViewportHeight = LimitToInt(limitsVk.maxViewportDimensions[1]);
mNativeCaps.maxSampleMaskWords = LimitToInt(limitsVk.maxSampleMaskWords);
mNativeCaps.maxColorTextureSamples = limitsVk.sampledImageColorSampleCounts;
mNativeCaps.maxDepthTextureSamples = limitsVk.sampledImageDepthSampleCounts;
mNativeCaps.maxIntegerSamples = limitsVk.sampledImageIntegerSampleCounts;
mNativeCaps.maxFramebufferWidth = LimitToInt(limitsVk.maxFramebufferWidth);
mNativeCaps.maxFramebufferHeight = LimitToInt(limitsVk.maxFramebufferHeight);
mNativeCaps.maxColorAttachments = LimitToInt(limitsVk.maxColorAttachments);
mNativeCaps.maxViewportWidth = LimitToInt(limitsVk.maxViewportDimensions[0]);
mNativeCaps.maxViewportHeight = LimitToInt(limitsVk.maxViewportDimensions[1]);
mNativeCaps.maxSampleMaskWords = LimitToInt(limitsVk.maxSampleMaskWords);
mNativeCaps.maxColorTextureSamples =
limitsVk.sampledImageColorSampleCounts & vk_gl::kSupportedSampleCounts;
mNativeCaps.maxDepthTextureSamples =
limitsVk.sampledImageDepthSampleCounts & vk_gl::kSupportedSampleCounts;
// TODO (ianelliott): Should mask this with vk_gl::kSupportedSampleCounts, but it causes
// end2end test failures with SwiftShader because SwiftShader returns a sample count of 1 in
// sampledImageIntegerSampleCounts.
// See: http://anglebug.com/4197
mNativeCaps.maxIntegerSamples = limitsVk.sampledImageIntegerSampleCounts;
mNativeCaps.maxVertexAttributes = LimitToInt(limitsVk.maxVertexInputAttributes);
mNativeCaps.maxVertexAttribBindings = LimitToInt(limitsVk.maxVertexInputBindings);
......@@ -440,9 +446,9 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
mNativeCaps.maxProgramTexelOffset = LimitToInt(limitsVk.maxTexelOffset);
const uint32_t sampleCounts = limitsVk.framebufferColorSampleCounts &
limitsVk.framebufferDepthSampleCounts &
limitsVk.framebufferStencilSampleCounts;
const uint32_t sampleCounts =
limitsVk.framebufferColorSampleCounts & limitsVk.framebufferDepthSampleCounts &
limitsVk.framebufferStencilSampleCounts & vk_gl::kSupportedSampleCounts;
mNativeCaps.maxSamples = LimitToInt(vk_gl::GetMaxSampleCount(sampleCounts));
mNativeCaps.maxFramebufferSamples = mNativeCaps.maxSamples;
......@@ -603,10 +609,12 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats,
const VkPhysicalDeviceLimits &limits =
display->getRenderer()->getPhysicalDeviceProperties().limits;
const uint32_t depthStencilSampleCountsLimit =
limits.framebufferDepthSampleCounts & limits.framebufferStencilSampleCounts;
const uint32_t depthStencilSampleCountsLimit = limits.framebufferDepthSampleCounts &
limits.framebufferStencilSampleCounts &
vk_gl::kSupportedSampleCounts;
vk_gl::AddSampleCounts(limits.framebufferColorSampleCounts, &colorSampleCounts);
vk_gl::AddSampleCounts(limits.framebufferColorSampleCounts & vk_gl::kSupportedSampleCounts,
&colorSampleCounts);
vk_gl::AddSampleCounts(depthStencilSampleCountsLimit, &depthStencilSampleCounts);
// Always support 0 samples
......
......@@ -867,7 +867,7 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *se
{
// The possible bits are VK_SAMPLE_COUNT_n_BIT = n, with n = 1 << b. At the time of this
// writing, b is in [0, 6], however, we test all 32 bits in case the enum is extended.
for (size_t bit : angle::BitSet32<32>(sampleCounts))
for (size_t bit : angle::BitSet32<32>(sampleCounts & kSupportedSampleCounts))
{
setOut->insert(static_cast<GLuint>(1 << bit));
}
......@@ -876,7 +876,7 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *se
GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts)
{
GLuint maxCount = 0;
for (size_t bit : angle::BitSet32<32>(sampleCounts))
for (size_t bit : angle::BitSet32<32>(sampleCounts & kSupportedSampleCounts))
{
maxCount = static_cast<GLuint>(1 << bit);
}
......@@ -885,7 +885,7 @@ GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts)
GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount)
{
for (size_t bit : angle::BitSet32<32>(supportedCounts))
for (size_t bit : angle::BitSet32<32>(supportedCounts & kSupportedSampleCounts))
{
GLuint sampleCount = static_cast<GLuint>(1 << bit);
if (sampleCount >= requestedCount)
......
......@@ -656,6 +656,20 @@ void GetExtentsAndLayerCount(gl::TextureType textureType,
namespace vk_gl
{
// The Vulkan back-end will not support a sample count of 1, because of a Vulkan specification
// restriction:
//
// If the image was created with VkImageCreateInfo::samples equal to VK_SAMPLE_COUNT_1_BIT, the
// instruction must: have MS = 0.
//
// This restriction was tracked in http://anglebug.com/4196 and Khronos-private Vulkan
// specification issue https://gitlab.khronos.org/vulkan/vulkan/issues/1925.
//
// In addition, the Vulkan back-end will not support sample counts of 32 or 64, since there are no
// standard sample locations for those sample counts.
constexpr unsigned int kSupportedSampleCounts = (VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT |
VK_SAMPLE_COUNT_8_BIT | VK_SAMPLE_COUNT_16_BIT);
// Find set bits in sampleCounts and add the corresponding sample count to the set.
void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *outSet);
// Return the maximum sample count with a bit set in |sampleCounts|.
......
......@@ -656,21 +656,8 @@
// Need to support non-color when staging image updates
4080 ANDROID VULKAN : dEQP-GLES31.functional.stencil_texturing.misc.base_level = SKIP
//// Multisampled textures:
// The following tests pass, but fail because of Vulkan validation-layer errors, which are the result
// of a Vulkan spec statement that 1-sample textures can't be used with multisample shaders.
// Issue 4197 tracks the external dependencies (Vulkan spec and validation-layer changes).
4197 VULKAN : dEQP-GLES31.functional.texture.multisample.samples_1.sample_position = FAIL
4197 VULKAN : dEQP-GLES31.functional.texture.multisample.samples_1.sample_mask* = FAIL
4197 VULKAN : dEQP-GLES31.functional.texture.multisample.samples_1.use_texture_*_2d = FAIL
4197 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_2d = FAIL
4197 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_int_2d = FAIL
4197 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.texture_size.samples_1_texture_uint_2d = FAIL
// The following tests cause an assert within SwiftShader because a sample count of 1 is used with alpha:
4212 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_1.sample_mask_and*alpha_to_coverage = SKIP
// The following are failing because of pixel/sub-pixel rendering differences than what is expected:
4213 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_1.sample_position = FAIL
4213 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_2.sample_position = FAIL
4213 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_3.sample_position = FAIL
4213 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_4.sample_position = FAIL
......
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