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 ...@@ -160,15 +160,21 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.maxDrawBuffers = mNativeCaps.maxDrawBuffers =
std::min(limitsVk.maxColorAttachments, limitsVk.maxFragmentOutputAttachments); std::min(limitsVk.maxColorAttachments, limitsVk.maxFragmentOutputAttachments);
mNativeCaps.maxFramebufferWidth = LimitToInt(limitsVk.maxFramebufferWidth); mNativeCaps.maxFramebufferWidth = LimitToInt(limitsVk.maxFramebufferWidth);
mNativeCaps.maxFramebufferHeight = LimitToInt(limitsVk.maxFramebufferHeight); mNativeCaps.maxFramebufferHeight = LimitToInt(limitsVk.maxFramebufferHeight);
mNativeCaps.maxColorAttachments = LimitToInt(limitsVk.maxColorAttachments); mNativeCaps.maxColorAttachments = LimitToInt(limitsVk.maxColorAttachments);
mNativeCaps.maxViewportWidth = LimitToInt(limitsVk.maxViewportDimensions[0]); mNativeCaps.maxViewportWidth = LimitToInt(limitsVk.maxViewportDimensions[0]);
mNativeCaps.maxViewportHeight = LimitToInt(limitsVk.maxViewportDimensions[1]); mNativeCaps.maxViewportHeight = LimitToInt(limitsVk.maxViewportDimensions[1]);
mNativeCaps.maxSampleMaskWords = LimitToInt(limitsVk.maxSampleMaskWords); mNativeCaps.maxSampleMaskWords = LimitToInt(limitsVk.maxSampleMaskWords);
mNativeCaps.maxColorTextureSamples = limitsVk.sampledImageColorSampleCounts; mNativeCaps.maxColorTextureSamples =
mNativeCaps.maxDepthTextureSamples = limitsVk.sampledImageDepthSampleCounts; limitsVk.sampledImageColorSampleCounts & vk_gl::kSupportedSampleCounts;
mNativeCaps.maxIntegerSamples = limitsVk.sampledImageIntegerSampleCounts; 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.maxVertexAttributes = LimitToInt(limitsVk.maxVertexInputAttributes);
mNativeCaps.maxVertexAttribBindings = LimitToInt(limitsVk.maxVertexInputBindings); mNativeCaps.maxVertexAttribBindings = LimitToInt(limitsVk.maxVertexInputBindings);
...@@ -440,9 +446,9 @@ void RendererVk::ensureCapsInitialized() const ...@@ -440,9 +446,9 @@ void RendererVk::ensureCapsInitialized() const
mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset; mNativeCaps.minProgramTexelOffset = limitsVk.minTexelOffset;
mNativeCaps.maxProgramTexelOffset = LimitToInt(limitsVk.maxTexelOffset); mNativeCaps.maxProgramTexelOffset = LimitToInt(limitsVk.maxTexelOffset);
const uint32_t sampleCounts = limitsVk.framebufferColorSampleCounts & const uint32_t sampleCounts =
limitsVk.framebufferDepthSampleCounts & limitsVk.framebufferColorSampleCounts & limitsVk.framebufferDepthSampleCounts &
limitsVk.framebufferStencilSampleCounts; limitsVk.framebufferStencilSampleCounts & vk_gl::kSupportedSampleCounts;
mNativeCaps.maxSamples = LimitToInt(vk_gl::GetMaxSampleCount(sampleCounts)); mNativeCaps.maxSamples = LimitToInt(vk_gl::GetMaxSampleCount(sampleCounts));
mNativeCaps.maxFramebufferSamples = mNativeCaps.maxSamples; mNativeCaps.maxFramebufferSamples = mNativeCaps.maxSamples;
...@@ -603,10 +609,12 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats, ...@@ -603,10 +609,12 @@ egl::ConfigSet GenerateConfigs(const GLenum *colorFormats,
const VkPhysicalDeviceLimits &limits = const VkPhysicalDeviceLimits &limits =
display->getRenderer()->getPhysicalDeviceProperties().limits; display->getRenderer()->getPhysicalDeviceProperties().limits;
const uint32_t depthStencilSampleCountsLimit = const uint32_t depthStencilSampleCountsLimit = limits.framebufferDepthSampleCounts &
limits.framebufferDepthSampleCounts & limits.framebufferStencilSampleCounts; 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); vk_gl::AddSampleCounts(depthStencilSampleCountsLimit, &depthStencilSampleCounts);
// Always support 0 samples // Always support 0 samples
......
...@@ -867,7 +867,7 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *se ...@@ -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 // 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. // 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)); setOut->insert(static_cast<GLuint>(1 << bit));
} }
...@@ -876,7 +876,7 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *se ...@@ -876,7 +876,7 @@ void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *se
GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts) GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts)
{ {
GLuint maxCount = 0; 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); maxCount = static_cast<GLuint>(1 << bit);
} }
...@@ -885,7 +885,7 @@ GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts) ...@@ -885,7 +885,7 @@ GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts)
GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount) 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); GLuint sampleCount = static_cast<GLuint>(1 << bit);
if (sampleCount >= requestedCount) if (sampleCount >= requestedCount)
......
...@@ -656,6 +656,20 @@ void GetExtentsAndLayerCount(gl::TextureType textureType, ...@@ -656,6 +656,20 @@ void GetExtentsAndLayerCount(gl::TextureType textureType,
namespace vk_gl 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. // Find set bits in sampleCounts and add the corresponding sample count to the set.
void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *outSet); void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *outSet);
// Return the maximum sample count with a bit set in |sampleCounts|. // Return the maximum sample count with a bit set in |sampleCounts|.
......
...@@ -656,21 +656,8 @@ ...@@ -656,21 +656,8 @@
// Need to support non-color when staging image updates // Need to support non-color when staging image updates
4080 ANDROID VULKAN : dEQP-GLES31.functional.stencil_texturing.misc.base_level = SKIP 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: // 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_2.sample_position = FAIL
4213 SWIFTSHADER : dEQP-GLES31.functional.texture.multisample.samples_3.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 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