1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2019 The Chromium Authors
// 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/dawn_ozone_image_representation.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/ozone_image_backing.h"
#include "gpu/command_buffer/service/shared_image/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image/shared_image_manager.h"
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
#include "gpu/config/gpu_finch_features.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap.h"
namespace gpu {
DawnOzoneImageRepresentation::DawnOzoneImageRepresentation(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
wgpu::Device device,
wgpu::TextureFormat format,
std::vector<wgpu::TextureFormat> view_formats,
scoped_refptr<gfx::NativePixmap> pixmap)
: DawnImageRepresentation(manager, backing, tracker),
device_(std::move(device)),
format_(format),
view_formats_(std::move(view_formats)),
pixmap_(pixmap) {
DCHECK(device_);
}
DawnOzoneImageRepresentation::~DawnOzoneImageRepresentation() {
EndAccess();
}
wgpu::Texture DawnOzoneImageRepresentation::BeginAccess(
wgpu::TextureUsage usage,
wgpu::TextureUsage internal_usage) {
// It doesn't make sense to have two overlapping BeginAccess calls on the same
// representation.
if (texture_) {
return nullptr;
}
// For multi-planar formats, Mesa is yet to support to allocate and bind
// vkmemory for each plane respectively.
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/intel/vulkan/anv_formats.c#L765
// For now we assume all plane handles are same, and we don't use the
// VK_IMAGE_CREATE_DISJOINT_BIT when creating the vkimage for the pixmap.
DCHECK(pixmap_->SupportsZeroCopyWebGPUImport() ||
pixmap_->GetNumberOfPlanes() == 1)
<< "Disjoint Multi-plane importing is not supported.";
std::vector<gfx::GpuFenceHandle> fences;
bool need_end_fence;
is_readonly_ =
(usage & kWriteUsage) == 0 && (internal_usage & kWriteUsage) == 0;
if (is_readonly_ && !IsCleared()) {
// Read-only access of an uncleared texture is not allowed: clients
// relying on Dawn's lazy clearing of uninitialized textures must make
// this reliance explicit by passing a write usage.
return nullptr;
}
if (!ozone_backing()->BeginAccess(
/*readonly=*/is_readonly_, OzoneImageBacking::AccessStream::kWebGPU,
&fences, need_end_fence)) {
return nullptr;
}
DCHECK(need_end_fence || is_readonly_);
gfx::Size pixmap_size = pixmap_->GetBufferSize();
wgpu::TextureDescriptor texture_descriptor;
texture_descriptor.format = format_;
texture_descriptor.viewFormats = view_formats_.data();
texture_descriptor.viewFormatCount = view_formats_.size();
texture_descriptor.usage = static_cast<wgpu::TextureUsage>(usage);
texture_descriptor.dimension = wgpu::TextureDimension::e2D;
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;
wgpu::DawnTextureInternalUsageDescriptor internalDesc;
internalDesc.internalUsage = internal_usage;
texture_descriptor.nextInChain = &internalDesc;
dawn::native::vulkan::ExternalImageDescriptorDmaBuf descriptor = {};
descriptor.cTextureDescriptor =
reinterpret_cast<WGPUTextureDescriptor*>(&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;
for (uint32_t plane = 0u; plane < pixmap_->GetNumberOfPlanes(); ++plane) {
descriptor.planeLayouts[plane].offset = pixmap_->GetDmaBufOffset(plane);
descriptor.planeLayouts[plane].stride = pixmap_->GetDmaBufPitch(plane);
}
descriptor.drmModifier = pixmap_->GetBufferFormatModifier();
descriptor.waitFDs = {};
for (auto& fence : fences) {
descriptor.waitFDs.push_back(fence.Release().release());
}
texture_ = wgpu::Texture::Acquire(
dawn::native::vulkan::WrapVulkanImage(device_.Get(), &descriptor));
if (!texture_) {
ozone_backing()->EndAccess(is_readonly_,
OzoneImageBacking::AccessStream::kWebGPU,
gfx::GpuFenceHandle());
close(fd);
}
return texture_.Get();
}
void DawnOzoneImageRepresentation::EndAccess() {
if (!texture_) {
return;
}
// Grab the signal semaphore from dawn
dawn::native::vulkan::ExternalImageExportInfoOpaqueFD export_info;
if (!dawn::native::vulkan::ExportVulkanImage(
texture_.Get(), 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.Adopt(base::ScopedFD(export_info.semaphoreHandles[0]));
ozone_backing()->EndAccess(is_readonly_,
OzoneImageBacking::AccessStream::kWebGPU,
std::move(fence));
}
texture_.Destroy();
texture_ = nullptr;
}
} // namespace gpu
|