Skip to content

Commit

Permalink
op: Implement 'default_blend_color,initial_blend_color' test in blend…
Browse files Browse the repository at this point in the history
…ing.spec.ts (#1980)

This PR implements a new test to ensure the initial blending color is correctly
set at the beginning of every sub-pass.

Issue: #1835
  • Loading branch information
Gyuyoung authored Nov 10, 2022
1 parent 7fbc3b6 commit aa6489b
Showing 1 changed file with 132 additions and 2 deletions.
134 changes: 132 additions & 2 deletions src/webgpu/api/operation/rendering/blending.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ TODO:
`;

import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { assert, unreachable } from '../../../../common/util/util.js';
import { assert, TypedArrayBufferView, unreachable } from '../../../../common/util/util.js';
import {
kBlendFactors,
kBlendOperations,
Expand All @@ -20,7 +20,71 @@ import { float32ToFloat16Bits } from '../../../util/conversion.js';
import { TexelView } from '../../../util/texture/texel_view.js';
import { textureContentIsOKByT2B } from '../../../util/texture/texture_ok.js';

export const g = makeTestGroup(GPUTest);
class BlendingTest extends GPUTest {
createRenderPipelineForTest(
colorTargetState: GPUColorTargetState,
blendComponent: GPUBlendComponent | undefined
): GPURenderPipeline {
return this.device.createRenderPipeline({
layout: 'auto',
fragment: {
targets: [
{
format: colorTargetState.format,
blend: {
color: blendComponent ?? {},
alpha: blendComponent ?? {},
},
},
],
module: this.device.createShaderModule({
code: `
struct Params {
color : vec4<f32>
}
@group(0) @binding(0) var<uniform> params : Params;
@fragment fn main() -> @location(0) vec4<f32> {
return params.color;
}
`,
}),
entryPoint: 'main',
},
vertex: {
module: this.device.createShaderModule({
code: `
@vertex fn main(
@builtin(vertex_index) VertexIndex : u32
) -> @builtin(position) vec4<f32> {
var pos = array<vec2<f32>, 3>(
vec2<f32>(-1.0, -1.0),
vec2<f32>(3.0, -1.0),
vec2<f32>(-1.0, 3.0));
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
}
`,
}),
entryPoint: 'main',
},
});
}

createBindGroupForTest(layout: GPUBindGroupLayout, data: TypedArrayBufferView): GPUBindGroup {
return this.device.createBindGroup({
layout,
entries: [
{
binding: 0,
resource: {
buffer: this.makeBufferWithContents(data, GPUBufferUsage.UNIFORM),
},
},
],
});
}
}

export const g = makeTestGroup(BlendingTest);

function mapColor(
col: GPUColorDict,
Expand Down Expand Up @@ -372,6 +436,72 @@ g.test('formats')
t.expectOK(result);
});

g.test('default_blend_constant,initial_blend_constant')
.desc(`Test that the blend constant is set to [0,0,0,0] at the beginning of a pass.`)
.fn(async t => {
const format = 'rgba8unorm';
const kSize = 1;
const kWhiteColorData = new Float32Array([255, 255, 255, 255]);
const kBlackColorData = new Float32Array([0, 0, 0, 0]);

const basePipeline = t.createRenderPipelineForTest({ format }, undefined);
const testPipeline = t.createRenderPipelineForTest(
{ format },
{
srcFactor: 'constant',
dstFactor: 'one',
operation: 'add',
}
);

const renderTarget = t.device.createTexture({
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
size: [kSize, kSize],
format,
});

const commandEncoder = t.device.createCommandEncoder();
const renderPass = commandEncoder.beginRenderPass({
colorAttachments: [
{
view: renderTarget.createView(),
loadOp: 'load',
storeOp: 'store',
},
],
});
renderPass.setPipeline(basePipeline);
renderPass.setBindGroup(
0,
t.createBindGroupForTest(basePipeline.getBindGroupLayout(0), kBlackColorData)
);
renderPass.setPipeline(testPipeline);
renderPass.setBindGroup(
0,
t.createBindGroupForTest(testPipeline.getBindGroupLayout(0), kWhiteColorData)
);
renderPass.draw(3);
// Draw [1,1,1,1] with `src * constant + dst * 1`.
// The blend constant defaults to [0,0,0,0], so the result is
// `[1,1,1,1] * [0,0,0,0] + [0,0,0,0] * 1` = [0,0,0,0].
renderPass.end();
t.device.queue.submit([commandEncoder.finish()]);

// Check that the initial blend color is black(0,0,0,0) after setting testPipeline which has
// a white color buffer data.
const expColor = { R: 0, G: 0, B: 0, A: 0 };
const expTexelView = TexelView.fromTexelsAsColors(format, coords => expColor);

const result = await textureContentIsOKByT2B(
t,
{ texture: renderTarget },
[kSize, kSize],
{ expTexelView },
{ maxDiffULPsForNormFormat: 1 }
);
t.expectOK(result);
});

g.test('clamp,blend_factor')
.desc('For fixed-point formats, test that the blend factor is clamped in the blend equation.')
.unimplemented();
Expand Down

0 comments on commit aa6489b

Please sign in to comment.