Commit 9058f786 authored by Antoine Labour's avatar Antoine Labour Committed by Commit Bot

Use SharedImageInterface for one-copy staging buffers

Bug: 882513
Change-Id: I7643ae90356a4a98f57cb5e14691af4362ad9b83
Reviewed-on: https://chromium-review.googlesource.com/c/1323719
Commit-Queue: Antoine Labour <piman@chromium.org>
Reviewed-by: default avatarJonathan Backer <backer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607454}
parent 0d45a99a
...@@ -366,61 +366,50 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( ...@@ -366,61 +366,50 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread(
bool mailbox_texture_is_overlay_candidate, bool mailbox_texture_is_overlay_candidate,
const gpu::SyncToken& sync_token, const gpu::SyncToken& sync_token,
const gfx::ColorSpace& color_space) { const gfx::ColorSpace& color_space) {
viz::RasterContextProvider::ScopedRasterContextLock scoped_context( auto* sii = worker_context_provider_->SharedImageInterface();
worker_context_provider_); DCHECK(sii);
gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
DCHECK(ri); if (!staging_buffer->gpu_memory_buffer.get()) {
// If GpuMemoryBuffer allocation failed (https://crbug.com/554541), then
// we don't have anything to give to copy into the resource. We report a
// zero mailbox that will result in checkerboarding, and be treated as OOM
// which should retry.
if (!mailbox->IsZero()) {
sii->DestroySharedImage(sync_token, *mailbox);
mailbox->SetZero();
}
return gpu::SyncToken();
}
if (mailbox->IsZero()) { if (mailbox->IsZero()) {
auto* sii = worker_context_provider_->SharedImageInterface();
uint32_t flags = gpu::SHARED_IMAGE_USAGE_RASTER; uint32_t flags = gpu::SHARED_IMAGE_USAGE_RASTER;
if (mailbox_texture_is_overlay_candidate) if (mailbox_texture_is_overlay_candidate)
flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT; flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
*mailbox = sii->CreateSharedImage(resource_format, resource_size, *mailbox = sii->CreateSharedImage(resource_format, resource_size,
color_space, flags); color_space, flags);
ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData()); }
// Create staging shared image.
if (staging_buffer->mailbox.IsZero()) {
staging_buffer->mailbox = sii->CreateSharedImage(
staging_buffer->gpu_memory_buffer.get(), gpu_memory_buffer_manager_,
color_space, gpu::SHARED_IMAGE_USAGE_RASTER);
} else { } else {
ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); sii->UpdateSharedImage(staging_buffer->sync_token, staging_buffer->mailbox);
} }
viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
worker_context_provider_);
gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
DCHECK(ri);
ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
GLuint mailbox_texture_id = ri->CreateAndConsumeTexture( GLuint mailbox_texture_id = ri->CreateAndConsumeTexture(
mailbox_texture_is_overlay_candidate, gfx::BufferUsage::SCANOUT, mailbox_texture_is_overlay_candidate, gfx::BufferUsage::SCANOUT,
resource_format, mailbox->name); resource_format, mailbox->name);
GLuint staging_texture_id = ri->CreateAndConsumeTexture(
// Create and bind staging texture. true, StagingBufferUsage(), staging_buffer->format,
if (!staging_buffer->texture_id) { staging_buffer->mailbox.name);
staging_buffer->texture_id =
ri->CreateTexture(true, StagingBufferUsage(), staging_buffer->format);
ri->TexParameteri(staging_buffer->texture_id, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
ri->TexParameteri(staging_buffer->texture_id, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
ri->TexParameteri(staging_buffer->texture_id, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
ri->TexParameteri(staging_buffer->texture_id, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
}
// Create and bind image.
if (!staging_buffer->image_id) {
if (staging_buffer->gpu_memory_buffer) {
staging_buffer->image_id = ri->CreateImageCHROMIUM(
staging_buffer->gpu_memory_buffer->AsClientBuffer(),
staging_buffer->size.width(), staging_buffer->size.height(),
GLInternalFormat(staging_buffer->format));
ri->BindTexImage2DCHROMIUM(staging_buffer->texture_id,
staging_buffer->image_id);
}
} else {
ri->ReleaseTexImage2DCHROMIUM(staging_buffer->texture_id,
staging_buffer->image_id);
ri->BindTexImage2DCHROMIUM(staging_buffer->texture_id,
staging_buffer->image_id);
}
// Unbind staging texture.
// TODO(vmiura): Need a way to ensure we don't hold onto bindings?
// ri->BindTexture(image_target, 0);
// Do not use queries unless COMMANDS_COMPLETED queries are supported, or // Do not use queries unless COMMANDS_COMPLETED queries are supported, or
// COMMANDS_ISSUED queries are sufficient. // COMMANDS_ISSUED queries are sufficient.
...@@ -467,8 +456,8 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( ...@@ -467,8 +456,8 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread(
int rows_to_copy = std::min(chunk_size_in_rows, height - y); int rows_to_copy = std::min(chunk_size_in_rows, height - y);
DCHECK_GT(rows_to_copy, 0); DCHECK_GT(rows_to_copy, 0);
ri->CopySubTexture(staging_buffer->texture_id, mailbox_texture_id, 0, y, 0, ri->CopySubTexture(staging_texture_id, mailbox_texture_id, 0, y, 0, y,
y, rect_to_copy.width(), rows_to_copy); rect_to_copy.width(), rows_to_copy);
y += rows_to_copy; y += rows_to_copy;
// Increment |bytes_scheduled_since_last_flush_| by the amount of memory // Increment |bytes_scheduled_since_last_flush_| by the amount of memory
...@@ -484,11 +473,20 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( ...@@ -484,11 +473,20 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread(
if (query_target != GL_NONE) if (query_target != GL_NONE)
ri->EndQueryEXT(query_target); ri->EndQueryEXT(query_target);
ri->DeleteTextures(1, &mailbox_texture_id); GLuint textures_to_delete[] = {mailbox_texture_id, staging_texture_id};
ri->DeleteTextures(2, textures_to_delete);
// Generate sync token on the worker context that will be sent to and waited // Generate sync token on the worker context that will be sent to and waited
// for by the display compositor before using the content generated here. // for by the display compositor before using the content generated here.
return viz::ClientResourceProvider::GenerateSyncTokenHelper(ri); // The same sync token is used to synchronize operations on the staging
// buffer. Note, the query completion is generally enough to guarantee
// ordering, but there are some paths (e.g.
// StagingBufferPool::ReduceMemoryUsage) that may destroy the staging buffer
// without waiting for the query completion.
gpu::SyncToken out_sync_token =
viz::ClientResourceProvider::GenerateSyncTokenHelper(ri);
staging_buffer->sync_token = out_sync_token;
return out_sync_token;
} }
gfx::BufferUsage OneCopyRasterBufferProvider::StagingBufferUsage() const { gfx::BufferUsage OneCopyRasterBufferProvider::StagingBufferUsage() const {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "components/viz/common/gpu/raster_context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/common/resources/resource_sizes.h" #include "components/viz/common/resources/resource_sizes.h"
#include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/gpu_memory_buffer.h"
...@@ -68,23 +69,19 @@ StagingBuffer::StagingBuffer(const gfx::Size& size, viz::ResourceFormat format) ...@@ -68,23 +69,19 @@ StagingBuffer::StagingBuffer(const gfx::Size& size, viz::ResourceFormat format)
: size(size), format(format) {} : size(size), format(format) {}
StagingBuffer::~StagingBuffer() { StagingBuffer::~StagingBuffer() {
DCHECK_EQ(texture_id, 0u); DCHECK(mailbox.IsZero());
DCHECK_EQ(image_id, 0u);
DCHECK_EQ(query_id, 0u); DCHECK_EQ(query_id, 0u);
} }
void StagingBuffer::DestroyGLResources(gpu::raster::RasterInterface* ri) { void StagingBuffer::DestroyGLResources(gpu::raster::RasterInterface* ri,
gpu::SharedImageInterface* sii) {
if (query_id) { if (query_id) {
ri->DeleteQueriesEXT(1, &query_id); ri->DeleteQueriesEXT(1, &query_id);
query_id = 0; query_id = 0;
} }
if (image_id) { if (!mailbox.IsZero()) {
ri->DestroyImageCHROMIUM(image_id); sii->DestroySharedImage(sync_token, mailbox);
image_id = 0; mailbox.SetZero();
}
if (texture_id) {
ri->DeleteTextures(1, &texture_id);
texture_id = 0;
} }
} }
...@@ -248,6 +245,8 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer( ...@@ -248,6 +245,8 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer(
worker_context_provider_); worker_context_provider_);
gpu::raster::RasterInterface* ri = scoped_context.RasterInterface(); gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
gpu::SharedImageInterface* sii =
worker_context_provider_->SharedImageInterface();
DCHECK(ri); DCHECK(ri);
// Check if any busy buffers have become available. // Check if any busy buffers have become available.
...@@ -324,7 +323,7 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer( ...@@ -324,7 +323,7 @@ std::unique_ptr<StagingBuffer> StagingBufferPool::AcquireStagingBuffer(
if (free_buffers_.empty()) if (free_buffers_.empty())
break; break;
free_buffers_.front()->DestroyGLResources(ri); free_buffers_.front()->DestroyGLResources(ri, sii);
MarkStagingBufferAsBusy(free_buffers_.front().get()); MarkStagingBufferAsBusy(free_buffers_.front().get());
RemoveStagingBuffer(free_buffers_.front().get()); RemoveStagingBuffer(free_buffers_.front().get());
free_buffers_.pop_front(); free_buffers_.pop_front();
...@@ -395,6 +394,9 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) { ...@@ -395,6 +394,9 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) {
gpu::raster::RasterInterface* ri = scoped_context.RasterInterface(); gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
DCHECK(ri); DCHECK(ri);
gpu::SharedImageInterface* sii =
worker_context_provider_->SharedImageInterface();
DCHECK(sii);
// Note: Front buffer is guaranteed to be LRU so we can stop releasing // Note: Front buffer is guaranteed to be LRU so we can stop releasing
// buffers as soon as we find a buffer that has been used since |time|. // buffers as soon as we find a buffer that has been used since |time|.
...@@ -402,7 +404,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) { ...@@ -402,7 +404,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) {
if (free_buffers_.front()->last_usage > time) if (free_buffers_.front()->last_usage > time)
return; return;
free_buffers_.front()->DestroyGLResources(ri); free_buffers_.front()->DestroyGLResources(ri, sii);
MarkStagingBufferAsBusy(free_buffers_.front().get()); MarkStagingBufferAsBusy(free_buffers_.front().get());
RemoveStagingBuffer(free_buffers_.front().get()); RemoveStagingBuffer(free_buffers_.front().get());
free_buffers_.pop_front(); free_buffers_.pop_front();
...@@ -412,7 +414,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) { ...@@ -412,7 +414,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) {
if (busy_buffers_.front()->last_usage > time) if (busy_buffers_.front()->last_usage > time)
return; return;
busy_buffers_.front()->DestroyGLResources(ri); busy_buffers_.front()->DestroyGLResources(ri, sii);
RemoveStagingBuffer(busy_buffers_.front().get()); RemoveStagingBuffer(busy_buffers_.front().get());
busy_buffers_.pop_front(); busy_buffers_.pop_front();
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "cc/cc_export.h" #include "cc/cc_export.h"
#include "components/viz/common/resources/resource_format.h" #include "components/viz/common/resources/resource_format.h"
#include "gpu/command_buffer/common/gl2_types.h" #include "gpu/command_buffer/common/gl2_types.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/gpu_memory_buffer.h"
...@@ -32,6 +34,7 @@ namespace gpu { ...@@ -32,6 +34,7 @@ namespace gpu {
namespace raster { namespace raster {
class RasterInterface; class RasterInterface;
} }
class SharedImageInterface;
} // namespace gpu } // namespace gpu
namespace viz { namespace viz {
...@@ -44,7 +47,8 @@ struct StagingBuffer { ...@@ -44,7 +47,8 @@ struct StagingBuffer {
StagingBuffer(const gfx::Size& size, viz::ResourceFormat format); StagingBuffer(const gfx::Size& size, viz::ResourceFormat format);
~StagingBuffer(); ~StagingBuffer();
void DestroyGLResources(gpu::raster::RasterInterface* gl); void DestroyGLResources(gpu::raster::RasterInterface* gl,
gpu::SharedImageInterface* sii);
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
viz::ResourceFormat format, viz::ResourceFormat format,
bool is_free) const; bool is_free) const;
...@@ -58,11 +62,11 @@ struct StagingBuffer { ...@@ -58,11 +62,11 @@ struct StagingBuffer {
// GpuMemoryBuffer. // GpuMemoryBuffer.
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
// Id for image used to import the GpuMemoryBuffer to command buffer. // Mailbox for the shared image bound to the GpuMemoryBuffer.
GLuint image_id = 0; gpu::Mailbox mailbox;
// Id for texture that's bound to the GpuMemoryBuffer image. // Sync token for the last RasterInterface operations using the shared image.
GLuint texture_id = 0; gpu::SyncToken sync_token;
// Id of command buffer query that tracks use of this staging buffer by the // Id of command buffer query that tracks use of this staging buffer by the
// GPU. In general, GPU synchronization is necessary for native // GPU. In general, GPU synchronization is necessary for native
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment