@@ -214,37 +214,30 @@ uint32_t EntityPass::GetTotalPassReads(ContentContext& renderer) const {
214
214
215
215
bool EntityPass::Render (ContentContext& renderer,
216
216
const RenderTarget& render_target) const {
217
- if (render_target.GetColorAttachments ().empty ()) {
218
- VALIDATION_LOG << " The root RenderTarget must have a color attachment." ;
219
- return false ;
220
- }
221
-
222
- if (!render_target.GetStencilAttachment ().has_value ()) {
223
- VALIDATION_LOG << " The root RenderTarget must have a stencil attachment." ;
224
- return false ;
225
- }
217
+ auto root_render_target = render_target;
226
218
227
- auto stencil_texture = render_target.GetStencilAttachment ()->texture ;
228
- if (!stencil_texture) {
229
- VALIDATION_LOG << " The root RenderTarget must have a stencil texture." ;
219
+ if (root_render_target.GetColorAttachments ().empty ()) {
220
+ VALIDATION_LOG << " The root RenderTarget must have a color attachment." ;
230
221
return false ;
231
222
}
232
223
233
224
StencilCoverageStack stencil_coverage_stack = {StencilCoverageLayer{
234
- .coverage = Rect::MakeSize (render_target .GetRenderTargetSize ()),
225
+ .coverage = Rect::MakeSize (root_render_target .GetRenderTargetSize ()),
235
226
.stencil_depth = 0 }};
236
227
237
- bool supports_root_pass_reads =
228
+ bool supports_onscreen_backdrop_reads =
238
229
renderer.GetDeviceCapabilities ().SupportsReadFromOnscreenTexture () &&
239
230
// If the backend doesn't have `SupportsReadFromResolve`, we need to flip
240
231
// between two textures when restoring a previous MSAA pass.
241
- renderer.GetDeviceCapabilities ().SupportsReadFromResolve () &&
242
- stencil_texture->GetTextureDescriptor ().storage_mode !=
243
- StorageMode::kDeviceTransient ;
244
- if (!supports_root_pass_reads && GetTotalPassReads (renderer) > 0 ) {
232
+ renderer.GetDeviceCapabilities ().SupportsReadFromResolve ();
233
+ bool reads_from_onscreen_backdrop = GetTotalPassReads (renderer) > 0 ;
234
+ // In this branch path, we need to render everything to an offscreen texture
235
+ // and then blit the results onto the onscreen texture. If using this branch,
236
+ // there's no need to set up a stencil attachment on the root render target.
237
+ if (!supports_onscreen_backdrop_reads && reads_from_onscreen_backdrop) {
245
238
auto offscreen_target =
246
- CreateRenderTarget (renderer, render_target .GetRenderTargetSize (), true ,
247
- clear_color_.Premultiply ());
239
+ CreateRenderTarget (renderer, root_render_target .GetRenderTargetSize (),
240
+ true , clear_color_.Premultiply ());
248
241
249
242
if (!OnRender (renderer, // renderer
250
243
offscreen_target.GetRenderTarget ()
@@ -263,22 +256,25 @@ bool EntityPass::Render(ContentContext& renderer,
263
256
auto command_buffer = renderer.GetContext ()->CreateCommandBuffer ();
264
257
command_buffer->SetLabel (" EntityPass Root Command Buffer" );
265
258
259
+ // If the context supports blitting, blit the offscreen texture to the
260
+ // onscreen texture. Otherwise, draw it to the parent texture using a
261
+ // pipeline (slower).
266
262
if (renderer.GetContext ()
267
263
->GetCapabilities ()
268
264
->SupportsTextureToTextureBlits ()) {
269
265
auto blit_pass = command_buffer->CreateBlitPass ();
270
266
271
267
blit_pass->AddCopy (
272
268
offscreen_target.GetRenderTarget ().GetRenderTargetTexture (),
273
- render_target .GetRenderTargetTexture ());
269
+ root_render_target .GetRenderTargetTexture ());
274
270
275
271
if (!blit_pass->EncodeCommands (
276
272
renderer.GetContext ()->GetResourceAllocator ())) {
277
273
VALIDATION_LOG << " Failed to encode root pass blit command." ;
278
274
return false ;
279
275
}
280
276
} else {
281
- auto render_pass = command_buffer->CreateRenderPass (render_target );
277
+ auto render_pass = command_buffer->CreateRenderPass (root_render_target );
282
278
render_pass->SetLabel (" EntityPass Root Render Pass" );
283
279
284
280
{
@@ -309,11 +305,43 @@ bool EntityPass::Render(ContentContext& renderer,
309
305
return true ;
310
306
}
311
307
308
+ // If we make it this far, that means the context is capable of rendering
309
+ // everything directly to the onscreen texture.
310
+
311
+ // The safety check for fetching this color attachment is at the beginning of
312
+ // this method.
313
+ auto color0 = root_render_target.GetColorAttachments ().find (0 )->second ;
314
+
315
+ // If a root stencil was provided by the caller, then verify that it has a
316
+ // configuration which can be used to render this pass.
317
+ if (root_render_target.GetStencilAttachment ().has_value ()) {
318
+ auto stencil_texture = root_render_target.GetStencilAttachment ()->texture ;
319
+ if (!stencil_texture) {
320
+ VALIDATION_LOG << " The root RenderTarget must have a stencil texture." ;
321
+ return false ;
322
+ }
323
+
324
+ auto stencil_storage_mode =
325
+ stencil_texture->GetTextureDescriptor ().storage_mode ;
326
+ if (reads_from_onscreen_backdrop &&
327
+ stencil_storage_mode == StorageMode::kDeviceTransient ) {
328
+ VALIDATION_LOG << " The given root RenderTarget stencil needs to be read, "
329
+ " but it's marked as transient." ;
330
+ return false ;
331
+ }
332
+ }
333
+ // Setup a new root stencil with an optimal configuration if one wasn't
334
+ // provided by the caller.
335
+ else {
336
+ root_render_target.SetupStencilAttachment (
337
+ *renderer.GetContext (), color0.texture ->GetSize (),
338
+ renderer.GetContext ()->GetCapabilities ()->SupportsOffscreenMSAA (),
339
+ " ImpellerOnscreen" ,
340
+ GetDefaultStencilConfig (reads_from_onscreen_backdrop));
341
+ }
342
+
312
343
// Set up the clear color of the root pass.
313
- auto color0 = render_target.GetColorAttachments ().find (0 )->second ;
314
344
color0.clear_color = clear_color_.Premultiply ();
315
-
316
- auto root_render_target = render_target;
317
345
root_render_target.SetColorAttachment (color0, 0 );
318
346
319
347
EntityPassTarget pass_target (
0 commit comments