blob: 65adb4b6dd14feebc8de6c85e53e3f3a101c9b84 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/shared_image_representation_dawn_ozone.h"
#include <dawn_native/VulkanBackend.h>
#include <vulkan/vulkan.h>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap.h"
namespace gpu {
SharedImageRepresentationDawnOzone::SharedImageRepresentationDawnOzone(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
WGPUDevice device,
WGPUTextureFormat format,
scoped_refptr<gfx::NativePixmap> pixmap,
scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs)
: SharedImageRepresentationDawn(manager, backing, tracker),
device_(device),
format_(format),
pixmap_(pixmap),
dawn_procs_(dawn_procs) {
DCHECK(device_);
// Keep a reference to the device so that it stays valid (it might become
// lost in which case operations will be noops).
dawn_procs_->data.deviceReference(device_);
}
SharedImageRepresentationDawnOzone::~SharedImageRepresentationDawnOzone() {
EndAccess();
dawn_procs_->data.deviceRelease(device_);
}
WGPUTexture SharedImageRepresentationDawnOzone::BeginAccess(
WGPUTextureUsage usage) {
// It doesn't make sense to have two overlapping BeginAccess calls on the same
// representation.
if (texture_) {
return nullptr;
}
if (!ozone_backing()->VaSync()) {
return nullptr;
}
DCHECK(pixmap_->GetNumberOfPlanes() == 1)
<< "Multi-plane formats are not supported.";
std::vector<gfx::GpuFenceHandle> fences;
ozone_backing()->BeginAccess(&fences);
gfx::Size pixmap_size = pixmap_->GetBufferSize();
WGPUTextureDescriptor texture_descriptor = {};
texture_descriptor.format = format_;
texture_descriptor.usage = usage;
texture_descriptor.dimension = WGPUTextureDimension_2D;
texture_descriptor.size = {static_cast<uint32_t>(pixmap_size.width()),
static_cast<uint32_t>(pixmap_size.height()), 1};
texture_descriptor.mipLevelCount = 1;
texture_descriptor.sampleCount = 1;
// We need to have an internal usage of CopySrc in order to use
// CopyTextureToTextureInternal.
WGPUDawnTextureInternalUsageDescriptor internalDesc = {};
internalDesc.chain.sType = WGPUSType_DawnTextureInternalUsageDescriptor;
internalDesc.internalUsage = WGPUTextureUsage_CopySrc;
texture_descriptor.nextInChain =
reinterpret_cast<WGPUChainedStruct*>(&internalDesc);
dawn_native::vulkan::ExternalImageDescriptorDmaBuf descriptor = {};
descriptor.cTextureDescriptor = &texture_descriptor;
descriptor.isInitialized = IsCleared();
// Import the dma-buf into Dawn via the Vulkan backend. As per the Vulkan
// documentation, importing memory from a file descriptor transfers
// ownership of the fd from the application to the Vulkan implementation.
// Thus, we need to dup the fd so the fd corresponding to the dmabuf isn't
// closed twice (once by ScopedFD and once by the Vulkan implementation).
int fd = dup(pixmap_->GetDmaBufFd(0));
descriptor.memoryFD = fd;
descriptor.stride = pixmap_->GetDmaBufPitch(0);
descriptor.drmModifier = pixmap_->GetBufferFormatModifier();
descriptor.waitFDs = {};
if (ozone_backing()->NeedsSynchronization()) {
for (auto& fence : fences) {
descriptor.waitFDs.push_back(fence.owned_fd.release());
}
}
texture_ = dawn_native::vulkan::WrapVulkanImage(device_, &descriptor);
if (!texture_) {
close(fd);
}
return texture_;
}
void SharedImageRepresentationDawnOzone::EndAccess() {
if (!texture_) {
return;
}
// Grab the signal semaphore from dawn
dawn_native::vulkan::ExternalImageExportInfoOpaqueFD export_info;
if (!dawn_native::vulkan::ExportVulkanImage(
texture_, VK_IMAGE_LAYOUT_UNDEFINED, &export_info)) {
DLOG(ERROR) << "Failed to export Dawn Vulkan image.";
} else {
if (export_info.isInitialized) {
SetCleared();
}
// TODO(hob): Handle waiting on multiple semaphores from dawn.
DCHECK(export_info.semaphoreHandles.size() == 1);
gfx::GpuFenceHandle fence;
fence.owned_fd = base::ScopedFD(export_info.semaphoreHandles[0]);
ozone_backing()->EndAccess(false /* readonly */, std::move(fence));
}
dawn_procs_->data.textureDestroy(texture_);
dawn_procs_->data.textureRelease(texture_);
texture_ = nullptr;
}
} // namespace gpu