Validate the declaration of storage texture format in shader
This patch adds the validation on the storage texture format declared in shaders when we create a rendering or compute pipeline with read-only or write-only storage textures. This patch also fixes a typo in the TextureValidationTest. BUG=dawn:267 TEST=dawn_unittests Change-Id: Id302b4b7803d7e03b57c61de1290cc71ba940e2c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16940 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
2550e96724
commit
971a6233c2
2
BUILD.gn
2
BUILD.gn
|
@ -751,6 +751,8 @@ static_library("dawn_utils") {
|
||||||
"src/utils/SystemUtils.h",
|
"src/utils/SystemUtils.h",
|
||||||
"src/utils/TerribleCommandBuffer.cpp",
|
"src/utils/TerribleCommandBuffer.cpp",
|
||||||
"src/utils/TerribleCommandBuffer.h",
|
"src/utils/TerribleCommandBuffer.h",
|
||||||
|
"src/utils/TextureFormatUtils.cpp",
|
||||||
|
"src/utils/TextureFormatUtils.h",
|
||||||
"src/utils/Timer.h",
|
"src/utils/Timer.h",
|
||||||
"src/utils/WGPUHelpers.cpp",
|
"src/utils/WGPUHelpers.cpp",
|
||||||
"src/utils/WGPUHelpers.h",
|
"src/utils/WGPUHelpers.h",
|
||||||
|
|
|
@ -94,7 +94,8 @@
|
||||||
{"name": "has dynamic offset", "type": "bool", "default": "false"},
|
{"name": "has dynamic offset", "type": "bool", "default": "false"},
|
||||||
{"name": "multisampled", "type": "bool", "default": "false"},
|
{"name": "multisampled", "type": "bool", "default": "false"},
|
||||||
{"name": "texture dimension", "type": "texture view dimension", "default": "undefined"},
|
{"name": "texture dimension", "type": "texture view dimension", "default": "undefined"},
|
||||||
{"name": "texture component type", "type": "texture component type", "default": "float"}
|
{"name": "texture component type", "type": "texture component type", "default": "float"},
|
||||||
|
{"name": "storage texture format", "type": "texture format", "default": "undefined"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"bind group layout descriptor": {
|
"bind group layout descriptor": {
|
||||||
|
|
|
@ -58,7 +58,35 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase*,
|
MaybeError ValidateStorageTextureFormat(DeviceBase* device,
|
||||||
|
wgpu::BindingType bindingType,
|
||||||
|
wgpu::TextureFormat storageTextureFormat) {
|
||||||
|
switch (bindingType) {
|
||||||
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
|
case wgpu::BindingType::WriteonlyStorageTexture: {
|
||||||
|
DAWN_TRY(ValidateTextureFormat(storageTextureFormat));
|
||||||
|
|
||||||
|
const Format& format = device->GetValidInternalFormat(storageTextureFormat);
|
||||||
|
if (!format.supportsStorageUsage) {
|
||||||
|
return DAWN_VALIDATION_ERROR("The storage texture format is not supported");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case wgpu::BindingType::StorageBuffer:
|
||||||
|
case wgpu::BindingType::UniformBuffer:
|
||||||
|
case wgpu::BindingType::ReadonlyStorageBuffer:
|
||||||
|
case wgpu::BindingType::Sampler:
|
||||||
|
case wgpu::BindingType::SampledTexture:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase* device,
|
||||||
const BindGroupLayoutDescriptor* descriptor) {
|
const BindGroupLayoutDescriptor* descriptor) {
|
||||||
if (descriptor->nextInChain != nullptr) {
|
if (descriptor->nextInChain != nullptr) {
|
||||||
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
||||||
|
@ -87,6 +115,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(
|
DAWN_TRY(
|
||||||
ValidateBindingTypeWithShaderStageVisibility(binding.type, binding.visibility));
|
ValidateBindingTypeWithShaderStageVisibility(binding.type, binding.visibility));
|
||||||
|
|
||||||
|
DAWN_TRY(
|
||||||
|
ValidateStorageTextureFormat(device, binding.type, binding.storageTextureFormat));
|
||||||
|
|
||||||
switch (binding.type) {
|
switch (binding.type) {
|
||||||
case wgpu::BindingType::UniformBuffer:
|
case wgpu::BindingType::UniformBuffer:
|
||||||
if (binding.hasDynamicOffset) {
|
if (binding.hasDynamicOffset) {
|
||||||
|
|
|
@ -36,6 +36,10 @@ namespace dawn_native {
|
||||||
wgpu::BindingType bindingType,
|
wgpu::BindingType bindingType,
|
||||||
wgpu::ShaderStage shaderStageVisibility);
|
wgpu::ShaderStage shaderStageVisibility);
|
||||||
|
|
||||||
|
MaybeError ValidateStorageTextureFormat(DeviceBase* device,
|
||||||
|
wgpu::BindingType bindingType,
|
||||||
|
wgpu::TextureFormat storageTextureFormat);
|
||||||
|
|
||||||
class BindGroupLayoutBase : public CachedObject {
|
class BindGroupLayoutBase : public CachedObject {
|
||||||
public:
|
public:
|
||||||
BindGroupLayoutBase(DeviceBase* device, const BindGroupLayoutDescriptor* descriptor);
|
BindGroupLayoutBase(DeviceBase* device, const BindGroupLayoutDescriptor* descriptor);
|
||||||
|
|
|
@ -160,6 +160,9 @@ namespace dawn_native {
|
||||||
|
|
||||||
DAWN_TRY(ValidateBindingTypeWithShaderStageVisibility(
|
DAWN_TRY(ValidateBindingTypeWithShaderStageVisibility(
|
||||||
bindingInfo.type, StageBit(module->GetExecutionModel())));
|
bindingInfo.type, StageBit(module->GetExecutionModel())));
|
||||||
|
DAWN_TRY(ValidateStorageTextureFormat(device, bindingInfo.type,
|
||||||
|
bindingInfo.storageTextureFormat));
|
||||||
|
|
||||||
bindingSlot.visibility =
|
bindingSlot.visibility =
|
||||||
GetShaderStageVisibilityWithBindingType(bindingInfo.type);
|
GetShaderStageVisibilityWithBindingType(bindingInfo.type);
|
||||||
|
|
||||||
|
@ -169,6 +172,7 @@ namespace dawn_native {
|
||||||
bindingSlot.textureDimension = bindingInfo.textureDimension;
|
bindingSlot.textureDimension = bindingInfo.textureDimension;
|
||||||
bindingSlot.textureComponentType =
|
bindingSlot.textureComponentType =
|
||||||
Format::FormatTypeToTextureComponentType(bindingInfo.textureComponentType);
|
Format::FormatTypeToTextureComponentType(bindingInfo.textureComponentType);
|
||||||
|
bindingSlot.storageTextureFormat = bindingInfo.storageTextureFormat;
|
||||||
|
|
||||||
if (usedBindings[group][binding]) {
|
if (usedBindings[group][binding]) {
|
||||||
if (bindingSlot == bindingData[group][usedBindingsMap[group][binding]]) {
|
if (bindingSlot == bindingData[group][usedBindingsMap[group][binding]]) {
|
||||||
|
|
|
@ -113,6 +113,9 @@ namespace dawn_native {
|
||||||
return wgpu::BindingType::Sampler;
|
return wgpu::BindingType::Sampler;
|
||||||
case shaderc_spvc_binding_type_sampled_texture:
|
case shaderc_spvc_binding_type_sampled_texture:
|
||||||
return wgpu::BindingType::SampledTexture;
|
return wgpu::BindingType::SampledTexture;
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): add convertion to read-only and write-only storage
|
||||||
|
// textures when they are supported as shaderc_spvc binding types.
|
||||||
case shaderc_spvc_binding_type_storage_texture:
|
case shaderc_spvc_binding_type_storage_texture:
|
||||||
return wgpu::BindingType::StorageTexture;
|
return wgpu::BindingType::StorageTexture;
|
||||||
}
|
}
|
||||||
|
@ -134,6 +137,77 @@ namespace dawn_native {
|
||||||
"Attempted to convert invalid spvc execution model to SingleShaderStage");
|
"Attempted to convert invalid spvc execution model to SingleShaderStage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wgpu::TextureFormat ToWGPUTextureFormat(spv::ImageFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case spv::ImageFormatR8:
|
||||||
|
return wgpu::TextureFormat::R8Unorm;
|
||||||
|
case spv::ImageFormatR8Snorm:
|
||||||
|
return wgpu::TextureFormat::R8Snorm;
|
||||||
|
case spv::ImageFormatR8ui:
|
||||||
|
return wgpu::TextureFormat::R8Uint;
|
||||||
|
case spv::ImageFormatR8i:
|
||||||
|
return wgpu::TextureFormat::R8Sint;
|
||||||
|
case spv::ImageFormatR16ui:
|
||||||
|
return wgpu::TextureFormat::R16Uint;
|
||||||
|
case spv::ImageFormatR16i:
|
||||||
|
return wgpu::TextureFormat::R16Sint;
|
||||||
|
case spv::ImageFormatR16f:
|
||||||
|
return wgpu::TextureFormat::R16Float;
|
||||||
|
case spv::ImageFormatRg8:
|
||||||
|
return wgpu::TextureFormat::RG8Unorm;
|
||||||
|
case spv::ImageFormatRg8Snorm:
|
||||||
|
return wgpu::TextureFormat::RG8Snorm;
|
||||||
|
case spv::ImageFormatRg8ui:
|
||||||
|
return wgpu::TextureFormat::RG8Uint;
|
||||||
|
case spv::ImageFormatRg8i:
|
||||||
|
return wgpu::TextureFormat::RG8Sint;
|
||||||
|
case spv::ImageFormatR32f:
|
||||||
|
return wgpu::TextureFormat::R32Float;
|
||||||
|
case spv::ImageFormatR32ui:
|
||||||
|
return wgpu::TextureFormat::R32Uint;
|
||||||
|
case spv::ImageFormatR32i:
|
||||||
|
return wgpu::TextureFormat::R32Sint;
|
||||||
|
case spv::ImageFormatRg16ui:
|
||||||
|
return wgpu::TextureFormat::RG16Uint;
|
||||||
|
case spv::ImageFormatRg16i:
|
||||||
|
return wgpu::TextureFormat::RG16Sint;
|
||||||
|
case spv::ImageFormatRg16f:
|
||||||
|
return wgpu::TextureFormat::RG16Float;
|
||||||
|
case spv::ImageFormatRgba8:
|
||||||
|
return wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
case spv::ImageFormatRgba8Snorm:
|
||||||
|
return wgpu::TextureFormat::RGBA8Snorm;
|
||||||
|
case spv::ImageFormatRgba8ui:
|
||||||
|
return wgpu::TextureFormat::RGBA8Uint;
|
||||||
|
case spv::ImageFormatRgba8i:
|
||||||
|
return wgpu::TextureFormat::RGBA8Sint;
|
||||||
|
case spv::ImageFormatRgb10A2:
|
||||||
|
return wgpu::TextureFormat::RGB10A2Unorm;
|
||||||
|
case spv::ImageFormatR11fG11fB10f:
|
||||||
|
return wgpu::TextureFormat::RG11B10Float;
|
||||||
|
case spv::ImageFormatRg32f:
|
||||||
|
return wgpu::TextureFormat::RG32Float;
|
||||||
|
case spv::ImageFormatRg32ui:
|
||||||
|
return wgpu::TextureFormat::RG32Uint;
|
||||||
|
case spv::ImageFormatRg32i:
|
||||||
|
return wgpu::TextureFormat::RG32Sint;
|
||||||
|
case spv::ImageFormatRgba16ui:
|
||||||
|
return wgpu::TextureFormat::RGBA16Uint;
|
||||||
|
case spv::ImageFormatRgba16i:
|
||||||
|
return wgpu::TextureFormat::RGBA16Sint;
|
||||||
|
case spv::ImageFormatRgba16f:
|
||||||
|
return wgpu::TextureFormat::RGBA16Float;
|
||||||
|
case spv::ImageFormatRgba32f:
|
||||||
|
return wgpu::TextureFormat::RGBA32Float;
|
||||||
|
case spv::ImageFormatRgba32ui:
|
||||||
|
return wgpu::TextureFormat::RGBA32Uint;
|
||||||
|
case spv::ImageFormatRgba32i:
|
||||||
|
return wgpu::TextureFormat::RGBA32Sint;
|
||||||
|
default:
|
||||||
|
return wgpu::TextureFormat::Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
MaybeError ValidateShaderModuleDescriptor(DeviceBase*,
|
MaybeError ValidateShaderModuleDescriptor(DeviceBase*,
|
||||||
|
@ -173,7 +247,7 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
// ShaderModuleBase
|
// ShaderModuleBase
|
||||||
|
|
||||||
|
@ -251,6 +325,7 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): extract binding information about storage textures.
|
||||||
std::vector<shaderc_spvc_binding_info> resource_bindings;
|
std::vector<shaderc_spvc_binding_info> resource_bindings;
|
||||||
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
|
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.GetBindingInfo(
|
||||||
shaderc_spvc_shader_resource_uniform_buffers,
|
shaderc_spvc_shader_resource_uniform_buffers,
|
||||||
|
@ -415,6 +490,22 @@ namespace dawn_native {
|
||||||
} else {
|
} else {
|
||||||
info->type = wgpu::BindingType::StorageTexture;
|
info->type = wgpu::BindingType::StorageTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spirv_cross::SPIRType::ImageType imageType =
|
||||||
|
compiler.get_type(info->base_type_id).image;
|
||||||
|
wgpu::TextureFormat storageTextureFormat =
|
||||||
|
ToWGPUTextureFormat(imageType.format);
|
||||||
|
if (storageTextureFormat == wgpu::TextureFormat::Undefined) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"Invalid image format declaration on storage image");
|
||||||
|
}
|
||||||
|
const Format& format =
|
||||||
|
GetDevice()->GetValidInternalFormat(storageTextureFormat);
|
||||||
|
if (!format.supportsStorageUsage) {
|
||||||
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
"The storage texture format is not supported");
|
||||||
|
}
|
||||||
|
info->storageTextureFormat = storageTextureFormat;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
info->type = bindingType;
|
info->type = bindingType;
|
||||||
|
|
|
@ -58,6 +58,7 @@ namespace dawn_native {
|
||||||
Format::Type textureComponentType = Format::Type::Float;
|
Format::Type textureComponentType = Format::Type::Float;
|
||||||
bool multisampled = false;
|
bool multisampled = false;
|
||||||
bool used = false;
|
bool used = false;
|
||||||
|
wgpu::TextureFormat storageTextureFormat = wgpu::TextureFormat::Undefined;
|
||||||
};
|
};
|
||||||
using ModuleBindingInfo =
|
using ModuleBindingInfo =
|
||||||
std::array<std::array<BindingInfo, kMaxBindingsPerGroup>, kMaxBindGroups>;
|
std::array<std::array<BindingInfo, kMaxBindingsPerGroup>, kMaxBindGroups>;
|
||||||
|
|
|
@ -25,6 +25,7 @@ TEST_P(StorageTextureTests, BindGroupLayoutWithStorageTextureBindingType) {
|
||||||
{
|
{
|
||||||
wgpu::BindGroupLayoutBinding binding = {0, wgpu::ShaderStage::Compute,
|
wgpu::BindGroupLayoutBinding binding = {0, wgpu::ShaderStage::Compute,
|
||||||
wgpu::BindingType::ReadonlyStorageTexture};
|
wgpu::BindingType::ReadonlyStorageTexture};
|
||||||
|
binding.storageTextureFormat = wgpu::TextureFormat::R32Float;
|
||||||
wgpu::BindGroupLayoutDescriptor descriptor;
|
wgpu::BindGroupLayoutDescriptor descriptor;
|
||||||
descriptor.bindingCount = 1;
|
descriptor.bindingCount = 1;
|
||||||
descriptor.bindings = &binding;
|
descriptor.bindings = &binding;
|
||||||
|
@ -36,6 +37,7 @@ TEST_P(StorageTextureTests, BindGroupLayoutWithStorageTextureBindingType) {
|
||||||
{
|
{
|
||||||
wgpu::BindGroupLayoutBinding binding = {0, wgpu::ShaderStage::Compute,
|
wgpu::BindGroupLayoutBinding binding = {0, wgpu::ShaderStage::Compute,
|
||||||
wgpu::BindingType::WriteonlyStorageTexture};
|
wgpu::BindingType::WriteonlyStorageTexture};
|
||||||
|
binding.storageTextureFormat = wgpu::TextureFormat::R32Float;
|
||||||
wgpu::BindGroupLayoutDescriptor descriptor;
|
wgpu::BindGroupLayoutDescriptor descriptor;
|
||||||
descriptor.bindingCount = 1;
|
descriptor.bindingCount = 1;
|
||||||
descriptor.bindings = &binding;
|
descriptor.bindings = &binding;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "common/Assert.h"
|
#include "common/Assert.h"
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -185,21 +186,7 @@ class TextureFormatTest : public DawnTest {
|
||||||
})");
|
})");
|
||||||
|
|
||||||
// Compute the prefix needed for GLSL types that handle our texture's data.
|
// Compute the prefix needed for GLSL types that handle our texture's data.
|
||||||
const char* prefix = nullptr;
|
const char* prefix = utils::GetColorTextureComponentTypePrefix(sampleFormatInfo.format);
|
||||||
switch (sampleFormatInfo.type) {
|
|
||||||
case wgpu::TextureComponentType::Float:
|
|
||||||
prefix = "";
|
|
||||||
break;
|
|
||||||
case wgpu::TextureComponentType::Sint:
|
|
||||||
prefix = "i";
|
|
||||||
break;
|
|
||||||
case wgpu::TextureComponentType::Uint:
|
|
||||||
prefix = "u";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostringstream fsSource;
|
std::ostringstream fsSource;
|
||||||
fsSource << "#version 450\n";
|
fsSource << "#version 450\n";
|
||||||
|
|
|
@ -12,19 +12,132 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "common/Assert.h"
|
||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#include "tests/unittests/validation/ValidationTest.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
class StorageTextureValidationTests : public ValidationTest {
|
class StorageTextureValidationTests : public ValidationTest {
|
||||||
protected:
|
protected:
|
||||||
wgpu::ShaderModule mDefaultVSModule =
|
static const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
|
||||||
|
switch (textureFormat) {
|
||||||
|
case wgpu::TextureFormat::R8Unorm:
|
||||||
|
return "r8";
|
||||||
|
case wgpu::TextureFormat::R8Snorm:
|
||||||
|
return "r8_snorm";
|
||||||
|
case wgpu::TextureFormat::R8Uint:
|
||||||
|
return "r8ui";
|
||||||
|
case wgpu::TextureFormat::R8Sint:
|
||||||
|
return "r8i";
|
||||||
|
case wgpu::TextureFormat::R16Uint:
|
||||||
|
return "r16ui";
|
||||||
|
case wgpu::TextureFormat::R16Sint:
|
||||||
|
return "r16i";
|
||||||
|
case wgpu::TextureFormat::R16Float:
|
||||||
|
return "r16f";
|
||||||
|
case wgpu::TextureFormat::RG8Unorm:
|
||||||
|
return "rg8";
|
||||||
|
case wgpu::TextureFormat::RG8Snorm:
|
||||||
|
return "rg8_snorm";
|
||||||
|
case wgpu::TextureFormat::RG8Uint:
|
||||||
|
return "rg8ui";
|
||||||
|
case wgpu::TextureFormat::RG8Sint:
|
||||||
|
return "rg8i";
|
||||||
|
case wgpu::TextureFormat::R32Float:
|
||||||
|
return "r32f";
|
||||||
|
case wgpu::TextureFormat::R32Uint:
|
||||||
|
return "r32ui";
|
||||||
|
case wgpu::TextureFormat::R32Sint:
|
||||||
|
return "r32i";
|
||||||
|
case wgpu::TextureFormat::RG16Uint:
|
||||||
|
return "rg16ui";
|
||||||
|
case wgpu::TextureFormat::RG16Sint:
|
||||||
|
return "rg16i";
|
||||||
|
case wgpu::TextureFormat::RG16Float:
|
||||||
|
return "rg16f";
|
||||||
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
return "rgba8";
|
||||||
|
case wgpu::TextureFormat::RGBA8Snorm:
|
||||||
|
return "rgba8_snorm";
|
||||||
|
case wgpu::TextureFormat::RGBA8Uint:
|
||||||
|
return "rgba8ui";
|
||||||
|
case wgpu::TextureFormat::RGBA8Sint:
|
||||||
|
return "rgba8i";
|
||||||
|
case wgpu::TextureFormat::RGB10A2Unorm:
|
||||||
|
return "rgb10_a2";
|
||||||
|
case wgpu::TextureFormat::RG11B10Float:
|
||||||
|
return "r11f_g11f_b10f";
|
||||||
|
case wgpu::TextureFormat::RG32Float:
|
||||||
|
return "rg32f";
|
||||||
|
case wgpu::TextureFormat::RG32Uint:
|
||||||
|
return "rg32ui";
|
||||||
|
case wgpu::TextureFormat::RG32Sint:
|
||||||
|
return "rg32i";
|
||||||
|
case wgpu::TextureFormat::RGBA16Uint:
|
||||||
|
return "rgba16ui";
|
||||||
|
case wgpu::TextureFormat::RGBA16Sint:
|
||||||
|
return "rgba16i";
|
||||||
|
case wgpu::TextureFormat::RGBA16Float:
|
||||||
|
return "rgba16f";
|
||||||
|
case wgpu::TextureFormat::RGBA32Float:
|
||||||
|
return "rgba32f";
|
||||||
|
case wgpu::TextureFormat::RGBA32Uint:
|
||||||
|
return "rgba32ui";
|
||||||
|
case wgpu::TextureFormat::RGBA32Sint:
|
||||||
|
return "rgba32i";
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string CreateComputeShaderWithStorageTexture(
|
||||||
|
wgpu::BindingType storageTextureBindingType,
|
||||||
|
wgpu::TextureFormat textureFormat) {
|
||||||
|
const char* glslImageFormatQualifier = GetGLSLImageFormatQualifier(textureFormat);
|
||||||
|
const char* textureComponentTypePrefix =
|
||||||
|
utils::GetColorTextureComponentTypePrefix(textureFormat);
|
||||||
|
return CreateComputeShaderWithStorageTexture(
|
||||||
|
storageTextureBindingType, glslImageFormatQualifier, textureComponentTypePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string CreateComputeShaderWithStorageTexture(
|
||||||
|
wgpu::BindingType storageTextureBindingType,
|
||||||
|
const char* glslImageFormatQualifier,
|
||||||
|
const char* textureComponentTypePrefix) {
|
||||||
|
const char* memoryQualifier = "";
|
||||||
|
switch (storageTextureBindingType) {
|
||||||
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
|
memoryQualifier = "readonly";
|
||||||
|
break;
|
||||||
|
case wgpu::BindingType::WriteonlyStorageTexture:
|
||||||
|
memoryQualifier = "writeonly";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream ostream;
|
||||||
|
ostream << "#version 450\n"
|
||||||
|
"layout (set = 0, binding = 0, "
|
||||||
|
<< glslImageFormatQualifier << ") uniform " << memoryQualifier << " "
|
||||||
|
<< textureComponentTypePrefix
|
||||||
|
<< "image2D image0;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
return ostream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const wgpu::ShaderModule mDefaultVSModule =
|
||||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||||
#version 450
|
#version 450
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
|
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
|
||||||
})");
|
})");
|
||||||
wgpu::ShaderModule mDefaultFSModule =
|
const wgpu::ShaderModule mDefaultFSModule =
|
||||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||||
#version 450
|
#version 450
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
@ -227,6 +340,7 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingTy
|
||||||
|
|
||||||
for (const auto& testSpec : kTestSpecs) {
|
for (const auto& testSpec : kTestSpecs) {
|
||||||
wgpu::BindGroupLayoutBinding binding = {0, testSpec.stage, testSpec.type};
|
wgpu::BindGroupLayoutBinding binding = {0, testSpec.stage, testSpec.type};
|
||||||
|
binding.storageTextureFormat = wgpu::TextureFormat::R32Uint;
|
||||||
wgpu::BindGroupLayoutDescriptor descriptor;
|
wgpu::BindGroupLayoutDescriptor descriptor;
|
||||||
descriptor.bindingCount = 1;
|
descriptor.bindingCount = 1;
|
||||||
descriptor.bindings = &binding;
|
descriptor.bindings = &binding;
|
||||||
|
@ -238,3 +352,73 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate it is an error to declare a read-only or write-only storage texture in shaders with any
|
||||||
|
// format that doesn't support TextureUsage::Storage texture usages.
|
||||||
|
TEST_F(StorageTextureValidationTests, StorageTextureFormatInShaders) {
|
||||||
|
// Not include RGBA8UnormSrgb, BGRA8Unorm, BGRA8UnormSrgb because they are not related to any
|
||||||
|
// SPIR-V Image Formats.
|
||||||
|
constexpr std::array<wgpu::TextureFormat, 32> kWGPUTextureFormatSupportedAsSPIRVImageFormats = {
|
||||||
|
wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint,
|
||||||
|
wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RGBA8Unorm,
|
||||||
|
wgpu::TextureFormat::RGBA8Snorm, wgpu::TextureFormat::RGBA8Uint,
|
||||||
|
wgpu::TextureFormat::RGBA8Sint, wgpu::TextureFormat::RG32Uint,
|
||||||
|
wgpu::TextureFormat::RG32Sint, wgpu::TextureFormat::RG32Float,
|
||||||
|
wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint,
|
||||||
|
wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Uint,
|
||||||
|
wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::RGBA32Float,
|
||||||
|
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Snorm,
|
||||||
|
wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint,
|
||||||
|
wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint,
|
||||||
|
wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RG8Unorm,
|
||||||
|
wgpu::TextureFormat::RG8Snorm, wgpu::TextureFormat::RG8Uint,
|
||||||
|
wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::RG16Uint,
|
||||||
|
wgpu::TextureFormat::RG16Sint, wgpu::TextureFormat::RG16Float,
|
||||||
|
wgpu::TextureFormat::RGB10A2Unorm, wgpu::TextureFormat::RG11B10Float};
|
||||||
|
|
||||||
|
constexpr std::array<wgpu::BindingType, 2> kStorageTextureBindingTypes = {
|
||||||
|
wgpu::BindingType::ReadonlyStorageTexture, wgpu::BindingType::WriteonlyStorageTexture};
|
||||||
|
|
||||||
|
for (wgpu::BindingType storageTextureBindingType : kStorageTextureBindingTypes) {
|
||||||
|
for (wgpu::TextureFormat format : kWGPUTextureFormatSupportedAsSPIRVImageFormats) {
|
||||||
|
std::string computeShader =
|
||||||
|
CreateComputeShaderWithStorageTexture(storageTextureBindingType, format);
|
||||||
|
if (utils::TextureFormatSupportsStorageTexture(format)) {
|
||||||
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute,
|
||||||
|
computeShader.c_str());
|
||||||
|
} else {
|
||||||
|
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(
|
||||||
|
device, utils::SingleShaderStage::Compute, computeShader.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that declaring a storage texture format that is not supported in WebGPU causes validation
|
||||||
|
// error.
|
||||||
|
TEST_F(StorageTextureValidationTests, UnsupportedSPIRVStorageTextureFormat) {
|
||||||
|
struct TextureFormatInfo {
|
||||||
|
const char* name;
|
||||||
|
const char* componentTypePrefix;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<TextureFormatInfo, 7> kUnsupportedTextureFormats = {{{"rgba16", ""},
|
||||||
|
{"rg16", ""},
|
||||||
|
{"r16", ""},
|
||||||
|
{"rgba16_snorm", ""},
|
||||||
|
{"rg16_snorm", ""},
|
||||||
|
{"r16_snorm", ""},
|
||||||
|
{"rgb10_a2ui", "u"}}};
|
||||||
|
|
||||||
|
constexpr std::array<wgpu::BindingType, 2> kStorageTextureBindingTypes = {
|
||||||
|
wgpu::BindingType::ReadonlyStorageTexture, wgpu::BindingType::WriteonlyStorageTexture};
|
||||||
|
|
||||||
|
for (wgpu::BindingType bindingType : kStorageTextureBindingTypes) {
|
||||||
|
for (const TextureFormatInfo& formatInfo : kUnsupportedTextureFormats) {
|
||||||
|
std::string computeShader = CreateComputeShaderWithStorageTexture(
|
||||||
|
bindingType, formatInfo.name, formatInfo.componentTypePrefix);
|
||||||
|
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, utils::SingleShaderStage::Compute,
|
||||||
|
computeShader.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -345,38 +346,14 @@ TEST_F(TextureValidationTest, TextureFormatNotSupportTextureUsageStorage) {
|
||||||
descriptor.size = {1, 1, 1};
|
descriptor.size = {1, 1, 1};
|
||||||
descriptor.usage = wgpu::TextureUsage::Storage;
|
descriptor.usage = wgpu::TextureUsage::Storage;
|
||||||
|
|
||||||
wgpu::TextureFormat kSupportedFormatsWithStorageUsage[] = {
|
for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
|
||||||
wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint,
|
|
||||||
wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::RGBA8Unorm,
|
|
||||||
wgpu::TextureFormat::RGBA8Snorm, wgpu::TextureFormat::RGBA8Uint,
|
|
||||||
wgpu::TextureFormat::RGBA8Sint, wgpu::TextureFormat::RG32Uint,
|
|
||||||
wgpu::TextureFormat::RG32Sint, wgpu::TextureFormat::RG32Float,
|
|
||||||
wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint,
|
|
||||||
wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Uint,
|
|
||||||
wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::RGBA32Float};
|
|
||||||
for (wgpu::TextureFormat format : kSupportedFormatsWithStorageUsage) {
|
|
||||||
descriptor.format = format;
|
descriptor.format = format;
|
||||||
|
if (utils::TextureFormatSupportsStorageTexture(format)) {
|
||||||
device.CreateTexture(&descriptor);
|
device.CreateTexture(&descriptor);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
wgpu::TextureFormat kUnsupportedFormatsWithStorageUsage[] = {
|
|
||||||
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Snorm,
|
|
||||||
wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint,
|
|
||||||
wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint,
|
|
||||||
wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RG8Unorm,
|
|
||||||
wgpu::TextureFormat::RG8Snorm, wgpu::TextureFormat::RG8Uint,
|
|
||||||
wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::RG16Uint,
|
|
||||||
wgpu::TextureFormat::RG16Sint, wgpu::TextureFormat::RG16Float,
|
|
||||||
wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::BGRA8Unorm,
|
|
||||||
wgpu::TextureFormat::BGRA8UnormSrgb, wgpu::TextureFormat::RGB10A2Unorm,
|
|
||||||
wgpu::TextureFormat::RG11B10Float,
|
|
||||||
|
|
||||||
wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Depth24PlusStencil8,
|
|
||||||
wgpu::TextureFormat::Depth32Float};
|
|
||||||
for (wgpu::TextureFormat format : kUnsupportedFormatsWithStorageUsage) {
|
|
||||||
descriptor.format = format;
|
|
||||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test it is an error to create a texture with format "Undefined".
|
// Test it is an error to create a texture with format "Undefined".
|
||||||
|
|
|
@ -26,6 +26,8 @@ target_sources(dawn_utils PRIVATE
|
||||||
"SystemUtils.h"
|
"SystemUtils.h"
|
||||||
"TerribleCommandBuffer.cpp"
|
"TerribleCommandBuffer.cpp"
|
||||||
"TerribleCommandBuffer.h"
|
"TerribleCommandBuffer.h"
|
||||||
|
"TextureFormatUtils.cpp"
|
||||||
|
"TextureFormatUtils.h"
|
||||||
"Timer.h"
|
"Timer.h"
|
||||||
"WGPUHelpers.cpp"
|
"WGPUHelpers.cpp"
|
||||||
"WGPUHelpers.h"
|
"WGPUHelpers.h"
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "TextureFormatUtils.h"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat) {
|
||||||
|
switch (textureFormat) {
|
||||||
|
case wgpu::TextureFormat::R8Unorm:
|
||||||
|
case wgpu::TextureFormat::R8Snorm:
|
||||||
|
case wgpu::TextureFormat::R16Float:
|
||||||
|
case wgpu::TextureFormat::RG8Unorm:
|
||||||
|
case wgpu::TextureFormat::RG8Snorm:
|
||||||
|
case wgpu::TextureFormat::R32Float:
|
||||||
|
case wgpu::TextureFormat::RG16Float:
|
||||||
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8Snorm:
|
||||||
|
case wgpu::TextureFormat::RGB10A2Unorm:
|
||||||
|
case wgpu::TextureFormat::RG11B10Float:
|
||||||
|
case wgpu::TextureFormat::RG32Float:
|
||||||
|
case wgpu::TextureFormat::RGBA16Float:
|
||||||
|
case wgpu::TextureFormat::RGBA32Float:
|
||||||
|
case wgpu::TextureFormat::BGRA8Unorm:
|
||||||
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||||
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||||
|
return "";
|
||||||
|
|
||||||
|
case wgpu::TextureFormat::R8Uint:
|
||||||
|
case wgpu::TextureFormat::R16Uint:
|
||||||
|
case wgpu::TextureFormat::RG8Uint:
|
||||||
|
case wgpu::TextureFormat::R32Uint:
|
||||||
|
case wgpu::TextureFormat::RG16Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA8Uint:
|
||||||
|
case wgpu::TextureFormat::RG32Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA32Uint:
|
||||||
|
return "u";
|
||||||
|
|
||||||
|
case wgpu::TextureFormat::R8Sint:
|
||||||
|
case wgpu::TextureFormat::R16Sint:
|
||||||
|
case wgpu::TextureFormat::RG8Sint:
|
||||||
|
case wgpu::TextureFormat::R32Sint:
|
||||||
|
case wgpu::TextureFormat::RG16Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA8Sint:
|
||||||
|
case wgpu::TextureFormat::RG32Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA32Sint:
|
||||||
|
return "i";
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R32Uint:
|
||||||
|
case wgpu::TextureFormat::R32Sint:
|
||||||
|
case wgpu::TextureFormat::R32Float:
|
||||||
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8Snorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA8Sint:
|
||||||
|
case wgpu::TextureFormat::RG32Uint:
|
||||||
|
case wgpu::TextureFormat::RG32Sint:
|
||||||
|
case wgpu::TextureFormat::RG32Float:
|
||||||
|
case wgpu::TextureFormat::RGBA16Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Float:
|
||||||
|
case wgpu::TextureFormat::RGBA32Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA32Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA32Float:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace utils
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef UTILS_TEXTURE_FORMAT_UTILS_H_
|
||||||
|
#define UTILS_TEXTURE_FORMAT_UTILS_H_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <dawn/webgpu_cpp.h>
|
||||||
|
|
||||||
|
#include "common/Assert.h"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
static constexpr std::array<wgpu::TextureFormat, 52> kAllTextureFormats = {
|
||||||
|
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Snorm,
|
||||||
|
wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint,
|
||||||
|
wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint,
|
||||||
|
wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RG8Unorm,
|
||||||
|
wgpu::TextureFormat::RG8Snorm, wgpu::TextureFormat::RG8Uint,
|
||||||
|
wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::R32Float,
|
||||||
|
wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint,
|
||||||
|
wgpu::TextureFormat::RG16Uint, wgpu::TextureFormat::RG16Sint,
|
||||||
|
wgpu::TextureFormat::RG16Float, wgpu::TextureFormat::RGBA8Unorm,
|
||||||
|
wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::RGBA8Snorm,
|
||||||
|
wgpu::TextureFormat::RGBA8Uint, wgpu::TextureFormat::RGBA8Sint,
|
||||||
|
wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::BGRA8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::RGB10A2Unorm, wgpu::TextureFormat::RG11B10Float,
|
||||||
|
wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::RG32Uint,
|
||||||
|
wgpu::TextureFormat::RG32Sint, wgpu::TextureFormat::RGBA16Uint,
|
||||||
|
wgpu::TextureFormat::RGBA16Sint, wgpu::TextureFormat::RGBA16Float,
|
||||||
|
wgpu::TextureFormat::RGBA32Float, wgpu::TextureFormat::RGBA32Uint,
|
||||||
|
wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::Depth32Float,
|
||||||
|
wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Depth24PlusStencil8,
|
||||||
|
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
|
||||||
|
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
|
||||||
|
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBSfloat,
|
||||||
|
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat);
|
||||||
|
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue