Support multisampled depth texture bindings

Adds support for processing texture_depth_multisampled_2d bindings
reflected from Tint, and also removes Dawn restrictions against
multisampled depth. These restrictions were originally added in
https://dawn-review.googlesource.com/c/dawn/+/30240 to validate
against using a multisampled depth texture with a
comparison sampler. This is now disallowed by the language with
distinct binding types and builtins in WGSL. Previously with
SPIR-V, we inferred Depth if the texture was used
with a comparison sampler.

Also check Vulkan limits for supported sample counts.

Bug: dawn:1021, dawn:1030
Change-Id: I7233b16c14dc80d10a851cc4e786d5b05512b57a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/60020
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2021-07-29 08:06:07 +00:00 committed by Dawn LUCI CQ
parent 448e3ac4c2
commit d05777bd2f
5 changed files with 47 additions and 43 deletions

View File

@ -130,18 +130,8 @@ namespace dawn_native {
viewDimension = texture.viewDimension; viewDimension = texture.viewDimension;
} }
if (texture.multisampled) { if (texture.multisampled && viewDimension != wgpu::TextureViewDimension::e2D) {
if (viewDimension != wgpu::TextureViewDimension::e2D) { return DAWN_VALIDATION_ERROR("Multisampled texture bindings must be 2D.");
return DAWN_VALIDATION_ERROR("Multisampled texture bindings must be 2D.");
}
// TODO: This check should eventually become obsolete. According to the spec,
// depth can be used with both regular and comparison sampling. As such, during
// pipeline creation we have to check that if a comparison sampler is used
// with a texture, that texture must be both depth and not multisampled.
if (texture.sampleType == wgpu::TextureSampleType::Depth) {
return DAWN_VALIDATION_ERROR(
"Multisampled texture bindings must not be Depth.");
}
} }
} }
if (entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) { if (entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {

View File

@ -155,6 +155,7 @@ namespace dawn_native {
case tint::inspector::ResourceBinding::ResourceType::kSampledTexture: case tint::inspector::ResourceBinding::ResourceType::kSampledTexture:
case tint::inspector::ResourceBinding::ResourceType::kMultisampledTexture: case tint::inspector::ResourceBinding::ResourceType::kMultisampledTexture:
case tint::inspector::ResourceBinding::ResourceType::kDepthTexture: case tint::inspector::ResourceBinding::ResourceType::kDepthTexture:
case tint::inspector::ResourceBinding::ResourceType::kDepthMultisampledTexture:
return BindingInfoType::Texture; return BindingInfoType::Texture;
case tint::inspector::ResourceBinding::ResourceType::kReadOnlyStorageTexture: case tint::inspector::ResourceBinding::ResourceType::kReadOnlyStorageTexture:
case tint::inspector::ResourceBinding::ResourceType::kWriteOnlyStorageTexture: case tint::inspector::ResourceBinding::ResourceType::kWriteOnlyStorageTexture:
@ -747,10 +748,6 @@ namespace dawn_native {
SpirvBaseTypeToSampleTypeBit(textureComponentType); SpirvBaseTypeToSampleTypeBit(textureComponentType);
if (imageType.depth) { if (imageType.depth) {
if (imageType.ms) {
return DAWN_VALIDATION_ERROR(
"Multisampled depth textures aren't supported");
}
if ((info->texture.compatibleSampleTypes & SampleTypeBit::Float) == if ((info->texture.compatibleSampleTypes & SampleTypeBit::Float) ==
0) { 0) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
@ -1129,15 +1126,21 @@ namespace dawn_native {
info->texture.viewDimension = info->texture.viewDimension =
TintTextureDimensionToTextureViewDimension(resource.dim); TintTextureDimensionToTextureViewDimension(resource.dim);
if (resource.resource_type == if (resource.resource_type ==
tint::inspector::ResourceBinding::ResourceType::kDepthTexture) { tint::inspector::ResourceBinding::ResourceType::kDepthTexture ||
resource.resource_type ==
tint::inspector::ResourceBinding::ResourceType::
kDepthMultisampledTexture) {
info->texture.compatibleSampleTypes = SampleTypeBit::Depth; info->texture.compatibleSampleTypes = SampleTypeBit::Depth;
} else { } else {
info->texture.compatibleSampleTypes = info->texture.compatibleSampleTypes =
TintSampledKindToSampleTypeBit(resource.sampled_kind); TintSampledKindToSampleTypeBit(resource.sampled_kind);
} }
info->texture.multisampled = resource.resource_type == info->texture.multisampled =
tint::inspector::ResourceBinding:: resource.resource_type == tint::inspector::ResourceBinding::
ResourceType::kMultisampledTexture; ResourceType::kMultisampledTexture ||
resource.resource_type ==
tint::inspector::ResourceBinding::ResourceType::
kDepthMultisampledTexture;
break; break;
case BindingInfoType::StorageTexture: case BindingInfoType::StorageTexture:

View File

@ -223,6 +223,16 @@ namespace dawn_native { namespace vulkan {
if (limits.maxColorAttachments < kMaxColorAttachments) { if (limits.maxColorAttachments < kMaxColorAttachments) {
return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxColorAttachments"); return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxColorAttachments");
} }
if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
limits.framebufferColorSampleCounts)) {
return DAWN_INTERNAL_ERROR(
"Insufficient Vulkan limits for framebufferColorSampleCounts");
}
if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
limits.framebufferDepthSampleCounts)) {
return DAWN_INTERNAL_ERROR(
"Insufficient Vulkan limits for framebufferDepthSampleCounts");
}
// Only check maxFragmentCombinedOutputResources on mobile GPUs. Desktop GPUs drivers seem // Only check maxFragmentCombinedOutputResources on mobile GPUs. Desktop GPUs drivers seem
// to put incorrect values for this limit with things like 8 or 16 when they can do bindless // to put incorrect values for this limit with things like 8 or 16 when they can do bindless

View File

@ -50,6 +50,9 @@ class MultisampledSamplingTest : public DawnTest {
void SetUp() override { void SetUp() override {
DawnTest::SetUp(); DawnTest::SetUp();
// TODO(crbug.com/dawn/1030): Compute pipeline compilation crashes.
DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsIntel());
{ {
utils::ComboRenderPipelineDescriptor desc; utils::ComboRenderPipelineDescriptor desc;
@ -94,7 +97,7 @@ class MultisampledSamplingTest : public DawnTest {
desc.compute.entryPoint = "main"; desc.compute.entryPoint = "main";
desc.compute.module = utils::CreateShaderModule(device, R"( desc.compute.module = utils::CreateShaderModule(device, R"(
[[group(0), binding(0)]] var texture0 : texture_multisampled_2d<f32>; [[group(0), binding(0)]] var texture0 : texture_multisampled_2d<f32>;
[[group(0), binding(1)]] var texture1 : texture_multisampled_2d<f32>; [[group(0), binding(1)]] var texture1 : texture_depth_multisampled_2d;
[[block]] struct Results { [[block]] struct Results {
colorSamples : array<f32, 4>; colorSamples : array<f32, 4>;
@ -105,7 +108,7 @@ class MultisampledSamplingTest : public DawnTest {
[[stage(compute), workgroup_size(1)]] fn main() { [[stage(compute), workgroup_size(1)]] fn main() {
for (var i : i32 = 0; i < 4; i = i + 1) { for (var i : i32 = 0; i < 4; i = i + 1) {
results.colorSamples[i] = textureLoad(texture0, vec2<i32>(0, 0), i).x; results.colorSamples[i] = textureLoad(texture0, vec2<i32>(0, 0), i).x;
results.depthSamples[i] = textureLoad(texture1, vec2<i32>(0, 0), i).x; results.depthSamples[i] = textureLoad(texture1, vec2<i32>(0, 0), i);
} }
})"); })");
@ -123,6 +126,8 @@ class MultisampledSamplingTest : public DawnTest {
// must cover both the X and Y coordinates of the sample position (no false positives if // must cover both the X and Y coordinates of the sample position (no false positives if
// it covers the X position but not the Y, or vice versa). // it covers the X position but not the Y, or vice versa).
TEST_P(MultisampledSamplingTest, SamplePositions) { TEST_P(MultisampledSamplingTest, SamplePositions) {
DAWN_TEST_UNSUPPORTED_IF(!HasToggleEnabled("use_tint_generator"));
static constexpr wgpu::Extent3D kTextureSize = {1, 1, 1}; static constexpr wgpu::Extent3D kTextureSize = {1, 1, 1};
wgpu::Texture colorTexture; wgpu::Texture colorTexture;
@ -206,16 +211,12 @@ TEST_P(MultisampledSamplingTest, SamplePositions) {
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass(); wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
computePassEncoder.SetPipeline(checkSamplePipeline); computePassEncoder.SetPipeline(checkSamplePipeline);
// TODO(crbug.com/dawn/1021): Disallow using float/unfilterable-float with depth computePassEncoder.SetBindGroup(
// textures. 0, utils::MakeBindGroup(
wgpu::BindGroup bindGroup; device, checkSamplePipeline.GetBindGroupLayout(0),
EXPECT_DEPRECATION_WARNING( {{0, colorView},
bindGroup = utils::MakeBindGroup( {1, depthView},
device, checkSamplePipeline.GetBindGroupLayout(0), {2, outputBuffer, alignedResultSize * sampleOffset, kResultSize}}));
{{0, colorView},
{1, depthView},
{2, outputBuffer, alignedResultSize * sampleOffset, kResultSize}}));
computePassEncoder.SetBindGroup(0, bindGroup);
computePassEncoder.Dispatch(1); computePassEncoder.Dispatch(1);
computePassEncoder.EndPass(); computePassEncoder.EndPass();
} }

View File

@ -1348,35 +1348,35 @@ TEST_F(BindGroupLayoutValidationTest, MultisampledTextureViewDimension) {
})); }));
} }
// Test that multisampled textures cannot be DepthComparison // Test that multisampled texture bindings are valid
TEST_F(BindGroupLayoutValidationTest, MultisampledTextureComponentType) { TEST_F(BindGroupLayoutValidationTest, MultisampledTextureSampleType) {
// Multisampled float component type works. // Multisampled float sample type works.
utils::MakeBindGroupLayout(device, utils::MakeBindGroupLayout(device,
{ {
{0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Float, {0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Float,
wgpu::TextureViewDimension::e2D, true}, wgpu::TextureViewDimension::e2D, true},
}); });
// Multisampled uint component type works. // Multisampled uint sample type works.
utils::MakeBindGroupLayout(device, utils::MakeBindGroupLayout(device,
{ {
{0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Uint, {0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Uint,
wgpu::TextureViewDimension::e2D, true}, wgpu::TextureViewDimension::e2D, true},
}); });
// Multisampled sint component type works. // Multisampled sint sample type works.
utils::MakeBindGroupLayout(device, utils::MakeBindGroupLayout(device,
{ {
{0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Sint, {0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Sint,
wgpu::TextureViewDimension::e2D, true}, wgpu::TextureViewDimension::e2D, true},
}); });
// Multisampled depth comparison component typeworks. // Multisampled depth sample type works.
ASSERT_DEVICE_ERROR(utils::MakeBindGroupLayout( utils::MakeBindGroupLayout(device,
device, { {
{0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Depth, {0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Depth,
wgpu::TextureViewDimension::e2D, true}, wgpu::TextureViewDimension::e2D, true},
})); });
} }
constexpr uint64_t kBufferSize = 3 * kMinUniformBufferOffsetAlignment + 8; constexpr uint64_t kBufferSize = 3 * kMinUniformBufferOffsetAlignment + 8;