mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-11 14:39:13 +00:00
The WGSL spec has been updated with 'Default Struct Layouts': https://github.com/gpuweb/gpuweb/pull/1447 This removes the `[[offset(n)]]` decoration, and replaces it with two optional decorations: `[[size(n)]]` and `[[align(n)]]`, and a sensible set of sizes and alignments for each type. Most `[[stride(n)]]` decorations have also been removed from arrays. Bug: tint:626 Bug: tint:629 Change-Id: Ib0d2741f61ea943e6fb99d00cbb5cab2f97ae7be Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/44280 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
319 lines
13 KiB
C++
319 lines
13 KiB
C++
// 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 "tests/DawnTest.h"
|
|
|
|
#include "common/Constants.h"
|
|
#include "common/Math.h"
|
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
|
#include "utils/TestUtils.h"
|
|
#include "utils/TextureFormatUtils.h"
|
|
#include "utils/WGPUHelpers.h"
|
|
|
|
class CopyTextureForBrowserTests : public DawnTest {
|
|
protected:
|
|
static constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
|
static constexpr uint64_t kDefaultTextureWidth = 4;
|
|
static constexpr uint64_t kDefaultTextureHeight = 4;
|
|
|
|
struct TextureSpec {
|
|
wgpu::Origin3D copyOrigin = {};
|
|
wgpu::Extent3D textureSize = {kDefaultTextureWidth, kDefaultTextureHeight};
|
|
uint32_t level = 0;
|
|
wgpu::TextureFormat format = kTextureFormat;
|
|
};
|
|
|
|
static std::vector<RGBA8> GetSourceTextureData(const utils::TextureDataCopyLayout& layout) {
|
|
std::vector<RGBA8> textureData(layout.texelBlockCount);
|
|
for (uint32_t layer = 0; layer < layout.mipSize.depth; ++layer) {
|
|
const uint32_t sliceOffset = layout.texelBlocksPerImage * layer;
|
|
for (uint32_t y = 0; y < layout.mipSize.height; ++y) {
|
|
const uint32_t rowOffset = layout.texelBlocksPerRow * y;
|
|
for (uint32_t x = 0; x < layout.mipSize.width; ++x) {
|
|
textureData[sliceOffset + rowOffset + x] =
|
|
RGBA8(static_cast<uint8_t>((x + layer * x) % 256),
|
|
static_cast<uint8_t>((y + layer * y) % 256),
|
|
static_cast<uint8_t>(x / 256), static_cast<uint8_t>(y / 256));
|
|
}
|
|
}
|
|
}
|
|
|
|
return textureData;
|
|
}
|
|
|
|
void SetUp() override {
|
|
DawnTest::SetUp();
|
|
|
|
testPipeline = MakeTestPipeline();
|
|
|
|
uint32_t uniformBufferData[] = {
|
|
0, // copy have flipY option
|
|
};
|
|
|
|
wgpu::BufferDescriptor uniformBufferDesc = {};
|
|
uniformBufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
|
|
uniformBufferDesc.size = sizeof(uniformBufferData);
|
|
uniformBuffer = device.CreateBuffer(&uniformBufferDesc);
|
|
}
|
|
|
|
// Do the bit-by-bit comparison between the source and destination texture with GPU (compute
|
|
// shader) instead of CPU after executing CopyTextureForBrowser() to avoid the errors caused by
|
|
// comparing a value generated on CPU to the one generated on GPU.
|
|
wgpu::ComputePipeline MakeTestPipeline() {
|
|
wgpu::ShaderModule csModule = utils::CreateShaderModuleFromWGSL(device, R"(
|
|
[[block]] struct Uniforms {
|
|
dstTextureFlipY : u32;
|
|
};
|
|
[[block]] struct OutputBuf {
|
|
result : array<u32>;
|
|
};
|
|
[[group(0), binding(0)]] var src : texture_2d<f32>;
|
|
[[group(0), binding(1)]] var dst : texture_2d<f32>;
|
|
[[group(0), binding(2)]] var<storage_buffer> output : OutputBuf;
|
|
[[group(0), binding(3)]] var<uniform> uniforms : Uniforms;
|
|
[[builtin(global_invocation_id)]] var<in> GlobalInvocationID : vec3<u32>;
|
|
[[stage(compute), workgroup_size(1, 1, 1)]]
|
|
fn main() -> void {
|
|
// Current CopyTextureForBrowser only support full copy now.
|
|
// TODO(dawn:465): Refactor this after CopyTextureForBrowser
|
|
// support sub-rect copy.
|
|
var size : vec2<i32> = textureDimensions(src);
|
|
var dstTexCoord : vec2<i32> = vec2<i32>(GlobalInvocationID.xy);
|
|
var srcTexCoord : vec2<i32> = dstTexCoord;
|
|
if (uniforms.dstTextureFlipY == 1u) {
|
|
srcTexCoord.y = size.y - dstTexCoord.y - 1;
|
|
}
|
|
|
|
var srcColor : vec4<f32> = textureLoad(src, srcTexCoord, 0);
|
|
var dstColor : vec4<f32> = textureLoad(dst, dstTexCoord, 0);
|
|
var success : bool = all(srcColor == dstColor);
|
|
|
|
var outputIndex : u32 = GlobalInvocationID.y * u32(size.x) + GlobalInvocationID.x;
|
|
if (success) {
|
|
output.result[outputIndex] = 1u;
|
|
} else {
|
|
output.result[outputIndex] = 0u;
|
|
}
|
|
}
|
|
)");
|
|
|
|
wgpu::ComputePipelineDescriptor csDesc;
|
|
csDesc.computeStage.module = csModule;
|
|
csDesc.computeStage.entryPoint = "main";
|
|
|
|
return device.CreateComputePipeline(&csDesc);
|
|
}
|
|
|
|
void DoTest(const TextureSpec& srcSpec,
|
|
const TextureSpec& dstSpec,
|
|
const wgpu::Extent3D& copySize = {kDefaultTextureWidth, kDefaultTextureHeight},
|
|
const wgpu::CopyTextureForBrowserOptions options = {}) {
|
|
wgpu::TextureDescriptor srcDescriptor;
|
|
srcDescriptor.size = srcSpec.textureSize;
|
|
srcDescriptor.format = srcSpec.format;
|
|
srcDescriptor.mipLevelCount = srcSpec.level + 1;
|
|
srcDescriptor.usage =
|
|
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled;
|
|
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
|
|
|
wgpu::Texture dstTexture;
|
|
wgpu::TextureDescriptor dstDescriptor;
|
|
dstDescriptor.size = dstSpec.textureSize;
|
|
dstDescriptor.format = dstSpec.format;
|
|
dstDescriptor.mipLevelCount = dstSpec.level + 1;
|
|
dstDescriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled |
|
|
wgpu::TextureUsage::OutputAttachment;
|
|
dstTexture = device.CreateTexture(&dstDescriptor);
|
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
|
|
const utils::TextureDataCopyLayout copyLayout =
|
|
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
|
kTextureFormat,
|
|
{srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depth},
|
|
srcSpec.level);
|
|
|
|
const std::vector<RGBA8> textureArrayCopyData = GetSourceTextureData(copyLayout);
|
|
wgpu::ImageCopyTexture imageCopyTexture =
|
|
utils::CreateImageCopyTexture(srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z});
|
|
|
|
wgpu::TextureDataLayout textureDataLayout;
|
|
textureDataLayout.offset = 0;
|
|
textureDataLayout.bytesPerRow = copyLayout.bytesPerRow;
|
|
textureDataLayout.rowsPerImage = copyLayout.rowsPerImage;
|
|
|
|
device.GetQueue().WriteTexture(&imageCopyTexture, textureArrayCopyData.data(),
|
|
textureArrayCopyData.size() * sizeof(RGBA8),
|
|
&textureDataLayout, ©Layout.mipSize);
|
|
|
|
// Perform the texture to texture copy
|
|
wgpu::ImageCopyTexture srcImageCopyTexture =
|
|
utils::CreateImageCopyTexture(srcTexture, srcSpec.level, srcSpec.copyOrigin);
|
|
wgpu::ImageCopyTexture dstImageCopyTexture =
|
|
utils::CreateImageCopyTexture(dstTexture, dstSpec.level, dstSpec.copyOrigin);
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
queue.Submit(1, &commands);
|
|
|
|
device.GetQueue().CopyTextureForBrowser(&srcImageCopyTexture, &dstImageCopyTexture,
|
|
©Size, &options);
|
|
|
|
// Update uniform buffer based on test config
|
|
uint32_t uniformBufferData[] = {
|
|
options.flipY, // copy have flipY option
|
|
};
|
|
|
|
device.GetQueue().WriteBuffer(uniformBuffer, 0, uniformBufferData,
|
|
sizeof(uniformBufferData));
|
|
|
|
// Create output buffer to store result
|
|
wgpu::BufferDescriptor outputDesc;
|
|
outputDesc.size = copySize.width * copySize.height * sizeof(uint32_t);
|
|
outputDesc.usage =
|
|
wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
|
wgpu::Buffer outputBuffer = device.CreateBuffer(&outputDesc);
|
|
|
|
// Create texture views for test.
|
|
wgpu::TextureViewDescriptor srcTextureViewDesc = {};
|
|
srcTextureViewDesc.baseMipLevel = srcSpec.level;
|
|
wgpu::TextureView srcTextureView = srcTexture.CreateView(&srcTextureViewDesc);
|
|
|
|
wgpu::TextureViewDescriptor dstTextureViewDesc = {};
|
|
dstTextureViewDesc.baseMipLevel = dstSpec.level;
|
|
wgpu::TextureView dstTextureView = dstTexture.CreateView(&dstTextureViewDesc);
|
|
|
|
// Create bind group based on the config.
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(
|
|
device, testPipeline.GetBindGroupLayout(0),
|
|
{{0, srcTextureView},
|
|
{1, dstTextureView},
|
|
{2, outputBuffer, 0, copySize.width * copySize.height * sizeof(uint32_t)},
|
|
{3, uniformBuffer, 0, sizeof(uniformBufferData)}});
|
|
|
|
// Start a pipeline to check pixel value in bit form.
|
|
wgpu::CommandEncoder testEncoder = device.CreateCommandEncoder();
|
|
|
|
wgpu::CommandBuffer testCommands;
|
|
{
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
|
pass.SetPipeline(testPipeline);
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.Dispatch(copySize.width, copySize.height);
|
|
pass.EndPass();
|
|
|
|
testCommands = encoder.Finish();
|
|
}
|
|
queue.Submit(1, &testCommands);
|
|
|
|
std::vector<uint32_t> expectResult(copySize.width * copySize.height, 1);
|
|
EXPECT_BUFFER_U32_RANGE_EQ(expectResult.data(), outputBuffer, 0,
|
|
copySize.width * copySize.height);
|
|
}
|
|
|
|
wgpu::Buffer uniformBuffer; // Uniform buffer to store dst texture meta info.
|
|
wgpu::ComputePipeline testPipeline;
|
|
};
|
|
|
|
// Verify CopyTextureForBrowserTests works with internal pipeline.
|
|
// The case do copy without any transform.
|
|
TEST_P(CopyTextureForBrowserTests, PassthroughCopy) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 10;
|
|
constexpr uint32_t kHeight = 1;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnXDirection) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 1000;
|
|
constexpr uint32_t kHeight = 1;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnYDirection) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 1;
|
|
constexpr uint32_t kHeight = 1000;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyFromLargeTexture) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 899;
|
|
constexpr uint32_t kHeight = 999;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowserTests, VerifyFlipY) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 901;
|
|
constexpr uint32_t kHeight = 1001;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.flipY = true;
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight}, options);
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowserTests, VerifyFlipYInSlimTexture) {
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
constexpr uint32_t kWidth = 1;
|
|
constexpr uint32_t kHeight = 1001;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.flipY = true;
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight}, options);
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests,
|
|
D3D12Backend(),
|
|
MetalBackend(),
|
|
OpenGLBackend(),
|
|
OpenGLESBackend(),
|
|
VulkanBackend());
|