mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-19 01:46:35 +00:00
Remove deprecated API surface, Pt. 1
- Remove Device.getDefaultQueue() - Remove Extent3D.depth - Remove setIndexBufferWithFormat - Remove TextureUsage::OutputAttachment Change-Id: If1c39b5630c88c3b87b37e317aafe7442419f7d0 Bug: dawn:22 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/50700 Reviewed-by: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Brandon Jones <bajones@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
82ba34a941
commit
76e5a9f6dd
@@ -1699,7 +1699,7 @@ TEST_P(CopyTests_T2B, CopyOneRowWithDepth32Float) {
|
||||
wgpu::TextureDescriptor textureDescriptor;
|
||||
textureDescriptor.format = kFormat;
|
||||
textureDescriptor.size = {kPixelsPerRow, 1, 1};
|
||||
textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::OutputAttachment;
|
||||
textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment;
|
||||
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
|
||||
@@ -287,7 +287,7 @@ class CopyTextureForBrowserTests : public DawnTest {
|
||||
dstDescriptor.format = dstSpec.format;
|
||||
dstDescriptor.mipLevelCount = dstSpec.level + 1;
|
||||
dstDescriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled |
|
||||
wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
|
||||
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
||||
dstTexture = device.CreateTexture(&dstDescriptor);
|
||||
|
||||
if (testSubRectCopy) {
|
||||
|
||||
@@ -35,22 +35,6 @@ class DeprecationTests : public DawnTest {
|
||||
}
|
||||
};
|
||||
|
||||
// Test that SetIndexBufferWithFormat is deprecated.
|
||||
TEST_P(DeprecationTests, SetIndexBufferWithFormat) {
|
||||
wgpu::BufferDescriptor bufferDesc;
|
||||
bufferDesc.size = 4;
|
||||
bufferDesc.usage = wgpu::BufferUsage::Index;
|
||||
wgpu::Buffer indexBuffer = device.CreateBuffer(&bufferDesc);
|
||||
|
||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
pass.SetIndexBufferWithFormat(indexBuffer, wgpu::IndexFormat::Uint32));
|
||||
pass.EndPass();
|
||||
}
|
||||
|
||||
// Test that SetBlendColor is deprecated.
|
||||
TEST_P(DeprecationTests, SetSetBlendColor) {
|
||||
wgpu::Color blendColor{1.0, 0.0, 0.0, 1.0};
|
||||
@@ -204,309 +188,11 @@ TEST_P(DeprecationTests, BindGroupLayoutEntryViewDimensionDefaulting) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test Device::GetDefaultQueue deprecation.
|
||||
TEST_P(DeprecationTests, GetDefaultQueueDeprecation) {
|
||||
// Using GetDefaultQueue emits a warning.
|
||||
wgpu::Queue deprecatedQueue;
|
||||
EXPECT_DEPRECATION_WARNING(deprecatedQueue = device.GetDefaultQueue());
|
||||
|
||||
// Using GetQueue doesn't emit a warning.
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
|
||||
// Both objects are the same, even with dawn_wire.
|
||||
EXPECT_EQ(deprecatedQueue.Get(), queue.Get());
|
||||
}
|
||||
|
||||
// Test that fences are deprecated.
|
||||
TEST_P(DeprecationTests, CreateFence) {
|
||||
EXPECT_DEPRECATION_WARNING(queue.CreateFence());
|
||||
}
|
||||
|
||||
// Test GPUExtent3D.depth deprecation in TextureDescriptor.size
|
||||
TEST_P(DeprecationTests, GPUExtent3DDepthDeprecationTextureDescriptor) {
|
||||
wgpu::TextureDescriptor kBaseDesc;
|
||||
kBaseDesc.usage = wgpu::TextureUsage::Sampled;
|
||||
kBaseDesc.size.width = 1;
|
||||
kBaseDesc.size.height = 1;
|
||||
kBaseDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
kBaseDesc.dimension = wgpu::TextureDimension::e2D;
|
||||
|
||||
{
|
||||
// Valid: default
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
wgpu::Texture texture;
|
||||
texture = device.CreateTexture(&desc);
|
||||
}
|
||||
{
|
||||
// Warning: use deprecated depth but still valid
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
desc.mipLevelCount = 2;
|
||||
desc.size.width = 2;
|
||||
desc.size.height = 2;
|
||||
desc.size.depth = 2;
|
||||
wgpu::Texture texture;
|
||||
EXPECT_DEPRECATION_WARNING(texture = device.CreateTexture(&desc));
|
||||
}
|
||||
{
|
||||
// Warning: use deprecated depth
|
||||
// Error: use deprecated depth and the descriptor is invalid
|
||||
// because 2D texture with depth == 0 is not allowed
|
||||
// This is to verify the deprecated depth is picked up by the implementation.
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
desc.size.depth = 0;
|
||||
wgpu::Texture texture;
|
||||
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(texture = device.CreateTexture(&desc)));
|
||||
}
|
||||
{
|
||||
// Error: use both deprecated depth and depthOrArrayLayers
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
desc.size.depth = 2;
|
||||
desc.size.depthOrArrayLayers = 2;
|
||||
wgpu::Texture texture;
|
||||
ASSERT_DEVICE_ERROR(texture = device.CreateTexture(&desc));
|
||||
}
|
||||
{
|
||||
// Valid: use updated depthOrArrayLayers
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
desc.mipLevelCount = 2;
|
||||
desc.size.width = 2;
|
||||
desc.size.height = 2;
|
||||
desc.size.depthOrArrayLayers = 2;
|
||||
wgpu::Texture texture;
|
||||
texture = device.CreateTexture(&desc);
|
||||
}
|
||||
{
|
||||
// Error: use updated depthOrArrayLayers and the descriptor is invalid
|
||||
// because 2D texture with depthOrArrayLayers == 0 is not allowed
|
||||
wgpu::TextureDescriptor desc = kBaseDesc;
|
||||
desc.size.depthOrArrayLayers = 0;
|
||||
wgpu::Texture texture;
|
||||
ASSERT_DEVICE_ERROR(texture = device.CreateTexture(&desc));
|
||||
}
|
||||
}
|
||||
|
||||
// Test GPUExtent3D.depth deprecation in CopyBufferToTexture, CopyTextureToBuffer, and
|
||||
// CopyTextureToTexture
|
||||
TEST_P(DeprecationTests, GPUExtent3DDepthDeprecationCopy) {
|
||||
wgpu::BufferDescriptor bufferDesc;
|
||||
bufferDesc.size = 4 * 256;
|
||||
bufferDesc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||
wgpu::Buffer srcBuffer = device.CreateBuffer(&bufferDesc);
|
||||
|
||||
wgpu::TextureDescriptor dstTextureDesc;
|
||||
dstTextureDesc.usage = wgpu::TextureUsage::CopyDst;
|
||||
dstTextureDesc.size.width = 4;
|
||||
dstTextureDesc.size.height = 4;
|
||||
dstTextureDesc.size.depthOrArrayLayers = 1;
|
||||
dstTextureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
dstTextureDesc.dimension = wgpu::TextureDimension::e2D;
|
||||
wgpu::Texture dstTexture = device.CreateTexture(&dstTextureDesc);
|
||||
|
||||
wgpu::TextureDescriptor srcTextureDesc = dstTextureDesc;
|
||||
srcTextureDesc.usage = wgpu::TextureUsage::CopySrc;
|
||||
wgpu::Texture srcTexture = device.CreateTexture(&srcTextureDesc);
|
||||
|
||||
wgpu::ImageCopyBuffer imageCopyBuffer = utils::CreateImageCopyBuffer(srcBuffer, 0, 256, 4);
|
||||
wgpu::ImageCopyTexture imageCopyDstTexture =
|
||||
utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::All);
|
||||
wgpu::ImageCopyTexture imageCopySrcTexture =
|
||||
utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::All);
|
||||
|
||||
wgpu::Extent3D kBaseExtent3D;
|
||||
kBaseExtent3D.width = 4;
|
||||
kBaseExtent3D.height = 4;
|
||||
|
||||
{
|
||||
// Valid: default
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D);
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D);
|
||||
encoder.CopyTextureToTexture(&imageCopySrcTexture, &imageCopyDstTexture, &extent3D);
|
||||
encoder.Finish();
|
||||
}
|
||||
{
|
||||
// Warning: empty copy use deprecated depth == 0 but still valid
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depth = 0;
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D));
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D));
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
encoder.CopyTextureToTexture(&imageCopySrcTexture, &imageCopyDstTexture, &extent3D));
|
||||
encoder.Finish();
|
||||
}
|
||||
{
|
||||
// Warning: use deprecated depth
|
||||
// Error: depth > 1
|
||||
// This is to verify the deprecated depth is picked up by the implementation.
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.depth = 2;
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D));
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
EXPECT_DEPRECATION_WARNING(
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D));
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
EXPECT_DEPRECATION_WARNING(encoder.CopyTextureToTexture(
|
||||
&imageCopySrcTexture, &imageCopyDstTexture, &extent3D));
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
{
|
||||
// Error: use both deprecated depth and depthOrArrayLayers
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depth = 0;
|
||||
extent3D.depthOrArrayLayers = 0;
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToTexture(&imageCopySrcTexture, &imageCopyDstTexture, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
{
|
||||
// Valid: use updated depthOrArrayLayers
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depthOrArrayLayers = 0;
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D);
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D);
|
||||
encoder.CopyTextureToTexture(&imageCopySrcTexture, &imageCopyDstTexture, &extent3D);
|
||||
encoder.Finish();
|
||||
}
|
||||
{
|
||||
// Error: use updated depthOrArrayLayers and is invalid
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.depthOrArrayLayers = 2;
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyDstTexture, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&imageCopySrcTexture, &imageCopyBuffer, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToTexture(&imageCopySrcTexture, &imageCopyDstTexture, &extent3D);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test GPUExtent3D.depth deprecation in WriteTexture
|
||||
TEST_P(DeprecationTests, GPUExtent3DDepthDeprecationWriteTexture) {
|
||||
wgpu::TextureDescriptor dstTextureDesc;
|
||||
dstTextureDesc.usage = wgpu::TextureUsage::CopyDst;
|
||||
dstTextureDesc.size.width = 4;
|
||||
dstTextureDesc.size.height = 4;
|
||||
dstTextureDesc.size.depthOrArrayLayers = 1;
|
||||
dstTextureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
dstTextureDesc.dimension = wgpu::TextureDimension::e2D;
|
||||
wgpu::Texture dstTexture = device.CreateTexture(&dstTextureDesc);
|
||||
|
||||
size_t dataSize = 4 * 256;
|
||||
std::vector<uint8_t> data(dataSize);
|
||||
|
||||
wgpu::TextureDataLayout textureDataLayout;
|
||||
textureDataLayout.offset = 0;
|
||||
textureDataLayout.bytesPerRow = 256;
|
||||
textureDataLayout.rowsPerImage = 4;
|
||||
|
||||
wgpu::ImageCopyTexture imageCopyDstTexture =
|
||||
utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::All);
|
||||
|
||||
wgpu::Extent3D kBaseExtent3D;
|
||||
kBaseExtent3D.width = 4;
|
||||
kBaseExtent3D.height = 4;
|
||||
|
||||
{
|
||||
// Valid: default
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
queue.WriteTexture(&imageCopyDstTexture, data.data(), dataSize, &textureDataLayout,
|
||||
&extent3D);
|
||||
}
|
||||
{
|
||||
// Warning: use deprecated depth == 0 but still valid
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depth = 0;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
EXPECT_DEPRECATION_WARNING(queue.WriteTexture(&imageCopyDstTexture, data.data(), dataSize,
|
||||
&textureDataLayout, &extent3D));
|
||||
}
|
||||
{
|
||||
// Warning: use deprecated depth
|
||||
// Error: depth > 1 for 2D textures
|
||||
// This is to verify the deprecated depth is picked up by the implementation.
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.depth = 2;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(queue.WriteTexture(
|
||||
&imageCopyDstTexture, data.data(), dataSize, &textureDataLayout, &extent3D)));
|
||||
}
|
||||
{
|
||||
// Error: use both deprecated depth and depthOrArrayLayers
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depth = 0;
|
||||
extent3D.depthOrArrayLayers = 0;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyDstTexture, data.data(), dataSize,
|
||||
&textureDataLayout, &extent3D));
|
||||
}
|
||||
{
|
||||
// Valid: use updated depthOrArrayLayers
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.width = 0;
|
||||
extent3D.height = 0;
|
||||
extent3D.depthOrArrayLayers = 0;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
queue.WriteTexture(&imageCopyDstTexture, data.data(), dataSize, &textureDataLayout,
|
||||
&extent3D);
|
||||
}
|
||||
{
|
||||
// Error: use updated depthOrArrayLayers and depthOrArrayLayers > 1 for 2D textures
|
||||
wgpu::Extent3D extent3D = kBaseExtent3D;
|
||||
extent3D.depthOrArrayLayers = 2;
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyDstTexture, data.data(), dataSize,
|
||||
&textureDataLayout, &extent3D));
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(DeprecationTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
||||
@@ -244,7 +244,7 @@ class DepthStencilSamplingTest : public DawnTest {
|
||||
|
||||
wgpu::Texture CreateInputTexture(wgpu::TextureFormat format) {
|
||||
wgpu::TextureDescriptor inputTextureDesc;
|
||||
inputTextureDesc.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment;
|
||||
inputTextureDesc.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::RenderAttachment;
|
||||
inputTextureDesc.size = {1, 1, 1};
|
||||
inputTextureDesc.format = format;
|
||||
return device.CreateTexture(&inputTextureDesc);
|
||||
@@ -253,7 +253,7 @@ class DepthStencilSamplingTest : public DawnTest {
|
||||
wgpu::Texture CreateOutputTexture(wgpu::TextureFormat format) {
|
||||
wgpu::TextureDescriptor outputTextureDesc;
|
||||
outputTextureDesc.usage =
|
||||
wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
|
||||
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
||||
outputTextureDesc.size = {1, 1, 1};
|
||||
outputTextureDesc.format = format;
|
||||
return device.CreateTexture(&outputTextureDesc);
|
||||
|
||||
@@ -69,17 +69,17 @@ class SwapChainValidationTests : public DawnTest {
|
||||
wgpu::SwapChainDescriptor goodDescriptor;
|
||||
wgpu::SwapChainDescriptor badDescriptor;
|
||||
|
||||
// Checks that an RenderAttachment view is an error by trying to create a render pass on it.
|
||||
// Checks that a RenderAttachment view is an error by trying to create a render pass on it.
|
||||
void CheckTextureViewIsError(wgpu::TextureView view) {
|
||||
CheckTextureView(view, true, false);
|
||||
}
|
||||
|
||||
// Checks that an RenderAttachment view is an error by trying to submit a render pass on it.
|
||||
// Checks that a RenderAttachment view is an error by trying to submit a render pass on it.
|
||||
void CheckTextureViewIsDestroyed(wgpu::TextureView view) {
|
||||
CheckTextureView(view, false, true);
|
||||
}
|
||||
|
||||
// Checks that an OutputAttachment view is valid by submitting a render pass on it.
|
||||
// Checks that a RenderAttachment view is valid by submitting a render pass on it.
|
||||
void CheckTextureViewIsValid(wgpu::TextureView view) {
|
||||
CheckTextureView(view, false, false);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size.width = kWidth;
|
||||
descriptor.size.height = kHeight;
|
||||
descriptor.size.depth = kDefaultDepth;
|
||||
descriptor.size.depthOrArrayLayers = kDefaultDepth;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
descriptor.sampleCount = kDefaultSampleCount;
|
||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
|
||||
Reference in New Issue
Block a user