Make TextureComponentType an internal enum
Fixed: dawn:1682 Change-Id: Iadbe7e2829805fed9a7f7e3bb0925544f4318380 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/130440 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
ba242e53cc
commit
7b82609894
10
dawn.json
10
dawn.json
|
@ -2671,16 +2671,6 @@
|
|||
{"value": 4, "name": "plane 1 only", "tags": ["dawn"]}
|
||||
]
|
||||
},
|
||||
"texture component type": {
|
||||
"category": "enum",
|
||||
"tags": ["dawn"],
|
||||
"values": [
|
||||
{"value": 0, "name": "float"},
|
||||
{"value": 1, "name": "sint"},
|
||||
{"value": 2, "name": "uint"},
|
||||
{"value": 3, "name": "depth comparison"}
|
||||
]
|
||||
},
|
||||
"texture data layout": {
|
||||
"category": "structure",
|
||||
"extensible": "in",
|
||||
|
|
|
@ -51,13 +51,11 @@ const char* GetTextureComponentTypeString(DeviceBase* device, wgpu::TextureForma
|
|||
|
||||
const Format& formatInfo = device->GetValidInternalFormat(format);
|
||||
switch (formatInfo.GetAspectInfo(Aspect::Color).baseType) {
|
||||
case wgpu::TextureComponentType::Sint:
|
||||
case TextureComponentType::Sint:
|
||||
return "i32";
|
||||
case wgpu::TextureComponentType::Uint:
|
||||
case TextureComponentType::Uint:
|
||||
return "u32";
|
||||
case wgpu::TextureComponentType::Float:
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
default:
|
||||
case TextureComponentType::Float:
|
||||
UNREACHABLE();
|
||||
return "";
|
||||
}
|
||||
|
@ -178,12 +176,12 @@ ResultOrError<Ref<BufferBase>> CreateUniformBufferWithClearValues(
|
|||
uint32_t offset = 0;
|
||||
for (uint32_t i : IterateBitSet(key.colorTargetsToApplyClearColorValue)) {
|
||||
const Format& format = renderPassDescriptor->colorAttachments[i].view->GetFormat();
|
||||
wgpu::TextureComponentType baseType = format.GetAspectInfo(Aspect::Color).baseType;
|
||||
TextureComponentType baseType = format.GetAspectInfo(Aspect::Color).baseType;
|
||||
|
||||
Color initialClearValue = GetClearColorValue(renderPassDescriptor->colorAttachments[i]);
|
||||
Color clearValue = ClampClearColorValueToLegalRange(initialClearValue, format);
|
||||
switch (baseType) {
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
uint32_t* clearValuePtr = reinterpret_cast<uint32_t*>(clearValues.data() + offset);
|
||||
clearValuePtr[0] = static_cast<uint32_t>(clearValue.r);
|
||||
clearValuePtr[1] = static_cast<uint32_t>(clearValue.g);
|
||||
|
@ -191,7 +189,7 @@ ResultOrError<Ref<BufferBase>> CreateUniformBufferWithClearValues(
|
|||
clearValuePtr[3] = static_cast<uint32_t>(clearValue.a);
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
int32_t* clearValuePtr = reinterpret_cast<int32_t*>(clearValues.data() + offset);
|
||||
clearValuePtr[0] = static_cast<int32_t>(clearValue.r);
|
||||
clearValuePtr[1] = static_cast<int32_t>(clearValue.g);
|
||||
|
@ -199,7 +197,7 @@ ResultOrError<Ref<BufferBase>> CreateUniformBufferWithClearValues(
|
|||
clearValuePtr[3] = static_cast<int32_t>(clearValue.a);
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Float: {
|
||||
case TextureComponentType::Float: {
|
||||
float* clearValuePtr = reinterpret_cast<float*>(clearValues.data() + offset);
|
||||
clearValuePtr[0] = static_cast<float>(clearValue.r);
|
||||
clearValuePtr[1] = static_cast<float>(clearValue.g);
|
||||
|
@ -207,11 +205,6 @@ ResultOrError<Ref<BufferBase>> CreateUniformBufferWithClearValues(
|
|||
clearValuePtr[3] = static_cast<float>(clearValue.a);
|
||||
break;
|
||||
}
|
||||
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
offset += sizeof(uint32_t) * 4;
|
||||
}
|
||||
|
@ -255,7 +248,7 @@ bool ShouldApplyClearBigIntegerColorValueWithDraw(
|
|||
// TODO(dawn:537): only check the color channels that are available in the current color format.
|
||||
Color clearValue = GetClearColorValue(colorAttachmentInfo);
|
||||
switch (format.GetAspectInfo(Aspect::Color).baseType) {
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
constexpr double kMaxUintRepresentableInFloat = 1 << std::numeric_limits<float>::digits;
|
||||
if (clearValue.r <= kMaxUintRepresentableInFloat &&
|
||||
clearValue.g <= kMaxUintRepresentableInFloat &&
|
||||
|
@ -265,7 +258,7 @@ bool ShouldApplyClearBigIntegerColorValueWithDraw(
|
|||
}
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
constexpr double kMaxSintRepresentableInFloat = 1 << std::numeric_limits<float>::digits;
|
||||
constexpr double kMinSintRepresentableInFloat = -kMaxSintRepresentableInFloat;
|
||||
if (clearValue.r <= kMaxSintRepresentableInFloat &&
|
||||
|
@ -280,9 +273,7 @@ bool ShouldApplyClearBigIntegerColorValueWithDraw(
|
|||
}
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Float:
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
default:
|
||||
case TextureComponentType::Float:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -636,10 +636,10 @@ Color ClampClearColorValueToLegalRange(const Color& originalColor, const Format&
|
|||
double minValue = 0;
|
||||
double maxValue = 0;
|
||||
switch (aspectInfo.baseType) {
|
||||
case wgpu::TextureComponentType::Float: {
|
||||
case TextureComponentType::Float: {
|
||||
return originalColor;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
const uint32_t bitsPerComponent =
|
||||
(aspectInfo.block.byteSize * 8 / format.componentCount);
|
||||
maxValue =
|
||||
|
@ -647,16 +647,12 @@ Color ClampClearColorValueToLegalRange(const Color& originalColor, const Format&
|
|||
minValue = -static_cast<double>(static_cast<uint64_t>(1) << (bitsPerComponent - 1));
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
const uint32_t bitsPerComponent =
|
||||
(aspectInfo.block.byteSize * 8 / format.componentCount);
|
||||
maxValue = static_cast<double>((static_cast<uint64_t>(1) << bitsPerComponent) - 1);
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
return {std::clamp(originalColor.r, minValue, maxValue),
|
||||
|
|
|
@ -205,20 +205,20 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
|
|||
switch (sampleTypes) {
|
||||
case SampleTypeBit::Float:
|
||||
case SampleTypeBit::UnfilterableFloat:
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Float;
|
||||
firstAspect->baseType = TextureComponentType::Float;
|
||||
break;
|
||||
case SampleTypeBit::Sint:
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Sint;
|
||||
firstAspect->baseType = TextureComponentType::Sint;
|
||||
break;
|
||||
case SampleTypeBit::Uint:
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Uint;
|
||||
firstAspect->baseType = TextureComponentType::Uint;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
ASSERT(sampleTypes & SampleTypeBit::Float);
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Float;
|
||||
firstAspect->baseType = TextureComponentType::Float;
|
||||
}
|
||||
firstAspect->supportedSampleTypes = sampleTypes;
|
||||
firstAspect->format = format;
|
||||
|
@ -243,7 +243,7 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
|
|||
firstAspect->block.byteSize = byteSize;
|
||||
firstAspect->block.width = 1;
|
||||
firstAspect->block.height = 1;
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Float;
|
||||
firstAspect->baseType = TextureComponentType::Float;
|
||||
firstAspect->supportedSampleTypes = SampleTypeBit::Depth | SampleTypeBit::UnfilterableFloat;
|
||||
firstAspect->format = format;
|
||||
AddFormat(internalFormat);
|
||||
|
@ -272,7 +272,7 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
|
|||
internalFormat.aspectInfo[0].block.byteSize = 1;
|
||||
internalFormat.aspectInfo[0].block.width = 1;
|
||||
internalFormat.aspectInfo[0].block.height = 1;
|
||||
internalFormat.aspectInfo[0].baseType = wgpu::TextureComponentType::Uint;
|
||||
internalFormat.aspectInfo[0].baseType = TextureComponentType::Uint;
|
||||
internalFormat.aspectInfo[0].supportedSampleTypes = SampleTypeBit::Uint;
|
||||
internalFormat.aspectInfo[0].format = format;
|
||||
|
||||
|
@ -307,7 +307,7 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
|
|||
firstAspect->block.byteSize = byteSize;
|
||||
firstAspect->block.width = width;
|
||||
firstAspect->block.height = height;
|
||||
firstAspect->baseType = wgpu::TextureComponentType::Float;
|
||||
firstAspect->baseType = TextureComponentType::Float;
|
||||
firstAspect->supportedSampleTypes = kAnyFloat;
|
||||
firstAspect->format = format;
|
||||
AddFormat(internalFormat);
|
||||
|
|
|
@ -66,11 +66,15 @@ struct TexelBlockInfo {
|
|||
uint32_t height;
|
||||
};
|
||||
|
||||
enum class TextureComponentType {
|
||||
Float,
|
||||
Sint,
|
||||
Uint,
|
||||
};
|
||||
|
||||
struct AspectInfo {
|
||||
TexelBlockInfo block;
|
||||
// TODO(crbug.com/dawn/367): Replace TextureComponentType with TextureSampleType, or make it
|
||||
// an internal Dawn enum.
|
||||
wgpu::TextureComponentType baseType{};
|
||||
TextureComponentType baseType{};
|
||||
SampleTypeBit supportedSampleTypes{};
|
||||
wgpu::TextureFormat format = wgpu::TextureFormat::Undefined;
|
||||
};
|
||||
|
|
|
@ -156,16 +156,16 @@ SampleTypeBit TintSampledKindToSampleTypeBit(tint::inspector::ResourceBinding::S
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ResultOrError<wgpu::TextureComponentType> TintComponentTypeToTextureComponentType(
|
||||
ResultOrError<TextureComponentType> TintComponentTypeToTextureComponentType(
|
||||
tint::inspector::ComponentType type) {
|
||||
switch (type) {
|
||||
case tint::inspector::ComponentType::kF32:
|
||||
case tint::inspector::ComponentType::kF16:
|
||||
return wgpu::TextureComponentType::Float;
|
||||
return TextureComponentType::Float;
|
||||
case tint::inspector::ComponentType::kI32:
|
||||
return wgpu::TextureComponentType::Sint;
|
||||
return TextureComponentType::Sint;
|
||||
case tint::inspector::ComponentType::kU32:
|
||||
return wgpu::TextureComponentType::Uint;
|
||||
return TextureComponentType::Uint;
|
||||
case tint::inspector::ComponentType::kUnknown:
|
||||
return DAWN_VALIDATION_ERROR("Attempted to convert 'Unknown' component type from Tint");
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ struct EntryPointMetadata {
|
|||
|
||||
// An array to record the basic types (float, int and uint) of the fragment shader outputs.
|
||||
struct FragmentOutputVariableInfo {
|
||||
wgpu::TextureComponentType baseType;
|
||||
TextureComponentType baseType;
|
||||
uint8_t componentCount;
|
||||
};
|
||||
ityp::array<ColorAttachmentIndex, FragmentOutputVariableInfo, kMaxColorAttachments>
|
||||
|
|
|
@ -69,7 +69,7 @@ D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS D3D12EndingAccessResolveParam
|
|||
|
||||
// RESOLVE_MODE_AVERAGE is only valid for non-integer formats.
|
||||
ASSERT(resolveDestination->GetFormat().GetAspectInfo(Aspect::Color).baseType ==
|
||||
wgpu::TextureComponentType::Float);
|
||||
TextureComponentType::Float);
|
||||
resolveParameters.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE;
|
||||
|
||||
resolveParameters.SubresourceCount = 1;
|
||||
|
|
|
@ -934,30 +934,27 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
|
|||
if (attachmentInfo->loadOp == wgpu::LoadOp::Clear) {
|
||||
gl.ColorMask(true, true, true, true);
|
||||
|
||||
wgpu::TextureComponentType baseType =
|
||||
TextureComponentType baseType =
|
||||
attachmentInfo->view->GetFormat().GetAspectInfo(Aspect::Color).baseType;
|
||||
switch (baseType) {
|
||||
case wgpu::TextureComponentType::Float: {
|
||||
case TextureComponentType::Float: {
|
||||
const std::array<float, 4> appliedClearColor =
|
||||
ConvertToFloatColor(attachmentInfo->clearColor);
|
||||
gl.ClearBufferfv(GL_COLOR, i, appliedClearColor.data());
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
const std::array<uint32_t, 4> appliedClearColor =
|
||||
ConvertToUnsignedIntegerColor(attachmentInfo->clearColor);
|
||||
gl.ClearBufferuiv(GL_COLOR, i, appliedClearColor.data());
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
const std::array<int32_t, 4> appliedClearColor =
|
||||
ConvertToSignedIntegerColor(attachmentInfo->clearColor);
|
||||
gl.ClearBufferiv(GL_COLOR, i, appliedClearColor.data());
|
||||
break;
|
||||
}
|
||||
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ MaybeError Texture::ClearTexture(const SubresourceRange& range,
|
|||
constexpr std::array<GLbyte, MAX_TEXEL_SIZE> kClearColorDataBytes255 = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
wgpu::TextureComponentType baseType = GetFormat().GetAspectInfo(Aspect::Color).baseType;
|
||||
TextureComponentType baseType = GetFormat().GetAspectInfo(Aspect::Color).baseType;
|
||||
|
||||
const GLFormat& glFormat = GetGLFormat();
|
||||
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||
|
@ -409,21 +409,21 @@ MaybeError Texture::ClearTexture(const SubresourceRange& range,
|
|||
|
||||
auto DoClear = [&]() {
|
||||
switch (baseType) {
|
||||
case wgpu::TextureComponentType::Float: {
|
||||
case TextureComponentType::Float: {
|
||||
gl.ClearBufferfv(GL_COLOR, 0,
|
||||
clearValue == TextureBase::ClearValue::Zero
|
||||
? kClearColorDataFloat0.data()
|
||||
: kClearColorDataFloat1.data());
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
gl.ClearBufferuiv(GL_COLOR, 0,
|
||||
clearValue == TextureBase::ClearValue::Zero
|
||||
? kClearColorDataUint0.data()
|
||||
: kClearColorDataUint1.data());
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
gl.ClearBufferiv(GL_COLOR, 0,
|
||||
reinterpret_cast<const GLint*>(
|
||||
clearValue == TextureBase::ClearValue::Zero
|
||||
|
@ -431,9 +431,6 @@ MaybeError Texture::ClearTexture(const SubresourceRange& range,
|
|||
: kClearColorDataUint1.data()));
|
||||
break;
|
||||
}
|
||||
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext,
|
|||
attachments[attachmentCount] = view->GetHandle();
|
||||
|
||||
switch (view->GetFormat().GetAspectInfo(Aspect::Color).baseType) {
|
||||
case wgpu::TextureComponentType::Float: {
|
||||
case TextureComponentType::Float: {
|
||||
const std::array<float, 4> appliedClearColor =
|
||||
ConvertToFloatColor(attachmentInfo.clearColor);
|
||||
for (uint32_t i = 0; i < 4; ++i) {
|
||||
|
@ -260,7 +260,7 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Uint: {
|
||||
case TextureComponentType::Uint: {
|
||||
const std::array<uint32_t, 4> appliedClearColor =
|
||||
ConvertToUnsignedIntegerColor(attachmentInfo.clearColor);
|
||||
for (uint32_t i = 0; i < 4; ++i) {
|
||||
|
@ -268,7 +268,7 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case wgpu::TextureComponentType::Sint: {
|
||||
case TextureComponentType::Sint: {
|
||||
const std::array<int32_t, 4> appliedClearColor =
|
||||
ConvertToSignedIntegerColor(attachmentInfo.clearColor);
|
||||
for (uint32_t i = 0; i < 4; ++i) {
|
||||
|
@ -276,9 +276,6 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext,
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
UNREACHABLE();
|
||||
}
|
||||
attachmentCount++;
|
||||
}
|
||||
|
|
|
@ -1341,26 +1341,24 @@ MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
|
|||
ASSERT(aspects == Aspect::Color);
|
||||
VkClearColorValue clearColorValue;
|
||||
switch (GetFormat().GetAspectInfo(Aspect::Color).baseType) {
|
||||
case wgpu::TextureComponentType::Float:
|
||||
case TextureComponentType::Float:
|
||||
clearColorValue.float32[0] = fClearColor;
|
||||
clearColorValue.float32[1] = fClearColor;
|
||||
clearColorValue.float32[2] = fClearColor;
|
||||
clearColorValue.float32[3] = fClearColor;
|
||||
break;
|
||||
case wgpu::TextureComponentType::Sint:
|
||||
case TextureComponentType::Sint:
|
||||
clearColorValue.int32[0] = sClearColor;
|
||||
clearColorValue.int32[1] = sClearColor;
|
||||
clearColorValue.int32[2] = sClearColor;
|
||||
clearColorValue.int32[3] = sClearColor;
|
||||
break;
|
||||
case wgpu::TextureComponentType::Uint:
|
||||
case TextureComponentType::Uint:
|
||||
clearColorValue.uint32[0] = uClearColor;
|
||||
clearColorValue.uint32[1] = uClearColor;
|
||||
clearColorValue.uint32[2] = uClearColor;
|
||||
clearColorValue.uint32[3] = uClearColor;
|
||||
break;
|
||||
case wgpu::TextureComponentType::DepthComparison:
|
||||
UNREACHABLE();
|
||||
}
|
||||
device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
|
|
|
@ -436,4 +436,22 @@ absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConv
|
|||
return {true};
|
||||
}
|
||||
|
||||
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
|
||||
TextureComponentType value,
|
||||
const absl::FormatConversionSpec& spec,
|
||||
absl::FormatSink* s) {
|
||||
switch (value) {
|
||||
case TextureComponentType::Float:
|
||||
s->Append("Float");
|
||||
break;
|
||||
case TextureComponentType::Sint:
|
||||
s->Append("Sint");
|
||||
break;
|
||||
case TextureComponentType::Uint:
|
||||
s->Append("Uint");
|
||||
break;
|
||||
}
|
||||
return {true};
|
||||
}
|
||||
|
||||
} // namespace dawn::native
|
||||
|
|
|
@ -129,6 +129,12 @@ absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConv
|
|||
const absl::FormatConversionSpec& spec,
|
||||
absl::FormatSink* s);
|
||||
|
||||
enum class TextureComponentType;
|
||||
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
|
||||
TextureComponentType value,
|
||||
const absl::FormatConversionSpec& spec,
|
||||
absl::FormatSink* s);
|
||||
|
||||
} // namespace dawn::native
|
||||
|
||||
#endif // SRC_DAWN_NATIVE_WEBGPU_ABSL_FORMAT_H_
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
#include "dawn/utils/TextureUtils.h"
|
||||
#include "dawn/utils/WGPUHelpers.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class TextureComponentType {
|
||||
Float,
|
||||
Sint,
|
||||
Uint,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// An expectation for float buffer content that can correctly compare different NaN values and
|
||||
// supports a basic tolerance for comparison of finite values.
|
||||
class ExpectFloatWithTolerance : public detail::Expectation {
|
||||
|
@ -194,7 +204,7 @@ class TextureFormatTest : public DawnTest {
|
|||
struct FormatTestInfo {
|
||||
wgpu::TextureFormat format;
|
||||
uint32_t texelByteSize;
|
||||
wgpu::TextureComponentType type;
|
||||
TextureComponentType type;
|
||||
uint32_t componentCount;
|
||||
};
|
||||
|
||||
|
@ -202,11 +212,11 @@ class TextureFormatTest : public DawnTest {
|
|||
// of the format. That the equivalent format with all channels 32bit-sized.
|
||||
FormatTestInfo GetUncompressedFormatInfo(FormatTestInfo formatInfo) {
|
||||
switch (formatInfo.type) {
|
||||
case wgpu::TextureComponentType::Float:
|
||||
case TextureComponentType::Float:
|
||||
return {wgpu::TextureFormat::RGBA32Float, 16, formatInfo.type, 4};
|
||||
case wgpu::TextureComponentType::Sint:
|
||||
case TextureComponentType::Sint:
|
||||
return {wgpu::TextureFormat::RGBA32Sint, 16, formatInfo.type, 4};
|
||||
case wgpu::TextureComponentType::Uint:
|
||||
case TextureComponentType::Uint:
|
||||
return {wgpu::TextureFormat::RGBA32Uint, 16, formatInfo.type, 4};
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -429,7 +439,7 @@ class TextureFormatTest : public DawnTest {
|
|||
void DoUnormTest(FormatTestInfo formatInfo) {
|
||||
static_assert(!std::is_signed<T>::value && std::is_integral<T>::value);
|
||||
ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Float);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Float);
|
||||
|
||||
T maxValue = std::numeric_limits<T>::max();
|
||||
std::vector<T> textureData = {0, 1, maxValue, maxValue};
|
||||
|
@ -443,7 +453,7 @@ class TextureFormatTest : public DawnTest {
|
|||
void DoSnormTest(FormatTestInfo formatInfo) {
|
||||
static_assert(std::is_signed<T>::value && std::is_integral<T>::value);
|
||||
ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Float);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Float);
|
||||
|
||||
T maxValue = std::numeric_limits<T>::max();
|
||||
T minValue = std::numeric_limits<T>::min();
|
||||
|
@ -459,7 +469,7 @@ class TextureFormatTest : public DawnTest {
|
|||
void DoUintTest(FormatTestInfo formatInfo) {
|
||||
static_assert(!std::is_signed<T>::value && std::is_integral<T>::value);
|
||||
ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Uint);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Uint);
|
||||
|
||||
T maxValue = std::numeric_limits<T>::max();
|
||||
std::vector<T> textureData = {0, 1, maxValue, maxValue};
|
||||
|
@ -473,7 +483,7 @@ class TextureFormatTest : public DawnTest {
|
|||
void DoSintTest(FormatTestInfo formatInfo) {
|
||||
static_assert(std::is_signed<T>::value && std::is_integral<T>::value);
|
||||
ASSERT(sizeof(T) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Sint);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Sint);
|
||||
|
||||
T maxValue = std::numeric_limits<T>::max();
|
||||
T minValue = std::numeric_limits<T>::min();
|
||||
|
@ -486,7 +496,7 @@ class TextureFormatTest : public DawnTest {
|
|||
|
||||
void DoFloat32Test(FormatTestInfo formatInfo) {
|
||||
ASSERT(sizeof(float) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Float);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Float);
|
||||
|
||||
std::vector<float> textureData = {+0.0f, -0.0f, 1.0f, 1.0e-29f,
|
||||
1.0e29f, NAN, INFINITY, -INFINITY};
|
||||
|
@ -498,7 +508,7 @@ class TextureFormatTest : public DawnTest {
|
|||
|
||||
void DoFloat16Test(FormatTestInfo formatInfo) {
|
||||
ASSERT(sizeof(int16_t) * formatInfo.componentCount == formatInfo.texelByteSize);
|
||||
ASSERT(formatInfo.type == wgpu::TextureComponentType::Float);
|
||||
ASSERT(formatInfo.type == TextureComponentType::Float);
|
||||
|
||||
std::vector<float> uncompressedData = {+0.0f, -0.0f, 1.0f, 1.01e-4f,
|
||||
1.0e4f, NAN, INFINITY, -INFINITY};
|
||||
|
@ -533,18 +543,17 @@ class TextureFormatTest : public DawnTest {
|
|||
|
||||
// Test the R8Unorm format
|
||||
TEST_P(TextureFormatTest, R8Unorm) {
|
||||
DoUnormTest<uint8_t>({wgpu::TextureFormat::R8Unorm, 1, wgpu::TextureComponentType::Float, 1});
|
||||
DoUnormTest<uint8_t>({wgpu::TextureFormat::R8Unorm, 1, TextureComponentType::Float, 1});
|
||||
}
|
||||
|
||||
// Test the RG8Unorm format
|
||||
TEST_P(TextureFormatTest, RG8Unorm) {
|
||||
DoUnormTest<uint8_t>({wgpu::TextureFormat::RG8Unorm, 2, wgpu::TextureComponentType::Float, 2});
|
||||
DoUnormTest<uint8_t>({wgpu::TextureFormat::RG8Unorm, 2, TextureComponentType::Float, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA8Unorm format
|
||||
TEST_P(TextureFormatTest, RGBA8Unorm) {
|
||||
DoUnormTest<uint8_t>(
|
||||
{wgpu::TextureFormat::RGBA8Unorm, 4, wgpu::TextureComponentType::Float, 4});
|
||||
DoUnormTest<uint8_t>({wgpu::TextureFormat::RGBA8Unorm, 4, TextureComponentType::Float, 4});
|
||||
}
|
||||
|
||||
// Test the BGRA8Unorm format
|
||||
|
@ -558,132 +567,130 @@ TEST_P(TextureFormatTest, BGRA8Unorm) {
|
|||
uint8_t maxValue = std::numeric_limits<uint8_t>::max();
|
||||
std::vector<uint8_t> textureData = {maxValue, 1, 0, maxValue};
|
||||
std::vector<float> uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f};
|
||||
DoFormatSamplingTest({wgpu::TextureFormat::BGRA8Unorm, 4, wgpu::TextureComponentType::Float, 4},
|
||||
DoFormatSamplingTest({wgpu::TextureFormat::BGRA8Unorm, 4, TextureComponentType::Float, 4},
|
||||
textureData, uncompressedData);
|
||||
DoFormatRenderingTest(
|
||||
{wgpu::TextureFormat::BGRA8Unorm, 4, wgpu::TextureComponentType::Float, 4},
|
||||
DoFormatRenderingTest({wgpu::TextureFormat::BGRA8Unorm, 4, TextureComponentType::Float, 4},
|
||||
uncompressedData, textureData);
|
||||
}
|
||||
|
||||
// Test the R8Snorm format
|
||||
TEST_P(TextureFormatTest, R8Snorm) {
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::R8Snorm, 1, wgpu::TextureComponentType::Float, 1});
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::R8Snorm, 1, TextureComponentType::Float, 1});
|
||||
}
|
||||
|
||||
// Test the RG8Snorm format
|
||||
TEST_P(TextureFormatTest, RG8Snorm) {
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::RG8Snorm, 2, wgpu::TextureComponentType::Float, 2});
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::RG8Snorm, 2, TextureComponentType::Float, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA8Snorm format
|
||||
TEST_P(TextureFormatTest, RGBA8Snorm) {
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::RGBA8Snorm, 4, wgpu::TextureComponentType::Float, 4});
|
||||
DoSnormTest<int8_t>({wgpu::TextureFormat::RGBA8Snorm, 4, TextureComponentType::Float, 4});
|
||||
}
|
||||
|
||||
// Test the R8Uint format
|
||||
TEST_P(TextureFormatTest, R8Uint) {
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::R8Uint, 1, wgpu::TextureComponentType::Uint, 1});
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::R8Uint, 1, TextureComponentType::Uint, 1});
|
||||
}
|
||||
|
||||
// Test the RG8Uint format
|
||||
TEST_P(TextureFormatTest, RG8Uint) {
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::RG8Uint, 2, wgpu::TextureComponentType::Uint, 2});
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::RG8Uint, 2, TextureComponentType::Uint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA8Uint format
|
||||
TEST_P(TextureFormatTest, RGBA8Uint) {
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::RGBA8Uint, 4, wgpu::TextureComponentType::Uint, 4});
|
||||
DoUintTest<uint8_t>({wgpu::TextureFormat::RGBA8Uint, 4, TextureComponentType::Uint, 4});
|
||||
}
|
||||
|
||||
// Test the R16Uint format
|
||||
TEST_P(TextureFormatTest, R16Uint) {
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::R16Uint, 2, wgpu::TextureComponentType::Uint, 1});
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::R16Uint, 2, TextureComponentType::Uint, 1});
|
||||
}
|
||||
|
||||
// Test the RG16Uint format
|
||||
TEST_P(TextureFormatTest, RG16Uint) {
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::RG16Uint, 4, wgpu::TextureComponentType::Uint, 2});
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::RG16Uint, 4, TextureComponentType::Uint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA16Uint format
|
||||
TEST_P(TextureFormatTest, RGBA16Uint) {
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::RGBA16Uint, 8, wgpu::TextureComponentType::Uint, 4});
|
||||
DoUintTest<uint16_t>({wgpu::TextureFormat::RGBA16Uint, 8, TextureComponentType::Uint, 4});
|
||||
}
|
||||
|
||||
// Test the R32Uint format
|
||||
TEST_P(TextureFormatTest, R32Uint) {
|
||||
DoUintTest<uint32_t>({wgpu::TextureFormat::R32Uint, 4, wgpu::TextureComponentType::Uint, 1});
|
||||
DoUintTest<uint32_t>({wgpu::TextureFormat::R32Uint, 4, TextureComponentType::Uint, 1});
|
||||
}
|
||||
|
||||
// Test the RG32Uint format
|
||||
TEST_P(TextureFormatTest, RG32Uint) {
|
||||
DoUintTest<uint32_t>({wgpu::TextureFormat::RG32Uint, 8, wgpu::TextureComponentType::Uint, 2});
|
||||
DoUintTest<uint32_t>({wgpu::TextureFormat::RG32Uint, 8, TextureComponentType::Uint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA32Uint format
|
||||
TEST_P(TextureFormatTest, RGBA32Uint) {
|
||||
DoUintTest<uint32_t>(
|
||||
{wgpu::TextureFormat::RGBA32Uint, 16, wgpu::TextureComponentType::Uint, 4});
|
||||
DoUintTest<uint32_t>({wgpu::TextureFormat::RGBA32Uint, 16, TextureComponentType::Uint, 4});
|
||||
}
|
||||
|
||||
// Test the R8Sint format
|
||||
TEST_P(TextureFormatTest, R8Sint) {
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::R8Sint, 1, wgpu::TextureComponentType::Sint, 1});
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::R8Sint, 1, TextureComponentType::Sint, 1});
|
||||
}
|
||||
|
||||
// Test the RG8Sint format
|
||||
TEST_P(TextureFormatTest, RG8Sint) {
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::RG8Sint, 2, wgpu::TextureComponentType::Sint, 2});
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::RG8Sint, 2, TextureComponentType::Sint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA8Sint format
|
||||
TEST_P(TextureFormatTest, RGBA8Sint) {
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::RGBA8Sint, 4, wgpu::TextureComponentType::Sint, 4});
|
||||
DoSintTest<int8_t>({wgpu::TextureFormat::RGBA8Sint, 4, TextureComponentType::Sint, 4});
|
||||
}
|
||||
|
||||
// Test the R16Sint format
|
||||
TEST_P(TextureFormatTest, R16Sint) {
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::R16Sint, 2, wgpu::TextureComponentType::Sint, 1});
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::R16Sint, 2, TextureComponentType::Sint, 1});
|
||||
}
|
||||
|
||||
// Test the RG16Sint format
|
||||
TEST_P(TextureFormatTest, RG16Sint) {
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::RG16Sint, 4, wgpu::TextureComponentType::Sint, 2});
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::RG16Sint, 4, TextureComponentType::Sint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA16Sint format
|
||||
TEST_P(TextureFormatTest, RGBA16Sint) {
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::RGBA16Sint, 8, wgpu::TextureComponentType::Sint, 4});
|
||||
DoSintTest<int16_t>({wgpu::TextureFormat::RGBA16Sint, 8, TextureComponentType::Sint, 4});
|
||||
}
|
||||
|
||||
// Test the R32Sint format
|
||||
TEST_P(TextureFormatTest, R32Sint) {
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::R32Sint, 4, wgpu::TextureComponentType::Sint, 1});
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::R32Sint, 4, TextureComponentType::Sint, 1});
|
||||
}
|
||||
|
||||
// Test the RG32Sint format
|
||||
TEST_P(TextureFormatTest, RG32Sint) {
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::RG32Sint, 8, wgpu::TextureComponentType::Sint, 2});
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::RG32Sint, 8, TextureComponentType::Sint, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA32Sint format
|
||||
TEST_P(TextureFormatTest, RGBA32Sint) {
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::RGBA32Sint, 16, wgpu::TextureComponentType::Sint, 4});
|
||||
DoSintTest<int32_t>({wgpu::TextureFormat::RGBA32Sint, 16, TextureComponentType::Sint, 4});
|
||||
}
|
||||
|
||||
// Test the R32Float format
|
||||
TEST_P(TextureFormatTest, R32Float) {
|
||||
DoFloat32Test({wgpu::TextureFormat::R32Float, 4, wgpu::TextureComponentType::Float, 1});
|
||||
DoFloat32Test({wgpu::TextureFormat::R32Float, 4, TextureComponentType::Float, 1});
|
||||
}
|
||||
|
||||
// Test the RG32Float format
|
||||
TEST_P(TextureFormatTest, RG32Float) {
|
||||
DoFloat32Test({wgpu::TextureFormat::RG32Float, 8, wgpu::TextureComponentType::Float, 2});
|
||||
DoFloat32Test({wgpu::TextureFormat::RG32Float, 8, TextureComponentType::Float, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA32Float format
|
||||
TEST_P(TextureFormatTest, RGBA32Float) {
|
||||
DoFloat32Test({wgpu::TextureFormat::RGBA32Float, 16, wgpu::TextureComponentType::Float, 4});
|
||||
DoFloat32Test({wgpu::TextureFormat::RGBA32Float, 16, TextureComponentType::Float, 4});
|
||||
}
|
||||
|
||||
// Test the R16Float format
|
||||
|
@ -692,7 +699,7 @@ TEST_P(TextureFormatTest, R16Float) {
|
|||
// swiftshader
|
||||
DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsSwiftshader() || IsANGLE());
|
||||
|
||||
DoFloat16Test({wgpu::TextureFormat::R16Float, 2, wgpu::TextureComponentType::Float, 1});
|
||||
DoFloat16Test({wgpu::TextureFormat::R16Float, 2, TextureComponentType::Float, 1});
|
||||
}
|
||||
|
||||
// Test the RG16Float format
|
||||
|
@ -701,7 +708,7 @@ TEST_P(TextureFormatTest, RG16Float) {
|
|||
// swiftshader
|
||||
DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsSwiftshader() || IsANGLE());
|
||||
|
||||
DoFloat16Test({wgpu::TextureFormat::RG16Float, 4, wgpu::TextureComponentType::Float, 2});
|
||||
DoFloat16Test({wgpu::TextureFormat::RG16Float, 4, TextureComponentType::Float, 2});
|
||||
}
|
||||
|
||||
// Test the RGBA16Float format
|
||||
|
@ -710,7 +717,7 @@ TEST_P(TextureFormatTest, RGBA16Float) {
|
|||
// swiftshader
|
||||
DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsSwiftshader() || IsANGLE());
|
||||
|
||||
DoFloat16Test({wgpu::TextureFormat::RGBA16Float, 8, wgpu::TextureComponentType::Float, 4});
|
||||
DoFloat16Test({wgpu::TextureFormat::RGBA16Float, 8, TextureComponentType::Float, 4});
|
||||
}
|
||||
|
||||
// Test the RGBA8Unorm format
|
||||
|
@ -728,10 +735,9 @@ TEST_P(TextureFormatTest, RGBA8UnormSrgb) {
|
|||
}
|
||||
|
||||
DoFloatFormatSamplingTest(
|
||||
{wgpu::TextureFormat::RGBA8UnormSrgb, 4, wgpu::TextureComponentType::Float, 4}, textureData,
|
||||
{wgpu::TextureFormat::RGBA8UnormSrgb, 4, TextureComponentType::Float, 4}, textureData,
|
||||
uncompressedData, 1.0e-3);
|
||||
DoFormatRenderingTest(
|
||||
{wgpu::TextureFormat::RGBA8UnormSrgb, 4, wgpu::TextureComponentType::Float, 4},
|
||||
DoFormatRenderingTest({wgpu::TextureFormat::RGBA8UnormSrgb, 4, TextureComponentType::Float, 4},
|
||||
uncompressedData, textureData);
|
||||
}
|
||||
|
||||
|
@ -755,10 +761,9 @@ TEST_P(TextureFormatTest, BGRA8UnormSrgb) {
|
|||
}
|
||||
|
||||
DoFloatFormatSamplingTest(
|
||||
{wgpu::TextureFormat::BGRA8UnormSrgb, 4, wgpu::TextureComponentType::Float, 4}, textureData,
|
||||
{wgpu::TextureFormat::BGRA8UnormSrgb, 4, TextureComponentType::Float, 4}, textureData,
|
||||
uncompressedData, 1.0e-3);
|
||||
DoFormatRenderingTest(
|
||||
{wgpu::TextureFormat::BGRA8UnormSrgb, 4, wgpu::TextureComponentType::Float, 4},
|
||||
DoFormatRenderingTest({wgpu::TextureFormat::BGRA8UnormSrgb, 4, TextureComponentType::Float, 4},
|
||||
uncompressedData, textureData);
|
||||
}
|
||||
|
||||
|
@ -784,10 +789,9 @@ TEST_P(TextureFormatTest, RGB10A2Unorm) {
|
|||
// clang-format on
|
||||
|
||||
DoFloatFormatSamplingTest(
|
||||
{wgpu::TextureFormat::RGB10A2Unorm, 4, wgpu::TextureComponentType::Float, 4}, textureData,
|
||||
{wgpu::TextureFormat::RGB10A2Unorm, 4, TextureComponentType::Float, 4}, textureData,
|
||||
uncompressedData, 1.0e-5);
|
||||
DoFormatRenderingTest(
|
||||
{wgpu::TextureFormat::RGB10A2Unorm, 4, wgpu::TextureComponentType::Float, 4},
|
||||
DoFormatRenderingTest({wgpu::TextureFormat::RGB10A2Unorm, 4, TextureComponentType::Float, 4},
|
||||
uncompressedData, textureData);
|
||||
}
|
||||
|
||||
|
@ -831,7 +835,7 @@ TEST_P(TextureFormatTest, RG11B10Ufloat) {
|
|||
// clang-format on
|
||||
|
||||
DoFloatFormatSamplingTest(
|
||||
{wgpu::TextureFormat::RG11B10Ufloat, 4, wgpu::TextureComponentType::Float, 4}, textureData,
|
||||
{wgpu::TextureFormat::RG11B10Ufloat, 4, TextureComponentType::Float, 4}, textureData,
|
||||
uncompressedData);
|
||||
|
||||
// This format is renderable if "rg11b10ufloat-renderable" feature is enabled
|
||||
|
@ -843,7 +847,7 @@ TEST_P(TextureFormatTest, RG11B10Ufloat) {
|
|||
"and NaN correctly for RG11B10Ufloat texture format.";
|
||||
} else {
|
||||
DoFormatRenderingTest(
|
||||
{wgpu::TextureFormat::RG11B10Ufloat, 4, wgpu::TextureComponentType::Float, 4},
|
||||
{wgpu::TextureFormat::RG11B10Ufloat, 4, TextureComponentType::Float, 4},
|
||||
uncompressedData, textureData, new ExpectRG11B10Ufloat(textureData));
|
||||
}
|
||||
}
|
||||
|
@ -891,7 +895,7 @@ TEST_P(TextureFormatTest, RGB9E5Ufloat) {
|
|||
// clang-format on
|
||||
|
||||
DoFloatFormatSamplingTest(
|
||||
{wgpu::TextureFormat::RGB9E5Ufloat, 4, wgpu::TextureComponentType::Float, 4}, textureData,
|
||||
{wgpu::TextureFormat::RGB9E5Ufloat, 4, TextureComponentType::Float, 4}, textureData,
|
||||
uncompressedData);
|
||||
// This format is not renderable.
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue