Files
test/source/blender/gpu/vulkan/vk_pixel_buffer.cc
Jeroen Bakker bd139fef14 Fix: Vulkan: Validation error on devices without external memory
Qualcomm devices don't support external memory, but there an external
memory pool was still being constructed. This PR skips the creation and
asserts when using external memory on those devices.

Pull Request: https://projects.blender.org/blender/blender/pulls/139326
2025-05-23 15:59:29 +02:00

126 lines
3.2 KiB
C++

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "vk_pixel_buffer.hh"
#include "vk_backend.hh"
#include "CLG_log.h"
namespace blender::gpu {
static CLG_LogRef LOG = {"gpu.vulkan"};
VKPixelBuffer::VKPixelBuffer(size_t size) : PixelBuffer(size) {}
void VKPixelBuffer::create(bool memory_export)
{
/* 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_,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VmaAllocationCreateFlags(0),
memory_export);
debug::object_label(buffer_.vk_handle(), "PixelBuffer");
buffer_initialized_ = true;
buffer_memory_export_ = memory_export;
native_handle_ = GPUPixelBufferNativeHandle{};
}
void *VKPixelBuffer::map()
{
/* Vulkan buffers are always mapped between allocation and freeing. */
create(false);
return buffer_.mapped_memory_get();
}
void VKPixelBuffer::unmap()
{
/* Vulkan buffers are always mapped between allocation and freeing. */
}
GPUPixelBufferNativeHandle VKPixelBuffer::get_native_handle()
{
/* Initialize once. */
if (buffer_initialized_) {
return native_handle_;
}
VKDevice &device = VKBackend::get().device;
/* Functionality supported? */
if (!device.extensions_get().external_memory) {
return native_handle_;
}
/* 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");
return native_handle_;
}
#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");
return native_handle_;
}
native_handle_.handle = int64_t(handle);
native_handle_.size = memory_size;
#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");
return native_handle_;
}
native_handle_.handle = int64_t(fd);
native_handle_.size = memory_size;
#endif
return native_handle_;
}
size_t VKPixelBuffer::get_size()
{
return size_;
}
} // namespace blender::gpu