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:
parent
5d17ed6541
commit
bcbe2e0c94
|
@ -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" ]
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
@ -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_
|
Loading…
Reference in New Issue