2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2022-12-02 08:35:17 +01:00
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "vk_pixel_buffer.hh"
|
|
|
|
|
|
2025-04-12 14:21:03 +02:00
|
|
|
#include "vk_backend.hh"
|
|
|
|
|
|
|
|
|
|
#include "CLG_log.h"
|
2023-03-24 07:47:50 +01:00
|
|
|
|
2022-12-02 08:35:17 +01:00
|
|
|
namespace blender::gpu {
|
|
|
|
|
|
2025-04-12 14:21:03 +02:00
|
|
|
static CLG_LogRef LOG = {"gpu.vulkan"};
|
|
|
|
|
|
|
|
|
|
VKPixelBuffer::VKPixelBuffer(size_t size) : PixelBuffer(size) {}
|
|
|
|
|
|
|
|
|
|
void VKPixelBuffer::create(bool memory_export)
|
2022-12-02 08:35:17 +01:00
|
|
|
{
|
2025-04-12 14:21:03 +02:00
|
|
|
/* Create on demand with or without memory export. When memory export is
|
|
|
|
|
* enabled there is no host mapping. */
|
|
|
|
|
if (buffer_initialized_ && buffer_memory_export_ == memory_export) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buffer_.is_allocated()) {
|
|
|
|
|
buffer_.free();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer_.create(size_,
|
2024-06-28 13:51:51 +02:00
|
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
2025-01-14 17:41:35 +01:00
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
2025-01-24 11:54:59 +01:00
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
2025-04-12 14:21:03 +02:00
|
|
|
VmaAllocationCreateFlags(0),
|
|
|
|
|
memory_export);
|
2023-05-04 10:06:48 +02:00
|
|
|
debug::object_label(buffer_.vk_handle(), "PixelBuffer");
|
2025-04-12 14:21:03 +02:00
|
|
|
|
|
|
|
|
buffer_initialized_ = true;
|
|
|
|
|
buffer_memory_export_ = memory_export;
|
2022-12-02 08:35:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *VKPixelBuffer::map()
|
|
|
|
|
{
|
2023-03-13 19:25:18 +01:00
|
|
|
/* Vulkan buffers are always mapped between allocation and freeing. */
|
2025-04-12 14:21:03 +02:00
|
|
|
create(false);
|
2023-03-13 19:25:18 +01:00
|
|
|
return buffer_.mapped_memory_get();
|
2022-12-02 08:35:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VKPixelBuffer::unmap()
|
|
|
|
|
{
|
2023-03-13 19:25:18 +01:00
|
|
|
/* Vulkan buffers are always mapped between allocation and freeing. */
|
2022-12-02 08:35:17 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-12 14:21:03 +02:00
|
|
|
GPUPixelBufferNativeHandle VKPixelBuffer::get_native_handle()
|
2022-12-02 08:35:17 +01:00
|
|
|
{
|
2025-04-12 14:21:03 +02:00
|
|
|
VKDevice &device = VKBackend::get().device;
|
|
|
|
|
|
2025-05-08 22:38:55 +02:00
|
|
|
GPUPixelBufferNativeHandle native_handle;
|
|
|
|
|
|
2025-04-12 14:21:03 +02:00
|
|
|
/* Functionality supported? */
|
2025-05-23 15:59:29 +02:00
|
|
|
if (!device.extensions_get().external_memory) {
|
2025-05-08 22:38:55 +02:00
|
|
|
return native_handle;
|
2025-04-12 14:21:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create buffer. */
|
|
|
|
|
create(true);
|
|
|
|
|
|
|
|
|
|
/* Get device memory. */
|
|
|
|
|
size_t memory_size = 0;
|
|
|
|
|
VkDeviceMemory memory = buffer_.export_memory_get(memory_size);
|
|
|
|
|
if (memory == nullptr) {
|
|
|
|
|
CLOG_ERROR(&LOG, "Failed to get device memory for Vulkan pixel buffer");
|
2025-05-08 22:38:55 +02:00
|
|
|
return native_handle;
|
2025-04-12 14:21:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
/* Opaque Windows handle. */
|
|
|
|
|
VkMemoryGetWin32HandleInfoKHR info = {};
|
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
|
|
|
|
info.pNext = nullptr;
|
|
|
|
|
info.memory = memory;
|
|
|
|
|
info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
|
|
|
|
|
|
|
|
|
|
HANDLE handle = 0;
|
|
|
|
|
if (device.functions.vkGetMemoryWin32Handle(device.vk_handle(), &info, &handle) != VK_SUCCESS) {
|
|
|
|
|
CLOG_ERROR(&LOG, "Failed to get Windows handle for Vulkan pixel buffer");
|
2025-05-08 22:38:55 +02:00
|
|
|
return native_handle;
|
2025-04-12 14:21:03 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-08 22:38:55 +02:00
|
|
|
native_handle.handle = int64_t(handle);
|
|
|
|
|
native_handle.size = memory_size;
|
2025-04-12 14:21:03 +02:00
|
|
|
#else
|
|
|
|
|
/* Opaque file descriptor. */
|
|
|
|
|
VkMemoryGetFdInfoKHR info = {};
|
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
|
|
|
|
|
info.pNext = nullptr;
|
|
|
|
|
info.memory = memory;
|
|
|
|
|
info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
|
|
|
|
|
|
|
|
int fd = -1;
|
|
|
|
|
if (device.functions.vkGetMemoryFd(device.vk_handle(), &info, &fd) != VK_SUCCESS) {
|
|
|
|
|
CLOG_ERROR(&LOG, "Failed to get file descriptor for Vulkan pixel buffer");
|
2025-05-08 22:38:55 +02:00
|
|
|
return native_handle;
|
2025-04-12 14:21:03 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-08 22:38:55 +02:00
|
|
|
native_handle.handle = int64_t(fd);
|
|
|
|
|
native_handle.size = memory_size;
|
2025-04-12 14:21:03 +02:00
|
|
|
#endif
|
|
|
|
|
|
2025-05-08 22:38:55 +02:00
|
|
|
return native_handle;
|
2022-12-02 08:35:17 +01:00
|
|
|
}
|
|
|
|
|
|
2023-05-25 08:50:14 +02:00
|
|
|
size_t VKPixelBuffer::get_size()
|
2022-12-02 08:35:17 +01:00
|
|
|
{
|
|
|
|
|
return size_;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 15:49:04 +11:00
|
|
|
} // namespace blender::gpu
|