mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 14:43:31 +00:00
ExternalTexture has active, expired and destroyed states. Only active state external texture is valid to submit. Expired state external texture can be refresh to active but destroyed external texture cannot be refresh. Bug: chromium:1412338 Change-Id: Ic7f12d274d27b644f19ec3ef8b46c110610afa2b Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120982 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
645 lines
29 KiB
C++
645 lines
29 KiB
C++
// Copyright 2021 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 "dawn/tests/unittests/validation/ValidationTest.h"
|
|
|
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
|
#include "dawn/utils/WGPUHelpers.h"
|
|
|
|
namespace {
|
|
class ExternalTextureTest : public ValidationTest {
|
|
public:
|
|
wgpu::TextureDescriptor CreateTextureDescriptor(
|
|
wgpu::TextureFormat format = kDefaultTextureFormat) {
|
|
wgpu::TextureDescriptor descriptor;
|
|
descriptor.size.width = kWidth;
|
|
descriptor.size.height = kHeight;
|
|
descriptor.size.depthOrArrayLayers = kDefaultDepth;
|
|
descriptor.mipLevelCount = kDefaultMipLevels;
|
|
descriptor.sampleCount = kDefaultSampleCount;
|
|
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
descriptor.format = format;
|
|
descriptor.usage = kDefaultUsage;
|
|
return descriptor;
|
|
}
|
|
|
|
wgpu::ExternalTexture CreateDefaultExternalTexture() {
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = defaultTexture.CreateView();
|
|
return device.CreateExternalTexture(&externalDesc);
|
|
}
|
|
|
|
void SubmitExternalTextureInDefaultRenderPass(wgpu::ExternalTexture externalTexture,
|
|
bool success) {
|
|
// Create a bind group that contains the external texture.
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
|
|
// Create another texture to use as a color attachment.
|
|
wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
|
|
wgpu::TextureView renderView = renderTexture.CreateView();
|
|
|
|
utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
if (success) {
|
|
queue.Submit(1, &commands);
|
|
} else {
|
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
|
}
|
|
}
|
|
|
|
void SubmitExternalTextureInDefaultComputePass(wgpu::ExternalTexture externalTexture,
|
|
bool success) {
|
|
// Create a bind group that contains the external texture.
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
|
|
wgpu::ComputePassDescriptor computePass;
|
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass(&computePass);
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
if (success) {
|
|
queue.Submit(1, &commands);
|
|
} else {
|
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void SetUp() override {
|
|
ValidationTest::SetUp();
|
|
|
|
queue = device.GetQueue();
|
|
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
defaultTexture = device.CreateTexture(&textureDescriptor);
|
|
}
|
|
|
|
wgpu::ExternalTextureDescriptor CreateDefaultExternalTextureDescriptor() {
|
|
wgpu::ExternalTextureDescriptor desc;
|
|
desc.yuvToRgbConversionMatrix = mPlaceholderConstantArray.data();
|
|
desc.gamutConversionMatrix = mPlaceholderConstantArray.data();
|
|
desc.srcTransferFunctionParameters = mPlaceholderConstantArray.data();
|
|
desc.dstTransferFunctionParameters = mPlaceholderConstantArray.data();
|
|
desc.visibleSize = {kWidth, kHeight};
|
|
|
|
return desc;
|
|
}
|
|
|
|
static constexpr uint32_t kWidth = 32;
|
|
static constexpr uint32_t kHeight = 32;
|
|
static constexpr uint32_t kDefaultDepth = 1;
|
|
static constexpr uint32_t kDefaultMipLevels = 1;
|
|
static constexpr uint32_t kDefaultSampleCount = 1;
|
|
static constexpr wgpu::TextureUsage kDefaultUsage =
|
|
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
|
|
|
|
static constexpr wgpu::TextureFormat kDefaultTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
|
static constexpr wgpu::TextureFormat kBiplanarPlane0Format = wgpu::TextureFormat::R8Unorm;
|
|
static constexpr wgpu::TextureFormat kBiplanarPlane1Format = wgpu::TextureFormat::RG8Unorm;
|
|
|
|
std::array<float, 12> mPlaceholderConstantArray;
|
|
|
|
wgpu::Queue queue;
|
|
wgpu::Texture defaultTexture;
|
|
};
|
|
|
|
TEST_F(ExternalTextureTest, CreateExternalTextureValidation) {
|
|
// Creating an external texture from a 2D, single-subresource texture should succeed.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
device.CreateExternalTexture(&externalDesc);
|
|
}
|
|
|
|
// Creating an external texture from a non-2D texture should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
textureDescriptor.dimension = wgpu::TextureDimension::e3D;
|
|
textureDescriptor.usage = wgpu::TextureUsage::TextureBinding;
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = internalTexture.CreateView();
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture from a texture with mip count > 1 should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
textureDescriptor.mipLevelCount = 2;
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = internalTexture.CreateView();
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture from a texture without TextureUsage::TextureBinding should
|
|
// fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
textureDescriptor.mipLevelCount = 2;
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = internalTexture.CreateView();
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture with an unsupported format should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
textureDescriptor.format = wgpu::TextureFormat::R8Uint;
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = internalTexture.CreateView();
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture with an multisampled texture should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
textureDescriptor.sampleCount = 4;
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = internalTexture.CreateView();
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture with an error texture view should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture internalTexture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::TextureViewDescriptor errorViewDescriptor;
|
|
errorViewDescriptor.format = kDefaultTextureFormat;
|
|
errorViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
|
|
errorViewDescriptor.mipLevelCount = 1;
|
|
errorViewDescriptor.arrayLayerCount = 2;
|
|
ASSERT_DEVICE_ERROR(wgpu::TextureView errorTextureView =
|
|
internalTexture.CreateView(&errorViewDescriptor));
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = errorTextureView;
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
}
|
|
|
|
TEST_F(ExternalTextureTest, CreateExternalTextureConstantValueValidation) {
|
|
DAWN_SKIP_TEST_IF(UsesWire());
|
|
// Creating a single plane external texture without a YUV-to-RGB matrix should pass.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.yuvToRgbConversionMatrix = nullptr;
|
|
device.CreateExternalTexture(&externalDesc);
|
|
}
|
|
|
|
// Creating a multiplanar external texture without a YUV-to-RGB matrix should fail.
|
|
{
|
|
wgpu::TextureDescriptor plane0TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane0Format);
|
|
wgpu::TextureDescriptor plane1TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane1Format);
|
|
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
|
|
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture0.CreateView();
|
|
externalDesc.plane1 = texture1.CreateView();
|
|
externalDesc.yuvToRgbConversionMatrix = nullptr;
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture without a gamut conversion matrix should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.gamutConversionMatrix = nullptr;
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture without source transfer function constants should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.srcTransferFunctionParameters = nullptr;
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating an external texture without destination transfer function constants should fail.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.dstTransferFunctionParameters = nullptr;
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
}
|
|
|
|
// Test that external texture creation works as expected in multiplane scenarios.
|
|
TEST_F(ExternalTextureTest, CreateMultiplanarExternalTextureValidation) {
|
|
// Creating an external texture from two 2D, single-subresource textures with a biplanar
|
|
// format should succeed.
|
|
{
|
|
wgpu::TextureDescriptor plane0TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane0Format);
|
|
wgpu::TextureDescriptor plane1TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane1Format);
|
|
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
|
|
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture0.CreateView();
|
|
externalDesc.plane1 = texture1.CreateView();
|
|
|
|
device.CreateExternalTexture(&externalDesc);
|
|
}
|
|
|
|
// Creating a multiplanar external texture with an unsupported format for plane0 should
|
|
// result in an error.
|
|
{
|
|
wgpu::TextureDescriptor plane0TextureDescriptor =
|
|
CreateTextureDescriptor(kDefaultTextureFormat);
|
|
wgpu::TextureDescriptor plane1TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane1Format);
|
|
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
|
|
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture0.CreateView();
|
|
externalDesc.plane1 = texture1.CreateView();
|
|
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// Creating a multiplanar external texture with an unsupported format for plane1 should
|
|
// result in an error.
|
|
{
|
|
wgpu::TextureDescriptor plane0TextureDescriptor =
|
|
CreateTextureDescriptor(kBiplanarPlane0Format);
|
|
wgpu::TextureDescriptor plane1TextureDescriptor =
|
|
CreateTextureDescriptor(kDefaultTextureFormat);
|
|
wgpu::Texture texture0 = device.CreateTexture(&plane0TextureDescriptor);
|
|
wgpu::Texture texture1 = device.CreateTexture(&plane1TextureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture0.CreateView();
|
|
externalDesc.plane1 = texture1.CreateView();
|
|
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
}
|
|
|
|
// Test that refresh on an expired/active external texture.
|
|
TEST_F(ExternalTextureTest, RefreshExternalTexture) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
|
|
externalTexture.Refresh();
|
|
externalTexture.Expire();
|
|
externalTexture.Refresh();
|
|
}
|
|
|
|
// Test that refresh on a destroyed external texture results in an error.
|
|
TEST_F(ExternalTextureTest, RefreshDestroyedExternalTexture) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
|
|
// Refresh on destroyed external texture should result in an error.
|
|
externalTexture.Destroy();
|
|
ASSERT_DEVICE_ERROR(externalTexture.Refresh());
|
|
}
|
|
|
|
// Test that expire on a destroyed external texture results in an error.
|
|
TEST_F(ExternalTextureTest, ExpireDestroyedExternalTexture) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
|
|
externalTexture.Destroy();
|
|
ASSERT_DEVICE_ERROR(externalTexture.Expire());
|
|
}
|
|
|
|
// Test that submitting a render pass that contains an active external texture.
|
|
TEST_F(ExternalTextureTest, SubmitActiveExternalTextureInRenderPass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
SubmitExternalTextureInDefaultRenderPass(externalTexture, true /* success = true */);
|
|
}
|
|
|
|
// Test that submitting a render pass that contains an expired external texture results in an error.
|
|
TEST_F(ExternalTextureTest, SubmitExpiredExternalTextureInRenderPass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
externalTexture.Expire();
|
|
SubmitExternalTextureInDefaultRenderPass(externalTexture, false /* success = false */);
|
|
}
|
|
|
|
// Test that submitting a render pass that contains an destroyed external texture results in an
|
|
// error.
|
|
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInRenderPass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
externalTexture.Destroy();
|
|
SubmitExternalTextureInDefaultRenderPass(externalTexture, false /* success = false */);
|
|
}
|
|
|
|
// Test that submitting a compute pass that contains an active external.
|
|
TEST_F(ExternalTextureTest, SubmitActiveExternalTextureInComputePass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
SubmitExternalTextureInDefaultComputePass(externalTexture, true /* success = true */);
|
|
}
|
|
|
|
// Test that submitting a compute pass that contains an expired external texture results in an
|
|
// error.
|
|
TEST_F(ExternalTextureTest, SubmitExpiredExternalTextureInComputePass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
externalTexture.Expire();
|
|
SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
|
|
}
|
|
|
|
// Test that submitting a compute pass that contains an active external texture should success.
|
|
TEST_F(ExternalTextureTest, SubmitDestroyedExternalTextureInComputePass) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
externalTexture.Destroy();
|
|
SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
|
|
}
|
|
|
|
// Test that refresh an expired external texture and submit a compute pass with it.
|
|
TEST_F(ExternalTextureTest, RefreshExpiredExternalTexture) {
|
|
wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
|
|
externalTexture.Expire();
|
|
|
|
// Submit with expired external texture results in error
|
|
SubmitExternalTextureInDefaultComputePass(externalTexture, false /* success = false */);
|
|
|
|
externalTexture.Refresh();
|
|
// Refreshed external texture could be submitted.
|
|
SubmitExternalTextureInDefaultComputePass(externalTexture, true /* success = true */);
|
|
}
|
|
|
|
// Test that submitting a render pass that contains a dereferenced external texture results in
|
|
// success
|
|
TEST_F(ExternalTextureTest, SubmitDereferencedExternalTextureInRenderPass) {
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
|
|
|
|
// Create a bind group that contains the external texture.
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
|
|
// Create another texture to use as a color attachment.
|
|
wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
|
|
wgpu::TextureView renderView = renderTexture.CreateView();
|
|
|
|
utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
|
|
|
|
// Control case should succeed.
|
|
{
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
|
{
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
}
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
queue.Submit(1, &commands);
|
|
}
|
|
|
|
// Dereferencing the external texture should not result in a use-after-free error.
|
|
{
|
|
externalTexture = nullptr;
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
|
{
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
}
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
queue.Submit(1, &commands);
|
|
}
|
|
}
|
|
|
|
// Ensure that bind group validation catches external textures mimatched from the BGL.
|
|
TEST_F(ExternalTextureTest, BindGroupDoesNotMatchLayout) {
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
|
|
|
|
// Control case should succeed.
|
|
{
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
}
|
|
|
|
// Bind group creation should fail when an external texture is not present in the
|
|
// corresponding slot of the bind group layout.
|
|
{
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Uniform}});
|
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, bgl, {{0, externalTexture}}));
|
|
}
|
|
}
|
|
|
|
// Regression test for crbug.com/1343099 where BindGroup validation let other binding types be used
|
|
// for external texture bindings.
|
|
TEST_F(ExternalTextureTest, TextureViewBindingDoesntMatch) {
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
// The bug was that this passed validation and crashed inside the backends with a null
|
|
// dereference. It passed validation because the number of bindings matched (1 == 1) and that
|
|
// the validation didn't check that an external texture binding was required, fell back to
|
|
// checking for the binding type of entry 0 that had been decayed to be a sampled texture view.
|
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, bgl, {{0, texture.CreateView()}}));
|
|
}
|
|
|
|
// Ensure that bind group validation catches error external textures.
|
|
TEST_F(ExternalTextureTest, UseErrorExternalTextureInBindGroup) {
|
|
// Control case should succeed.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
}
|
|
|
|
// Bind group creation should fail when an error external texture is present.
|
|
{
|
|
wgpu::ExternalTexture errorExternalTexture = device.CreateErrorExternalTexture();
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, bgl, {{0, errorExternalTexture}}));
|
|
}
|
|
}
|
|
|
|
// Test create external texture with too large visible rect results in error.
|
|
TEST_F(ExternalTextureTest, CreateExternalTextureWithErrorVisibleOriginOrSize) {
|
|
// Control case should succeed.
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.visibleOrigin = {0, 0};
|
|
externalDesc.visibleSize = {texture.GetWidth(), texture.GetHeight()};
|
|
device.CreateExternalTexture(&externalDesc);
|
|
}
|
|
|
|
// VisibleOrigin is OOB on x
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.visibleOrigin = {1, 0};
|
|
externalDesc.visibleSize = {texture.GetWidth(), texture.GetHeight()};
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// VisibleOrigin is OOB on y
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.visibleOrigin = {0, 1};
|
|
externalDesc.visibleSize = {texture.GetWidth(), texture.GetHeight()};
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// VisibleSize is OOB on width
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.visibleOrigin = {0, 0};
|
|
externalDesc.visibleSize = {texture.GetWidth() + 1, texture.GetHeight()};
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
|
|
// VisibleSize is OOB on height
|
|
{
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
externalDesc.visibleOrigin = {0, 0};
|
|
externalDesc.visibleSize = {texture.GetWidth(), texture.GetHeight() + 1};
|
|
ASSERT_DEVICE_ERROR(device.CreateExternalTexture(&externalDesc));
|
|
}
|
|
}
|
|
|
|
// Test that submitting an external texture with a plane that is not submittable results in error.
|
|
TEST_F(ExternalTextureTest, SubmitExternalTextureWithDestroyedPlane) {
|
|
wgpu::TextureDescriptor textureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
|
|
|
wgpu::ExternalTextureDescriptor externalDesc = CreateDefaultExternalTextureDescriptor();
|
|
externalDesc.plane0 = texture.CreateView();
|
|
wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
|
|
|
|
// Create a bind group that contains the external texture.
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
|
device, {{0, wgpu::ShaderStage::Fragment, &utils::kExternalTextureBindingLayout}});
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, externalTexture}});
|
|
|
|
// Create another texture to use as a color attachment.
|
|
wgpu::TextureDescriptor renderTextureDescriptor = CreateTextureDescriptor();
|
|
wgpu::Texture renderTexture = device.CreateTexture(&renderTextureDescriptor);
|
|
wgpu::TextureView renderView = renderTexture.CreateView();
|
|
|
|
utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
|
|
|
|
// Control case should succeed.
|
|
{
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
|
{
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
}
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
queue.Submit(1, &commands);
|
|
}
|
|
|
|
// Destroying the plane0 backed texture should result in an error.
|
|
{
|
|
texture.Destroy();
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
|
{
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.End();
|
|
}
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
|
}
|
|
}
|
|
|
|
} // namespace
|