Move SPIRV-Cross functions into OpenGL backend.
Since the other backends no longer need it, move all of the
utility functions specific to SPIRV-Cross into the OpenGL backend.
This obviates the need for the DAWN_USE_SPIRV_CROSS define, so remove it.
Bug: dawn:1036
Change-Id: I67bb5a85dc128a6f343d09876046cf559395e05f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/61541
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/common/BUILD.gn b/src/common/BUILD.gn
index ebb7018..afaa18f 100644
--- a/src/common/BUILD.gn
+++ b/src/common/BUILD.gn
@@ -85,10 +85,6 @@
defines += [ "DAWN_USE_X11" ]
}
- if (dawn_use_spirv_cross) {
- defines += [ "DAWN_USE_SPIRV_CROSS" ]
- }
-
if (dawn_enable_error_injection) {
defines += [ "DAWN_ENABLE_ERROR_INJECTION" ]
}
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index 27731a5..d44de36 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -313,13 +313,6 @@
]
}
- if (dawn_use_spirv_cross) {
- sources += [
- "SpirvUtils.cpp",
- "SpirvUtils.h",
- ]
- }
-
# Only win32 app needs to link with user32.lib
# In UWP, all availiable APIs are defined in WindowsApp.lib
if (is_win && !dawn_is_winuwp) {
@@ -527,6 +520,8 @@
"opengl/SamplerGL.h",
"opengl/ShaderModuleGL.cpp",
"opengl/ShaderModuleGL.h",
+ "opengl/SpirvUtils.cpp",
+ "opengl/SpirvUtils.h",
"opengl/SwapChainGL.cpp",
"opengl/SwapChainGL.h",
"opengl/TextureGL.cpp",
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 87af445..96ae1ec 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -24,16 +24,10 @@
#include "dawn_native/Pipeline.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/RenderPipeline.h"
-#if defined(DAWN_USE_SPIRV_CROSS)
-# include "dawn_native/SpirvUtils.h"
-#endif
#include "dawn_native/TintUtils.h"
#include <spirv-tools/libspirv.hpp>
#include <spirv-tools/optimizer.hpp>
-#if defined(DAWN_USE_SPIRV_CROSS)
-# include <spirv_cross.hpp>
-#endif
// Tint include must be after spirv_cross.hpp, because spirv-cross has its own
// version of spirv_headers. We also need to undef SPV_REVISION because SPIRV-Cross
@@ -679,252 +673,6 @@
return {};
}
-#if defined(DAWN_USE_SPIRV_CROSS)
- ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfo(
- const DeviceBase* device,
- const spirv_cross::Compiler& compiler,
- const std::string& entryPointName,
- SingleShaderStage stage) {
- std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
- metadata->stage = stage;
-
- const auto& resources = compiler.get_shader_resources();
-
- if (resources.push_constant_buffers.size() > 0) {
- return DAWN_VALIDATION_ERROR("Push constants aren't supported.");
- }
-
- if (resources.sampled_images.size() > 0) {
- return DAWN_VALIDATION_ERROR("Combined images and samplers aren't supported.");
- }
-
- // Fill in bindingInfo with the SPIRV bindings
- auto ExtractResourcesBinding =
- [](const DeviceBase* device,
- const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
- const spirv_cross::Compiler& compiler, BindingInfoType bindingType,
- EntryPointMetadata::BindingInfoArray* metadataBindings,
- bool isStorageBuffer = false) -> MaybeError {
- for (const auto& resource : resources) {
- if (!compiler.get_decoration_bitset(resource.id).get(spv::DecorationBinding)) {
- return DAWN_VALIDATION_ERROR("No Binding decoration set for resource");
- }
-
- if (!compiler.get_decoration_bitset(resource.id)
- .get(spv::DecorationDescriptorSet)) {
- return DAWN_VALIDATION_ERROR("No Descriptor Decoration set for resource");
- }
-
- BindingNumber bindingNumber(
- compiler.get_decoration(resource.id, spv::DecorationBinding));
- BindGroupIndex bindGroupIndex(
- compiler.get_decoration(resource.id, spv::DecorationDescriptorSet));
-
- if (bindGroupIndex >= kMaxBindGroupsTyped) {
- return DAWN_VALIDATION_ERROR("Bind group index over limits in the SPIRV");
- }
-
- const auto& it = (*metadataBindings)[bindGroupIndex].emplace(
- bindingNumber, EntryPointMetadata::ShaderBindingInfo{});
- if (!it.second) {
- return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
- }
-
- EntryPointMetadata::ShaderBindingInfo* info = &it.first->second;
- info->id = resource.id;
- info->base_type_id = resource.base_type_id;
- info->bindingType = bindingType;
-
- switch (bindingType) {
- case BindingInfoType::Texture: {
- spirv_cross::SPIRType::ImageType imageType =
- compiler.get_type(info->base_type_id).image;
- spirv_cross::SPIRType::BaseType textureComponentType =
- compiler.get_type(imageType.type).basetype;
-
- info->texture.viewDimension =
- SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
- info->texture.multisampled = imageType.ms;
- info->texture.compatibleSampleTypes =
- SpirvBaseTypeToSampleTypeBit(textureComponentType);
-
- if (imageType.depth) {
- if ((info->texture.compatibleSampleTypes & SampleTypeBit::Float) ==
- 0) {
- return DAWN_VALIDATION_ERROR(
- "Depth textures must have a float type");
- }
- info->texture.compatibleSampleTypes = SampleTypeBit::Depth;
- }
-
- if (imageType.ms && imageType.arrayed) {
- return DAWN_VALIDATION_ERROR(
- "Multisampled array textures aren't supported");
- }
- break;
- }
- case BindingInfoType::Buffer: {
- // Determine buffer size, with a minimum of 1 element in the runtime
- // array
- spirv_cross::SPIRType type = compiler.get_type(info->base_type_id);
- info->buffer.minBindingSize =
- compiler.get_declared_struct_size_runtime_array(type, 1);
-
- // Differentiate between readonly storage bindings and writable ones
- // based on the NonWritable decoration.
- // TODO(dawn:527): Could isStorageBuffer be determined by calling
- // compiler.get_storage_class(resource.id)?
- if (isStorageBuffer) {
- spirv_cross::Bitset flags =
- compiler.get_buffer_block_flags(resource.id);
- if (flags.get(spv::DecorationNonWritable)) {
- info->buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
- } else {
- info->buffer.type = wgpu::BufferBindingType::Storage;
- }
- } else {
- info->buffer.type = wgpu::BufferBindingType::Uniform;
- }
- break;
- }
- case BindingInfoType::StorageTexture: {
- spirv_cross::Bitset flags = compiler.get_decoration_bitset(resource.id);
- if (flags.get(spv::DecorationNonReadable)) {
- info->storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
- } else if (flags.get(spv::DecorationNonWritable)) {
- info->storageTexture.access = wgpu::StorageTextureAccess::ReadOnly;
- } else {
- return DAWN_VALIDATION_ERROR(
- "Read-write storage textures are not supported");
- }
-
- spirv_cross::SPIRType::ImageType imageType =
- compiler.get_type(info->base_type_id).image;
- wgpu::TextureFormat storageTextureFormat =
- SpirvImageFormatToTextureFormat(imageType.format);
- if (storageTextureFormat == wgpu::TextureFormat::Undefined) {
- return DAWN_VALIDATION_ERROR(
- "Invalid image format declaration on storage image");
- }
- const Format& format =
- device->GetValidInternalFormat(storageTextureFormat);
- if (!format.supportsStorageUsage) {
- return DAWN_VALIDATION_ERROR(
- "The storage texture format is not supported");
- }
- if (imageType.ms) {
- return DAWN_VALIDATION_ERROR(
- "Multisampled storage textures aren't supported");
- }
- if (imageType.depth) {
- return DAWN_VALIDATION_ERROR(
- "Depth storage textures aren't supported");
- }
- info->storageTexture.format = storageTextureFormat;
- info->storageTexture.viewDimension =
- SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
- break;
- }
- case BindingInfoType::Sampler: {
- info->sampler.isComparison = false;
- break;
- }
- case BindingInfoType::ExternalTexture: {
- return DAWN_VALIDATION_ERROR("External textures are not supported.");
- }
- }
- }
- return {};
- };
-
- DAWN_TRY(ExtractResourcesBinding(device, resources.uniform_buffers, compiler,
- BindingInfoType::Buffer, &metadata->bindings));
- DAWN_TRY(ExtractResourcesBinding(device, resources.separate_images, compiler,
- BindingInfoType::Texture, &metadata->bindings));
- DAWN_TRY(ExtractResourcesBinding(device, resources.separate_samplers, compiler,
- BindingInfoType::Sampler, &metadata->bindings));
- DAWN_TRY(ExtractResourcesBinding(device, resources.storage_buffers, compiler,
- BindingInfoType::Buffer, &metadata->bindings, true));
- // ReadonlyStorageTexture is used as a tag to do general storage texture handling.
- DAWN_TRY(ExtractResourcesBinding(device, resources.storage_images, compiler,
- BindingInfoType::StorageTexture, &metadata->bindings));
-
- // Extract the vertex attributes
- if (stage == SingleShaderStage::Vertex) {
- for (const auto& attrib : resources.stage_inputs) {
- if (!(compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation))) {
- return DAWN_VALIDATION_ERROR(
- "Unable to find Location decoration for Vertex input");
- }
- uint32_t unsanitizedLocation =
- compiler.get_decoration(attrib.id, spv::DecorationLocation);
-
- if (unsanitizedLocation >= kMaxVertexAttributes) {
- return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
- }
- VertexAttributeLocation location(static_cast<uint8_t>(unsanitizedLocation));
-
- spirv_cross::SPIRType::BaseType inputBaseType =
- compiler.get_type(attrib.base_type_id).basetype;
- metadata->vertexInputBaseTypes[location] =
- SpirvBaseTypeToVertexFormatBaseType(inputBaseType);
- metadata->usedVertexInputs.set(location);
- }
-
- // Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives
- // them all the location 0, causing a compile error.
- for (const auto& attrib : resources.stage_outputs) {
- if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
- return DAWN_VALIDATION_ERROR("Need location qualifier on vertex output");
- }
- }
- }
-
- if (stage == SingleShaderStage::Fragment) {
- // Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
- // them all the location 0, causing a compile error.
- for (const auto& attrib : resources.stage_inputs) {
- if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
- return DAWN_VALIDATION_ERROR("Need location qualifier on fragment input");
- }
- }
-
- for (const auto& fragmentOutput : resources.stage_outputs) {
- if (!compiler.get_decoration_bitset(fragmentOutput.id)
- .get(spv::DecorationLocation)) {
- return DAWN_VALIDATION_ERROR(
- "Unable to find Location decoration for Fragment output");
- }
- uint32_t unsanitizedAttachment =
- compiler.get_decoration(fragmentOutput.id, spv::DecorationLocation);
-
- if (unsanitizedAttachment >= kMaxColorAttachments) {
- return DAWN_VALIDATION_ERROR(
- "Fragment output index must be less than max number of color "
- "attachments");
- }
- ColorAttachmentIndex attachment(static_cast<uint8_t>(unsanitizedAttachment));
-
- spirv_cross::SPIRType::BaseType shaderFragmentOutputBaseType =
- compiler.get_type(fragmentOutput.base_type_id).basetype;
- metadata->fragmentOutputFormatBaseTypes[attachment] =
- SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType);
- metadata->fragmentOutputsWritten.set(attachment);
- }
- }
-
- if (stage == SingleShaderStage::Compute) {
- const spirv_cross::SPIREntryPoint& spirEntryPoint =
- compiler.get_entry_point(entryPointName, spv::ExecutionModelGLCompute);
- metadata->localWorkgroupSize.x = spirEntryPoint.workgroup_size.x;
- metadata->localWorkgroupSize.y = spirEntryPoint.workgroup_size.y;
- metadata->localWorkgroupSize.z = spirEntryPoint.workgroup_size.z;
- }
-
- return {std::move(metadata)};
- }
-#endif
-
ResultOrError<EntryPointMetadataTable> ReflectShaderUsingTint(
DeviceBase*,
const tint::Program* program) {
@@ -1628,26 +1376,6 @@
return {};
}
-#if defined(DAWN_USE_SPIRV_CROSS)
- ResultOrError<EntryPointMetadataTable> ShaderModuleBase::ReflectShaderUsingSPIRVCross(
- DeviceBase* device,
- const std::vector<uint32_t>& spirv) {
- EntryPointMetadataTable result;
- spirv_cross::Compiler compiler(spirv);
- for (const spirv_cross::EntryPoint& entryPoint : compiler.get_entry_points_and_stages()) {
- ASSERT(result.count(entryPoint.name) == 0);
-
- SingleShaderStage stage = ExecutionModelToShaderStage(entryPoint.execution_model);
- compiler.set_entry_point(entryPoint.name, entryPoint.execution_model);
-
- std::unique_ptr<EntryPointMetadata> metadata;
- DAWN_TRY_ASSIGN(metadata, ExtractSpirvInfo(device, compiler, entryPoint.name, stage));
- result[entryPoint.name] = std::move(metadata);
- }
- return std::move(result);
- }
-#endif
-
size_t PipelineLayoutEntryPointPairHashFunc::operator()(
const PipelineLayoutEntryPointPair& pair) const {
size_t hash = 0;
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index 7d92c42..3f17ceb 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -240,11 +240,6 @@
protected:
MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
-#if defined(DAWN_USE_SPIRV_CROSS)
- static ResultOrError<EntryPointMetadataTable> ReflectShaderUsingSPIRVCross(
- DeviceBase* device,
- const std::vector<uint32_t>& spirv);
-#endif
private:
ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag);
diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
index 28228a7..3a59890 100644
--- a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
+++ b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
@@ -17,7 +17,6 @@
#include "common/Assert.h"
#include "common/BitSetIterator.h"
#include "common/Log.h"
-#include "dawn_native/SpirvUtils.h"
#include "dawn_native/TintUtils.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h"
diff --git a/src/dawn_native/opengl/ShaderModuleGL.cpp b/src/dawn_native/opengl/ShaderModuleGL.cpp
index c56d950..a5a3dd0 100644
--- a/src/dawn_native/opengl/ShaderModuleGL.cpp
+++ b/src/dawn_native/opengl/ShaderModuleGL.cpp
@@ -17,10 +17,10 @@
#include "common/Assert.h"
#include "common/Platform.h"
#include "dawn_native/BindGroupLayout.h"
-#include "dawn_native/SpirvUtils.h"
#include "dawn_native/TintUtils.h"
#include "dawn_native/opengl/DeviceGL.h"
#include "dawn_native/opengl/PipelineLayoutGL.h"
+#include "dawn_native/opengl/SpirvUtils.h"
#include <spirv_glsl.hpp>
@@ -64,6 +64,247 @@
return o.str();
}
+ ResultOrError<std::unique_ptr<EntryPointMetadata>> ExtractSpirvInfo(
+ const DeviceBase* device,
+ const spirv_cross::Compiler& compiler,
+ const std::string& entryPointName,
+ SingleShaderStage stage) {
+ std::unique_ptr<EntryPointMetadata> metadata = std::make_unique<EntryPointMetadata>();
+ metadata->stage = stage;
+
+ const auto& resources = compiler.get_shader_resources();
+
+ if (resources.push_constant_buffers.size() > 0) {
+ return DAWN_VALIDATION_ERROR("Push constants aren't supported.");
+ }
+
+ if (resources.sampled_images.size() > 0) {
+ return DAWN_VALIDATION_ERROR("Combined images and samplers aren't supported.");
+ }
+
+ // Fill in bindingInfo with the SPIRV bindings
+ auto ExtractResourcesBinding =
+ [](const DeviceBase* device,
+ const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
+ const spirv_cross::Compiler& compiler, BindingInfoType bindingType,
+ EntryPointMetadata::BindingInfoArray* metadataBindings,
+ bool isStorageBuffer = false) -> MaybeError {
+ for (const auto& resource : resources) {
+ if (!compiler.get_decoration_bitset(resource.id).get(spv::DecorationBinding)) {
+ return DAWN_VALIDATION_ERROR("No Binding decoration set for resource");
+ }
+
+ if (!compiler.get_decoration_bitset(resource.id)
+ .get(spv::DecorationDescriptorSet)) {
+ return DAWN_VALIDATION_ERROR("No Descriptor Decoration set for resource");
+ }
+
+ BindingNumber bindingNumber(
+ compiler.get_decoration(resource.id, spv::DecorationBinding));
+ BindGroupIndex bindGroupIndex(
+ compiler.get_decoration(resource.id, spv::DecorationDescriptorSet));
+
+ if (bindGroupIndex >= kMaxBindGroupsTyped) {
+ return DAWN_VALIDATION_ERROR("Bind group index over limits in the SPIRV");
+ }
+
+ const auto& it = (*metadataBindings)[bindGroupIndex].emplace(
+ bindingNumber, EntryPointMetadata::ShaderBindingInfo{});
+ if (!it.second) {
+ return DAWN_VALIDATION_ERROR("Shader has duplicate bindings");
+ }
+
+ EntryPointMetadata::ShaderBindingInfo* info = &it.first->second;
+ info->id = resource.id;
+ info->base_type_id = resource.base_type_id;
+ info->bindingType = bindingType;
+
+ switch (bindingType) {
+ case BindingInfoType::Texture: {
+ spirv_cross::SPIRType::ImageType imageType =
+ compiler.get_type(info->base_type_id).image;
+ spirv_cross::SPIRType::BaseType textureComponentType =
+ compiler.get_type(imageType.type).basetype;
+
+ info->texture.viewDimension =
+ SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
+ info->texture.multisampled = imageType.ms;
+ info->texture.compatibleSampleTypes =
+ SpirvBaseTypeToSampleTypeBit(textureComponentType);
+
+ if (imageType.depth) {
+ if ((info->texture.compatibleSampleTypes & SampleTypeBit::Float) == 0) {
+ return DAWN_VALIDATION_ERROR(
+ "Depth textures must have a float type");
+ }
+ info->texture.compatibleSampleTypes = SampleTypeBit::Depth;
+ }
+
+ if (imageType.ms && imageType.arrayed) {
+ return DAWN_VALIDATION_ERROR(
+ "Multisampled array textures aren't supported");
+ }
+ break;
+ }
+ case BindingInfoType::Buffer: {
+ // Determine buffer size, with a minimum of 1 element in the runtime
+ // array
+ spirv_cross::SPIRType type = compiler.get_type(info->base_type_id);
+ info->buffer.minBindingSize =
+ compiler.get_declared_struct_size_runtime_array(type, 1);
+
+ // Differentiate between readonly storage bindings and writable ones
+ // based on the NonWritable decoration.
+ // TODO(dawn:527): Could isStorageBuffer be determined by calling
+ // compiler.get_storage_class(resource.id)?
+ if (isStorageBuffer) {
+ spirv_cross::Bitset flags =
+ compiler.get_buffer_block_flags(resource.id);
+ if (flags.get(spv::DecorationNonWritable)) {
+ info->buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
+ } else {
+ info->buffer.type = wgpu::BufferBindingType::Storage;
+ }
+ } else {
+ info->buffer.type = wgpu::BufferBindingType::Uniform;
+ }
+ break;
+ }
+ case BindingInfoType::StorageTexture: {
+ spirv_cross::Bitset flags = compiler.get_decoration_bitset(resource.id);
+ if (flags.get(spv::DecorationNonReadable)) {
+ info->storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
+ } else if (flags.get(spv::DecorationNonWritable)) {
+ info->storageTexture.access = wgpu::StorageTextureAccess::ReadOnly;
+ } else {
+ return DAWN_VALIDATION_ERROR(
+ "Read-write storage textures are not supported");
+ }
+
+ spirv_cross::SPIRType::ImageType imageType =
+ compiler.get_type(info->base_type_id).image;
+ wgpu::TextureFormat storageTextureFormat =
+ SpirvImageFormatToTextureFormat(imageType.format);
+ if (storageTextureFormat == wgpu::TextureFormat::Undefined) {
+ return DAWN_VALIDATION_ERROR(
+ "Invalid image format declaration on storage image");
+ }
+ const Format& format = device->GetValidInternalFormat(storageTextureFormat);
+ if (!format.supportsStorageUsage) {
+ return DAWN_VALIDATION_ERROR(
+ "The storage texture format is not supported");
+ }
+ if (imageType.ms) {
+ return DAWN_VALIDATION_ERROR(
+ "Multisampled storage textures aren't supported");
+ }
+ if (imageType.depth) {
+ return DAWN_VALIDATION_ERROR("Depth storage textures aren't supported");
+ }
+ info->storageTexture.format = storageTextureFormat;
+ info->storageTexture.viewDimension =
+ SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
+ break;
+ }
+ case BindingInfoType::Sampler: {
+ info->sampler.isComparison = false;
+ break;
+ }
+ case BindingInfoType::ExternalTexture: {
+ return DAWN_VALIDATION_ERROR("External textures are not supported.");
+ }
+ }
+ }
+ return {};
+ };
+
+ DAWN_TRY(ExtractResourcesBinding(device, resources.uniform_buffers, compiler,
+ BindingInfoType::Buffer, &metadata->bindings));
+ DAWN_TRY(ExtractResourcesBinding(device, resources.separate_images, compiler,
+ BindingInfoType::Texture, &metadata->bindings));
+ DAWN_TRY(ExtractResourcesBinding(device, resources.separate_samplers, compiler,
+ BindingInfoType::Sampler, &metadata->bindings));
+ DAWN_TRY(ExtractResourcesBinding(device, resources.storage_buffers, compiler,
+ BindingInfoType::Buffer, &metadata->bindings, true));
+ // ReadonlyStorageTexture is used as a tag to do general storage texture handling.
+ DAWN_TRY(ExtractResourcesBinding(device, resources.storage_images, compiler,
+ BindingInfoType::StorageTexture, &metadata->bindings));
+
+ // Extract the vertex attributes
+ if (stage == SingleShaderStage::Vertex) {
+ for (const auto& attrib : resources.stage_inputs) {
+ if (!(compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation))) {
+ return DAWN_VALIDATION_ERROR(
+ "Unable to find Location decoration for Vertex input");
+ }
+ uint32_t unsanitizedLocation =
+ compiler.get_decoration(attrib.id, spv::DecorationLocation);
+
+ if (unsanitizedLocation >= kMaxVertexAttributes) {
+ return DAWN_VALIDATION_ERROR("Attribute location over limits in the SPIRV");
+ }
+ VertexAttributeLocation location(static_cast<uint8_t>(unsanitizedLocation));
+
+ spirv_cross::SPIRType::BaseType inputBaseType =
+ compiler.get_type(attrib.base_type_id).basetype;
+ metadata->vertexInputBaseTypes[location] =
+ SpirvBaseTypeToVertexFormatBaseType(inputBaseType);
+ metadata->usedVertexInputs.set(location);
+ }
+
+ // Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives
+ // them all the location 0, causing a compile error.
+ for (const auto& attrib : resources.stage_outputs) {
+ if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
+ return DAWN_VALIDATION_ERROR("Need location qualifier on vertex output");
+ }
+ }
+ }
+
+ if (stage == SingleShaderStage::Fragment) {
+ // Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives
+ // them all the location 0, causing a compile error.
+ for (const auto& attrib : resources.stage_inputs) {
+ if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
+ return DAWN_VALIDATION_ERROR("Need location qualifier on fragment input");
+ }
+ }
+
+ for (const auto& fragmentOutput : resources.stage_outputs) {
+ if (!compiler.get_decoration_bitset(fragmentOutput.id)
+ .get(spv::DecorationLocation)) {
+ return DAWN_VALIDATION_ERROR(
+ "Unable to find Location decoration for Fragment output");
+ }
+ uint32_t unsanitizedAttachment =
+ compiler.get_decoration(fragmentOutput.id, spv::DecorationLocation);
+
+ if (unsanitizedAttachment >= kMaxColorAttachments) {
+ return DAWN_VALIDATION_ERROR(
+ "Fragment output index must be less than max number of color "
+ "attachments");
+ }
+ ColorAttachmentIndex attachment(static_cast<uint8_t>(unsanitizedAttachment));
+
+ spirv_cross::SPIRType::BaseType shaderFragmentOutputBaseType =
+ compiler.get_type(fragmentOutput.base_type_id).basetype;
+ metadata->fragmentOutputFormatBaseTypes[attachment] =
+ SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType);
+ metadata->fragmentOutputsWritten.set(attachment);
+ }
+ }
+
+ if (stage == SingleShaderStage::Compute) {
+ const spirv_cross::SPIREntryPoint& spirEntryPoint =
+ compiler.get_entry_point(entryPointName, spv::ExecutionModelGLCompute);
+ metadata->localWorkgroupSize.x = spirEntryPoint.workgroup_size.x;
+ metadata->localWorkgroupSize.y = spirEntryPoint.workgroup_size.y;
+ metadata->localWorkgroupSize.z = spirEntryPoint.workgroup_size.z;
+ }
+
+ return {std::move(metadata)};
+ }
+
// static
ResultOrError<Ref<ShaderModule>> ShaderModule::Create(Device* device,
const ShaderModuleDescriptor* descriptor,
@@ -77,6 +318,25 @@
: ShaderModuleBase(device, descriptor) {
}
+ // static
+ ResultOrError<EntryPointMetadataTable> ShaderModule::ReflectShaderUsingSPIRVCross(
+ DeviceBase* device,
+ const std::vector<uint32_t>& spirv) {
+ EntryPointMetadataTable result;
+ spirv_cross::Compiler compiler(spirv);
+ for (const spirv_cross::EntryPoint& entryPoint : compiler.get_entry_points_and_stages()) {
+ ASSERT(result.count(entryPoint.name) == 0);
+
+ SingleShaderStage stage = ExecutionModelToShaderStage(entryPoint.execution_model);
+ compiler.set_entry_point(entryPoint.name, entryPoint.execution_model);
+
+ std::unique_ptr<EntryPointMetadata> metadata;
+ DAWN_TRY_ASSIGN(metadata, ExtractSpirvInfo(device, compiler, entryPoint.name, stage));
+ result[entryPoint.name] = std::move(metadata);
+ }
+ return std::move(result);
+ }
+
MaybeError ShaderModule::Initialize(ShaderModuleParseResult* parseResult) {
ScopedTintICEHandler scopedICEHandler(GetDevice());
diff --git a/src/dawn_native/opengl/ShaderModuleGL.h b/src/dawn_native/opengl/ShaderModuleGL.h
index d6d9f74..78a2f2a 100644
--- a/src/dawn_native/opengl/ShaderModuleGL.h
+++ b/src/dawn_native/opengl/ShaderModuleGL.h
@@ -60,6 +60,9 @@
ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor);
~ShaderModule() override = default;
MaybeError Initialize(ShaderModuleParseResult* parseResult);
+ static ResultOrError<EntryPointMetadataTable> ReflectShaderUsingSPIRVCross(
+ DeviceBase* device,
+ const std::vector<uint32_t>& spirv);
EntryPointMetadataTable mGLEntryPoints;
};
diff --git a/src/dawn_native/SpirvUtils.cpp b/src/dawn_native/opengl/SpirvUtils.cpp
similarity index 99%
rename from src/dawn_native/SpirvUtils.cpp
rename to src/dawn_native/opengl/SpirvUtils.cpp
index 01749de..a274300 100644
--- a/src/dawn_native/SpirvUtils.cpp
+++ b/src/dawn_native/opengl/SpirvUtils.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "dawn_native/SpirvUtils.h"
+#include "dawn_native/opengl/SpirvUtils.h"
namespace dawn_native {
diff --git a/src/dawn_native/SpirvUtils.h b/src/dawn_native/opengl/SpirvUtils.h
similarity index 89%
rename from src/dawn_native/SpirvUtils.h
rename to src/dawn_native/opengl/SpirvUtils.h
index 3719794..844b0b7 100644
--- a/src/dawn_native/SpirvUtils.h
+++ b/src/dawn_native/opengl/SpirvUtils.h
@@ -15,12 +15,8 @@
// This file contains utilities to convert from-to spirv.hpp datatypes without polluting other
// headers with spirv.hpp
-#ifndef DAWNNATIVE_SPIRV_UTILS_H_
-#define DAWNNATIVE_SPIRV_UTILS_H_
-
-#if !defined(DAWN_USE_SPIRV_CROSS)
-# error "SpirvCross.h should not be included if dawn_use_spirv_cross is false"
-#endif
+#ifndef DAWNNATIVE_OPENGL_SPIRV_UTILS_H_
+#define DAWNNATIVE_OPENGL_SPIRV_UTILS_H_
#include "dawn_native/Format.h"
#include "dawn_native/PerStage.h"
@@ -52,4 +48,4 @@
} // namespace dawn_native
-#endif // DAWNNATIVE_SPIRV_UTILS_H_
+#endif // DAWNNATIVE_OPENGL_SPIRV_UTILS_H_