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 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
// 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/external_vk_image_dawn_representation.h"
#include <dawn/native/VulkanBackend.h>
#include <utility>
#include <vector>
#include "base/posix/eintr_wrapper.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/vulkan/vulkan_image.h"
#include "third_party/skia/include/gpu/MutableTextureState.h"
#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkTypes.h"
#include "third_party/skia/include/gpu/vk/VulkanMutableTextureState.h"
namespace gpu {
ExternalVkImageDawnImageRepresentation::ExternalVkImageDawnImageRepresentation(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
wgpu::Device device,
wgpu::TextureFormat wgpu_format,
std::vector<wgpu::TextureFormat> view_formats,
base::ScopedFD memory_fd)
: DawnImageRepresentation(manager, backing, tracker),
device_(std::move(device)),
wgpu_format_(wgpu_format),
view_formats_(std::move(view_formats)),
memory_fd_(std::move(memory_fd)) {
DCHECK(device_);
}
ExternalVkImageDawnImageRepresentation::
~ExternalVkImageDawnImageRepresentation() {
EndAccess();
}
wgpu::Texture ExternalVkImageDawnImageRepresentation::BeginAccess(
wgpu::TextureUsage usage,
wgpu::TextureUsage internal_usage) {
DCHECK(begin_access_semaphores_.empty());
if (!backing_impl()->BeginAccess(false, &begin_access_semaphores_,
/*is_gl=*/false)) {
return nullptr;
}
wgpu::TextureDescriptor texture_descriptor;
texture_descriptor.format = wgpu_format_;
texture_descriptor.usage = static_cast<wgpu::TextureUsage>(usage);
texture_descriptor.dimension = wgpu::TextureDimension::e2D;
texture_descriptor.size = {static_cast<uint32_t>(size().width()),
static_cast<uint32_t>(size().height()), 1};
texture_descriptor.mipLevelCount = 1;
texture_descriptor.sampleCount = 1;
texture_descriptor.viewFormatCount = view_formats_.size();
texture_descriptor.viewFormats = view_formats_.data();
const GrBackendTexture& backend_texture = backing_impl()->backend_texture();
GrVkImageInfo image_info;
GrBackendTextures::GetVkImageInfo(backend_texture, &image_info);
wgpu::DawnTextureInternalUsageDescriptor internalDesc;
internalDesc.internalUsage = internal_usage;
if (image_info.fImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
// We pass `image_info.fImageLayout` to Dawn in the
// ExternalImageDescriptor below as the old/new layout for it to use. For
// a Vulkan-backed Dawn texture to be usable with the Vulkan color
// attachment layout, it must have RenderAttachment usage.
// TODO(crbug.com/339171225): Determine if it is possible to eliminate the
// need for this workaround, which turns these Dawn accesses into write
// accesses regardless of whether the client has specified any write
// usages.
internalDesc.internalUsage |= wgpu::TextureUsage::RenderAttachment;
}
texture_descriptor.nextInChain = &internalDesc;
dawn::native::vulkan::ExternalImageDescriptorOpaqueFD descriptor = {};
descriptor.cTextureDescriptor =
reinterpret_cast<WGPUTextureDescriptor*>(&texture_descriptor);
descriptor.isInitialized = IsCleared();
descriptor.allocationSize = backing_impl()->image()->device_size();
descriptor.memoryTypeIndex = backing_impl()->image()->memory_type_index();
descriptor.memoryFD = dup(memory_fd_.get());
// We should either be importing the image from the external queue, or it
// was just created with no queue ownership.
DCHECK(image_info.fCurrentQueueFamily == VK_QUEUE_FAMILY_IGNORED ||
image_info.fCurrentQueueFamily == VK_QUEUE_FAMILY_EXTERNAL);
// Note: This assumes the previous owner of the shared image did not do a
// layout transition on EndAccess, and saved the exported layout on the
// GrBackendTexture.
descriptor.releasedOldLayout = image_info.fImageLayout;
descriptor.releasedNewLayout = image_info.fImageLayout;
for (auto& external_semaphore : begin_access_semaphores_) {
descriptor.waitFDs.push_back(
external_semaphore.handle().TakeHandle().release());
}
texture_ = wgpu::Texture::Acquire(
dawn::native::vulkan::WrapVulkanImage(device_.Get(), &descriptor));
if (!texture_) {
backing_impl()->EndAccess(false, ExternalSemaphore(), /*is_gl=*/false);
// In this case we didn't submit anything, so we can't reuse them.
// Release them immediately.
backing_impl()->ReleaseSemaphoresWithFenceHelper(
std::move(begin_access_semaphores_));
begin_access_semaphores_.clear();
return nullptr;
}
return texture_.Get();
}
void ExternalVkImageDawnImageRepresentation::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();
}
// Exporting to VK_IMAGE_LAYOUT_UNDEFINED means no transition should be
// done. The old/new layouts are the same.
DCHECK_EQ(export_info.releasedOldLayout, export_info.releasedNewLayout);
// Save the layout on the GrBackendTexture. Other shared image
// representations read it from here.
GrBackendTexture backend_texture = backing_impl()->backend_texture();
backend_texture.setMutableState(skgpu::MutableTextureStates::MakeVulkan(
export_info.releasedNewLayout, VK_QUEUE_FAMILY_EXTERNAL));
// TODO(enga): Handle waiting on multiple semaphores from dawn
DCHECK(export_info.semaphoreHandles.size() == 1);
// Wrap file descriptor in a handle
SemaphoreHandle handle(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
base::ScopedFD(export_info.semaphoreHandles[0]));
auto semaphore = ExternalSemaphore::CreateFromHandle(
backing_impl()->context_provider(), std::move(handle));
backing_impl()->EndAccess(false, std::move(semaphore), /*is_gl=*/false);
}
// Destroy the texture, signaling the semaphore in dawn
texture_.Destroy();
texture_ = nullptr;
// We have done with |begin_access_semaphores_|. They should have been waited.
// So add them to pending semaphores for reusing or relaeasing.
backing_impl()->AddSemaphoresToPendingListOrRelease(
std::move(begin_access_semaphores_));
begin_access_semaphores_.clear();
}
} // namespace gpu
|