mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-17 00:47:13 +00:00
Support Storage Textures as Valid Binding Types
This patch adds the basic validation of read-only storage texture, write-only storage texture and read-write storage texture as new binding types with no bind group layout provided in the creation of pipeline state objects. - Read-only storage textures can be used in vertex, fragment and compute shaders. - Write-only storage textures can only be used in compute shaders due to the limitation on Metal. - Read-write storage textures are not allowed now and they are reserved to be supported as an extension in the future. BUG=dawn:267 TEST=dawn_unittests Change-Id: Iffc432f29a855b85d59451cb3c50269e03b84627 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16661 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
52d0627d56
commit
421684f943
207
src/tests/unittests/validation/StorageTextureValidationTests.cpp
Normal file
207
src/tests/unittests/validation/StorageTextureValidationTests.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright 2020 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
class StorageTextureValidationTests : public ValidationTest {
|
||||
protected:
|
||||
wgpu::ShaderModule mDefaultVSModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
void main() {
|
||||
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
|
||||
})");
|
||||
wgpu::ShaderModule mDefaultFSModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = vec4(1.f, 0.f, 0.f, 1.f);
|
||||
})");
|
||||
};
|
||||
|
||||
// Validate read-only storage textures can be declared in vertex and fragment
|
||||
// shaders, while writeonly storage textures can't.
|
||||
TEST_F(StorageTextureValidationTests, RenderPipeline) {
|
||||
// Readonly storage texture can be declared in a vertex shader.
|
||||
{
|
||||
wgpu::ShaderModule vsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform readonly image2D image0;
|
||||
void main() {
|
||||
gl_Position = imageLoad(image0, ivec2(gl_VertexIndex, 0));
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = mDefaultFSModule;
|
||||
device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
||||
// Read-only storage textures can be declared in a fragment shader.
|
||||
{
|
||||
wgpu::ShaderModule fsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform readonly image2D image0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = imageLoad(image0, ivec2(gl_FragCoord.xy));
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = mDefaultVSModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
||||
// Write-only storage textures cannot be declared in a vertex shader.
|
||||
{
|
||||
wgpu::ShaderModule vsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform writeonly image2D image0;
|
||||
void main() {
|
||||
imageStore(image0, ivec2(gl_VertexIndex, 0), vec4(1.f, 0.f, 0.f, 1.f));
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = mDefaultFSModule;
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
|
||||
// Write-only storage textures cannot be declared in a fragment shader.
|
||||
{
|
||||
wgpu::ShaderModule fsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform writeonly image2D image0;
|
||||
void main() {
|
||||
imageStore(image0, ivec2(gl_FragCoord.xy), vec4(1.f, 0.f, 0.f, 1.f));
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = mDefaultVSModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Validate both read-only and write-only storage textures can be declared in
|
||||
// compute shaders.
|
||||
TEST_F(StorageTextureValidationTests, ComputePipeline) {
|
||||
// Read-only storage textures can be declared in a compute shader.
|
||||
{
|
||||
wgpu::ShaderModule csModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform readonly image2D image0;
|
||||
layout(std430, set = 0, binding = 0) buffer Buf { uint buf; };
|
||||
void main() {
|
||||
vec4 pixel = imageLoad(image0, ivec2(gl_LocalInvocationID.xy));
|
||||
buf = uint(pixel.x);
|
||||
})");
|
||||
|
||||
wgpu::ComputePipelineDescriptor descriptor;
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.computeStage.module = csModule;
|
||||
descriptor.computeStage.entryPoint = "main";
|
||||
|
||||
device.CreateComputePipeline(&descriptor);
|
||||
}
|
||||
|
||||
// Write-only storage textures can be declared in a compute shader.
|
||||
{
|
||||
wgpu::ShaderModule csModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform writeonly image2D image0;
|
||||
void main() {
|
||||
imageStore(image0, ivec2(gl_LocalInvocationID.xy), vec4(0.f, 0.f, 0.f, 0.f));
|
||||
})");
|
||||
|
||||
wgpu::ComputePipelineDescriptor descriptor;
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.computeStage.module = csModule;
|
||||
descriptor.computeStage.entryPoint = "main";
|
||||
|
||||
device.CreateComputePipeline(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate read-write storage textures have not been supported yet.
|
||||
TEST_F(StorageTextureValidationTests, ReadWriteStorageTexture) {
|
||||
// Read-write storage textures cannot be declared in a vertex shader by default.
|
||||
{
|
||||
wgpu::ShaderModule vsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform image2D image0;
|
||||
void main() {
|
||||
vec4 pixel = imageLoad(image0, ivec2(gl_VertexIndex, 0));
|
||||
imageStore(image0, ivec2(gl_VertexIndex, 0), pixel * 2);
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = mDefaultFSModule;
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
|
||||
// Read-write storage textures cannot be declared in a fragment shader by default.
|
||||
{
|
||||
wgpu::ShaderModule fsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform image2D image0;
|
||||
void main() {
|
||||
vec4 pixel = imageLoad(image0, ivec2(gl_FragCoord.xy));
|
||||
imageStore(image0, ivec2(gl_FragCoord.xy), pixel * 2);
|
||||
})");
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.vertexStage.module = mDefaultVSModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
|
||||
// Read-write storage textures cannot be declared in a compute shader by default.
|
||||
{
|
||||
wgpu::ShaderModule csModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
|
||||
#version 450
|
||||
layout(set = 0, binding = 0, rgba8) uniform image2D image0;
|
||||
void main() {
|
||||
vec4 pixel = imageLoad(image0, ivec2(gl_LocalInvocationID.xy));
|
||||
imageStore(image0, ivec2(gl_LocalInvocationID.xy), pixel * 2);
|
||||
})");
|
||||
|
||||
wgpu::ComputePipelineDescriptor descriptor;
|
||||
descriptor.layout = nullptr;
|
||||
descriptor.computeStage.module = csModule;
|
||||
descriptor.computeStage.entryPoint = "main";
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&descriptor));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user