Implement depth24unorm-stencil8 and depth32float-stencil8 formats

- Add format implementation on D3D12, Metal and Vulkan
- Add more formats in depth/stencil copy, sampling and load op tests and
  refactor them to test with parameters.

BUG=dawn:690

Change-Id: I829d1eea3ce35ffb39417ea23fb8afba6d542769
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/73180
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
This commit is contained in:
Li Hao 2022-01-05 01:31:16 +00:00 committed by Dawn LUCI CQ
parent b61f09ec58
commit 538d8d5d1c
11 changed files with 481 additions and 216 deletions

View File

@ -89,6 +89,11 @@ uint16_t Float32ToFloat16(float fp32);
float Float16ToFloat32(uint16_t fp16); float Float16ToFloat32(uint16_t fp16);
bool IsFloat16NaN(uint16_t fp16); bool IsFloat16NaN(uint16_t fp16);
template <typename T>
T FloatToUnorm(float value) {
return static_cast<T>(value * static_cast<float>(std::numeric_limits<T>::max()));
}
float SRGBToLinear(float srgb); float SRGBToLinear(float srgb);
template <typename T1, template <typename T1,

View File

@ -135,6 +135,9 @@ namespace dawn_native { namespace d3d12 {
mSupportedFeatures.EnableFeature(Feature::TextureCompressionBC); mSupportedFeatures.EnableFeature(Feature::TextureCompressionBC);
mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery); mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery);
mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats); mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats);
mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8);
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
return {}; return {};
} }

View File

@ -178,7 +178,10 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::Depth24Plus: case wgpu::TextureFormat::Depth24Plus:
return DXGI_FORMAT_R32_TYPELESS; return DXGI_FORMAT_R32_TYPELESS;
case wgpu::TextureFormat::Depth24UnormStencil8:
return DXGI_FORMAT_R24G8_TYPELESS;
case wgpu::TextureFormat::Depth24PlusStencil8: case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Depth32FloatStencil8:
return DXGI_FORMAT_R32G8X24_TYPELESS; return DXGI_FORMAT_R32G8X24_TYPELESS;
case wgpu::TextureFormat::BC1RGBAUnorm: case wgpu::TextureFormat::BC1RGBAUnorm:
@ -252,10 +255,6 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::R8BG8Biplanar420Unorm: case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
// TODO(dawn:666): implement stencil8 // TODO(dawn:666): implement stencil8
case wgpu::TextureFormat::Stencil8: case wgpu::TextureFormat::Stencil8:
// TODO(dawn:690): implement depth24unorm-stencil8
case wgpu::TextureFormat::Depth24UnormStencil8:
// TODO(dawn:690): implement depth32float-stencil8
case wgpu::TextureFormat::Depth32FloatStencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -342,14 +341,16 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::RGBA32Float: case wgpu::TextureFormat::RGBA32Float:
return DXGI_FORMAT_R32G32B32A32_FLOAT; return DXGI_FORMAT_R32G32B32A32_FLOAT;
case wgpu::TextureFormat::Depth32Float:
return DXGI_FORMAT_D32_FLOAT;
case wgpu::TextureFormat::Depth24Plus:
return DXGI_FORMAT_D32_FLOAT;
case wgpu::TextureFormat::Depth24PlusStencil8:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
case wgpu::TextureFormat::Depth16Unorm: case wgpu::TextureFormat::Depth16Unorm:
return DXGI_FORMAT_D16_UNORM; return DXGI_FORMAT_D16_UNORM;
case wgpu::TextureFormat::Depth32Float:
case wgpu::TextureFormat::Depth24Plus:
return DXGI_FORMAT_D32_FLOAT;
case wgpu::TextureFormat::Depth24UnormStencil8:
return DXGI_FORMAT_D24_UNORM_S8_UINT;
case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Depth32FloatStencil8:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
case wgpu::TextureFormat::BC1RGBAUnorm: case wgpu::TextureFormat::BC1RGBAUnorm:
return DXGI_FORMAT_BC1_UNORM; return DXGI_FORMAT_BC1_UNORM;
@ -425,10 +426,6 @@ namespace dawn_native { namespace d3d12 {
// TODO(dawn:666): implement stencil8 // TODO(dawn:666): implement stencil8
case wgpu::TextureFormat::Stencil8: case wgpu::TextureFormat::Stencil8:
// TODO(dawn:690): implement depth24unorm-stencil8
case wgpu::TextureFormat::Depth24UnormStencil8:
// TODO(dawn:690): implement depth32float-stencil8
case wgpu::TextureFormat::Depth32FloatStencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -699,7 +696,9 @@ namespace dawn_native { namespace d3d12 {
ASSERT(GetFormat().aspects & aspect); ASSERT(GetFormat().aspects & aspect);
switch (GetFormat().format) { switch (GetFormat().format) {
case wgpu::TextureFormat::Depth24UnormStencil8:
case wgpu::TextureFormat::Depth24PlusStencil8: case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Depth32FloatStencil8:
switch (aspect) { switch (aspect) {
case Aspect::Depth: case Aspect::Depth:
return DXGI_FORMAT_R32_FLOAT; return DXGI_FORMAT_R32_FLOAT;
@ -1186,7 +1185,39 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::Depth16Unorm: case wgpu::TextureFormat::Depth16Unorm:
mSrvDesc.Format = DXGI_FORMAT_R16_UNORM; mSrvDesc.Format = DXGI_FORMAT_R16_UNORM;
break; break;
case wgpu::TextureFormat::Depth24UnormStencil8:
switch (descriptor->aspect) {
case wgpu::TextureAspect::DepthOnly:
planeSlice = 0;
mSrvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
break;
case wgpu::TextureAspect::StencilOnly:
planeSlice = 1;
mSrvDesc.Format = DXGI_FORMAT_X24_TYPELESS_G8_UINT;
// Stencil is accessed using the .g component in the shader.
// Map it to the zeroth component to match other APIs.
mSrvDesc.Shader4ComponentMapping =
D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
break;
case wgpu::TextureAspect::All:
// A single aspect is not selected. The texture view must not be
// sampled.
mSrvDesc.Format = DXGI_FORMAT_UNKNOWN;
break;
// Depth formats cannot use plane aspects.
case wgpu::TextureAspect::Plane0Only:
case wgpu::TextureAspect::Plane1Only:
UNREACHABLE();
break;
}
break;
case wgpu::TextureFormat::Depth24PlusStencil8: case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Depth32FloatStencil8:
switch (descriptor->aspect) { switch (descriptor->aspect) {
case wgpu::TextureAspect::DepthOnly: case wgpu::TextureAspect::DepthOnly:
planeSlice = 0; planeSlice = 0;

View File

@ -324,6 +324,17 @@ namespace dawn_native { namespace metal {
mSupportedFeatures.EnableFeature(Feature::DepthClamping); mSupportedFeatures.EnableFeature(Feature::DepthClamping);
} }
if (@available(macOS 10.11, iOS 9.0, *)) {
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
}
#if defined(DAWN_PLATFORM_MACOS)
// MTLPixelFormatDepth24Unorm_Stencil8 is only available on macOS 10.11+
if ([*mDevice isDepth24Stencil8PixelFormatSupported]) {
mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8);
}
#endif
return {}; return {};
} }

View File

@ -222,6 +222,7 @@ namespace dawn_native { namespace metal {
case wgpu::TextureFormat::Depth24Plus: case wgpu::TextureFormat::Depth24Plus:
return MTLPixelFormatDepth32Float; return MTLPixelFormatDepth32Float;
case wgpu::TextureFormat::Depth24PlusStencil8: case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Depth32FloatStencil8:
return MTLPixelFormatDepth32Float_Stencil8; return MTLPixelFormatDepth32Float_Stencil8;
case wgpu::TextureFormat::Depth16Unorm: case wgpu::TextureFormat::Depth16Unorm:
if (@available(macOS 10.12, iOS 13.0, *)) { if (@available(macOS 10.12, iOS 13.0, *)) {
@ -232,6 +233,9 @@ namespace dawn_native { namespace metal {
} }
#if defined(DAWN_PLATFORM_MACOS) #if defined(DAWN_PLATFORM_MACOS)
case wgpu::TextureFormat::Depth24UnormStencil8:
return MTLPixelFormatDepth24Unorm_Stencil8;
case wgpu::TextureFormat::BC1RGBAUnorm: case wgpu::TextureFormat::BC1RGBAUnorm:
return MTLPixelFormatBC1_RGBA; return MTLPixelFormatBC1_RGBA;
case wgpu::TextureFormat::BC1RGBAUnormSrgb: case wgpu::TextureFormat::BC1RGBAUnormSrgb:
@ -261,6 +265,8 @@ namespace dawn_native { namespace metal {
case wgpu::TextureFormat::BC7RGBAUnormSrgb: case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return MTLPixelFormatBC7_RGBAUnorm_sRGB; return MTLPixelFormatBC7_RGBAUnorm_sRGB;
#else #else
case wgpu::TextureFormat::Depth24UnormStencil8:
case wgpu::TextureFormat::BC1RGBAUnorm: case wgpu::TextureFormat::BC1RGBAUnorm:
case wgpu::TextureFormat::BC1RGBAUnormSrgb: case wgpu::TextureFormat::BC1RGBAUnormSrgb:
case wgpu::TextureFormat::BC2RGBAUnorm: case wgpu::TextureFormat::BC2RGBAUnorm:
@ -321,10 +327,6 @@ namespace dawn_native { namespace metal {
// TODO(dawn:666): implement stencil8 // TODO(dawn:666): implement stencil8
case wgpu::TextureFormat::Stencil8: case wgpu::TextureFormat::Stencil8:
// TODO(dawn:690): implement depth24unorm-stencil8
case wgpu::TextureFormat::Depth24UnormStencil8:
// TODO(dawn:690): implement depth32float-stencil8
case wgpu::TextureFormat::Depth32FloatStencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
UNREACHABLE(); UNREACHABLE();
} }
@ -746,8 +748,17 @@ namespace dawn_native { namespace metal {
MTLPixelFormat format = MetalPixelFormat(descriptor->format); MTLPixelFormat format = MetalPixelFormat(descriptor->format);
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) { if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
if (@available(macOS 10.12, iOS 10.0, *)) { if (@available(macOS 10.12, iOS 10.0, *)) {
ASSERT(format == MTLPixelFormatDepth32Float_Stencil8); if (format == MTLPixelFormatDepth32Float_Stencil8) {
format = MTLPixelFormatX32_Stencil8; format = MTLPixelFormatX32_Stencil8;
}
#if defined(DAWN_PLATFORM_MACOS)
else if (format == MTLPixelFormatDepth24Unorm_Stencil8) {
format = MTLPixelFormatX24_Stencil8;
}
#endif
else {
UNREACHABLE();
}
} else { } else {
// TODO(enga): Add a workaround to back combined depth/stencil textures // TODO(enga): Add a workaround to back combined depth/stencil textures
// with Sampled usage using two separate textures. // with Sampled usage using two separate textures.

View File

@ -151,6 +151,14 @@ namespace dawn_native { namespace vulkan {
mSupportedFeatures.EnableFeature(Feature::TimestampQuery); mSupportedFeatures.EnableFeature(Feature::TimestampQuery);
} }
if (IsDepthStencilFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT)) {
mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8);
}
if (IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT)) {
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
}
#if defined(DAWN_USE_SYNC_FDS) #if defined(DAWN_USE_SYNC_FDS)
// TODO(chromium:1258986): Precisely enable the feature by querying the device's format // TODO(chromium:1258986): Precisely enable the feature by querying the device's format
// features. // features.

View File

@ -311,6 +311,10 @@ namespace dawn_native { namespace vulkan {
} else { } else {
return VK_FORMAT_D24_UNORM_S8_UINT; return VK_FORMAT_D24_UNORM_S8_UINT;
} }
case wgpu::TextureFormat::Depth24UnormStencil8:
return VK_FORMAT_D24_UNORM_S8_UINT;
case wgpu::TextureFormat::Depth32FloatStencil8:
return VK_FORMAT_D32_SFLOAT_S8_UINT;
case wgpu::TextureFormat::BC1RGBAUnorm: case wgpu::TextureFormat::BC1RGBAUnorm:
return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
@ -424,10 +428,6 @@ namespace dawn_native { namespace vulkan {
// TODO(dawn:666): implement stencil8 // TODO(dawn:666): implement stencil8
case wgpu::TextureFormat::Stencil8: case wgpu::TextureFormat::Stencil8:
// TODO(dawn:690): implement depth24unorm-stencil8
case wgpu::TextureFormat::Depth24UnormStencil8:
// TODO(dawn:690): implement depth32float-stencil8
case wgpu::TextureFormat::Depth32FloatStencil8:
case wgpu::TextureFormat::Undefined: case wgpu::TextureFormat::Undefined:
break; break;
} }

View File

@ -22,10 +22,23 @@
#include "utils/TextureUtils.h" #include "utils/TextureUtils.h"
#include "utils/WGPUHelpers.h" #include "utils/WGPUHelpers.h"
class DepthStencilCopyTests : public DawnTest { namespace {
using TextureFormat = wgpu::TextureFormat;
DAWN_TEST_PARAM_STRUCT(DepthStencilCopyTestParams, TextureFormat);
constexpr std::array<wgpu::TextureFormat, 3> kValidDepthCopyTextureFormats = {
wgpu::TextureFormat::Depth16Unorm,
wgpu::TextureFormat::Depth32Float,
wgpu::TextureFormat::Depth32FloatStencil8,
};
} // namespace
class DepthStencilCopyTests : public DawnTestWithParams<DepthStencilCopyTestParams> {
protected: protected:
void SetUp() override { void SetUp() override {
DawnTest::SetUp(); DawnTestWithParams<DepthStencilCopyTestParams>::SetUp();
DAWN_TEST_UNSUPPORTED_IF(!mIsFormatSupported);
// Draw a square in the bottom left quarter of the screen. // Draw a square in the bottom left quarter of the screen.
mVertexModule = utils::CreateShaderModule(device, R"( mVertexModule = utils::CreateShaderModule(device, R"(
@ -42,13 +55,56 @@ class DepthStencilCopyTests : public DawnTest {
})"); })");
} }
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
switch (GetParam().mTextureFormat) {
case wgpu::TextureFormat::Depth24UnormStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth24UnormStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth24UnormStencil8};
}
return {};
case wgpu::TextureFormat::Depth32FloatStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth32FloatStencil8};
}
return {};
default:
mIsFormatSupported = true;
return {};
}
}
bool IsValidDepthCopyTextureFormat() {
switch (GetParam().mTextureFormat) {
case wgpu::TextureFormat::Depth16Unorm:
case wgpu::TextureFormat::Depth32Float:
case wgpu::TextureFormat::Depth32FloatStencil8:
return true;
default:
return false;
}
}
wgpu::Texture CreateTexture(uint32_t width,
uint32_t height,
wgpu::TextureUsage usage,
uint32_t mipLevelCount = 1) {
wgpu::TextureDescriptor texDescriptor = {};
texDescriptor.size = {width, height, 1};
texDescriptor.format = GetParam().mTextureFormat;
texDescriptor.usage = usage;
texDescriptor.mipLevelCount = mipLevelCount;
return device.CreateTexture(&texDescriptor);
}
wgpu::Texture CreateDepthStencilTexture(uint32_t width, wgpu::Texture CreateDepthStencilTexture(uint32_t width,
uint32_t height, uint32_t height,
wgpu::TextureUsage usage, wgpu::TextureUsage usage,
uint32_t mipLevelCount = 1) { uint32_t mipLevelCount = 1) {
wgpu::TextureDescriptor texDescriptor = {}; wgpu::TextureDescriptor texDescriptor = {};
texDescriptor.size = {width, height, 1}; texDescriptor.size = {width, height, 1};
texDescriptor.format = wgpu::TextureFormat::Depth24PlusStencil8; texDescriptor.format = GetParam().mTextureFormat;
texDescriptor.usage = usage; texDescriptor.usage = usage;
texDescriptor.mipLevelCount = mipLevelCount; texDescriptor.mipLevelCount = mipLevelCount;
return device.CreateTexture(&texDescriptor); return device.CreateTexture(&texDescriptor);
@ -60,7 +116,7 @@ class DepthStencilCopyTests : public DawnTest {
uint32_t mipLevelCount = 1) { uint32_t mipLevelCount = 1) {
wgpu::TextureDescriptor texDescriptor = {}; wgpu::TextureDescriptor texDescriptor = {};
texDescriptor.size = {width, height, 1}; texDescriptor.size = {width, height, 1};
texDescriptor.format = wgpu::TextureFormat::Depth32Float; texDescriptor.format = GetParam().mTextureFormat;
texDescriptor.usage = usage; texDescriptor.usage = usage;
texDescriptor.mipLevelCount = mipLevelCount; texDescriptor.mipLevelCount = mipLevelCount;
return device.CreateTexture(&texDescriptor); return device.CreateTexture(&texDescriptor);
@ -97,7 +153,7 @@ class DepthStencilCopyTests : public DawnTest {
renderPassDesc.cDepthStencilAttachmentInfo.clearDepth = clearDepth; renderPassDesc.cDepthStencilAttachmentInfo.clearDepth = clearDepth;
utils::ComboRenderPipelineDescriptor renderPipelineDesc; utils::ComboRenderPipelineDescriptor renderPipelineDesc;
PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc, wgpu::TextureFormat::Depth32Float, PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc, GetParam().mTextureFormat,
regionDepth); regionDepth);
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc); wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);
@ -129,8 +185,8 @@ class DepthStencilCopyTests : public DawnTest {
renderPassDesc.cDepthStencilAttachmentInfo.clearStencil = clearStencil; renderPassDesc.cDepthStencilAttachmentInfo.clearStencil = clearStencil;
utils::ComboRenderPipelineDescriptor renderPipelineDesc; utils::ComboRenderPipelineDescriptor renderPipelineDesc;
PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc, PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc, GetParam().mTextureFormat,
wgpu::TextureFormat::Depth24PlusStencil8, regionDepth); regionDepth);
renderPipelineDesc.cDepthStencil.stencilFront.passOp = wgpu::StencilOperation::Replace; renderPipelineDesc.cDepthStencil.stencilFront.passOp = wgpu::StencilOperation::Replace;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc); wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);
@ -183,97 +239,11 @@ class DepthStencilCopyTests : public DawnTest {
} }
wgpu::ShaderModule mVertexModule; wgpu::ShaderModule mVertexModule;
private:
bool mIsFormatSupported = false;
}; };
// Test copying the depth-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromDepthAspect) {
constexpr uint32_t kWidth = 4;
constexpr uint32_t kHeight = 4;
wgpu::Texture depthTexture = CreateDepthTexture(
kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
InitializeDepthTextureRegion(depthTexture, 0.f, 0.3f);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<float> expectedData = {
0.0, 0.0, 0.0, 0.0, //
0.0, 0.0, 0.0, 0.0, //
0.3, 0.3, 0.0, 0.0, //
0.3, 0.3, 0.0, 0.0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::DepthOnly);
}
// Test copying the stencil-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromStencilAspect) {
// TODO(crbug.com/dawn/667): Work around the fact that some platforms are unable to read
// stencil.
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read"));
constexpr uint32_t kWidth = 4;
constexpr uint32_t kHeight = 4;
wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<uint8_t> expectedData = {
0u, 0u, 0u, 0u, //
0u, 0u, 0u, 0u, //
1u, 1u, 0u, 0u, //
1u, 1u, 0u, 0u, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::StencilOnly);
}
// Test copying the non-zero mip, stencil-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromNonZeroMipStencilAspect) {
// TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work
// on some Intel drivers.
DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel());
// TODO(crbug.com/dawn/667): Work around some platforms' inability to read back stencil.
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read"));
wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);
InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u, 1u);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<uint8_t> expectedData = {
0u, 0u, 0u, 0u, //
0u, 0u, 0u, 0u, //
1u, 1u, 0u, 0u, //
1u, 1u, 0u, 0u, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, {0, 0}, {4, 4}, 1,
wgpu::TextureAspect::StencilOnly);
}
// Test copying the non-zero mip, depth-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromNonZeroMipDepthAspect) {
wgpu::Texture depthTexture = CreateDepthTexture(
9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);
InitializeDepthTextureRegion(depthTexture, 0.f, 0.4f, 1);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<float> expectedData = {
0.0, 0.0, 0.0, 0.0, //
0.0, 0.0, 0.0, 0.0, //
0.4, 0.4, 0.0, 0.0, //
0.4, 0.4, 0.0, 0.0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, {0, 0}, {4, 4}, 1,
wgpu::TextureAspect::DepthOnly);
}
// Test copying both aspects in a T2T copy, then copying only stencil. // Test copying both aspects in a T2T copy, then copying only stencil.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencil) { TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencil) {
// TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work // TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work
@ -354,6 +324,8 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonRenderableNonZeroMipStenc
// Test copying both aspects in a T2T copy, then copying only depth. // Test copying both aspects in a T2T copy, then copying only depth.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepth) { TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepth) {
DAWN_TEST_UNSUPPORTED_IF(!IsValidDepthCopyTextureFormat());
constexpr uint32_t kWidth = 4; constexpr uint32_t kWidth = 4;
constexpr uint32_t kHeight = 4; constexpr uint32_t kHeight = 4;
@ -361,8 +333,7 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepth) {
0.1f, 0.3f, 1u, 3u, kWidth, kHeight, wgpu::TextureUsage::RenderAttachment); 0.1f, 0.3f, 1u, 3u, kWidth, kHeight, wgpu::TextureUsage::RenderAttachment);
// Check the depth // Check the depth
ExpectAttachmentDepthTestData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, ExpectAttachmentDepthTestData(texture, GetParam().mTextureFormat, kWidth, kHeight, 0, 0,
kHeight, 0, 0,
{ {
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
@ -373,11 +344,13 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepth) {
// Test copying both aspects in a T2T copy, then copying only depth at a nonzero mip. // Test copying both aspects in a T2T copy, then copying only depth at a nonzero mip.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonZeroMipDepth) { TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonZeroMipDepth) {
DAWN_TEST_UNSUPPORTED_IF(!IsValidDepthCopyTextureFormat());
wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T( wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
0.1f, 0.3f, 1u, 3u, 8, 8, wgpu::TextureUsage::RenderAttachment, 1); 0.1f, 0.3f, 1u, 3u, 8, 8, wgpu::TextureUsage::RenderAttachment, 1);
// Check the depth // Check the depth
ExpectAttachmentDepthTestData(texture, wgpu::TextureFormat::Depth24PlusStencil8, 4, 4, 0, 1, ExpectAttachmentDepthTestData(texture, GetParam().mTextureFormat, 4, 4, 0, 1,
{ {
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
@ -388,6 +361,8 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonZeroMipDepth) {
// Test copying both aspects in a T2T copy, then copying stencil, then copying depth // Test copying both aspects in a T2T copy, then copying stencil, then copying depth
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencilThenDepth) { TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencilThenDepth) {
DAWN_TEST_UNSUPPORTED_IF(!IsValidDepthCopyTextureFormat());
// TODO(crbug.com/dawn/667): Work around some platforms' inability to read back stencil. // TODO(crbug.com/dawn/667): Work around some platforms' inability to read back stencil.
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read")); DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read"));
@ -409,8 +384,7 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencilThenDepth) {
wgpu::TextureAspect::StencilOnly); wgpu::TextureAspect::StencilOnly);
// Check the depth // Check the depth
ExpectAttachmentDepthTestData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, ExpectAttachmentDepthTestData(texture, GetParam().mTextureFormat, kWidth, kHeight, 0, 0,
kHeight, 0, 0,
{ {
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
@ -421,6 +395,8 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencilThenDepth) {
// Test copying both aspects in a T2T copy, then copying depth, then copying stencil // Test copying both aspects in a T2T copy, then copying depth, then copying stencil
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepthThenStencil) { TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepthThenStencil) {
DAWN_TEST_UNSUPPORTED_IF(!IsValidDepthCopyTextureFormat());
// TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work // TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work
// on some Intel drivers. // on some Intel drivers.
// It seems like the depth readback copy mutates the stencil because the previous // It seems like the depth readback copy mutates the stencil because the previous
@ -440,8 +416,7 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepthThenStencil) {
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment); wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);
// Check the depth // Check the depth
ExpectAttachmentDepthTestData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, ExpectAttachmentDepthTestData(texture, GetParam().mTextureFormat, kWidth, kHeight, 0, 0,
kHeight, 0, 0,
{ {
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
0.1, 0.1, 0.1, 0.1, // 0.1, 0.1, 0.1, 0.1, //
@ -460,8 +435,137 @@ TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepthThenStencil) {
wgpu::TextureAspect::StencilOnly); wgpu::TextureAspect::StencilOnly);
} }
class DepthCopyTests : public DepthStencilCopyTests {};
// Test copying the depth-only aspect into a buffer.
TEST_P(DepthCopyTests, FromDepthAspect) {
// TODO(crbug.com/dawn/1237): Depth16Unorm test failed on OpenGL and OpenGLES which says
// Invalid format and type combination in glReadPixels
DAWN_TEST_UNSUPPORTED_IF(GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm &&
(IsOpenGL() || IsOpenGLES()));
constexpr uint32_t kWidth = 4;
constexpr uint32_t kHeight = 4;
wgpu::Texture texture = CreateTexture(
kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
constexpr float kInitDepth = 0.2f;
InitializeDepthTextureRegion(texture, 0.f, kInitDepth);
// This expectation is the test as it performs the CopyTextureToBuffer.
if (GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm) {
uint16_t expected = FloatToUnorm<uint16_t>(kInitDepth);
std::vector<uint16_t> expectedData = {
0, 0, 0, 0, //
0, 0, 0, 0, //
expected, expected, 0, 0, //
expected, expected, 0, 0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), texture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::DepthOnly);
} else {
std::vector<float> expectedData = {
0.0, 0.0, 0.0, 0.0, //
0.0, 0.0, 0.0, 0.0, //
kInitDepth, kInitDepth, 0.0, 0.0, //
kInitDepth, kInitDepth, 0.0, 0.0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), texture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::DepthOnly);
}
}
// Test copying the non-zero mip, depth-only aspect into a buffer.
TEST_P(DepthCopyTests, FromNonZeroMipDepthAspect) {
// TODO(crbug.com/dawn/1237): Depth16Unorm test failed on OpenGL and OpenGLES which says
// Invalid format and type combination in glReadPixels
DAWN_TEST_UNSUPPORTED_IF(GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm &&
(IsOpenGL() || IsOpenGLES()));
wgpu::Texture depthTexture = CreateDepthTexture(
9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);
constexpr float kInitDepth = 0.4f;
InitializeDepthTextureRegion(depthTexture, 0.f, kInitDepth, 1);
// This expectation is the test as it performs the CopyTextureToBuffer.
if (GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm) {
uint16_t expected = FloatToUnorm<uint16_t>(kInitDepth);
std::vector<uint16_t> expectedData = {
0, 0, 0, 0, //
0, 0, 0, 0, //
expected, expected, 0, 0, //
expected, expected, 0, 0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, {0, 0}, {4, 4}, 1,
wgpu::TextureAspect::DepthOnly);
} else {
std::vector<float> expectedData = {
0.0, 0.0, 0.0, 0.0, //
0.0, 0.0, 0.0, 0.0, //
kInitDepth, kInitDepth, 0.0, 0.0, //
kInitDepth, kInitDepth, 0.0, 0.0, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, {0, 0}, {4, 4}, 1,
wgpu::TextureAspect::DepthOnly);
}
}
class StencilCopyTests : public DepthStencilCopyTests {};
// Test copying the stencil-only aspect into a buffer.
TEST_P(StencilCopyTests, FromStencilAspect) {
// TODO(crbug.com/dawn/667): Work around the fact that some platforms are unable to read
// stencil.
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read"));
constexpr uint32_t kWidth = 4;
constexpr uint32_t kHeight = 4;
wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<uint8_t> expectedData = {
0u, 0u, 0u, 0u, //
0u, 0u, 0u, 0u, //
1u, 1u, 0u, 0u, //
1u, 1u, 0u, 0u, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::StencilOnly);
}
// Test copying the non-zero mip, stencil-only aspect into a buffer.
TEST_P(StencilCopyTests, FromNonZeroMipStencilAspect) {
// TODO(crbug.com/dawn/704): Readback after clear via stencil copy does not work
// on some Intel drivers.
DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel());
// TODO(crbug.com/dawn/667): Work around some platforms' inability to read back stencil.
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_depth_stencil_read"));
wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);
InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u, 1u);
// This expectation is the test as it performs the CopyTextureToBuffer.
std::vector<uint8_t> expectedData = {
0u, 0u, 0u, 0u, //
0u, 0u, 0u, 0u, //
1u, 1u, 0u, 0u, //
1u, 1u, 0u, 0u, //
};
EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, {0, 0}, {4, 4}, 1,
wgpu::TextureAspect::StencilOnly);
}
// Test copying to the stencil-aspect of a buffer // Test copying to the stencil-aspect of a buffer
TEST_P(DepthStencilCopyTests, ToStencilAspect) { TEST_P(StencilCopyTests, ToStencilAspect) {
// Copies to a single aspect are unsupported on OpenGL. // Copies to a single aspect are unsupported on OpenGL.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL()); DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES()); DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
@ -531,7 +635,7 @@ TEST_P(DepthStencilCopyTests, ToStencilAspect) {
[[stage(fragment)]] fn main() { [[stage(fragment)]] fn main() {
})"); })");
wgpu::DepthStencilState* depthStencil = wgpu::DepthStencilState* depthStencil =
renderPipelineDesc.EnableDepthStencil(wgpu::TextureFormat::Depth24PlusStencil8); renderPipelineDesc.EnableDepthStencil(GetParam().mTextureFormat);
depthStencil->stencilFront.passOp = wgpu::StencilOperation::DecrementClamp; depthStencil->stencilFront.passOp = wgpu::StencilOperation::DecrementClamp;
renderPipelineDesc.cFragment.targetCount = 0; renderPipelineDesc.cFragment.targetCount = 0;
@ -557,8 +661,8 @@ TEST_P(DepthStencilCopyTests, ToStencilAspect) {
EXPECT_TEXTURE_EQ(expectedStencilData.data(), depthStencilTexture, {0, 0}, {kWidth, kHeight}, 0, EXPECT_TEXTURE_EQ(expectedStencilData.data(), depthStencilTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::StencilOnly); wgpu::TextureAspect::StencilOnly);
ExpectAttachmentDepthTestData(depthStencilTexture, wgpu::TextureFormat::Depth24PlusStencil8, ExpectAttachmentDepthTestData(depthStencilTexture, GetParam().mTextureFormat, kWidth, kHeight,
kWidth, kHeight, 0, 0, 0, 0,
{ {
0.7, 0.7, 0.7, 0.7, // 0.7, 0.7, 0.7, 0.7, //
0.7, 0.7, 0.7, 0.7, // 0.7, 0.7, 0.7, 0.7, //
@ -567,9 +671,20 @@ TEST_P(DepthStencilCopyTests, ToStencilAspect) {
}); });
} }
DAWN_INSTANTIATE_TEST(DepthStencilCopyTests, DAWN_INSTANTIATE_TEST_P(DepthStencilCopyTests,
D3D12Backend(), {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
MetalBackend(), VulkanBackend()},
OpenGLBackend(), std::vector<wgpu::TextureFormat>(utils::kDepthAndStencilFormats.begin(),
OpenGLESBackend(), utils::kDepthAndStencilFormats.end()));
VulkanBackend());
DAWN_INSTANTIATE_TEST_P(DepthCopyTests,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
std::vector<wgpu::TextureFormat>(kValidDepthCopyTextureFormats.begin(),
kValidDepthCopyTextureFormats.end()));
DAWN_INSTANTIATE_TEST_P(StencilCopyTests,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
std::vector<wgpu::TextureFormat>(utils::kStencilFormats.begin(),
utils::kStencilFormats.end()));

View File

@ -62,6 +62,8 @@ namespace {
void SetUp() override { void SetUp() override {
DawnTestWithParams<DepthStencilLoadOpTestParams>::SetUp(); DawnTestWithParams<DepthStencilLoadOpTestParams>::SetUp();
DAWN_TEST_UNSUPPORTED_IF(!mIsFormatSupported);
// Readback of Depth/Stencil textures not fully supported on GL right now. // Readback of Depth/Stencil textures not fully supported on GL right now.
// Also depends on glTextureView which is not supported on ES. // Also depends on glTextureView which is not supported on ES.
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES()); DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
@ -91,6 +93,26 @@ namespace {
} }
} }
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
switch (GetParam().mFormat) {
case wgpu::TextureFormat::Depth24UnormStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth24UnormStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth24UnormStencil8};
}
return {};
case wgpu::TextureFormat::Depth32FloatStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth32FloatStencil8};
}
return {};
default:
mIsFormatSupported = true;
return {};
}
}
void CheckMipLevel(uint32_t mipLevel) { void CheckMipLevel(uint32_t mipLevel) {
uint32_t mipSize = std::max(kRTSize >> mipLevel, 1u); uint32_t mipSize = std::max(kRTSize >> mipLevel, 1u);
@ -151,6 +173,9 @@ namespace {
std::array<wgpu::TextureView, kMipLevelCount> textureViews; std::array<wgpu::TextureView, kMipLevelCount> textureViews;
// Vector instead of array because there is no default constructor. // Vector instead of array because there is no default constructor.
std::vector<utils::ComboRenderPassDescriptor> renderPassDescriptors; std::vector<utils::ComboRenderPassDescriptor> renderPassDescriptors;
private:
bool mIsFormatSupported = false;
}; };
} // anonymous namespace } // anonymous namespace
@ -240,7 +265,8 @@ namespace {
auto params2 = MakeParamGenerator<DepthStencilLoadOpTestParams>( auto params2 = MakeParamGenerator<DepthStencilLoadOpTestParams>(
{D3D12Backend(), D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(), {D3D12Backend(), D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(),
OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
{wgpu::TextureFormat::Depth24PlusStencil8}, {wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureFormat::Depth24UnormStencil8,
wgpu::TextureFormat::Depth32FloatStencil8},
{Check::CopyStencil, Check::StencilTest, Check::DepthTest, Check::SampleDepth}); {Check::CopyStencil, Check::StencilTest, Check::DepthTest, Check::SampleDepth});
std::vector<DepthStencilLoadOpTestParams> allParams; std::vector<DepthStencilLoadOpTestParams> allParams;

View File

@ -18,17 +18,8 @@
#include "utils/WGPUHelpers.h" #include "utils/WGPUHelpers.h"
namespace { namespace {
using TextureFormat = wgpu::TextureFormat;
constexpr wgpu::TextureFormat kDepthFormats[] = { DAWN_TEST_PARAM_STRUCT(DepthStencilSamplingTestParams, TextureFormat);
wgpu::TextureFormat::Depth32Float,
wgpu::TextureFormat::Depth24Plus,
wgpu::TextureFormat::Depth24PlusStencil8,
wgpu::TextureFormat::Depth16Unorm,
};
constexpr wgpu::TextureFormat kStencilFormats[] = {
wgpu::TextureFormat::Depth24PlusStencil8,
};
constexpr wgpu::CompareFunction kCompareFunctions[] = { constexpr wgpu::CompareFunction kCompareFunctions[] = {
wgpu::CompareFunction::Never, wgpu::CompareFunction::Less, wgpu::CompareFunction::Never, wgpu::CompareFunction::Less,
@ -48,7 +39,7 @@ namespace {
} // anonymous namespace } // anonymous namespace
class DepthStencilSamplingTest : public DawnTest { class DepthStencilSamplingTest : public DawnTestWithParams<DepthStencilSamplingTestParams> {
protected: protected:
enum class TestAspect { enum class TestAspect {
Depth, Depth,
@ -56,7 +47,9 @@ class DepthStencilSamplingTest : public DawnTest {
}; };
void SetUp() override { void SetUp() override {
DawnTest::SetUp(); DawnTestWithParams<DepthStencilSamplingTestParams>::SetUp();
DAWN_TEST_UNSUPPORTED_IF(!mIsFormatSupported);
wgpu::BufferDescriptor uniformBufferDesc; wgpu::BufferDescriptor uniformBufferDesc;
uniformBufferDesc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst; uniformBufferDesc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst;
@ -64,6 +57,26 @@ class DepthStencilSamplingTest : public DawnTest {
mUniformBuffer = device.CreateBuffer(&uniformBufferDesc); mUniformBuffer = device.CreateBuffer(&uniformBufferDesc);
} }
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
switch (GetParam().mTextureFormat) {
case wgpu::TextureFormat::Depth24UnormStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth24UnormStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth24UnormStencil8};
}
return {};
case wgpu::TextureFormat::Depth32FloatStencil8:
if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) {
mIsFormatSupported = true;
return {wgpu::FeatureName::Depth32FloatStencil8};
}
return {};
default:
mIsFormatSupported = true;
return {};
}
}
void GenerateSamplingShader(const std::vector<TestAspect>& aspects, void GenerateSamplingShader(const std::vector<TestAspect>& aspects,
const std::vector<uint32_t> components, const std::vector<uint32_t> components,
std::ostringstream& shaderSource, std::ostringstream& shaderSource,
@ -581,58 +594,39 @@ class DepthStencilSamplingTest : public DawnTest {
private: private:
wgpu::Buffer mUniformBuffer; wgpu::Buffer mUniformBuffer;
bool mIsFormatSupported = false;
}; };
// Test that sampling a depth texture with a render/compute pipeline works
TEST_P(DepthStencilSamplingTest, SampleDepth) {
for (wgpu::TextureFormat format : kDepthFormats) {
float tolerance = 0.0f;
if (format == wgpu::TextureFormat::Depth16Unorm) {
tolerance = 0.001f;
}
// Test 0, between [0, 1], and 1.
DoSamplingTest(TestAspect::Depth, CreateSamplingRenderPipeline({TestAspect::Depth}, 0),
format, kNormalizedTextureValues, tolerance);
DoSamplingTest(TestAspect::Depth, CreateSamplingComputePipeline({TestAspect::Depth}, 0),
format, kNormalizedTextureValues, tolerance);
}
}
// Test that sampling a stencil texture with a render/compute pipeline works
TEST_P(DepthStencilSamplingTest, SampleStencil) {
// TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
for (wgpu::TextureFormat format : kStencilFormats) {
DoSamplingTest(TestAspect::Stencil, CreateSamplingRenderPipeline({TestAspect::Stencil}, 0),
format, kStencilValues);
DoSamplingTest(TestAspect::Stencil, CreateSamplingComputePipeline({TestAspect::Stencil}, 0),
format, kStencilValues);
}
}
// Test that sampling a depth/stencil texture at components 1, 2, and 3 yield 0, 0, and 1 // Test that sampling a depth/stencil texture at components 1, 2, and 3 yield 0, 0, and 1
// respectively // respectively
TEST_P(DepthStencilSamplingTest, SampleExtraComponents) { TEST_P(DepthStencilSamplingTest, SampleExtraComponents) {
// TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES. // TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES()); DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
DoSamplingExtraStencilComponentsRenderTest( wgpu::TextureFormat format = GetParam().mTextureFormat;
TestAspect::Stencil, wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(42), uint8_t(37)});
DoSamplingExtraStencilComponentsComputeTest( // TODO(crbug.com/dawn/1239): depth24unorm-stencil8 fails on D3D12 Nvidia old driver version.
TestAspect::Stencil, wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(42), uint8_t(37)}); DAWN_SUPPRESS_TEST_IF(format == wgpu::TextureFormat::Depth24UnormStencil8 && IsD3D12() &&
IsNvidia());
DoSamplingExtraStencilComponentsRenderTest(TestAspect::Stencil, format,
{uint8_t(42), uint8_t(37)});
DoSamplingExtraStencilComponentsComputeTest(TestAspect::Stencil, format,
{uint8_t(42), uint8_t(37)});
} }
// Test sampling both depth and stencil with a render/compute pipeline works. // Test sampling both depth and stencil with a render/compute pipeline works.
TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) { TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
// TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES. // TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES()); DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
wgpu::TextureFormat format = GetParam().mTextureFormat;
wgpu::SamplerDescriptor samplerDesc; wgpu::SamplerDescriptor samplerDesc;
wgpu::Sampler sampler = device.CreateSampler(&samplerDesc); wgpu::Sampler sampler = device.CreateSampler(&samplerDesc);
wgpu::Texture inputTexture = CreateInputTexture(wgpu::TextureFormat::Depth24PlusStencil8); wgpu::Texture inputTexture = CreateInputTexture(format);
wgpu::TextureViewDescriptor depthViewDesc = {}; wgpu::TextureViewDescriptor depthViewDesc = {};
depthViewDesc.aspect = wgpu::TextureAspect::DepthOnly; depthViewDesc.aspect = wgpu::TextureAspect::DepthOnly;
@ -640,6 +634,8 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
wgpu::TextureViewDescriptor stencilViewDesc = {}; wgpu::TextureViewDescriptor stencilViewDesc = {};
stencilViewDesc.aspect = wgpu::TextureAspect::StencilOnly; stencilViewDesc.aspect = wgpu::TextureAspect::StencilOnly;
float tolerance = format == wgpu::TextureFormat::Depth24UnormStencil8 ? 0.001f : 0.0f;
// With render pipeline // With render pipeline
{ {
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
@ -682,15 +678,16 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
wgpu::CommandBuffer commands = commandEncoder.Finish(); wgpu::CommandBuffer commands = commandEncoder.Finish();
queue.Submit(1, &commands); queue.Submit(1, &commands);
uint32_t expectedValueU32 = 0; float expectedDepth = 0.0f;
memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearDepth, memcpy(&expectedDepth, &passDescriptor.cDepthStencilAttachmentInfo.clearDepth,
sizeof(float)); sizeof(float));
EXPECT_BUFFER_U32_EQ(expectedValueU32, depthOutput, 0); EXPECT_BUFFER(depthOutput, 0, sizeof(float),
new ::detail::ExpectEq<float>(expectedDepth, tolerance));
expectedValueU32 = 0; uint8_t expectedStencil = 0;
memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearStencil, memcpy(&expectedStencil, &passDescriptor.cDepthStencilAttachmentInfo.clearStencil,
sizeof(uint8_t)); sizeof(uint8_t));
EXPECT_BUFFER_U32_EQ(expectedValueU32, stencilOutput, 0); EXPECT_BUFFER_U32_EQ(expectedStencil, stencilOutput, 0);
} }
// With compute pipeline // With compute pipeline
@ -729,30 +726,49 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
wgpu::CommandBuffer commands = commandEncoder.Finish(); wgpu::CommandBuffer commands = commandEncoder.Finish();
queue.Submit(1, &commands); queue.Submit(1, &commands);
uint32_t expectedValueU32 = 0; float expectedDepth = 0.0f;
memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearDepth, memcpy(&expectedDepth, &passDescriptor.cDepthStencilAttachmentInfo.clearDepth,
sizeof(float)); sizeof(float));
EXPECT_BUFFER_U32_EQ(expectedValueU32, depthOutput, 0); EXPECT_BUFFER(depthOutput, 0, sizeof(float),
new ::detail::ExpectEq<float>(expectedDepth, tolerance));
expectedValueU32 = 0; uint8_t expectedStencil = 0;
memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearStencil, memcpy(&expectedStencil, &passDescriptor.cDepthStencilAttachmentInfo.clearStencil,
sizeof(uint8_t)); sizeof(uint8_t));
EXPECT_BUFFER_U32_EQ(expectedValueU32, stencilOutput, 0); EXPECT_BUFFER_U32_EQ(expectedStencil, stencilOutput, 0);
} }
} }
class DepthSamplingTest : public DepthStencilSamplingTest {};
// Test that sampling a depth texture with a render/compute pipeline works
TEST_P(DepthSamplingTest, SampleDepthOnly) {
wgpu::TextureFormat format = GetParam().mTextureFormat;
float tolerance = format == wgpu::TextureFormat::Depth16Unorm ||
format == wgpu::TextureFormat::Depth24UnormStencil8
? 0.001f
: 0.0f;
// Test 0, between [0, 1], and 1.
DoSamplingTest(TestAspect::Depth, CreateSamplingRenderPipeline({TestAspect::Depth}, 0), format,
kNormalizedTextureValues, tolerance);
DoSamplingTest(TestAspect::Depth, CreateSamplingComputePipeline({TestAspect::Depth}, 0), format,
kNormalizedTextureValues, tolerance);
}
// Test that sampling in a render pipeline with all of the compare functions works. // Test that sampling in a render pipeline with all of the compare functions works.
TEST_P(DepthStencilSamplingTest, CompareFunctionsRender) { TEST_P(DepthSamplingTest, CompareFunctionsRender) {
// Initialization via renderPass loadOp doesn't work on Mac Intel. // Initialization via renderPass loadOp doesn't work on Mac Intel.
DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel()); DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel());
wgpu::RenderPipeline pipeline = CreateComparisonRenderPipeline(); wgpu::TextureFormat format = GetParam().mTextureFormat;
// Test does not account for precision issues when comparison testing Depth16Unorm and
// Depth24UnormStencil8.
DAWN_TEST_UNSUPPORTED_IF(format == wgpu::TextureFormat::Depth16Unorm ||
format == wgpu::TextureFormat::Depth24UnormStencil8);
for (wgpu::TextureFormat format : kDepthFormats) { wgpu::RenderPipeline pipeline = CreateComparisonRenderPipeline();
// Test does not account for precision issues when comparison testing Depth16Unorm.
if (format == wgpu::TextureFormat::Depth16Unorm) {
continue;
}
// Test a "normal" ref value between 0 and 1; as well as negative and > 1 refs. // Test a "normal" ref value between 0 and 1; as well as negative and > 1 refs.
for (float compareRef : kCompareRefs) { for (float compareRef : kCompareRefs) {
@ -762,11 +778,37 @@ TEST_P(DepthStencilSamplingTest, CompareFunctionsRender) {
} }
} }
} }
class StencilSamplingTest : public DepthStencilSamplingTest {};
// Test that sampling a stencil texture with a render/compute pipeline works
TEST_P(StencilSamplingTest, SampleStencilOnly) {
// TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
wgpu::TextureFormat format = GetParam().mTextureFormat;
DoSamplingTest(TestAspect::Stencil, CreateSamplingRenderPipeline({TestAspect::Stencil}, 0),
format, kStencilValues);
DoSamplingTest(TestAspect::Stencil, CreateSamplingComputePipeline({TestAspect::Stencil}, 0),
format, kStencilValues);
} }
DAWN_INSTANTIATE_TEST(DepthStencilSamplingTest, DAWN_INSTANTIATE_TEST_P(DepthStencilSamplingTest,
D3D12Backend(), {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
MetalBackend(), VulkanBackend()},
OpenGLBackend(), std::vector<wgpu::TextureFormat>(utils::kDepthAndStencilFormats.begin(),
OpenGLESBackend(), utils::kDepthAndStencilFormats.end()));
VulkanBackend());
DAWN_INSTANTIATE_TEST_P(DepthSamplingTest,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
std::vector<wgpu::TextureFormat>(utils::kDepthFormats.begin(),
utils::kDepthFormats.end()));
DAWN_INSTANTIATE_TEST_P(StencilSamplingTest,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
std::vector<wgpu::TextureFormat>(utils::kStencilFormats.begin(),
utils::kStencilFormats.end()));

View File

@ -249,6 +249,19 @@ TEST(Math, IsFloat16NaN) {
ASSERT_TRUE(IsFloat16NaN(0xFFFF)); ASSERT_TRUE(IsFloat16NaN(0xFFFF));
} }
// Tests for FloatToUnorm
TEST(Math, FloatToUnorm) {
std::vector<float> kTestFloatValues = {0.0f, 0.4f, 0.5f, 1.0f};
std::vector<unsigned char> kExpectedCharValues = {0, 102, 127, 255};
std::vector<uint8_t> kExpectedUint8Values = {0, 102, 127, 255};
std::vector<uint16_t> kExpectedUint16Values = {0, 26214, 32767, 65535};
for (size_t i = 0; i < kTestFloatValues.size(); i++) {
ASSERT_EQ(FloatToUnorm<unsigned char>(kTestFloatValues[i]), kExpectedCharValues[i]);
ASSERT_EQ(FloatToUnorm<uint8_t>(kTestFloatValues[i]), kExpectedUint8Values[i]);
ASSERT_EQ(FloatToUnorm<uint16_t>(kTestFloatValues[i]), kExpectedUint16Values[i]);
}
}
// Tests for SRGBToLinear // Tests for SRGBToLinear
TEST(Math, SRGBToLinear) { TEST(Math, SRGBToLinear) {
ASSERT_EQ(SRGBToLinear(0.0f), 0.0f); ASSERT_EQ(SRGBToLinear(0.0f), 0.0f);