mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-08 06:05:55 +00:00
Make ShaderModuleBase use an internal EntryPointMetadata
WGSL and SPIR-V modules can contain multiple entrypoints, for different shader stages, that the pipelines can choose from. This is the first CL in a stack that will change Dawn internals to not rely on ShaderModules having a single entrypoint. EntryPointMetadata is introduced that will contain all reflection data for an entrypoint of a shader module. To ease review this CL doesn't introduce any functional changes and doesn't expose the EntryPointMetadata at the ShaderModuleBase interface. Instead ShaderModuleBase contains a single metadata object for its single entry point, and layout-related queries and proxied to the EntryPointMetadata object. Finally some small renames and formatting changes are done. Bug: dawn:216 Change-Id: I0f4d12a5075ba14c5e8fd666be4073d34288f6f9 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27240 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
c3e3c30b0d
commit
4f8bdaf473
@ -371,7 +371,6 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
MaybeError ValidateSpirv(DeviceBase*, const uint32_t* code, uint32_t codeSize) {
|
MaybeError ValidateSpirv(DeviceBase*, const uint32_t* code, uint32_t codeSize) {
|
||||||
spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1);
|
spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1);
|
||||||
@ -386,14 +385,16 @@ namespace dawn_native {
|
|||||||
case SPV_MSG_FATAL:
|
case SPV_MSG_FATAL:
|
||||||
case SPV_MSG_INTERNAL_ERROR:
|
case SPV_MSG_INTERNAL_ERROR:
|
||||||
case SPV_MSG_ERROR:
|
case SPV_MSG_ERROR:
|
||||||
errorStream << "error: line " << position.index << ": " << message << std::endl;
|
errorStream << "error: line " << position.index << ": " << message
|
||||||
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
case SPV_MSG_WARNING:
|
case SPV_MSG_WARNING:
|
||||||
errorStream << "warning: line " << position.index << ": " << message
|
errorStream << "warning: line " << position.index << ": " << message
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
case SPV_MSG_INFO:
|
case SPV_MSG_INFO:
|
||||||
errorStream << "info: line " << position.index << ": " << message << std::endl;
|
errorStream << "info: line " << position.index << ": " << message
|
||||||
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -547,6 +548,153 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
#endif // DAWN_ENABLE_WGSL
|
#endif // DAWN_ENABLE_WGSL
|
||||||
|
|
||||||
|
std::vector<uint64_t> GetBindGroupMinBufferSizes(
|
||||||
|
const ShaderModuleBase::BindingInfoMap& shaderBindings,
|
||||||
|
const BindGroupLayoutBase* layout) {
|
||||||
|
std::vector<uint64_t> requiredBufferSizes(layout->GetUnverifiedBufferCount());
|
||||||
|
uint32_t packedIdx = 0;
|
||||||
|
|
||||||
|
for (BindingIndex bindingIndex{0}; bindingIndex < layout->GetBufferCount();
|
||||||
|
++bindingIndex) {
|
||||||
|
const BindingInfo& bindingInfo = layout->GetBindingInfo(bindingIndex);
|
||||||
|
if (bindingInfo.minBufferBindingSize != 0) {
|
||||||
|
// Skip bindings that have minimum buffer size set in the layout
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(packedIdx < requiredBufferSizes.size());
|
||||||
|
const auto& shaderInfo = shaderBindings.find(bindingInfo.binding);
|
||||||
|
if (shaderInfo != shaderBindings.end()) {
|
||||||
|
requiredBufferSizes[packedIdx] = shaderInfo->second.minBufferBindingSize;
|
||||||
|
} else {
|
||||||
|
// We have to include buffers if they are included in the bind group's
|
||||||
|
// packed vector. We don't actually need to check these at draw time, so
|
||||||
|
// if this is a problem in the future we can optimize it further.
|
||||||
|
requiredBufferSizes[packedIdx] = 0;
|
||||||
|
}
|
||||||
|
++packedIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return requiredBufferSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeError ValidateCompatibilityWithBindGroupLayout(
|
||||||
|
BindGroupIndex group,
|
||||||
|
const ShaderModuleBase::EntryPointMetadata& entryPoint,
|
||||||
|
const BindGroupLayoutBase* layout) {
|
||||||
|
const BindGroupLayoutBase::BindingMap& layoutBindings = layout->GetBindingMap();
|
||||||
|
|
||||||
|
// Iterate over all bindings used by this group in the shader, and find the
|
||||||
|
// corresponding binding in the BindGroupLayout, if it exists.
|
||||||
|
for (const auto& it : entryPoint.bindings[group]) {
|
||||||
|
BindingNumber bindingNumber = it.first;
|
||||||
|
const ShaderModuleBase::ShaderBindingInfo& shaderInfo = it.second;
|
||||||
|
|
||||||
|
const auto& bindingIt = layoutBindings.find(bindingNumber);
|
||||||
|
if (bindingIt == layoutBindings.end()) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Missing bind group layout entry for " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
BindingIndex bindingIndex(bindingIt->second);
|
||||||
|
const BindingInfo& layoutInfo = layout->GetBindingInfo(bindingIndex);
|
||||||
|
|
||||||
|
if (layoutInfo.type != shaderInfo.type) {
|
||||||
|
// Binding mismatch between shader and bind group is invalid. For example, a
|
||||||
|
// writable binding in the shader with a readonly storage buffer in the bind
|
||||||
|
// group layout is invalid. However, a readonly binding in the shader with a
|
||||||
|
// writable storage buffer in the bind group layout is valid.
|
||||||
|
bool validBindingConversion =
|
||||||
|
layoutInfo.type == wgpu::BindingType::StorageBuffer &&
|
||||||
|
shaderInfo.type == wgpu::BindingType::ReadonlyStorageBuffer;
|
||||||
|
|
||||||
|
// TODO(crbug.com/dawn/367): Temporarily allow using either a sampler or a
|
||||||
|
// comparison sampler until we can perform the proper shader analysis of what
|
||||||
|
// type is used in the shader module.
|
||||||
|
validBindingConversion |=
|
||||||
|
(layoutInfo.type == wgpu::BindingType::Sampler &&
|
||||||
|
shaderInfo.type == wgpu::BindingType::ComparisonSampler);
|
||||||
|
validBindingConversion |=
|
||||||
|
(layoutInfo.type == wgpu::BindingType::ComparisonSampler &&
|
||||||
|
shaderInfo.type == wgpu::BindingType::Sampler);
|
||||||
|
|
||||||
|
if (!validBindingConversion) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The binding type of the bind group layout entry conflicts " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((layoutInfo.visibility & StageBit(entryPoint.stage)) == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("The bind group layout entry for " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber) +
|
||||||
|
" is not visible for the shader stage");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (layoutInfo.type) {
|
||||||
|
case wgpu::BindingType::SampledTexture: {
|
||||||
|
if (layoutInfo.textureComponentType != shaderInfo.textureComponentType) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The textureComponentType of the bind group layout entry is "
|
||||||
|
"different from " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutInfo.viewDimension != shaderInfo.viewDimension) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The viewDimension of the bind group layout entry is different "
|
||||||
|
"from " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
|
case wgpu::BindingType::WriteonlyStorageTexture: {
|
||||||
|
ASSERT(layoutInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
|
||||||
|
ASSERT(shaderInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
|
||||||
|
if (layoutInfo.storageTextureFormat != shaderInfo.storageTextureFormat) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The storageTextureFormat of the bind group layout entry is "
|
||||||
|
"different from " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
if (layoutInfo.viewDimension != shaderInfo.viewDimension) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The viewDimension of the bind group layout entry is different "
|
||||||
|
"from " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case wgpu::BindingType::UniformBuffer:
|
||||||
|
case wgpu::BindingType::ReadonlyStorageBuffer:
|
||||||
|
case wgpu::BindingType::StorageBuffer: {
|
||||||
|
if (layoutInfo.minBufferBindingSize != 0 &&
|
||||||
|
shaderInfo.minBufferBindingSize > layoutInfo.minBufferBindingSize) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The minimum buffer size of the bind group layout entry is smaller "
|
||||||
|
"than " +
|
||||||
|
GetShaderDeclarationString(group, bindingNumber));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::BindingType::Sampler:
|
||||||
|
case wgpu::BindingType::ComparisonSampler:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wgpu::BindingType::StorageTexture:
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return DAWN_VALIDATION_ERROR("Unsupported binding type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
MaybeError ValidateShaderModuleDescriptor(DeviceBase* device,
|
MaybeError ValidateShaderModuleDescriptor(DeviceBase* device,
|
||||||
const ShaderModuleDescriptor* descriptor) {
|
const ShaderModuleDescriptor* descriptor) {
|
||||||
const ChainedStruct* chainedDescriptor = descriptor->nextInChain;
|
const ChainedStruct* chainedDescriptor = descriptor->nextInChain;
|
||||||
@ -582,7 +730,45 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
} // namespace
|
}
|
||||||
|
|
||||||
|
RequiredBufferSizes ComputeRequiredBufferSizesForLayout(
|
||||||
|
const ShaderModuleBase::EntryPointMetadata& entryPoint,
|
||||||
|
const PipelineLayoutBase* layout) {
|
||||||
|
RequiredBufferSizes bufferSizes;
|
||||||
|
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||||
|
bufferSizes[group] = GetBindGroupMinBufferSizes(entryPoint.bindings[group],
|
||||||
|
layout->GetBindGroupLayout(group));
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufferSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeError ValidateCompatibilityWithPipelineLayout(
|
||||||
|
const ShaderModuleBase::EntryPointMetadata& entryPoint,
|
||||||
|
const PipelineLayoutBase* layout) {
|
||||||
|
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
||||||
|
DAWN_TRY(ValidateCompatibilityWithBindGroupLayout(group, entryPoint,
|
||||||
|
layout->GetBindGroupLayout(group)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BindGroupIndex group : IterateBitSet(~layout->GetBindGroupLayoutsMask())) {
|
||||||
|
if (entryPoint.bindings[group].size() > 0) {
|
||||||
|
std::ostringstream ostream;
|
||||||
|
ostream << "No bind group layout entry matches the declaration set "
|
||||||
|
<< static_cast<uint32_t>(group) << " in the shader module";
|
||||||
|
return DAWN_VALIDATION_ERROR(ostream.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntryPointMetadata
|
||||||
|
|
||||||
|
ShaderModuleBase::EntryPointMetadata::EntryPointMetadata() {
|
||||||
|
fragmentOutputFormatBaseTypes.fill(Format::Type::Other);
|
||||||
|
}
|
||||||
|
|
||||||
// ShaderModuleBase
|
// ShaderModuleBase
|
||||||
|
|
||||||
@ -608,7 +794,6 @@ namespace dawn_native {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
mFragmentOutputFormatBaseTypes.fill(Format::Type::Other);
|
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) {
|
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) {
|
||||||
mSpvcContext.SetUseSpvcParser(true);
|
mSpvcContext.SetUseSpvcParser(true);
|
||||||
}
|
}
|
||||||
@ -632,18 +817,22 @@ namespace dawn_native {
|
|||||||
MaybeError ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
MaybeError ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
|
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
|
||||||
DAWN_TRY(ExtractSpirvInfoWithSpvc());
|
DAWN_TRY_ASSIGN(mMainEntryPoint, ExtractSpirvInfoWithSpvc());
|
||||||
} else {
|
} else {
|
||||||
DAWN_TRY(ExtractSpirvInfoWithSpirvCross(compiler));
|
DAWN_TRY_ASSIGN(mMainEntryPoint, ExtractSpirvInfoWithSpirvCross(compiler));
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ShaderModuleBase::ExtractSpirvInfoWithSpvc() {
|
ResultOrError<std::unique_ptr<ShaderModuleBase::EntryPointMetadata>>
|
||||||
|
ShaderModuleBase::ExtractSpirvInfoWithSpvc() {
|
||||||
|
DeviceBase* device = GetDevice();
|
||||||
|
std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
|
||||||
|
|
||||||
shaderc_spvc_execution_model execution_model;
|
shaderc_spvc_execution_model execution_model;
|
||||||
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetExecutionModel(&execution_model),
|
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetExecutionModel(&execution_model),
|
||||||
"Unable to get execution model for shader."));
|
"Unable to get execution model for shader."));
|
||||||
mExecutionModel = ToSingleShaderStage(execution_model);
|
metadata->stage = ToSingleShaderStage(execution_model);
|
||||||
|
|
||||||
size_t push_constant_buffers_count;
|
size_t push_constant_buffers_count;
|
||||||
DAWN_TRY(
|
DAWN_TRY(
|
||||||
@ -658,15 +847,16 @@ namespace dawn_native {
|
|||||||
|
|
||||||
// Fill in bindingInfo with the SPIRV bindings
|
// Fill in bindingInfo with the SPIRV bindings
|
||||||
auto ExtractResourcesBinding =
|
auto ExtractResourcesBinding =
|
||||||
[this](std::vector<shaderc_spvc_binding_info> bindings) -> MaybeError {
|
[](const DeviceBase* device, const std::vector<shaderc_spvc_binding_info>& spvcBindings,
|
||||||
for (const auto& binding : bindings) {
|
ModuleBindingInfo* metadataBindings) -> MaybeError {
|
||||||
|
for (const shaderc_spvc_binding_info& binding : spvcBindings) {
|
||||||
BindGroupIndex bindGroupIndex(binding.set);
|
BindGroupIndex bindGroupIndex(binding.set);
|
||||||
|
|
||||||
if (bindGroupIndex >= kMaxBindGroupsTyped) {
|
if (bindGroupIndex >= kMaxBindGroupsTyped) {
|
||||||
return DAWN_VALIDATION_ERROR("Bind group index over limits in the SPIRV");
|
return DAWN_VALIDATION_ERROR("Bind group index over limits in the SPIRV");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& it = mBindingInfo[bindGroupIndex].emplace(
|
const auto& it = (*metadataBindings)[bindGroupIndex].emplace(
|
||||||
BindingNumber(binding.binding), ShaderBindingInfo{});
|
BindingNumber(binding.binding), ShaderBindingInfo{});
|
||||||
if (!it.second) {
|
if (!it.second) {
|
||||||
return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
|
return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
|
||||||
@ -694,8 +884,7 @@ namespace dawn_native {
|
|||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Invalid image format declaration on storage image");
|
"Invalid image format declaration on storage image");
|
||||||
}
|
}
|
||||||
const Format& format =
|
const Format& format = device->GetValidInternalFormat(storageTextureFormat);
|
||||||
GetDevice()->GetValidInternalFormat(storageTextureFormat);
|
|
||||||
if (!format.supportsStorageUsage) {
|
if (!format.supportsStorageUsage) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The storage texture format is not supported");
|
"The storage texture format is not supported");
|
||||||
@ -722,45 +911,45 @@ namespace dawn_native {
|
|||||||
shaderc_spvc_shader_resource_uniform_buffers,
|
shaderc_spvc_shader_resource_uniform_buffers,
|
||||||
shaderc_spvc_binding_type_uniform_buffer, &resource_bindings),
|
shaderc_spvc_binding_type_uniform_buffer, &resource_bindings),
|
||||||
"Unable to get binding info for uniform buffers from shader"));
|
"Unable to get binding info for uniform buffers from shader"));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resource_bindings));
|
DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
|
||||||
|
|
||||||
DAWN_TRY(CheckSpvcSuccess(
|
DAWN_TRY(CheckSpvcSuccess(
|
||||||
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_images,
|
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_images,
|
||||||
shaderc_spvc_binding_type_sampled_texture,
|
shaderc_spvc_binding_type_sampled_texture,
|
||||||
&resource_bindings),
|
&resource_bindings),
|
||||||
"Unable to get binding info for sampled textures from shader"));
|
"Unable to get binding info for sampled textures from shader"));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resource_bindings));
|
DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
|
||||||
|
|
||||||
DAWN_TRY(CheckSpvcSuccess(
|
DAWN_TRY(CheckSpvcSuccess(
|
||||||
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_samplers,
|
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_separate_samplers,
|
||||||
shaderc_spvc_binding_type_sampler, &resource_bindings),
|
shaderc_spvc_binding_type_sampler, &resource_bindings),
|
||||||
"Unable to get binding info for samples from shader"));
|
"Unable to get binding info for samples from shader"));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resource_bindings));
|
DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
|
||||||
|
|
||||||
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
|
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
|
||||||
shaderc_spvc_shader_resource_storage_buffers,
|
shaderc_spvc_shader_resource_storage_buffers,
|
||||||
shaderc_spvc_binding_type_storage_buffer, &resource_bindings),
|
shaderc_spvc_binding_type_storage_buffer, &resource_bindings),
|
||||||
"Unable to get binding info for storage buffers from shader"));
|
"Unable to get binding info for storage buffers from shader"));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resource_bindings));
|
DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
|
||||||
|
|
||||||
DAWN_TRY(CheckSpvcSuccess(
|
DAWN_TRY(CheckSpvcSuccess(
|
||||||
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_storage_images,
|
mSpvcContext.GetBindingInfo(shaderc_spvc_shader_resource_storage_images,
|
||||||
shaderc_spvc_binding_type_storage_texture,
|
shaderc_spvc_binding_type_storage_texture,
|
||||||
&resource_bindings),
|
&resource_bindings),
|
||||||
"Unable to get binding info for storage textures from shader"));
|
"Unable to get binding info for storage textures from shader"));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resource_bindings));
|
DAWN_TRY(ExtractResourcesBinding(device, resource_bindings, &metadata->bindings));
|
||||||
|
|
||||||
std::vector<shaderc_spvc_resource_location_info> input_stage_locations;
|
std::vector<shaderc_spvc_resource_location_info> input_stage_locations;
|
||||||
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetInputStageLocationInfo(&input_stage_locations),
|
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetInputStageLocationInfo(&input_stage_locations),
|
||||||
"Unable to get input stage location information from shader"));
|
"Unable to get input stage location information from shader"));
|
||||||
|
|
||||||
for (const auto& input : input_stage_locations) {
|
for (const auto& input : input_stage_locations) {
|
||||||
if (mExecutionModel == SingleShaderStage::Vertex) {
|
if (metadata->stage == SingleShaderStage::Vertex) {
|
||||||
if (input.location >= kMaxVertexAttributes) {
|
if (input.location >= kMaxVertexAttributes) {
|
||||||
return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
|
return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
|
||||||
}
|
}
|
||||||
mUsedVertexAttributes.set(input.location);
|
metadata->usedVertexAttributes.set(input.location);
|
||||||
} else if (mExecutionModel == SingleShaderStage::Fragment) {
|
} else if (metadata->stage == SingleShaderStage::Fragment) {
|
||||||
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
|
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
|
||||||
// them all the location 0, causing a compile error.
|
// them all the location 0, causing a compile error.
|
||||||
if (!input.has_location) {
|
if (!input.has_location) {
|
||||||
@ -774,13 +963,13 @@ namespace dawn_native {
|
|||||||
"Unable to get output stage location information from shader"));
|
"Unable to get output stage location information from shader"));
|
||||||
|
|
||||||
for (const auto& output : output_stage_locations) {
|
for (const auto& output : output_stage_locations) {
|
||||||
if (mExecutionModel == SingleShaderStage::Vertex) {
|
if (metadata->stage == SingleShaderStage::Vertex) {
|
||||||
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL
|
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL
|
||||||
// gives them all the location 0, causing a compile error.
|
// gives them all the location 0, causing a compile error.
|
||||||
if (!output.has_location) {
|
if (!output.has_location) {
|
||||||
return DAWN_VALIDATION_ERROR("Need location qualifier on vertex output");
|
return DAWN_VALIDATION_ERROR("Need location qualifier on vertex output");
|
||||||
}
|
}
|
||||||
} else if (mExecutionModel == SingleShaderStage::Fragment) {
|
} else if (metadata->stage == SingleShaderStage::Fragment) {
|
||||||
if (output.location >= kMaxColorAttachments) {
|
if (output.location >= kMaxColorAttachments) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Fragment output location over limits in the SPIRV");
|
"Fragment output location over limits in the SPIRV");
|
||||||
@ -788,7 +977,7 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExecutionModel == SingleShaderStage::Fragment) {
|
if (metadata->stage == SingleShaderStage::Fragment) {
|
||||||
std::vector<shaderc_spvc_resource_type_info> output_types;
|
std::vector<shaderc_spvc_resource_type_info> output_types;
|
||||||
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetOutputStageTypeInfo(&output_types),
|
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetOutputStageTypeInfo(&output_types),
|
||||||
"Unable to get output stage type information from shader"));
|
"Unable to get output stage type information from shader"));
|
||||||
@ -797,27 +986,32 @@ namespace dawn_native {
|
|||||||
if (output.type == shaderc_spvc_texture_format_type_other) {
|
if (output.type == shaderc_spvc_texture_format_type_other) {
|
||||||
return DAWN_VALIDATION_ERROR("Unexpected Fragment output type");
|
return DAWN_VALIDATION_ERROR("Unexpected Fragment output type");
|
||||||
}
|
}
|
||||||
mFragmentOutputFormatBaseTypes[output.location] = ToDawnFormatType(output.type);
|
metadata->fragmentOutputFormatBaseTypes[output.location] =
|
||||||
|
ToDawnFormatType(output.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ShaderModuleBase::ExtractSpirvInfoWithSpirvCross(
|
return {std::move(metadata)};
|
||||||
const spirv_cross::Compiler& compiler) {
|
}
|
||||||
|
|
||||||
|
ResultOrError<std::unique_ptr<ShaderModuleBase::EntryPointMetadata>>
|
||||||
|
ShaderModuleBase::ExtractSpirvInfoWithSpirvCross(const spirv_cross::Compiler& compiler) {
|
||||||
|
DeviceBase* device = GetDevice();
|
||||||
|
std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): make errors here creation errors
|
// TODO(cwallez@chromium.org): make errors here creation errors
|
||||||
// currently errors here do not prevent the shadermodule from being used
|
// currently errors here do not prevent the shadermodule from being used
|
||||||
const auto& resources = compiler.get_shader_resources();
|
const auto& resources = compiler.get_shader_resources();
|
||||||
|
|
||||||
switch (compiler.get_execution_model()) {
|
switch (compiler.get_execution_model()) {
|
||||||
case spv::ExecutionModelVertex:
|
case spv::ExecutionModelVertex:
|
||||||
mExecutionModel = SingleShaderStage::Vertex;
|
metadata->stage = SingleShaderStage::Vertex;
|
||||||
break;
|
break;
|
||||||
case spv::ExecutionModelFragment:
|
case spv::ExecutionModelFragment:
|
||||||
mExecutionModel = SingleShaderStage::Fragment;
|
metadata->stage = SingleShaderStage::Fragment;
|
||||||
break;
|
break;
|
||||||
case spv::ExecutionModelGLCompute:
|
case spv::ExecutionModelGLCompute:
|
||||||
mExecutionModel = SingleShaderStage::Compute;
|
metadata->stage = SingleShaderStage::Compute;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -834,9 +1028,10 @@ namespace dawn_native {
|
|||||||
|
|
||||||
// Fill in bindingInfo with the SPIRV bindings
|
// Fill in bindingInfo with the SPIRV bindings
|
||||||
auto ExtractResourcesBinding =
|
auto ExtractResourcesBinding =
|
||||||
[this](const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
|
[](const DeviceBase* device,
|
||||||
const spirv_cross::Compiler& compiler,
|
const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
|
||||||
wgpu::BindingType bindingType) -> MaybeError {
|
const spirv_cross::Compiler& compiler, wgpu::BindingType bindingType,
|
||||||
|
ModuleBindingInfo* metadataBindings) -> MaybeError {
|
||||||
for (const auto& resource : resources) {
|
for (const auto& resource : resources) {
|
||||||
if (!compiler.get_decoration_bitset(resource.id).get(spv::DecorationBinding)) {
|
if (!compiler.get_decoration_bitset(resource.id).get(spv::DecorationBinding)) {
|
||||||
return DAWN_VALIDATION_ERROR("No Binding decoration set for resource");
|
return DAWN_VALIDATION_ERROR("No Binding decoration set for resource");
|
||||||
@ -857,7 +1052,7 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto& it =
|
const auto& it =
|
||||||
mBindingInfo[bindGroupIndex].emplace(bindingNumber, ShaderBindingInfo{});
|
(*metadataBindings)[bindGroupIndex].emplace(bindingNumber, ShaderBindingInfo{});
|
||||||
if (!it.second) {
|
if (!it.second) {
|
||||||
return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
|
return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
|
||||||
}
|
}
|
||||||
@ -919,8 +1114,7 @@ namespace dawn_native {
|
|||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Invalid image format declaration on storage image");
|
"Invalid image format declaration on storage image");
|
||||||
}
|
}
|
||||||
const Format& format =
|
const Format& format = device->GetValidInternalFormat(storageTextureFormat);
|
||||||
GetDevice()->GetValidInternalFormat(storageTextureFormat);
|
|
||||||
if (!format.supportsStorageUsage) {
|
if (!format.supportsStorageUsage) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The storage texture format is not supported");
|
"The storage texture format is not supported");
|
||||||
@ -938,19 +1132,19 @@ namespace dawn_native {
|
|||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
DAWN_TRY(ExtractResourcesBinding(resources.uniform_buffers, compiler,
|
DAWN_TRY(ExtractResourcesBinding(device, resources.uniform_buffers, compiler,
|
||||||
wgpu::BindingType::UniformBuffer));
|
wgpu::BindingType::UniformBuffer, &metadata->bindings));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resources.separate_images, compiler,
|
DAWN_TRY(ExtractResourcesBinding(device, resources.separate_images, compiler,
|
||||||
wgpu::BindingType::SampledTexture));
|
wgpu::BindingType::SampledTexture, &metadata->bindings));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resources.separate_samplers, compiler,
|
DAWN_TRY(ExtractResourcesBinding(device, resources.separate_samplers, compiler,
|
||||||
wgpu::BindingType::Sampler));
|
wgpu::BindingType::Sampler, &metadata->bindings));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resources.storage_buffers, compiler,
|
DAWN_TRY(ExtractResourcesBinding(device, resources.storage_buffers, compiler,
|
||||||
wgpu::BindingType::StorageBuffer));
|
wgpu::BindingType::StorageBuffer, &metadata->bindings));
|
||||||
DAWN_TRY(ExtractResourcesBinding(resources.storage_images, compiler,
|
DAWN_TRY(ExtractResourcesBinding(device, resources.storage_images, compiler,
|
||||||
wgpu::BindingType::StorageTexture));
|
wgpu::BindingType::StorageTexture, &metadata->bindings));
|
||||||
|
|
||||||
// Extract the vertex attributes
|
// Extract the vertex attributes
|
||||||
if (mExecutionModel == SingleShaderStage::Vertex) {
|
if (metadata->stage == SingleShaderStage::Vertex) {
|
||||||
for (const auto& attrib : resources.stage_inputs) {
|
for (const auto& attrib : resources.stage_inputs) {
|
||||||
if (!(compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation))) {
|
if (!(compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation))) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
@ -962,7 +1156,7 @@ namespace dawn_native {
|
|||||||
return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
|
return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
|
||||||
}
|
}
|
||||||
|
|
||||||
mUsedVertexAttributes.set(location);
|
metadata->usedVertexAttributes.set(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives
|
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives
|
||||||
@ -974,7 +1168,7 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExecutionModel == SingleShaderStage::Fragment) {
|
if (metadata->stage == SingleShaderStage::Fragment) {
|
||||||
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
|
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
|
||||||
// them all the location 0, causing a compile error.
|
// them all the location 0, causing a compile error.
|
||||||
for (const auto& attrib : resources.stage_inputs) {
|
for (const auto& attrib : resources.stage_inputs) {
|
||||||
@ -1003,209 +1197,44 @@ namespace dawn_native {
|
|||||||
if (formatType == Format::Type::Other) {
|
if (formatType == Format::Type::Other) {
|
||||||
return DAWN_VALIDATION_ERROR("Unexpected Fragment output type");
|
return DAWN_VALIDATION_ERROR("Unexpected Fragment output type");
|
||||||
}
|
}
|
||||||
mFragmentOutputFormatBaseTypes[location] = formatType;
|
metadata->fragmentOutputFormatBaseTypes[location] = formatType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
|
return {std::move(metadata)};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
|
const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mBindingInfo;
|
return mMainEntryPoint->bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
|
const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mUsedVertexAttributes;
|
return mMainEntryPoint->usedVertexAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShaderModuleBase::FragmentOutputBaseTypes& ShaderModuleBase::GetFragmentOutputBaseTypes()
|
const ShaderModuleBase::FragmentOutputBaseTypes& ShaderModuleBase::GetFragmentOutputBaseTypes()
|
||||||
const {
|
const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mFragmentOutputFormatBaseTypes;
|
return mMainEntryPoint->fragmentOutputFormatBaseTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleShaderStage ShaderModuleBase::GetExecutionModel() const {
|
SingleShaderStage ShaderModuleBase::GetExecutionModel() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mExecutionModel;
|
return mMainEntryPoint->stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequiredBufferSizes ShaderModuleBase::ComputeRequiredBufferSizesForLayout(
|
RequiredBufferSizes ShaderModuleBase::ComputeRequiredBufferSizesForLayout(
|
||||||
const PipelineLayoutBase* layout) const {
|
const PipelineLayoutBase* layout) const {
|
||||||
RequiredBufferSizes bufferSizes;
|
ASSERT(!IsError());
|
||||||
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
return ::dawn_native::ComputeRequiredBufferSizesForLayout(*mMainEntryPoint, layout);
|
||||||
bufferSizes[group] =
|
|
||||||
GetBindGroupMinBufferSizes(mBindingInfo[group], layout->GetBindGroupLayout(group));
|
|
||||||
}
|
|
||||||
|
|
||||||
return bufferSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint64_t> ShaderModuleBase::GetBindGroupMinBufferSizes(
|
|
||||||
const BindingInfoMap& shaderMap,
|
|
||||||
const BindGroupLayoutBase* layout) const {
|
|
||||||
std::vector<uint64_t> requiredBufferSizes(layout->GetUnverifiedBufferCount());
|
|
||||||
uint32_t packedIdx = 0;
|
|
||||||
|
|
||||||
for (BindingIndex bindingIndex{0}; bindingIndex < layout->GetBufferCount();
|
|
||||||
++bindingIndex) {
|
|
||||||
const BindingInfo& bindingInfo = layout->GetBindingInfo(bindingIndex);
|
|
||||||
if (bindingInfo.minBufferBindingSize != 0) {
|
|
||||||
// Skip bindings that have minimum buffer size set in the layout
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(packedIdx < requiredBufferSizes.size());
|
|
||||||
const auto& shaderInfo = shaderMap.find(bindingInfo.binding);
|
|
||||||
if (shaderInfo != shaderMap.end()) {
|
|
||||||
requiredBufferSizes[packedIdx] = shaderInfo->second.minBufferBindingSize;
|
|
||||||
} else {
|
|
||||||
// We have to include buffers if they are included in the bind group's
|
|
||||||
// packed vector. We don't actually need to check these at draw time, so
|
|
||||||
// if this is a problem in the future we can optimize it further.
|
|
||||||
requiredBufferSizes[packedIdx] = 0;
|
|
||||||
}
|
|
||||||
++packedIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return requiredBufferSizes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ShaderModuleBase::ValidateCompatibilityWithPipelineLayout(
|
MaybeError ShaderModuleBase::ValidateCompatibilityWithPipelineLayout(
|
||||||
const PipelineLayoutBase* layout) const {
|
const PipelineLayoutBase* layout) const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
|
return ::dawn_native::ValidateCompatibilityWithPipelineLayout(*mMainEntryPoint, layout);
|
||||||
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
|
||||||
DAWN_TRY(
|
|
||||||
ValidateCompatibilityWithBindGroupLayout(group, layout->GetBindGroupLayout(group)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BindGroupIndex group : IterateBitSet(~layout->GetBindGroupLayoutsMask())) {
|
|
||||||
if (mBindingInfo[group].size() > 0) {
|
|
||||||
std::ostringstream ostream;
|
|
||||||
ostream << "No bind group layout entry matches the declaration set "
|
|
||||||
<< static_cast<uint32_t>(group) << " in the shader module";
|
|
||||||
return DAWN_VALIDATION_ERROR(ostream.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ShaderModuleBase::ValidateCompatibilityWithBindGroupLayout(
|
|
||||||
BindGroupIndex group,
|
|
||||||
const BindGroupLayoutBase* layout) const {
|
|
||||||
ASSERT(!IsError());
|
|
||||||
|
|
||||||
const BindGroupLayoutBase::BindingMap& bindingMap = layout->GetBindingMap();
|
|
||||||
|
|
||||||
// Iterate over all bindings used by this group in the shader, and find the
|
|
||||||
// corresponding binding in the BindGroupLayout, if it exists.
|
|
||||||
for (const auto& it : mBindingInfo[group]) {
|
|
||||||
BindingNumber bindingNumber = it.first;
|
|
||||||
const ShaderBindingInfo& moduleInfo = it.second;
|
|
||||||
|
|
||||||
const auto& bindingIt = bindingMap.find(bindingNumber);
|
|
||||||
if (bindingIt == bindingMap.end()) {
|
|
||||||
return DAWN_VALIDATION_ERROR("Missing bind group layout entry for " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
BindingIndex bindingIndex(bindingIt->second);
|
|
||||||
|
|
||||||
const BindingInfo& bindingInfo = layout->GetBindingInfo(bindingIndex);
|
|
||||||
|
|
||||||
if (bindingInfo.type != moduleInfo.type) {
|
|
||||||
// Binding mismatch between shader and bind group is invalid. For example, a
|
|
||||||
// writable binding in the shader with a readonly storage buffer in the bind group
|
|
||||||
// layout is invalid. However, a readonly binding in the shader with a writable
|
|
||||||
// storage buffer in the bind group layout is valid.
|
|
||||||
bool validBindingConversion =
|
|
||||||
bindingInfo.type == wgpu::BindingType::StorageBuffer &&
|
|
||||||
moduleInfo.type == wgpu::BindingType::ReadonlyStorageBuffer;
|
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/367): Temporarily allow using either a sampler or a
|
|
||||||
// comparison sampler until we can perform the proper shader analysis of what type
|
|
||||||
// is used in the shader module.
|
|
||||||
validBindingConversion |= (bindingInfo.type == wgpu::BindingType::Sampler &&
|
|
||||||
moduleInfo.type == wgpu::BindingType::ComparisonSampler);
|
|
||||||
validBindingConversion |=
|
|
||||||
(bindingInfo.type == wgpu::BindingType::ComparisonSampler &&
|
|
||||||
moduleInfo.type == wgpu::BindingType::Sampler);
|
|
||||||
|
|
||||||
if (!validBindingConversion) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The binding type of the bind group layout entry conflicts " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((bindingInfo.visibility & StageBit(mExecutionModel)) == 0) {
|
|
||||||
return DAWN_VALIDATION_ERROR("The bind group layout entry for " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber) +
|
|
||||||
" is not visible for the shader stage");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bindingInfo.type) {
|
|
||||||
case wgpu::BindingType::SampledTexture: {
|
|
||||||
if (bindingInfo.textureComponentType != moduleInfo.textureComponentType) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The textureComponentType of the bind group layout entry is different "
|
|
||||||
"from " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bindingInfo.viewDimension != moduleInfo.viewDimension) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The viewDimension of the bind group layout entry is different "
|
|
||||||
"from " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case wgpu::BindingType::ReadonlyStorageTexture:
|
|
||||||
case wgpu::BindingType::WriteonlyStorageTexture: {
|
|
||||||
ASSERT(bindingInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
|
|
||||||
ASSERT(moduleInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
|
|
||||||
if (bindingInfo.storageTextureFormat != moduleInfo.storageTextureFormat) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The storageTextureFormat of the bind group layout entry is different "
|
|
||||||
"from " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
if (bindingInfo.viewDimension != moduleInfo.viewDimension) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The viewDimension of the bind group layout entry is different "
|
|
||||||
"from " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case wgpu::BindingType::UniformBuffer:
|
|
||||||
case wgpu::BindingType::ReadonlyStorageBuffer:
|
|
||||||
case wgpu::BindingType::StorageBuffer: {
|
|
||||||
if (bindingInfo.minBufferBindingSize != 0 &&
|
|
||||||
moduleInfo.minBufferBindingSize > bindingInfo.minBufferBindingSize) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The minimum buffer size of the bind group layout entry is smaller "
|
|
||||||
"than " +
|
|
||||||
GetShaderDeclarationString(group, bindingNumber));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case wgpu::BindingType::Sampler:
|
|
||||||
case wgpu::BindingType::ComparisonSampler:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wgpu::BindingType::StorageTexture:
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
return DAWN_VALIDATION_ERROR("Unsupported binding type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ShaderModuleBase::HashFunc::operator()(const ShaderModuleBase* module) const {
|
size_t ShaderModuleBase::HashFunc::operator()(const ShaderModuleBase* module) const {
|
||||||
|
@ -43,8 +43,6 @@ namespace dawn_native {
|
|||||||
|
|
||||||
class ShaderModuleBase : public CachedObject {
|
class ShaderModuleBase : public CachedObject {
|
||||||
public:
|
public:
|
||||||
enum class Type { Undefined, Spirv, Wgsl };
|
|
||||||
|
|
||||||
ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
|
ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
|
||||||
~ShaderModuleBase() override;
|
~ShaderModuleBase() override;
|
||||||
|
|
||||||
@ -98,6 +96,15 @@ namespace dawn_native {
|
|||||||
uint32_t pullingBufferBindingSet) const;
|
uint32_t pullingBufferBindingSet) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct EntryPointMetadata {
|
||||||
|
EntryPointMetadata();
|
||||||
|
|
||||||
|
ModuleBindingInfo bindings;
|
||||||
|
std::bitset<kMaxVertexAttributes> usedVertexAttributes;
|
||||||
|
SingleShaderStage stage;
|
||||||
|
FragmentOutputBaseTypes fragmentOutputFormatBaseTypes;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static MaybeError CheckSpvcSuccess(shaderc_spvc_status status, const char* error_msg);
|
static MaybeError CheckSpvcSuccess(shaderc_spvc_status status, const char* error_msg);
|
||||||
shaderc_spvc::CompileOptions GetCompileOptions() const;
|
shaderc_spvc::CompileOptions GetCompileOptions() const;
|
||||||
@ -108,27 +115,18 @@ namespace dawn_native {
|
|||||||
private:
|
private:
|
||||||
ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
MaybeError ValidateCompatibilityWithBindGroupLayout(
|
|
||||||
BindGroupIndex group,
|
|
||||||
const BindGroupLayoutBase* layout) const;
|
|
||||||
|
|
||||||
std::vector<uint64_t> GetBindGroupMinBufferSizes(const BindingInfoMap& shaderMap,
|
|
||||||
const BindGroupLayoutBase* layout) const;
|
|
||||||
|
|
||||||
// Different implementations reflection into the shader depending on
|
// Different implementations reflection into the shader depending on
|
||||||
// whether using spvc, or directly accessing spirv-cross.
|
// whether using spvc, or directly accessing spirv-cross.
|
||||||
MaybeError ExtractSpirvInfoWithSpvc();
|
ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfoWithSpvc();
|
||||||
MaybeError ExtractSpirvInfoWithSpirvCross(const spirv_cross::Compiler& compiler);
|
ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfoWithSpirvCross(
|
||||||
|
const spirv_cross::Compiler& compiler);
|
||||||
|
|
||||||
|
enum class Type { Undefined, Spirv, Wgsl };
|
||||||
Type mType;
|
Type mType;
|
||||||
std::vector<uint32_t> mSpirv;
|
std::vector<uint32_t> mSpirv;
|
||||||
std::string mWgsl;
|
std::string mWgsl;
|
||||||
|
|
||||||
ModuleBindingInfo mBindingInfo;
|
std::unique_ptr<EntryPointMetadata> mMainEntryPoint;
|
||||||
std::bitset<kMaxVertexAttributes> mUsedVertexAttributes;
|
|
||||||
SingleShaderStage mExecutionModel;
|
|
||||||
|
|
||||||
FragmentOutputBaseTypes mFragmentOutputFormatBaseTypes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
Loading…
x
Reference in New Issue
Block a user