Skip to content

Commit

Permalink
Convert ExternalVkImageBacking representations
Browse files Browse the repository at this point in the history
Convert Skia and GL representations for ExternalVkImageBacking to be
compatible to be able to handle multiple VkImages or GL textures. There
is no multiplanar support for dawn right now or overlay representations.

ExternalVkImageBacking still only contains a single Vulkan or GL texture
so this should be a no-op.

Bug: 1414560
Change-Id: I9e46290a4dd96ee23e4472c40d8c32fb232dd68b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4324477
Reviewed-by: Saifuddin Hitawala <hitawala@chromium.org>
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1116545}
  • Loading branch information
kylechar authored and Chromium LUCI CQ committed Mar 13, 2023
1 parent 621bf29 commit 71fca4d
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 168 deletions.
Expand Up @@ -313,6 +313,21 @@ ExternalVkImageBacking::~ExternalVkImageBacking() {
}
}

std::vector<GLenum> ExternalVkImageBacking::GetVkImageLayoutsForGL() {
GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info);
DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
return {VkImageLayoutToGLImageLayout(info.fImageLayout)};
}

std::vector<sk_sp<SkPromiseImageTexture>>
ExternalVkImageBacking::GetPromiseTextures() {
return {promise_texture_};
}

bool ExternalVkImageBacking::BeginAccess(
bool readonly,
std::vector<ExternalSemaphore>* external_semaphores,
Expand Down Expand Up @@ -341,18 +356,12 @@ bool ExternalVkImageBacking::BeginAccess(
DCHECK(readonly);
DCHECK(gl_texture_);

GLuint texture_id = gl_texture_->GetServiceId();
std::vector<GLuint> texture_ids = {gl_texture_->GetServiceId()};
MakeGLContextCurrent();

GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info);
DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
auto release_semaphore =
ExternalVkImageGLRepresentationShared::ReleaseTexture(
external_semaphore_pool(), texture_id, info.fImageLayout);
external_semaphore_pool(), texture_ids, GetVkImageLayoutsForGL());
if (!release_semaphore) {
context_state_->MarkContextLost();
return false;
Expand Down Expand Up @@ -432,21 +441,15 @@ void ExternalVkImageBacking::EndAccess(bool readonly,
DCHECK(!is_gl);
DCHECK(readonly);
DCHECK(gl_texture_);
GLuint texture_id = gl_texture_->GetServiceId();
std::vector<GLuint> texture_ids = {gl_texture_->GetServiceId()};
MakeGLContextCurrent();
std::vector<ExternalSemaphore> external_semaphores;
BeginAccessInternal(true, &external_semaphores);
DCHECK_LE(external_semaphores.size(), 1u);

for (auto& semaphore : external_semaphores) {
GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info);
DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
ExternalVkImageGLRepresentationShared::AcquireTexture(
&semaphore, texture_id, info.fImageLayout);
&semaphore, texture_ids, GetVkImageLayoutsForGL());
}
// |external_semaphores| has been waited on a GL context, so it can not be
// reused until a vulkan GPU work depends on the following GL task is over.
Expand Down Expand Up @@ -700,8 +703,10 @@ ExternalVkImageBacking::ProduceGLTexture(SharedImageManager* manager,
return nullptr;
}
}

std::vector<gles2::Texture*> textures = {gl_texture_->texture()};
return std::make_unique<ExternalVkImageGLRepresentation>(
manager, this, tracker, gl_texture_->texture());
manager, this, tracker, std::move(textures));
}

std::unique_ptr<GLTexturePassthroughImageRepresentation>
Expand All @@ -719,8 +724,10 @@ ExternalVkImageBacking::ProduceGLTexturePassthrough(
}
}

std::vector<scoped_refptr<gles2::TexturePassthrough>> textures = {
gl_texture_->passthrough_texture()};
return std::make_unique<ExternalVkImageGLPassthroughRepresentation>(
manager, this, tracker, gl_texture_->passthrough_texture());
manager, this, tracker, std::move(textures));
}

std::unique_ptr<SkiaImageRepresentation> ExternalVkImageBacking::ProduceSkia(
Expand Down
Expand Up @@ -77,9 +77,6 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking {

SharedContextState* context_state() const { return context_state_.get(); }
const GrBackendTexture& backend_texture() const { return backend_texture_; }
sk_sp<SkPromiseImageTexture> promise_texture() const {
return promise_texture_;
}
VulkanImage* image() const { return image_.get(); }
viz::VulkanContextProvider* context_provider() const {
return context_state()->vk_context_provider();
Expand Down Expand Up @@ -113,6 +110,12 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking {
uint32_t reads_in_progress() const { return reads_in_progress_; }
uint32_t gl_reads_in_progress() const { return gl_reads_in_progress_; }

// Returns VkImage layouts for each plane as GL layouts.
std::vector<GLenum> GetVkImageLayoutsForGL();

// Returns skia promise images for each plane.
std::vector<sk_sp<SkPromiseImageTexture>> GetPromiseTextures();

// Notifies the backing that an access will start. Return false if there is
// currently any other conflict access in progress. Otherwise, returns true
// and semaphores which will be waited on before accessing.
Expand Down
Expand Up @@ -11,50 +11,65 @@
#include "ui/gl/gl_bindings.h"

namespace gpu {
namespace {

template <typename T>
std::vector<GLuint> GetTextureIds(const std::vector<T>& textures) {
std::vector<GLuint> texture_ids;
texture_ids.reserve(textures.size());
for (const T& texture : textures) {
texture_ids.push_back(texture->service_id());
}
return texture_ids;
}

} // namespace

// static
void ExternalVkImageGLRepresentationShared::AcquireTexture(
ExternalSemaphore* semaphore,
GLuint texture_id,
VkImageLayout src_layout) {
const std::vector<GLuint>& texture_ids,
const std::vector<GLenum>& src_layouts) {
DCHECK_EQ(texture_ids.size(), src_layouts.size());

GLuint gl_semaphore = semaphore->GetGLSemaphore();
if (gl_semaphore) {
GLenum gl_layout = VkImageLayoutToGLImageLayout(src_layout);
auto* api = gl::g_current_gl_context;
api->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id,
&gl_layout);
api->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, texture_ids.size(),
texture_ids.data(), src_layouts.data());
}
}

// static
ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture(
ExternalSemaphorePool* pool,
GLuint texture_id,
VkImageLayout dst_layout) {
const std::vector<GLuint>& texture_ids,
const std::vector<GLenum>& dst_layouts) {
DCHECK_EQ(texture_ids.size(), dst_layouts.size());

ExternalSemaphore semaphore = pool->GetOrCreateSemaphore();
if (!semaphore) {
// TODO(crbug.com/933452): We should be able to handle this failure more
// gracefully rather than shutting down the whole process.
LOG(ERROR) << "Unable to create an ExternalSemaphore in "
<< "ExternalVkImageGLRepresentation for synchronization with "
<< "Vulkan";
DLOG(ERROR) << "Unable to create an ExternalSemaphore in "
<< "ExternalVkImageGLRepresentation for synchronization with "
<< "Vulkan";
return {};
}

GLuint gl_semaphore = semaphore.GetGLSemaphore();
if (!gl_semaphore) {
// TODO(crbug.com/933452): We should be able to semaphore_handle this
// failure more gracefully rather than shutting down the whole process.
LOG(ERROR) << "Unable to export VkSemaphore into GL in "
<< "ExternalVkImageGLRepresentation for synchronization with "
<< "Vulkan";
DLOG(ERROR) << "Unable to export VkSemaphore into GL in "
<< "ExternalVkImageGLRepresentation for synchronization with "
<< "Vulkan";
return {};
}

GLenum gl_layout = VkImageLayoutToGLImageLayout(dst_layout);
auto* api = gl::g_current_gl_context;
api->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id,
&gl_layout);
api->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, texture_ids.size(),
texture_ids.data(), dst_layouts.data());
// Base on the spec, the glSignalSemaphoreEXT() call just inserts signal
// semaphore command in the gl context. It may or may not flush the context
// which depends on the implementation. So to make it safe, we always call
Expand All @@ -67,9 +82,9 @@ ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture(

ExternalVkImageGLRepresentationShared::ExternalVkImageGLRepresentationShared(
SharedImageBacking* backing,
GLuint texture_service_id)
std::vector<GLuint> texture_service_ids)
: backing_(static_cast<ExternalVkImageBacking*>(backing)),
texture_service_id_(texture_service_id) {}
texture_service_ids_(std::move(texture_service_ids)) {}

ExternalVkImageGLRepresentationShared::
~ExternalVkImageGLRepresentationShared() = default;
Expand All @@ -78,8 +93,8 @@ bool ExternalVkImageGLRepresentationShared::BeginAccess(GLenum mode) {
// There should not be multiple accesses in progress on the same
// representation.
if (current_access_mode_) {
LOG(ERROR) << "BeginAccess called on ExternalVkImageGLRepresentation before"
<< " the previous access ended.";
DLOG(ERROR) << "BeginAccess called on ExternalVkImageGLRepresentation"
<< " before the previous access ended.";
return false;
}

Expand All @@ -95,13 +110,8 @@ bool ExternalVkImageGLRepresentationShared::BeginAccess(GLenum mode) {
}

for (auto& external_semaphore : begin_access_semaphores_) {
GrVkImageInfo info;
auto result = backing_impl()->backend_texture().getVkImageInfo(&info);
DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
AcquireTexture(&external_semaphore, texture_service_id_, info.fImageLayout);
auto image_layouts = backing_impl()->GetVkImageLayoutsForGL();
AcquireTexture(&external_semaphore, texture_service_ids_, image_layouts);
}
current_access_mode_ = mode;
return true;
Expand All @@ -111,8 +121,8 @@ void ExternalVkImageGLRepresentationShared::EndAccess() {
if (!current_access_mode_) {
// TODO(crbug.com/933452): We should be able to handle this failure more
// gracefully rather than shutting down the whole process.
LOG(ERROR) << "EndAccess called on ExternalVkImageGLRepresentation before "
<< "BeginAccess";
DLOG(ERROR) << "EndAccess called on ExternalVkImageGLRepresentation before "
<< "BeginAccess";
return;
}

Expand All @@ -127,15 +137,11 @@ void ExternalVkImageGLRepresentationShared::EndAccess() {
if (backing_impl()->need_synchronization() &&
backing_impl()->gl_reads_in_progress() <= 1) {
DCHECK(readonly == !!backing_impl()->gl_reads_in_progress());
GrVkImageInfo info;
auto result = backing_impl()->backend_texture().getVkImageInfo(&info);
DCHECK(result);
DCHECK_EQ(info.fCurrentQueueFamily, VK_QUEUE_FAMILY_EXTERNAL);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_UNDEFINED);
DCHECK_NE(info.fImageLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
auto image_layouts = backing_impl()->GetVkImageLayoutsForGL();

external_semaphore =
ReleaseTexture(backing_impl()->external_semaphore_pool(),
texture_service_id_, info.fImageLayout);
texture_service_ids_, image_layouts);
if (!external_semaphore) {
backing_impl()->context_state()->MarkContextLost();
return;
Expand All @@ -155,18 +161,17 @@ ExternalVkImageGLRepresentation::ExternalVkImageGLRepresentation(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
gles2::Texture* texture)
std::vector<gles2::Texture*> textures)
: GLTextureImageRepresentation(manager, backing, tracker),
texture_(texture),
representation_shared_(backing, texture_->service_id()) {
DCHECK(texture_);
textures_(std::move(textures)),
representation_shared_(backing, GetTextureIds(textures_)) {
DCHECK_EQ(textures_.size(), NumPlanesExpected());
}

ExternalVkImageGLRepresentation::~ExternalVkImageGLRepresentation() {}
ExternalVkImageGLRepresentation::~ExternalVkImageGLRepresentation() = default;

gles2::Texture* ExternalVkImageGLRepresentation::GetTexture(int plane_index) {
DCHECK_EQ(plane_index, 0);
return texture_;
return textures_[plane_index];
}

bool ExternalVkImageGLRepresentation::BeginAccess(GLenum mode) {
Expand All @@ -181,11 +186,11 @@ ExternalVkImageGLPassthroughRepresentation::
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
scoped_refptr<gles2::TexturePassthrough> texture)
std::vector<scoped_refptr<gles2::TexturePassthrough>> textures)
: GLTexturePassthroughImageRepresentation(manager, backing, tracker),
texture_(std::move(texture)),
representation_shared_(backing, texture_->service_id()) {
DCHECK(texture_);
textures_(std::move(textures)),
representation_shared_(backing, GetTextureIds(textures_)) {
DCHECK_EQ(textures_.size(), NumPlanesExpected());
}

ExternalVkImageGLPassthroughRepresentation::
Expand All @@ -194,8 +199,7 @@ ExternalVkImageGLPassthroughRepresentation::
const scoped_refptr<gles2::TexturePassthrough>&
ExternalVkImageGLPassthroughRepresentation::GetTexturePassthrough(
int plane_index) {
DCHECK_EQ(plane_index, 0);
return texture_;
return textures_[plane_index];
}

bool ExternalVkImageGLPassthroughRepresentation::BeginAccess(GLenum mode) {
Expand Down
Expand Up @@ -18,14 +18,16 @@ namespace gpu {
class ExternalVkImageGLRepresentationShared {
public:
static void AcquireTexture(ExternalSemaphore* semaphore,
GLuint texture_id,
VkImageLayout src_layout);
static ExternalSemaphore ReleaseTexture(ExternalSemaphorePool* pool,
GLuint texture_id,
VkImageLayout dst_layout);
const std::vector<GLuint>& texture_ids,
const std::vector<GLenum>& src_layouts);
static ExternalSemaphore ReleaseTexture(
ExternalSemaphorePool* pool,
const std::vector<GLuint>& texture_ids,
const std::vector<GLenum>& dst_layouts);

ExternalVkImageGLRepresentationShared(SharedImageBacking* backing,
GLuint texture_service_id);
ExternalVkImageGLRepresentationShared(
SharedImageBacking* backing,
std::vector<GLuint> texture_service_ids);

ExternalVkImageGLRepresentationShared(
const ExternalVkImageGLRepresentationShared&) = delete;
Expand All @@ -45,7 +47,7 @@ class ExternalVkImageGLRepresentationShared {
}

const raw_ptr<ExternalVkImageBacking> backing_;
const GLuint texture_service_id_;
const std::vector<GLuint> texture_service_ids_;
GLenum current_access_mode_ = 0;
std::vector<ExternalSemaphore> begin_access_semaphores_;
};
Expand All @@ -55,7 +57,7 @@ class ExternalVkImageGLRepresentation : public GLTextureImageRepresentation {
ExternalVkImageGLRepresentation(SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
gles2::Texture* texture);
std::vector<gles2::Texture*> textures);

ExternalVkImageGLRepresentation(const ExternalVkImageGLRepresentation&) =
delete;
Expand All @@ -70,7 +72,7 @@ class ExternalVkImageGLRepresentation : public GLTextureImageRepresentation {
void EndAccess() override;

private:
const raw_ptr<gles2::Texture> texture_;
std::vector<gles2::Texture*> textures_;
ExternalVkImageGLRepresentationShared representation_shared_;
};

Expand All @@ -81,7 +83,7 @@ class ExternalVkImageGLPassthroughRepresentation
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
scoped_refptr<gles2::TexturePassthrough> texture);
std::vector<scoped_refptr<gles2::TexturePassthrough>> texture);

ExternalVkImageGLPassthroughRepresentation(
const ExternalVkImageGLPassthroughRepresentation&) = delete;
Expand All @@ -97,7 +99,7 @@ class ExternalVkImageGLPassthroughRepresentation
void EndAccess() override;

private:
scoped_refptr<gles2::TexturePassthrough> texture_;
std::vector<scoped_refptr<gles2::TexturePassthrough>> textures_;
ExternalVkImageGLRepresentationShared representation_shared_;
};

Expand Down

0 comments on commit 71fca4d

Please sign in to comment.