mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-02 12:41:36 +00:00
Use const*const* to annotate a sequence of descriptors
BUG=dawn:77 Change-Id: I2a523e54a06173c157730e043c25e9629887fd1f Reviewed-on: https://dawn-review.googlesource.com/c/3820 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
850c0d9aec
commit
c0f31e73e4
@ -654,7 +654,7 @@
|
||||
"extensible": true,
|
||||
"members": [
|
||||
{"name": "num color attachments", "type": "uint32_t"},
|
||||
{"name": "color attachments", "type": "attachment descriptor", "annotation": "const*", "length": "num color attachments"},
|
||||
{"name": "color attachments", "type": "attachment descriptor", "annotation": "const*const*", "length": "num color attachments"},
|
||||
{"name": "has depth stencil attachment", "type": "bool"},
|
||||
{"name": "depth stencil attachment", "type": "attachment descriptor", "annotation":"const*"}
|
||||
]
|
||||
|
@ -115,8 +115,7 @@ void init() {
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
|
||||
pipeline = device.CreateRenderPipeline(&descriptor);
|
||||
|
||||
|
@ -75,7 +75,8 @@ void init() {
|
||||
attachmentsState.nextInChain = nullptr;
|
||||
attachmentsState.numColorAttachments = 1;
|
||||
dawnAttachmentDescriptor colorAttachment = {nullptr, swapChainFormat};
|
||||
attachmentsState.colorAttachments = &colorAttachment;
|
||||
dawnAttachmentDescriptor* colorAttachmentPtr[] = {&colorAttachment};
|
||||
attachmentsState.colorAttachments = colorAttachmentPtr;
|
||||
attachmentsState.hasDepthStencilAttachment = false;
|
||||
// Even with hasDepthStencilAttachment = false, depthStencilAttachment must point to valid
|
||||
// data because we don't have optional substructures yet.
|
||||
|
@ -130,8 +130,7 @@ void initRender() {
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
|
||||
renderPipeline = device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
@ -133,8 +133,7 @@ void init() {
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
|
||||
pipeline = device.CreateRenderPipeline(&descriptor);
|
||||
|
||||
|
@ -200,8 +200,7 @@ void init() {
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cDepthStencilState.depthWriteEnabled = true;
|
||||
descriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less;
|
||||
|
||||
@ -214,8 +213,7 @@ void init() {
|
||||
pDescriptor.inputState = inputState;
|
||||
pDescriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
pDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
pDescriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
pDescriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
pDescriptor.cDepthStencilState.front.passOp = dawn::StencilOperation::Replace;
|
||||
pDescriptor.cDepthStencilState.back.passOp = dawn::StencilOperation::Replace;
|
||||
pDescriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less;
|
||||
@ -229,8 +227,7 @@ void init() {
|
||||
rfDescriptor.inputState = inputState;
|
||||
rfDescriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
rfDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
rfDescriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
rfDescriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
pDescriptor.cDepthStencilState.front.compare = dawn::CompareFunction::Equal;
|
||||
pDescriptor.cDepthStencilState.back.compare = dawn::CompareFunction::Equal;
|
||||
pDescriptor.cDepthStencilState.front.passOp = dawn::StencilOperation::Replace;
|
||||
|
@ -292,8 +292,7 @@ namespace {
|
||||
descriptor.indexFormat = dawn::IndexFormat::Uint16;
|
||||
descriptor.cAttachmentsState.hasDepthStencilAttachment = true;
|
||||
descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat();
|
||||
descriptor.cDepthStencilState.depthWriteEnabled = true;
|
||||
descriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less;
|
||||
|
||||
|
@ -243,6 +243,8 @@ def decorate(name, typ, arg):
|
||||
return typ + ' ' + name
|
||||
elif arg.annotation == 'const*':
|
||||
return typ + ' const * ' + name
|
||||
elif arg.annotation == 'const*const*':
|
||||
return 'const ' + typ + '* const * ' + name
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
|
@ -51,12 +51,13 @@
|
||||
{%- if member.type.category == "object" -%}
|
||||
{%- set Optional = "Optional" if member.optional else "" -%}
|
||||
{{out}} = provider.Get{{Optional}}Id({{in}});
|
||||
{%- elif member.type.category == "structure" -%}
|
||||
{{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer
|
||||
{%- if member.type.has_dawn_object -%}
|
||||
, provider
|
||||
{%- endif -%}
|
||||
);
|
||||
{% elif member.type.category == "structure"%}
|
||||
{%- set Provider = ", provider" if member.type.has_dawn_object else "" -%}
|
||||
{% if member.annotation == "const*const*" %}
|
||||
{{as_cType(member.type.name)}}Serialize(*{{in}}, &{{out}}, buffer{{Provider}});
|
||||
{% else %}
|
||||
{{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}});
|
||||
{% endif %}
|
||||
{%- else -%}
|
||||
{{out}} = {{in}};
|
||||
{%- endif -%}
|
||||
@ -126,7 +127,11 @@
|
||||
//* Structures might contain more pointers so we need to add their extra size as well.
|
||||
{% if member.type.category == "structure" %}
|
||||
for (size_t i = 0; i < memberLength; ++i) {
|
||||
result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}[i]);
|
||||
{% if member.annotation == "const*const*" %}
|
||||
result += {{as_cType(member.type.name)}}GetExtraRequiredSize(*record.{{as_varName(member.name)}}[i]);
|
||||
{% else %}
|
||||
result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}[i]);
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
@ -279,7 +284,16 @@
|
||||
|
||||
{{as_cType(member.type.name)}}* copiedMembers = nullptr;
|
||||
DESERIALIZE_TRY(GetSpace(allocator, memberLength, &copiedMembers));
|
||||
record->{{memberName}} = copiedMembers;
|
||||
{% if member.annotation == "const*const*" %}
|
||||
{{as_cType(member.type.name)}}** pointerArray = nullptr;
|
||||
DESERIALIZE_TRY(GetSpace(allocator, memberLength, &pointerArray));
|
||||
for (size_t i = 0; i < memberLength; ++i) {
|
||||
pointerArray[i] = &copiedMembers[i];
|
||||
}
|
||||
record->{{memberName}} = pointerArray;
|
||||
{% else %}
|
||||
record->{{memberName}} = copiedMembers;
|
||||
{% endif %}
|
||||
|
||||
for (size_t i = 0; i < memberLength; ++i) {
|
||||
{{deserialize_member(member, "memberBuffer[i]", "copiedMembers[i]")}}
|
||||
|
@ -61,7 +61,7 @@ namespace dawn_native {
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < descriptor->numColorAttachments; ++i) {
|
||||
dawn::TextureFormat format = descriptor->colorAttachments[i].format;
|
||||
dawn::TextureFormat format = descriptor->colorAttachments[i]->format;
|
||||
DAWN_TRY(ValidateTextureFormat(format));
|
||||
|
||||
if (!IsColorRenderableTextureFormat(format)) {
|
||||
@ -190,7 +190,7 @@ namespace dawn_native {
|
||||
for (uint32_t i = 0; i < descriptor->attachmentsState->numColorAttachments; ++i) {
|
||||
mColorAttachmentsSet.set(i);
|
||||
mBlendStates[i] = descriptor->blendStates[i];
|
||||
mColorAttachmentFormats[i] = descriptor->attachmentsState->colorAttachments[i].format;
|
||||
mColorAttachmentFormats[i] = descriptor->attachmentsState->colorAttachments[i]->format;
|
||||
}
|
||||
|
||||
// TODO(cwallez@chromium.org): Check against the shader module that the correct color
|
||||
|
@ -130,8 +130,7 @@ TEST_P(BindGroupTests, ReusedUBO) {
|
||||
textureDescriptor.layout = pipelineLayout;
|
||||
textureDescriptor.cVertexStage.module = vsModule;
|
||||
textureDescriptor.cFragmentStage.module = fsModule;
|
||||
textureDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
textureDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
|
||||
|
||||
@ -216,8 +215,7 @@ TEST_P(BindGroupTests, UBOSamplerAndTexture) {
|
||||
pipelineDescriptor.layout = pipelineLayout;
|
||||
pipelineDescriptor.cVertexStage.module = vsModule;
|
||||
pipelineDescriptor.cFragmentStage.module = fsModule;
|
||||
pipelineDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
pipelineDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
|
||||
@ -339,7 +337,7 @@ TEST_P(BindGroupTests, MultipleBindLayouts) {
|
||||
textureDescriptor.layout = pipelineLayout;
|
||||
textureDescriptor.cVertexStage.module = vsModule;
|
||||
textureDescriptor.cFragmentStage.module = fsModule;
|
||||
textureDescriptor.cColorAttachments[0].format = renderPass.colorFormat;
|
||||
textureDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
|
||||
|
||||
@ -433,7 +431,7 @@ TEST_P(BindGroupTests, DrawTwiceInSamePipelineWithFourBindGroupSets)
|
||||
pipelineDescriptor.layout = pipelineLayout;
|
||||
pipelineDescriptor.cVertexStage.module = vsModule;
|
||||
pipelineDescriptor.cFragmentStage.module = fsModule;
|
||||
pipelineDescriptor.cColorAttachments[0].format = renderPass.colorFormat;
|
||||
pipelineDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
|
||||
|
@ -71,8 +71,7 @@ class BlendStateTest : public DawnTest {
|
||||
baseDescriptor.layout = pipelineLayout;
|
||||
baseDescriptor.cVertexStage.module = vsModule;
|
||||
baseDescriptor.cFragmentStage.module = fsModule;
|
||||
baseDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
baseDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
basePipeline = device.CreateRenderPipeline(&baseDescriptor);
|
||||
|
||||
@ -80,8 +79,7 @@ class BlendStateTest : public DawnTest {
|
||||
testDescriptor.layout = pipelineLayout;
|
||||
testDescriptor.cVertexStage.module = vsModule;
|
||||
testDescriptor.cFragmentStage.module = fsModule;
|
||||
testDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
testDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
testDescriptor.cBlendStates[0] = blendStateDescriptor;
|
||||
|
||||
testPipeline = device.CreateRenderPipeline(&testDescriptor);
|
||||
@ -867,8 +865,7 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
|
||||
baseDescriptor.layout = pipelineLayout;
|
||||
baseDescriptor.cVertexStage.module = vsModule;
|
||||
baseDescriptor.cFragmentStage.module = fsModule;
|
||||
baseDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
baseDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
basePipeline = device.CreateRenderPipeline(&baseDescriptor);
|
||||
|
||||
@ -876,8 +873,7 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
|
||||
testDescriptor.layout = pipelineLayout;
|
||||
testDescriptor.cVertexStage.module = vsModule;
|
||||
testDescriptor.cFragmentStage.module = fsModule;
|
||||
testDescriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
testDescriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::BlendDescriptor blend;
|
||||
blend.operation = dawn::BlendOperation::Add;
|
||||
|
@ -53,8 +53,7 @@ class DrawIndexedTest : public DawnTest {
|
||||
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
|
||||
descriptor.indexFormat = dawn::IndexFormat::Uint32;
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
pipeline = device.CreateRenderPipeline(&descriptor);
|
||||
|
||||
|
@ -58,8 +58,7 @@ class IndexFormatTest : public DawnTest {
|
||||
descriptor.primitiveTopology = dawn::PrimitiveTopology::TriangleStrip;
|
||||
descriptor.indexFormat = format;
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
return device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
@ -125,8 +125,7 @@ class InputStateTest : public DawnTest {
|
||||
descriptor.cVertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
return device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
@ -192,8 +192,7 @@ class PrimitiveTopologyTest : public DawnTest {
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.primitiveTopology = primitiveTopology;
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
|
||||
|
||||
|
@ -77,8 +77,7 @@ protected:
|
||||
pipelineDescriptor.layout = pipelineLayout;
|
||||
pipelineDescriptor.cVertexStage.module = vsModule;
|
||||
pipelineDescriptor.cFragmentStage.module = fsModule;
|
||||
pipelineDescriptor.cColorAttachments[0].format =
|
||||
mRenderPass.colorFormat;
|
||||
pipelineDescriptor.cColorAttachments[0]->format = mRenderPass.colorFormat;
|
||||
|
||||
mPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
|
||||
|
@ -40,8 +40,7 @@ class ScissorTest: public DawnTest {
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.cVertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
format;
|
||||
descriptor.cColorAttachments[0]->format = format;
|
||||
|
||||
return device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
@ -172,8 +172,7 @@ protected:
|
||||
textureDescriptor.cVertexStage.module = mVSModule;
|
||||
textureDescriptor.cFragmentStage.module = fsModule;
|
||||
textureDescriptor.layout = mPipelineLayout;
|
||||
textureDescriptor.cColorAttachments[0].format =
|
||||
mRenderPass.colorFormat;
|
||||
textureDescriptor.cColorAttachments[0]->format = mRenderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
|
||||
|
||||
@ -517,7 +516,7 @@ class TextureViewRenderingTest : public DawnTest {
|
||||
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
|
||||
pipelineDescriptor.cVertexStage.module = vsModule;
|
||||
pipelineDescriptor.cFragmentStage.module = oneColorFsModule;
|
||||
pipelineDescriptor.cColorAttachments[0].format = kDefaultFormat;
|
||||
pipelineDescriptor.cColorAttachments[0]->format = kDefaultFormat;
|
||||
|
||||
dawn::RenderPipeline oneColorPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
|
||||
|
@ -40,8 +40,7 @@ TEST_P(ViewportOrientationTests, OriginAt0x0) {
|
||||
descriptor.cVertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.primitiveTopology = dawn::PrimitiveTopology::PointList;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderPass.colorFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderPass.colorFormat;
|
||||
|
||||
dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
|
||||
|
||||
|
@ -404,7 +404,8 @@ TEST_F(WireTests, CStringArgument) {
|
||||
attachmentsState.nextInChain = nullptr;
|
||||
attachmentsState.numColorAttachments = 1;
|
||||
dawnAttachmentDescriptor colorAttachment = {nullptr, DAWN_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM};
|
||||
attachmentsState.colorAttachments = &colorAttachment;
|
||||
dawnAttachmentDescriptor* colorAttachmentPtr[] = {&colorAttachment};
|
||||
attachmentsState.colorAttachments = colorAttachmentPtr;
|
||||
attachmentsState.hasDepthStencilAttachment = false;
|
||||
// Even with hasDepthStencilAttachment = false, depthStencilAttachment must point to valid
|
||||
// data because we don't have optional substructures yet.
|
||||
|
@ -35,8 +35,7 @@ class InputStateTest : public ValidationTest {
|
||||
descriptor.cVertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
descriptor.inputState = inputState;
|
||||
descriptor.cColorAttachments[0].format =
|
||||
renderpassData.attachmentFormat;
|
||||
descriptor.cColorAttachments[0]->format = renderpassData.attachmentFormat;
|
||||
|
||||
if (!success) {
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
|
@ -46,7 +46,8 @@ namespace utils {
|
||||
cAttachmentsState.hasDepthStencilAttachment = false;
|
||||
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
cColorAttachments[i].format = dawn::TextureFormat::R8G8B8A8Unorm;
|
||||
colorAttachments[i].format = dawn::TextureFormat::R8G8B8A8Unorm;
|
||||
cColorAttachments[i] = &colorAttachments[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,13 @@ namespace utils {
|
||||
dawn::PipelineStageDescriptor cFragmentStage;
|
||||
|
||||
dawn::AttachmentsStateDescriptor cAttachmentsState;
|
||||
std::array<dawn::AttachmentDescriptor, kMaxColorAttachments> cColorAttachments;
|
||||
std::array<dawn::AttachmentDescriptor*, kMaxColorAttachments> cColorAttachments;
|
||||
dawn::AttachmentDescriptor cDepthStencilAttachment;
|
||||
std::array<dawn::BlendStateDescriptor, kMaxColorAttachments> cBlendStates;
|
||||
dawn::DepthStencilStateDescriptor cDepthStencilState;
|
||||
|
||||
private:
|
||||
dawn::AttachmentDescriptor colorAttachments[kMaxColorAttachments];
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
Loading…
x
Reference in New Issue
Block a user