Skip to content

Commit

Permalink
viz: win: Allocate root surface in SkiaRenderer
Browse files Browse the repository at this point in the history
This CL moves the allocation of the root surface from the output device
to the renderer. SkiaOutputDeviceDCompPresenter now supports
renderer_allocates_images. However, it will not use buffer queue,
since both DXGI swap chains and DComp surfaces internally handle
cross-frame damage and buffer management.

Bug: 1378741
Change-Id: Iaf7641f97a8eed075fb7d120b1a6c89d994d815a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4205034
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com>
Commit-Queue: Michael Tang <tangm@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1120881}
  • Loading branch information
tangm-msft authored and Chromium LUCI CQ committed Mar 22, 2023
1 parent ecf0888 commit e3ca4df
Show file tree
Hide file tree
Showing 20 changed files with 475 additions and 833 deletions.
7 changes: 7 additions & 0 deletions components/viz/common/quads/aggregated_render_pass.h
Expand Up @@ -98,6 +98,13 @@ class VIZ_COMMON_EXPORT AggregatedRenderPass : public RenderPassInternal {
// Indicates current RenderPass is a color conversion pass.
bool is_color_conversion_pass = false;

// Windows only: Indicates that the render pass backing's updates need to be
// synchronized with tree updates. A swap chain does not synchronize its
// presents with DComp commits. This is needed when e.g. the render pass has
// video holes that need to line up with other overlays or is itself presented
// as an overlay.
bool needs_synchronous_dcomp_commit = false;

void AsValueInto(base::trace_event::TracedValue* dict) const;

private:
Expand Down
1 change: 0 additions & 1 deletion components/viz/service/BUILD.gn
Expand Up @@ -571,7 +571,6 @@ viz_source_set("unit_tests") {
sources += [
"display/overlay_dc_unittest.cc",
"display_embedder/output_device_backing_unittest.cc",
"display_embedder/skia_output_device_dcomp_unittest.cc",
"display_embedder/software_output_device_win_unittest.cc",
]

Expand Down
93 changes: 62 additions & 31 deletions components/viz/service/display/direct_renderer.cc
Expand Up @@ -189,28 +189,20 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
base::flat_map<AggregatedRenderPassId, RenderPassRequirements>
render_passes_in_frame;
for (const auto& pass : render_passes_in_draw_order) {
if (pass == root_render_pass) {
// Requirements for the root render pass are communicated in
// AllocateRenderPassResourceIfNeeded().
continue;
}

// If there's a copy request, we need an explicit renderpass backing so
// only try to draw directly if there are no copy requests.
if (pass->copy_requests.empty()) {
bool is_root = pass == root_render_pass;
if (!is_root && pass->copy_requests.empty()) {
if (const DrawQuad* quad = CanPassBeDrawnDirectly(pass.get())) {
// If the render pass is drawn directly, it will not be drawn from as
// a render pass so it's not added to the map.
render_pass_bypass_quads_[pass->id] = quad;
continue;
}
}
gfx::Size size = CalculateTextureSizeForRenderPass(pass.get());
auto color_space = RenderPassColorSpace(pass.get());
auto format = GetColorSpaceResourceFormat(color_space);

render_passes_in_frame[pass->id] = {size, pass->generate_mipmap, format,
color_space};
render_passes_in_frame[pass->id] =
CalculateRenderPassRequirements(pass.get());
}
UMA_HISTOGRAM_COUNTS_1000(
"Compositing.Display.FlattenedRenderPassCount",
Expand Down Expand Up @@ -262,11 +254,6 @@ void DirectRenderer::DrawFrame(
current_frame()->device_viewport_size = device_viewport_size;
current_frame()->display_color_spaces = display_color_spaces;

// DecideRenderPassAllocationsForFrame needs
// current_frame()->display_color_spaces to decide the color space
// of each render pass.
DecideRenderPassAllocationsForFrame(*render_passes_in_draw_order);

output_surface_->SetNeedsMeasureNextDrawLatency();
BeginDrawingFrame();

Expand Down Expand Up @@ -379,7 +366,7 @@ void DirectRenderer::DrawFrame(
// TODO(penghuang): verify this logic with SkiaRenderer.
if (!output_surface_->capabilities().supports_surfaceless)
needs_full_frame_redraw = true;
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
#elif BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN)
// If compositing is delegated, then there will be no output_surface_plane,
// and we should not trigger a redraw of the root render pass.
// Pixel tests will not be displayed as overlay planes, so they need redraw.
Expand All @@ -393,6 +380,13 @@ void DirectRenderer::DrawFrame(
#endif
}

// DecideRenderPassAllocationsForFrame needs
// current_frame()->display_color_spaces to decide the color space
// of each render pass. Overlay processing is also allowed to modify the
// render pass backing requirements due to e.g. a underlay promotion. On
// Windows, the root render pass' size is based on the |reshape_params_|.
DecideRenderPassAllocationsForFrame(*render_passes_in_draw_order);

// Draw all non-root render passes except for the root render pass.
for (const auto& pass : *render_passes_in_draw_order) {
if (pass.get() == root_render_pass)
Expand Down Expand Up @@ -772,6 +766,51 @@ bool DirectRenderer::CanSkipRenderPass(
return false;
}

DirectRenderer::RenderPassRequirements
DirectRenderer::CalculateRenderPassRequirements(
const AggregatedRenderPass* render_pass) const {
bool is_root = render_pass == current_frame()->root_render_pass;

RenderPassRequirements requirements;

if (is_root) {
requirements.size = surface_size_for_swap_buffers();
requirements.generate_mipmap = false;
requirements.color_space = reshape_color_space();
requirements.format = GetResourceFormat(reshape_buffer_format());

// All root render pass backings allocated by the renderer needs to
// eventually go into some composition tree. Other things that own/allocate
// the root pass backing include the output device and buffer queue.
requirements.is_scanout = true;

#if BUILDFLAG(IS_WIN)
requirements.scanout_dcomp_surface =
render_pass->needs_synchronous_dcomp_commit;

// On Windows, the root render pass can be made transparent due to overlay
// processing promoting a quad as an underlay. If the format we picked does
// not have alpha bits, we ned to change to one that does.
if (render_pass->has_transparent_background &&
AlphaBits(requirements.format) == 0) {
requirements.format =
GetColorSpaceResourceFormat(requirements.color_space);
}
#endif
} else {
requirements.size = CalculateTextureSizeForRenderPass(render_pass);
requirements.generate_mipmap = render_pass->generate_mipmap;
requirements.color_space = RenderPassColorSpace(render_pass);
requirements.format = GetColorSpaceResourceFormat(requirements.color_space);
}

if (render_pass->has_transparent_background) {
DCHECK_GT(AlphaBits(requirements.format), 0);
}

return requirements;
}

void DirectRenderer::UseRenderPass(const AggregatedRenderPass* render_pass) {
bool is_root = render_pass == current_frame()->root_render_pass;
current_frame()->current_render_pass = render_pass;
Expand All @@ -790,21 +829,13 @@ void DirectRenderer::UseRenderPass(const AggregatedRenderPass* render_pass) {
return;
}

RenderPassRequirements requirements;
if (is_root) {
requirements.size = surface_size_for_swap_buffers();
requirements.generate_mipmap = false;
requirements.color_space = reshape_color_space();
requirements.format = GetResourceFormat(reshape_buffer_format());
} else {
requirements.size = CalculateTextureSizeForRenderPass(render_pass);
DirectRenderer::RenderPassRequirements requirements =
CalculateRenderPassRequirements(render_pass);
// We should not change the buffer size for the root render pass.
if (!is_root) {
requirements.size.Enlarge(enlarge_pass_texture_amount_.width(),
enlarge_pass_texture_amount_.height());
requirements.generate_mipmap = render_pass->generate_mipmap;
requirements.color_space = CurrentRenderPassColorSpace();
requirements.format = GetColorSpaceResourceFormat(requirements.color_space);
}

AllocateRenderPassResourceIfNeeded(render_pass->id, requirements);

// TODO(crbug.com/582554): This change applies only when Vulkan is enabled and
Expand Down Expand Up @@ -936,7 +967,7 @@ gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass(
}

gfx::Size DirectRenderer::CalculateTextureSizeForRenderPass(
const AggregatedRenderPass* render_pass) {
const AggregatedRenderPass* render_pass) const {
// Round the size of the render pass backings to a multiple of 64 pixels. This
// reduces memory fragmentation. https://crbug.com/146070. This also allows
// backings to be more easily reused during a resize operation.
Expand Down
9 changes: 8 additions & 1 deletion components/viz/service/display/direct_renderer.h
Expand Up @@ -204,6 +204,11 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
bool generate_mipmap = false;
ResourceFormat format;
gfx::ColorSpace color_space;
// Render pass wants scanout
bool is_scanout = false;
// Render pass wants to synchronize updates with other overlays, on Windows
// this means a DComp surface.
bool scanout_dcomp_surface = false;
};

static gfx::RectF QuadVertexRect();
Expand All @@ -228,9 +233,11 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
void SetScissorTestRectInDrawSpace(const gfx::Rect& draw_space_rect);

gfx::Size CalculateTextureSizeForRenderPass(
const AggregatedRenderPass* render_pass);
const AggregatedRenderPass* render_pass) const;
gfx::Size CalculateSizeForOutputSurface(
const gfx::Size& device_viewport_size);
RenderPassRequirements CalculateRenderPassRequirements(
const AggregatedRenderPass* render_pass) const;

void FlushPolygons(
base::circular_deque<std::unique_ptr<DrawPolygon>>* poly_list,
Expand Down

0 comments on commit e3ca4df

Please sign in to comment.