Deprecate sampling depth textures with float/unfilterable-float

Dawn currently allows sampling depth textures this way, but it is
not in the WebGPU spec, and the behavior is not guaranteed with the
Metal API.

This commit also updates the stencil sampling tests to expect
(s, s, s, s) or (s, 0, 0, 1).

Bug: dawn:1021
Change-Id: I9210a2a3ff1655747a202a51f46f38faa35c85d4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/59320
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Austin Eng 2021-07-27 22:08:32 +00:00 committed by Dawn LUCI CQ
parent 0eff5987f0
commit d6af6bd7f3
7 changed files with 223 additions and 158 deletions

View File

@ -117,7 +117,7 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateTextureBinding(const DeviceBase* device, MaybeError ValidateTextureBinding(DeviceBase* device,
const BindGroupEntry& entry, const BindGroupEntry& entry,
const BindingInfo& bindingInfo) { const BindingInfo& bindingInfo) {
if (entry.textureView == nullptr || entry.sampler != nullptr || if (entry.textureView == nullptr || entry.sampler != nullptr ||
@ -150,7 +150,15 @@ namespace dawn_native {
} }
if ((supportedTypes & requiredType) == 0) { if ((supportedTypes & requiredType) == 0) {
return DAWN_VALIDATION_ERROR("Texture component type usage mismatch"); if (IsSubset(SampleTypeBit::Depth, supportedTypes) != 0 &&
IsSubset(requiredType,
SampleTypeBit::Float | SampleTypeBit::UnfilterableFloat)) {
device->EmitDeprecationWarning(
"Using depth textures with 'float' or 'unfilterable-float' texture "
"bindings is deprecated. Use 'depth' instead.");
} else {
return DAWN_VALIDATION_ERROR("Texture component type usage mismatch");
}
} }
if (entry.textureView->GetDimension() != bindingInfo.texture.viewDimension) { if (entry.textureView->GetDimension() != bindingInfo.texture.viewDimension) {

View File

@ -207,7 +207,7 @@ namespace dawn_native {
firstAspect->block.width = 1; firstAspect->block.width = 1;
firstAspect->block.height = 1; firstAspect->block.height = 1;
firstAspect->baseType = wgpu::TextureComponentType::Float; firstAspect->baseType = wgpu::TextureComponentType::Float;
firstAspect->supportedSampleTypes = kAnyFloat | SampleTypeBit::Depth; firstAspect->supportedSampleTypes = SampleTypeBit::Depth;
firstAspect->format = format; firstAspect->format = format;
AddFormat(internalFormat); AddFormat(internalFormat);
}; };

View File

@ -63,8 +63,59 @@ class DepthStencilSamplingTest : public DawnTest {
mUniformBuffer = device.CreateBuffer(&uniformBufferDesc); mUniformBuffer = device.CreateBuffer(&uniformBufferDesc);
} }
void GenerateSamplingShader(const std::vector<TestAspect>& aspects,
const std::vector<uint32_t> components,
std::ostringstream& shaderSource,
std::ostringstream& shaderBody) {
shaderSource << "type StencilValues = array<u32, " << components.size() << ">;\n";
shaderSource << R"(
[[block]] struct DepthResult {
value : f32;
};
[[block]] struct StencilResult {
values : StencilValues;
};)";
shaderSource << "\n";
uint32_t index = 0;
for (TestAspect aspect : aspects) {
switch (aspect) {
case TestAspect::Depth:
shaderSource << "[[group(0), binding(" << 2 * index << ")]] var tex" << index
<< " : texture_depth_2d;\n";
shaderSource << "[[group(0), binding(" << 2 * index + 1
<< ")]] var<storage, read_write> result" << index
<< " : DepthResult;\n";
ASSERT(components.size() == 1 && components[0] == 0);
shaderBody << "\nresult" << index << ".value = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0);";
break;
case TestAspect::Stencil:
shaderSource << "[[group(0), binding(" << 2 * index << ")]] var tex" << index
<< " : texture_2d<u32>;\n";
shaderSource << "[[group(0), binding(" << 2 * index + 1
<< ")]] var<storage, read_write> result" << index
<< " : StencilResult;\n";
shaderBody << "var texel = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0);";
for (uint32_t i = 0; i < components.size(); ++i) {
shaderBody << "\nresult" << index << ".values[" << i << "] = texel["
<< components[i] << "];";
}
break;
}
index++;
}
}
wgpu::RenderPipeline CreateSamplingRenderPipeline(std::vector<TestAspect> aspects, wgpu::RenderPipeline CreateSamplingRenderPipeline(std::vector<TestAspect> aspects,
uint32_t componentIndex) { std::vector<uint32_t> components) {
wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"( wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
[[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> { [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0); return vec4<f32>(0.0, 0.0, 0.0, 1.0);
@ -76,92 +127,25 @@ class DepthStencilSamplingTest : public DawnTest {
std::ostringstream shaderOutputStruct; std::ostringstream shaderOutputStruct;
std::ostringstream shaderBody; std::ostringstream shaderBody;
uint32_t index = 0; GenerateSamplingShader(aspects, components, shaderSource, shaderBody);
for (TestAspect aspect : aspects) {
switch (aspect) {
case TestAspect::Depth:
shaderSource << "[[group(0), binding(" << index << ")]] var tex" << index
<< " : texture_2d<f32>;\n";
shaderOutputStruct << " [[location(" << index << ")]] result" << index shaderSource << "[[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {\n";
<< " : f32;\n"; shaderSource << shaderBody.str() << "return vec4<f32>();\n }";
shaderBody << "\n output.result" << index << " = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0)[" << componentIndex << "];\n";
pipelineDescriptor.cTargets[index].format = wgpu::TextureFormat::R32Float;
break;
case TestAspect::Stencil:
shaderSource << "[[group(0), binding(" << index << ")]] var tex" << index
<< " : texture_2d<u32>;\n";
shaderOutputStruct << " [[location(" << index << ")]] result" << index
<< " : u32;\n";
shaderBody << "\n output.result" << index << " = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0)[" << componentIndex << "];\n";
pipelineDescriptor.cTargets[index].format = wgpu::TextureFormat::R8Uint;
break;
}
index++;
}
shaderSource << "struct FragOutputs {\n" << shaderOutputStruct.str() << "};\n";
shaderSource << "[[stage(fragment)]] fn main() -> FragOutputs {\n";
shaderSource << " var output : FragOutputs;\n"
<< shaderBody.str() << " return output;\n}";
wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, shaderSource.str().c_str()); wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, shaderSource.str().c_str());
pipelineDescriptor.vertex.module = vsModule; pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsModule; pipelineDescriptor.cFragment.module = fsModule;
pipelineDescriptor.primitive.topology = wgpu::PrimitiveTopology::PointList; pipelineDescriptor.primitive.topology = wgpu::PrimitiveTopology::PointList;
pipelineDescriptor.cFragment.targetCount = static_cast<uint32_t>(aspects.size()); pipelineDescriptor.cTargets[0].writeMask = wgpu::ColorWriteMask::None;
return device.CreateRenderPipeline(&pipelineDescriptor); return device.CreateRenderPipeline(&pipelineDescriptor);
} }
wgpu::ComputePipeline CreateSamplingComputePipeline(std::vector<TestAspect> aspects, wgpu::ComputePipeline CreateSamplingComputePipeline(std::vector<TestAspect> aspects,
uint32_t componentIndex) { std::vector<uint32_t> components) {
std::ostringstream shaderSource; std::ostringstream shaderSource;
std::ostringstream shaderBody; std::ostringstream shaderBody;
shaderSource << R"( GenerateSamplingShader(aspects, components, shaderSource, shaderBody);
[[block]] struct DepthResult {
value : f32;
};
[[block]] struct StencilResult {
value : u32;
};)";
shaderSource << "\n";
uint32_t index = 0;
for (TestAspect aspect : aspects) {
switch (aspect) {
case TestAspect::Depth:
shaderSource << "[[group(0), binding(" << 2 * index << ")]] var tex" << index
<< " : texture_2d<f32>;\n";
shaderSource << "[[group(0), binding(" << 2 * index + 1
<< ")]] var<storage, read_write> result" << index
<< " : DepthResult;\n";
shaderBody << "\nresult" << index << ".value = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0)[" << componentIndex << "];";
break;
case TestAspect::Stencil:
shaderSource << "[[group(0), binding(" << 2 * index << ")]] var tex" << index
<< " : texture_2d<u32>;\n";
shaderSource << "[[group(0), binding(" << 2 * index + 1
<< ")]] var<storage, read_write> result" << index
<< " : StencilResult;\n";
shaderBody << "\nresult" << index << ".value = textureLoad(tex" << index
<< ", vec2<i32>(0, 0), 0)[" << componentIndex << "];";
break;
}
index++;
}
shaderSource << "[[stage(compute), workgroup_size(1)]] fn main() { " << shaderBody.str() shaderSource << "[[stage(compute), workgroup_size(1)]] fn main() { " << shaderBody.str()
<< "\n}"; << "\n}";
@ -175,6 +159,18 @@ class DepthStencilSamplingTest : public DawnTest {
return device.CreateComputePipeline(&pipelineDescriptor); return device.CreateComputePipeline(&pipelineDescriptor);
} }
wgpu::RenderPipeline CreateSamplingRenderPipeline(std::vector<TestAspect> aspects,
uint32_t componentIndex) {
return CreateSamplingRenderPipeline(std::move(aspects),
std::vector<uint32_t>{componentIndex});
}
wgpu::ComputePipeline CreateSamplingComputePipeline(std::vector<TestAspect> aspects,
uint32_t componentIndex) {
return CreateSamplingComputePipeline(std::move(aspects),
std::vector<uint32_t>{componentIndex});
}
wgpu::RenderPipeline CreateComparisonRenderPipeline() { wgpu::RenderPipeline CreateComparisonRenderPipeline() {
wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"( wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
[[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> { [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {
@ -244,10 +240,10 @@ class DepthStencilSamplingTest : public DawnTest {
return device.CreateTexture(&outputTextureDesc); return device.CreateTexture(&outputTextureDesc);
} }
wgpu::Buffer CreateOutputBuffer() { wgpu::Buffer CreateOutputBuffer(uint32_t componentCount = 1) {
wgpu::BufferDescriptor outputBufferDesc; wgpu::BufferDescriptor outputBufferDesc;
outputBufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc; outputBufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
outputBufferDesc.size = sizeof(float); // Large enough for both float and uint8_t outputBufferDesc.size = sizeof(uint32_t) * componentCount;
return device.CreateBuffer(&outputBufferDesc); return device.CreateBuffer(&outputBufferDesc);
} }
@ -271,30 +267,29 @@ class DepthStencilSamplingTest : public DawnTest {
pass.EndPass(); pass.EndPass();
} }
template <typename T> template <typename T, typename CheckBufferFn>
void DoSamplingTest(TestAspect aspect, void DoSamplingTestImpl(TestAspect aspect,
wgpu::RenderPipeline pipeline, wgpu::RenderPipeline pipeline,
wgpu::TextureFormat format, wgpu::TextureFormat format,
std::vector<T> textureValues, std::vector<T> textureValues,
std::vector<T> expectedValues) { uint32_t componentCount,
ASSERT(textureValues.size() == expectedValues.size()); CheckBufferFn CheckBuffer) {
wgpu::Texture outputTexture;
wgpu::Texture inputTexture = CreateInputTexture(format); wgpu::Texture inputTexture = CreateInputTexture(format);
wgpu::TextureViewDescriptor inputViewDesc = {}; wgpu::TextureViewDescriptor inputViewDesc = {};
switch (aspect) { switch (aspect) {
case TestAspect::Depth: case TestAspect::Depth:
inputViewDesc.aspect = wgpu::TextureAspect::DepthOnly; inputViewDesc.aspect = wgpu::TextureAspect::DepthOnly;
outputTexture = CreateOutputTexture(wgpu::TextureFormat::R32Float);
break; break;
case TestAspect::Stencil: case TestAspect::Stencil:
inputViewDesc.aspect = wgpu::TextureAspect::StencilOnly; inputViewDesc.aspect = wgpu::TextureAspect::StencilOnly;
outputTexture = CreateOutputTexture(wgpu::TextureFormat::R8Uint);
break; break;
} }
wgpu::BindGroup bindGroup = utils::MakeBindGroup( wgpu::Buffer outputBuffer = CreateOutputBuffer(componentCount);
device, pipeline.GetBindGroupLayout(0), {{0, inputTexture.CreateView(&inputViewDesc)}});
wgpu::BindGroup bindGroup =
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
{{0, inputTexture.CreateView(&inputViewDesc)}, {1, outputBuffer}});
for (size_t i = 0; i < textureValues.size(); ++i) { for (size_t i = 0; i < textureValues.size(); ++i) {
// Set the input depth texture to the provided texture value // Set the input depth texture to the provided texture value
@ -310,8 +305,10 @@ class DepthStencilSamplingTest : public DawnTest {
// Render into the output texture // Render into the output texture
{ {
utils::ComboRenderPassDescriptor passDescriptor({outputTexture.CreateView()}); utils::BasicRenderPass renderPass =
wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor); utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
wgpu::RenderPassEncoder pass =
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.SetPipeline(pipeline); pass.SetPipeline(pipeline);
pass.SetBindGroup(0, bindGroup); pass.SetBindGroup(0, bindGroup);
pass.Draw(1); pass.Draw(1);
@ -321,18 +318,19 @@ class DepthStencilSamplingTest : public DawnTest {
wgpu::CommandBuffer commands = commandEncoder.Finish(); wgpu::CommandBuffer commands = commandEncoder.Finish();
queue.Submit(1, &commands); queue.Submit(1, &commands);
EXPECT_TEXTURE_EQ(expectedValues[i], outputTexture, {0, 0}); uint32_t expectedValueU32 = 0;
memcpy(&expectedValueU32, &textureValues[i], std::min(sizeof(T), sizeof(uint32_t)));
CheckBuffer(expectedValueU32, outputBuffer);
} }
} }
template <typename T> template <typename T, typename CheckBufferFn>
void DoSamplingTest(TestAspect aspect, void DoSamplingTestImpl(TestAspect aspect,
wgpu::ComputePipeline pipeline, wgpu::ComputePipeline pipeline,
wgpu::TextureFormat format, wgpu::TextureFormat format,
std::vector<T> textureValues, std::vector<T> textureValues,
std::vector<T> expectedValues) { uint32_t componentCount,
ASSERT(textureValues.size() == expectedValues.size()); CheckBufferFn CheckBuffer) {
wgpu::Texture inputTexture = CreateInputTexture(format); wgpu::Texture inputTexture = CreateInputTexture(format);
wgpu::TextureViewDescriptor inputViewDesc = {}; wgpu::TextureViewDescriptor inputViewDesc = {};
switch (aspect) { switch (aspect) {
@ -344,7 +342,7 @@ class DepthStencilSamplingTest : public DawnTest {
break; break;
} }
wgpu::Buffer outputBuffer = CreateOutputBuffer(); wgpu::Buffer outputBuffer = CreateOutputBuffer(componentCount);
wgpu::BindGroup bindGroup = wgpu::BindGroup bindGroup =
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
@ -375,8 +373,8 @@ class DepthStencilSamplingTest : public DawnTest {
queue.Submit(1, &commands); queue.Submit(1, &commands);
uint32_t expectedValueU32 = 0; uint32_t expectedValueU32 = 0;
memcpy(&expectedValueU32, &expectedValues[i], std::min(sizeof(T), sizeof(uint32_t))); memcpy(&expectedValueU32, &textureValues[i], std::min(sizeof(T), sizeof(uint32_t)));
EXPECT_BUFFER_U32_EQ(expectedValueU32, outputBuffer, 0); CheckBuffer(expectedValueU32, outputBuffer);
} }
} }
@ -385,7 +383,10 @@ class DepthStencilSamplingTest : public DawnTest {
wgpu::RenderPipeline pipeline, wgpu::RenderPipeline pipeline,
wgpu::TextureFormat format, wgpu::TextureFormat format,
std::vector<T> textureValues) { std::vector<T> textureValues) {
DoSamplingTest(aspect, pipeline, format, textureValues, textureValues); DoSamplingTestImpl(aspect, pipeline, format, textureValues, 1,
[this](uint32_t expected, wgpu::Buffer buffer) {
EXPECT_BUFFER_U32_EQ(expected, buffer, 0);
});
} }
template <typename T> template <typename T>
@ -393,7 +394,65 @@ class DepthStencilSamplingTest : public DawnTest {
wgpu::ComputePipeline pipeline, wgpu::ComputePipeline pipeline,
wgpu::TextureFormat format, wgpu::TextureFormat format,
std::vector<T> textureValues) { std::vector<T> textureValues) {
DoSamplingTest(aspect, pipeline, format, textureValues, textureValues); DoSamplingTestImpl(aspect, pipeline, format, textureValues, 1,
[this](uint32_t expected, wgpu::Buffer buffer) {
EXPECT_BUFFER_U32_EQ(expected, buffer, 0);
});
}
class ExtraStencilComponentsExpectation : public detail::Expectation {
using StencilData = std::array<uint32_t, 4>;
public:
ExtraStencilComponentsExpectation(uint32_t expected) : mExpected(expected) {
}
~ExtraStencilComponentsExpectation() override = default;
testing::AssertionResult Check(const void* rawData, size_t size) override {
ASSERT(size == sizeof(StencilData));
const uint32_t* data = static_cast<const uint32_t*>(rawData);
StencilData ssss = {mExpected, mExpected, mExpected, mExpected};
StencilData s001 = {mExpected, 0, 0, 1};
if (memcmp(data, ssss.data(), size) == 0 || memcmp(data, s001.data(), size) == 0) {
return testing::AssertionSuccess();
}
return testing::AssertionFailure() << "Expected stencil data to be "
<< "(" << ssss[0] << ", " << ssss[1] << ", "
<< ssss[2] << ", " << ssss[3] << ") or "
<< "(" << s001[0] << ", " << s001[1] << ", "
<< s001[2] << ", " << s001[3] << "). Got "
<< "(" << data[0] << ", " << data[1] << ", "
<< data[2] << ", " << data[3] << ").";
}
private:
uint32_t mExpected;
};
void DoSamplingExtraStencilComponentsRenderTest(TestAspect aspect,
wgpu::TextureFormat format,
std::vector<uint8_t> textureValues) {
DoSamplingTestImpl(aspect,
CreateSamplingRenderPipeline({TestAspect::Stencil}, {0, 1, 2, 3}),
format, textureValues, 4, [&](uint32_t expected, wgpu::Buffer buffer) {
EXPECT_BUFFER(buffer, 0, 4 * sizeof(uint32_t),
new ExtraStencilComponentsExpectation(expected));
});
}
void DoSamplingExtraStencilComponentsComputeTest(TestAspect aspect,
wgpu::TextureFormat format,
std::vector<uint8_t> textureValues) {
DoSamplingTestImpl(aspect,
CreateSamplingComputePipeline({TestAspect::Stencil}, {0, 1, 2, 3}),
format, textureValues, 4, [&](uint32_t expected, wgpu::Buffer buffer) {
EXPECT_BUFFER(buffer, 0, 4 * sizeof(uint32_t),
new ExtraStencilComponentsExpectation(expected));
});
} }
static bool CompareFunctionPasses(float compareRef, static bool CompareFunctionPasses(float compareRef,
@ -552,32 +611,12 @@ TEST_P(DepthStencilSamplingTest, SampleStencil) {
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());
// TODO(enga): In Metal, color textures' unspecified default components values
// are (0, 0, 0, 1). Depth/stencil textures are undefined! Figure out what
// to do here.
// See Section 6.10 of the Metal Shading Language Specification
DAWN_SUPPRESS_TEST_IF(IsMetal());
float expectedDepth[4] = {0, 0, 0, 1}; DoSamplingExtraStencilComponentsRenderTest(
uint8_t expectedStencil[4] = {0, 0, 0, 1}; TestAspect::Stencil, wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(42), uint8_t(37)});
for (uint32_t component : {1, 2, 3}) { DoSamplingExtraStencilComponentsComputeTest(
DoSamplingTest<float>( TestAspect::Stencil, wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(42), uint8_t(37)});
TestAspect::Depth, CreateSamplingRenderPipeline({TestAspect::Depth}, component),
wgpu::TextureFormat::Depth24PlusStencil8, {0.2f}, {expectedDepth[component]});
DoSamplingTest<float>(
TestAspect::Depth, CreateSamplingComputePipeline({TestAspect::Depth}, component),
wgpu::TextureFormat::Depth24PlusStencil8, {0.2f}, {expectedDepth[component]});
DoSamplingTest<uint8_t>(
TestAspect::Stencil, CreateSamplingRenderPipeline({TestAspect::Stencil}, component),
wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(37)}, {expectedStencil[component]});
DoSamplingTest<uint8_t>(
TestAspect::Stencil, CreateSamplingComputePipeline({TestAspect::Stencil}, component),
wgpu::TextureFormat::Depth24PlusStencil8, {uint8_t(37)}, {expectedStencil[component]});
}
} }
// Test sampling both depth and stencil with a render/compute pipeline works. // Test sampling both depth and stencil with a render/compute pipeline works.
@ -600,16 +639,18 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
wgpu::RenderPipeline pipeline = wgpu::RenderPipeline pipeline =
CreateSamplingRenderPipeline({TestAspect::Depth, TestAspect::Stencil}, 0); CreateSamplingRenderPipeline({TestAspect::Depth, TestAspect::Stencil}, 0);
wgpu::Buffer depthOutput = CreateOutputBuffer();
wgpu::Buffer stencilOutput = CreateOutputBuffer();
wgpu::BindGroup bindGroup = wgpu::BindGroup bindGroup =
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
{ {
{0, inputTexture.CreateView(&depthViewDesc)}, {0, inputTexture.CreateView(&depthViewDesc)},
{1, inputTexture.CreateView(&stencilViewDesc)}, {1, depthOutput},
{2, inputTexture.CreateView(&stencilViewDesc)},
{3, stencilOutput},
}); });
wgpu::Texture depthOutput = CreateOutputTexture(wgpu::TextureFormat::R32Float);
wgpu::Texture stencilOutput = CreateOutputTexture(wgpu::TextureFormat::R8Uint);
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
// Initialize both depth and stencil aspects. // Initialize both depth and stencil aspects.
@ -622,9 +663,10 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
// Render into the output textures // Render into the output textures
{ {
utils::ComboRenderPassDescriptor passDescriptor( utils::BasicRenderPass renderPass =
{depthOutput.CreateView(), stencilOutput.CreateView()}); utils::CreateBasicRenderPass(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor); wgpu::RenderPassEncoder pass =
commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
pass.SetPipeline(pipeline); pass.SetPipeline(pipeline);
pass.SetBindGroup(0, bindGroup); pass.SetBindGroup(0, bindGroup);
pass.Draw(1); pass.Draw(1);
@ -634,10 +676,15 @@ TEST_P(DepthStencilSamplingTest, SampleDepthAndStencilRender) {
wgpu::CommandBuffer commands = commandEncoder.Finish(); wgpu::CommandBuffer commands = commandEncoder.Finish();
queue.Submit(1, &commands); queue.Submit(1, &commands);
EXPECT_TEXTURE_EQ(passDescriptor.cDepthStencilAttachmentInfo.clearDepth, depthOutput, uint32_t expectedValueU32 = 0;
{0, 0}); memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearDepth,
EXPECT_TEXTURE_EQ(uint8_t(passDescriptor.cDepthStencilAttachmentInfo.clearStencil), sizeof(float));
stencilOutput, {0, 0}); EXPECT_BUFFER_U32_EQ(expectedValueU32, depthOutput, 0);
expectedValueU32 = 0;
memcpy(&expectedValueU32, &passDescriptor.cDepthStencilAttachmentInfo.clearStencil,
sizeof(uint8_t));
EXPECT_BUFFER_U32_EQ(expectedValueU32, stencilOutput, 0);
} }
// With compute pipeline // With compute pipeline

View File

@ -206,12 +206,16 @@ TEST_P(MultisampledSamplingTest, SamplePositions) {
wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass(); wgpu::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
computePassEncoder.SetPipeline(checkSamplePipeline); computePassEncoder.SetPipeline(checkSamplePipeline);
computePassEncoder.SetBindGroup( // TODO(crbug.com/dawn/1021): Disallow using float/unfilterable-float with depth
0, utils::MakeBindGroup( // textures.
device, checkSamplePipeline.GetBindGroupLayout(0), wgpu::BindGroup bindGroup;
{{0, colorView}, EXPECT_DEPRECATION_WARNING(
{1, depthView}, bindGroup = utils::MakeBindGroup(
{2, outputBuffer, alignedResultSize * sampleOffset, kResultSize}})); device, checkSamplePipeline.GetBindGroupLayout(0),
{{0, colorView},
{1, depthView},
{2, outputBuffer, alignedResultSize * sampleOffset, kResultSize}}));
computePassEncoder.SetBindGroup(0, bindGroup);
computePassEncoder.Dispatch(1); computePassEncoder.Dispatch(1);
computePassEncoder.EndPass(); computePassEncoder.EndPass();
} }

View File

@ -470,9 +470,12 @@ TEST_F(BindGroupValidationTest, TextureSampleType) {
DoTest(false, wgpu::TextureFormat::R32Float, wgpu::TextureSampleType::Uint); DoTest(false, wgpu::TextureFormat::R32Float, wgpu::TextureSampleType::Uint);
DoTest(false, wgpu::TextureFormat::R32Float, wgpu::TextureSampleType::Sint); DoTest(false, wgpu::TextureFormat::R32Float, wgpu::TextureSampleType::Sint);
// Test that Depth32Float is only compatible with float/unfilterable-float/depth // Test that Depth32Float is only compatible with depth. float/unfilterable-float is deprecated.
DoTest(true, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Float); // TODO(crbug.com/dawn/1021): Disallow using float/unfilterable-float with depth textures.
DoTest(true, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::UnfilterableFloat); EXPECT_DEPRECATION_WARNING(
DoTest(true, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Float));
EXPECT_DEPRECATION_WARNING(DoTest(true, wgpu::TextureFormat::Depth32Float,
wgpu::TextureSampleType::UnfilterableFloat));
DoTest(true, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Depth); DoTest(true, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Depth);
DoTest(false, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Uint); DoTest(false, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Uint);
DoTest(false, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Sint); DoTest(false, wgpu::TextureFormat::Depth32Float, wgpu::TextureSampleType::Sint);
@ -495,7 +498,7 @@ TEST_F(BindGroupValidationTest, TextureSampleType) {
// Test which depth-stencil formats are allowed to be sampled (all). // Test which depth-stencil formats are allowed to be sampled (all).
TEST_F(BindGroupValidationTest, SamplingDepthStencilTexture) { TEST_F(BindGroupValidationTest, SamplingDepthStencilTexture) {
wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout( wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}}); device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Depth}});
wgpu::TextureDescriptor desc; wgpu::TextureDescriptor desc;
desc.size = {1, 1, 1}; desc.size = {1, 1, 1};

View File

@ -160,7 +160,8 @@ namespace utils {
BasicRenderPass CreateBasicRenderPass(const wgpu::Device& device, BasicRenderPass CreateBasicRenderPass(const wgpu::Device& device,
uint32_t width, uint32_t width,
uint32_t height) { uint32_t height,
wgpu::TextureFormat format) {
DAWN_ASSERT(width > 0 && height > 0); DAWN_ASSERT(width > 0 && height > 0);
wgpu::TextureDescriptor descriptor; wgpu::TextureDescriptor descriptor;
@ -169,7 +170,7 @@ namespace utils {
descriptor.size.height = height; descriptor.size.height = height;
descriptor.size.depthOrArrayLayers = 1; descriptor.size.depthOrArrayLayers = 1;
descriptor.sampleCount = 1; descriptor.sampleCount = 1;
descriptor.format = BasicRenderPass::kDefaultColorFormat; descriptor.format = format;
descriptor.mipLevelCount = 1; descriptor.mipLevelCount = 1;
descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc; descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
wgpu::Texture color = device.CreateTexture(&descriptor); wgpu::Texture color = device.CreateTexture(&descriptor);

View File

@ -87,9 +87,11 @@ namespace utils {
wgpu::TextureFormat colorFormat; wgpu::TextureFormat colorFormat;
utils::ComboRenderPassDescriptor renderPassInfo; utils::ComboRenderPassDescriptor renderPassInfo;
}; };
BasicRenderPass CreateBasicRenderPass(const wgpu::Device& device, BasicRenderPass CreateBasicRenderPass(
uint32_t width, const wgpu::Device& device,
uint32_t height); uint32_t width,
uint32_t height,
wgpu::TextureFormat format = BasicRenderPass::kDefaultColorFormat);
wgpu::PipelineLayout MakeBasicPipelineLayout(const wgpu::Device& device, wgpu::PipelineLayout MakeBasicPipelineLayout(const wgpu::Device& device,
const wgpu::BindGroupLayout* bindGroupLayout); const wgpu::BindGroupLayout* bindGroupLayout);