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>
This commit is contained in:
Stephen White 2021-08-10 22:04:33 +00:00 committed by Dawn LUCI CQ
parent 5d17ed6541
commit bcbe2e0c94
9 changed files with 270 additions and 298 deletions

View File

@ -85,10 +85,6 @@ config("dawn_internal") {
defines += [ "DAWN_USE_X11" ]
}
if (dawn_use_spirv_cross) {
defines += [ "DAWN_USE_SPIRV_CROSS" ]
}
if (dawn_enable_error_injection) {
defines += [ "DAWN_ENABLE_ERROR_INJECTION" ]
}

View File

@ -313,13 +313,6 @@ source_set("dawn_native_sources") {
]
}
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 @@ source_set("dawn_native_sources") {
"opengl/SamplerGL.h",
"opengl/ShaderModuleGL.cpp",
"opengl/ShaderModuleGL.h",
"opengl/SpirvUtils.cpp",
"opengl/SpirvUtils.h",
"opengl/SwapChainGL.cpp",
"opengl/SwapChainGL.h",
"opengl/TextureGL.cpp",

View File

@ -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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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;

View File

@ -240,11 +240,6 @@ namespace dawn_native {
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);

View File

@ -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"

View File

@ -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 @@ namespace dawn_native { namespace opengl {
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 @@ namespace dawn_native { namespace opengl {
: 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());

View File

@ -60,6 +60,9 @@ namespace dawn_native { namespace opengl {
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;
};

View File

@ -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 {

View File

@ -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 {
} // namespace dawn_native
#endif // DAWNNATIVE_SPIRV_UTILS_H_
#endif // DAWNNATIVE_OPENGL_SPIRV_UTILS_H_