Skip to content

Commit 2ba38fc

Browse files
KangzDawn LUCI CQ
authored andcommitted
[dawn][native] Remove the ExternalTextureExpansionsMap
The last use was in ValidateCompatibilityOfSingleBindingWithLayout to know if a binding was an ExternalTexture. Instead handle external textures there as any other kind of bindings. This makes ExternalTexture correctly validated that they are in the visibility of the BGL, which wasn't the case previously (so a validation is added). As a drive-by the validation of static samplers is also fixed to check for the visibility in the BGL and that the comparisoness in the shader matches the BGL. Bug: 42240282 Change-Id: I08079a5a6351850c27313e6f69a5b10e73f2623f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/264034 Reviewed-by: Loko Kung <[email protected]> Commit-Queue: Corentin Wallez <[email protected]> Reviewed-by: Geoff Lang <[email protected]>
1 parent 01c3878 commit 2ba38fc

File tree

4 files changed

+122
-67
lines changed

4 files changed

+122
-67
lines changed

src/dawn/native/BindGroupLayoutInternal.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,6 @@ bool SortBindingsCompare(const BindingInfo& a, const BindingInfo& b) {
556556
struct ExpandedBindingInfo {
557557
BindGroupLayoutInternalBase::BindingMap apiBindingMap;
558558
ityp::vector<BindingIndex, BindingInfo> entries;
559-
ExternalTextureBindingExpansionMap externalTextureBindingExpansions;
560559
std::optional<BindingIndex> dynamicArrayMetadata;
561560
};
562561
ExpandedBindingInfo ConvertAndExpandBGLEntries(
@@ -585,7 +584,12 @@ ExpandedBindingInfo ConvertAndExpandBGLEntries(
585584

586585
// Keep track of the BindingNumbers for additional bindings for external textures, it is used
587586
// below to link the ExternalTextureBindingInfo to the BindingIndex of the additional bindings.
588-
ExternalTextureBindingExpansionMap externalTextureExpansions;
587+
struct ExternalTextureExpansion {
588+
BindingNumber plane0;
589+
BindingNumber plane1;
590+
BindingNumber params;
591+
};
592+
absl::flat_hash_map<BindingNumber, ExternalTextureExpansion> externalTextureExpansions;
589593

590594
for (uint32_t i = 0; i < descriptor->entryCount; i++) {
591595
UnpackedPtr<BindGroupLayoutEntry> entry = Unpack(&descriptor->entries[i]);
@@ -687,7 +691,6 @@ ExpandedBindingInfo ConvertAndExpandBGLEntries(
687691
}
688692

689693
result.entries = std::move(entries);
690-
result.externalTextureBindingExpansions = std::move(externalTextureExpansions);
691694
return result;
692695
}
693696

@@ -719,8 +722,6 @@ BindGroupLayoutInternalBase::BindGroupLayoutInternalBase(
719722
ApiObjectBase::UntrackedByDeviceTag tag)
720723
: ApiObjectBase(device, descriptor->label) {
721724
ExpandedBindingInfo unpackedBindings = ConvertAndExpandBGLEntries(descriptor);
722-
mExternalTextureBindingExpansionMap =
723-
std::move(unpackedBindings.externalTextureBindingExpansions);
724725
mBindingInfo = std::move(unpackedBindings.entries);
725726
mBindingMap = std::move(unpackedBindings.apiBindingMap);
726727

@@ -1055,12 +1056,6 @@ BeginEndRange<BindingIndex> BindGroupLayoutInternalBase::GetInputAttachmentIndic
10551056
GetBindingTypeEnd(BindingTypeOrder_InputAttachment));
10561057
}
10571058

1058-
const ExternalTextureBindingExpansionMap&
1059-
BindGroupLayoutInternalBase::GetExternalTextureBindingExpansionMap() const {
1060-
DAWN_ASSERT(!IsError());
1061-
return mExternalTextureBindingExpansionMap;
1062-
}
1063-
10641059
bool BindGroupLayoutInternalBase::NeedsCrossBindingValidation() const {
10651060
DAWN_ASSERT(!IsError());
10661061
return mNeedsCrossBindingValidation;

src/dawn/native/BindGroupLayoutInternal.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,6 @@
5050
#include "dawn/native/dawn_platform.h"
5151

5252
namespace dawn::native {
53-
// TODO(https://crbug.com/42240282): The expansion information is now stored in
54-
// ExternalTextureBindingInfo. Remove this structure and the map once backends transition to using
55-
// ExternalTextureBindingInfo.
56-
struct ExternalTextureBindingExpansion {
57-
BindingNumber plane0;
58-
BindingNumber plane1;
59-
BindingNumber params;
60-
};
61-
using ExternalTextureBindingExpansionMap =
62-
absl::flat_hash_map<BindingNumber, ExternalTextureBindingExpansion>;
6353

6454
ResultOrError<UnpackedPtr<BindGroupLayoutDescriptor>> ValidateBindGroupLayoutDescriptor(
6555
DeviceBase* device,
@@ -187,11 +177,6 @@ class BindGroupLayoutInternalBase : public ApiObjectBase,
187177
// used to get the stored counts.
188178
const BindingCounts& GetValidationBindingCounts() const;
189179

190-
// Used to specify unpacked external texture binding slots when transforming shader modules.
191-
// TODO(https://crbug.com/42240282): The expansion information is now stored in
192-
// ExternalTextureBindingInfo. Remove this getter once all the backends are updated to use it.
193-
const ExternalTextureBindingExpansionMap& GetExternalTextureBindingExpansionMap() const;
194-
195180
uint32_t GetUnexpandedBindingCount() const;
196181

197182
bool NeedsCrossBindingValidation() const;
@@ -256,8 +241,6 @@ class BindGroupLayoutInternalBase : public ApiObjectBase,
256241
// Map from BindGroupLayoutEntry.binding as BindingNumber to packed indices as BindingIndex.
257242
// TODO(https://issues.chromium.org/448578977): Use a more optimized map type.
258243
BindingMap mBindingMap;
259-
// Map from the BindingNumber of the ExternalTexture to the BindingNumber of the expansion.
260-
ExternalTextureBindingExpansionMap mExternalTextureBindingExpansionMap;
261244

262245
BindingCounts mValidationBindingCounts = {};
263246
bool mNeedsCrossBindingValidation = false;

src/dawn/native/ShaderModule.cpp

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -603,54 +603,30 @@ MaybeError ValidateCompatibilityOfSingleBindingWithLayout(const DeviceBase* devi
603603
SingleShaderStage entryPointStage,
604604
BindingNumber bindingNumber,
605605
const ShaderBindingInfo& shaderInfo) {
606+
// Check that the binding exists.
606607
const BindGroupLayoutInternalBase::BindingMap& layoutBindings = layout->GetBindingMap();
607608

608-
// An external texture binding found in the shader will later be expanded into multiple
609-
// bindings at compile time. This expansion will have already happened in the bgl - so
610-
// the shader and bgl will always mismatch at this point. Expansion info is contained in
611-
// the bgl object, so we can still verify the bgl used to have an external texture in
612-
// the slot corresponding to the shader reflection.
613-
if (std::holds_alternative<ExternalTextureBindingInfo>(shaderInfo.bindingInfo)) {
614-
// If an external texture binding used to exist in the bgl, it will be found as a
615-
// key in the ExternalTextureBindingExpansions map.
616-
// TODO(dawn:563): Provide info about the binding types.
617-
DAWN_INVALID_IF(!layout->GetExternalTextureBindingExpansionMap().contains(bindingNumber),
618-
"Binding type in the shader (texture_external) doesn't match the "
619-
"type in the layout.");
620-
621-
return {};
622-
}
623-
624609
const auto& bindingIt = layoutBindings.find(bindingNumber);
625610
DAWN_INVALID_IF(bindingIt == layoutBindings.end(), "Binding doesn't exist in %s.", layout);
626611

627612
APIBindingIndex bindingIndex(bindingIt->second);
628613
const BindingInfo& layoutInfo = layout->GetAPIBindingInfo(bindingIndex);
629614

630-
BindingInfoType bindingLayoutType = GetBindingInfoType(layoutInfo);
615+
// Check that it is of the same type as in the layout.
631616
BindingInfoType shaderBindingType = GetShaderBindingType(shaderInfo);
632-
633-
if (bindingLayoutType == BindingInfoType::StaticSampler) {
634-
DAWN_INVALID_IF(shaderBindingType != BindingInfoType::Sampler,
635-
"Binding type in the shader (%s) doesn't match the required type of %s for "
636-
"the %s type in the layout.",
637-
shaderBindingType, BindingInfoType::Sampler, bindingLayoutType);
638-
return {};
617+
BindingInfoType requiredType = GetBindingInfoType(layoutInfo);
618+
if (requiredType == BindingInfoType::StaticSampler) {
619+
requiredType = BindingInfoType::Sampler;
639620
}
640-
641-
DAWN_INVALID_IF(bindingLayoutType != shaderBindingType,
621+
DAWN_INVALID_IF(requiredType != shaderBindingType,
642622
"Binding type in the shader (%s) doesn't match the type in the layout (%s).",
643-
shaderBindingType, bindingLayoutType);
644-
645-
ExternalTextureBindingExpansionMap expansions = layout->GetExternalTextureBindingExpansionMap();
646-
DAWN_INVALID_IF(expansions.contains(bindingNumber),
647-
"Binding type (buffer vs. texture vs. sampler vs. external) doesn't "
648-
"match the type in the layout.");
623+
shaderBindingType, requiredType);
649624

650625
DAWN_INVALID_IF((layoutInfo.visibility & StageBit(entryPointStage)) == 0,
651626
"Entry point's stage (%s) is not in the binding visibility in the layout (%s).",
652627
StageBit(entryPointStage), layoutInfo.visibility);
653628

629+
// Check the arraySize matches the layout and that the shader has the start of the array.
654630
DAWN_INVALID_IF(layoutInfo.arraySize < shaderInfo.arraySize,
655631
"Binding type in the shader is a binding_array with %u elements but the "
656632
"layout only provides %u elements",
@@ -661,6 +637,7 @@ MaybeError ValidateCompatibilityOfSingleBindingWithLayout(const DeviceBase* devi
661637
shaderInfo.binding, layoutInfo.indexInArray,
662638
uint32_t(layoutInfo.binding) - uint32_t(layoutInfo.indexInArray));
663639

640+
// Validation specific to each type of binding.
664641
return MatchVariant(
665642
shaderInfo.bindingInfo,
666643
[&](const TextureBindingInfo& bindingInfo) -> MaybeError {
@@ -760,19 +737,26 @@ MaybeError ValidateCompatibilityOfSingleBindingWithLayout(const DeviceBase* devi
760737
return {};
761738
},
762739
[&](const SamplerBindingInfo& bindingInfo) -> MaybeError {
763-
const SamplerBindingInfo& bindingLayout =
764-
std::get<SamplerBindingInfo>(layoutInfo.bindingLayout);
740+
bool comparisonInShader = bindingInfo.type == wgpu::SamplerBindingType::Comparison;
741+
bool comparisonInLayout;
742+
if (auto* staticBindingLayout =
743+
std::get_if<StaticSamplerBindingInfo>(&layoutInfo.bindingLayout)) {
744+
comparisonInLayout = staticBindingLayout->sampler->IsComparison();
745+
} else {
746+
const SamplerBindingInfo& bindingLayout =
747+
std::get<SamplerBindingInfo>(layoutInfo.bindingLayout);
748+
comparisonInLayout = bindingLayout.type == wgpu::SamplerBindingType::Comparison;
749+
}
750+
765751
DAWN_INVALID_IF(
766-
(bindingLayout.type == wgpu::SamplerBindingType::Comparison) !=
767-
(bindingInfo.type == wgpu::SamplerBindingType::Comparison),
752+
comparisonInShader != comparisonInLayout,
768753
"The sampler type in the shader (comparison: %u) doesn't match the type in "
769754
"the layout (comparison: %u).",
770-
bindingInfo.type == wgpu::SamplerBindingType::Comparison,
771-
bindingLayout.type == wgpu::SamplerBindingType::Comparison);
755+
comparisonInShader, comparisonInLayout);
772756
return {};
773757
},
774758
[](const ExternalTextureBindingInfo&) -> MaybeError {
775-
DAWN_UNREACHABLE();
759+
// There are no other things to validate for the external textures.
776760
return {};
777761
},
778762
[&](const InputAttachmentBindingInfo& bindingInfo) -> MaybeError {

src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,80 @@ TEST_F(BindGroupLayoutWithStaticSamplersValidationTest, StaticSamplerWithArraySi
24342434
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
24352435
}
24362436

2437+
// Test that the BGL visibility of a static sampler contain the shader's stage.
2438+
TEST_F(BindGroupLayoutWithStaticSamplersValidationTest, BGLVisibilityContainsShaderStage) {
2439+
// Set up the static sampler binding but don't create the BGL yet.
2440+
wgpu::StaticSamplerBindingLayout staticSamplerBinding = {};
2441+
staticSamplerBinding.sampler = device.CreateSampler();
2442+
2443+
wgpu::BindGroupLayoutEntry binding = {};
2444+
binding.binding = 0;
2445+
binding.nextInChain = &staticSamplerBinding;
2446+
2447+
wgpu::BindGroupLayoutDescriptor desc = {};
2448+
desc.entryCount = 1;
2449+
desc.entries = &binding;
2450+
2451+
// Set up the compute pipeline but don't create it yet.
2452+
wgpu::ComputePipelineDescriptor csDesc;
2453+
csDesc.compute.module = utils::CreateShaderModule(device, R"(
2454+
@group(0) @binding(0) var s : sampler;
2455+
@compute @workgroup_size(1) fn main() {
2456+
_ = s;
2457+
}
2458+
)");
2459+
2460+
// Success case, the BGL contains compute.
2461+
binding.visibility = wgpu::ShaderStage::Compute;
2462+
wgpu::BindGroupLayout bglCompute = device.CreateBindGroupLayout(&desc);
2463+
csDesc.layout = utils::MakeBasicPipelineLayout(device, &bglCompute);
2464+
device.CreateComputePipeline(&csDesc);
2465+
2466+
// Error case, the BGL doesn't contains compute.
2467+
binding.visibility = wgpu::ShaderStage::Fragment;
2468+
wgpu::BindGroupLayout bglFragment = device.CreateBindGroupLayout(&desc);
2469+
csDesc.layout = utils::MakeBasicPipelineLayout(device, &bglFragment);
2470+
ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
2471+
}
2472+
2473+
// Test that the BGL comparisoness for static sampler must match the shader.
2474+
TEST_F(BindGroupLayoutWithStaticSamplersValidationTest, BGLComparisonessMatchesShader) {
2475+
// Set up the static sampler binding but don't create the BGL yet.
2476+
wgpu::StaticSamplerBindingLayout staticSamplerBinding = {};
2477+
2478+
wgpu::BindGroupLayoutEntry binding = {};
2479+
binding.binding = 0;
2480+
binding.visibility = wgpu::ShaderStage::Compute;
2481+
binding.nextInChain = &staticSamplerBinding;
2482+
2483+
wgpu::BindGroupLayoutDescriptor desc = {};
2484+
desc.entryCount = 1;
2485+
desc.entries = &binding;
2486+
2487+
// Set up the compute pipeline but don't create it yet.
2488+
wgpu::ComputePipelineDescriptor csDesc;
2489+
csDesc.compute.module = utils::CreateShaderModule(device, R"(
2490+
@group(0) @binding(0) var s : sampler;
2491+
@compute @workgroup_size(1) fn main() {
2492+
_ = s;
2493+
}
2494+
)");
2495+
2496+
// Success case, the BGL contains a non-comparison sampler, like the shader.
2497+
staticSamplerBinding.sampler = device.CreateSampler();
2498+
wgpu::BindGroupLayout bglCompute = device.CreateBindGroupLayout(&desc);
2499+
csDesc.layout = utils::MakeBasicPipelineLayout(device, &bglCompute);
2500+
device.CreateComputePipeline(&csDesc);
2501+
2502+
// Error case, the BGL contains a comparison sampler unlike the shader.
2503+
wgpu::SamplerDescriptor comparisonDesc = {};
2504+
comparisonDesc.compare = wgpu::CompareFunction::Never;
2505+
staticSamplerBinding.sampler = device.CreateSampler(&comparisonDesc);
2506+
wgpu::BindGroupLayout bglFragment = device.CreateBindGroupLayout(&desc);
2507+
csDesc.layout = utils::MakeBasicPipelineLayout(device, &bglFragment);
2508+
ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
2509+
}
2510+
24372511
constexpr uint32_t kBindingSize = 8;
24382512

24392513
class SetBindGroupValidationTest : public ValidationTest {
@@ -3556,6 +3630,25 @@ TEST_F(BindGroupLayoutCompatibilityTest, ExternalTextureBindGroupLayoutCompatibi
35563630
{bgl}));
35573631
}
35583632

3633+
// Test that the ExternalTexture in the BGL must have visibility that's a superset of the shader.
3634+
TEST_F(BindGroupLayoutCompatibilityTest, ExternalTextureLayoutVisibility) {
3635+
const char shader[] = R"(
3636+
@group(0) @binding(0) var myExternalTexture: texture_external;
3637+
@fragment fn main() {
3638+
_ = myExternalTexture;
3639+
})";
3640+
3641+
// Success case, visibility in the BGL contains Fragment.
3642+
wgpu::BindGroupLayout bglFragment = utils::MakeBindGroupLayout(
3643+
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
3644+
CreateFSRenderPipeline(shader, {bglFragment});
3645+
3646+
// Error case, visibility in the BGL doesn't have Fragment.
3647+
wgpu::BindGroupLayout bglCompute = utils::MakeBindGroupLayout(
3648+
device, {{0, wgpu::ShaderStage::Compute, &utils::kExternalTextureBindingLayout}});
3649+
ASSERT_DEVICE_ERROR(CreateFSRenderPipeline(shader, {bglCompute}));
3650+
}
3651+
35593652
// Test that a BGL is compatible with a pipeline if a binding's array size is at least as big as the
35603653
// shader's binding_array's size.
35613654
TEST_F(BindGroupLayoutCompatibilityTest, ArraySizeCompatibility) {

0 commit comments

Comments
 (0)