Separate entry point reflection in its own function.
This allows adding as an error context the name of the entry point, and
dedents the code a little bit.
Bug: dawn:563
Change-Id: I1ea9760fc1aca506826ca7ef5a65d40f8370136d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85500
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
diff --git a/src/dawn/native/Error.h b/src/dawn/native/Error.h
index 9e9e591..64c481f 100644
--- a/src/dawn/native/Error.h
+++ b/src/dawn/native/Error.h
@@ -130,6 +130,8 @@
// DAWN_TRY_ASSIGN is the same as DAWN_TRY for ResultOrError and assigns the success value, if
// any, to VAR.
#define DAWN_TRY_ASSIGN(VAR, EXPR) DAWN_TRY_ASSIGN_WITH_CLEANUP(VAR, EXPR, {})
+#define DAWN_TRY_ASSIGN_CONTEXT(VAR, EXPR, ...) \
+ DAWN_TRY_ASSIGN_WITH_CLEANUP(VAR, EXPR, { error->AppendContext(absl::StrFormat(__VA_ARGS__)); })
// Argument helpers are used to determine which macro implementations should be called when
// overloading with different number of variables.
diff --git a/src/dawn/native/ShaderModule.cpp b/src/dawn/native/ShaderModule.cpp
index 3beb348..afacee7 100644
--- a/src/dawn/native/ShaderModule.cpp
+++ b/src/dawn/native/ShaderModule.cpp
@@ -374,9 +374,8 @@
return EntryPointMetadata::OverridableConstant::Type::Int32;
case tint::inspector::OverridableConstant::Type::kUint32:
return EntryPointMetadata::OverridableConstant::Type::Uint32;
- default:
- UNREACHABLE();
}
+ UNREACHABLE();
}
ResultOrError<tint::Program> ParseWGSL(const tint::Source::File* file,
@@ -598,351 +597,347 @@
return {};
}
+ ResultOrError<std::unique_ptr<EntryPointMetadata>> ReflectEntryPointUsingTint(
+ const DeviceBase* device,
+ tint::inspector::Inspector* inspector,
+ const tint::inspector::EntryPoint& entryPoint) {
+ const CombinedLimits& limits = device->GetLimits();
+ constexpr uint32_t kMaxInterStageShaderLocation = kMaxInterStageShaderVariables - 1;
+
+ std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
+
+ if (!entryPoint.overridable_constants.empty()) {
+ DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
+ "Pipeline overridable constants are disallowed because they "
+ "are partially implemented.");
+
+ const auto& name2Id = inspector->GetConstantNameToIdMap();
+ const auto& id2Scalar = inspector->GetConstantIDs();
+
+ for (auto& c : entryPoint.overridable_constants) {
+ uint32_t id = name2Id.at(c.name);
+ OverridableConstantScalar defaultValue;
+ if (c.is_initialized) {
+ // if it is initialized, the scalar must exist
+ const auto& scalar = id2Scalar.at(id);
+ if (scalar.IsBool()) {
+ defaultValue.b = scalar.AsBool();
+ } else if (scalar.IsU32()) {
+ defaultValue.u32 = scalar.AsU32();
+ } else if (scalar.IsI32()) {
+ defaultValue.i32 = scalar.AsI32();
+ } else if (scalar.IsFloat()) {
+ defaultValue.f32 = scalar.AsFloat();
+ } else {
+ UNREACHABLE();
+ }
+ }
+ EntryPointMetadata::OverridableConstant constant = {
+ id, FromTintOverridableConstantType(c.type), c.is_initialized,
+ defaultValue};
+
+ std::string identifier =
+ c.is_numeric_id_specified ? std::to_string(constant.id) : c.name;
+ metadata->overridableConstants[identifier] = constant;
+
+ if (!c.is_initialized) {
+ auto [_, inserted] = metadata->uninitializedOverridableConstants.emplace(
+ std::move(identifier));
+ // The insertion should have taken place
+ ASSERT(inserted);
+ } else {
+ auto [_, inserted] = metadata->initializedOverridableConstants.emplace(
+ std::move(identifier));
+ // The insertion should have taken place
+ ASSERT(inserted);
+ }
+ }
+ }
+
+ DAWN_TRY_ASSIGN(metadata->stage, TintPipelineStageToShaderStage(entryPoint.stage));
+
+ if (metadata->stage == SingleShaderStage::Compute) {
+ DAWN_INVALID_IF(
+ entryPoint.workgroup_size_x > limits.v1.maxComputeWorkgroupSizeX ||
+ entryPoint.workgroup_size_y > limits.v1.maxComputeWorkgroupSizeY ||
+ entryPoint.workgroup_size_z > limits.v1.maxComputeWorkgroupSizeZ,
+ "Entry-point uses workgroup_size(%u, %u, %u) that exceeds the "
+ "maximum allowed (%u, %u, %u).",
+ entryPoint.workgroup_size_x, entryPoint.workgroup_size_y,
+ entryPoint.workgroup_size_z, limits.v1.maxComputeWorkgroupSizeX,
+ limits.v1.maxComputeWorkgroupSizeY, limits.v1.maxComputeWorkgroupSizeZ);
+
+ // Dimensions have already been validated against their individual limits above.
+ // Cast to uint64_t to avoid overflow in this multiplication.
+ uint64_t numInvocations = static_cast<uint64_t>(entryPoint.workgroup_size_x) *
+ entryPoint.workgroup_size_y * entryPoint.workgroup_size_z;
+ DAWN_INVALID_IF(numInvocations > limits.v1.maxComputeInvocationsPerWorkgroup,
+ "The total number of workgroup invocations (%u) exceeds the "
+ "maximum allowed (%u).",
+ numInvocations, limits.v1.maxComputeInvocationsPerWorkgroup);
+
+ const size_t workgroupStorageSize =
+ inspector->GetWorkgroupStorageSize(entryPoint.name);
+ DAWN_INVALID_IF(workgroupStorageSize > limits.v1.maxComputeWorkgroupStorageSize,
+ "The total use of workgroup storage (%u bytes) is larger than "
+ "the maximum allowed (%u bytes).",
+ workgroupStorageSize, limits.v1.maxComputeWorkgroupStorageSize);
+
+ metadata->localWorkgroupSize.x = entryPoint.workgroup_size_x;
+ metadata->localWorkgroupSize.y = entryPoint.workgroup_size_y;
+ metadata->localWorkgroupSize.z = entryPoint.workgroup_size_z;
+
+ metadata->usesNumWorkgroups = entryPoint.num_workgroups_used;
+ }
+
+ if (metadata->stage == SingleShaderStage::Vertex) {
+ for (const auto& inputVar : entryPoint.input_variables) {
+ DAWN_INVALID_IF(
+ !inputVar.has_location_decoration,
+ "Vertex input variable \"%s\" doesn't have a location decoration.",
+ inputVar.name);
+
+ uint32_t unsanitizedLocation = inputVar.location_decoration;
+ DAWN_INVALID_IF(unsanitizedLocation >= kMaxVertexAttributes,
+ "Vertex input variable \"%s\" has a location (%u) that "
+ "exceeds the maximum (%u)",
+ inputVar.name, unsanitizedLocation, kMaxVertexAttributes);
+ VertexAttributeLocation location(static_cast<uint8_t>(unsanitizedLocation));
+
+ DAWN_TRY_ASSIGN(
+ metadata->vertexInputBaseTypes[location],
+ TintComponentTypeToVertexFormatBaseType(inputVar.component_type));
+ metadata->usedVertexInputs.set(location);
+ }
+
+ // [[position]] must be declared in a vertex shader but is not exposed as an
+ // output variable by Tint so we directly add its components to the total.
+ uint32_t totalInterStageShaderComponents = 4;
+ for (const auto& outputVar : entryPoint.output_variables) {
+ DAWN_INVALID_IF(
+ !outputVar.has_location_decoration,
+ "Vertex ouput variable \"%s\" doesn't have a location decoration.",
+ outputVar.name);
+
+ uint32_t location = outputVar.location_decoration;
+ DAWN_INVALID_IF(location > kMaxInterStageShaderLocation,
+ "Vertex output variable \"%s\" has a location (%u) that "
+ "exceeds the maximum (%u).",
+ outputVar.name, location, kMaxInterStageShaderLocation);
+
+ metadata->usedInterStageVariables.set(location);
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].baseType,
+ TintComponentTypeToInterStageComponentType(outputVar.component_type));
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].componentCount,
+ TintCompositionTypeToInterStageComponentCount(outputVar.composition_type));
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].interpolationType,
+ TintInterpolationTypeToInterpolationType(outputVar.interpolation_type));
+ DAWN_TRY_ASSIGN(metadata->interStageVariables[location].interpolationSampling,
+ TintInterpolationSamplingToInterpolationSamplingType(
+ outputVar.interpolation_sampling));
+
+ totalInterStageShaderComponents +=
+ metadata->interStageVariables[location].componentCount;
+ }
+
+ DAWN_INVALID_IF(
+ totalInterStageShaderComponents > kMaxInterStageShaderComponents,
+ "Total vertex output components count (%u) exceeds the maximum (%u).",
+ totalInterStageShaderComponents, kMaxInterStageShaderComponents);
+ }
+
+ if (metadata->stage == SingleShaderStage::Fragment) {
+ uint32_t totalInterStageShaderComponents = 0;
+ for (const auto& inputVar : entryPoint.input_variables) {
+ DAWN_INVALID_IF(
+ !inputVar.has_location_decoration,
+ "Fragment input variable \"%s\" doesn't have a location decoration.",
+ inputVar.name);
+
+ uint32_t location = inputVar.location_decoration;
+ DAWN_INVALID_IF(location > kMaxInterStageShaderLocation,
+ "Fragment input variable \"%s\" has a location (%u) that "
+ "exceeds the maximum (%u).",
+ inputVar.name, location, kMaxInterStageShaderLocation);
+
+ metadata->usedInterStageVariables.set(location);
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].baseType,
+ TintComponentTypeToInterStageComponentType(inputVar.component_type));
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].componentCount,
+ TintCompositionTypeToInterStageComponentCount(inputVar.composition_type));
+ DAWN_TRY_ASSIGN(
+ metadata->interStageVariables[location].interpolationType,
+ TintInterpolationTypeToInterpolationType(inputVar.interpolation_type));
+ DAWN_TRY_ASSIGN(metadata->interStageVariables[location].interpolationSampling,
+ TintInterpolationSamplingToInterpolationSamplingType(
+ inputVar.interpolation_sampling));
+
+ totalInterStageShaderComponents +=
+ metadata->interStageVariables[location].componentCount;
+ }
+
+ if (entryPoint.front_facing_used) {
+ totalInterStageShaderComponents += 1;
+ }
+ if (entryPoint.input_sample_mask_used) {
+ totalInterStageShaderComponents += 1;
+ }
+ if (entryPoint.sample_index_used) {
+ totalInterStageShaderComponents += 1;
+ }
+ if (entryPoint.input_position_used) {
+ totalInterStageShaderComponents += 4;
+ }
+
+ DAWN_INVALID_IF(
+ totalInterStageShaderComponents > kMaxInterStageShaderComponents,
+ "Total fragment input components count (%u) exceeds the maximum (%u).",
+ totalInterStageShaderComponents, kMaxInterStageShaderComponents);
+
+ for (const auto& outputVar : entryPoint.output_variables) {
+ DAWN_INVALID_IF(
+ !outputVar.has_location_decoration,
+ "Fragment input variable \"%s\" doesn't have a location decoration.",
+ outputVar.name);
+
+ uint32_t unsanitizedAttachment = outputVar.location_decoration;
+ DAWN_INVALID_IF(unsanitizedAttachment >= kMaxColorAttachments,
+ "Fragment output variable \"%s\" has a location (%u) that "
+ "exceeds the maximum (%u).",
+ outputVar.name, unsanitizedAttachment, kMaxColorAttachments);
+ ColorAttachmentIndex attachment(static_cast<uint8_t>(unsanitizedAttachment));
+
+ DAWN_TRY_ASSIGN(
+ metadata->fragmentOutputVariables[attachment].baseType,
+ TintComponentTypeToTextureComponentType(outputVar.component_type));
+ uint32_t componentCount;
+ DAWN_TRY_ASSIGN(componentCount, TintCompositionTypeToInterStageComponentCount(
+ outputVar.composition_type));
+ // componentCount should be no larger than 4u
+ ASSERT(componentCount <= 4u);
+ metadata->fragmentOutputVariables[attachment].componentCount = componentCount;
+ metadata->fragmentOutputsWritten.set(attachment);
+ }
+ }
+
+ for (const tint::inspector::ResourceBinding& resource :
+ inspector->GetResourceBindings(entryPoint.name)) {
+ DAWN_INVALID_IF(resource.bind_group >= kMaxBindGroups,
+ "The entry-point uses a binding with a group decoration (%u) "
+ "that exceeds the maximum (%u).",
+ resource.bind_group, kMaxBindGroups);
+
+ BindingNumber bindingNumber(resource.binding);
+ BindGroupIndex bindGroupIndex(resource.bind_group);
+
+ DAWN_INVALID_IF(bindingNumber > kMaxBindingNumberTyped,
+ "Binding number (%u) exceeds the maximum binding number (%u).",
+ uint32_t(bindingNumber), uint32_t(kMaxBindingNumberTyped));
+
+ const auto& [binding, inserted] =
+ metadata->bindings[bindGroupIndex].emplace(bindingNumber, ShaderBindingInfo{});
+ DAWN_INVALID_IF(!inserted,
+ "Entry-point has a duplicate binding for (group:%u, binding:%u).",
+ resource.binding, resource.bind_group);
+
+ ShaderBindingInfo* info = &binding->second;
+ info->bindingType = TintResourceTypeToBindingInfoType(resource.resource_type);
+
+ switch (info->bindingType) {
+ case BindingInfoType::Buffer:
+ info->buffer.minBindingSize = resource.size_no_padding;
+ DAWN_TRY_ASSIGN(info->buffer.type, TintResourceTypeToBufferBindingType(
+ resource.resource_type));
+ break;
+ case BindingInfoType::Sampler:
+ switch (resource.resource_type) {
+ case tint::inspector::ResourceBinding::ResourceType::kSampler:
+ info->sampler.isComparison = false;
+ break;
+ case tint::inspector::ResourceBinding::ResourceType::kComparisonSampler:
+ info->sampler.isComparison = true;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case BindingInfoType::Texture:
+ info->texture.viewDimension =
+ TintTextureDimensionToTextureViewDimension(resource.dim);
+ if (resource.resource_type ==
+ tint::inspector::ResourceBinding::ResourceType::kDepthTexture ||
+ resource.resource_type == tint::inspector::ResourceBinding::
+ ResourceType::kDepthMultisampledTexture) {
+ info->texture.compatibleSampleTypes = SampleTypeBit::Depth;
+ } else {
+ info->texture.compatibleSampleTypes =
+ TintSampledKindToSampleTypeBit(resource.sampled_kind);
+ }
+ info->texture.multisampled =
+ resource.resource_type == tint::inspector::ResourceBinding::
+ ResourceType::kMultisampledTexture ||
+ resource.resource_type == tint::inspector::ResourceBinding::
+ ResourceType::kDepthMultisampledTexture;
+
+ break;
+ case BindingInfoType::StorageTexture:
+ DAWN_TRY_ASSIGN(
+ info->storageTexture.access,
+ TintResourceTypeToStorageTextureAccess(resource.resource_type));
+ info->storageTexture.format =
+ TintImageFormatToTextureFormat(resource.image_format);
+ info->storageTexture.viewDimension =
+ TintTextureDimensionToTextureViewDimension(resource.dim);
+
+ break;
+ case BindingInfoType::ExternalTexture:
+ break;
+ default:
+ return DAWN_VALIDATION_ERROR("Unknown binding type in Shader");
+ }
+ }
+
+ std::vector<tint::inspector::SamplerTexturePair> samplerTextureUses =
+ inspector->GetSamplerTextureUses(entryPoint.name);
+ metadata->samplerTexturePairs.reserve(samplerTextureUses.size());
+ std::transform(samplerTextureUses.begin(), samplerTextureUses.end(),
+ std::back_inserter(metadata->samplerTexturePairs),
+ [](const tint::inspector::SamplerTexturePair& pair) {
+ EntryPointMetadata::SamplerTexturePair result;
+ result.sampler = {BindGroupIndex(pair.sampler_binding_point.group),
+ BindingNumber(pair.sampler_binding_point.binding)};
+ result.texture = {BindGroupIndex(pair.texture_binding_point.group),
+ BindingNumber(pair.texture_binding_point.binding)};
+ return result;
+ });
+
+ return std::move(metadata);
+ }
+
ResultOrError<EntryPointMetadataTable> ReflectShaderUsingTint(
const DeviceBase* device,
const tint::Program* program) {
ASSERT(program->IsValid());
- const CombinedLimits& limits = device->GetLimits();
-
- EntryPointMetadataTable result;
-
tint::inspector::Inspector inspector(program);
- auto entryPoints = inspector.GetEntryPoints();
+ std::vector<tint::inspector::EntryPoint> entryPoints = inspector.GetEntryPoints();
DAWN_INVALID_IF(inspector.has_error(), "Tint Reflection failure: Inspector: %s\n",
inspector.error());
- // TODO(dawn:563): use DAWN_TRY_CONTEXT to output the name of the entry point we're
- // reflecting.
- constexpr uint32_t kMaxInterStageShaderLocation = kMaxInterStageShaderVariables - 1;
- for (auto& entryPoint : entryPoints) {
+ EntryPointMetadataTable result;
+
+ for (const tint::inspector::EntryPoint& entryPoint : entryPoints) {
+ std::unique_ptr<EntryPointMetadata> metadata;
+ DAWN_TRY_ASSIGN_CONTEXT(metadata,
+ ReflectEntryPointUsingTint(device, &inspector, entryPoint),
+ "processing entry point \"%s\".", entryPoint.name);
+
ASSERT(result.count(entryPoint.name) == 0);
-
- auto metadata = std::make_unique<EntryPointMetadata>();
-
- if (!entryPoint.overridable_constants.empty()) {
- DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
- "Pipeline overridable constants are disallowed because they "
- "are partially implemented.");
-
- const auto& name2Id = inspector.GetConstantNameToIdMap();
- const auto& id2Scalar = inspector.GetConstantIDs();
-
- for (auto& c : entryPoint.overridable_constants) {
- uint32_t id = name2Id.at(c.name);
- OverridableConstantScalar defaultValue;
- if (c.is_initialized) {
- // if it is initialized, the scalar must exist
- const auto& scalar = id2Scalar.at(id);
- if (scalar.IsBool()) {
- defaultValue.b = scalar.AsBool();
- } else if (scalar.IsU32()) {
- defaultValue.u32 = scalar.AsU32();
- } else if (scalar.IsI32()) {
- defaultValue.i32 = scalar.AsI32();
- } else if (scalar.IsFloat()) {
- defaultValue.f32 = scalar.AsFloat();
- } else {
- UNREACHABLE();
- }
- }
- EntryPointMetadata::OverridableConstant constant = {
- id, FromTintOverridableConstantType(c.type), c.is_initialized,
- defaultValue};
-
- std::string identifier =
- c.is_numeric_id_specified ? std::to_string(constant.id) : c.name;
- metadata->overridableConstants[identifier] = constant;
-
- if (!c.is_initialized) {
- auto [_, inserted] =
- metadata->uninitializedOverridableConstants.emplace(
- std::move(identifier));
- // The insertion should have taken place
- ASSERT(inserted);
- } else {
- auto [_, inserted] = metadata->initializedOverridableConstants.emplace(
- std::move(identifier));
- // The insertion should have taken place
- ASSERT(inserted);
- }
- }
- }
-
- DAWN_TRY_ASSIGN(metadata->stage, TintPipelineStageToShaderStage(entryPoint.stage));
-
- if (metadata->stage == SingleShaderStage::Compute) {
- DAWN_INVALID_IF(
- entryPoint.workgroup_size_x > limits.v1.maxComputeWorkgroupSizeX ||
- entryPoint.workgroup_size_y > limits.v1.maxComputeWorkgroupSizeY ||
- entryPoint.workgroup_size_z > limits.v1.maxComputeWorkgroupSizeZ,
- "Entry-point uses workgroup_size(%u, %u, %u) that exceeds the "
- "maximum allowed (%u, %u, %u).",
- entryPoint.workgroup_size_x, entryPoint.workgroup_size_y,
- entryPoint.workgroup_size_z, limits.v1.maxComputeWorkgroupSizeX,
- limits.v1.maxComputeWorkgroupSizeY, limits.v1.maxComputeWorkgroupSizeZ);
-
- // Dimensions have already been validated against their individual limits above.
- // Cast to uint64_t to avoid overflow in this multiplication.
- uint64_t numInvocations = static_cast<uint64_t>(entryPoint.workgroup_size_x) *
- entryPoint.workgroup_size_y *
- entryPoint.workgroup_size_z;
- DAWN_INVALID_IF(numInvocations > limits.v1.maxComputeInvocationsPerWorkgroup,
- "The total number of workgroup invocations (%u) exceeds the "
- "maximum allowed (%u).",
- numInvocations, limits.v1.maxComputeInvocationsPerWorkgroup);
-
- const size_t workgroupStorageSize =
- inspector.GetWorkgroupStorageSize(entryPoint.name);
- DAWN_INVALID_IF(workgroupStorageSize > limits.v1.maxComputeWorkgroupStorageSize,
- "The total use of workgroup storage (%u bytes) is larger than "
- "the maximum allowed (%u bytes).",
- workgroupStorageSize, limits.v1.maxComputeWorkgroupStorageSize);
-
- metadata->localWorkgroupSize.x = entryPoint.workgroup_size_x;
- metadata->localWorkgroupSize.y = entryPoint.workgroup_size_y;
- metadata->localWorkgroupSize.z = entryPoint.workgroup_size_z;
-
- metadata->usesNumWorkgroups = entryPoint.num_workgroups_used;
- }
-
- if (metadata->stage == SingleShaderStage::Vertex) {
- for (const auto& inputVar : entryPoint.input_variables) {
- DAWN_INVALID_IF(
- !inputVar.has_location_decoration,
- "Vertex input variable \"%s\" doesn't have a location decoration.",
- inputVar.name);
-
- uint32_t unsanitizedLocation = inputVar.location_decoration;
- DAWN_INVALID_IF(unsanitizedLocation >= kMaxVertexAttributes,
- "Vertex input variable \"%s\" has a location (%u) that "
- "exceeds the maximum (%u)",
- inputVar.name, unsanitizedLocation, kMaxVertexAttributes);
- VertexAttributeLocation location(static_cast<uint8_t>(unsanitizedLocation));
-
- DAWN_TRY_ASSIGN(
- metadata->vertexInputBaseTypes[location],
- TintComponentTypeToVertexFormatBaseType(inputVar.component_type));
- metadata->usedVertexInputs.set(location);
- }
-
- // [[position]] must be declared in a vertex shader but is not exposed as an
- // output variable by Tint so we directly add its components to the total.
- uint32_t totalInterStageShaderComponents = 4;
- for (const auto& outputVar : entryPoint.output_variables) {
- DAWN_INVALID_IF(
- !outputVar.has_location_decoration,
- "Vertex ouput variable \"%s\" doesn't have a location decoration.",
- outputVar.name);
-
- uint32_t location = outputVar.location_decoration;
- DAWN_INVALID_IF(location > kMaxInterStageShaderLocation,
- "Vertex output variable \"%s\" has a location (%u) that "
- "exceeds the maximum (%u).",
- outputVar.name, location, kMaxInterStageShaderLocation);
-
- metadata->usedInterStageVariables.set(location);
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].baseType,
- TintComponentTypeToInterStageComponentType(outputVar.component_type));
- DAWN_TRY_ASSIGN(metadata->interStageVariables[location].componentCount,
- TintCompositionTypeToInterStageComponentCount(
- outputVar.composition_type));
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].interpolationType,
- TintInterpolationTypeToInterpolationType(outputVar.interpolation_type));
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].interpolationSampling,
- TintInterpolationSamplingToInterpolationSamplingType(
- outputVar.interpolation_sampling));
-
- totalInterStageShaderComponents +=
- metadata->interStageVariables[location].componentCount;
- }
-
- DAWN_INVALID_IF(
- totalInterStageShaderComponents > kMaxInterStageShaderComponents,
- "Total vertex output components count (%u) exceeds the maximum (%u).",
- totalInterStageShaderComponents, kMaxInterStageShaderComponents);
- }
-
- if (metadata->stage == SingleShaderStage::Fragment) {
- uint32_t totalInterStageShaderComponents = 0;
- for (const auto& inputVar : entryPoint.input_variables) {
- DAWN_INVALID_IF(
- !inputVar.has_location_decoration,
- "Fragment input variable \"%s\" doesn't have a location decoration.",
- inputVar.name);
-
- uint32_t location = inputVar.location_decoration;
- DAWN_INVALID_IF(location > kMaxInterStageShaderLocation,
- "Fragment input variable \"%s\" has a location (%u) that "
- "exceeds the maximum (%u).",
- inputVar.name, location, kMaxInterStageShaderLocation);
-
- metadata->usedInterStageVariables.set(location);
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].baseType,
- TintComponentTypeToInterStageComponentType(inputVar.component_type));
- DAWN_TRY_ASSIGN(metadata->interStageVariables[location].componentCount,
- TintCompositionTypeToInterStageComponentCount(
- inputVar.composition_type));
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].interpolationType,
- TintInterpolationTypeToInterpolationType(inputVar.interpolation_type));
- DAWN_TRY_ASSIGN(
- metadata->interStageVariables[location].interpolationSampling,
- TintInterpolationSamplingToInterpolationSamplingType(
- inputVar.interpolation_sampling));
-
- totalInterStageShaderComponents +=
- metadata->interStageVariables[location].componentCount;
- }
-
- if (entryPoint.front_facing_used) {
- totalInterStageShaderComponents += 1;
- }
- if (entryPoint.input_sample_mask_used) {
- totalInterStageShaderComponents += 1;
- }
- if (entryPoint.sample_index_used) {
- totalInterStageShaderComponents += 1;
- }
- if (entryPoint.input_position_used) {
- totalInterStageShaderComponents += 4;
- }
-
- DAWN_INVALID_IF(
- totalInterStageShaderComponents > kMaxInterStageShaderComponents,
- "Total fragment input components count (%u) exceeds the maximum (%u).",
- totalInterStageShaderComponents, kMaxInterStageShaderComponents);
-
- for (const auto& outputVar : entryPoint.output_variables) {
- DAWN_INVALID_IF(
- !outputVar.has_location_decoration,
- "Fragment input variable \"%s\" doesn't have a location decoration.",
- outputVar.name);
-
- uint32_t unsanitizedAttachment = outputVar.location_decoration;
- DAWN_INVALID_IF(unsanitizedAttachment >= kMaxColorAttachments,
- "Fragment output variable \"%s\" has a location (%u) that "
- "exceeds the maximum (%u).",
- outputVar.name, unsanitizedAttachment,
- kMaxColorAttachments);
- ColorAttachmentIndex attachment(
- static_cast<uint8_t>(unsanitizedAttachment));
-
- DAWN_TRY_ASSIGN(
- metadata->fragmentOutputVariables[attachment].baseType,
- TintComponentTypeToTextureComponentType(outputVar.component_type));
- uint32_t componentCount;
- DAWN_TRY_ASSIGN(componentCount,
- TintCompositionTypeToInterStageComponentCount(
- outputVar.composition_type));
- // componentCount should be no larger than 4u
- ASSERT(componentCount <= 4u);
- metadata->fragmentOutputVariables[attachment].componentCount =
- componentCount;
- metadata->fragmentOutputsWritten.set(attachment);
- }
- }
-
- for (const tint::inspector::ResourceBinding& resource :
- inspector.GetResourceBindings(entryPoint.name)) {
- DAWN_INVALID_IF(resource.bind_group >= kMaxBindGroups,
- "The entry-point uses a binding with a group decoration (%u) "
- "that exceeds the maximum (%u).",
- resource.bind_group, kMaxBindGroups);
-
- BindingNumber bindingNumber(resource.binding);
- BindGroupIndex bindGroupIndex(resource.bind_group);
-
- DAWN_INVALID_IF(bindingNumber > kMaxBindingNumberTyped,
- "Binding number (%u) exceeds the maximum binding number (%u).",
- uint32_t(bindingNumber), uint32_t(kMaxBindingNumberTyped));
-
- const auto& [binding, inserted] = metadata->bindings[bindGroupIndex].emplace(
- bindingNumber, ShaderBindingInfo{});
- DAWN_INVALID_IF(
- !inserted,
- "Entry-point has a duplicate binding for (group:%u, binding:%u).",
- resource.binding, resource.bind_group);
-
- ShaderBindingInfo* info = &binding->second;
- info->bindingType = TintResourceTypeToBindingInfoType(resource.resource_type);
-
- switch (info->bindingType) {
- case BindingInfoType::Buffer:
- info->buffer.minBindingSize = resource.size_no_padding;
- DAWN_TRY_ASSIGN(info->buffer.type, TintResourceTypeToBufferBindingType(
- resource.resource_type));
- break;
- case BindingInfoType::Sampler:
- switch (resource.resource_type) {
- case tint::inspector::ResourceBinding::ResourceType::kSampler:
- info->sampler.isComparison = false;
- break;
- case tint::inspector::ResourceBinding::ResourceType::
- kComparisonSampler:
- info->sampler.isComparison = true;
- break;
- default:
- UNREACHABLE();
- }
- break;
- case BindingInfoType::Texture:
- info->texture.viewDimension =
- TintTextureDimensionToTextureViewDimension(resource.dim);
- if (resource.resource_type ==
- tint::inspector::ResourceBinding::ResourceType::kDepthTexture ||
- resource.resource_type ==
- tint::inspector::ResourceBinding::ResourceType::
- kDepthMultisampledTexture) {
- info->texture.compatibleSampleTypes = SampleTypeBit::Depth;
- } else {
- info->texture.compatibleSampleTypes =
- TintSampledKindToSampleTypeBit(resource.sampled_kind);
- }
- info->texture.multisampled =
- resource.resource_type == tint::inspector::ResourceBinding::
- ResourceType::kMultisampledTexture ||
- resource.resource_type ==
- tint::inspector::ResourceBinding::ResourceType::
- kDepthMultisampledTexture;
-
- break;
- case BindingInfoType::StorageTexture:
- DAWN_TRY_ASSIGN(
- info->storageTexture.access,
- TintResourceTypeToStorageTextureAccess(resource.resource_type));
- info->storageTexture.format =
- TintImageFormatToTextureFormat(resource.image_format);
- info->storageTexture.viewDimension =
- TintTextureDimensionToTextureViewDimension(resource.dim);
-
- break;
- case BindingInfoType::ExternalTexture:
- break;
- default:
- return DAWN_VALIDATION_ERROR("Unknown binding type in Shader");
- }
- }
-
- std::vector<tint::inspector::SamplerTexturePair> samplerTextureUses =
- inspector.GetSamplerTextureUses(entryPoint.name);
- metadata->samplerTexturePairs.reserve(samplerTextureUses.size());
- std::transform(
- samplerTextureUses.begin(), samplerTextureUses.end(),
- std::back_inserter(metadata->samplerTexturePairs),
- [](const tint::inspector::SamplerTexturePair& pair) {
- EntryPointMetadata::SamplerTexturePair result;
- result.sampler = {BindGroupIndex(pair.sampler_binding_point.group),
- BindingNumber(pair.sampler_binding_point.binding)};
- result.texture = {BindGroupIndex(pair.texture_binding_point.group),
- BindingNumber(pair.texture_binding_point.binding)};
- return result;
- });
-
result[entryPoint.name] = std::move(metadata);
}
return std::move(result);