blob: e95c7e1a5056dd11180539e22ff7592059910f67 [file] [log] [blame]
// 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.
// This file contains test for deprecated parts of Dawn's API while following WebGPU's evolution.
// It contains test for the "old" behavior that will be deleted once users are migrated, tests that
// a deprecation warning is emitted when the "old" behavior is used, and tests that an error is
// emitted when both the old and the new behavior are used (when applicable).
#include "tests/DawnTest.h"
#include "common/Constants.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/WGPUHelpers.h"
class DeprecationTests : public DawnTest {
protected:
void TestSetUp() override {
// Skip when validation is off because warnings might be emitted during validation calls
DAWN_SKIP_TEST_IF(IsDawnValidationSkipped());
}
void TearDown() override {
if (!UsesWire()) {
EXPECT_EQ(mLastWarningCount,
dawn_native::GetDeprecationWarningCountForTesting(device.Get()));
}
}
size_t mLastWarningCount = 0;
};
#define EXPECT_DEPRECATION_WARNING(statement) \
do { \
if (UsesWire()) { \
statement; \
} else { \
size_t warningsBefore = \
dawn_native::GetDeprecationWarningCountForTesting(device.Get()); \
statement; \
size_t warningsAfter = \
dawn_native::GetDeprecationWarningCountForTesting(device.Get()); \
EXPECT_EQ(mLastWarningCount, warningsBefore); \
EXPECT_EQ(warningsAfter, warningsBefore + 1); \
mLastWarningCount = warningsAfter; \
} \
} while (0)
// Tests for Device::CreateQueue -> Device::GetDefaultQueue.
// Test that using CreateQueue produces a deprecation warning
TEST_P(DeprecationTests, CreateQueueIsDeprecated) {
EXPECT_DEPRECATION_WARNING(device.CreateQueue());
}
// Test that queues created from CreateQueue can be used for things
TEST_P(DeprecationTests, CreateQueueReturnsFunctionalQueue) {
wgpu::Queue q;
EXPECT_DEPRECATION_WARNING(q = device.CreateQueue());
q.Submit(0, nullptr);
}
// Tests for BindGroupLayoutEntry::textureDimension -> viewDimension
// Test that creating a BGL with textureDimension produces a deprecation warning.
TEST_P(DeprecationTests, BGLEntryTextureDimensionIsDeprecated) {
wgpu::BindGroupLayoutEntry entryDesc;
entryDesc.binding = 0;
entryDesc.visibility = wgpu::ShaderStage::None;
entryDesc.type = wgpu::BindingType::SampledTexture;
entryDesc.textureDimension = wgpu::TextureViewDimension::e2D;
wgpu::BindGroupLayoutDescriptor bglDesc;
bglDesc.entryCount = 1;
bglDesc.entries = &entryDesc;
EXPECT_DEPRECATION_WARNING(device.CreateBindGroupLayout(&bglDesc));
}
// Test that creating a BGL with default viewDimension and textureDimension doesn't emit a warning
TEST_P(DeprecationTests, BGLEntryTextureDimensionAndViewUndefinedEmitsNoWarning) {
wgpu::BindGroupLayoutEntry entryDesc;
entryDesc.binding = 0;
entryDesc.visibility = wgpu::ShaderStage::None;
entryDesc.type = wgpu::BindingType::Sampler;
wgpu::BindGroupLayoutDescriptor bglDesc;
bglDesc.entryCount = 1;
bglDesc.entries = &entryDesc;
device.CreateBindGroupLayout(&bglDesc);
}
// Test that creating a BGL with both textureDimension and viewDimension is an error
TEST_P(DeprecationTests, BGLEntryTextureAndViewDimensionIsInvalid) {
wgpu::BindGroupLayoutEntry entryDesc;
entryDesc.binding = 0;
entryDesc.visibility = wgpu::ShaderStage::None;
entryDesc.type = wgpu::BindingType::SampledTexture;
entryDesc.textureDimension = wgpu::TextureViewDimension::e2D;
entryDesc.viewDimension = wgpu::TextureViewDimension::e2D;
wgpu::BindGroupLayoutDescriptor bglDesc;
bglDesc.entryCount = 1;
bglDesc.entries = &entryDesc;
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&bglDesc));
}
// Test that creating a BGL with both textureDimension still does correct state tracking
TEST_P(DeprecationTests, BGLEntryTextureDimensionStateTracking) {
// Create a BGL that expects a cube map
wgpu::BindGroupLayoutEntry entryDesc = {};
entryDesc.binding = 0;
entryDesc.visibility = wgpu::ShaderStage::None;
entryDesc.type = wgpu::BindingType::SampledTexture;
entryDesc.textureDimension = wgpu::TextureViewDimension::Cube;
wgpu::BindGroupLayoutDescriptor bglDesc = {};
bglDesc.entryCount = 1;
bglDesc.entries = &entryDesc;
wgpu::BindGroupLayout layout;
EXPECT_DEPRECATION_WARNING(layout = device.CreateBindGroupLayout(&bglDesc));
// Create a 2D array view and a cube view
wgpu::TextureDescriptor textureDesc = {};
textureDesc.usage = wgpu::TextureUsage::Sampled;
textureDesc.size = {1, 1, 1};
textureDesc.arrayLayerCount = 6;
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
wgpu::Texture texture = device.CreateTexture(&textureDesc);
wgpu::TextureViewDescriptor viewDesc = {};
viewDesc.dimension = wgpu::TextureViewDimension::e2DArray;
viewDesc.baseArrayLayer = 0;
viewDesc.arrayLayerCount = 6;
wgpu::TextureView arrayView = texture.CreateView(&viewDesc);
viewDesc.dimension = wgpu::TextureViewDimension::Cube;
wgpu::TextureView cubeView = texture.CreateView(&viewDesc);
// textureDimension is correctly taken into account and only the BindGroup with the Cube view is
// valid.
utils::MakeBindGroup(device, layout, {{0, cubeView}});
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, arrayView}}));
}
// Tests for ShaderModuleDescriptor.code/codeSize -> ShaderModuleSPIRVDescriptor
static const char kEmptyShader[] = R"(#version 450
void main() {
})";
// That creating a ShaderModule without the chained descriptor gives a warning.
TEST_P(DeprecationTests, ShaderModuleNoSubDescriptorIsDeprecated) {
std::vector<uint32_t> spirv =
CompileGLSLToSpirv(utils::SingleShaderStage::Compute, kEmptyShader);
wgpu::ShaderModuleDescriptor descriptor;
descriptor.codeSize = static_cast<uint32_t>(spirv.size());
descriptor.code = spirv.data();
EXPECT_DEPRECATION_WARNING(device.CreateShaderModule(&descriptor));
}
// That creating a ShaderModule with both inline code and the chained descriptor is an error.
TEST_P(DeprecationTests, ShaderModuleBothInlinedAndChainedIsInvalid) {
std::vector<uint32_t> spirv =
CompileGLSLToSpirv(utils::SingleShaderStage::Compute, kEmptyShader);
wgpu::ShaderModuleSPIRVDescriptor spirvDesc;
spirvDesc.codeSize = static_cast<uint32_t>(spirv.size());
spirvDesc.code = spirv.data();
wgpu::ShaderModuleDescriptor descriptor;
descriptor.nextInChain = &spirvDesc;
descriptor.codeSize = static_cast<uint32_t>(spirv.size());
descriptor.code = spirv.data();
ASSERT_DEVICE_ERROR(device.CreateShaderModule(&descriptor));
}
// That creating a ShaderModule with both inline code still does correct state tracking
TEST_P(DeprecationTests, ShaderModuleInlinedCodeStateTracking) {
std::vector<uint32_t> spirv =
CompileGLSLToSpirv(utils::SingleShaderStage::Compute, kEmptyShader);
wgpu::ShaderModuleDescriptor descriptor;
descriptor.codeSize = static_cast<uint32_t>(spirv.size());
descriptor.code = spirv.data();
wgpu::ShaderModule module;
EXPECT_DEPRECATION_WARNING(module = device.CreateShaderModule(&descriptor));
// Creating a compute pipeline works, because it is a compute module.
wgpu::ComputePipelineDescriptor computePipelineDesc;
computePipelineDesc.layout = nullptr;
computePipelineDesc.computeStage.module = module;
computePipelineDesc.computeStage.entryPoint = "main";
device.CreateComputePipeline(&computePipelineDesc);
utils::ComboRenderPipelineDescriptor renderPipelineDesc(device);
renderPipelineDesc.vertexStage.module =
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, kEmptyShader);
renderPipelineDesc.cFragmentStage.module = module;
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&renderPipelineDesc));
}
// Tests for BufferCopyView.rowPitch/imageHeight -> bytesPerRow/rowsPerImage
class BufferCopyViewDeprecationTests : public DeprecationTests {
protected:
void TestSetUp() override {
DeprecationTests::TestSetUp();
wgpu::BufferDescriptor bufferDesc;
bufferDesc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
bufferDesc.size = kTextureBytesPerRowAlignment * 2;
buffer = device.CreateBuffer(&bufferDesc);
wgpu::TextureDescriptor textureDesc;
textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
textureDesc.size = {2, 2, 1};
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
texture = device.CreateTexture(&textureDesc);
}
enum CopyType {
B2T,
T2B,
};
void DoCopy(CopyType type, const wgpu::BufferCopyView& bufferView) {
wgpu::TextureCopyView textureCopyView;
textureCopyView.texture = texture;
textureCopyView.mipLevel = 0;
textureCopyView.arrayLayer = 0;
textureCopyView.origin = {0, 0};
wgpu::Extent3D copySize = {2, 2, 1};
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
switch (type) {
case B2T:
encoder.CopyBufferToTexture(&bufferView, &textureCopyView, &copySize);
break;
case T2B:
encoder.CopyTextureToBuffer(&textureCopyView, &bufferView, &copySize);
break;
}
encoder.Finish();
}
wgpu::Buffer buffer;
wgpu::Texture texture;
};
// Test that using rowPitch produces a deprecation warning.
TEST_P(BufferCopyViewDeprecationTests, RowPitchIsDeprecated) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.rowPitch = 256;
EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view));
EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view));
}
// Test that using imageHeight produces a deprecation warning.
TEST_P(BufferCopyViewDeprecationTests, ImageHeightIsDeprecated) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.imageHeight = 2;
view.bytesPerRow = 256;
EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view));
EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view));
}
// Test that using both rowPitch and bytesPerRow produces a validation error.
TEST_P(BufferCopyViewDeprecationTests, BothRowPitchAndBytesPerRowIsInvalid) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.rowPitch = 256;
view.bytesPerRow = 256;
ASSERT_DEVICE_ERROR(DoCopy(B2T, view));
ASSERT_DEVICE_ERROR(DoCopy(T2B, view));
}
// Test that using both imageHeight and rowsPerImage produces a validation error.
TEST_P(BufferCopyViewDeprecationTests, BothImageHeightAndRowsPerImageIsInvalid) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.imageHeight = 2;
view.bytesPerRow = 256;
view.rowsPerImage = 2;
ASSERT_DEVICE_ERROR(DoCopy(B2T, view));
ASSERT_DEVICE_ERROR(DoCopy(T2B, view));
}
// Test that rowPitch is correctly taken into account for validation
TEST_P(BufferCopyViewDeprecationTests, RowPitchTakenIntoAccountForValidation) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.rowPitch = 256;
EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view));
EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view));
view.rowPitch = 128;
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view)));
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view)));
}
// Test that imageHeight is correctly taken into account for validation
TEST_P(BufferCopyViewDeprecationTests, ImageHeightTakenIntoAccountForValidation) {
wgpu::BufferCopyView view;
view.buffer = buffer;
view.imageHeight = 2;
view.bytesPerRow = 256;
EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view));
EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view));
view.imageHeight = 1;
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(DoCopy(B2T, view)));
ASSERT_DEVICE_ERROR(EXPECT_DEPRECATION_WARNING(DoCopy(T2B, view)));
}
DAWN_INSTANTIATE_TEST(BufferCopyViewDeprecationTests,
D3D12Backend(),
MetalBackend(),
NullBackend(),
OpenGLBackend(),
VulkanBackend());
DAWN_INSTANTIATE_TEST(DeprecationTests,
D3D12Backend(),
MetalBackend(),
NullBackend(),
OpenGLBackend(),
VulkanBackend());