diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn index 762b141b02..54cc12bd87 100644 --- a/src/tests/BUILD.gn +++ b/src/tests/BUILD.gn @@ -336,6 +336,7 @@ source_set("dawn_end2end_tests_sources") { "end2end/QueryTests.cpp", "end2end/QueueTests.cpp", "end2end/QueueTimelineTests.cpp", + "end2end/RenderAttachmentTests.cpp", "end2end/RenderBundleTests.cpp", "end2end/RenderPassLoadOpTests.cpp", "end2end/RenderPassTests.cpp", diff --git a/src/tests/end2end/RenderAttachmentTests.cpp b/src/tests/end2end/RenderAttachmentTests.cpp new file mode 100644 index 0000000000..a02dd4a4cf --- /dev/null +++ b/src/tests/end2end/RenderAttachmentTests.cpp @@ -0,0 +1,84 @@ +// Copyright 2021 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "tests/DawnTest.h" + +#include "utils/ComboRenderPipelineDescriptor.h" +#include "utils/WGPUHelpers.h" + +class RenderAttachmentTest : public DawnTest {}; + +// Test that it is ok to have more fragment outputs than color attachments. +// There should be no backend validation errors or indexing out-of-bounds. +TEST_P(RenderAttachmentTest, MoreFragmentOutputsThanAttachments) { + wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"( + [[stage(vertex)]] + fn main() -> [[builtin(position)]] vec4 { + return vec4(0.0, 0.0, 0.0, 1.0); + })"); + + wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"( + struct Output { + [[location(0)]] color0 : vec4; + [[location(1)]] color1 : vec4; + [[location(2)]] color2 : vec4; + [[location(3)]] color3 : vec4; + }; + + [[stage(fragment)]] + fn main() -> Output { + var output : Output; + output.color0 = vec4(1.0, 0.0, 0.0, 1.0); + output.color1 = vec4(0.0, 1.0, 0.0, 1.0); + output.color2 = vec4(0.0, 0.0, 1.0, 1.0); + output.color3 = vec4(1.0, 1.0, 0.0, 1.0); + return output; + })"); + + // Fragment outputs 1, 2, 3 are written in the shader, but unused by the pipeline. + utils::ComboRenderPipelineDescriptor pipelineDesc; + pipelineDesc.vertex.module = vsModule; + pipelineDesc.cFragment.module = fsModule; + pipelineDesc.primitive.topology = wgpu::PrimitiveTopology::PointList; + pipelineDesc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm; + pipelineDesc.cFragment.targetCount = 1; + + wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc); + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + + wgpu::TextureDescriptor textureDesc; + textureDesc.size = {1, 1, 1}; + textureDesc.format = wgpu::TextureFormat::RGBA8Unorm; + textureDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc; + + wgpu::Texture renderTarget = device.CreateTexture(&textureDesc); + utils::ComboRenderPassDescriptor renderPass({renderTarget.CreateView()}); + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); + pass.SetPipeline(pipeline); + pass.Draw(1); + pass.EndPass(); + wgpu::CommandBuffer commands = encoder.Finish(); + queue.Submit(1, &commands); + + EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderTarget, 0, 0); +} + +DAWN_INSTANTIATE_TEST(RenderAttachmentTest, + D3D12Backend(), + D3D12Backend({}, {"use_d3d12_render_pass"}), + MetalBackend(), + OpenGLBackend(), + OpenGLESBackend(), + VulkanBackend());