blob: cd1034ada742f52f1911f4e014ea089555690959 [file] [log] [blame]
Yunchao He77752582019-02-16 02:27:30 +00001// Copyright 2017 The Dawn Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Carl Woffenden22eff1e2021-01-12 19:47:13 +000015#include <algorithm>
Yunchao He77752582019-02-16 02:27:30 +000016#include <array>
17#include <cmath>
18
19#include "tests/DawnTest.h"
20
21#include "common/Assert.h"
22#include "common/Constants.h"
23#include "utils/ComboRenderPipelineDescriptor.h"
Corentin Wallez04863c42019-10-25 11:36:47 +000024#include "utils/WGPUHelpers.h"
Yunchao He77752582019-02-16 02:27:30 +000025
26constexpr static unsigned int kRTSize = 64;
27
28class ColorStateTest : public DawnTest {
29 protected:
Austin Eng40dc5d32020-05-15 22:06:35 +000030 void SetUp() override {
31 DawnTest::SetUp();
Yunchao He77752582019-02-16 02:27:30 +000032
Ben Clayton955146e2021-03-30 12:05:47 +000033 // TODO(crbug.com/dawn/489): D3D12_Microsoft_Basic_Render_Driver_CPU
34 // produces invalid results for these tests.
Jiawei Shao4589de62021-05-21 02:26:58 +000035 DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsWARP());
Ben Clayton955146e2021-03-30 12:05:47 +000036
Corentin Wallez7aec4ae2021-03-24 15:55:32 +000037 vsModule = utils::CreateShaderModule(device, R"(
Brandon Jonese87ea2b2021-04-14 17:05:07 +000038 [[stage(vertex)]]
39 fn main([[builtin(vertex_index)]] VertexIndex : u32) -> [[builtin(position)]] vec4<f32> {
Corentin Wallezb86e45f2021-06-17 21:36:11 +000040 var pos = array<vec2<f32>, 3>(
Austin Enge08776a2020-11-13 17:30:59 +000041 vec2<f32>(-1.0, -1.0),
42 vec2<f32>(3.0, -1.0),
43 vec2<f32>(-1.0, 3.0));
Brandon Jonese87ea2b2021-04-14 17:05:07 +000044 return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
Yunchao He77752582019-02-16 02:27:30 +000045 }
46 )");
47
Yunchao He77752582019-02-16 02:27:30 +000048 renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
49 }
50
51 struct TriangleSpec {
52 RGBA8 color;
53 std::array<float, 4> blendFactor = {};
54 };
55
56 // Set up basePipeline and testPipeline. testPipeline has the given blend state on the first
57 // attachment. basePipeline has no blending
Brandon Jonesbff9d3a2021-03-18 02:54:27 +000058 void SetupSingleSourcePipelines(wgpu::ColorTargetState colorTargetState) {
Corentin Wallez7aec4ae2021-03-24 15:55:32 +000059 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
Austin Enge08776a2020-11-13 17:30:59 +000060 [[block]] struct MyBlock {
Ben Claytonc5686842021-03-17 09:48:19 +000061 color : vec4<f32>;
Austin Enge08776a2020-11-13 17:30:59 +000062 };
Yunchao He77752582019-02-16 02:27:30 +000063
dan sinclair0f9c2d72021-01-19 14:18:51 +000064 [[group(0), binding(0)]] var<uniform> myUbo : MyBlock;
Yunchao He77752582019-02-16 02:27:30 +000065
Brandon Jonese87ea2b2021-04-14 17:05:07 +000066 [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
67 return myUbo.color;
Yunchao He77752582019-02-16 02:27:30 +000068 }
69 )");
70
Brandon Jones41c87d92021-05-21 05:01:38 +000071 utils::ComboRenderPipelineDescriptor baseDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +000072 baseDescriptor.vertex.module = vsModule;
73 baseDescriptor.cFragment.module = fsModule;
74 baseDescriptor.cTargets[0].format = renderPass.colorFormat;
Yunchao He77752582019-02-16 02:27:30 +000075
Brandon Jones41c87d92021-05-21 05:01:38 +000076 basePipeline = device.CreateRenderPipeline(&baseDescriptor);
Yunchao He77752582019-02-16 02:27:30 +000077
Brandon Jones41c87d92021-05-21 05:01:38 +000078 utils::ComboRenderPipelineDescriptor testDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +000079 testDescriptor.vertex.module = vsModule;
80 testDescriptor.cFragment.module = fsModule;
81 testDescriptor.cTargets[0] = colorTargetState;
82 testDescriptor.cTargets[0].format = renderPass.colorFormat;
Yunchao He77752582019-02-16 02:27:30 +000083
Brandon Jones41c87d92021-05-21 05:01:38 +000084 testPipeline = device.CreateRenderPipeline(&testDescriptor);
Yunchao He77752582019-02-16 02:27:30 +000085 }
86
87 // Create a bind group to set the colors as a uniform buffer
88 template <size_t N>
Corentin Wallezcab352c2019-10-28 13:27:36 +000089 wgpu::BindGroup MakeBindGroupForColors(std::array<RGBA8, N> colors) {
Yunchao He77752582019-02-16 02:27:30 +000090 std::array<float, 4 * N> data;
91 for (unsigned int i = 0; i < N; ++i) {
92 data[4 * i + 0] = static_cast<float>(colors[i].r) / 255.f;
93 data[4 * i + 1] = static_cast<float>(colors[i].g) / 255.f;
94 data[4 * i + 2] = static_cast<float>(colors[i].b) / 255.f;
95 data[4 * i + 3] = static_cast<float>(colors[i].a) / 255.f;
96 }
97
98 uint32_t bufferSize = static_cast<uint32_t>(4 * N * sizeof(float));
99
Corentin Wallezcab352c2019-10-28 13:27:36 +0000100 wgpu::Buffer buffer =
101 utils::CreateBufferFromData(device, &data, bufferSize, wgpu::BufferUsage::Uniform);
Austin Eng3d383012019-12-03 20:39:53 +0000102 return utils::MakeBindGroup(device, testPipeline.GetBindGroupLayout(0),
103 {{0, buffer, 0, bufferSize}});
Yunchao He77752582019-02-16 02:27:30 +0000104 }
105
106 // Test that after drawing a triangle with the base color, and then the given triangle spec, the
107 // color is as expected
108 void DoSingleSourceTest(RGBA8 base, const TriangleSpec& triangle, const RGBA8& expected) {
Brandon Jones413dcf82021-04-15 19:33:58 +0000109 wgpu::Color blendConstant{triangle.blendFactor[0], triangle.blendFactor[1],
110 triangle.blendFactor[2], triangle.blendFactor[3]};
Yunchao He77752582019-02-16 02:27:30 +0000111
Corentin Wallezcab352c2019-10-28 13:27:36 +0000112 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000113 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000114 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +0000115 // First use the base pipeline to draw a triangle with no blending
116 pass.SetPipeline(basePipeline);
Corentin Wallez70c8c102019-10-09 16:08:42 +0000117 pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({{base}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000118 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000119
120 // Then use the test pipeline to draw the test triangle with blending
121 pass.SetPipeline(testPipeline);
Corentin Wallez70c8c102019-10-09 16:08:42 +0000122 pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({{triangle.color}})));
Brandon Jones413dcf82021-04-15 19:33:58 +0000123 pass.SetBlendConstant(&blendConstant);
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000124 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000125 pass.EndPass();
126 }
127
Corentin Wallezcab352c2019-10-28 13:27:36 +0000128 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +0000129 queue.Submit(1, &commands);
130
131 EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
132 }
133
134 // Given a vector of tests where each element is <testColor, expectedColor>, check that all
135 // expectations are true for the given blend operation
136 void CheckBlendOperation(RGBA8 base,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000137 wgpu::BlendOperation operation,
Yunchao He77752582019-02-16 02:27:30 +0000138 std::vector<std::pair<RGBA8, RGBA8>> tests) {
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000139 wgpu::BlendComponent blendComponent;
140 blendComponent.operation = operation;
141 blendComponent.srcFactor = wgpu::BlendFactor::One;
142 blendComponent.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000143
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000144 wgpu::BlendState blend;
145 blend.color = blendComponent;
146 blend.alpha = blendComponent;
147
148 wgpu::ColorTargetState descriptor;
149 descriptor.blend = &blend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000150 descriptor.writeMask = wgpu::ColorWriteMask::All;
Yunchao He77752582019-02-16 02:27:30 +0000151
152 SetupSingleSourcePipelines(descriptor);
153
154 for (const auto& test : tests) {
155 DoSingleSourceTest(base, {test.first}, test.second);
156 }
157 }
158
159 // Given a vector of tests where each element is <testSpec, expectedColor>, check that all
160 // expectations are true for the given blend factors
161 void CheckBlendFactor(RGBA8 base,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000162 wgpu::BlendFactor colorSrcFactor,
163 wgpu::BlendFactor colorDstFactor,
164 wgpu::BlendFactor alphaSrcFactor,
165 wgpu::BlendFactor alphaDstFactor,
Yunchao He77752582019-02-16 02:27:30 +0000166 std::vector<std::pair<TriangleSpec, RGBA8>> tests) {
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000167 wgpu::BlendComponent colorBlend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000168 colorBlend.operation = wgpu::BlendOperation::Add;
Yunchao He77752582019-02-16 02:27:30 +0000169 colorBlend.srcFactor = colorSrcFactor;
170 colorBlend.dstFactor = colorDstFactor;
171
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000172 wgpu::BlendComponent alphaBlend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000173 alphaBlend.operation = wgpu::BlendOperation::Add;
Yunchao He77752582019-02-16 02:27:30 +0000174 alphaBlend.srcFactor = alphaSrcFactor;
175 alphaBlend.dstFactor = alphaDstFactor;
176
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000177 wgpu::BlendState blend;
178 blend.color = colorBlend;
179 blend.alpha = alphaBlend;
180
181 wgpu::ColorTargetState descriptor;
182 descriptor.blend = &blend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000183 descriptor.writeMask = wgpu::ColorWriteMask::All;
Yunchao He77752582019-02-16 02:27:30 +0000184
185 SetupSingleSourcePipelines(descriptor);
186
187 for (const auto& test : tests) {
188 DoSingleSourceTest(base, test.first, test.second);
189 }
190 }
191
192 void CheckSrcBlendFactor(RGBA8 base,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000193 wgpu::BlendFactor colorFactor,
194 wgpu::BlendFactor alphaFactor,
Yunchao He77752582019-02-16 02:27:30 +0000195 std::vector<std::pair<TriangleSpec, RGBA8>> tests) {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000196 CheckBlendFactor(base, colorFactor, wgpu::BlendFactor::One, alphaFactor,
197 wgpu::BlendFactor::One, tests);
Yunchao He77752582019-02-16 02:27:30 +0000198 }
199
200 void CheckDstBlendFactor(RGBA8 base,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000201 wgpu::BlendFactor colorFactor,
202 wgpu::BlendFactor alphaFactor,
Yunchao He77752582019-02-16 02:27:30 +0000203 std::vector<std::pair<TriangleSpec, RGBA8>> tests) {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000204 CheckBlendFactor(base, wgpu::BlendFactor::One, colorFactor, wgpu::BlendFactor::One,
Yunchao He77752582019-02-16 02:27:30 +0000205 alphaFactor, tests);
206 }
207
208 utils::BasicRenderPass renderPass;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000209 wgpu::RenderPipeline basePipeline;
210 wgpu::RenderPipeline testPipeline;
211 wgpu::ShaderModule vsModule;
Yunchao He77752582019-02-16 02:27:30 +0000212};
213
214namespace {
215 // Add two colors and clamp
216 constexpr RGBA8 operator+(const RGBA8& col1, const RGBA8& col2) {
217 int r = static_cast<int>(col1.r) + static_cast<int>(col2.r);
218 int g = static_cast<int>(col1.g) + static_cast<int>(col2.g);
219 int b = static_cast<int>(col1.b) + static_cast<int>(col2.b);
220 int a = static_cast<int>(col1.a) + static_cast<int>(col2.a);
221 r = (r > 255 ? 255 : (r < 0 ? 0 : r));
222 g = (g > 255 ? 255 : (g < 0 ? 0 : g));
223 b = (b > 255 ? 255 : (b < 0 ? 0 : b));
224 a = (a > 255 ? 255 : (a < 0 ? 0 : a));
225
226 return RGBA8(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b),
227 static_cast<uint8_t>(a));
228 }
229
230 // Subtract two colors and clamp
231 constexpr RGBA8 operator-(const RGBA8& col1, const RGBA8& col2) {
232 int r = static_cast<int>(col1.r) - static_cast<int>(col2.r);
233 int g = static_cast<int>(col1.g) - static_cast<int>(col2.g);
234 int b = static_cast<int>(col1.b) - static_cast<int>(col2.b);
235 int a = static_cast<int>(col1.a) - static_cast<int>(col2.a);
236 r = (r > 255 ? 255 : (r < 0 ? 0 : r));
237 g = (g > 255 ? 255 : (g < 0 ? 0 : g));
238 b = (b > 255 ? 255 : (b < 0 ? 0 : b));
239 a = (a > 255 ? 255 : (a < 0 ? 0 : a));
240
241 return RGBA8(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b),
242 static_cast<uint8_t>(a));
243 }
244
245 // Get the component-wise minimum of two colors
246 RGBA8 min(const RGBA8& col1, const RGBA8& col2) {
247 return RGBA8(std::min(col1.r, col2.r), std::min(col1.g, col2.g), std::min(col1.b, col2.b),
248 std::min(col1.a, col2.a));
249 }
250
251 // Get the component-wise maximum of two colors
252 RGBA8 max(const RGBA8& col1, const RGBA8& col2) {
253 return RGBA8(std::max(col1.r, col2.r), std::max(col1.g, col2.g), std::max(col1.b, col2.b),
254 std::max(col1.a, col2.a));
255 }
256
257 // Blend two RGBA8 color values parameterized by the provided factors in the range [0.f, 1.f]
258 RGBA8 mix(const RGBA8& col1, const RGBA8& col2, std::array<float, 4> fac) {
259 float r = static_cast<float>(col1.r) * (1.f - fac[0]) + static_cast<float>(col2.r) * fac[0];
260 float g = static_cast<float>(col1.g) * (1.f - fac[1]) + static_cast<float>(col2.g) * fac[1];
261 float b = static_cast<float>(col1.b) * (1.f - fac[2]) + static_cast<float>(col2.b) * fac[2];
262 float a = static_cast<float>(col1.a) * (1.f - fac[3]) + static_cast<float>(col2.a) * fac[3];
263
264 return RGBA8({static_cast<uint8_t>(std::round(r)), static_cast<uint8_t>(std::round(g)),
265 static_cast<uint8_t>(std::round(b)), static_cast<uint8_t>(std::round(a))});
266 }
267
268 // Blend two RGBA8 color values parameterized by the provided RGBA8 factor
269 RGBA8 mix(const RGBA8& col1, const RGBA8& col2, const RGBA8& fac) {
270 std::array<float, 4> f = {{
271 static_cast<float>(fac.r) / 255.f,
272 static_cast<float>(fac.g) / 255.f,
273 static_cast<float>(fac.b) / 255.f,
274 static_cast<float>(fac.a) / 255.f,
275 }};
276 return mix(col1, col2, f);
277 }
278
279 constexpr std::array<RGBA8, 8> kColors = {{
280 // check operations over multiple channels
281 RGBA8(64, 0, 0, 0),
282 RGBA8(0, 64, 0, 0),
283 RGBA8(64, 0, 32, 0),
284 RGBA8(0, 64, 32, 0),
285 RGBA8(128, 0, 128, 128),
286 RGBA8(0, 128, 128, 128),
287
288 // check cases that may cause overflow
289 RGBA8(0, 0, 0, 0),
290 RGBA8(255, 255, 255, 255),
291 }};
292} // namespace
293
294// Test compilation and usage of the fixture
295TEST_P(ColorStateTest, Basic) {
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000296 wgpu::BlendComponent blendComponent;
297 blendComponent.operation = wgpu::BlendOperation::Add;
298 blendComponent.srcFactor = wgpu::BlendFactor::One;
299 blendComponent.dstFactor = wgpu::BlendFactor::Zero;
300
301 wgpu::BlendState blend;
302 blend.color = blendComponent;
303 blend.alpha = blendComponent;
304
305 wgpu::ColorTargetState descriptor;
306 descriptor.blend = &blend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000307 descriptor.writeMask = wgpu::ColorWriteMask::All;
Yunchao He77752582019-02-16 02:27:30 +0000308
309 SetupSingleSourcePipelines(descriptor);
310
311 DoSingleSourceTest(RGBA8(0, 0, 0, 0), {RGBA8(255, 0, 0, 0)}, RGBA8(255, 0, 0, 0));
312}
313
314// The following tests check test that the blend operation works
315TEST_P(ColorStateTest, BlendOperationAdd) {
316 RGBA8 base(32, 64, 128, 192);
317 std::vector<std::pair<RGBA8, RGBA8>> tests;
318 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
319 [&](const RGBA8& color) { return std::make_pair(color, base + color); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000320 CheckBlendOperation(base, wgpu::BlendOperation::Add, tests);
Yunchao He77752582019-02-16 02:27:30 +0000321}
322
323TEST_P(ColorStateTest, BlendOperationSubtract) {
324 RGBA8 base(32, 64, 128, 192);
325 std::vector<std::pair<RGBA8, RGBA8>> tests;
326 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
327 [&](const RGBA8& color) { return std::make_pair(color, color - base); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000328 CheckBlendOperation(base, wgpu::BlendOperation::Subtract, tests);
Yunchao He77752582019-02-16 02:27:30 +0000329}
330
331TEST_P(ColorStateTest, BlendOperationReverseSubtract) {
332 RGBA8 base(32, 64, 128, 192);
333 std::vector<std::pair<RGBA8, RGBA8>> tests;
334 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
335 [&](const RGBA8& color) { return std::make_pair(color, base - color); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000336 CheckBlendOperation(base, wgpu::BlendOperation::ReverseSubtract, tests);
Yunchao He77752582019-02-16 02:27:30 +0000337}
338
339TEST_P(ColorStateTest, BlendOperationMin) {
340 RGBA8 base(32, 64, 128, 192);
341 std::vector<std::pair<RGBA8, RGBA8>> tests;
342 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
343 [&](const RGBA8& color) { return std::make_pair(color, min(base, color)); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000344 CheckBlendOperation(base, wgpu::BlendOperation::Min, tests);
Yunchao He77752582019-02-16 02:27:30 +0000345}
346
347TEST_P(ColorStateTest, BlendOperationMax) {
348 RGBA8 base(32, 64, 128, 192);
349 std::vector<std::pair<RGBA8, RGBA8>> tests;
350 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
351 [&](const RGBA8& color) { return std::make_pair(color, max(base, color)); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000352 CheckBlendOperation(base, wgpu::BlendOperation::Max, tests);
Yunchao He77752582019-02-16 02:27:30 +0000353}
354
355// The following tests check that the Source blend factor works
356TEST_P(ColorStateTest, SrcBlendFactorZero) {
357 RGBA8 base(32, 64, 128, 192);
358 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
359 std::transform(
360 kColors.begin(), kColors.end(), std::back_inserter(tests),
361 [&](const RGBA8& color) { return std::make_pair(TriangleSpec({{color}}), base); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000362 CheckSrcBlendFactor(base, wgpu::BlendFactor::Zero, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000363}
364
365TEST_P(ColorStateTest, SrcBlendFactorOne) {
366 RGBA8 base(32, 64, 128, 192);
367 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
368 std::transform(
369 kColors.begin(), kColors.end(), std::back_inserter(tests),
370 [&](const RGBA8& color) { return std::make_pair(TriangleSpec({{color}}), base + color); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000371 CheckSrcBlendFactor(base, wgpu::BlendFactor::One, wgpu::BlendFactor::One, tests);
Yunchao He77752582019-02-16 02:27:30 +0000372}
373
Brandon Jones22b923c2021-04-15 18:34:29 +0000374TEST_P(ColorStateTest, SrcBlendFactorSrc) {
Yunchao He77752582019-02-16 02:27:30 +0000375 RGBA8 base(32, 64, 128, 192);
376 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
377 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
378 [&](const RGBA8& color) {
379 RGBA8 fac = color;
380 fac.a = 0;
381 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
382 return std::make_pair(TriangleSpec({{color}}), expected);
383 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000384 CheckSrcBlendFactor(base, wgpu::BlendFactor::Src, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000385}
386
Brandon Jones22b923c2021-04-15 18:34:29 +0000387TEST_P(ColorStateTest, SrcBlendFactorOneMinusSrc) {
Yunchao He77752582019-02-16 02:27:30 +0000388 RGBA8 base(32, 64, 128, 192);
389 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
390 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
391 [&](const RGBA8& color) {
392 RGBA8 fac = RGBA8(255, 255, 255, 255) - color;
393 fac.a = 0;
394 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
395 return std::make_pair(TriangleSpec({{color}}), expected);
396 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000397 CheckSrcBlendFactor(base, wgpu::BlendFactor::OneMinusSrc, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000398}
399
400TEST_P(ColorStateTest, SrcBlendFactorSrcAlpha) {
401 RGBA8 base(32, 64, 128, 192);
402 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
403 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
404 [&](const RGBA8& color) {
405 RGBA8 fac(color.a, color.a, color.a, color.a);
406 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
407 return std::make_pair(TriangleSpec({{color}}), expected);
408 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000409 CheckSrcBlendFactor(base, wgpu::BlendFactor::SrcAlpha, wgpu::BlendFactor::SrcAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000410}
411
412TEST_P(ColorStateTest, SrcBlendFactorOneMinusSrcAlpha) {
413 RGBA8 base(32, 64, 128, 192);
414 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
415 std::transform(
416 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
417 RGBA8 fac = RGBA8(255, 255, 255, 255) - RGBA8(color.a, color.a, color.a, color.a);
418 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
419 return std::make_pair(TriangleSpec({{color}}), expected);
420 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000421 CheckSrcBlendFactor(base, wgpu::BlendFactor::OneMinusSrcAlpha,
422 wgpu::BlendFactor::OneMinusSrcAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000423}
424
Brandon Jones22b923c2021-04-15 18:34:29 +0000425TEST_P(ColorStateTest, SrcBlendFactorDst) {
Yunchao He77752582019-02-16 02:27:30 +0000426 RGBA8 base(32, 64, 128, 192);
427 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
428 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
429 [&](const RGBA8& color) {
430 RGBA8 fac = base;
431 fac.a = 0;
432 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
433 return std::make_pair(TriangleSpec({{color}}), expected);
434 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000435 CheckSrcBlendFactor(base, wgpu::BlendFactor::Dst, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000436}
437
Brandon Jones22b923c2021-04-15 18:34:29 +0000438TEST_P(ColorStateTest, SrcBlendFactorOneMinusDst) {
Yunchao He77752582019-02-16 02:27:30 +0000439 RGBA8 base(32, 64, 128, 192);
440 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
441 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
442 [&](const RGBA8& color) {
443 RGBA8 fac = RGBA8(255, 255, 255, 255) - base;
444 fac.a = 0;
445 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
446 return std::make_pair(TriangleSpec({{color}}), expected);
447 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000448 CheckSrcBlendFactor(base, wgpu::BlendFactor::OneMinusDst, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000449}
450
451TEST_P(ColorStateTest, SrcBlendFactorDstAlpha) {
452 RGBA8 base(32, 64, 128, 192);
453 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
454 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
455 [&](const RGBA8& color) {
456 RGBA8 fac(base.a, base.a, base.a, base.a);
457 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
458 return std::make_pair(TriangleSpec({{color}}), expected);
459 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000460 CheckSrcBlendFactor(base, wgpu::BlendFactor::DstAlpha, wgpu::BlendFactor::DstAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000461}
462
463TEST_P(ColorStateTest, SrcBlendFactorOneMinusDstAlpha) {
464 RGBA8 base(32, 64, 128, 192);
465 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
466 std::transform(
467 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
468 RGBA8 fac = RGBA8(255, 255, 255, 255) - RGBA8(base.a, base.a, base.a, base.a);
469 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
470 return std::make_pair(TriangleSpec({{color}}), expected);
471 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000472 CheckSrcBlendFactor(base, wgpu::BlendFactor::OneMinusDstAlpha,
473 wgpu::BlendFactor::OneMinusDstAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000474}
475
476TEST_P(ColorStateTest, SrcBlendFactorSrcAlphaSaturated) {
477 RGBA8 base(32, 64, 128, 192);
478 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
479 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
480 [&](const RGBA8& color) {
481 uint8_t f = std::min(color.a, static_cast<uint8_t>(255 - base.a));
482 RGBA8 fac(f, f, f, 255);
483 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, fac);
484 return std::make_pair(TriangleSpec({{color}}), expected);
485 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000486 CheckSrcBlendFactor(base, wgpu::BlendFactor::SrcAlphaSaturated,
487 wgpu::BlendFactor::SrcAlphaSaturated, tests);
Yunchao He77752582019-02-16 02:27:30 +0000488}
489
Brandon Jones22b923c2021-04-15 18:34:29 +0000490TEST_P(ColorStateTest, SrcBlendFactorConstant) {
Yunchao He77752582019-02-16 02:27:30 +0000491 RGBA8 base(32, 64, 128, 192);
492 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
493 std::transform(
494 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
495 auto triangleSpec = TriangleSpec({{color}, {{0.2f, 0.4f, 0.6f, 0.8f}}});
496 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, triangleSpec.blendFactor);
497 return std::make_pair(triangleSpec, expected);
498 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000499 CheckSrcBlendFactor(base, wgpu::BlendFactor::Constant, wgpu::BlendFactor::Constant, tests);
Yunchao He77752582019-02-16 02:27:30 +0000500}
501
Brandon Jones22b923c2021-04-15 18:34:29 +0000502TEST_P(ColorStateTest, SrcBlendFactorOneMinusConstant) {
Yunchao He77752582019-02-16 02:27:30 +0000503 RGBA8 base(32, 64, 128, 192);
504 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
505 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
506 [&](const RGBA8& color) {
507 auto triangleSpec = TriangleSpec({{color}, {{0.2f, 0.4f, 0.6f, 0.8f}}});
508 std::array<float, 4> f = {{0.8f, 0.6f, 0.4f, 0.2f}};
509 RGBA8 expected = base + mix(RGBA8(0, 0, 0, 0), color, f);
510 return std::make_pair(triangleSpec, expected);
511 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000512 CheckSrcBlendFactor(base, wgpu::BlendFactor::OneMinusConstant,
513 wgpu::BlendFactor::OneMinusConstant, tests);
Yunchao He77752582019-02-16 02:27:30 +0000514}
515
516// The following tests check that the Destination blend factor works
517TEST_P(ColorStateTest, DstBlendFactorZero) {
518 RGBA8 base(32, 64, 128, 192);
519 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
520 std::transform(
521 kColors.begin(), kColors.end(), std::back_inserter(tests),
522 [&](const RGBA8& color) { return std::make_pair(TriangleSpec({{color}}), color); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000523 CheckDstBlendFactor(base, wgpu::BlendFactor::Zero, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000524}
525
526TEST_P(ColorStateTest, DstBlendFactorOne) {
527 RGBA8 base(32, 64, 128, 192);
528 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
529 std::transform(
530 kColors.begin(), kColors.end(), std::back_inserter(tests),
531 [&](const RGBA8& color) { return std::make_pair(TriangleSpec({{color}}), base + color); });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000532 CheckDstBlendFactor(base, wgpu::BlendFactor::One, wgpu::BlendFactor::One, tests);
Yunchao He77752582019-02-16 02:27:30 +0000533}
534
Brandon Jones22b923c2021-04-15 18:34:29 +0000535TEST_P(ColorStateTest, DstBlendFactorSrc) {
Yunchao He77752582019-02-16 02:27:30 +0000536 RGBA8 base(32, 64, 128, 192);
537 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
538 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
539 [&](const RGBA8& color) {
540 RGBA8 fac = color;
541 fac.a = 0;
542 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
543 return std::make_pair(TriangleSpec({{color}}), expected);
544 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000545 CheckDstBlendFactor(base, wgpu::BlendFactor::Src, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000546}
547
Brandon Jones22b923c2021-04-15 18:34:29 +0000548TEST_P(ColorStateTest, DstBlendFactorOneMinusSrc) {
Yunchao He77752582019-02-16 02:27:30 +0000549 RGBA8 base(32, 64, 128, 192);
550 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
551 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
552 [&](const RGBA8& color) {
553 RGBA8 fac = RGBA8(255, 255, 255, 255) - color;
554 fac.a = 0;
555 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
556 return std::make_pair(TriangleSpec({{color}}), expected);
557 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000558 CheckDstBlendFactor(base, wgpu::BlendFactor::OneMinusSrc, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000559}
560
561TEST_P(ColorStateTest, DstBlendFactorSrcAlpha) {
562 RGBA8 base(32, 64, 128, 192);
563 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
564 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
565 [&](const RGBA8& color) {
566 RGBA8 fac(color.a, color.a, color.a, color.a);
567 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
568 return std::make_pair(TriangleSpec({{color}}), expected);
569 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000570 CheckDstBlendFactor(base, wgpu::BlendFactor::SrcAlpha, wgpu::BlendFactor::SrcAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000571}
572
573TEST_P(ColorStateTest, DstBlendFactorOneMinusSrcAlpha) {
574 RGBA8 base(32, 64, 128, 192);
575 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
576 std::transform(
577 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
578 RGBA8 fac = RGBA8(255, 255, 255, 255) - RGBA8(color.a, color.a, color.a, color.a);
579 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
580 return std::make_pair(TriangleSpec({{color}}), expected);
581 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000582 CheckDstBlendFactor(base, wgpu::BlendFactor::OneMinusSrcAlpha,
583 wgpu::BlendFactor::OneMinusSrcAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000584}
585
Brandon Jones22b923c2021-04-15 18:34:29 +0000586TEST_P(ColorStateTest, DstBlendFactorDst) {
Yunchao He77752582019-02-16 02:27:30 +0000587 RGBA8 base(32, 64, 128, 192);
588 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
589 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
590 [&](const RGBA8& color) {
591 RGBA8 fac = base;
592 fac.a = 0;
593 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
594 return std::make_pair(TriangleSpec({{color}}), expected);
595 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000596 CheckDstBlendFactor(base, wgpu::BlendFactor::Dst, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000597}
598
Brandon Jones22b923c2021-04-15 18:34:29 +0000599TEST_P(ColorStateTest, DstBlendFactorOneMinusDst) {
Yunchao He77752582019-02-16 02:27:30 +0000600 RGBA8 base(32, 64, 128, 192);
601 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
602 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
603 [&](const RGBA8& color) {
604 RGBA8 fac = RGBA8(255, 255, 255, 255) - base;
605 fac.a = 0;
606 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
607 return std::make_pair(TriangleSpec({{color}}), expected);
608 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000609 CheckDstBlendFactor(base, wgpu::BlendFactor::OneMinusDst, wgpu::BlendFactor::Zero, tests);
Yunchao He77752582019-02-16 02:27:30 +0000610}
611
612TEST_P(ColorStateTest, DstBlendFactorDstAlpha) {
613 RGBA8 base(32, 64, 128, 192);
614 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
615 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
616 [&](const RGBA8& color) {
617 RGBA8 fac(base.a, base.a, base.a, base.a);
618 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
619 return std::make_pair(TriangleSpec({{color}}), expected);
620 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000621 CheckDstBlendFactor(base, wgpu::BlendFactor::DstAlpha, wgpu::BlendFactor::DstAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000622}
623
624TEST_P(ColorStateTest, DstBlendFactorOneMinusDstAlpha) {
625 RGBA8 base(32, 64, 128, 192);
626 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
627 std::transform(
628 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
629 RGBA8 fac = RGBA8(255, 255, 255, 255) - RGBA8(base.a, base.a, base.a, base.a);
630 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
631 return std::make_pair(TriangleSpec({{color}}), expected);
632 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000633 CheckDstBlendFactor(base, wgpu::BlendFactor::OneMinusDstAlpha,
634 wgpu::BlendFactor::OneMinusDstAlpha, tests);
Yunchao He77752582019-02-16 02:27:30 +0000635}
636
637TEST_P(ColorStateTest, DstBlendFactorSrcAlphaSaturated) {
638 RGBA8 base(32, 64, 128, 192);
639 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
640 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
641 [&](const RGBA8& color) {
642 uint8_t f = std::min(color.a, static_cast<uint8_t>(255 - base.a));
643 RGBA8 fac(f, f, f, 255);
644 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, fac);
645 return std::make_pair(TriangleSpec({{color}}), expected);
646 });
Corentin Wallezcab352c2019-10-28 13:27:36 +0000647 CheckDstBlendFactor(base, wgpu::BlendFactor::SrcAlphaSaturated,
648 wgpu::BlendFactor::SrcAlphaSaturated, tests);
Yunchao He77752582019-02-16 02:27:30 +0000649}
650
Brandon Jones22b923c2021-04-15 18:34:29 +0000651TEST_P(ColorStateTest, DstBlendFactorConstant) {
Yunchao He77752582019-02-16 02:27:30 +0000652 RGBA8 base(32, 64, 128, 192);
653 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
654 std::transform(
655 kColors.begin(), kColors.end(), std::back_inserter(tests), [&](const RGBA8& color) {
656 auto triangleSpec = TriangleSpec({{color}, {{0.2f, 0.4f, 0.6f, 0.8f}}});
657 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, triangleSpec.blendFactor);
658 return std::make_pair(triangleSpec, expected);
659 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000660 CheckDstBlendFactor(base, wgpu::BlendFactor::Constant, wgpu::BlendFactor::Constant, tests);
Yunchao He77752582019-02-16 02:27:30 +0000661}
662
Brandon Jones22b923c2021-04-15 18:34:29 +0000663TEST_P(ColorStateTest, DstBlendFactorOneMinusConstant) {
Yunchao He77752582019-02-16 02:27:30 +0000664 RGBA8 base(32, 64, 128, 192);
665 std::vector<std::pair<TriangleSpec, RGBA8>> tests;
666 std::transform(kColors.begin(), kColors.end(), std::back_inserter(tests),
667 [&](const RGBA8& color) {
668 auto triangleSpec = TriangleSpec({{color}, {{0.2f, 0.4f, 0.6f, 0.8f}}});
669 std::array<float, 4> f = {{0.8f, 0.6f, 0.4f, 0.2f}};
670 RGBA8 expected = color + mix(RGBA8(0, 0, 0, 0), base, f);
671 return std::make_pair(triangleSpec, expected);
672 });
Brandon Jones22b923c2021-04-15 18:34:29 +0000673 CheckDstBlendFactor(base, wgpu::BlendFactor::OneMinusConstant,
674 wgpu::BlendFactor::OneMinusConstant, tests);
Yunchao He77752582019-02-16 02:27:30 +0000675}
676
677// Check that the color write mask works
678TEST_P(ColorStateTest, ColorWriteMask) {
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000679 wgpu::BlendComponent blendComponent;
680 blendComponent.operation = wgpu::BlendOperation::Add;
681 blendComponent.srcFactor = wgpu::BlendFactor::One;
682 blendComponent.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000683
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000684 wgpu::BlendState blend;
685 blend.color = blendComponent;
686 blend.alpha = blendComponent;
687
688 wgpu::ColorTargetState descriptor;
689 descriptor.blend = &blend;
Yunchao He77752582019-02-16 02:27:30 +0000690 {
691 // Test single channel color write
Corentin Wallezcab352c2019-10-28 13:27:36 +0000692 descriptor.writeMask = wgpu::ColorWriteMask::Red;
Yunchao He77752582019-02-16 02:27:30 +0000693 SetupSingleSourcePipelines(descriptor);
694
695 RGBA8 base(32, 64, 128, 192);
696 for (auto& color : kColors) {
697 RGBA8 expected = base + RGBA8(color.r, 0, 0, 0);
698 DoSingleSourceTest(base, {color}, expected);
699 }
700 }
701
702 {
703 // Test multi channel color write
Corentin Wallezcab352c2019-10-28 13:27:36 +0000704 descriptor.writeMask = wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Alpha;
Yunchao He77752582019-02-16 02:27:30 +0000705 SetupSingleSourcePipelines(descriptor);
706
707 RGBA8 base(32, 64, 128, 192);
708 for (auto& color : kColors) {
709 RGBA8 expected = base + RGBA8(0, color.g, 0, color.a);
710 DoSingleSourceTest(base, {color}, expected);
711 }
712 }
713
714 {
715 // Test no channel color write
Corentin Wallezcab352c2019-10-28 13:27:36 +0000716 descriptor.writeMask = wgpu::ColorWriteMask::None;
Yunchao He77752582019-02-16 02:27:30 +0000717 SetupSingleSourcePipelines(descriptor);
718
719 RGBA8 base(32, 64, 128, 192);
720 for (auto& color : kColors) {
721 DoSingleSourceTest(base, {color}, base);
722 }
723 }
724}
725
726// Check that the color write mask works when blending is disabled
727TEST_P(ColorStateTest, ColorWriteMaskBlendingDisabled) {
728 {
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000729 wgpu::BlendComponent blendComponent;
730 blendComponent.operation = wgpu::BlendOperation::Add;
731 blendComponent.srcFactor = wgpu::BlendFactor::One;
732 blendComponent.dstFactor = wgpu::BlendFactor::Zero;
Yunchao He77752582019-02-16 02:27:30 +0000733
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000734 wgpu::BlendState blend;
735 blend.color = blendComponent;
736 blend.alpha = blendComponent;
737
738 wgpu::ColorTargetState descriptor;
739 descriptor.blend = &blend;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000740 descriptor.writeMask = wgpu::ColorWriteMask::Red;
Yunchao He77752582019-02-16 02:27:30 +0000741 SetupSingleSourcePipelines(descriptor);
742
743 RGBA8 base(32, 64, 128, 192);
744 RGBA8 expected(32, 0, 0, 0);
745
Corentin Wallezcab352c2019-10-28 13:27:36 +0000746 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000747 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000748 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +0000749 pass.SetPipeline(testPipeline);
Corentin Wallez70c8c102019-10-09 16:08:42 +0000750 pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({{base}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000751 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000752 pass.EndPass();
753 }
754
Corentin Wallezcab352c2019-10-28 13:27:36 +0000755 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +0000756 queue.Submit(1, &commands);
757 EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
758 }
759}
760
761// Test that independent color states on render targets works
762TEST_P(ColorStateTest, IndependentColorState) {
Jiawei Shao4589de62021-05-21 02:26:58 +0000763 DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_indexed_draw_buffers"));
Stephen White04218412020-12-07 19:31:03 +0000764
Corentin Wallezcab352c2019-10-28 13:27:36 +0000765 std::array<wgpu::Texture, 4> renderTargets;
766 std::array<wgpu::TextureView, 4> renderTargetViews;
Yunchao He77752582019-02-16 02:27:30 +0000767
Corentin Wallezcab352c2019-10-28 13:27:36 +0000768 wgpu::TextureDescriptor descriptor;
769 descriptor.dimension = wgpu::TextureDimension::e2D;
Yunchao He77752582019-02-16 02:27:30 +0000770 descriptor.size.width = kRTSize;
771 descriptor.size.height = kRTSize;
shrekshaob00de7f2021-03-22 21:12:36 +0000772 descriptor.size.depthOrArrayLayers = 1;
Yunchao He77752582019-02-16 02:27:30 +0000773 descriptor.sampleCount = 1;
Corentin Wallezcab352c2019-10-28 13:27:36 +0000774 descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
Jiawei Shao20301662019-02-21 00:45:19 +0000775 descriptor.mipLevelCount = 1;
Corentin Wallez6b087812020-10-27 15:35:56 +0000776 descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
Yunchao He77752582019-02-16 02:27:30 +0000777
778 for (uint32_t i = 0; i < 4; ++i) {
779 renderTargets[i] = device.CreateTexture(&descriptor);
Kai Ninomiya4078ed82019-08-27 17:56:23 +0000780 renderTargetViews[i] = renderTargets[i].CreateView();
Yunchao He77752582019-02-16 02:27:30 +0000781 }
782
Kai Ninomiya2afea0c2020-07-10 20:33:08 +0000783 utils::ComboRenderPassDescriptor renderPass(
784 {renderTargetViews[0], renderTargetViews[1], renderTargetViews[2], renderTargetViews[3]});
Yunchao He77752582019-02-16 02:27:30 +0000785
Corentin Wallez7aec4ae2021-03-24 15:55:32 +0000786 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
Austin Enge08776a2020-11-13 17:30:59 +0000787 [[block]] struct MyBlock {
Ben Claytonc5686842021-03-17 09:48:19 +0000788 color0 : vec4<f32>;
789 color1 : vec4<f32>;
790 color2 : vec4<f32>;
791 color3 : vec4<f32>;
Austin Enge08776a2020-11-13 17:30:59 +0000792 };
Yunchao He77752582019-02-16 02:27:30 +0000793
dan sinclair0f9c2d72021-01-19 14:18:51 +0000794 [[group(0), binding(0)]] var<uniform> myUbo : MyBlock;
Yunchao He77752582019-02-16 02:27:30 +0000795
Brandon Jonese87ea2b2021-04-14 17:05:07 +0000796 struct FragmentOut {
797 [[location(0)]] fragColor0 : vec4<f32>;
798 [[location(1)]] fragColor1 : vec4<f32>;
799 [[location(2)]] fragColor2 : vec4<f32>;
800 [[location(3)]] fragColor3 : vec4<f32>;
801 };
Austin Enge08776a2020-11-13 17:30:59 +0000802
Brandon Jonese87ea2b2021-04-14 17:05:07 +0000803 [[stage(fragment)]] fn main() -> FragmentOut {
804 var output : FragmentOut;
805 output.fragColor0 = myUbo.color0;
806 output.fragColor1 = myUbo.color1;
807 output.fragColor2 = myUbo.color2;
808 output.fragColor3 = myUbo.color3;
809 return output;
Yunchao He77752582019-02-16 02:27:30 +0000810 }
811 )");
812
Brandon Jones41c87d92021-05-21 05:01:38 +0000813 utils::ComboRenderPipelineDescriptor baseDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000814 baseDescriptor.vertex.module = vsModule;
815 baseDescriptor.cFragment.module = fsModule;
816 baseDescriptor.cFragment.targetCount = 4;
Yunchao He77752582019-02-16 02:27:30 +0000817
Brandon Jones41c87d92021-05-21 05:01:38 +0000818 basePipeline = device.CreateRenderPipeline(&baseDescriptor);
Yunchao He77752582019-02-16 02:27:30 +0000819
Brandon Jones41c87d92021-05-21 05:01:38 +0000820 utils::ComboRenderPipelineDescriptor testDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000821 testDescriptor.vertex.module = vsModule;
822 testDescriptor.cFragment.module = fsModule;
823 testDescriptor.cFragment.targetCount = 4;
Yunchao He77752582019-02-16 02:27:30 +0000824
825 // set color states
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000826 wgpu::BlendComponent blendComponent0;
827 blendComponent0.operation = wgpu::BlendOperation::Add;
828 blendComponent0.srcFactor = wgpu::BlendFactor::One;
829 blendComponent0.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000830
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000831 wgpu::BlendState blend0;
832 blend0.color = blendComponent0;
833 blend0.alpha = blendComponent0;
Yunchao He77752582019-02-16 02:27:30 +0000834
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000835 wgpu::BlendComponent blendComponent1;
836 blendComponent1.operation = wgpu::BlendOperation::Subtract;
837 blendComponent1.srcFactor = wgpu::BlendFactor::One;
838 blendComponent1.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000839
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000840 wgpu::BlendState blend1;
841 blend1.color = blendComponent1;
842 blend1.alpha = blendComponent1;
Yunchao He77752582019-02-16 02:27:30 +0000843
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000844 // Blend state intentionally omitted for target 2
Yunchao He77752582019-02-16 02:27:30 +0000845
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000846 wgpu::BlendDescriptor blendComponent3;
847 blendComponent3.operation = wgpu::BlendOperation::Min;
848 blendComponent3.srcFactor = wgpu::BlendFactor::One;
849 blendComponent3.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000850
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000851 wgpu::BlendState blend3;
852 blend3.color = blendComponent3;
853 blend3.alpha = blendComponent3;
854
855 testDescriptor.cTargets[0].blend = &blend0;
856 testDescriptor.cTargets[1].blend = &blend1;
857 testDescriptor.cTargets[3].blend = &blend3;
858
Brandon Jones41c87d92021-05-21 05:01:38 +0000859 testPipeline = device.CreateRenderPipeline(&testDescriptor);
Yunchao He77752582019-02-16 02:27:30 +0000860
861 for (unsigned int c = 0; c < kColors.size(); ++c) {
862 RGBA8 base = kColors[((c + 31) * 29) % kColors.size()];
863 RGBA8 color0 = kColors[((c + 19) * 13) % kColors.size()];
864 RGBA8 color1 = kColors[((c + 11) * 43) % kColors.size()];
865 RGBA8 color2 = kColors[((c + 7) * 3) % kColors.size()];
866 RGBA8 color3 = kColors[((c + 13) * 71) % kColors.size()];
867
868 RGBA8 expected0 = color0 + base;
869 RGBA8 expected1 = color1 - base;
870 RGBA8 expected2 = color2;
871 RGBA8 expected3 = min(color3, base);
872
Corentin Wallezcab352c2019-10-28 13:27:36 +0000873 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000874 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000875 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
Yunchao He77752582019-02-16 02:27:30 +0000876 pass.SetPipeline(basePipeline);
877 pass.SetBindGroup(
Corentin Wallez70c8c102019-10-09 16:08:42 +0000878 0, MakeBindGroupForColors(std::array<RGBA8, 4>({{base, base, base, base}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000879 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000880
881 pass.SetPipeline(testPipeline);
882 pass.SetBindGroup(0, MakeBindGroupForColors(
Corentin Wallez70c8c102019-10-09 16:08:42 +0000883 std::array<RGBA8, 4>({{color0, color1, color2, color3}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000884 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000885 pass.EndPass();
886 }
887
Corentin Wallezcab352c2019-10-28 13:27:36 +0000888 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +0000889 queue.Submit(1, &commands);
890
891 EXPECT_PIXEL_RGBA8_EQ(expected0, renderTargets[0], kRTSize / 2, kRTSize / 2)
892 << "Attachment slot 0 should have been " << color0 << " + " << base << " = "
893 << expected0;
894 EXPECT_PIXEL_RGBA8_EQ(expected1, renderTargets[1], kRTSize / 2, kRTSize / 2)
895 << "Attachment slot 1 should have been " << color1 << " - " << base << " = "
896 << expected1;
897 EXPECT_PIXEL_RGBA8_EQ(expected2, renderTargets[2], kRTSize / 2, kRTSize / 2)
898 << "Attachment slot 2 should have been " << color2 << " = " << expected2
899 << "(no blending)";
900 EXPECT_PIXEL_RGBA8_EQ(expected3, renderTargets[3], kRTSize / 2, kRTSize / 2)
901 << "Attachment slot 3 should have been min(" << color3 << ", " << base
902 << ") = " << expected3;
903 }
904}
905
906// Test that the default blend color is correctly set at the beginning of every subpass
907TEST_P(ColorStateTest, DefaultBlendColor) {
Corentin Wallez7aec4ae2021-03-24 15:55:32 +0000908 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
Austin Enge08776a2020-11-13 17:30:59 +0000909 [[block]] struct MyBlock {
Ben Claytonc5686842021-03-17 09:48:19 +0000910 color : vec4<f32>;
Austin Enge08776a2020-11-13 17:30:59 +0000911 };
Yunchao He77752582019-02-16 02:27:30 +0000912
dan sinclair0f9c2d72021-01-19 14:18:51 +0000913 [[group(0), binding(0)]] var<uniform> myUbo : MyBlock;
Yunchao He77752582019-02-16 02:27:30 +0000914
Brandon Jonese87ea2b2021-04-14 17:05:07 +0000915 [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
916 return myUbo.color;
Yunchao He77752582019-02-16 02:27:30 +0000917 }
918 )");
919
Brandon Jones41c87d92021-05-21 05:01:38 +0000920 utils::ComboRenderPipelineDescriptor baseDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000921 baseDescriptor.vertex.module = vsModule;
922 baseDescriptor.cFragment.module = fsModule;
923 baseDescriptor.cTargets[0].format = renderPass.colorFormat;
Yunchao He77752582019-02-16 02:27:30 +0000924
Brandon Jones41c87d92021-05-21 05:01:38 +0000925 basePipeline = device.CreateRenderPipeline(&baseDescriptor);
Yunchao He77752582019-02-16 02:27:30 +0000926
Brandon Jones41c87d92021-05-21 05:01:38 +0000927 utils::ComboRenderPipelineDescriptor testDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000928 testDescriptor.vertex.module = vsModule;
929 testDescriptor.cFragment.module = fsModule;
930 testDescriptor.cTargets[0].format = renderPass.colorFormat;
Yunchao He77752582019-02-16 02:27:30 +0000931
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000932 wgpu::BlendComponent blendComponent;
933 blendComponent.operation = wgpu::BlendOperation::Add;
Brandon Jones22b923c2021-04-15 18:34:29 +0000934 blendComponent.srcFactor = wgpu::BlendFactor::Constant;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000935 blendComponent.dstFactor = wgpu::BlendFactor::One;
Yunchao He77752582019-02-16 02:27:30 +0000936
Brandon Jonesbff9d3a2021-03-18 02:54:27 +0000937 wgpu::BlendState blend;
938 blend.color = blendComponent;
939 blend.alpha = blendComponent;
940
941 testDescriptor.cTargets[0].blend = &blend;
942
Brandon Jones41c87d92021-05-21 05:01:38 +0000943 testPipeline = device.CreateRenderPipeline(&testDescriptor);
Corentin Wallezcab352c2019-10-28 13:27:36 +0000944 constexpr wgpu::Color kWhite{1.0f, 1.0f, 1.0f, 1.0f};
Yunchao He77752582019-02-16 02:27:30 +0000945
946 // Check that the initial blend color is (0,0,0,0)
947 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000948 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000949 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000950 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +0000951 pass.SetPipeline(basePipeline);
952 pass.SetBindGroup(0,
Corentin Wallez70c8c102019-10-09 16:08:42 +0000953 MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(0, 0, 0, 0)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000954 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000955 pass.SetPipeline(testPipeline);
956 pass.SetBindGroup(
Corentin Wallez70c8c102019-10-09 16:08:42 +0000957 0, MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(255, 255, 255, 255)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000958 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000959 pass.EndPass();
960 }
961
Corentin Wallezcab352c2019-10-28 13:27:36 +0000962 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +0000963 queue.Submit(1, &commands);
964
965 EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
966 }
967
968 // Check that setting the blend color works
969 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000970 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000971 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000972 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +0000973 pass.SetPipeline(basePipeline);
974 pass.SetBindGroup(0,
Corentin Wallez70c8c102019-10-09 16:08:42 +0000975 MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(0, 0, 0, 0)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000976 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000977 pass.SetPipeline(testPipeline);
Brandon Jones413dcf82021-04-15 19:33:58 +0000978 pass.SetBlendConstant(&kWhite);
Yunchao He77752582019-02-16 02:27:30 +0000979 pass.SetBindGroup(
Corentin Wallez70c8c102019-10-09 16:08:42 +0000980 0, MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(255, 255, 255, 255)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +0000981 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +0000982 pass.EndPass();
983 }
984
Corentin Wallezcab352c2019-10-28 13:27:36 +0000985 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +0000986 queue.Submit(1, &commands);
987
988 EXPECT_PIXEL_RGBA8_EQ(RGBA8(255, 255, 255, 255), renderPass.color, kRTSize / 2,
989 kRTSize / 2);
990 }
991
992 // Check that the blend color is not inherited between render passes
993 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000994 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He77752582019-02-16 02:27:30 +0000995 {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000996 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +0000997 pass.SetPipeline(basePipeline);
998 pass.SetBindGroup(0,
Corentin Wallez70c8c102019-10-09 16:08:42 +0000999 MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(0, 0, 0, 0)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +00001000 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +00001001 pass.SetPipeline(testPipeline);
Brandon Jones413dcf82021-04-15 19:33:58 +00001002 pass.SetBlendConstant(&kWhite);
Yunchao He77752582019-02-16 02:27:30 +00001003 pass.SetBindGroup(
Corentin Wallez70c8c102019-10-09 16:08:42 +00001004 0, MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(255, 255, 255, 255)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +00001005 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +00001006 pass.EndPass();
1007 }
1008 {
Corentin Wallezcab352c2019-10-28 13:27:36 +00001009 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Yunchao He77752582019-02-16 02:27:30 +00001010 pass.SetPipeline(basePipeline);
1011 pass.SetBindGroup(0,
Corentin Wallez70c8c102019-10-09 16:08:42 +00001012 MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(0, 0, 0, 0)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +00001013 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +00001014 pass.SetPipeline(testPipeline);
1015 pass.SetBindGroup(
Corentin Wallez70c8c102019-10-09 16:08:42 +00001016 0, MakeBindGroupForColors(std::array<RGBA8, 1>({{RGBA8(255, 255, 255, 255)}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +00001017 pass.Draw(3);
Yunchao He77752582019-02-16 02:27:30 +00001018 pass.EndPass();
1019 }
1020
Corentin Wallezcab352c2019-10-28 13:27:36 +00001021 wgpu::CommandBuffer commands = encoder.Finish();
Yunchao He77752582019-02-16 02:27:30 +00001022 queue.Submit(1, &commands);
1023
1024 EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
1025 }
1026}
1027
Austin Engbff933a2019-04-12 17:43:05 +00001028// This tests a problem in the OpenGL backend where a previous color write mask
1029// persisted and prevented a render pass loadOp from fully clearing the output
1030// attachment.
1031TEST_P(ColorStateTest, ColorWriteMaskDoesNotAffectRenderPassLoadOpClear) {
Corentin Wallez7aec4ae2021-03-24 15:55:32 +00001032 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
Austin Enge08776a2020-11-13 17:30:59 +00001033 [[block]] struct MyBlock {
Ben Claytonc5686842021-03-17 09:48:19 +00001034 color : vec4<f32>;
Austin Enge08776a2020-11-13 17:30:59 +00001035 };
Austin Engbff933a2019-04-12 17:43:05 +00001036
dan sinclair0f9c2d72021-01-19 14:18:51 +00001037 [[group(0), binding(0)]] var<uniform> myUbo : MyBlock;
Austin Engbff933a2019-04-12 17:43:05 +00001038
Brandon Jonese87ea2b2021-04-14 17:05:07 +00001039 [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
1040 return myUbo.color;
Austin Engbff933a2019-04-12 17:43:05 +00001041 }
1042 )");
1043
Brandon Jones41c87d92021-05-21 05:01:38 +00001044 utils::ComboRenderPipelineDescriptor baseDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +00001045 baseDescriptor.vertex.module = vsModule;
1046 baseDescriptor.cFragment.module = fsModule;
1047 baseDescriptor.cTargets[0].format = renderPass.colorFormat;
Austin Engbff933a2019-04-12 17:43:05 +00001048
Brandon Jones41c87d92021-05-21 05:01:38 +00001049 basePipeline = device.CreateRenderPipeline(&baseDescriptor);
Austin Engbff933a2019-04-12 17:43:05 +00001050
Brandon Jones41c87d92021-05-21 05:01:38 +00001051 utils::ComboRenderPipelineDescriptor testDescriptor;
Brandon Jonesbff9d3a2021-03-18 02:54:27 +00001052 testDescriptor.vertex.module = vsModule;
1053 testDescriptor.cFragment.module = fsModule;
1054 testDescriptor.cTargets[0].format = renderPass.colorFormat;
1055 testDescriptor.cTargets[0].writeMask = wgpu::ColorWriteMask::Red;
Austin Engbff933a2019-04-12 17:43:05 +00001056
Brandon Jones41c87d92021-05-21 05:01:38 +00001057 testPipeline = device.CreateRenderPipeline(&testDescriptor);
Austin Engbff933a2019-04-12 17:43:05 +00001058
1059 RGBA8 base(32, 64, 128, 192);
1060 RGBA8 expected(0, 0, 0, 0);
1061
Corentin Wallezcab352c2019-10-28 13:27:36 +00001062 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Austin Engbff933a2019-04-12 17:43:05 +00001063 {
Corentin Wallez49a1f722021-01-22 19:51:37 +00001064 // Clear the render attachment to |base|
Corentin Wallezcab352c2019-10-28 13:27:36 +00001065 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Austin Engbff933a2019-04-12 17:43:05 +00001066 pass.SetPipeline(basePipeline);
Corentin Wallez70c8c102019-10-09 16:08:42 +00001067 pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({{base}})));
Corentin Wallez67b1ad72020-03-31 16:21:35 +00001068 pass.Draw(3);
Austin Engbff933a2019-04-12 17:43:05 +00001069
1070 // Set a pipeline that will dirty the color write mask
1071 pass.SetPipeline(testPipeline);
1072 pass.EndPass();
1073 }
1074 {
Corentin Wallez49a1f722021-01-22 19:51:37 +00001075 // This renderpass' loadOp should clear all channels of the render attachment
Corentin Wallezcab352c2019-10-28 13:27:36 +00001076 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
Austin Engbff933a2019-04-12 17:43:05 +00001077 pass.EndPass();
1078 }
Corentin Wallezcab352c2019-10-28 13:27:36 +00001079 wgpu::CommandBuffer commands = encoder.Finish();
Austin Engbff933a2019-04-12 17:43:05 +00001080 queue.Submit(1, &commands);
1081
1082 EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
1083}
1084
Kai Ninomiya2afea0c2020-07-10 20:33:08 +00001085DAWN_INSTANTIATE_TEST(ColorStateTest,
1086 D3D12Backend(),
1087 MetalBackend(),
1088 OpenGLBackend(),
Stephen Whiteab59a102020-12-01 18:37:19 +00001089 OpenGLESBackend(),
Kai Ninomiya2afea0c2020-07-10 20:33:08 +00001090 VulkanBackend());