Files
test2/source/blender/gpu/vulkan/vk_pixel_buffer.cc
Jeroen Bakker 1dedbe3f9a Fix: Vulkan: VMA validation errors
Fixes several validation errors when using VMA.
- Always enable buffer device address in VMA as it is already a Blender
  requirement.
- Add host access hints when host access is needed.

Pull Request: https://projects.blender.org/blender/blender/pulls/146312
2025-09-15 16:47:26 +02:00

123 lines
3.1 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,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
0.8f,
memory_export);
debug::object_label(buffer_.vk_handle(), "PixelBuffer");
buffer_initialized_ = true;
buffer_memory_export_ = memory_export;
}
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()
{
VKDevice &device = VKBackend::get().device;
GPUPixelBufferNativeHandle native_handle;
/* 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