mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-11 14:41:50 +00:00
Support internal pipelines for Dawn
Like copyTextureCHROMIUM in Chromium, CopyImageBitmapToTexture can use internal pipeline to do the GPU uploading. But Dawn doesn't support internal pipeline now. This patch adds the first internal pipeline for Dawn and add the API CopyTextureForBrowser to use internal pipeline to do gpu uploading. The patch integrates very simple wgsl vertex/fragment shaders to do simple direct blit to verify the whole system works. BUG=dawn:465 Change-Id: I8b566af38a10eea00f7426c39e752958ef057abd Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/30960 Commit-Queue: Shaobo Yan <shaobo.yan@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
131e619fe4
commit
db8766bb23
@@ -275,6 +275,7 @@ source_set("dawn_end2end_tests_sources") {
|
||||
"end2end/ComputeSharedMemoryTests.cpp",
|
||||
"end2end/ComputeStorageBufferBarrierTests.cpp",
|
||||
"end2end/CopyTests.cpp",
|
||||
"end2end/CopyTextureForBrowserTests.cpp",
|
||||
"end2end/CreateReadyPipelineTests.cpp",
|
||||
"end2end/CullingTests.cpp",
|
||||
"end2end/DebugMarkerTests.cpp",
|
||||
|
||||
183
src/tests/end2end/CopyTextureForBrowserTests.cpp
Normal file
183
src/tests/end2end/CopyTextureForBrowserTests.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// 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/TestUtils.h"
|
||||
#include "utils/TextureFormatUtils.h"
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
class CopyTextureForBrowserTests : public DawnTest {
|
||||
protected:
|
||||
static constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||
|
||||
struct TextureSpec {
|
||||
wgpu::Origin3D copyOrigin;
|
||||
wgpu::Extent3D textureSize;
|
||||
uint32_t level;
|
||||
};
|
||||
|
||||
static std::vector<RGBA8> GetExpectedTextureData(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;
|
||||
}
|
||||
|
||||
static void PackTextureData(const RGBA8* srcData,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t srcTexelsPerRow,
|
||||
RGBA8* dstData,
|
||||
uint32_t dstTexelsPerRow) {
|
||||
for (unsigned int y = 0; y < height; ++y) {
|
||||
for (unsigned int x = 0; x < width; ++x) {
|
||||
unsigned int src = x + y * srcTexelsPerRow;
|
||||
unsigned int dst = x + y * dstTexelsPerRow;
|
||||
dstData[dst] = srcData[src];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoTest(const TextureSpec& srcSpec,
|
||||
const TextureSpec& dstSpec,
|
||||
const wgpu::Extent3D& copySize) {
|
||||
wgpu::TextureDescriptor srcDescriptor;
|
||||
srcDescriptor.size = srcSpec.textureSize;
|
||||
srcDescriptor.format = kTextureFormat;
|
||||
srcDescriptor.mipLevelCount = srcSpec.level + 1;
|
||||
srcDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
||||
wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment;
|
||||
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
||||
|
||||
wgpu::Texture dstTexture;
|
||||
wgpu::TextureDescriptor dstDescriptor;
|
||||
dstDescriptor.size = dstSpec.textureSize;
|
||||
dstDescriptor.format = kTextureFormat;
|
||||
dstDescriptor.mipLevelCount = dstSpec.level + 1;
|
||||
dstDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
||||
wgpu::TextureUsage::OutputAttachment;
|
||||
dstTexture = device.CreateTexture(&dstDescriptor);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
|
||||
// Use writeTexture to populate the current slice of the texture in
|
||||
// `level` mip level for all platforms except OpenGL.
|
||||
// TODO(shaobo.yan@intel.com): OpenGL doesn't have 'WriteTexture' implementation.
|
||||
const utils::TextureDataCopyLayout copyLayout =
|
||||
utils::GetTextureDataCopyLayoutForTexture2DAtLevel(
|
||||
kTextureFormat,
|
||||
{srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depth},
|
||||
srcSpec.level, 0);
|
||||
|
||||
const std::vector<RGBA8> textureArrayCopyData = GetExpectedTextureData(copyLayout);
|
||||
wgpu::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z});
|
||||
|
||||
wgpu::TextureDataLayout textureDataLayout;
|
||||
textureDataLayout.offset = 0;
|
||||
textureDataLayout.bytesPerRow = copyLayout.bytesPerRow;
|
||||
textureDataLayout.rowsPerImage = copyLayout.bytesPerImage / copyLayout.bytesPerRow;
|
||||
|
||||
device.GetDefaultQueue().WriteTexture(&textureCopyView, textureArrayCopyData.data(),
|
||||
textureArrayCopyData.size() * sizeof(RGBA8),
|
||||
&textureDataLayout, ©Layout.mipSize);
|
||||
|
||||
const wgpu::Extent3D copySizePerSlice = {copySize.width, copySize.height, 1};
|
||||
// Perform the texture to texture copy
|
||||
wgpu::TextureCopyView srcTextureCopyView =
|
||||
utils::CreateTextureCopyView(srcTexture, srcSpec.level, srcSpec.copyOrigin);
|
||||
wgpu::TextureCopyView dstTextureCopyView =
|
||||
utils::CreateTextureCopyView(dstTexture, dstSpec.level, dstSpec.copyOrigin);
|
||||
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
// Perform a copy here for testing.
|
||||
device.GetDefaultQueue().CopyTextureForBrowser(&srcTextureCopyView, &dstTextureCopyView,
|
||||
©Size);
|
||||
|
||||
// Texels in single slice.
|
||||
const uint32_t texelCountInCopyRegion = utils::GetTexelCountInCopyRegion(
|
||||
copyLayout.bytesPerRow, copyLayout.bytesPerImage / copyLayout.bytesPerRow,
|
||||
copySizePerSlice, kTextureFormat);
|
||||
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
||||
for (uint32_t slice = 0; slice < copySize.depth; ++slice) {
|
||||
std::fill(expected.begin(), expected.end(), RGBA8());
|
||||
const uint32_t texelIndexOffset = copyLayout.texelBlocksPerImage * slice;
|
||||
const uint32_t expectedTexelArrayDataStartIndex =
|
||||
texelIndexOffset +
|
||||
(srcSpec.copyOrigin.x + srcSpec.copyOrigin.y * copyLayout.texelBlocksPerRow);
|
||||
PackTextureData(&textureArrayCopyData[expectedTexelArrayDataStartIndex], copySize.width,
|
||||
copySize.height, copyLayout.texelBlocksPerRow, expected.data(),
|
||||
copySize.width);
|
||||
|
||||
EXPECT_TEXTURE_RGBA8_EQ(expected.data(), dstTexture, dstSpec.copyOrigin.x,
|
||||
dstSpec.copyOrigin.y, copySize.width, copySize.height,
|
||||
dstSpec.level, dstSpec.copyOrigin.z + slice)
|
||||
<< "Texture to Texture copy failed copying region [(" << srcSpec.copyOrigin.x
|
||||
<< ", " << srcSpec.copyOrigin.y << "), (" << srcSpec.copyOrigin.x + copySize.width
|
||||
<< ", " << srcSpec.copyOrigin.y + copySize.height << ")) from "
|
||||
<< srcSpec.textureSize.width << " x " << srcSpec.textureSize.height
|
||||
<< " texture at mip level " << srcSpec.level << " layer "
|
||||
<< srcSpec.copyOrigin.z + slice << " to [(" << dstSpec.copyOrigin.x << ", "
|
||||
<< dstSpec.copyOrigin.y << "), (" << dstSpec.copyOrigin.x + copySize.width << ", "
|
||||
<< dstSpec.copyOrigin.y + copySize.height << ")) region of "
|
||||
<< dstSpec.textureSize.width << " x " << dstSpec.textureSize.height
|
||||
<< " texture at mip level " << dstSpec.level << " layer "
|
||||
<< dstSpec.copyOrigin.z + slice << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Verify CopyTextureForBrowserTests works with internal pipeline.
|
||||
// The case do copy without any transform.
|
||||
TEST_P(CopyTextureForBrowserTests, PassthroughCopy) {
|
||||
// These tests fails due to crbug.com/tint/63.
|
||||
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||
DAWN_SKIP_TEST_IF(IsVulkan());
|
||||
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
||||
|
||||
// OpenGL tests fails due to 'WriteTexture' unimplemented.
|
||||
// Related bug : crbug.com/dawn/483
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
constexpr uint32_t kWidth = 10;
|
||||
constexpr uint32_t kHeight = 1;
|
||||
|
||||
TextureSpec textureSpec;
|
||||
textureSpec.copyOrigin = {0, 0, 0};
|
||||
textureSpec.level = 0;
|
||||
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
OpenGLBackend(),
|
||||
VulkanBackend());
|
||||
Reference in New Issue
Block a user