Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fbf8c46

Browse files
authored
[Flutter GPU] Add setStencilReference to RenderPass. (#55270)
1 parent 34878d9 commit fbf8c46

4 files changed

Lines changed: 92 additions & 18 deletions

File tree

lib/gpu/lib/src/render_pass.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ base class RenderPass extends NativeFieldWrapperClass1 {
212212
_setDepthCompareOperation(compareFunction.index);
213213
}
214214

215+
void setStencilReference(int referenceValue) {
216+
if (referenceValue < 0 || referenceValue > 0xFFFFFFFF) {
217+
throw Exception(
218+
"The stencil reference value must be in the range [0, 2^32 - 1]");
219+
}
220+
_setStencilReference(referenceValue);
221+
}
222+
215223
void draw() {
216224
if (!_draw()) {
217225
throw Exception("Failed to append draw");
@@ -335,6 +343,10 @@ base class RenderPass extends NativeFieldWrapperClass1 {
335343
symbol: 'InternalFlutterGpu_RenderPass_SetDepthCompareOperation')
336344
external void _setDepthCompareOperation(int compareOperation);
337345

346+
@Native<Void Function(Pointer<Void>, Int)>(
347+
symbol: 'InternalFlutterGpu_RenderPass_SetStencilReference')
348+
external void _setStencilReference(int referenceValue);
349+
338350
@Native<Bool Function(Pointer<Void>)>(
339351
symbol: 'InternalFlutterGpu_RenderPass_Draw')
340352
external bool _draw();

lib/gpu/render_pass.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,13 @@ void InternalFlutterGpu_RenderPass_SetDepthCompareOperation(
511511
flutter::gpu::ToImpellerCompareFunction(compare_operation);
512512
}
513513

514+
void InternalFlutterGpu_RenderPass_SetStencilReference(
515+
flutter::gpu::RenderPass* wrapper,
516+
int stencil_reference) {
517+
auto& command = wrapper->GetCommand();
518+
command.stencil_reference = static_cast<uint32_t>(stencil_reference);
519+
}
520+
514521
bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) {
515522
return wrapper->Draw();
516523
}

lib/gpu/render_pass.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ extern void InternalFlutterGpu_RenderPass_SetDepthCompareOperation(
221221
flutter::gpu::RenderPass* wrapper,
222222
int compare_operation);
223223

224+
FLUTTER_GPU_EXPORT
225+
extern void InternalFlutterGpu_RenderPass_SetStencilReference(
226+
flutter::gpu::RenderPass* wrapper,
227+
int stencil_reference);
228+
224229
FLUTTER_GPU_EXPORT
225230
extern bool InternalFlutterGpu_RenderPass_Draw(
226231
flutter::gpu::RenderPass* wrapper);

testing/dart/gpu_test.dart

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,37 @@ gpu.RenderPipeline createUnlitRenderPipeline() {
3232
return gpu.gpuContext.createRenderPipeline(vertex!, fragment!);
3333
}
3434

35+
class RenderPassState {
36+
RenderPassState(this.renderTexture, this.commandBuffer, this.renderPass);
37+
38+
final gpu.Texture renderTexture;
39+
final gpu.CommandBuffer commandBuffer;
40+
final gpu.RenderPass renderPass;
41+
}
42+
43+
/// Create a simple RenderPass with simple color and depth-stencil attachments.
44+
RenderPassState createSimpleRenderPass() {
45+
final gpu.Texture? renderTexture =
46+
gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100);
47+
assert(renderTexture != null);
48+
49+
final gpu.Texture? depthStencilTexture = gpu.gpuContext.createTexture(
50+
gpu.StorageMode.deviceTransient, 100, 100,
51+
format: gpu.gpuContext.defaultDepthStencilFormat);
52+
53+
final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer();
54+
55+
final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor(
56+
gpu.ColorAttachment(texture: renderTexture!),
57+
depthStencilAttachment:
58+
gpu.DepthStencilAttachment(texture: depthStencilTexture!));
59+
60+
final gpu.RenderPass renderPass =
61+
commandBuffer.createRenderPass(renderTarget);
62+
63+
return RenderPassState(renderTexture, commandBuffer, renderPass);
64+
}
65+
3566
void main() async {
3667
final ImageComparer comparer = await ImageComparer.create();
3768

@@ -203,25 +234,44 @@ void main() async {
203234
}
204235
}, skip: !impellerEnabled);
205236

206-
test('Can render triangle', () async {
207-
final gpu.Texture? renderTexture =
208-
gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100);
209-
assert(renderTexture != null);
237+
test('RenderPass.setStencilReference doesnt throw for valid values',
238+
() async {
239+
final state = createSimpleRenderPass();
210240

211-
final gpu.CommandBuffer commandBuffer =
212-
gpu.gpuContext.createCommandBuffer();
241+
state.renderPass.setStencilReference(0);
242+
state.renderPass.setStencilReference(2 << 30);
243+
}, skip: !impellerEnabled);
213244

214-
final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor(
215-
gpu.ColorAttachment(texture: renderTexture!),
216-
);
217-
final gpu.RenderPass encoder = commandBuffer.createRenderPass(renderTarget);
245+
test('RenderPass.setStencilReference throws for invalid values', () async {
246+
final state = createSimpleRenderPass();
247+
248+
try {
249+
state.renderPass.setStencilReference(-1);
250+
fail('Exception not thrown for out of bounds stencil reference.');
251+
} catch (e) {
252+
expect(e.toString(),
253+
contains('The stencil reference value must be in the range'));
254+
}
255+
256+
try {
257+
state.renderPass.setStencilReference(2 << 31);
258+
fail('Exception not thrown for out of bounds stencil reference.');
259+
} catch (e) {
260+
expect(e.toString(),
261+
contains('The stencil reference value must be in the range'));
262+
}
263+
}, skip: !impellerEnabled);
264+
265+
// Renders a green triangle pointing downwards.
266+
test('Can render triangle', () async {
267+
final state = createSimpleRenderPass();
218268

219269
final gpu.RenderPipeline pipeline = createUnlitRenderPipeline();
220-
encoder.bindPipeline(pipeline);
270+
state.renderPass.bindPipeline(pipeline);
221271

222272
// Configure blending with defaults (just to test the bindings).
223-
encoder.setColorBlendEnable(true);
224-
encoder.setColorBlendEquation(gpu.ColorBlendEquation());
273+
state.renderPass.setColorBlendEnable(true);
274+
state.renderPass.setColorBlendEquation(gpu.ColorBlendEquation());
225275

226276
final gpu.HostBuffer transients = gpu.gpuContext.createHostBuffer();
227277
final gpu.BufferView vertices = transients.emplace(float32(<double>[
@@ -236,16 +286,16 @@ void main() async {
236286
0, 0, 0, 1, // mvp
237287
0, 1, 0, 1, // color
238288
]));
239-
encoder.bindVertexBuffer(vertices, 3);
289+
state.renderPass.bindVertexBuffer(vertices, 3);
240290

241291
final gpu.UniformSlot vertInfo =
242292
pipeline.vertexShader.getUniformSlot('VertInfo');
243-
encoder.bindUniform(vertInfo, vertInfoData);
244-
encoder.draw();
293+
state.renderPass.bindUniform(vertInfo, vertInfoData);
294+
state.renderPass.draw();
245295

246-
commandBuffer.submit();
296+
state.commandBuffer.submit();
247297

248-
final ui.Image image = renderTexture.asImage();
298+
final ui.Image image = state.renderTexture.asImage();
249299
await comparer.addGoldenImage(image, 'flutter_gpu_test_triangle.png');
250300
}, skip: !impellerEnabled);
251301
}

0 commit comments

Comments
 (0)