diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e570cb7..5259bc85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ include_directories("${Anvil_BINARY_DIR}/include" "${Anvil_SOURCE_DIR}" "${Anvil_SOURCE_DIR}/deps" "${Anvil_SOURCE_DIR}/include") - + if (WIN32) if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") link_directories ($ENV{VK_SDK_PATH}/Bin @@ -46,6 +46,7 @@ SET (SRC_LIST "${Anvil_SOURCE_DIR}/include/misc/memalloc_backends/backend_onesho "${Anvil_SOURCE_DIR}/include/misc/dummy_window.h" "${Anvil_SOURCE_DIR}/include/misc/event_create_info.h" "${Anvil_SOURCE_DIR}/include/misc/extensions.h" + "${Anvil_SOURCE_DIR}/include/misc/external_handle.h" "${Anvil_SOURCE_DIR}/include/misc/fence_create_info.h" "${Anvil_SOURCE_DIR}/include/misc/formats.h" "${Anvil_SOURCE_DIR}/include/misc/fp16.h" @@ -56,6 +57,7 @@ SET (SRC_LIST "${Anvil_SOURCE_DIR}/include/misc/memalloc_backends/backend_onesho "${Anvil_SOURCE_DIR}/include/misc/image_view_create_info.h" "${Anvil_SOURCE_DIR}/include/misc/io.h" "${Anvil_SOURCE_DIR}/include/misc/memory_allocator.h" + "${Anvil_SOURCE_DIR}/include/misc/memory_block_create_info.h" "${Anvil_SOURCE_DIR}/include/misc/mt_safety.h" "${Anvil_SOURCE_DIR}/include/misc/object_tracker.h" "${Anvil_SOURCE_DIR}/include/misc/page_tracker.h" @@ -120,6 +122,7 @@ SET (SRC_LIST "${Anvil_SOURCE_DIR}/include/misc/memalloc_backends/backend_onesho "${Anvil_SOURCE_DIR}/src/misc/debug_marker.cpp" "${Anvil_SOURCE_DIR}/src/misc/descriptor_set_create_info.cpp" "${Anvil_SOURCE_DIR}/src/misc/dummy_window.cpp" + "${Anvil_SOURCE_DIR}/src/misc/external_handle.cpp" "${Anvil_SOURCE_DIR}/src/misc/event_create_info.cpp" "${Anvil_SOURCE_DIR}/src/misc/fence_create_info.cpp" "${Anvil_SOURCE_DIR}/src/misc/formats.cpp" @@ -131,6 +134,7 @@ SET (SRC_LIST "${Anvil_SOURCE_DIR}/include/misc/memalloc_backends/backend_onesho "${Anvil_SOURCE_DIR}/src/misc/image_view_create_info.cpp" "${Anvil_SOURCE_DIR}/src/misc/io.cpp" "${Anvil_SOURCE_DIR}/src/misc/memory_allocator.cpp" + "${Anvil_SOURCE_DIR}/src/misc/memory_block_create_info.cpp" "${Anvil_SOURCE_DIR}/src/misc/object_tracker.cpp" "${Anvil_SOURCE_DIR}/src/misc/page_tracker.cpp" "${Anvil_SOURCE_DIR}/src/misc/pools.cpp" diff --git a/examples/DynamicBuffers/src/app.cpp b/examples/DynamicBuffers/src/app.cpp index 3dff0ae0..e64174c8 100644 --- a/examples/DynamicBuffers/src/app.cpp +++ b/examples/DynamicBuffers/src/app.cpp @@ -303,14 +303,15 @@ void App::draw_frame() &t); /* Submit jobs to relevant queues and make sure they are correctly synchronized */ - m_device_ptr->get_universal_queue(0)->submit_command_buffer_with_signal_wait_semaphores(m_command_buffers[n_swapchain_image].get(), - 1, /* n_semaphores_to_signal */ - &curr_frame_signal_semaphore_ptr, - 1, /* n_semaphores_to_wait_on */ - &curr_frame_wait_semaphore_ptr, - &wait_stage_mask, - false, /* should_block */ - nullptr); + m_device_ptr->get_universal_queue(0)->submit( + Anvil::SubmitInfo::create_wait_execute_signal(m_command_buffers[n_swapchain_image].get(), + 1, /* n_semaphores_to_signal */ + &curr_frame_signal_semaphore_ptr, + 1, /* n_semaphores_to_wait_on */ + &curr_frame_wait_semaphore_ptr, + &wait_stage_mask, + false) /* should_block */ + ); m_present_queue_ptr->present(m_swapchain_ptr.get(), n_swapchain_image, diff --git a/examples/MultiViewport/src/app.cpp b/examples/MultiViewport/src/app.cpp index 888b5c3b..d7c24b17 100644 --- a/examples/MultiViewport/src/app.cpp +++ b/examples/MultiViewport/src/app.cpp @@ -243,14 +243,15 @@ void App::draw_frame() n_swapchain_image = m_swapchain_ptr->acquire_image(curr_frame_wait_semaphore_ptr); /* Submit work chunk and present */ - m_device_ptr->get_universal_queue(0)->submit_command_buffer_with_signal_wait_semaphores(m_command_buffers[n_swapchain_image].get(), - 1, /* n_semaphores_to_signal */ - &curr_frame_signal_semaphore_ptr, - 1, /* n_semaphores_to_wait_on */ - &curr_frame_wait_semaphore_ptr, - &wait_stage_mask, - false, /* should_block */ - nullptr); /* opt_fence_ptr */ + m_device_ptr->get_universal_queue(0)->submit( + Anvil::SubmitInfo::create_wait_execute_signal(m_command_buffers[n_swapchain_image].get(), + 1, /* n_semaphores_to_signal */ + &curr_frame_signal_semaphore_ptr, + 1, /* n_semaphores_to_wait_on */ + &curr_frame_wait_semaphore_ptr, + &wait_stage_mask, + false) /* should_block */ + ); present_queue_ptr->present(m_swapchain_ptr.get(), n_swapchain_image, diff --git a/examples/OcclusionQuery/src/app.cpp b/examples/OcclusionQuery/src/app.cpp index 56fd072f..56fd9789 100644 --- a/examples/OcclusionQuery/src/app.cpp +++ b/examples/OcclusionQuery/src/app.cpp @@ -295,14 +295,16 @@ void App::draw_frame() }; const uint32_t n_cmd_buffers = sizeof(cmd_buffers) / sizeof(cmd_buffers[0]); - present_queue_ptr->submit_command_buffers(n_cmd_buffers, - cmd_buffers, - 1, /* n_semaphores_to_signal */ - &curr_frame_signal_semaphore_ptr, - 1, /* n_semaphores_to_wait_on */ - &curr_frame_wait_semaphore_ptr, - &wait_stage_mask, - false); /* should_block */ + present_queue_ptr->submit( + Anvil::SubmitInfo::create_wait_execute_signal(cmd_buffers, + n_cmd_buffers, + 1, /* n_semaphores_to_signal */ + &curr_frame_signal_semaphore_ptr, + 1, /* n_semaphores_to_wait_on */ + &curr_frame_wait_semaphore_ptr, + &wait_stage_mask, + false) /* should_block */ + ); present_queue_ptr->present(m_swapchain_ptr.get(), n_swapchain_image, diff --git a/examples/OutOfOrderRasterization/src/app.cpp b/examples/OutOfOrderRasterization/src/app.cpp index 44be3923..2e2e63f2 100644 --- a/examples/OutOfOrderRasterization/src/app.cpp +++ b/examples/OutOfOrderRasterization/src/app.cpp @@ -344,13 +344,15 @@ void App::draw_frame() } { - m_present_queue_ptr->submit_command_buffer_with_signal_wait_semaphores(render_cmdbuffer_ptr, - 1, /* n_semaphores_to_signal */ - &frame_ready_for_present_semaphore_ptr, - 1, /* n_semaphores_to_wait_on */ - &frame_ready_to_render_semaphore_ptr, - &wait_stage_mask, - false /* should_block */); + m_present_queue_ptr->submit( + Anvil::SubmitInfo::create_wait_execute_signal(render_cmdbuffer_ptr, + 1, /* n_semaphores_to_signal */ + &frame_ready_for_present_semaphore_ptr, + 1, /* n_semaphores_to_wait_on */ + &frame_ready_to_render_semaphore_ptr, + &wait_stage_mask, + false /* should_block */) + ); } { diff --git a/examples/PushConstants/src/app.cpp b/examples/PushConstants/src/app.cpp index f704345c..2424d6b0 100644 --- a/examples/PushConstants/src/app.cpp +++ b/examples/PushConstants/src/app.cpp @@ -282,13 +282,15 @@ void App::draw_frame() /* Submit work chunk and present */ update_data_ub_contents(n_swapchain_image); - present_queue_ptr->submit_command_buffer_with_signal_wait_semaphores(m_command_buffers[n_swapchain_image].get(), - 1, /* n_semaphores_to_signal */ - &curr_frame_signal_semaphore_ptr, - 1, /* n_semaphores_to_wait_on */ - &curr_frame_wait_semaphore_ptr, - &wait_stage_mask, - false /* should_block */); + present_queue_ptr->submit( + Anvil::SubmitInfo::create(m_command_buffers[n_swapchain_image].get(), + 1, /* n_semaphores_to_signal */ + &curr_frame_signal_semaphore_ptr, + 1, /* n_semaphores_to_wait_on */ + &curr_frame_wait_semaphore_ptr, + &wait_stage_mask, + false /* should_block */) + ); present_queue_ptr->present(m_swapchain_ptr.get(), n_swapchain_image, diff --git a/include/misc/buffer_create_info.h b/include/misc/buffer_create_info.h index 77d533d0..5230fc6e 100644 --- a/include/misc/buffer_create_info.h +++ b/include/misc/buffer_create_info.h @@ -119,16 +119,16 @@ namespace Anvil * @param in_residency_scope Scope of residency to support for the buffer. * @param in_external_memory_handle_types If the buffer is going to be exported to another process or Vulkan instance, use * this field to specify which handle types the allocation needs to support. Please see - * documentation of Anvil::ExternalMemoryHandleTypeFlags for more details. + * documentation of Anvil::ExternalMemoryHandleTypeBits for more details. **/ - static Anvil::BufferCreateInfoUniquePtr create_sparse_no_alloc(const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - Anvil::SparseResidencyScope in_residency_scope, - MTSafety in_mt_safety = MT_SAFETY_INHERIT_FROM_PARENT_DEVICE, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + static Anvil::BufferCreateInfoUniquePtr create_sparse_no_alloc(const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + Anvil::SparseResidencyScope in_residency_scope, + MTSafety in_mt_safety = MT_SAFETY_INHERIT_FROM_PARENT_DEVICE, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); const void* const get_client_data() const { @@ -140,7 +140,7 @@ namespace Anvil return m_device_ptr; } - const Anvil::ExternalMemoryHandleTypeFlags& get_external_memory_handle_types() const + const Anvil::ExternalMemoryHandleTypeBits& get_external_memory_handle_types() const { return m_external_memory_handle_types; } @@ -222,7 +222,7 @@ namespace Anvil m_device_ptr = in_device_ptr; } - void set_external_memory_handle_types(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) + void set_external_memory_handle_types(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) { m_external_memory_handle_types = in_external_memory_handle_types; } @@ -267,43 +267,43 @@ namespace Anvil /* Private functions */ - BufferCreateInfo(const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - Anvil::SparseResidencyScope in_residency_scope, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types); - BufferCreateInfo(const Anvil::BufferType& in_buffer_type, - const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - MemoryFeatureFlags in_memory_features, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types, - const void* in_opt_client_data_ptr); - BufferCreateInfo(Anvil::Buffer* in_parent_buffer_ptr, - VkDeviceSize in_start_offset, - VkDeviceSize in_size); + BufferCreateInfo(const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + Anvil::SparseResidencyScope in_residency_scope, + MTSafety in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types); + BufferCreateInfo(const Anvil::BufferType& in_buffer_type, + const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + MemoryFeatureFlags in_memory_features, + MTSafety in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types, + const void* in_opt_client_data_ptr); + BufferCreateInfo(Anvil::Buffer* in_parent_buffer_ptr, + VkDeviceSize in_start_offset, + VkDeviceSize in_size); /* Private variables */ - const void* m_client_data_ptr; - const Anvil::BaseDevice* m_device_ptr; - Anvil::ExternalMemoryHandleTypeFlags m_external_memory_handle_types; - Anvil::MemoryFeatureFlags m_memory_features; - MTSafety m_mt_safety; - Anvil::Buffer* const m_parent_buffer_ptr; - Anvil::QueueFamilyBits m_queue_families; - const Anvil::SparseResidencyScope m_residency_scope; - VkSharingMode m_sharing_mode; - VkDeviceSize m_size; - VkDeviceSize m_start_offset; - const BufferType m_type; - VkBufferUsageFlags m_usage_flags; + const void* m_client_data_ptr; + const Anvil::BaseDevice* m_device_ptr; + Anvil::ExternalMemoryHandleTypeBits m_external_memory_handle_types; + Anvil::MemoryFeatureFlags m_memory_features; + MTSafety m_mt_safety; + Anvil::Buffer* const m_parent_buffer_ptr; + Anvil::QueueFamilyBits m_queue_families; + const Anvil::SparseResidencyScope m_residency_scope; + VkSharingMode m_sharing_mode; + VkDeviceSize m_size; + VkDeviceSize m_start_offset; + const BufferType m_type; + VkBufferUsageFlags m_usage_flags; ANVIL_DISABLE_ASSIGNMENT_OPERATOR(BufferCreateInfo); ANVIL_DISABLE_COPY_CONSTRUCTOR(BufferCreateInfo); diff --git a/include/misc/extensions.h b/include/misc/extensions.h index 5a493ee3..8185a5ab 100644 --- a/include/misc/extensions.h +++ b/include/misc/extensions.h @@ -54,12 +54,24 @@ namespace Anvil ValueType khr_16bit_storage; ValueType khr_bind_memory2; ValueType khr_descriptor_update_template; + ValueType khr_external_fence; ValueType khr_external_memory; + ValueType khr_external_semaphore; ValueType khr_maintenance1; ValueType khr_maintenance3; ValueType khr_storage_buffer_storage_class; ValueType khr_swapchain; + #if defined(_WIN32) + ValueType khr_external_fence_win32; + ValueType khr_external_memory_win32; + ValueType khr_external_semaphore_win32; + #else + ValueType khr_external_fence_fd; + ValueType khr_external_memory_fd; + ValueType khr_external_semaphore_fd; + #endif + std::map values_by_extension_names; @@ -103,7 +115,18 @@ namespace Anvil {ExtensionData(VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, &ext_shader_subgroup_vote)}, {ExtensionData(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, &khr_16bit_storage)}, {ExtensionData(VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, &khr_descriptor_update_template)}, + {ExtensionData(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME, &khr_external_fence)}, {ExtensionData(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, &khr_external_memory)}, + {ExtensionData(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, &khr_external_semaphore)}, + #if defined(_WIN32) + {ExtensionData(VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME, &khr_external_fence_win32)}, + {ExtensionData(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, &khr_external_memory_win32)}, + {ExtensionData(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, &khr_external_semaphore_win32)}, + #else + {ExtensionData(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, &khr_external_fence_fd)}, + {ExtensionData(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, &khr_external_memory_fd)}, + {ExtensionData(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, &khr_external_semaphore_fd)}, + #endif {ExtensionData(VK_KHR_MAINTENANCE1_EXTENSION_NAME, &khr_maintenance1)}, {ExtensionData(VK_KHR_MAINTENANCE3_EXTENSION_NAME, &khr_maintenance3)}, {ExtensionData(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, &khr_bind_memory2)}, @@ -134,7 +157,9 @@ namespace Anvil template struct InstanceExtensions { + ValueType khr_external_fence_capabilities; ValueType khr_external_memory_capabilities; + ValueType khr_external_semaphore_capabilities; ValueType khr_get_physical_device_properties2; ValueType khr_surface; @@ -166,7 +191,9 @@ namespace Anvil std::vector recognized_extensions = { + {ExtensionData(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, &khr_external_fence_capabilities)}, {ExtensionData(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, &khr_external_memory_capabilities)}, + {ExtensionData(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, &khr_external_semaphore_capabilities)}, {ExtensionData(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, &khr_get_physical_device_properties2)}, {ExtensionData(VK_KHR_SURFACE_EXTENSION_NAME, &khr_surface)}, @@ -228,7 +255,18 @@ namespace Anvil virtual ValueType khr_16bit_storage () const = 0; virtual ValueType khr_bind_memory2 () const = 0; virtual ValueType khr_descriptor_update_template () const = 0; + virtual ValueType khr_external_fence () const = 0; virtual ValueType khr_external_memory () const = 0; + virtual ValueType khr_external_semaphore () const = 0; + #if defined(_WIN32) + virtual ValueType khr_external_fence_win32 () const = 0; + virtual ValueType khr_external_memory_win32 () const = 0; + virtual ValueType khr_external_semaphore_win32() const = 0; + #else + virtual ValueType khr_external_fence_fd () const = 0; + virtual ValueType khr_external_memory_fd () const = 0; + virtual ValueType khr_external_semaphore_fd() const = 0; + #endif virtual ValueType khr_maintenance1 () const = 0; virtual ValueType khr_maintenance3 () const = 0; virtual ValueType khr_storage_buffer_storage_class () const = 0; @@ -246,7 +284,9 @@ namespace Anvil /* Stub */ } + virtual bool khr_external_fence_capabilities () const = 0; virtual bool khr_external_memory_capabilities () const = 0; + virtual bool khr_external_semaphore_capabilities() const = 0; virtual bool khr_get_physical_device_properties2() const = 0; virtual bool khr_surface () const = 0; @@ -500,6 +540,29 @@ namespace Anvil return m_device_extensions_ptr->khr_descriptor_update_template; } + ValueType khr_external_fence() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_fence; + } + + #if defined(_WIN32) + ValueType khr_external_fence_win32() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_fence_win32; + } + #else + ValueType khr_external_fence_fd() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_fence_fd; + } + #endif + ValueType khr_external_memory() const final { anvil_assert(m_expose_device_extensions); @@ -507,6 +570,45 @@ namespace Anvil return m_device_extensions_ptr->khr_external_memory; } + #if defined(_WIN32) + ValueType khr_external_memory_win32() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_memory_win32; + } + #else + ValueType khr_external_memory_fd() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_memory_fd; + } + #endif + + ValueType khr_external_semaphore() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_semaphore; + } + + #if defined(_WIN32) + ValueType khr_external_semaphore_win32() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_semaphore_win32; + } + #else + ValueType khr_external_semaphore_fd() const final + { + anvil_assert(m_expose_device_extensions); + + return m_device_extensions_ptr->khr_external_semaphore_fd; + } + #endif + ValueType khr_maintenance1() const final { anvil_assert(m_expose_device_extensions); @@ -537,6 +639,13 @@ namespace Anvil /* IExtensionInfoInstance */ + ValueType khr_external_fence_capabilities() const final + { + anvil_assert(!m_expose_device_extensions); + + return m_instance_extensions_ptr->khr_external_fence_capabilities; + } + ValueType khr_external_memory_capabilities() const final { anvil_assert(!m_expose_device_extensions); @@ -544,6 +653,13 @@ namespace Anvil return m_instance_extensions_ptr->khr_external_memory_capabilities; } + ValueType khr_external_semaphore_capabilities() const final + { + anvil_assert(!m_expose_device_extensions); + + return m_instance_extensions_ptr->khr_external_semaphore_capabilities; + } + ValueType khr_get_physical_device_properties2() const final { anvil_assert(!m_expose_device_extensions); @@ -589,7 +705,7 @@ namespace Anvil { DeviceExtensionConfiguration() { - /* NOTE: By default, Anvil enables all extensions it has support implemented for, which are reported + /* NOTE: By default, Anvil enables nearly all extensions it has support implemented for, which are reported * as available. */ { @@ -614,6 +730,9 @@ namespace Anvil extension_status[VK_EXT_DEBUG_MARKER_EXTENSION_NAME] = EXTENSION_AVAILABILITY_IGNORE; } #endif + + /* 3. Disable VK_AMD_shader_info by default. */ + extension_status[VK_AMD_SHADER_INFO_EXTENSION_NAME] = EXTENSION_AVAILABILITY_IGNORE; } std::map extension_status; diff --git a/include/misc/external_handle.h b/include/misc/external_handle.h new file mode 100644 index 00000000..8b06d3d6 --- /dev/null +++ b/include/misc/external_handle.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#ifndef MISC_EXTERNAL_HANDLE_H +#define MISC_EXTERNAL_HANDLE_H + +#include "misc/types.h" + +namespace Anvil +{ + class ExternalHandle + { + public: + /* Public functions */ + static ExternalHandleUniquePtr create(const ExternalHandleType& in_handle, + const bool& in_close_at_destruction_time); + + ~ExternalHandle(); + + ExternalHandleType get_handle() const + { + return m_handle; + } + + private: + ExternalHandle(const ExternalHandleType& in_handle, + const bool& in_close_at_destruction_time); + + const bool m_close_at_destruction_time; + const ExternalHandleType m_handle; + + ANVIL_DISABLE_ASSIGNMENT_OPERATOR(ExternalHandle); + ANVIL_DISABLE_COPY_CONSTRUCTOR(ExternalHandle); + }; +} /* namespace Anvil */ + +#endif /* MISC_EXTERNAL_HANDLE_H */ diff --git a/include/misc/fence_create_info.h b/include/misc/fence_create_info.h index d10b5739..5021c9c5 100644 --- a/include/misc/fence_create_info.h +++ b/include/misc/fence_create_info.h @@ -35,7 +35,8 @@ namespace Anvil * * NOTE: Unless specified later with a corresponding set_..() invocation, the following parameters are assumed by default: * - * - MT safety: MT_SAFETY_INHERIT_FROM_PARENT_DEVICE + * - Exportable external fence handle type: none + * - MT safety: MT_SAFETY_INHERIT_FROM_PARENT_DEVICE */ static Anvil::FenceCreateInfoUniquePtr create(const Anvil::BaseDevice* in_device_ptr, bool in_create_signalled); @@ -45,6 +46,31 @@ namespace Anvil return m_device_ptr; } + const Anvil::ExternalFenceHandleTypeBits& get_exportable_external_fence_handle_types() const + { + return m_exportable_external_fence_handle_types; + } + + #if defined(_WIN32) + /* Returns true if set_exportable_nt_handle_info() has been called prior to this call. + * Otherwise returns false. + * + * If the func returns true, *out_result_ptr is set to the queried data. + */ + bool get_exportable_nt_handle_info(const ExternalNTHandleInfo** out_result_ptr_ptr) const + { + bool result = false; + + if (m_exportable_nt_handle_info_specified) + { + *out_result_ptr_ptr = &m_exportable_nt_handle_info; + result = true; + } + + return result; + } + #endif + const MTSafety& get_mt_safety() const { return m_mt_safety; @@ -55,6 +81,36 @@ namespace Anvil return m_create_signalled; } + #if defined(_WIN32) + /* Lets the app specify additional details for exportable NT handles. + * + * If @param in_name is zero-sized, member of the VkExportFenceWin32HandleInfoKHR struct, as chained to the VkFenceCreateInfo struct chain, + * will be set to nullptr. + * + * Requires VK_KHR_external_fence_win32 + */ + void set_exportable_nt_handle_info(const SECURITY_ATTRIBUTES* in_opt_attributes_ptr, + const DWORD& in_access, + const std::wstring& in_name) + { + anvil_assert(!m_exportable_nt_handle_info_specified); + + m_exportable_nt_handle_info.access = in_access; + m_exportable_nt_handle_info.attributes_ptr = in_opt_attributes_ptr; + m_exportable_nt_handle_info.name = in_name; + + m_exportable_nt_handle_info_specified = true; + } + #endif + + /* TODO + * + * Requires VK_KHR_external_fence. + */ + void set_exportable_external_fence_handle_types(const Anvil::ExternalFenceHandleTypeBits& in_external_fence_handle_types) + { + m_exportable_external_fence_handle_types = in_external_fence_handle_types; + } void set_device(const Anvil::BaseDevice* in_device_ptr) { @@ -78,9 +134,15 @@ namespace Anvil MTSafety in_mt_safety); /* Private variables */ - bool m_create_signalled; - const Anvil::BaseDevice* m_device_ptr; - Anvil::MTSafety m_mt_safety; + bool m_create_signalled; + const Anvil::BaseDevice* m_device_ptr; + Anvil::ExternalFenceHandleTypeBits m_exportable_external_fence_handle_types; + Anvil::MTSafety m_mt_safety; + + #ifdef _WIN32 + ExternalNTHandleInfo m_exportable_nt_handle_info; + bool m_exportable_nt_handle_info_specified; + #endif ANVIL_DISABLE_ASSIGNMENT_OPERATOR(FenceCreateInfo); ANVIL_DISABLE_COPY_CONSTRUCTOR(FenceCreateInfo); diff --git a/include/misc/image_create_info.h b/include/misc/image_create_info.h index 4cdf1f32..e101bf0c 100644 --- a/include/misc/image_create_info.h +++ b/include/misc/image_create_info.h @@ -254,7 +254,7 @@ namespace Anvil return m_device_ptr; } - const Anvil::ExternalMemoryHandleTypeFlags& get_external_memory_handle_types() const + const Anvil::ExternalMemoryHandleTypeBits& get_external_memory_handle_types() const { return m_external_memory_handle_types; } @@ -375,7 +375,7 @@ namespace Anvil m_depth = in_depth; } - void set_external_memory_handle_types(const ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) + void set_external_memory_handle_types(const ExternalMemoryHandleTypeBits& in_external_memory_handle_types) { m_external_memory_handle_types = in_external_memory_handle_types; } @@ -468,53 +468,53 @@ namespace Anvil private: /* Private functions */ - ImageCreateInfo(Anvil::ImageType in_type, - const Anvil::BaseDevice* in_device_ptr, - VkImageType in_type_vk, - VkFormat in_format, - VkImageTiling in_tiling, - VkSharingMode in_sharing_mode, - VkImageUsageFlags in_usage, - uint32_t in_base_mipmap_width, - uint32_t in_base_mipmap_height, - uint32_t in_base_mipmap_depth, - uint32_t in_n_layers, - VkSampleCountFlagBits in_sample_count, - bool in_use_full_mipmap_chain, - ImageCreateFlags in_create_flags, - Anvil::QueueFamilyBits in_queue_families, - VkImageLayout in_post_create_image_layout, - const VkImageLayout& in_post_alloc_image_layout, - const std::vector* in_opt_mipmaps_ptr, - const Anvil::MTSafety& in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types, - const Anvil::MemoryFeatureFlags& in_memory_features, - const Anvil::SparseResidencyScope& in_residency_scope); + ImageCreateInfo(Anvil::ImageType in_type, + const Anvil::BaseDevice* in_device_ptr, + VkImageType in_type_vk, + VkFormat in_format, + VkImageTiling in_tiling, + VkSharingMode in_sharing_mode, + VkImageUsageFlags in_usage, + uint32_t in_base_mipmap_width, + uint32_t in_base_mipmap_height, + uint32_t in_base_mipmap_depth, + uint32_t in_n_layers, + VkSampleCountFlagBits in_sample_count, + bool in_use_full_mipmap_chain, + ImageCreateFlags in_create_flags, + Anvil::QueueFamilyBits in_queue_families, + VkImageLayout in_post_create_image_layout, + const VkImageLayout& in_post_alloc_image_layout, + const std::vector* in_opt_mipmaps_ptr, + const Anvil::MTSafety& in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types, + const Anvil::MemoryFeatureFlags& in_memory_features, + const Anvil::SparseResidencyScope& in_residency_scope); /* Private variables */ - Anvil::ImageCreateFlags m_create_flags; - uint32_t m_depth; - const Anvil::BaseDevice* m_device_ptr; - Anvil::ExternalMemoryHandleTypeFlags m_external_memory_handle_types; - VkFormat m_format; - uint32_t m_height; - Anvil::MemoryFeatureFlags m_memory_features; - std::vector m_mipmaps_to_upload; - Anvil::MTSafety m_mt_safety; - uint32_t m_n_layers; - VkImageLayout m_post_alloc_layout; - VkImageLayout m_post_create_layout; - Anvil::QueueFamilyBits m_queue_families; - Anvil::SparseResidencyScope m_residency_scope; - VkSampleCountFlags m_sample_count; - VkSharingMode m_sharing_mode; - VkImageTiling m_tiling; - const Anvil::ImageType m_type; - const VkImageType m_type_vk; - VkImageUsageFlags m_usage_flags; - bool m_use_full_mipmap_chain; - uint32_t m_width; + Anvil::ImageCreateFlags m_create_flags; + uint32_t m_depth; + const Anvil::BaseDevice* m_device_ptr; + Anvil::ExternalMemoryHandleTypeBits m_external_memory_handle_types; + VkFormat m_format; + uint32_t m_height; + Anvil::MemoryFeatureFlags m_memory_features; + std::vector m_mipmaps_to_upload; + Anvil::MTSafety m_mt_safety; + uint32_t m_n_layers; + VkImageLayout m_post_alloc_layout; + VkImageLayout m_post_create_layout; + Anvil::QueueFamilyBits m_queue_families; + Anvil::SparseResidencyScope m_residency_scope; + VkSampleCountFlags m_sample_count; + VkSharingMode m_sharing_mode; + VkImageTiling m_tiling; + const Anvil::ImageType m_type; + const VkImageType m_type_vk; + VkImageUsageFlags m_usage_flags; + bool m_use_full_mipmap_chain; + uint32_t m_width; /* Only used for swapchain wrapper images */ uint32_t m_n_swapchain_image; diff --git a/include/misc/memalloc_backends/backend_oneshot.h b/include/misc/memalloc_backends/backend_oneshot.h index 27e8eeb5..5ac7fa7d 100644 --- a/include/misc/memalloc_backends/backend_oneshot.h +++ b/include/misc/memalloc_backends/backend_oneshot.h @@ -61,14 +61,14 @@ namespace Anvil private: /* IMemoryAllocatorBackend functions */ - bool bake (Anvil::MemoryAllocator::Items& in_items) final; - VkResult map (void* in_memory_object, - VkDeviceSize in_start_offset, - VkDeviceSize in_size, - void** out_result_ptr) final; + bool bake (Anvil::MemoryAllocator::Items& in_items) final; + VkResult map (void* in_memory_object, + VkDeviceSize in_start_offset, + VkDeviceSize in_size, + void** out_result_ptr) final; bool supports_baking () const final; - bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const final; - void unmap (void* in_memory_object) final; + bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const final; + void unmap (void* in_memory_object) final; /* Private functions */ diff --git a/include/misc/memalloc_backends/backend_vma.h b/include/misc/memalloc_backends/backend_vma.h index c19726c1..8877a8e2 100644 --- a/include/misc/memalloc_backends/backend_vma.h +++ b/include/misc/memalloc_backends/backend_vma.h @@ -123,14 +123,14 @@ namespace Anvil /* IMemoryAllocatorBackend functions */ - bool bake (Anvil::MemoryAllocator::Items& in_items) final; - VkResult map (void* in_memory_object, - VkDeviceSize in_start_offset, - VkDeviceSize in_size, - void** out_result_ptr); + bool bake (Anvil::MemoryAllocator::Items& in_items) final; + VkResult map (void* in_memory_object, + VkDeviceSize in_start_offset, + VkDeviceSize in_size, + void** out_result_ptr); bool supports_baking () const final; - bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const final; - void unmap (void* in_memory_object); + bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const final; + void unmap (void* in_memory_object); /* Private variables */ const Anvil::BaseDevice* m_device_ptr; diff --git a/include/misc/memory_allocator.h b/include/misc/memory_allocator.h index 4cb1f7b9..33eb9f8c 100644 --- a/include/misc/memory_allocator.h +++ b/include/misc/memory_allocator.h @@ -69,15 +69,15 @@ namespace Anvil ItemType type; - Anvil::ExternalMemoryHandleTypeFlags alloc_external_memory_handle_types; - MemoryBlockUniquePtr alloc_memory_block_ptr; - uint32_t alloc_memory_final_type; - VkDeviceSize alloc_memory_required_alignment; - MemoryFeatureFlags alloc_memory_required_features; - uint32_t alloc_memory_supported_memory_types; - uint32_t alloc_memory_types; - VkDeviceSize alloc_offset; - VkDeviceSize alloc_size; + Anvil::ExternalMemoryHandleTypeBits alloc_external_memory_handle_types; + MemoryBlockUniquePtr alloc_memory_block_ptr; + uint32_t alloc_memory_final_type; + VkDeviceSize alloc_memory_required_alignment; + MemoryFeatureFlags alloc_memory_required_features; + uint32_t alloc_memory_supported_memory_types; + uint32_t alloc_memory_types; + VkDeviceSize alloc_offset; + VkDeviceSize alloc_size; VkExtent3D extent; bool is_baked; @@ -86,56 +86,56 @@ namespace Anvil VkOffset3D offset; VkImageSubresource subresource; - Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types); - - Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_alloc_offset, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types); - - Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - uint32_t in_n_layer, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_miptail_offset, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types); - - Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - const VkImageSubresource& in_subresource, - const VkOffset3D& in_offset, - const VkExtent3D& in_extent, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types); - - Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types); + Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types); + + Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_alloc_offset, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types); + + Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + uint32_t in_n_layer, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_miptail_offset, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types); + + Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + const VkImageSubresource& in_subresource, + const VkOffset3D& in_offset, + const VkExtent3D& in_extent, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types); + + Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types); /** TODO */ ~Item(); @@ -160,8 +160,8 @@ namespace Anvil /* Stub */ } - virtual bool bake (Items& in_items) = 0; - virtual bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const = 0; + virtual bool bake (Items& in_items) = 0; + virtual bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const = 0; }; /* Public functions */ @@ -189,39 +189,39 @@ namespace Anvil **/ bool add_buffer (Anvil::Buffer* in_buffer_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_float_data_ptr_based_post_fill (Anvil::Buffer* in_buffer_ptr, std::unique_ptr in_data_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_float_data_vector_ptr_based_post_fill (Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_float_data_vector_ptr_based_post_fill (Anvil::Buffer* in_buffer_ptr, const std::vector* in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_uchar8_data_ptr_based_post_fill (Anvil::Buffer* in_buffer_ptr, std::unique_ptr in_data_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_uchar8_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_uint32_data_ptr_based_post_fill (Anvil::Buffer* in_buffer_ptr, std::unique_ptr in_data_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_uint32_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); bool add_buffer_with_uint32_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, const std::vector* in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** TODO * @@ -237,11 +237,11 @@ namespace Anvil * * @return TODO */ - bool add_sparse_buffer_region(Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_offset, - VkDeviceSize in_size, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + bool add_sparse_buffer_region(Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_offset, + VkDeviceSize in_size, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** Adds an Image object which should be assigned storage coming from memory objects * maintained by the Memory Allocator. At baking time, all subresources of the image, @@ -261,9 +261,9 @@ namespace Anvil * * @return true if the image has been successfully scheduled for baking, false otherwise. **/ - bool add_image_whole(Anvil::Image* in_image_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + bool add_image_whole(Anvil::Image* in_image_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** Adds a new Image object whose layer @param in_n_layer 's miptail for @param in_aspect * aspect should be assigned a physical memory backing. The miptail will be bound a memory @@ -287,11 +287,11 @@ namespace Anvil * * @return true if the miptail has been successfully scheduled for baking, false otherwise. */ - bool add_sparse_image_miptail(Anvil::Image* in_image_ptr, - VkImageAspectFlagBits in_aspect, - uint32_t in_n_layer, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + bool add_sparse_image_miptail(Anvil::Image* in_image_ptr, + VkImageAspectFlagBits in_aspect, + uint32_t in_n_layer, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** Adds a single subresource which should be assigned memory backing. * @@ -316,12 +316,12 @@ namespace Anvil * * @return true if the subresource has been successfully scheduled for baking, false otherwise. **/ - bool add_sparse_image_subresource(Anvil::Image* in_image_ptr, - const VkImageSubresource& in_subresource, - const VkOffset3D& in_offset, - VkExtent3D in_extent, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + bool add_sparse_image_subresource(Anvil::Image* in_image_ptr, + const VkImageSubresource& in_subresource, + const VkOffset3D& in_offset, + VkExtent3D in_extent, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** TODO */ bool bake(); @@ -364,14 +364,14 @@ namespace Anvil private: /* Private functions */ - bool add_buffer_internal(Anvil::Buffer* in_buffer_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types); - - bool do_external_memory_handle_type_sanity_checks(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const; - bool is_alloc_supported (uint32_t in_memory_types, - Anvil::MemoryFeatureFlags in_memory_features, - uint32_t* out_opt_filtered_memory_types_ptr) const; + bool add_buffer_internal(Anvil::Buffer* in_buffer_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types); + + bool do_external_memory_handle_type_sanity_checks(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const; + bool is_alloc_supported (uint32_t in_memory_types, + Anvil::MemoryFeatureFlags in_memory_features, + uint32_t* out_opt_filtered_memory_types_ptr) const; void on_is_alloc_pending_for_buffer_query(CallbackArgument* in_callback_arg_ptr); void on_is_alloc_pending_for_image_query (CallbackArgument* in_callback_arg_ptr); diff --git a/include/misc/memory_block_create_info.h b/include/misc/memory_block_create_info.h new file mode 100644 index 00000000..2441e797 --- /dev/null +++ b/include/misc/memory_block_create_info.h @@ -0,0 +1,317 @@ +// +// Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#ifndef MISC_MEMORY_BLOCK_CREATE_INFO_H +#define MISC_MEMORY_BLOCK_CREATE_INFO_H + +#include "misc/types.h" + + +namespace Anvil +{ + class MemoryBlockCreateInfo + { + public: + /* Public functions */ + + /** Spawns a create info instance which can be used to instantiate a memory block whose storage space is maintained + * by another MemoryBlock instance. + * + * @param in_parent_memory_block_ptr MemoryBlock instance to use as a parent. Must not be nullptr. + * Parent memory block must not be mapped. + * @param in_start_offset Start offset of the storage maintained by the specified parent memory block, + * from which the new MemoryBlock instance's storage should start. + * Must not be equal to or larger than parent object's storage size. + * When added to @param in_size, the result value must not be be larger than the remaining + * storage size. + * @param in_size Region size to use for the derived memory block. + **/ + static MemoryBlockCreateInfoUniquePtr create_derived(MemoryBlock* in_parent_memory_block_ptr, + VkDeviceSize in_start_offset, + VkDeviceSize in_size); + + /** Spawns a create info instance which can be used to instantiate a memory block whose lifetime is maintained by a separate + * entity. While the memory block remains reference-counted as usual, the destruction process is carried out by an external + * party via the specified call-back. + * + * This implements a special case required for support of Vulkan Memory Allocator memory allocator backend. Applications + * are very unlikely to ever need to use this create() function. + * + * NOTE: The following parameters take the following default values: + * + * - Exportable external memory handle types: Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE + * - Importable external memory handle type: Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE + * + * These can be further adjusted by callingt corresponding set_..() functions prior to passing the CreateInfo instance + * to MemoryBlock::create(). + * + * TODO + */ + static MemoryBlockCreateInfoUniquePtr create_derived_with_custom_delete_proc(const Anvil::BaseDevice* in_device_ptr, + VkDeviceMemory in_memory, + uint32_t in_allowed_memory_bits, + Anvil::MemoryFeatureFlags in_memory_features, + uint32_t in_memory_type_index, + VkDeviceSize in_size, + VkDeviceSize in_start_offset, + OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function); + + /** Spawns a create info instance which can be used to instantiate a new memory block. + * + * NOTE: The following parameters take the following defautl values: + * + * - Exportable external memory handle types: Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE + * - Importable external memory handle type: Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE + * - MT safety: MT_SAFETY_INHERIT_FROM_PARENT_DEVICE. + * + * These can be further adjusted by callingt corresponding set_..() functions prior to passing the CreateInfo instance + * to MemoryBlock::create(). + * + * @param in_device_ptr Device to use. + * @param in_allowed_memory_bits Memory type bits which meet the allocation requirements. + * @param in_size Required allocation size. + * @param in_memory_features Required memory features. + **/ + static MemoryBlockCreateInfoUniquePtr create_regular(const Anvil::BaseDevice* in_device_ptr, + uint32_t in_allowed_memory_bits, + VkDeviceSize in_size, + Anvil::MemoryFeatureFlags in_memory_features); + + const uint32_t& get_allowed_memory_bits() const + { + return m_allowed_memory_bits; + } + + const Anvil::BaseDevice* get_device() const + { + return m_device_ptr; + } + + const Anvil::ExternalMemoryHandleTypeBits& get_exportable_external_memory_handle_types() const + { + return m_exportable_external_memory_handle_types; + } + + /* Returns true if set_external_handle_import_info() has been called prior to this call. + * Otherwise returns false. + * + * If the func returns true, *out_result_ptr is set to the queried data. + */ + bool get_external_handle_import_info(const ExternalMemoryHandleImportInfo** out_result_ptr_ptr) const + { + bool result = false; + + if (m_external_handle_import_info_specified) + { + *out_result_ptr_ptr = &m_external_handle_import_info; + result = true; + } + + return result; + } + + #if defined(_WIN32) + /* Returns true if set_external_nt_handle_import_info() has been called prior to this call. + * Otherwise returns false. + * + * If the func returns true, *out_result_ptr is set to the queried data. + */ + bool get_external_nt_handle_import_info(const ExternalNTHandleInfo** out_result_ptr_ptr) const + { + bool result = false; + + if (m_external_nt_handle_import_info_specified) + { + *out_result_ptr_ptr = &m_external_nt_handle_import_info; + result = true; + } + + return result; + } + #endif + + const Anvil::ExternalMemoryHandleTypeBit& get_imported_external_memory_handle_type() const + { + return m_imported_external_memory_handle_type; + } + + VkDeviceMemory get_memory() const + { + anvil_assert(m_type == Anvil::MemoryBlockType::DERIVED_WITH_CUSTOM_DELETE_PROC); + + return m_memory; + } + + /** Returns memory features of the underlying memory region */ + Anvil::MemoryFeatureFlags get_memory_features() const; + + /** Returns the memory type index the memory block was allocated from */ + uint32_t get_memory_type_index() const; + + const Anvil::MTSafety& get_mt_safety() const + { + return m_mt_safety; + } + + const Anvil::OnMemoryBlockReleaseCallbackFunction& get_on_release_callback_function() const + { + return m_on_release_callback_function; + } + + /* Returns parent memory block, if one has been defined for this instance */ + Anvil::MemoryBlock* get_parent_memory_block() const + { + return m_parent_memory_block_ptr; + } + + /* Returns the size of the memory block. */ + VkDeviceSize get_size() const + { + return m_size; + } + + /* Returns the start offset of the memory block. + * + * If the memory block has a parent, the returned start offset is NOT relative to the parent memory block's + * start offset (in other words: the returned value is an absolute offset which can be directly used against + * the memory block instance) + */ + VkDeviceSize get_start_offset() const + { + return m_start_offset; + } + + const Anvil::MemoryBlockType& get_type() const + { + return m_type; + } + + /* Requires VK_KHR_external_memory */ + void set_exportable_external_memory_handle_types(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) + { + m_exportable_external_memory_handle_types = in_external_memory_handle_types; + } + + /* Lets the app specify imported handle details. + * + * Under Windows, if @param in_name is zero-sized, member of the VkImportMemoryWin32HandleInfoKHR struct, as chained to the VkMemoryAllocateInfo struct chain, + * will be set to nullptr. + * + * NOTE: For NT handles, you also need to call set_external_nt_handle_import_info(). + * + * Requires VK_KHR_external_memory_fd under Windows. + * Requires VK_KHR_external_memory_win32 under Windows. + */ + #if defined(_WIN32) + void set_external_handle_import_info(ExternalHandleType in_handle, + const std::wstring& in_name) + #else + void set_external_handle_import_info(ExternalHandleType in_handle) + #endif + { + anvil_assert(!m_external_handle_import_info_specified); + + m_external_handle_import_info.handle = in_handle; + + #if defined(_WIN32) + { + m_external_handle_import_info.name = in_name; + } + #endif + + m_external_handle_import_info_specified = true; + } + + #if defined(_WIN32) + /* Lets the app specify additional details for exportable NT handles. + * + * If @param in_name is zero-sized, member of the VkExportMemoryWin32HandleInfoKHR struct, as chained to the VkMemoryAllocateInfo struct chain, + * will be set to nullptr. + * + * Requires VK_KHR_external_memory_win32 + */ + void set_external_nt_handle_import_info(const SECURITY_ATTRIBUTES* in_opt_attributes_ptr, + const DWORD& in_access, + const std::wstring& in_name) + { + anvil_assert(!m_external_nt_handle_import_info_specified); + + m_external_nt_handle_import_info.access = in_access; + m_external_nt_handle_import_info.attributes_ptr = in_opt_attributes_ptr; + m_external_nt_handle_import_info.name = in_name; + + m_external_nt_handle_import_info_specified = true; + } + #endif + + void set_imported_external_memory_handle_type(const Anvil::ExternalMemoryHandleTypeBit& in_memory_handle_type) + { + m_imported_external_memory_handle_type = in_memory_handle_type; + } + + void set_mt_safety(const Anvil::MTSafety& in_mt_safety) + { + m_mt_safety = in_mt_safety; + } + + private: + MemoryBlockCreateInfo(const Anvil::MemoryBlockType& in_type, + const uint32_t& in_allowed_memory_bits, + const Anvil::BaseDevice* in_device_ptr, + VkDeviceMemory in_memory, + const Anvil::MemoryFeatureFlags& in_memory_features, + const uint32_t& in_memory_type_index, + const uint32_t& in_n_physical_devices, + const Anvil::OnMemoryBlockReleaseCallbackFunction& in_on_release_callback_function, + const Anvil::PhysicalDevice* const* in_opt_physical_device_ptr_ptr, + Anvil::MemoryBlock* in_parent_memory_block_ptr, + const VkDeviceSize& in_size, + const VkDeviceSize& in_start_offset); + + uint32_t m_allowed_memory_bits; + const Anvil::BaseDevice* m_device_ptr; + Anvil::ExternalMemoryHandleTypeBits m_exportable_external_memory_handle_types; + Anvil::ExternalMemoryHandleTypeBit m_imported_external_memory_handle_type; + VkDeviceMemory m_memory; + Anvil::MemoryFeatureFlags m_memory_features; + uint32_t m_memory_type_index; + Anvil::MTSafety m_mt_safety; + Anvil::OnMemoryBlockReleaseCallbackFunction m_on_release_callback_function; + Anvil::MemoryBlock* m_parent_memory_block_ptr; + std::vector m_physical_devices; + VkDeviceSize m_size; + VkDeviceSize m_start_offset; + const Anvil::MemoryBlockType m_type; + + #ifdef _WIN32 + ExternalNTHandleInfo m_external_nt_handle_import_info; + bool m_external_nt_handle_import_info_specified; + #endif + + ExternalMemoryHandleImportInfo m_external_handle_import_info; + bool m_external_handle_import_info_specified; + + ANVIL_DISABLE_ASSIGNMENT_OPERATOR(MemoryBlockCreateInfo); + ANVIL_DISABLE_COPY_CONSTRUCTOR(MemoryBlockCreateInfo); + }; +} /* namespace Anvil */ + +#endif /* MISC_MEMORY_BLOCK_CREATE_INFO_H */ \ No newline at end of file diff --git a/include/misc/semaphore_create_info.h b/include/misc/semaphore_create_info.h index 8ca608cd..5968fbf0 100644 --- a/include/misc/semaphore_create_info.h +++ b/include/misc/semaphore_create_info.h @@ -30,14 +30,26 @@ namespace Anvil { public: /* Public functions */ - static Anvil::SemaphoreCreateInfoUniquePtr create(const Anvil::BaseDevice* in_device_ptr, - MTSafety in_mt_safety = MT_SAFETY_INHERIT_FROM_PARENT_DEVICE); + + /* TODO. + * + * NOTE: Unless specified later with a corresponding set_..() invocation, the following parameters are assumed by default: + * + * - Exportable external semaphore handle type: none + * - MT safety: MT_SAFETY_INHERIT_FROM_PARENT_DEVICE + */ + static Anvil::SemaphoreCreateInfoUniquePtr create(const Anvil::BaseDevice* in_device_ptr); const Anvil::BaseDevice* get_device() const { return m_device_ptr; } + const Anvil::ExternalSemaphoreHandleTypeBits& get_exportable_external_semaphore_handle_types() const + { + return m_exportable_external_semaphore_handle_types; + } + const MTSafety& get_mt_safety() const { return m_mt_safety; @@ -48,6 +60,15 @@ namespace Anvil m_device_ptr = in_device_ptr; } + /* TODO + * + * Requires VK_KHR_external_semaphore. + */ + void set_exportable_external_semaphore_handle_types(const Anvil::ExternalFenceHandleTypeBits& in_external_handle_types) + { + m_exportable_external_semaphore_handle_types = in_external_handle_types; + } + void set_mt_safety(const MTSafety& in_mt_safety) { m_mt_safety = in_mt_safety; @@ -59,8 +80,9 @@ namespace Anvil MTSafety in_mt_safety); /* Private variables */ - const Anvil::BaseDevice* m_device_ptr; - Anvil::MTSafety m_mt_safety; + const Anvil::BaseDevice* m_device_ptr; + Anvil::ExternalSemaphoreHandleTypeBits m_exportable_external_semaphore_handle_types; + Anvil::MTSafety m_mt_safety; ANVIL_DISABLE_ASSIGNMENT_OPERATOR(SemaphoreCreateInfo); ANVIL_DISABLE_COPY_CONSTRUCTOR(SemaphoreCreateInfo); diff --git a/include/misc/types.h b/include/misc/types.h index e4dfc8f2..1217e2dd 100644 --- a/include/misc/types.h +++ b/include/misc/types.h @@ -128,6 +128,7 @@ namespace Anvil class DescriptorSetLayout; class DescriptorSetLayoutManager; class DescriptorUpdateTemplate; + class ExternalHandle; class Event; class EventCreateInfo; class Fence; @@ -144,6 +145,7 @@ namespace Anvil class Instance; class MemoryAllocator; class MemoryBlock; + class MemoryBlockCreateInfo; struct MemoryHeap; struct MemoryProperties; struct MemoryType; @@ -185,6 +187,7 @@ namespace Anvil typedef std::unique_ptr > DescriptorSetLayoutManagerUniquePtr; typedef std::unique_ptr > DescriptorSetUniquePtr; typedef std::unique_ptr > DescriptorUpdateTemplateUniquePtr; + typedef std::unique_ptr > ExternalHandleUniquePtr; typedef std::unique_ptr EventCreateInfoUniquePtr; typedef std::unique_ptr > EventUniquePtr; typedef std::unique_ptr FenceCreateInfoUniquePtr; @@ -200,6 +203,7 @@ namespace Anvil typedef std::unique_ptr > ImageViewUniquePtr; typedef std::unique_ptr > InstanceUniquePtr; typedef std::unique_ptr > MemoryAllocatorUniquePtr; + typedef std::unique_ptr MemoryBlockCreateInfoUniquePtr; typedef std::unique_ptr > MemoryBlockUniquePtr; typedef std::unique_ptr > PipelineCacheUniquePtr; typedef std::unique_ptr > PipelineLayoutManagerUniquePtr; @@ -222,9 +226,15 @@ namespace Anvil typedef std::unique_ptr > WindowUniquePtr; }; -/* Defines various enums used by Vulkan API wrapper classes. */ +/* Defines various types used by Vulkan API wrapper classes. */ namespace Anvil { + #if defined(_WIN32) + typedef HANDLE ExternalHandleType; + #else + typedef int ExternalHandleType; + #endif + /** ID of an Anvil framebuffer's attachment */ typedef uint32_t FramebufferAttachmentID; @@ -235,6 +245,9 @@ namespace Anvil typedef std::pair BindingElementArrayRange; + /** "About to be deleted" call-back function prototype. */ + typedef std::function OnMemoryBlockReleaseCallbackFunction; + /** Base pipeline ID. Internal type, used to represent compute / graphics pipeline IDs */ typedef uint32_t PipelineID; diff --git a/include/misc/types_enums.h b/include/misc/types_enums.h index 38d21396..e89262fb 100644 --- a/include/misc/types_enums.h +++ b/include/misc/types_enums.h @@ -39,6 +39,14 @@ namespace Anvil ATTACHMENT_TYPE_UNKNOWN = ATTACHMENT_TYPE_COUNT }; + enum BufferCreateFlagBits + { + BUFFER_CREATE_FLAG_SPARSE_BINDING_BIT = 1 << 0, + BUFFER_CREATE_FLAG_SPARSE_RESIDENCY_BIT = 1 << 1, + BUFFER_CREATE_FLAG_SPARSE_ALIASED_BIT = 1 << 2, + }; + typedef uint32_t BufferCreateFlags; + typedef enum class BufferType { NONSPARSE_ALLOC, @@ -63,10 +71,52 @@ namespace Anvil typedef enum { - /* todo .. */ + EXTERNAL_FENCE_HANDLE_TYPE_NONE = 0, + + #if defined(_WIN32) + EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 1 << 0, + EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 1 << 1, + #else + EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 1 << 2, + EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 1 << 2, + #endif + + } ExternalFenceHandleTypeBit; + typedef uint32_t ExternalFenceHandleTypeBits; + + typedef enum + { + EXTERNAL_MEMORY_HANDLE_TYPE_NONE = 0, + + #if defined(_WIN32) + EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 1 << 0, + EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 1 << 1, + EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 1 << 2, + EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 1 << 3, + EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 1 << 4, + EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 1 << 5, + #else + EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 1 << 6, + #endif + + } ExternalMemoryHandleTypeBit; + typedef uint32_t ExternalMemoryHandleTypeBits; + + typedef enum + { + EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE = 0, - } ExternalMemoryHandleTypeFlag; - typedef uint32_t ExternalMemoryHandleTypeFlags; + #if defined(_WIN32) + EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 1 << 0, + EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 1 << 1, + EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 1 << 2, + #else + EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 1 << 3, + EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 1 << 4, + #endif + + } ExternalSemaphoreHandleTypeBit; + typedef uint32_t ExternalSemaphoreHandleTypeBits; /** Describes component layout of a format */ typedef enum @@ -205,6 +255,14 @@ namespace Anvil SWAPCHAIN_WRAPPER } ImageType; + typedef enum class MemoryBlockType + { + DERIVED, + DERIVED_WITH_CUSTOM_DELETE_PROC, + REGULAR + + } MemoryBlockType; + enum MemoryFeatureFlagBits { /* NOTE: If more memory feature flags are added here, make sure to also update Anvil::Utils::get_vk_property_flags_from_memory_feature_flags() @@ -322,6 +380,30 @@ namespace Anvil UNDEFINED = COUNT }; + typedef enum + { + /* Implementation should wait for each query's status to become available before retrieving its results + * + * Core VK 1.0 functionality + */ + QUERY_RESULT_WAIT_BIT = 1 << 0, + + /* Each query result value is going to be followed by a status value. Non-zero values indicate result is + * available. + * + * Core VK 1.0 functionality + */ + QUERY_RESULT_WITH_AVAILABILITY_BIT = 1 << 1, + + /* Indicates it is OK for the function to return result values for a sub-range of the requested query range. + * + * Core VK 1.0 frunctionality + */ + QUERY_RESULT_PARTIAL_BIT = 1 << 2, + + } QueryResultBit; + typedef uint32_t QueryResultBits; + /* Specifies one of the compute / rendering pipeline stages. */ typedef enum { diff --git a/include/misc/types_struct.h b/include/misc/types_struct.h index e7bf2c1d..cd4ccc19 100644 --- a/include/misc/types_struct.h +++ b/include/misc/types_struct.h @@ -24,6 +24,48 @@ namespace Anvil { + typedef struct ExternalFenceProperties + { + Anvil::ExternalFenceHandleTypeBits compatible_external_handle_types; + Anvil::ExternalFenceHandleTypeBits export_from_imported_external_handle_types; + + bool is_exportable; + bool is_importable; + + /* Dummy constructor */ + ExternalFenceProperties(); + + ExternalFenceProperties(const VkExternalFencePropertiesKHR& in_external_memory_props); + } ExternalFenceProperties; + + typedef struct ExternalMemoryProperties + { + Anvil::ExternalMemoryHandleTypeBits compatible_external_handle_types; + Anvil::ExternalMemoryHandleTypeBits export_from_imported_external_handle_types; + + bool is_exportable; + bool is_importable; + + /* Dummy constructor */ + ExternalMemoryProperties(); + + ExternalMemoryProperties(const VkExternalMemoryPropertiesKHR& in_external_memory_props); + } ExternalMemoryProperties; + + typedef struct ExternalSemaphoreProperties + { + Anvil::ExternalSemaphoreHandleTypeBits compatible_external_handle_types; + Anvil::ExternalSemaphoreHandleTypeBits export_from_imported_external_handle_types; + + bool is_exportable; + bool is_importable; + + /* Dummy constructor */ + ExternalSemaphoreProperties(); + + ExternalSemaphoreProperties(const VkExternalSemaphorePropertiesKHR& in_external_memory_props); + } ExternalSemaphoreProperties; + /* Holds shader core properties pertaining to a physical device */ typedef struct AMDShaderCoreProperties { @@ -124,17 +166,54 @@ namespace Anvil BufferBarrier& operator=(const BufferBarrier&); } BufferBarrier; - typedef struct BufferMemoryBindingUpdate + typedef struct BufferFormatProperties { - Anvil::Buffer* buffer_ptr; - bool memory_block_owned_by_buffer; - Anvil::MemoryBlock* memory_block_ptr; + ExternalMemoryProperties external_handle_properties; - /* May either be empty or hold the physical device, from which the logical device has been created */ - std::vector physical_devices; + BufferFormatProperties(); + BufferFormatProperties(const ExternalMemoryProperties& in_external_handle_properties); - BufferMemoryBindingUpdate(); - } BufferMemoryBindingUpdate; + BufferFormatProperties (const BufferFormatProperties&) = default; + BufferFormatProperties& operator=(const BufferFormatProperties&) = default; + } BufferFormatProperties; + + typedef struct BufferFormatPropertiesQuery + { + const Anvil::BufferCreateFlags create_flags; + const Anvil::ExternalMemoryHandleTypeBit external_memory_handle_type; + const VkFormat format; + const VkBufferUsageFlags usage_flags; + + explicit BufferFormatPropertiesQuery(const Anvil::BufferCreateFlags in_create_flags, + const Anvil::ExternalMemoryHandleTypeBit& in_external_memory_handle_type, + const VkFormat& in_format, + const VkBufferUsageFlags& in_usage_flags) + :create_flags (in_create_flags), + external_memory_handle_type(in_external_memory_handle_type), + format (in_format), + usage_flags (in_usage_flags) + { + /* Stub */ + } + + BufferFormatPropertiesQuery (const BufferFormatPropertiesQuery& in_query) = default; + BufferFormatPropertiesQuery& operator=(const BufferFormatPropertiesQuery& in_query) = delete; + } BufferFormatPropertiesQuery; + + #if defined(_WIN32) + typedef struct ExternalNTHandleInfo + { + DWORD access; + const SECURITY_ATTRIBUTES* attributes_ptr; + std::wstring name; + + ExternalNTHandleInfo() + { + access = 0; + attributes_ptr = nullptr; + } + } ExternalNTHandleInfo; + #endif typedef struct EXTDescriptorIndexingFeatures { @@ -307,6 +386,77 @@ namespace Anvil ExtensionKHRDescriptorUpdateTemplateEntrypoints(); } ExtensionKHRDescriptorUpdateTemplateEntrypoints; + typedef struct ExtensionKHRExternalFenceCapabilitiesEntrypoints + { + PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR; + + ExtensionKHRExternalFenceCapabilitiesEntrypoints(); + } ExtensionKHRExternalFenceCapabilitiesEntrypoints; + + typedef struct ExtensionKHRExternalMemoryCapabilitiesEntrypoints + { + PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; + + ExtensionKHRExternalMemoryCapabilitiesEntrypoints(); + } ExtensionKHRExternalMemoryCapabilitiesEntrypoints; + + typedef struct ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints + { + PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR vkGetPhysicalDeviceExternalSemaphorePropertiesKHR; + + ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints(); + } ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints; + + #if defined(_WIN32) + typedef struct ExtensionKHRExternalFenceWin32Entrypoints + { + PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR; + PFN_vkImportFenceWin32HandleKHR vkImportFenceWin32HandleKHR; + + ExtensionKHRExternalFenceWin32Entrypoints(); + } ExtensionKHRExternalFenceWin32Entrypoints; + + typedef struct ExtensionKHRExternalMemoryWin32Entrypoints + { + PFN_vkGetMemoryWin32HandleKHR vkGetMemoryWin32HandleKHR; + PFN_vkGetMemoryWin32HandlePropertiesKHR vkGetMemoryWin32HandlePropertiesKHR; + + ExtensionKHRExternalMemoryWin32Entrypoints(); + } ExtensionKHRExternalMemoryWin32Entrypoints; + + typedef struct ExtensionKHRExternalSemaphoreWin32Entrypoints + { + PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR; + PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR; + + ExtensionKHRExternalSemaphoreWin32Entrypoints(); + } ExtensionKHRExternalSemaphoreWin32Entrypoints; +#else + typedef struct ExtensionKHRExternalFenceFdEntrypoints + { + PFN_vkGetFenceFdKHR vkGetFenceFdKHR; + PFN_vkImportFenceFdKHR vkImportFenceFdKHR; + + ExtensionKHRExternalFenceFdEntrypoints(); + } ExtensionKHRExternalFenceFdEntrypoints; + + typedef struct ExtensionKHRExternalMemoryFdEntrypoints + { + PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; + PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHR; + + ExtensionKHRExternalMemoryFdEntrypoints(); + } ExtensionKHRExternalMemoryFdEntrypoints; + + typedef struct ExtensionKHRExternalSemaphoreFdEntrypoints + { + PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; + PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; + + ExtensionKHRExternalSemaphoreFdEntrypoints(); + } ExtensionKHRExternalSemaphoreFdEntrypoints; +#endif + typedef struct ExtensionKHRGetPhysicalDeviceProperties2 { PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; @@ -384,28 +534,104 @@ namespace Anvil ExtensionKHRDeviceGroupCreationEntrypoints(); } ExtensionKHRDeviceGroupCreationEntrypoints; - /** Holds driver-specific format capabilities */ + typedef struct FenceProperties + { + ExternalFenceProperties external_fence_properties; + + /* Dummy constructor */ + FenceProperties(); + + FenceProperties(const ExternalFenceProperties& in_external_fence_properties); + } FenceProperties; + + typedef struct FencePropertiesQuery + { + const Anvil::ExternalFenceHandleTypeBit external_fence_handle_type; + + explicit FencePropertiesQuery(const Anvil::ExternalFenceHandleTypeBit& in_external_fence_handle_type) + :external_fence_handle_type(in_external_fence_handle_type) + { + /* Stub */ + } + + FencePropertiesQuery (const FencePropertiesQuery&) = default; + FencePropertiesQuery& operator=(const FencePropertiesQuery&) = delete; + } FencePropertiesQuery; + typedef struct FormatProperties { VkFormatFeatureFlagsVariable(buffer_capabilities); VkFormatFeatureFlagsVariable(linear_tiling_capabilities); VkFormatFeatureFlagsVariable(optimal_tiling_capabilities); + FormatProperties(); + FormatProperties(const VkFormatProperties& in_format_props); + } FormatProperties; + + typedef struct ImageFormatProperties + { + ExternalMemoryProperties external_handle_properties; + + VkExtent3D max_extent; + VkDeviceSize max_resource_size; + uint32_t n_max_array_layers; + uint32_t n_max_mip_levels; + VkSampleCountFlags sample_counts; + /* Tells whether the format can be used with functions introduced in VK_AMD_texture_gather_bias_lod */ bool supports_amd_texture_gather_bias_lod; + /** Dummy constructor */ - FormatProperties(); + ImageFormatProperties(); /** Constructor. Initializes the instance using data provided by the driver. * * @param in_format_props Vulkan structure to use for initialization. **/ - FormatProperties(const VkFormatProperties& in_format_props); - } FormatProperties; + ImageFormatProperties(const VkImageFormatProperties& in_image_format_props, + const bool& in_supports_amd_texture_gather_bias_lod, + const ExternalMemoryProperties& in_external_handle_properties); + } ImageFormatProperties; + + typedef struct ImageFormatPropertiesQuery + { + /* TODO + * + * NOTE: In order to retrieve information regarding device's external handle support for a particular image + * configuration, make sure to call ImageFormatPropertiesQuery::set_external_memory_handle_type(), prior + * to passing the struct instance as an arg to get_image_format_properties(). + */ + explicit ImageFormatPropertiesQuery(const VkFormat& in_format, + const VkImageType& in_image_type, + const VkImageTiling& in_tiling, + const VkImageUsageFlags& in_usage_flags, + const VkImageCreateFlags& in_create_flags) + :create_flags (in_create_flags), + external_memory_handle_type(EXTERNAL_MEMORY_HANDLE_TYPE_NONE), + format (in_format), + image_type (in_image_type), + tiling (in_tiling), + usage_flags (in_usage_flags) + { + /* Stub */ + } + + void set_external_memory_handle_type(const Anvil::ExternalMemoryHandleTypeBit& in_external_memory_handle_type) + { + external_memory_handle_type = in_external_memory_handle_type; + } + + const VkImageCreateFlags create_flags; + Anvil::ExternalMemoryHandleTypeBit external_memory_handle_type; + const VkFormat format; + const VkImageType image_type; + const VkImageTiling tiling; + const VkImageUsageFlags usage_flags; - extern bool operator==(const FormatProperties& in1, - const FormatProperties& in2); + ImageFormatPropertiesQuery (const ImageFormatPropertiesQuery& in_query) = default; + ImageFormatPropertiesQuery& operator=(const ImageFormatPropertiesQuery& in_query) = delete; + } ImageFormatPropertiesQuery; /** Describes an image memory barrier. */ typedef struct ImageBarrier @@ -487,6 +713,24 @@ namespace Anvil ImageBarrier& operator=(const ImageBarrier&); } ImageBarrier; + typedef struct ExternalMemoryHandleImportInfo + { + ExternalHandleType handle; + + #if defined(_WIN32) + std::wstring name; + #endif + + ExternalMemoryHandleImportInfo() + { + #if defined(_WIN32) + handle = nullptr; + #else + handle = -1; + #endif + } + } ExternalMemoryHandleImportInfo; + /* Holds 16-bit storage features */ typedef struct KHR16BitStorageFeatures { @@ -503,6 +747,20 @@ namespace Anvil bool operator==(const KHR16BitStorageFeatures& in_features) const; } KHR16BitStorageFeatures; + typedef struct KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties + { + uint8_t device_luid[VK_LUID_SIZE]; + bool device_luid_valid; + + uint8_t device_uuid[VK_UUID_SIZE]; + uint8_t driver_uuid[VK_UUID_SIZE]; + + uint32_t device_node_mask; + + KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties(); + KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties(const VkPhysicalDeviceIDPropertiesKHR& in_properties); + } KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties; + typedef struct KHRMaintenance3Properties { VkDeviceSize max_memory_allocation_size; @@ -1015,7 +1273,7 @@ namespace Anvil bool independent_blend; bool inherited_queries; bool large_points; - bool logic_ip; + bool logic_op; bool multi_draw_indirect; bool multi_viewport; bool occlusion_query_precise; @@ -1229,16 +1487,18 @@ namespace Anvil typedef struct PhysicalDeviceProperties { - const AMDShaderCoreProperties* amd_shader_core_properties_ptr; - const PhysicalDevicePropertiesCoreVK10* core_vk1_0_properties_ptr; - const EXTDescriptorIndexingProperties* ext_descriptor_indexing_properties_ptr; - const KHRMaintenance3Properties* khr_maintenance3_properties_ptr; + const AMDShaderCoreProperties* amd_shader_core_properties_ptr; + const PhysicalDevicePropertiesCoreVK10* core_vk1_0_properties_ptr; + const EXTDescriptorIndexingProperties* ext_descriptor_indexing_properties_ptr; + const KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties* khr_external_memory_capabilities_physical_device_id_properties_ptr; + const KHRMaintenance3Properties* khr_maintenance3_properties_ptr; PhysicalDeviceProperties(); - PhysicalDeviceProperties(const AMDShaderCoreProperties* in_amd_shader_core_properties_ptr, - const PhysicalDevicePropertiesCoreVK10* in_core_vk1_0_properties_ptr, - const EXTDescriptorIndexingProperties* in_ext_descriptor_indexing_properties_ptr, - const KHRMaintenance3Properties* in_khr_maintenance3_properties_ptr); + PhysicalDeviceProperties(const AMDShaderCoreProperties* in_amd_shader_core_properties_ptr, + const PhysicalDevicePropertiesCoreVK10* in_core_vk1_0_properties_ptr, + const EXTDescriptorIndexingProperties* in_ext_descriptor_indexing_properties_ptr, + const KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties* in_khr_external_memory_caps_physical_device_id_props_ptr, + const KHRMaintenance3Properties* in_khr_maintenance3_properties_ptr); bool operator==(const PhysicalDeviceProperties& in_props) const; } PhysicalDeviceProperties; @@ -1296,6 +1556,30 @@ namespace Anvil explicit PhysicalDeviceGroup(); } PhysicalDeviceGroup; + typedef struct SemaphoreProperties + { + ExternalSemaphoreProperties external_semaphore_properties; + + /* Dummy constructor */ + SemaphoreProperties(); + + SemaphoreProperties(const ExternalSemaphoreProperties& in_external_semaphore_properties); + } SemaphoreProperties; + + typedef struct SemaphorePropertiesQuery + { + const Anvil::ExternalSemaphoreHandleTypeBit external_semaphore_handle_type; + + explicit SemaphorePropertiesQuery(const Anvil::ExternalSemaphoreHandleTypeBit& in_external_semaphore_handle_type) + :external_semaphore_handle_type(in_external_semaphore_handle_type) + { + /* Stub */ + } + + SemaphorePropertiesQuery (const SemaphorePropertiesQuery&) = default; + SemaphorePropertiesQuery& operator=(const SemaphorePropertiesQuery&) = delete; + } SemaphorePropertiesQuery; + /** Holds all information related to a specific shader module stage entry-point. */ typedef struct ShaderModuleStageEntryPoint { @@ -1367,6 +1651,296 @@ namespace Anvil typedef std::vector SpecializationConstants; + typedef enum class SubmissionType + { + SGPU + } SubmissionType; + + typedef struct SubmitInfo + { + /** Creates a submission info which, when submitted, waits on the semaphores specified by the user, + * executes user-defined command buffers, and then signals the semaphores passed by arguments. + * If a non-nullptr fence is specified, the function will also wait on the call to finish GPU-side + * before returning. + * + * It is valid to specify 0 command buffers or signal/wait semaphores, in which case + * these steps will be skipped. + * + * If @param in_should_block is true and @param in_opt_fence_ptr is nullptr, the function will create + * a new fence, wait on it, and then release it prior to leaving. This may come at a performance cost. + * + * NOTE: By default, the following values are associated with a new SubmitInfo instance: + * + * - D3D12 fence submit info: none + * + * To adjust these settings, please use corresponding set_..() functions, prior to passing the structure over to Queue::submit(). + * + * + * @param in_n_command_buffers Number of command buffers under @param in_opt_cmd_buffer_ptrs + * which should be executed. May be 0. + * @param in_opt_cmd_buffer_ptrs_ptr Ptr to an array of command buffers to execute. Can be nullptr if + * @param n_command_buffers is 0. + * @param in_n_semaphores_to_signal Number of semaphores to signal after command buffers finish + * executing. May be 0. + * @param in_opt_semaphore_to_signal_ptrs_ptr Ptr to an array of semaphores to signal after execution. May be nullptr if + * @param n_semaphores_to_signal is 0. + * @param in_n_semaphores_to_wait_on Number of semaphores to wait on before executing command buffers. + * May be 0. + * @param in_opt_semaphore_to_wait_on_ptrs_ptr Ptr to an array of semaphores to wait on prior to execution. May be nullptr + * if @param in_n_semaphores_to_wait_on is 0. + * @param in_opt_dst_stage_masks_to_wait_on_ptrs Array of size @param in_n_semaphores_to_wait_on, specifying stages + * at which the wait ops should be performed. May be nullptr if + * @param n_semaphores_to_wait_on is 0. + * @param in_should_block true if the function should wait for the scheduled commands to + * finish executing, false otherwise. + * @param in_opt_fence_ptr Fence to use when submitting the comamnd buffers to the queue. + * The fence will be waited on if @param in_should_block is true. + * If @param in_should_block is false, the fence will be passed at + * submit call time, but will not be waited on. + * + * @param in_command_buffer_submissions TODO + * @param in_semaphores_to_signal_ptr TODO + * @param in_semaphores_to_wait_on_ptr TODO + **/ + + static SubmitInfo create(Anvil::CommandBufferBase* in_opt_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + static SubmitInfo create(uint32_t in_n_cmd_buffers, + Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + static SubmitInfo create_execute(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + static SubmitInfo create_execute(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + static SubmitInfo create_execute_signal(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + static SubmitInfo create_execute_signal(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + /** TODO + * + * NOTE: This function always blocks. + */ + static SubmitInfo create_signal(uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + static SubmitInfo create_signal_wait(uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + /** TODO + * + * NOTE: This function always blocks. + */ + static SubmitInfo create_wait(uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + static SubmitInfo create_wait_execute(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + static SubmitInfo create_wait_execute(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + static SubmitInfo create_wait_execute_signal(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + static SubmitInfo create_wait_execute_signal(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr = nullptr); + + Anvil::CommandBufferBase* const* get_command_buffers_sgpu() const + { + return command_buffers_sgpu_ptr; + } + + #if defined(_WIN32) + bool get_d3d12_fence_semaphore_values(const uint64_t** out_d3d12_fence_signal_semaphore_values_ptr_ptr, + const uint64_t** out_d3d12_fence_wait_semaphore_values_ptr_ptr) const + { + bool result = (d3d12_fence_signal_semaphore_values_ptr != nullptr && n_signal_semaphores != 0) || + (d3d12_fence_wait_semaphore_values_ptr != nullptr && n_wait_semaphores != 0); + + *out_d3d12_fence_signal_semaphore_values_ptr_ptr = d3d12_fence_signal_semaphore_values_ptr; + *out_d3d12_fence_wait_semaphore_values_ptr_ptr = d3d12_fence_wait_semaphore_values_ptr; + + return result; + } + #endif + + const VkPipelineStageFlags* get_destination_stage_wait_masks() const + { + return dst_stage_wait_masks_ptr; + } + + Anvil::Fence* get_fence() const + { + return fence_ptr; + } + + const uint32_t& get_n_command_buffers() const + { + return n_command_buffers; + } + + const uint32_t& get_n_signal_semaphores() const + { + return n_signal_semaphores; + } + + const uint32_t& get_n_wait_semaphores() const + { + return n_wait_semaphores; + } + + Anvil::Semaphore* const* get_signal_semaphores_sgpu() const + { + return signal_semaphores_sgpu_ptr; + } + + const bool& get_should_block() const + { + return should_block; + } + + const SubmissionType& get_type() const + { + return type; + } + + Anvil::Semaphore* const* get_wait_semaphores_sgpu() const + { + return wait_semaphores_sgpu_ptr; + } + + #if defined(_WIN32) + /* Calling this function will make Anvil fill & chain a VkD3D12FenceSubmitInfoKHR struct at queue submission time. + * + * Requires VK_KHR_external_semaphore_win32 support. + * + * NOTE: The structure caches the provided pointers, not the contents available under derefs! Make sure the pointers remain valid + * for the time of the Queue::submit() call. + * + * @param in_signal_semaphore_values_ptr An array of exactly n_signal_semaphores values. Usage as per VkD3D12FenceSubmitInfoKHR::pSignalSemaphoreValues. + * Must not be nullptr unless n_signal_semaphores is 0. + * @param in_wait_semaphore_values_ptr An array of exactly n_wait_semaphores values. Usage as per VkD3D12FenceSubmitInfoKHR::pWaitSemaphoreValues. + * Must not be nullptr unless n_wait_semaphores is 0. + **/ + void set_d3d12_fence_semaphore_values(const uint64_t* in_signal_semaphore_values_ptr, + const uint32_t& in_n_signal_semaphore_values, + const uint64_t* in_wait_semaphore_values_ptr, + const uint32_t& in_n_wait_semaphore_values) + { + ANVIL_REDUNDANT_ARGUMENT_CONST(in_n_signal_semaphore_values); + ANVIL_REDUNDANT_ARGUMENT_CONST(in_n_wait_semaphore_values); + + anvil_assert((n_signal_semaphores != 0 && in_signal_semaphore_values_ptr != nullptr) || + (n_signal_semaphores == 0) ); + anvil_assert((n_wait_semaphores != 0 && in_wait_semaphore_values_ptr != nullptr) || + (n_wait_semaphores == 0) ); + + anvil_assert(in_n_signal_semaphore_values == n_signal_semaphores); + anvil_assert(in_n_wait_semaphore_values == n_wait_semaphores); + + d3d12_fence_signal_semaphore_values_ptr = in_signal_semaphore_values_ptr; + d3d12_fence_wait_semaphore_values_ptr = in_wait_semaphore_values_ptr; + } + #endif + + private: + SubmitInfo(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr); + + SubmitInfo(uint32_t in_n_command_buffers, + Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr); + + Anvil::CommandBufferBase* helper_cmd_buffer_raw_ptr; + + Anvil::CommandBufferBase* const* command_buffers_sgpu_ptr; + uint32_t n_command_buffers; + + Anvil::Semaphore* const* signal_semaphores_sgpu_ptr; + uint32_t n_signal_semaphores; + + const VkPipelineStageFlags* dst_stage_wait_masks_ptr; + Anvil::Semaphore* const* wait_semaphores_sgpu_ptr; + uint32_t n_wait_semaphores; + + Anvil::Fence* fence_ptr; + + #if defined(_WIN32) + const uint64_t* d3d12_fence_signal_semaphore_values_ptr; + const uint64_t* d3d12_fence_wait_semaphore_values_ptr; + #endif + + bool should_block; + const SubmissionType type; + + ANVIL_DISABLE_ASSIGNMENT_OPERATOR(SubmitInfo); + } SubmitInfo; + /* Represents a Vulkan structure header */ typedef struct { diff --git a/include/misc/types_utils.h b/include/misc/types_utils.h index d8261d47..5ca7f32e 100644 --- a/include/misc/types_utils.h +++ b/include/misc/types_utils.h @@ -28,7 +28,17 @@ namespace Anvil { MTSafety convert_boolean_to_mt_safety_enum(bool in_mt_safe); - VkExternalMemoryHandleTypeFlagsKHR convert_external_memory_handle_types_to_vk_external_memory_handle_type_flags(const Anvil::ExternalMemoryHandleTypeFlags& in_flags); + VkBufferCreateFlags convert_buffer_create_flags_to_vk_buffer_create_flags(const Anvil::BufferCreateFlags& in_create_flags); + Anvil::BufferCreateFlags convert_vk_buffer_create_flags_to_buffer_create_flags(const VkBufferCreateFlags& in_create_flags); + + VkExternalFenceHandleTypeFlagsKHR convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(const Anvil::ExternalFenceHandleTypeBits& in_types); + Anvil::ExternalFenceHandleTypeBits convert_vk_external_fence_handle_type_flags_to_external_fence_handle_type_bits(const VkExternalFenceHandleTypeFlagsKHR& in_types); + + VkExternalMemoryHandleTypeFlagsKHR convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(const Anvil::ExternalMemoryHandleTypeBits& in_types); + Anvil::ExternalMemoryHandleTypeBits convert_vk_external_memory_handle_type_flags_to_external_memory_handle_type_bits(const VkExternalMemoryHandleTypeFlagsKHR& in_types); + + VkExternalSemaphoreHandleTypeFlagsKHR convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(const Anvil::ExternalSemaphoreHandleTypeBits& in_types); + Anvil::ExternalSemaphoreHandleTypeBits convert_vk_external_semaphore_handle_type_flags_to_external_semaphore_handle_type_bits(const VkExternalSemaphoreHandleTypeFlagsKHR& in_types); bool convert_mt_safety_enum_to_boolean(MTSafety in_mt_safety, const Anvil::BaseDevice* in_device_ptr); @@ -259,6 +269,12 @@ namespace Anvil VkMemoryPropertyFlags* out_mem_type_flags_ptr, VkMemoryHeapFlags* out_mem_heap_flags_ptr); + #ifdef _WIN32 + bool is_nt_handle(const Anvil::ExternalFenceHandleTypeBit& in_type); + bool is_nt_handle(const Anvil::ExternalMemoryHandleTypeBit& in_type); + bool is_nt_handle(const Anvil::ExternalSemaphoreHandleTypeBit& in_type); + #endif + /** Tells whether @param in_value is a power-of-two. */ template type is_pow2(const type in_value) diff --git a/include/wrappers/buffer.h b/include/wrappers/buffer.h index 568d2ac3..f8a01329 100644 --- a/include/wrappers/buffer.h +++ b/include/wrappers/buffer.h @@ -235,8 +235,6 @@ namespace Anvil uint32_t in_n_physical_devices, const Anvil::PhysicalDevice* in_physical_devices_ptr); - bool do_external_memory_handle_type_sanity_checks() const; - /* Private members */ VkBuffer m_buffer; VkMemoryRequirements m_buffer_memory_reqs; diff --git a/include/wrappers/descriptor_pool.h b/include/wrappers/descriptor_pool.h index 12631e11..0c169e75 100644 --- a/include/wrappers/descriptor_pool.h +++ b/include/wrappers/descriptor_pool.h @@ -153,7 +153,7 @@ namespace Anvil std::vector m_ds_cache; std::vector m_ds_layout_cache; - const DescriptorPoolFlags& m_flags; + const DescriptorPoolFlags m_flags; }; }; /* namespace Anvil */ diff --git a/include/wrappers/device.h b/include/wrappers/device.h index dc497b19..dac3f5ce 100644 --- a/include/wrappers/device.h +++ b/include/wrappers/device.h @@ -165,6 +165,50 @@ namespace Anvil return m_khr_descriptor_update_template_extension_entrypoints; } + #if defined(_WIN32) + const ExtensionKHRExternalFenceWin32Entrypoints& get_extension_khr_external_fence_win32_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_fence_win32() ); + + return m_khr_external_fence_win32_extension_entrypoints; + } + + const ExtensionKHRExternalMemoryWin32Entrypoints& get_extension_khr_external_memory_win32_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_win32() ); + + return m_khr_external_memory_win32_extension_entrypoints; + } + + const ExtensionKHRExternalSemaphoreWin32Entrypoints& get_extension_khr_external_semaphore_win32_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_semaphore_win32() ); + + return m_khr_external_semaphore_win32_extension_entrypoints; + } + #else + const ExtensionKHRExternalFenceFdEntrypoints& get_extension_khr_external_fence_fd_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_fence_fd() ); + + return m_khr_external_fence_fd_extension_entrypoints; + } + + const ExtensionKHRExternalMemoryFdEntrypoints& get_extension_khr_external_memory_fd_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_fd() ); + + return m_khr_external_memory_fd_extension_entrypoints; + } + + const ExtensionKHRExternalSemaphoreFdEntrypoints& get_extension_khr_external_semaphore_fd_entrypoints() const + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_semaphore_fd() ); + + return m_khr_external_semaphore_fd_extension_entrypoints; + } + #endif + /** Returns a container with entry-points to functions introduced by VK_KHR_maintenance1 extension. **/ const ExtensionKHRMaintenance1Entrypoints& get_extension_khr_maintenance1_entrypoints() const { @@ -272,37 +316,21 @@ namespace Anvil return m_parent_instance_ptr; } + virtual bool get_physical_device_buffer_format_properties(const BufferFormatPropertiesQuery& in_query, + Anvil::BufferFormatProperties* out_opt_result_ptr = nullptr) const = 0; + /** Returns features supported by physical device(s) which have been used to instantiate * this logical device instance. **/ virtual const Anvil::PhysicalDeviceFeatures& get_physical_device_features() const = 0; - /** Returns format properties, as reported by physical device(s) which have been used to - * instantiate this logical device instance. - * - * @param in_format Format to use for the query. - */ - virtual const Anvil::FormatProperties& get_physical_device_format_properties(VkFormat in_format) const = 0; + virtual bool get_physical_device_fence_properties(const FencePropertiesQuery& in_query, + Anvil::FenceProperties* out_opt_result_ptr = nullptr) const = 0; - /** Returns image format properties, as reported by physical device(s) which have been used - * to instantiate this logical device instance. - * - * @param in_format Meaning as per Vulkan spec. - * @param in_type Meaning as per Vulkan spec. - * @param in_tiling Meaning as per Vulkan spec. - * @param in_usage Meaning as per Vulkan spec. - * @param in_flags Meaning as per Vulkan spec. - * @param out_result If the function returns true, the requested information will be stored - * at this location. - * - * @return true if successful, false otherwise. - **/ - virtual bool get_physical_device_image_format_properties(VkFormat in_format, - VkImageType in_type, - VkImageTiling in_tiling, - VkImageUsageFlags in_usage, - VkImageCreateFlags in_flags, - VkImageFormatProperties& out_result) const = 0; + virtual Anvil::FormatProperties get_physical_device_format_properties(VkFormat in_format) const = 0; + + virtual bool get_physical_device_image_format_properties(const ImageFormatPropertiesQuery& in_query, + Anvil::ImageFormatProperties* out_opt_result_ptr = nullptr) const = 0; /** Returns memory properties, as reported by physical device(s) which have been used * to instantiate this logical device instance. @@ -445,6 +473,24 @@ namespace Anvil Anvil::Queue* get_sparse_binding_queue(uint32_t in_n_queue, VkQueueFlags in_opt_required_queue_flags = 0) const; + /* Tells which memory types can be specified when creating an external memory handle for a Win32 handle @param in_handle + * + * Requires VK_KHR_external_memory_Fd under Windows. + * Requires VK_KHR_external_memory_win32 under Windows. + * + * @return true if successful, false otherwise. + * + * + * @param in_external_handle_type (Windows) must be either EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT or + * EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT. + * (Linux) must be EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT. + * @param out_supported_memory_type_bits_ptr Deref will be set to a set of bits where each index corresponds to support status + * of a memory type with corresponding index. Must not be null. + */ + bool get_memory_types_supported_for_external_handle(const Anvil::ExternalMemoryHandleTypeBit& in_external_handle_type, + ExternalHandleType in_handle, + uint32_t* out_supported_memory_type_bits) const; + /** Returns a Queue instance, corresponding to a transfer queue at index @param in_n_queue * * @param in_n_queue Index of the transfer queue to retrieve the wrapper instance for. @@ -508,8 +554,6 @@ namespace Anvil bool is_universal_queue_family_index(const uint32_t& in_queue_family_index) const; - bool supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_types) const; - bool wait_idle() const; protected: @@ -604,6 +648,15 @@ namespace Anvil ExtensionKHRSurfaceEntrypoints m_khr_surface_extension_entrypoints; ExtensionKHRSwapchainEntrypoints m_khr_swapchain_extension_entrypoints; + #if defined(_WIN32) + ExtensionKHRExternalFenceWin32Entrypoints m_khr_external_fence_win32_extension_entrypoints; + ExtensionKHRExternalMemoryWin32Entrypoints m_khr_external_memory_win32_extension_entrypoints; + ExtensionKHRExternalSemaphoreWin32Entrypoints m_khr_external_semaphore_win32_extension_entrypoints; + #else + ExtensionKHRExternalFenceFdEntrypoints m_khr_external_fence_fd_extension_entrypoints; + ExtensionKHRExternalMemoryFdEntrypoints m_khr_external_memory_fd_extension_entrypoints; + ExtensionKHRExternalSemaphoreFdEntrypoints m_khr_external_semaphore_fd_extension_entrypoints; + #endif private: /* Private variables */ @@ -685,19 +738,19 @@ namespace Anvil return m_parent_physical_device_ptr; } + bool get_physical_device_buffer_format_properties(const BufferFormatPropertiesQuery& in_query, + Anvil::BufferFormatProperties* out_opt_result_ptr = nullptr) const override; + /** See documentation in BaseDevice for more details */ const Anvil::PhysicalDeviceFeatures& get_physical_device_features() const override; - /** See documentation in BaseDevice for more details */ - const Anvil::FormatProperties& get_physical_device_format_properties(VkFormat in_format) const override; + bool get_physical_device_fence_properties(const FencePropertiesQuery& in_query, + Anvil::FenceProperties* out_opt_result_ptr = nullptr) const override; - /** See documentation in BaseDevice for more details */ - bool get_physical_device_image_format_properties(VkFormat in_format, - VkImageType in_type, - VkImageTiling in_tiling, - VkImageUsageFlags in_usage, - VkImageCreateFlags in_flags, - VkImageFormatProperties& out_result) const override; + Anvil::FormatProperties get_physical_device_format_properties(VkFormat in_format) const override; + + bool get_physical_device_image_format_properties(const ImageFormatPropertiesQuery& in_query, + Anvil::ImageFormatProperties* out_opt_result_ptr = nullptr) const override; /** See documentation in BaseDevice for more details */ const Anvil::MemoryProperties& get_physical_device_memory_properties() const override; diff --git a/include/wrappers/fence.h b/include/wrappers/fence.h index e95024fe..cb5845be 100644 --- a/include/wrappers/fence.h +++ b/include/wrappers/fence.h @@ -56,6 +56,18 @@ namespace Anvil */ static Anvil::FenceUniquePtr create(Anvil::FenceCreateInfoUniquePtr in_create_info_ptr); + /* Creates a new external fence handle of the user-specified type. + * + * For NT handle types, the function can only be called once per each NT handle type. Subsequent + * calls will result in the function triggering an assertion failure and returning null. + * + * Returns nullptr if unsuccessful. + * + * Requires VK_KHR_external_fence_fd under Linux. + * Requires VK_KHR_external_fence_win32 under Windows. + */ + ExternalHandleUniquePtr export_to_external_handle(const Anvil::ExternalFenceHandleTypeBit& in_fence_handle_type); + const Anvil::FenceCreateInfo* get_create_info_ptr() const { return m_create_info_ptr.get(); @@ -75,6 +87,32 @@ namespace Anvil return &m_fence; } + /* TODO + * + * Requires VK_KHR_external_fence_fd under Linux. + * Requires VK_KHR_external_fence_win32 under Windows. + * + * + * @return true if successful, false otherwise. + * + * @param in_temporary_import True if a temporary import operation should be performed. False if + * a permanent import is being requested. + * @param in_handle_type Type of the handle that is being imported. + * @param in_handle (Linux): Handle to use. + * @param in_opt_handle (Windows): Handle to use. Must not be null if @param in_opt_name is null and vice versa. + * @param in_opt_name (Windows): Name of the handle to use. Must not be null if @param in_opt_handle is null and vice versa. + */ + #if defined(_WIN32) + bool import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalFenceHandleTypeBit& in_handle_type, + const ExternalHandleType& in_opt_handle, + const std::wstring& in_opt_name); + #else + bool import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalFenceHandleTypeBit& in_handle_type, + const ExternalHandleType& in_handle); + #endif + /** Tells whether the fence is signalled at the time of the call. * * @return true if the fence is set, false otherwise. @@ -117,9 +155,10 @@ namespace Anvil void release_fence(); /* Private variables */ - Anvil::FenceCreateInfoUniquePtr m_create_info_ptr; - VkFence m_fence; - mutable bool m_possibly_set; + Anvil::FenceCreateInfoUniquePtr m_create_info_ptr; + std::map m_external_fence_created_for_handle_type; + VkFence m_fence; + mutable bool m_possibly_set; }; }; /* namespace Anvil */ diff --git a/include/wrappers/image.h b/include/wrappers/image.h index ca6419cd..2f04dcae 100644 --- a/include/wrappers/image.h +++ b/include/wrappers/image.h @@ -433,8 +433,6 @@ namespace Anvil Image(Anvil::ImageCreateInfoUniquePtr in_create_info_ptr); - bool do_sanity_checks_for_external_memory_handle_types(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const; - bool init (); void init_mipmap_props (); void init_page_occupancy(const std::vector& in_memory_reqs); diff --git a/include/wrappers/instance.h b/include/wrappers/instance.h index 376d8e34..fd990fc5 100644 --- a/include/wrappers/instance.h +++ b/include/wrappers/instance.h @@ -87,6 +87,12 @@ namespace Anvil return m_enabled_extensions_info_ptr->get_instance_extension_info(); } + const ExtensionKHRExternalFenceCapabilitiesEntrypoints& get_extension_khr_external_fence_capabilities_entrypoints() const; + + const ExtensionKHRExternalMemoryCapabilitiesEntrypoints& get_extension_khr_external_memory_capabilities_entrypoints() const; + + const ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints& get_extension_khr_external_semaphore_capabilities_entrypoints() const; + /** Returns a container with entry-points to functions introduced by VK_KHR_get_physical_device_properties2. * * Will fire an assertion failure if the extension is not supported. @@ -201,9 +207,12 @@ namespace Anvil /* DebugReport extension function pointers and data */ VkDebugReportCallbackEXT m_debug_callback_data; - ExtensionEXTDebugReportEntrypoints m_ext_debug_report_entrypoints; - ExtensionKHRGetPhysicalDeviceProperties2 m_khr_get_physical_device_properties2_entrypoints; - ExtensionKHRSurfaceEntrypoints m_khr_surface_entrypoints; + ExtensionEXTDebugReportEntrypoints m_ext_debug_report_entrypoints; + ExtensionKHRExternalFenceCapabilitiesEntrypoints m_khr_external_fence_capabilities_entrypoints; + ExtensionKHRExternalMemoryCapabilitiesEntrypoints m_khr_external_memory_capabilities_entrypoints; + ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints m_khr_external_semaphore_capabilities_entrypoints; + ExtensionKHRGetPhysicalDeviceProperties2 m_khr_get_physical_device_properties2_entrypoints; + ExtensionKHRSurfaceEntrypoints m_khr_surface_entrypoints; #ifdef _WIN32 #if defined(ANVIL_INCLUDE_WIN3264_WINDOW_SYSTEM_SUPPORT) diff --git a/include/wrappers/memory_block.h b/include/wrappers/memory_block.h index f6c3465b..ec9d928e 100644 --- a/include/wrappers/memory_block.h +++ b/include/wrappers/memory_block.h @@ -38,12 +38,10 @@ #include "misc/mt_safety.h" #include "misc/types.h" +#include "misc/memory_block_create_info.h" namespace Anvil { - /** "About to be deleted" call-back function prototype. */ - typedef std::function OnMemoryBlockReleaseCallbackFunction; - typedef class IMemoryBlockBackendSupport { public: @@ -63,7 +61,14 @@ namespace Anvil public: /* Public functions */ - /** Create and bind a new device memory object to the instantiated MemoryBlock object. + static MemoryBlockUniquePtr create(Anvil::MemoryBlockCreateInfoUniquePtr in_create_info_ptr); + + /* Creates a new external memory handle of the user-specified type. + * + * For NT handles, if one has been already created for this memory block instance & handle type, a cached instance + * of the handle will be returned instead. Otherwise, each create() call will return a new handle. + * + * Cached external memory handles will be destroyed & released at MemoryBlock's destruction time. * * @param in_device_ptr Device to use. * @param in_allowed_memory_bits Memory type bits which meet the allocation requirements. @@ -73,107 +78,53 @@ namespace Anvil * this field to specify which handle types the allocation needs to support. Please see * documentation of Anvil::ExternalMemoryHandleTypeFlags for more details. **/ - static MemoryBlockUniquePtr create(const Anvil::BaseDevice* in_device_ptr, - uint32_t in_allowed_memory_bits, - VkDeviceSize in_size, - Anvil::MemoryFeatureFlags in_memory_features, - MTSafety in_mt_safety = MT_SAFETY_INHERIT_FROM_PARENT_DEVICE, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types = 0); + static MemoryBlockUniquePtr create(const Anvil::BaseDevice* in_device_ptr, + uint32_t in_allowed_memory_bits, + VkDeviceSize in_size, + Anvil::MemoryFeatureFlags in_memory_features, + MTSafety in_mt_safety = MT_SAFETY_INHERIT_FROM_PARENT_DEVICE, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types = 0); /** Create a memory block whose storage space is maintained by another MemoryBlock instance. * - * @param in_parent_memory_block_ptr MemoryBlock instance to use as a parent. Must not be nullptr. - * Parent memory block must not be mapped. - * @param in_start_offset Start offset of the storage maintained by the specified parent memory block, - * from which the new MemoryBlock instance's storage should start. - * Must not be equal to or larger than parent object's storage size. - * When added to @param in_size, the result value must not be be larger than the remaining - * storage size. - * @param in_size Region size to use for the derived memory block. - **/ - static MemoryBlockUniquePtr create_derived(MemoryBlock* in_parent_memory_block_ptr, - VkDeviceSize in_start_offset, - VkDeviceSize in_size); - - /** Create a memory block whose lifetime is maintained by a separate entity. While the memory block remains reference-counted - * as usual, the destruction process is carried out by an external party via the specified call-back. + * Only supports REGULAR memory blocks. Derived memory blocks are NOT supported. * - * This implements a special case required for support of Vulkan Memory Allocator memory allocator backend. Applications - * are very unlikely to ever need to use this create() function. + * Returns nullptr if unsuccessful. * - * TODO + * Requires VK_KHR_external_memory_fd under Linux. + * Requires VK_KHR_external_memory_win32 under Windows. */ - static MemoryBlockUniquePtr create_derived_with_custom_delete_proc(const Anvil::BaseDevice* in_device_ptr, - VkDeviceMemory in_memory, - uint32_t in_allowed_memory_bits, - Anvil::MemoryFeatureFlags in_memory_features, - uint32_t in_memory_type_index, - VkDeviceSize in_size, - VkDeviceSize in_start_offset, - OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types); + ExternalHandleUniquePtr export_to_external_memory_handle(const Anvil::ExternalMemoryHandleTypeBit& in_memory_handle_type); /** Releases the Vulkan counterpart and unregisters the wrapper instance from the object tracker */ virtual ~MemoryBlock(); - /* Returns the underlying raw Vulkan VkDeviceMemory handle. */ - const VkDeviceMemory& get_memory() const + const Anvil::MemoryBlockCreateInfo* get_create_info_ptr() const { - if (m_parent_memory_block_ptr != nullptr) - { - return m_parent_memory_block_ptr->m_memory; - } - else - { - return m_memory; - } + return m_create_info_ptr.get(); } - /** Returns memory features of the underlying memory region */ - Anvil::MemoryFeatureFlags get_memory_features() const + /* Returns the underlying raw Vulkan VkDeviceMemory handle. */ + const VkDeviceMemory& get_memory() const { - if (m_parent_memory_block_ptr != nullptr) - { - return m_parent_memory_block_ptr->get_memory_features(); - } - else - { - return m_memory_features; - } - } + auto parent_mem_block_ptr = m_create_info_ptr->get_parent_memory_block(); - /** Returns the memory type index the memory block was allocated from */ - uint32_t get_memory_type_index() const - { - if (m_parent_memory_block_ptr != nullptr) + if (parent_mem_block_ptr != nullptr) { - return m_parent_memory_block_ptr->get_memory_type_index(); + return parent_mem_block_ptr->m_memory; } else { - return m_memory_type_index; + return m_memory; } } - /* Returns parent memory block, if one has been defined for this instance */ - const Anvil::MemoryBlock* get_parent_memory_block() const + const uint32_t& get_memory_type_index() const { - return m_parent_memory_block_ptr; + return m_memory_type_index; } - /* Returns the size of the memory block. */ - VkDeviceSize get_size() const - { - return m_size; - } - - /* Returns the start offset of the memory block. - * - * If the memory block has a parent, the returned start offset is NOT relative to the parent memory block's - * start offset (in other words: the returned value is an absolute offset which can be directly used against - * the memory block instance) - */ - VkDeviceSize get_start_offset() const + const VkDeviceSize& get_start_offset() const { return m_start_offset; } @@ -254,29 +205,7 @@ namespace Anvil /* Private functions */ bool init(); - /** Please see create() for documentation */ - MemoryBlock(const Anvil::BaseDevice* in_device_ptr, - uint32_t in_allowed_memory_bits, - VkDeviceSize in_size, - Anvil::MemoryFeatureFlags in_memory_features, - bool in_mt_safe, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types); - - /** Please see create() for documentation */ - MemoryBlock(MemoryBlock* in_parent_memory_block_ptr, - VkDeviceSize in_start_offset, - VkDeviceSize in_size); - - /** Please see create_derived_with_custom_delete_proc() for documentation */ - MemoryBlock(const Anvil::BaseDevice* in_device_ptr, - VkDeviceMemory in_memory, - uint32_t in_allowed_memory_bits, - Anvil::MemoryFeatureFlags in_memory_features, - uint32_t in_memory_type_index, - VkDeviceSize in_size, - VkDeviceSize in_start_offset, - OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types); + MemoryBlock(Anvil::MemoryBlockCreateInfoUniquePtr in_create_info_ptr); MemoryBlock (const MemoryBlock&); MemoryBlock& operator=(const MemoryBlock&); @@ -297,7 +226,7 @@ namespace Anvil m_parent_memory_allocator_backend_ptr = m_owned_parent_memory_allocator_backend_ptr.get(); { - auto parent_memory_block_ptr = m_parent_memory_block_ptr; + auto parent_memory_block_ptr = m_create_info_ptr->get_parent_memory_block(); while (parent_memory_block_ptr != nullptr) { @@ -307,30 +236,25 @@ namespace Anvil parent_memory_block_ptr->m_backend_object = in_backend_object; parent_memory_block_ptr->m_parent_memory_allocator_backend_ptr = in_backend_ptr.get(); - parent_memory_block_ptr = parent_memory_block_ptr->m_parent_memory_block_ptr; + parent_memory_block_ptr = parent_memory_block_ptr->get_create_info_ptr()->get_parent_memory_block(); } } } /* Private members */ - OnMemoryBlockReleaseCallbackFunction m_on_release_callback_function; - std::atomic m_gpu_data_map_count; /* Only set for root memory blocks */ void* m_gpu_data_ptr; /* Only set for root memory blocks */ - uint32_t m_allowed_memory_bits; - void* m_backend_object; - const Anvil::BaseDevice* m_device_ptr; - Anvil::ExternalMemoryHandleTypeFlags m_external_memory_handle_types; - VkDeviceMemory m_memory; - Anvil::MemoryFeatureFlags m_memory_features; - uint32_t m_memory_type_index; - Anvil::MemoryBlock* m_parent_memory_block_ptr; - VkDeviceSize m_size; - VkDeviceSize m_start_offset; + void* m_backend_object; + Anvil::MemoryBlockCreateInfoUniquePtr m_create_info_ptr; + VkDeviceMemory m_memory; + uint32_t m_memory_type_index; + VkDeviceSize m_start_offset; std::shared_ptr m_owned_parent_memory_allocator_backend_ptr; Anvil::IMemoryAllocatorBackendBase* m_parent_memory_allocator_backend_ptr; + + std::map m_external_handle_type_to_external_handle; }; }; /* Vulkan namespace */ diff --git a/include/wrappers/physical_device.h b/include/wrappers/physical_device.h index 120ae408..3a5183d4 100644 --- a/include/wrappers/physical_device.h +++ b/include/wrappers/physical_device.h @@ -59,87 +59,12 @@ namespace Anvil /** Destructor */ virtual ~PhysicalDevice(); - /* Returns physical device's LUID. + /* TODO * - * Requires VK_KHR_external_memory support, as well as VkPhysicalDeviceIDPropertiesKHR::deviceLUIDValid - * to have been set to true by the driver owning the physical device, in order to report success. - * - * @param out_result_ptr Exactly VK_LUID_SIZE_KHR bytes will be copied under *out_result_ptr if - * function returns true. Must not be nullptr. - * - * @return true if successful, false otherwise. - **/ - bool get_device_LUID(uint8_t* out_result_ptr) const - { - bool result = false; - - if (m_device_LUID_available) - { - static_assert(sizeof(m_device_LUID) == VK_LUID_SIZE_KHR, ""); - - memcpy(out_result_ptr, - m_device_LUID, - VK_LUID_SIZE_KHR); - - result = true; - } - - return result; - } - - /* Returns physical device's UUID. - * - * Requires VK_KHR_external_memory support to return successfully. - * - * @param out_result_ptr Exactly VK_UUID_SIZE bytes will be copied under *out_result_ptr if - * function returns true. Must not be nullptr. - * - * @return true if successful, false otherwise. - **/ - bool get_device_UUID(uint8_t* out_result_ptr) const - { - bool result = false; - - if (m_device_UUID_available) - { - static_assert(sizeof(m_device_UUID) == VK_UUID_SIZE, ""); - - memcpy(out_result_ptr, - m_device_UUID, - VK_UUID_SIZE); - - result = true; - } - - return result; - } - - /* Returns UUID of the driver owning the physical device. - * - * Requires VK_KHR_external_memory support to return successfully. - * - * @param out_result_ptr Exactly VK_UUID_SIZE bytes will be copied under *out_result_ptr if - * function returns true. Must not be nullptr. - * - * @return true if successful, false otherwise. - **/ - bool get_driver_UUID(uint8_t* out_result_ptr) const - { - bool result = false; - - if (m_driver_UUID_available) - { - static_assert(sizeof(m_driver_UUID) == VK_UUID_SIZE, ""); - - memcpy(out_result_ptr, - m_driver_UUID, - VK_UUID_SIZE); - - result = true; - } - - return result; - } + * Requires VK_KHR_external_memory_capabilities. + */ + bool get_buffer_format_properties(const Anvil::BufferFormatPropertiesQuery& in_query, + Anvil::BufferFormatProperties* out_opt_result_ptr = nullptr) const; /** Retrieves features supported by the physical device */ const Anvil::PhysicalDeviceFeatures& get_device_features() const @@ -152,27 +77,27 @@ namespace Anvil return m_properties; } - /** Retrieves format properties, as reported by the wrapped physical device. + /* TODO + * + * Requires VK_KHR_external_fence_capabiltiies. + * + */ + bool get_fence_properties(const Anvil::FencePropertiesQuery& in_query, + Anvil::FenceProperties* out_opt_result_ptr = nullptr) const; + + Anvil::FormatProperties get_format_properties(VkFormat in_format) const; + + /** Retrieves image format properties, as reported by the wrapped physical device. + * + * For external memory handle capability queries, VK_KHR_external_memory_capabilities support is required. + * * * @param in_format Vulkan format to retrieve the filled structure for. * * @return As per description. **/ - const FormatProperties& get_format_properties(VkFormat in_format) const - { - auto format_props_iterator = m_format_properties.find(in_format); - - if (format_props_iterator != m_format_properties.end() ) - { - return format_props_iterator->second; - } - else - { - anvil_assert_fail(); - - return m_dummy; - } - } + bool get_image_format_properties(const ImageFormatPropertiesQuery& in_query, + Anvil::ImageFormatProperties* out_opt_result_ptr = nullptr) const; /** Returns index of the physical device. */ uint32_t get_index() const @@ -219,6 +144,14 @@ namespace Anvil return m_queue_families; } + /* TODO + * + * Requires VK_KHR_external_semaphore_capabiltiies. + * + */ + bool get_semaphore_properties(const Anvil::SemaphorePropertiesQuery& in_query, + Anvil::SemaphoreProperties* out_opt_result_ptr = nullptr) const; + /** Returns sparse image format properties for this physical device. See Vulkan spec * for vkGetPhysicalDeviceSparseImageFormatProperties() function for more details. * @@ -258,9 +191,6 @@ namespace Anvil bool is_layer_supported(const std::string& in_layer_name) const; private: - /* Private type definitions */ - typedef std::map FormatPropertiesMap; - /* Private functions */ /** Constructor. Retrieves properties & capabilities of a physical device at @@ -274,11 +204,9 @@ namespace Anvil explicit PhysicalDevice(Anvil::Instance* in_instance_ptr, uint32_t in_index, VkPhysicalDevice in_physical_device) - :m_device_LUID_available(false), - m_device_UUID_available(false), - m_index (in_index), - m_instance_ptr (in_instance_ptr), - m_physical_device (in_physical_device) + :m_index (in_index), + m_instance_ptr (in_instance_ptr), + m_physical_device(in_physical_device) { anvil_assert(in_physical_device != VK_NULL_HANDLE); } @@ -294,27 +222,20 @@ namespace Anvil uint32_t m_index; Anvil::Instance* m_instance_ptr; Anvil::PhysicalDeviceFeatures m_features; - FormatPropertiesMap m_format_properties; Anvil::Layers m_layers; MemoryProperties m_memory_properties; VkPhysicalDevice m_physical_device; QueueFamilyInfoItems m_queue_families; Anvil::PhysicalDeviceProperties m_properties; - std::unique_ptr m_amd_shader_core_properties_ptr; - std::unique_ptr m_core_features_vk10_ptr; - std::unique_ptr m_core_properties_vk10_ptr; - std::unique_ptr m_ext_descriptor_indexing_features_ptr; - std::unique_ptr m_ext_descriptor_indexing_properties_ptr; - std::unique_ptr m_khr_16_bit_storage_features_ptr; - std::unique_ptr m_khr_maintenance3_properties_ptr; - - bool m_device_LUID_available; - uint8_t m_device_LUID[VK_LUID_SIZE_KHR]; - bool m_device_UUID_available; - uint8_t m_device_UUID[VK_UUID_SIZE]; - uint8_t m_driver_UUID[VK_UUID_SIZE]; - bool m_driver_UUID_available; + std::unique_ptr m_amd_shader_core_properties_ptr; + std::unique_ptr m_core_features_vk10_ptr; + std::unique_ptr m_core_properties_vk10_ptr; + std::unique_ptr m_ext_descriptor_indexing_features_ptr; + std::unique_ptr m_ext_descriptor_indexing_properties_ptr; + std::unique_ptr m_khr_16_bit_storage_features_ptr; + std::unique_ptr m_khr_external_memory_capabilities_physical_device_id_properties_ptr; + std::unique_ptr m_khr_maintenance3_properties_ptr; friend class Anvil::Instance; }; diff --git a/include/wrappers/query_pool.h b/include/wrappers/query_pool.h index b0544ceb..177c11c9 100644 --- a/include/wrappers/query_pool.h +++ b/include/wrappers/query_pool.h @@ -87,6 +87,43 @@ namespace Anvil return m_query_pool_vk; } + /* Uses vkGetQueryPoolResults() to retrieve result values for the user-specified query range. + * + * NOTE: It is assumed result values are to be returned to a tightly-packed array of size + * @param in_n_queries * sizeof(query result type). if @param in_query_props includes QUERY_RESULT_WITH_AVAILABILITY_BIT, + * twice the amount of memory is needed for result storage. + * + * NOTE: It is caller's responsibility to follow the requirements listed in the spec which guarantee + * the results returned by this entrypoint are correct. + * + **/ + bool get_query_pool_results(const uint32_t& in_first_query_index, + const uint32_t& in_n_queries, + const QueryResultBits& in_query_props, + uint32_t* out_results_ptr, + bool* out_all_query_results_retrieved_ptr) + { + return get_query_pool_results_internal(in_first_query_index, + in_n_queries, + in_query_props, + false, /* should_return_uint64 */ + out_results_ptr, + out_all_query_results_retrieved_ptr); + } + + bool get_query_pool_results(const uint32_t& in_first_query_index, + const uint32_t& in_n_queries, + const QueryResultBits& in_query_props, + uint64_t* out_results_ptr, + bool* out_all_query_results_retrieved_ptr) + { + return get_query_pool_results_internal(in_first_query_index, + in_n_queries, + in_query_props, + true, /* should_return_uint64 */ + out_results_ptr, + out_all_query_results_retrieved_ptr); + } private: /* Constructor. Please see corresponding create() for specification */ @@ -102,6 +139,13 @@ namespace Anvil uint32_t in_n_max_concurrent_queries, bool in_mt_safe); + bool get_query_pool_results_internal(const uint32_t& in_first_query_index, + const uint32_t& in_n_queries, + const QueryResultBits& in_query_props, + const bool& in_should_return_uint64, + void* out_results_ptr, + bool* out_all_query_results_retrieved_ptr); + /** Initializes the Vulkan counterpart. * * @param in_query_type Type of the query to instantiate the pool for. @@ -117,6 +161,7 @@ namespace Anvil const Anvil::BaseDevice* m_device_ptr; uint32_t m_n_max_indices; VkQueryPool m_query_pool_vk; + const VkQueryType m_query_type; }; }; /* namespace Anvil */ diff --git a/include/wrappers/queue.h b/include/wrappers/queue.h index 778bf1d5..99d9f036 100644 --- a/include/wrappers/queue.h +++ b/include/wrappers/queue.h @@ -132,142 +132,7 @@ namespace Anvil uint32_t in_n_wait_semaphores, Anvil::Semaphore* const* in_wait_semaphore_ptrs_ptr); - /** Waits on the semaphores specified by the user, executes user-defined command buffers, - * and then signals the semaphores passed by arguments. If a non-nullptr fence is specified, - * the function will also wait on the call to finish GPU-side before returning. - * - * It is valid to specify 0 command buffers or signal/wait semaphores, in which case - * these steps will be skipped. - * - * If @param in_should_block is true and @param in_opt_fence_ptr is nullptr, the function will create - * a new fence, wait on it, and then release it prior to leaving. This may come at a performance cost. - * - * @param in_n_command_buffers Number of command buffers under @param in_opt_cmd_buffer_ptrs - * which should be executed. May be 0. - * @param in_opt_cmd_buffer_ptrs_ptr Ptr to an array of command buffers to execute. Can be nullptr if - * @param n_command_buffers is 0. - * @param in_n_semaphores_to_signal Number of semaphores to signal after command buffers finish - * executing. May be 0. - * @param in_opt_semaphore_to_signal_ptrs_ptr Ptr to an array of semaphores to signal after execution. May be nullptr if - * @param n_semaphores_to_signal is 0. - * @param in_n_semaphores_to_wait_on Number of semaphores to wait on before executing command buffers. - * May be 0. - * @param in_opt_semaphore_to_wait_on_ptrs_ptr Ptr to an array of semaphores to wait on prior to execution. May be nullptr - * if @param in_n_semaphores_to_wait_on is 0. - * @param in_opt_dst_stage_masks_to_wait_on_ptrs Array of size @param in_n_semaphores_to_wait_on, specifying stages - * at which the wait ops should be performed. May be nullptr if - * @param n_semaphores_to_wait_on is 0. - * @param in_should_block true if the function should wait for the scheduled commands to - * finish executing, false otherwise. - * @param in_opt_fence_ptr Fence to use when submitting the comamnd buffers to the queue. - * The fence will be waited on if @param in_should_block is true. - * If @param in_should_block is false, the fence will be passed at - * submit call time, but will not be waited on. - **/ - void submit_command_buffers(uint32_t in_n_command_buffers, - Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs_ptr, - uint32_t in_n_semaphores_to_signal, - Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptr_ptrs_ptr, - uint32_t in_n_semaphores_to_wait_on, - Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, - const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr = nullptr); - - /** Submits specified command buffer to the queue. Can optionally wait until the execution finishes. - * - * For argument discussion, please see submit_command_buffers() documentation - **/ - void submit_command_buffer(Anvil::CommandBufferBase* in_cmd_buffer_ptr, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr = nullptr) - { - submit_command_buffers(1, /* n_command_buffers */ - &in_cmd_buffer_ptr, - 0, /* n_semaphores_to_signal */ - nullptr, /* semaphore_to_signal_ptrs */ - 0, /* n_semaphoires_to_wait_on */ - nullptr, /* semaphore_to_wait_on_ptrs */ - nullptr, - in_should_block, - in_opt_fence_ptr); - } - - /** Submits specified command buffer to the queue. After the command buffer finishes executing - * GPU-side, user-specified semaphores will be signalled. - * - * Can optionally wait until the execution finishes. - * - * For argument discussion, please see submit_command_buffers() documentation - **/ - void submit_command_buffer_with_signal_semaphores(Anvil::CommandBufferBase* in_opt_cmd_buffer_ptr, - uint32_t in_n_semaphores_to_signal, - Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr = nullptr) - { - submit_command_buffers((in_opt_cmd_buffer_ptr != nullptr) ? 1u : 0u, - &in_opt_cmd_buffer_ptr, - in_n_semaphores_to_signal, - in_semaphore_to_signal_ptrs_ptr, - 0, /* n_semaphores_to_wait_on */ - nullptr, /* semaphore_to_wait_on_ptr_ptrs */ - nullptr, /* opt_dst_stage_masks_to_wait_on_ptrs */ - in_should_block, - in_opt_fence_ptr); - } - - /** Waits on the user-specified semaphores and submits specified command buffer to the queue. - * After the command buffer finishes executing GPU-side, user-specified semaphores will be - * signalled. - * - * Can optionally wait until the execution finishes. - * - * For argument discussion, please see submit_command_buffers() documentation - **/ - void submit_command_buffer_with_signal_wait_semaphores(Anvil::CommandBufferBase* in_opt_cmd_buffer_ptr, - uint32_t in_n_semaphores_to_signal, - Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, - uint32_t in_n_semaphores_to_wait_on, - Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, - const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr = nullptr) - { - submit_command_buffers((in_opt_cmd_buffer_ptr != nullptr) ? 1u : 0u, - &in_opt_cmd_buffer_ptr, - in_n_semaphores_to_signal, - in_semaphore_to_signal_ptrs_ptr, - in_n_semaphores_to_wait_on, - in_semaphore_to_wait_on_ptrs_ptr, - in_dst_stage_masks_to_wait_on_ptrs, - in_should_block, - in_opt_fence_ptr); - } - - /** Waits on the user-specified semaphores and submits specified command buffer to the queue. - * - * Can optionally wait until the execution finishes. - * - * For argument discussion, please see submit_command_buffers() documentation - **/ - void submit_command_buffer_with_wait_semaphores(Anvil::CommandBufferBase* in_cmd_buffer_ptr, - uint32_t in_n_semaphores_to_wait_on, - Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, - const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr = nullptr) - { - submit_command_buffers((in_cmd_buffer_ptr != nullptr) ? 1u : 0u, - &in_cmd_buffer_ptr, - 0u, /* n_semaphores_to_signal */ - nullptr, /* semaphore_to_signal_ptr_ptrs */ - in_n_semaphores_to_wait_on, - in_semaphore_to_wait_on_ptrs_ptr, - in_dst_stage_masks_to_wait_on_ptrs, - in_should_block, - in_opt_fence_ptr); - } + void submit(const SubmitInfo& in_submit_info); /** Tells whether the queue supports sparse bindings */ bool supports_sparse_bindings() const diff --git a/include/wrappers/semaphore.h b/include/wrappers/semaphore.h index 71f0531a..4a111576 100644 --- a/include/wrappers/semaphore.h +++ b/include/wrappers/semaphore.h @@ -47,6 +47,18 @@ namespace Anvil /** Creates a single Vulkan semaphore instance and registers the object in Object Tracker. */ static Anvil::SemaphoreUniquePtr create(Anvil::SemaphoreCreateInfoUniquePtr in_create_info_ptr); + /* Creates a new external semaphore handle of the user-specified type. + * + * For NT handle types, the function can only be called once per each NT handle type. Subsequent + * calls will result in the function triggering an assertion failure and returning null. + * + * Returns nullptr if unsuccessful. + * + * Requires VK_KHR_external_semaphore_fd under Linux. + * Requires VK_KHR_external_semaphore_win32 under Windows. + */ + ExternalHandleUniquePtr export_to_external_handle(const Anvil::ExternalSemaphoreHandleTypeBit& in_semaphore_handle_type); + /** Destructor. * * Destroys the Vulkan counterpart and unregisters the wrapper instance from the Object Tracker. @@ -70,6 +82,32 @@ namespace Anvil return &m_semaphore; } + /* TODO + * + * Requires VK_KHR_external_semaphore_fd under Linux. + * Requires VK_KHR_external_semaphore_win32 under Windows. + * + * + * @return true if successful, false otherwise. + * + * @param in_temporary_import True if a temporary import operation should be performed. False if + * a permanent import is being requested. + * @param in_handle_type Type of the handle that is being imported. + * @param in_handle (Linux): Handle to use. Must not be -1. + * @param in_opt_handle (Windows): Win32 NT handle to use. Must not be null if @param in_opt_name is null and vice versa. + * @param in_opt_name (Windows): Name of the handle to use. Must not be null if @param in_opt_handle is null and vice versa. + */ + #if defined(_WIN32) + bool import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalSemaphoreHandleTypeBit& in_handle_type, + const ExternalHandleType& in_opt_handle, + const std::wstring& in_opt_name); + #else + bool import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalSemaphoreHandleTypeBit& in_handle_type, + const ExternalHandleType& in_handle); + #endif + /** Releases the underlying Vulkan Semaphore instance and creates a new Vulkan object. */ bool reset(); @@ -83,8 +121,9 @@ namespace Anvil void release_semaphore(); /* Private variables */ - Anvil::SemaphoreCreateInfoUniquePtr m_create_info_ptr; - VkSemaphore m_semaphore; + Anvil::SemaphoreCreateInfoUniquePtr m_create_info_ptr; + std::map m_external_semaphore_created_for_handle_type; + VkSemaphore m_semaphore; ANVIL_DISABLE_ASSIGNMENT_OPERATOR(Semaphore); ANVIL_DISABLE_COPY_CONSTRUCTOR(Semaphore); diff --git a/src/misc/buffer_create_info.cpp b/src/misc/buffer_create_info.cpp index 141d8017..8da43b69 100644 --- a/src/misc/buffer_create_info.cpp +++ b/src/misc/buffer_create_info.cpp @@ -91,14 +91,14 @@ Anvil::BufferCreateInfoUniquePtr Anvil::BufferCreateInfo::create_nonsparse_no_al return result_ptr; } -Anvil::BufferCreateInfoUniquePtr Anvil::BufferCreateInfo::create_sparse_no_alloc(const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - Anvil::SparseResidencyScope in_residency_scope, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +Anvil::BufferCreateInfoUniquePtr Anvil::BufferCreateInfo::create_sparse_no_alloc(const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + Anvil::SparseResidencyScope in_residency_scope, + MTSafety in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { Anvil::BufferCreateInfoUniquePtr result_ptr(nullptr, std::default_delete() ); @@ -117,14 +117,14 @@ Anvil::BufferCreateInfoUniquePtr Anvil::BufferCreateInfo::create_sparse_no_alloc return result_ptr; } -Anvil::BufferCreateInfo::BufferCreateInfo(const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - Anvil::SparseResidencyScope in_residency_scope, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +Anvil::BufferCreateInfo::BufferCreateInfo(const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + Anvil::SparseResidencyScope in_residency_scope, + MTSafety in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) :m_client_data_ptr (nullptr), m_device_ptr (in_device_ptr), m_external_memory_handle_types(in_external_memory_handle_types), @@ -164,16 +164,16 @@ Anvil::BufferCreateInfo::BufferCreateInfo(const Anvil::BaseDevice* i } } -Anvil::BufferCreateInfo::BufferCreateInfo(const Anvil::BufferType& in_buffer_type, - const Anvil::BaseDevice* in_device_ptr, - VkDeviceSize in_size, - QueueFamilyBits in_queue_families, - VkSharingMode in_sharing_mode, - VkBufferUsageFlags in_usage_flags, - MemoryFeatureFlags in_memory_features, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types, - const void* in_opt_client_data_ptr) +Anvil::BufferCreateInfo::BufferCreateInfo(const Anvil::BufferType& in_buffer_type, + const Anvil::BaseDevice* in_device_ptr, + VkDeviceSize in_size, + QueueFamilyBits in_queue_families, + VkSharingMode in_sharing_mode, + VkBufferUsageFlags in_usage_flags, + MemoryFeatureFlags in_memory_features, + MTSafety in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types, + const void* in_opt_client_data_ptr) :m_client_data_ptr (in_opt_client_data_ptr), m_device_ptr (in_device_ptr), m_external_memory_handle_types(in_external_memory_handle_types), diff --git a/src/misc/dummy_window.cpp b/src/misc/dummy_window.cpp index a924feda..d3a101ac 100644 --- a/src/misc/dummy_window.cpp +++ b/src/misc/dummy_window.cpp @@ -174,8 +174,6 @@ std::unique_ptr Anvil::DummyWindowWithPNGSnapshots::get_swapchain_ima ANVIL_REDUNDANT_VARIABLE(swapchain_image_format); anvil_assert(swapchain_image_subresource_range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - anvil_assert(device_ptr->get_physical_device_format_properties(swapchain_image_format).optimal_tiling_capabilities & VK_FORMAT_FEATURE_BLIT_SRC_BIT); - anvil_assert(device_ptr->get_physical_device_format_properties(VK_FORMAT_R8G8B8A8_UNORM).optimal_tiling_capabilities & VK_FORMAT_FEATURE_BLIT_DST_BIT); /* Initialize storage for the raw R8G8B8A8 image data */ Anvil::BufferUniquePtr raw_image_buffer_ptr; @@ -356,8 +354,14 @@ std::unique_ptr Anvil::DummyWindowWithPNGSnapshots::get_swapchain_ima command_buffer_ptr->stop_recording(); /* Execute the command buffer */ - universal_queue_ptr->submit_command_buffer(command_buffer_ptr.get(), - true); /* should_block */ + { + Anvil::CommandBufferBase* cmd_buffer_raw_ptr = command_buffer_ptr.get(); + + universal_queue_ptr->submit(Anvil::SubmitInfo::create_execute(&cmd_buffer_raw_ptr, + 1, /* in_n_cmd_buffers */ + true) /* should_block */ + ); + } /* Read back the result data */ raw_image_buffer_ptr->read(0, /* offset */ diff --git a/src/misc/external_handle.cpp b/src/misc/external_handle.cpp new file mode 100644 index 00000000..07b3720f --- /dev/null +++ b/src/misc/external_handle.cpp @@ -0,0 +1,64 @@ +// +// Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#include "misc/external_handle.h" + +#if !defined(_WIN32) + #include +#endif + +Anvil::ExternalHandle::ExternalHandle(const ExternalHandleType& in_handle, + const bool& in_close_at_destruction_time) + :m_close_at_destruction_time(in_close_at_destruction_time), + m_handle (in_handle) +{ + /* Stub */ +} + +Anvil::ExternalHandleUniquePtr Anvil::ExternalHandle::create(const ExternalHandleType& in_handle, + const bool& in_close_at_destruction_time) +{ + Anvil::ExternalHandleUniquePtr result_ptr(nullptr, + std::default_delete() ); + + result_ptr.reset( + new ExternalHandle(in_handle, + in_close_at_destruction_time) + ); + + return result_ptr; +} + +Anvil::ExternalHandle::~ExternalHandle() +{ + if (m_close_at_destruction_time) + { + #if defined(_WIN32) + { + ::CloseHandle(m_handle); + } + #else + { + close(m_handle); + } + #endif + } +} \ No newline at end of file diff --git a/src/misc/fence_create_info.cpp b/src/misc/fence_create_info.cpp index 106cce8a..90ed5403 100644 --- a/src/misc/fence_create_info.cpp +++ b/src/misc/fence_create_info.cpp @@ -39,9 +39,13 @@ Anvil::FenceCreateInfoUniquePtr Anvil::FenceCreateInfo::create(const Anvil::Base Anvil::FenceCreateInfo::FenceCreateInfo(const Anvil::BaseDevice* in_device_ptr, bool in_create_signalled, MTSafety in_mt_safety) - :m_create_signalled(in_create_signalled), - m_device_ptr (in_device_ptr), - m_mt_safety (in_mt_safety) + :m_create_signalled (in_create_signalled), + m_device_ptr (in_device_ptr), +#if defined(_WIN32) + m_exportable_nt_handle_info_specified (false), +#endif + m_exportable_external_fence_handle_types(Anvil::EXTERNAL_FENCE_HANDLE_TYPE_NONE), + m_mt_safety (in_mt_safety) { /* Stub */ } \ No newline at end of file diff --git a/src/misc/image_create_info.cpp b/src/misc/image_create_info.cpp index 27ffe84b..de2fff54 100644 --- a/src/misc/image_create_info.cpp +++ b/src/misc/image_create_info.cpp @@ -211,28 +211,28 @@ Anvil::ImageCreateInfoUniquePtr Anvil::ImageCreateInfo::create_swapchain_wrapper return result_ptr; } -Anvil::ImageCreateInfo::ImageCreateInfo(Anvil::ImageType in_type, - const Anvil::BaseDevice* in_device_ptr, - VkImageType in_type_vk, - VkFormat in_format, - VkImageTiling in_tiling, - VkSharingMode in_sharing_mode, - VkImageUsageFlags in_usage, - uint32_t in_base_mipmap_width, - uint32_t in_base_mipmap_height, - uint32_t in_base_mipmap_depth, - uint32_t in_n_layers, - VkSampleCountFlagBits in_sample_count, - bool in_use_full_mipmap_chain, - ImageCreateFlags in_create_flags, - Anvil::QueueFamilyBits in_queue_families, - VkImageLayout in_post_create_image_layout, - const VkImageLayout& in_post_alloc_image_layout, - const std::vector* in_opt_mipmaps_ptr, - const Anvil::MTSafety& in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types, - const Anvil::MemoryFeatureFlags& in_memory_features, - const Anvil::SparseResidencyScope& in_residency_scope) +Anvil::ImageCreateInfo::ImageCreateInfo(Anvil::ImageType in_type, + const Anvil::BaseDevice* in_device_ptr, + VkImageType in_type_vk, + VkFormat in_format, + VkImageTiling in_tiling, + VkSharingMode in_sharing_mode, + VkImageUsageFlags in_usage, + uint32_t in_base_mipmap_width, + uint32_t in_base_mipmap_height, + uint32_t in_base_mipmap_depth, + uint32_t in_n_layers, + VkSampleCountFlagBits in_sample_count, + bool in_use_full_mipmap_chain, + ImageCreateFlags in_create_flags, + Anvil::QueueFamilyBits in_queue_families, + VkImageLayout in_post_create_image_layout, + const VkImageLayout& in_post_alloc_image_layout, + const std::vector* in_opt_mipmaps_ptr, + const Anvil::MTSafety& in_mt_safety, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types, + const Anvil::MemoryFeatureFlags& in_memory_features, + const Anvil::SparseResidencyScope& in_residency_scope) :m_create_flags (in_create_flags), m_depth (in_base_mipmap_depth), m_device_ptr (in_device_ptr), diff --git a/src/misc/memalloc_backends/backend_oneshot.cpp b/src/misc/memalloc_backends/backend_oneshot.cpp index 30c735ea..c43f23de 100644 --- a/src/misc/memalloc_backends/backend_oneshot.cpp +++ b/src/misc/memalloc_backends/backend_oneshot.cpp @@ -24,6 +24,7 @@ #include "misc/debug.h" #include "misc/formats.h" #include "misc/memory_allocator.h" +#include "misc/memory_block_create_info.h" #include "wrappers/buffer.h" #include "wrappers/device.h" #include "wrappers/image.h" @@ -126,11 +127,16 @@ bool Anvil::MemoryAllocatorBackends::OneShot::bake(Anvil::MemoryAllocator::Items } /* Bake the block and stash it */ - new_memory_block_ptr = Anvil::MemoryBlock::create(m_device_ptr, - 1u << current_memory_type_index, - n_bytes_required, - (memory_props.types[current_memory_type_index].features), - Anvil::Utils::convert_boolean_to_mt_safety_enum(m_device_ptr->is_mt_safe()) ); + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_regular(m_device_ptr, + 1u << current_memory_type_index, + n_bytes_required, + (memory_props.types[current_memory_type_index].features) ); + + create_info_ptr->set_mt_safety(Anvil::Utils::convert_boolean_to_mt_safety_enum(m_device_ptr->is_mt_safe()) ); + + new_memory_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } if (new_memory_block_ptr == nullptr) { @@ -143,9 +149,13 @@ bool Anvil::MemoryAllocatorBackends::OneShot::bake(Anvil::MemoryAllocator::Items /* Go through the items again and assign the result memory block */ for (auto& current_item_ptr : current_item_vector) { - current_item_ptr->alloc_memory_block_ptr = Anvil::MemoryBlock::create_derived(new_memory_block_ptr.get(), - alloc_offset_map.at(current_item_ptr), - current_item_ptr->alloc_size); + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_derived(new_memory_block_ptr.get(), + alloc_offset_map.at(current_item_ptr), + current_item_ptr->alloc_size); + + current_item_ptr->alloc_memory_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } if (current_item_ptr->alloc_memory_block_ptr != nullptr) { @@ -197,7 +207,7 @@ bool Anvil::MemoryAllocatorBackends::OneShot::supports_baking() const return !m_is_baked; } -bool Anvil::MemoryAllocatorBackends::OneShot::supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const +bool Anvil::MemoryAllocatorBackends::OneShot::supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const { return (in_external_memory_handle_types == 0); } diff --git a/src/misc/memalloc_backends/backend_vma.cpp b/src/misc/memalloc_backends/backend_vma.cpp index 757a935e..53fccd42 100644 --- a/src/misc/memalloc_backends/backend_vma.cpp +++ b/src/misc/memalloc_backends/backend_vma.cpp @@ -21,6 +21,7 @@ // #include "misc/debug.h" +#include "misc/memory_block_create_info.h" #include "wrappers/device.h" #include "wrappers/memory_block.h" #include "wrappers/physical_device.h" @@ -205,15 +206,18 @@ bool Anvil::MemoryAllocatorBackends::VMA::bake(Anvil::MemoryAllocator::Items& in allocation ); - new_memory_block_ptr = Anvil::MemoryBlock::create_derived_with_custom_delete_proc(m_device_ptr, - allocation_info.deviceMemory, - memory_requirements_vk.memoryTypeBits, - current_item_ptr->alloc_memory_required_features, - allocation_info.memoryType, - memory_requirements_vk.size, - allocation_info.offset, - release_callback_function, - 0); /* in_external_memory_handle_types */ + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_derived_with_custom_delete_proc(m_device_ptr, + allocation_info.deviceMemory, + memory_requirements_vk.memoryTypeBits, + current_item_ptr->alloc_memory_required_features, + allocation_info.memoryType, + memory_requirements_vk.size, + allocation_info.offset, + release_callback_function); + + new_memory_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } if (new_memory_block_ptr == nullptr) { @@ -301,7 +305,7 @@ void Anvil::MemoryAllocatorBackends::VMA::VMAAllocator::on_vma_alloced_mem_block VmaAllocation in_vma_allocation) { /* Only physically deallocate those memory blocks that are not derivatives of another memory blocks! */ - if (in_memory_block_ptr->get_parent_memory_block() == nullptr) + if (in_memory_block_ptr->get_create_info_ptr()->get_parent_memory_block() == nullptr) { vmaFreeMemory(get_handle(), in_vma_allocation); @@ -323,7 +327,7 @@ bool Anvil::MemoryAllocatorBackends::VMA::supports_baking() const return true; } -bool Anvil::MemoryAllocatorBackends::VMA::supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const +bool Anvil::MemoryAllocatorBackends::VMA::supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const { /* Vulkan Memory Allocator does NOT support external memory handles */ ANVIL_REDUNDANT_VARIABLE_CONST(in_external_memory_handle_types); diff --git a/src/misc/memory_allocator.cpp b/src/misc/memory_allocator.cpp index b7508c2f..f45cb5e2 100644 --- a/src/misc/memory_allocator.cpp +++ b/src/misc/memory_allocator.cpp @@ -35,14 +35,14 @@ #include "wrappers/queue.h" /* Please see header for specification */ -Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types) +Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types) { anvil_assert(in_alloc_supported_memory_types != 0); anvil_assert(in_memory_allocator_ptr != nullptr); @@ -63,15 +63,15 @@ Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memor register_for_callbacks(); } -Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_alloc_offset, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types) +Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_alloc_offset, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types) { anvil_assert(in_alloc_supported_memory_types != 0); anvil_assert(in_memory_allocator_ptr != nullptr); @@ -94,16 +94,16 @@ Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memor } /* Please see header for specification */ -Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - uint32_t in_n_layer, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_miptail_offset, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types) +Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + uint32_t in_n_layer, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_miptail_offset, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types) { anvil_assert(in_alloc_supported_memory_types != 0); anvil_assert(in_memory_allocator_ptr != nullptr); @@ -128,17 +128,17 @@ Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memor } /* Please see header for specification */ -Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - const VkImageSubresource& in_subresource, - const VkOffset3D& in_offset, - const VkExtent3D& in_extent, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types) +Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + const VkImageSubresource& in_subresource, + const VkOffset3D& in_offset, + const VkExtent3D& in_extent, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types) { anvil_assert(in_alloc_supported_memory_types != 0); anvil_assert(in_memory_allocator_ptr != nullptr); @@ -164,14 +164,14 @@ Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memor } /* Please see header for specification */ -Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, - Anvil::Image* in_image_ptr, - VkDeviceSize in_alloc_size, - uint32_t in_alloc_memory_types, - VkDeviceSize in_alloc_alignment, - MemoryFeatureFlags in_alloc_required_memory_features, - uint32_t in_alloc_supported_memory_types, - Anvil::ExternalMemoryHandleTypeFlags in_alloc_external_memory_handle_types) +Anvil::MemoryAllocator::Item::Item(Anvil::MemoryAllocator* in_memory_allocator_ptr, + Anvil::Image* in_image_ptr, + VkDeviceSize in_alloc_size, + uint32_t in_alloc_memory_types, + VkDeviceSize in_alloc_alignment, + MemoryFeatureFlags in_alloc_required_memory_features, + uint32_t in_alloc_supported_memory_types, + Anvil::ExternalMemoryHandleTypeBits in_alloc_external_memory_handle_types) { anvil_assert(in_alloc_supported_memory_types != 0); anvil_assert(in_memory_allocator_ptr != nullptr); @@ -354,9 +354,9 @@ Anvil::MemoryAllocator::~MemoryAllocator() /** Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer(Anvil::Buffer* in_buffer_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer(Anvil::Buffer* in_buffer_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -378,9 +378,9 @@ bool Anvil::MemoryAllocator::add_buffer(Anvil::Buffer* in_ * * @param buffer_ptr Buffer instance to assign a memory block at baking time. **/ -bool Anvil::MemoryAllocator::add_buffer_internal(Anvil::Buffer* in_buffer_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_internal(Anvil::Buffer* in_buffer_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { IMemoryAllocatorBackend* backend_interface_ptr = dynamic_cast(m_backend_ptr.get() ); VkDeviceSize buffer_alignment = 0; @@ -450,10 +450,10 @@ bool Anvil::MemoryAllocator::add_buffer_internal(Anvil::Buffer* } /* Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer_with_float_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, - std::unique_ptr in_data_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_with_float_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, + std::unique_ptr in_data_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -482,7 +482,7 @@ bool Anvil::MemoryAllocator::add_buffer_with_float_data_ptr_based_post_fill(Anvi bool Anvil::MemoryAllocator::add_buffer_with_float_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -510,10 +510,10 @@ bool Anvil::MemoryAllocator::add_buffer_with_float_data_vector_ptr_based_post_fi } /* Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer_with_float_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, - const std::vector* in_data_vector_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_with_float_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, + const std::vector* in_data_vector_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -546,10 +546,10 @@ bool Anvil::MemoryAllocator::add_buffer_with_float_data_vector_ptr_based_post_fi } /* Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer_with_uchar8_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, - std::unique_ptr in_data_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_with_uchar8_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, + std::unique_ptr in_data_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -578,7 +578,7 @@ bool Anvil::MemoryAllocator::add_buffer_with_uchar8_data_ptr_based_post_fill(Anv bool Anvil::MemoryAllocator::add_buffer_with_uchar8_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -606,10 +606,10 @@ bool Anvil::MemoryAllocator::add_buffer_with_uchar8_data_vector_ptr_based_post_f } /* Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, - std::unique_ptr in_data_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, + std::unique_ptr in_data_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -638,7 +638,7 @@ bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_ptr_based_post_fill(Anv bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, std::unique_ptr > in_data_vector_ptr, MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -666,10 +666,10 @@ bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_vector_ptr_based_post_f } /** Please see header for specification */ -bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, - const std::vector* in_data_vector_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_vector_ptr_based_post_fill(Anvil::Buffer* in_buffer_ptr, + const std::vector* in_data_vector_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { std::unique_lock mutex_lock; auto mutex_ptr = get_mutex(); @@ -702,9 +702,9 @@ bool Anvil::MemoryAllocator::add_buffer_with_uint32_data_vector_ptr_based_post_f } /** Please see header for specification */ -bool Anvil::MemoryAllocator::add_image_whole(Anvil::Image* in_image_ptr, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_image_whole(Anvil::Image* in_image_ptr, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { uint32_t filtered_memory_types = 0; VkDeviceSize image_alignment = 0; @@ -776,11 +776,11 @@ bool Anvil::MemoryAllocator::add_image_whole(Anvil::Image* } /** Please see header for specification */ -bool Anvil::MemoryAllocator::add_sparse_buffer_region(Anvil::Buffer* in_buffer_ptr, - VkDeviceSize in_offset, - VkDeviceSize in_size, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_sparse_buffer_region(Anvil::Buffer* in_buffer_ptr, + VkDeviceSize in_offset, + VkDeviceSize in_size, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { uint32_t filtered_memory_types = 0; const auto& memory_reqs = in_buffer_ptr->get_memory_requirements(); @@ -854,11 +854,11 @@ bool Anvil::MemoryAllocator::add_sparse_buffer_region(Anvil::Buffer* } /** Please see header for specification */ -bool Anvil::MemoryAllocator::add_sparse_image_miptail(Anvil::Image* in_image_ptr, - VkImageAspectFlagBits in_aspect, - uint32_t in_n_layer, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_sparse_image_miptail(Anvil::Image* in_image_ptr, + VkImageAspectFlagBits in_aspect, + uint32_t in_n_layer, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { const Anvil::SparseImageAspectProperties* aspect_props_ptr = nullptr; uint32_t filtered_memory_types = 0; @@ -950,12 +950,12 @@ bool Anvil::MemoryAllocator::add_sparse_image_miptail(Anvil::Image* } /* Please see header for specification */ -bool Anvil::MemoryAllocator::add_sparse_image_subresource(Anvil::Image* in_image_ptr, - const VkImageSubresource& in_subresource, - const VkOffset3D& in_offset, - VkExtent3D in_extent, - MemoryFeatureFlags in_required_memory_features, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +bool Anvil::MemoryAllocator::add_sparse_image_subresource(Anvil::Image* in_image_ptr, + const VkImageSubresource& in_subresource, + const VkOffset3D& in_offset, + VkExtent3D in_extent, + MemoryFeatureFlags in_required_memory_features, + Anvil::ExternalMemoryHandleTypeBits in_external_memory_handle_types) { const Anvil::SparseImageAspectProperties* aspect_props_ptr = nullptr; uint32_t component_size_bits[4] = {0}; @@ -1535,19 +1535,12 @@ Anvil::MemoryAllocatorUniquePtr Anvil::MemoryAllocator::create_vma(const Anvil:: return std::move(result_ptr); } -bool Anvil::MemoryAllocator::do_external_memory_handle_type_sanity_checks(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const +bool Anvil::MemoryAllocator::do_external_memory_handle_type_sanity_checks(const Anvil::ExternalMemoryHandleTypeBits& in_external_memory_handle_types) const { bool result = true; if (in_external_memory_handle_types != 0) { - if (!m_device_ptr->supports_external_memory_handles(in_external_memory_handle_types) ) - { - anvil_assert(!m_device_ptr->supports_external_memory_handles(in_external_memory_handle_types) ); - - result = false; - } - else if (!m_backend_ptr->supports_external_memory_handles(in_external_memory_handle_types) ) { anvil_assert(m_backend_ptr->supports_external_memory_handles(in_external_memory_handle_types) ); diff --git a/src/misc/memory_block_create_info.cpp b/src/misc/memory_block_create_info.cpp new file mode 100644 index 00000000..60f4be5a --- /dev/null +++ b/src/misc/memory_block_create_info.cpp @@ -0,0 +1,184 @@ +// +// Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#include "misc/memory_block_create_info.h" +#include "wrappers/device.h" +#include "wrappers/memory_block.h" + + +Anvil::MemoryBlockCreateInfoUniquePtr Anvil::MemoryBlockCreateInfo::create_derived(MemoryBlock* in_parent_memory_block_ptr, + VkDeviceSize in_start_offset, + VkDeviceSize in_size) +{ + const uint32_t n_physical_devices = static_cast(in_parent_memory_block_ptr->get_create_info_ptr()->m_physical_devices.size() ); + auto result_ptr = Anvil::MemoryBlockCreateInfoUniquePtr(nullptr, + std::default_delete() ); + + anvil_assert(in_start_offset + in_size <= in_parent_memory_block_ptr->get_create_info_ptr()->get_start_offset() + in_parent_memory_block_ptr->get_create_info_ptr()->get_size() ); + + result_ptr.reset( + new Anvil::MemoryBlockCreateInfo(Anvil::MemoryBlockType::DERIVED, + in_parent_memory_block_ptr->get_create_info_ptr()->m_allowed_memory_bits, + const_cast(in_parent_memory_block_ptr->get_create_info_ptr()->m_device_ptr), + VK_NULL_HANDLE, /* in_memory */ + in_parent_memory_block_ptr->get_create_info_ptr()->m_memory_features, + UINT32_MAX, /* in_memory_type_index */ + n_physical_devices, + Anvil::OnMemoryBlockReleaseCallbackFunction(), + (n_physical_devices != 0) ? &in_parent_memory_block_ptr->get_create_info_ptr()->m_physical_devices.at(0) + : nullptr, + in_parent_memory_block_ptr, + in_size, + in_start_offset) + ); + + return result_ptr; +} + +Anvil::MemoryBlockCreateInfoUniquePtr Anvil::MemoryBlockCreateInfo::create_derived_with_custom_delete_proc(const Anvil::BaseDevice* in_device_ptr, + VkDeviceMemory in_memory, + uint32_t in_allowed_memory_bits, + Anvil::MemoryFeatureFlags in_memory_features, + uint32_t in_memory_type_index, + VkDeviceSize in_size, + VkDeviceSize in_start_offset, + Anvil::OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function) +{ + auto result_ptr = Anvil::MemoryBlockCreateInfoUniquePtr(nullptr, + std::default_delete() ); + + anvil_assert(in_device_ptr->get_type() == Anvil::DEVICE_TYPE_SINGLE_GPU); /* todo: pass physical device array below accordingly */ + + result_ptr.reset( + new Anvil::MemoryBlockCreateInfo(Anvil::MemoryBlockType::DERIVED_WITH_CUSTOM_DELETE_PROC, + in_allowed_memory_bits, + in_device_ptr, + in_memory, + in_memory_features, + in_memory_type_index, + 0, /* in_n_physical_devices */ + in_on_release_callback_function, + nullptr, /* in_physical_device_ptr_ptr */ + nullptr, /* in_parent_memory_block_ptr */ + in_size, + in_start_offset) + ); + + return result_ptr; +} + +Anvil::MemoryBlockCreateInfoUniquePtr Anvil::MemoryBlockCreateInfo::create_regular(const Anvil::BaseDevice* in_device_ptr, + uint32_t in_allowed_memory_bits, + VkDeviceSize in_size, + Anvil::MemoryFeatureFlags in_memory_features) +{ + auto result_ptr = Anvil::MemoryBlockCreateInfoUniquePtr(nullptr, + std::default_delete() ); + + anvil_assert(in_device_ptr->get_type() == Anvil::DEVICE_TYPE_SINGLE_GPU); /* todo: pass physical device array below accordingly */ + + result_ptr.reset( + new Anvil::MemoryBlockCreateInfo(Anvil::MemoryBlockType::REGULAR, + in_allowed_memory_bits, + in_device_ptr, + VK_NULL_HANDLE, /* in_memory */ + in_memory_features, + 0, /* in_memory_type_index */ + 0, /* in_n_physical_devices */ + OnMemoryBlockReleaseCallbackFunction(), + nullptr, /* in_physical_device_ptr_ptr */ + nullptr, /* in_parent_memory_block_ptr */ + in_size, + 0) /* in_start_offset */ + ); + + return result_ptr; +} + +Anvil::MemoryBlockCreateInfo::MemoryBlockCreateInfo(const Anvil::MemoryBlockType& in_type, + const uint32_t& in_allowed_memory_bits, + const Anvil::BaseDevice* in_device_ptr, + VkDeviceMemory in_memory, + const Anvil::MemoryFeatureFlags& in_memory_features, + const uint32_t& in_memory_type_index, + const uint32_t& in_n_physical_devices, + const Anvil::OnMemoryBlockReleaseCallbackFunction& in_on_release_callback_function, + const Anvil::PhysicalDevice* const* in_opt_physical_device_ptr_ptr, + Anvil::MemoryBlock* in_parent_memory_block_ptr, + const VkDeviceSize& in_size, + const VkDeviceSize& in_start_offset) + :m_allowed_memory_bits (in_allowed_memory_bits), + m_device_ptr (in_device_ptr), + m_exportable_external_memory_handle_types (Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE), + m_external_handle_import_info_specified (false), +#ifdef _WIN32 + m_external_nt_handle_import_info_specified(false), +#endif + m_imported_external_memory_handle_type (Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE), + m_memory (in_memory), + m_memory_features (in_memory_features), + m_memory_type_index (in_memory_type_index), + m_mt_safety (Anvil::MT_SAFETY_INHERIT_FROM_PARENT_DEVICE), + m_on_release_callback_function (in_on_release_callback_function), + m_parent_memory_block_ptr (in_parent_memory_block_ptr), + m_size (in_size), + m_start_offset (in_start_offset), + m_type (in_type) +{ + if (in_n_physical_devices != 0) + { + anvil_assert(in_opt_physical_device_ptr_ptr != nullptr); + + m_physical_devices.resize(in_n_physical_devices); + + for (uint32_t n_physical_device = 0; + n_physical_device < in_n_physical_devices; + ++n_physical_device) + { + m_physical_devices.at(n_physical_device) = in_opt_physical_device_ptr_ptr[n_physical_device]; + } + } +} + +Anvil::MemoryFeatureFlags Anvil::MemoryBlockCreateInfo::get_memory_features() const +{ + if (m_parent_memory_block_ptr != nullptr) + { + return m_parent_memory_block_ptr->get_create_info_ptr()->get_memory_features(); + } + else + { + return m_memory_features; + } +} + +/** Returns the memory type index the memory block was allocated from */ +uint32_t Anvil::MemoryBlockCreateInfo::get_memory_type_index() const +{ + if (m_parent_memory_block_ptr != nullptr) + { + return m_parent_memory_block_ptr->get_create_info_ptr()->get_memory_type_index(); + } + else + { + return m_memory_type_index; + } +} diff --git a/src/misc/semaphore_create_info.cpp b/src/misc/semaphore_create_info.cpp index 925a49c6..745d0732 100644 --- a/src/misc/semaphore_create_info.cpp +++ b/src/misc/semaphore_create_info.cpp @@ -21,15 +21,14 @@ // #include "misc/semaphore_create_info.h" -Anvil::SemaphoreCreateInfoUniquePtr Anvil::SemaphoreCreateInfo::create(const Anvil::BaseDevice* in_device_ptr, - MTSafety in_mt_safety) +Anvil::SemaphoreCreateInfoUniquePtr Anvil::SemaphoreCreateInfo::create(const Anvil::BaseDevice* in_device_ptr) { Anvil::SemaphoreCreateInfoUniquePtr result_ptr(nullptr, std::default_delete() ); result_ptr.reset( new Anvil::SemaphoreCreateInfo(in_device_ptr, - in_mt_safety) + Anvil::MT_SAFETY_INHERIT_FROM_PARENT_DEVICE) ); return result_ptr; @@ -37,8 +36,9 @@ Anvil::SemaphoreCreateInfoUniquePtr Anvil::SemaphoreCreateInfo::create(const Anv Anvil::SemaphoreCreateInfo::SemaphoreCreateInfo(const Anvil::BaseDevice* in_device_ptr, MTSafety in_mt_safety) - :m_device_ptr(in_device_ptr), - m_mt_safety (in_mt_safety) + :m_device_ptr (in_device_ptr), + m_exportable_external_semaphore_handle_types(Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE), + m_mt_safety (in_mt_safety) { /* Stub */ } \ No newline at end of file diff --git a/src/misc/types_classes.cpp b/src/misc/types_classes.cpp index 49f5f8e2..dd0358c3 100644 --- a/src/misc/types_classes.cpp +++ b/src/misc/types_classes.cpp @@ -71,7 +71,7 @@ void Anvil::SparseMemoryBindingUpdateInfo::append_buffer_memory_update(SparseMem if (in_memory_block_ptr != nullptr) { - anvil_assert(in_memory_block_ptr->get_size() >= in_memory_block_start_offset + in_size); + anvil_assert(in_memory_block_ptr->get_create_info_ptr()->get_size() >= in_memory_block_start_offset + in_size); } /* Cache the update */ @@ -119,7 +119,7 @@ void Anvil::SparseMemoryBindingUpdateInfo::append_image_memory_update(SparseMemo if (in_opt_memory_block_ptr != nullptr) { - anvil_assert(in_opt_memory_block_ptr->get_size() > in_opt_memory_block_start_offset); + anvil_assert(in_opt_memory_block_ptr->get_create_info_ptr()->get_size() > in_opt_memory_block_start_offset); } /* Cache the update */ @@ -165,7 +165,7 @@ void Anvil::SparseMemoryBindingUpdateInfo::append_opaque_image_memory_update(Spa if (in_opt_memory_block_ptr != nullptr) { - anvil_assert(in_opt_memory_block_ptr->get_size() >= in_opt_memory_block_start_offset + in_size); + anvil_assert(in_opt_memory_block_ptr->get_create_info_ptr()->get_size() >= in_opt_memory_block_start_offset + in_size); } /* Cache the update */ diff --git a/src/misc/types_struct.cpp b/src/misc/types_struct.cpp index 4cb60cab..c0eb3861 100644 --- a/src/misc/types_struct.cpp +++ b/src/misc/types_struct.cpp @@ -132,11 +132,15 @@ Anvil::BufferBarrier::~BufferBarrier() /* Stub */ } -Anvil::BufferMemoryBindingUpdate::BufferMemoryBindingUpdate() +Anvil::BufferFormatProperties::BufferFormatProperties() { - buffer_ptr = nullptr; - memory_block_owned_by_buffer = false; - memory_block_ptr = nullptr; + /* Stub */ +} + +Anvil::BufferFormatProperties::BufferFormatProperties(const ExternalMemoryProperties& in_external_handle_properties) + :external_handle_properties (in_external_handle_properties) +{ + /* Stub */ } Anvil::DescriptorSetAllocation::DescriptorSetAllocation(const Anvil::DescriptorSetLayout* in_ds_layout_ptr) @@ -330,6 +334,59 @@ Anvil::ExtensionKHRDeviceGroupCreationEntrypoints::ExtensionKHRDeviceGroupCreati vkEnumeratePhysicalDeviceGroupsKHR = nullptr; } +Anvil::ExtensionKHRExternalFenceCapabilitiesEntrypoints::ExtensionKHRExternalFenceCapabilitiesEntrypoints() +{ + vkGetPhysicalDeviceExternalFencePropertiesKHR = nullptr; +} + +Anvil::ExtensionKHRExternalMemoryCapabilitiesEntrypoints::ExtensionKHRExternalMemoryCapabilitiesEntrypoints() +{ + vkGetPhysicalDeviceExternalBufferPropertiesKHR = nullptr; +} + +Anvil::ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints::ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints() +{ + vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr; +} + +#ifdef _WIN32 + Anvil::ExtensionKHRExternalFenceWin32Entrypoints::ExtensionKHRExternalFenceWin32Entrypoints() + { + vkGetFenceWin32HandleKHR = nullptr; + vkImportFenceWin32HandleKHR = nullptr; + } + + Anvil::ExtensionKHRExternalMemoryWin32Entrypoints::ExtensionKHRExternalMemoryWin32Entrypoints() + { + vkGetMemoryWin32HandleKHR = nullptr; + vkGetMemoryWin32HandlePropertiesKHR = nullptr; + } + + Anvil::ExtensionKHRExternalSemaphoreWin32Entrypoints::ExtensionKHRExternalSemaphoreWin32Entrypoints() + { + vkGetSemaphoreWin32HandleKHR = nullptr; + vkImportSemaphoreWin32HandleKHR = nullptr; + } +#else + Anvil::ExtensionKHRExternalFenceFdEntrypoints::ExtensionKHRExternalFenceFdEntrypoints() + { + vkGetFenceFdKHR = nullptr; + vkImportFenceFdKHR = nullptr; + } + + Anvil::ExtensionKHRExternalMemoryFdEntrypoints::ExtensionKHRExternalMemoryFdEntrypoints() + { + vkGetMemoryFdKHR = nullptr; + vkGetMemoryFdPropertiesKHR = nullptr; + } + + Anvil::ExtensionKHRExternalSemaphoreFdEntrypoints::ExtensionKHRExternalSemaphoreFdEntrypoints() + { + vkGetSemaphoreFdKHR = nullptr; + vkImportSemaphoreFdKHR = nullptr; + } +#endif + Anvil::ExtensionKHRMaintenance1Entrypoints::ExtensionKHRMaintenance1Entrypoints() { vkTrimCommandPoolKHR = nullptr; @@ -567,6 +624,65 @@ bool Anvil::EXTDescriptorIndexingProperties::operator==(const EXTDescriptorIndex shader_uniform_buffer_array_non_uniform_indexing_native == in_props.shader_uniform_buffer_array_non_uniform_indexing_native); } +Anvil::ExternalFenceProperties::ExternalFenceProperties() +{ + compatible_external_handle_types = 0; + export_from_imported_external_handle_types = 0; + is_exportable = false; + is_importable = false; +} + +Anvil::ExternalFenceProperties::ExternalFenceProperties(const VkExternalFencePropertiesKHR& in_external_fence_props) +{ + compatible_external_handle_types = Anvil::Utils::convert_vk_external_fence_handle_type_flags_to_external_fence_handle_type_bits(in_external_fence_props.compatibleHandleTypes); + export_from_imported_external_handle_types = Anvil::Utils::convert_vk_external_fence_handle_type_flags_to_external_fence_handle_type_bits(in_external_fence_props.exportFromImportedHandleTypes); + is_exportable = (in_external_fence_props.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR) != 0; + is_importable = (in_external_fence_props.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR) != 0; +} + +Anvil::ExternalMemoryProperties::ExternalMemoryProperties() +{ + compatible_external_handle_types = 0; + export_from_imported_external_handle_types = 0; + is_exportable = false; + is_importable = false; +} + +Anvil::ExternalMemoryProperties::ExternalMemoryProperties(const VkExternalMemoryPropertiesKHR& in_external_memory_props) +{ + compatible_external_handle_types = Anvil::Utils::convert_vk_external_memory_handle_type_flags_to_external_memory_handle_type_bits(in_external_memory_props.compatibleHandleTypes); + export_from_imported_external_handle_types = Anvil::Utils::convert_vk_external_memory_handle_type_flags_to_external_memory_handle_type_bits(in_external_memory_props.exportFromImportedHandleTypes); + is_exportable = (in_external_memory_props.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) != 0; + is_importable = (in_external_memory_props.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0; +} + +Anvil::ExternalSemaphoreProperties::ExternalSemaphoreProperties() +{ + compatible_external_handle_types = 0; + export_from_imported_external_handle_types = 0; + is_exportable = false; + is_importable = false; +} + +Anvil::ExternalSemaphoreProperties::ExternalSemaphoreProperties(const VkExternalSemaphorePropertiesKHR& in_external_semaphore_props) +{ + compatible_external_handle_types = Anvil::Utils::convert_vk_external_semaphore_handle_type_flags_to_external_semaphore_handle_type_bits(in_external_semaphore_props.compatibleHandleTypes); + export_from_imported_external_handle_types = Anvil::Utils::convert_vk_external_semaphore_handle_type_flags_to_external_semaphore_handle_type_bits(in_external_semaphore_props.exportFromImportedHandleTypes); + is_exportable = (in_external_semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) != 0; + is_importable = (in_external_semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) != 0; +} + +Anvil::FenceProperties::FenceProperties() +{ + /* Stub */ +} + +Anvil::FenceProperties::FenceProperties(const ExternalFenceProperties& in_external_fence_properties) + :external_fence_properties(in_external_fence_properties) +{ + /* Stub */ +} + Anvil::FormatProperties::FormatProperties() { memset(this, @@ -576,19 +692,29 @@ Anvil::FormatProperties::FormatProperties() Anvil::FormatProperties::FormatProperties(const VkFormatProperties& in_format_props) { - buffer_capabilities = in_format_props.bufferFeatures; - linear_tiling_capabilities = in_format_props.linearTilingFeatures; - optimal_tiling_capabilities = in_format_props.optimalTilingFeatures; - supports_amd_texture_gather_bias_lod = false; + buffer_capabilities = in_format_props.bufferFeatures; + linear_tiling_capabilities = in_format_props.linearTilingFeatures; + optimal_tiling_capabilities = in_format_props.optimalTilingFeatures; } -/** Please see header for specification */ -bool Anvil::operator==(const Anvil::FormatProperties& in1, - const Anvil::FormatProperties& in2) +Anvil::ImageFormatProperties::ImageFormatProperties() +{ + memset(this, + 0, + sizeof(*this) ); +} + +Anvil::ImageFormatProperties::ImageFormatProperties(const VkImageFormatProperties& in_image_format_props, + const bool& in_supports_amd_texture_gather_bias_lod, + const ExternalMemoryProperties& in_external_handle_properties) { - return memcmp(&in1, - &in2, - sizeof(Anvil::FormatProperties) ) == 0; + external_handle_properties = in_external_handle_properties; + max_extent = in_image_format_props.maxExtent; + max_resource_size = in_image_format_props.maxResourceSize; + n_max_array_layers = in_image_format_props.maxArrayLayers; + n_max_mip_levels = in_image_format_props.maxMipLevels; + sample_counts = in_image_format_props.sampleCounts; + supports_amd_texture_gather_bias_lod = in_supports_amd_texture_gather_bias_lod; } /** Please see header for specification */ @@ -1404,14 +1530,16 @@ Anvil::PhysicalDeviceProperties::PhysicalDeviceProperties() khr_maintenance3_properties_ptr = nullptr; } -Anvil::PhysicalDeviceProperties::PhysicalDeviceProperties(const AMDShaderCoreProperties* in_amd_shader_core_properties_ptr, - const PhysicalDevicePropertiesCoreVK10* in_core_vk1_0_properties_ptr, - const EXTDescriptorIndexingProperties* in_ext_descriptor_indexing_properties_ptr, - const KHRMaintenance3Properties* in_khr_maintenance3_properties_ptr) - :amd_shader_core_properties_ptr (in_amd_shader_core_properties_ptr), - core_vk1_0_properties_ptr (in_core_vk1_0_properties_ptr), - ext_descriptor_indexing_properties_ptr(in_ext_descriptor_indexing_properties_ptr), - khr_maintenance3_properties_ptr (in_khr_maintenance3_properties_ptr) +Anvil::PhysicalDeviceProperties::PhysicalDeviceProperties(const AMDShaderCoreProperties* in_amd_shader_core_properties_ptr, + const PhysicalDevicePropertiesCoreVK10* in_core_vk1_0_properties_ptr, + const EXTDescriptorIndexingProperties* in_ext_descriptor_indexing_properties_ptr, + const Anvil::KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties* in_khr_external_memory_caps_physical_device_id_props_ptr, + const KHRMaintenance3Properties* in_khr_maintenance3_properties_ptr) + :amd_shader_core_properties_ptr (in_amd_shader_core_properties_ptr), + core_vk1_0_properties_ptr (in_core_vk1_0_properties_ptr), + ext_descriptor_indexing_properties_ptr (in_ext_descriptor_indexing_properties_ptr), + khr_external_memory_capabilities_physical_device_id_properties_ptr(in_khr_external_memory_caps_physical_device_id_props_ptr), + khr_maintenance3_properties_ptr (in_khr_maintenance3_properties_ptr) { /* Stub */ } @@ -1830,6 +1958,40 @@ bool Anvil::PhysicalDeviceLimits::operator==(const Anvil::PhysicalDeviceLimits& return result; } +Anvil::KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties::KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties() +{ + device_luid_valid = false; + device_node_mask = 0; + + memset(device_luid, + 0, + VK_LUID_SIZE); + memset(device_uuid, + 0, + VK_UUID_SIZE); + memset(driver_uuid, + 0, + VK_UUID_SIZE); +} + +Anvil::KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties::KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties(const VkPhysicalDeviceIDPropertiesKHR& in_properties) +{ + anvil_assert(in_properties.pNext == nullptr); + + device_luid_valid = VK_BOOL32_TO_BOOL(in_properties.deviceLUIDValid); + device_node_mask = in_properties.deviceNodeMask; + + memcpy(device_luid, + in_properties.deviceLUID, + VK_LUID_SIZE); + memcpy(device_uuid, + in_properties.deviceUUID, + VK_UUID_SIZE); + memcpy(driver_uuid, + in_properties.driverUUID, + VK_UUID_SIZE); +} + Anvil::PhysicalDevicePropertiesCoreVK10::PhysicalDevicePropertiesCoreVK10(const VkPhysicalDeviceProperties& in_physical_device_properties) :api_version (in_physical_device_properties.apiVersion), device_id (in_physical_device_properties.deviceID), @@ -1938,6 +2100,19 @@ bool Anvil::operator==(const Anvil::QueueFamilyInfo& in1, in1.n_timestamp_bits == in2.n_timestamp_bits); } +/** Please see header for specification */ +Anvil::SemaphoreProperties::SemaphoreProperties() +{ + /* Stub */ +} + +/** Please see header for specification */ +Anvil::SemaphoreProperties::SemaphoreProperties(const ExternalSemaphoreProperties& in_external_semaphore_properties) + :external_semaphore_properties(in_external_semaphore_properties) +{ + /* Stub */ +} + /** Please see header for specification */ Anvil::ShaderModuleStageEntryPoint::ShaderModuleStageEntryPoint() { @@ -2082,7 +2257,7 @@ Anvil::PhysicalDeviceFeaturesCoreVK10::PhysicalDeviceFeaturesCoreVK10() independent_blend (false), inherited_queries (false), large_points (false), - logic_ip (false), + logic_op (false), multi_draw_indirect (false), multi_viewport (false), occlusion_query_precise (false), @@ -2142,7 +2317,7 @@ Anvil::PhysicalDeviceFeaturesCoreVK10::PhysicalDeviceFeaturesCoreVK10(const VkPh independent_blend (VK_BOOL32_TO_BOOL(in_physical_device_features.independentBlend) ), inherited_queries (VK_BOOL32_TO_BOOL(in_physical_device_features.inheritedQueries) ), large_points (VK_BOOL32_TO_BOOL(in_physical_device_features.largePoints) ), - logic_ip (VK_BOOL32_TO_BOOL(in_physical_device_features.logicOp) ), + logic_op (VK_BOOL32_TO_BOOL(in_physical_device_features.logicOp) ), multi_draw_indirect (VK_BOOL32_TO_BOOL(in_physical_device_features.multiDrawIndirect) ), multi_viewport (VK_BOOL32_TO_BOOL(in_physical_device_features.multiViewport) ), occlusion_query_precise (VK_BOOL32_TO_BOOL(in_physical_device_features.occlusionQueryPrecise) ), @@ -2205,7 +2380,7 @@ VkPhysicalDeviceFeatures Anvil::PhysicalDeviceFeaturesCoreVK10::get_vk_physical_ result.independentBlend = BOOL_TO_VK_BOOL32(independent_blend); result.inheritedQueries = BOOL_TO_VK_BOOL32(inherited_queries); result.largePoints = BOOL_TO_VK_BOOL32(large_points); - result.logicOp = BOOL_TO_VK_BOOL32(logic_ip); + result.logicOp = BOOL_TO_VK_BOOL32(logic_op); result.multiDrawIndirect = BOOL_TO_VK_BOOL32(multi_draw_indirect); result.multiViewport = BOOL_TO_VK_BOOL32(multi_viewport); result.occlusionQueryPrecise = BOOL_TO_VK_BOOL32(occlusion_query_precise); @@ -2266,7 +2441,7 @@ bool Anvil::PhysicalDeviceFeaturesCoreVK10::operator==(const Anvil::PhysicalDevi (independent_blend == in_data.independent_blend) && (inherited_queries == in_data.inherited_queries) && (large_points == in_data.large_points) && - (logic_ip == in_data.logic_ip) && + (logic_op == in_data.logic_op) && (multi_draw_indirect == in_data.multi_draw_indirect) && (multi_viewport == in_data.multi_viewport) && (occlusion_query_precise == in_data.occlusion_query_precise) && @@ -2354,3 +2529,343 @@ bool Anvil::PhysicalDeviceProperties::operator==(const PhysicalDeviceProperties& ext_descriptor_indexing_properties_match && khr_maintenance3_properties_match; } + +Anvil::SubmitInfo::SubmitInfo(uint32_t in_n_command_buffers, + Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) + :command_buffers_sgpu_ptr (in_opt_cmd_buffer_ptrs_ptr), +#if defined(_WIN32) + d3d12_fence_signal_semaphore_values_ptr(nullptr), + d3d12_fence_wait_semaphore_values_ptr (nullptr), +#endif + dst_stage_wait_masks_ptr (in_opt_dst_stage_masks_to_wait_on_ptrs), + fence_ptr (in_opt_fence_ptr), + n_command_buffers (in_n_command_buffers), + n_signal_semaphores (in_n_semaphores_to_signal), + n_wait_semaphores (in_n_semaphores_to_wait_on), + signal_semaphores_sgpu_ptr (in_opt_semaphore_to_signal_ptrs_ptr), + should_block (in_should_block), + type (SubmissionType::SGPU), + wait_semaphores_sgpu_ptr (in_opt_semaphore_to_wait_on_ptrs_ptr) +{ + anvil_assert((in_n_command_buffers == 0) || + (in_n_command_buffers != 0 && in_opt_cmd_buffer_ptrs_ptr != nullptr) ); + + anvil_assert((in_n_semaphores_to_signal == 0) || + (in_n_semaphores_to_signal != 0 && in_opt_semaphore_to_signal_ptrs_ptr != nullptr) ); + + anvil_assert((in_n_semaphores_to_wait_on == 0) || + (in_n_semaphores_to_wait_on != 0 && in_opt_semaphore_to_wait_on_ptrs_ptr != nullptr && in_opt_dst_stage_masks_to_wait_on_ptrs != nullptr) ); +} + +Anvil::SubmitInfo::SubmitInfo(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) + :command_buffers_sgpu_ptr (nullptr), +#if defined(_WIN32) + d3d12_fence_signal_semaphore_values_ptr(nullptr), + d3d12_fence_wait_semaphore_values_ptr (nullptr), +#endif + dst_stage_wait_masks_ptr (in_opt_dst_stage_masks_to_wait_on_ptrs), + fence_ptr (in_opt_fence_ptr), + n_command_buffers ((in_cmd_buffer_ptr != nullptr) ? 1 : 0), + n_signal_semaphores (in_n_semaphores_to_signal), + n_wait_semaphores (in_n_semaphores_to_wait_on), + signal_semaphores_sgpu_ptr (in_opt_semaphore_to_signal_ptrs_ptr), + should_block (in_should_block), + type (SubmissionType::SGPU), + wait_semaphores_sgpu_ptr (in_opt_semaphore_to_wait_on_ptrs_ptr) +{ + anvil_assert((in_n_semaphores_to_signal == 0) || + (in_n_semaphores_to_signal != 0 && in_opt_semaphore_to_signal_ptrs_ptr != nullptr) ); + + anvil_assert((in_n_semaphores_to_wait_on == 0) || + (in_n_semaphores_to_wait_on != 0 && in_opt_semaphore_to_wait_on_ptrs_ptr != nullptr && in_opt_dst_stage_masks_to_wait_on_ptrs != nullptr) ); + + helper_cmd_buffer_raw_ptr = in_cmd_buffer_ptr; + command_buffers_sgpu_ptr = &helper_cmd_buffer_raw_ptr; +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create(Anvil::CommandBufferBase* in_opt_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + return Anvil::SubmitInfo(in_opt_cmd_buffer_ptr, + in_n_semaphores_to_signal, + in_opt_semaphore_to_signal_ptrs_ptr, + in_n_semaphores_to_wait_on, + in_opt_semaphore_to_wait_on_ptrs_ptr, + in_opt_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create(uint32_t in_n_cmd_buffers, + Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + return Anvil::SubmitInfo(in_n_cmd_buffers, + in_opt_cmd_buffer_ptrs_ptr, + in_n_semaphores_to_signal, + in_opt_semaphore_to_signal_ptrs_ptr, + in_n_semaphores_to_wait_on, + in_opt_semaphore_to_wait_on_ptrs_ptr, + in_opt_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_execute(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptr != nullptr); + + return Anvil::SubmitInfo(in_cmd_buffer_ptr, + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_opt_semaphore_to_signal_ptrs_ptr */ + 0, /* in_n_semaphores_to_wait_on */ + nullptr, /* in_opt_semaphore_to_wait_on_ptrs_ptr */ + nullptr, /* in_opt_dst_stage_masks_to_wait_on_ptrs */ + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_execute(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptrs_ptr != nullptr); + anvil_assert(in_n_cmd_buffers > 0); + + return Anvil::SubmitInfo(in_n_cmd_buffers, + in_cmd_buffer_ptrs_ptr, + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_opt_semaphore_to_signal_ptrs_ptr */ + 0, /* in_n_semaphores_to_wait_on */ + nullptr, /* in_opt_semaphore_to_wait_on_ptrs_ptr */ + nullptr, /* in_opt_dst_stage_masks_to_wait_on_ptrs */ + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_execute_signal(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptr != nullptr); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_cmd_buffer_ptr, + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + 0, /* in_n_semaphores_to_wait_on */ + nullptr, /* in_opt_semaphore_to_wait_on_ptrs_ptr */ + nullptr, /* in_opt_dst_stage_masks_to_wait_on_ptrs */ + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_execute_signal(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptrs_ptr != nullptr); + anvil_assert(in_n_cmd_buffers > 0); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_n_cmd_buffers, + in_cmd_buffer_ptrs_ptr, + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + 0, /* in_n_semaphores_to_wait_on */ + nullptr, /* in_opt_semaphore_to_wait_on_ptrs_ptr */ + nullptr, /* in_opt_dst_stage_masks_to_wait_on_ptrs */ + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_signal(uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_n_semaphores_to_signal > 0); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(0, /* in_n_command_buffers */ + nullptr, /* in_cmd_buffer_ptr */ + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + 0, /* in_n_semaphores_to_wait_on */ + nullptr, /* in_semaphore_to_wait_on_ptrs_ptr */ + nullptr, /* in_dst_stage_masks_to_wait_on_ptrs */ + true, /* in_should_block */ + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_signal_wait(uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_n_semaphores_to_signal > 0); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + anvil_assert(in_n_semaphores_to_wait_on > 0); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(0, /* in_n_command_buffers */ + nullptr, /* in_cmd_buffer_ptr */ + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_wait(uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_dst_stage_masks_to_wait_on_ptrs != nullptr); + anvil_assert(in_n_semaphores_to_wait_on > 0); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(0, /* in_n_command_buffers */ + nullptr, /* in_cmd_buffer_ptr */ + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_semaphore_to_signal_ptrs_ptr */ + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + true, /* in_should_block */ + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_wait_execute(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptr != nullptr); + anvil_assert(in_dst_stage_masks_to_wait_on_ptrs != nullptr); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_cmd_buffer_ptr, + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_opt_semaphore_to_signal_ptrs_ptr */ + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_wait_execute(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptrs_ptr != nullptr); + anvil_assert(in_n_cmd_buffers > 0); + anvil_assert(in_dst_stage_masks_to_wait_on_ptrs != nullptr); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_n_cmd_buffers, + in_cmd_buffer_ptrs_ptr, + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_opt_semaphore_to_signal_ptrs_ptr */ + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_wait_execute_signal(Anvil::CommandBufferBase* in_cmd_buffer_ptr, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptr != nullptr); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_cmd_buffer_ptr, + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + +Anvil::SubmitInfo Anvil::SubmitInfo::create_wait_execute_signal(Anvil::CommandBufferBase* const* in_cmd_buffer_ptrs_ptr, + uint32_t in_n_cmd_buffers, + uint32_t in_n_semaphores_to_signal, + Anvil::Semaphore* const* in_semaphore_to_signal_ptrs_ptr, + uint32_t in_n_semaphores_to_wait_on, + Anvil::Semaphore* const* in_semaphore_to_wait_on_ptrs_ptr, + const VkPipelineStageFlags* in_dst_stage_masks_to_wait_on_ptrs, + bool in_should_block, + Anvil::Fence* in_opt_fence_ptr) +{ + anvil_assert(in_cmd_buffer_ptrs_ptr != nullptr); + anvil_assert(in_n_cmd_buffers > 0); + anvil_assert(in_semaphore_to_signal_ptrs_ptr != nullptr); + anvil_assert(in_semaphore_to_wait_on_ptrs_ptr != nullptr); + + return Anvil::SubmitInfo(in_n_cmd_buffers, + in_cmd_buffer_ptrs_ptr, + in_n_semaphores_to_signal, + in_semaphore_to_signal_ptrs_ptr, + in_n_semaphores_to_wait_on, + in_semaphore_to_wait_on_ptrs_ptr, + in_dst_stage_masks_to_wait_on_ptrs, + in_should_block, + in_opt_fence_ptr); +} + diff --git a/src/misc/types_utils.cpp b/src/misc/types_utils.cpp index 1c9a5b62..412c85fe 100644 --- a/src/misc/types_utils.cpp +++ b/src/misc/types_utils.cpp @@ -64,12 +64,183 @@ Anvil::MTSafety Anvil::Utils::convert_boolean_to_mt_safety_enum(bool in_mt_safe) : MT_SAFETY_DISABLED; } -VkExternalMemoryHandleTypeFlagsKHR Anvil::Utils::convert_external_memory_handle_types_to_vk_external_memory_handle_type_flags(const Anvil::ExternalMemoryHandleTypeFlags& in_flags) +VkBufferCreateFlags Anvil::Utils::convert_buffer_create_flags_to_vk_buffer_create_flags(const Anvil::BufferCreateFlags& in_create_flags) { - ANVIL_REDUNDANT_ARGUMENT_CONST(in_flags); - anvil_assert (in_flags == 0); + VkBufferCreateFlags result = 0; - return 0; + if (in_create_flags & Anvil::BUFFER_CREATE_FLAG_SPARSE_ALIASED_BIT) + { + result |= VK_BUFFER_CREATE_SPARSE_ALIASED_BIT; + } + + if (in_create_flags & Anvil::BUFFER_CREATE_FLAG_SPARSE_BINDING_BIT) + { + result |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT; + } + + if (in_create_flags & Anvil::BUFFER_CREATE_FLAG_SPARSE_RESIDENCY_BIT) + { + result |= VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT; + } + + return result; +} + +VkExternalFenceHandleTypeFlagsKHR Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(const Anvil::ExternalFenceHandleTypeBits& in_types) +{ + VkExternalFenceHandleTypeFlagsKHR result = 0; + + #if defined(_WIN32) + { + if (in_types & Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT) + { + result |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) + { + result |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR; + } + } + #else + { + if (in_types & Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT) + { + result |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT) + { + result |= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR; + } + } + #endif + + return result; +} + +VkExternalMemoryHandleTypeFlagsKHR Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(const Anvil::ExternalMemoryHandleTypeBits& in_types) +{ + VkExternalMemoryHandleTypeFlagsKHR result = 0; + + #if defined(_WIN32) + { + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR; + } + } + #else + { + if (in_types & Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) + { + result |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + } + } + #endif + + return result; +} + +VkExternalSemaphoreHandleTypeFlagsKHR Anvil::Utils::convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(const Anvil::ExternalSemaphoreHandleTypeBits& in_types) +{ + VkExternalSemaphoreHandleTypeFlagsKHR result = 0; + + #if defined(_WIN32) + { + if (in_types & Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT) + { + result |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) + { + result |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) + { + result |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR; + } + } + #else + { + if (in_types & Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) + { + result |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + } + + if (in_types & Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) + { + result |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR; + } + } + #endif + + return result; +} + +Anvil::ExternalSemaphoreHandleTypeBits Anvil::Utils::convert_vk_external_semaphore_handle_type_flags_to_external_semaphore_handle_type_bits(const VkExternalSemaphoreHandleTypeFlagsKHR& in_types) +{ + Anvil::ExternalSemaphoreHandleTypeBits result = 0; + + #if defined(_WIN32) + { + if (in_types & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR) + { + result |= Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + } + + if (in_types & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR) + { + result |= Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; + } + + if (in_types & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) + { + result |= Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + } + } + #else + { + if (in_types & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) + { + result |= Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; + } + + if (in_types & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR) + { + result |= Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + } + } + #endif + + return result; } bool Anvil::Utils::convert_mt_safety_enum_to_boolean(Anvil::MTSafety in_mt_safety, @@ -856,6 +1027,109 @@ VkShaderStageFlagBits Anvil::Utils::get_shader_stage_flag_bits_from_shader_stage return result; } +Anvil::BufferCreateFlags Anvil::Utils::convert_vk_buffer_create_flags_to_buffer_create_flags(const VkBufferCreateFlags& in_create_flags) +{ + Anvil::BufferCreateFlags result = 0; + + if (in_create_flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) + { + result |= Anvil::BUFFER_CREATE_FLAG_SPARSE_ALIASED_BIT; + } + + if (in_create_flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) + { + result |= Anvil::BUFFER_CREATE_FLAG_SPARSE_BINDING_BIT; + } + + if (in_create_flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) + { + result |= Anvil::BUFFER_CREATE_FLAG_SPARSE_RESIDENCY_BIT; + } + + return result; +} + +Anvil::ExternalFenceHandleTypeBits Anvil::Utils::convert_vk_external_fence_handle_type_flags_to_external_fence_handle_type_bits(const VkExternalFenceHandleTypeFlagsKHR& in_types) +{ + Anvil::ExternalFenceHandleTypeBits result = 0; + + #if defined(_WIN32) + { + if (in_types & VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR) + { + result |= Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT; + } + + if (in_types & VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) + { + result |= Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + } + } + #else + { + if (in_types & VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) + { + result |= Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; + } + + if (in_types & VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) + { + result |= Anvil::EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; + } + } + #endif + + return result; +} + +Anvil::ExternalMemoryHandleTypeBits Anvil::Utils::convert_vk_external_memory_handle_type_flags_to_external_memory_handle_type_bits(const VkExternalMemoryHandleTypeFlagsKHR& in_types) +{ + Anvil::ExternalMemoryHandleTypeBits result = 0; + + #if defined(_WIN32) + { + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; + } + + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + } + + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; + } + + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT; + } + + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT; + } + + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; + } + } + #else + { + if (in_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) + { + result |= Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + } + } + #endif + + return result; +} + /* Please see header for specification */ void Anvil::Utils::get_vk_property_flags_from_memory_feature_flags(Anvil::MemoryFeatureFlags in_mem_feature_flags, VkMemoryPropertyFlags* out_mem_type_flags_ptr, @@ -892,3 +1166,24 @@ void Anvil::Utils::get_vk_property_flags_from_memory_feature_flags(Anvil::Memory *out_mem_heap_flags_ptr = result_mem_heap_flags; *out_mem_type_flags_ptr = result_mem_type_flags; } + +#ifdef _WIN32 + bool Anvil::Utils::is_nt_handle(const Anvil::ExternalFenceHandleTypeBit& in_type) + { + return (in_type == Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT); + } + + bool Anvil::Utils::is_nt_handle(const Anvil::ExternalMemoryHandleTypeBit& in_type) + { + return (in_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT || + in_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT || + in_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT || + in_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT); + } + + bool Anvil::Utils::is_nt_handle(const Anvil::ExternalSemaphoreHandleTypeBit& in_type) + { + return (in_type == Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT || + in_type == Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT); + } +#endif \ No newline at end of file diff --git a/src/wrappers/buffer.cpp b/src/wrappers/buffer.cpp index 1b8c1c83..24e271e0 100644 --- a/src/wrappers/buffer.cpp +++ b/src/wrappers/buffer.cpp @@ -180,24 +180,6 @@ Anvil::BufferUniquePtr Anvil::Buffer::create(Anvil::BufferCreateInfoUniquePtr in return new_buffer_ptr; } -bool Anvil::Buffer::do_external_memory_handle_type_sanity_checks() const -{ - const auto& external_memory_handle_types = m_create_info_ptr->get_external_memory_handle_types(); - bool result = true; - - if (external_memory_handle_types != 0) - { - if (!m_device_ptr->supports_external_memory_handles(external_memory_handle_types) ) - { - anvil_assert(!m_device_ptr->supports_external_memory_handles(external_memory_handle_types) ); - - result = false; - } - } - - return result; -} - /* Please see header for specification */ const Anvil::Buffer* Anvil::Buffer::get_base_buffer() { @@ -307,11 +289,6 @@ bool Anvil::Buffer::init() if (m_create_info_ptr->get_type() != BufferType::NONSPARSE_NO_ALLOC_CHILD) { - if (!do_external_memory_handle_type_sanity_checks() ) - { - goto end; - } - /* Determine which queues the buffer should be available to. */ Anvil::Utils::convert_queue_family_bits_to_family_indices(m_device_ptr, m_create_info_ptr->get_queue_families(), @@ -344,7 +321,7 @@ bool Anvil::Buffer::init() { VkExternalMemoryBufferCreateInfoKHR external_memory_buffer_create_info; - external_memory_buffer_create_info.handleTypes = Anvil::Utils::convert_external_memory_handle_types_to_vk_external_memory_handle_type_flags(external_memory_handle_types); + external_memory_buffer_create_info.handleTypes = Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(external_memory_handle_types); external_memory_buffer_create_info.pNext = nullptr; external_memory_buffer_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR; @@ -389,12 +366,19 @@ bool Anvil::Buffer::init() case Anvil::BufferType::NONSPARSE_ALLOC: { /* Create a memory object and preallocate as much space as we need */ - auto client_data_ptr = m_create_info_ptr->get_client_data(); - auto memory_block_ptr = Anvil::MemoryBlock::create(m_create_info_ptr->get_device(), - m_buffer_memory_reqs.memoryTypeBits, - m_buffer_memory_reqs.size, - m_create_info_ptr->get_memory_features(), - m_create_info_ptr->get_mt_safety () ); + auto client_data_ptr = m_create_info_ptr->get_client_data(); + Anvil::MemoryBlockUniquePtr memory_block_ptr; + + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_regular(m_create_info_ptr->get_device(), + m_buffer_memory_reqs.memoryTypeBits, + m_buffer_memory_reqs.size, + m_create_info_ptr->get_memory_features() ); + + create_info_ptr->set_mt_safety(m_create_info_ptr->get_mt_safety() ); + + memory_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } if (!set_nonsparse_memory( std::move(memory_block_ptr) )) { @@ -424,11 +408,17 @@ bool Anvil::Buffer::init() case Anvil::BufferType::NONSPARSE_NO_ALLOC_CHILD: { - m_owned_memory_blocks.push_back( - Anvil::MemoryBlock::create_derived(m_create_info_ptr->get_parent_buffer_ptr()->get_memory_block(0 /* in_n_memory_block */), - m_create_info_ptr->get_start_offset(), - m_create_info_ptr->get_size() ) - ); + Anvil::MemoryBlockUniquePtr mem_block_ptr; + + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_derived(m_create_info_ptr->get_parent_buffer_ptr()->get_memory_block(0 /* in_n_memory_block */), + m_create_info_ptr->get_start_offset(), + m_create_info_ptr->get_size() ); + + mem_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } + + m_owned_memory_blocks.push_back(std::move(mem_block_ptr) ); m_memory_block_ptr = m_owned_memory_blocks.back().get(); anvil_assert(m_memory_block_ptr != nullptr); @@ -489,7 +479,7 @@ bool Anvil::Buffer::read(VkDeviceSize in_start_offset, /* TODO: Support for sparse buffers */ anvil_assert(m_create_info_ptr->get_type() != Anvil::BufferType::SPARSE_NO_ALLOC); - if ((memory_block_ptr->get_memory_features() & MEMORY_FEATURE_FLAG_MAPPABLE) != 0) + if ((memory_block_ptr->get_create_info_ptr()->get_memory_features() & MEMORY_FEATURE_FLAG_MAPPABLE) != 0) { result = memory_block_ptr->read(in_start_offset, in_size, @@ -571,8 +561,10 @@ bool Anvil::Buffer::read(VkDeviceSize in_start_offset, if (device_type == Anvil::DEVICE_TYPE_SINGLE_GPU) { - queue_ptr->submit_command_buffer(copy_cmdbuf_ptr.get(), - true /* should_block */); + queue_ptr->submit( + Anvil::SubmitInfo::create_execute(copy_cmdbuf_ptr.get(), + true /* should_block */) + ); } result = staging_buffer_ptr->read(0, @@ -790,10 +782,10 @@ bool Anvil::Buffer::write(VkDeviceSize in_start_offset, anvil_assert(m_page_tracker_ptr->get_n_memory_blocks() == 1); } - anvil_assert(memory_block_ptr != nullptr); - anvil_assert(memory_block_ptr->get_size() >= in_size); + anvil_assert(memory_block_ptr != nullptr); + anvil_assert(memory_block_ptr->get_create_info_ptr()->get_size() >= in_size); - if ((memory_block_ptr->get_memory_features() & MEMORY_FEATURE_FLAG_MAPPABLE) != 0) + if ((memory_block_ptr->get_create_info_ptr()->get_memory_features() & MEMORY_FEATURE_FLAG_MAPPABLE) != 0) { result = memory_block_ptr->write(in_start_offset, in_size, @@ -940,8 +932,10 @@ bool Anvil::Buffer::write(VkDeviceSize in_start_offset, if (device_type == Anvil::DEVICE_TYPE_SINGLE_GPU) { - queue_ptr->submit_command_buffer(copy_cmdbuf_ptr.get(), - true /* should_block */); + queue_ptr->submit( + Anvil::SubmitInfo::create_execute(copy_cmdbuf_ptr.get(), + true /* should_block */) + ); } result = true; diff --git a/src/wrappers/descriptor_pool.cpp b/src/wrappers/descriptor_pool.cpp index 16a62b54..2aef815a 100644 --- a/src/wrappers/descriptor_pool.cpp +++ b/src/wrappers/descriptor_pool.cpp @@ -220,7 +220,6 @@ bool Anvil::DescriptorPool::alloc_descriptor_sets(uint32_t } result = is_vk_call_successful(result_vk); - end: return result; } diff --git a/src/wrappers/device.cpp b/src/wrappers/device.cpp index a61675ec..54137431 100644 --- a/src/wrappers/device.cpp +++ b/src/wrappers/device.cpp @@ -71,9 +71,9 @@ Anvil::BaseDevice::~BaseDevice() m_command_pool_ptr_per_vk_queue_fam.clear(); m_compute_pipeline_manager_ptr.reset (); - m_descriptor_set_layout_manager_ptr.reset(); m_dummy_dsg_ptr.reset (); m_graphics_pipeline_manager_ptr.reset (); + m_descriptor_set_layout_manager_ptr.reset(); m_pipeline_cache_ptr.reset (); m_pipeline_layout_manager_ptr.reset (); m_owned_queues.clear (); @@ -103,6 +103,88 @@ Anvil::DescriptorSetLayout* Anvil::BaseDevice::get_dummy_descriptor_set_layout() return m_dummy_dsg_ptr->get_descriptor_set_layout(0); } +/** Please see header for specification */ +bool Anvil::BaseDevice::get_memory_types_supported_for_external_handle(const Anvil::ExternalMemoryHandleTypeBit& in_external_handle_type, + ExternalHandleType in_handle, + uint32_t* out_supported_memory_type_bits) const +{ + bool result = false; + + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_win32() ) + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_win32() ); + + goto end; + } + + if (in_external_handle_type != Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT && + in_external_handle_type != Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) + { + anvil_assert(in_external_handle_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT || + in_external_handle_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); + + goto end; + } + } + #else + { + if (!m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_fd() ) + { + anvil_assert(m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_fd() ); + + goto end; + } + + if (in_external_handle_type != Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) + { + anvil_assert(in_external_handle_type == Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); + + goto end; + } + } + #endif + + /* Go ahead with the query */ + #if defined(_WIN32) + VkMemoryWin32HandlePropertiesKHR result_props; + + result_props.pNext = nullptr; + result_props.sType = VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR; + #else + VkMemoryFdPropertiesKHR result_props; + + result_props.pNext = nullptr; + result_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR; + #endif + + #if defined(_WIN32) + if (m_khr_external_memory_win32_extension_entrypoints.vkGetMemoryWin32HandlePropertiesKHR(m_device, + static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(in_external_handle_type) ), + in_handle, + &result_props) != VK_SUCCESS) + #else + if (m_khr_external_memory_fd_extension_entrypoints.vkGetMemoryFdPropertiesKHR(m_device, + static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(in_external_handle_type) ), + in_handle, + &result_props) != VK_SUCCESS) + #endif + { + anvil_assert_fail(); + + goto end; + } + + *out_supported_memory_type_bits = result_props.memoryTypeBits; + + /* All done */ + result = true; +end: + return result; +} + /** Please see header for specification */ uint32_t Anvil::BaseDevice::get_n_queues(uint32_t in_n_queue_family) const { @@ -651,6 +733,36 @@ void Anvil::BaseDevice::init(const DeviceExtensionConfiguration& in_extensions, anvil_assert(m_khr_bind_memory2_extension_entrypoints.vkBindImageMemory2KHR != nullptr); } + #if defined(_WIN32) + { + if (m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_fence_win32() ) + { + m_khr_external_fence_win32_extension_entrypoints.vkGetFenceWin32HandleKHR = reinterpret_cast (get_proc_address("vkGetFenceWin32HandleKHR") ); + m_khr_external_fence_win32_extension_entrypoints.vkImportFenceWin32HandleKHR = reinterpret_cast(get_proc_address("vkImportFenceWin32HandleKHR") ); + + anvil_assert(m_khr_external_fence_win32_extension_entrypoints.vkGetFenceWin32HandleKHR != nullptr); + anvil_assert(m_khr_external_fence_win32_extension_entrypoints.vkImportFenceWin32HandleKHR != nullptr); + } + + if (m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory_win32() ) + { + m_khr_external_memory_win32_extension_entrypoints.vkGetMemoryWin32HandleKHR = reinterpret_cast (get_proc_address("vkGetMemoryWin32HandleKHR")); + m_khr_external_memory_win32_extension_entrypoints.vkGetMemoryWin32HandlePropertiesKHR = reinterpret_cast(get_proc_address("vkGetMemoryWin32HandlePropertiesKHR")); + + anvil_assert(m_khr_external_memory_win32_extension_entrypoints.vkGetMemoryWin32HandleKHR != nullptr); + anvil_assert(m_khr_external_memory_win32_extension_entrypoints.vkGetMemoryWin32HandlePropertiesKHR != nullptr); + } + + if (m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_semaphore_win32() ) + { + m_khr_external_semaphore_win32_extension_entrypoints.vkGetSemaphoreWin32HandleKHR = reinterpret_cast (get_proc_address("vkGetSemaphoreWin32HandleKHR")); + m_khr_external_semaphore_win32_extension_entrypoints.vkImportSemaphoreWin32HandleKHR = reinterpret_cast(get_proc_address("vkImportSemaphoreWin32HandleKHR")); + + anvil_assert(m_khr_external_semaphore_win32_extension_entrypoints.vkGetSemaphoreWin32HandleKHR != nullptr); + anvil_assert(m_khr_external_semaphore_win32_extension_entrypoints.vkImportSemaphoreWin32HandleKHR != nullptr); + } + } + #endif if (m_extension_enabled_info_ptr->get_device_extension_info()->khr_maintenance1() ) { @@ -854,16 +966,6 @@ bool Anvil::BaseDevice::is_universal_queue_family_index(const uint32_t& in_queue (m_queue_family_index_to_type.at (in_queue_family_index) == Anvil::QueueFamilyType::UNIVERSAL); } -bool Anvil::BaseDevice::supports_external_memory_handles(const Anvil::ExternalMemoryHandleTypeFlags& in_types) const -{ - bool result = m_extension_enabled_info_ptr->get_device_extension_info()->khr_external_memory(); - - /* NOTE: Anvil does not support any external memory handle types YET. */ - result &= (in_types == 0); - - return result; -} - /* Please see header for specification */ bool Anvil::BaseDevice::wait_idle() const { @@ -1046,6 +1148,13 @@ Anvil::SwapchainUniquePtr Anvil::SGPUDevice::create_swapchain(Anvil::RenderingSu return result_ptr; } +bool Anvil::SGPUDevice::get_physical_device_buffer_format_properties(const BufferFormatPropertiesQuery& in_query, + Anvil::BufferFormatProperties* out_opt_result_ptr) const +{ + return m_parent_physical_device_ptr->get_buffer_format_properties(in_query, + out_opt_result_ptr); +} + /** Please see header for specification */ const Anvil::PhysicalDeviceFeatures& Anvil::SGPUDevice::get_physical_device_features() const { @@ -1053,30 +1162,25 @@ const Anvil::PhysicalDeviceFeatures& Anvil::SGPUDevice::get_physical_device_feat } /** Please see header for specification */ -const Anvil::FormatProperties& Anvil::SGPUDevice::get_physical_device_format_properties(VkFormat in_format) const +bool Anvil::SGPUDevice::get_physical_device_fence_properties(const FencePropertiesQuery& in_query, + Anvil::FenceProperties* out_opt_result_ptr) const { - return m_parent_physical_device_ptr->get_format_properties(in_format); + return m_parent_physical_device_ptr->get_fence_properties(in_query, + out_opt_result_ptr); } /** Please see header for specification */ -bool Anvil::SGPUDevice::get_physical_device_image_format_properties(VkFormat in_format, - VkImageType in_type, - VkImageTiling in_tiling, - VkImageUsageFlags in_usage, - VkImageCreateFlags in_flags, - VkImageFormatProperties& out_result) const +Anvil::FormatProperties Anvil::SGPUDevice::get_physical_device_format_properties(VkFormat in_format) const { - bool result; - - result = is_vk_call_successful(vkGetPhysicalDeviceImageFormatProperties(m_parent_physical_device_ptr->get_physical_device(), - in_format, - in_type, - in_tiling, - in_usage, - in_flags, - &out_result) ); + return m_parent_physical_device_ptr->get_format_properties(in_format); +} - return result; +/** Please see header for specification */ +bool Anvil::SGPUDevice::get_physical_device_image_format_properties(const ImageFormatPropertiesQuery& in_query, + Anvil::ImageFormatProperties* out_opt_result_ptr) const +{ + return m_parent_physical_device_ptr->get_image_format_properties(in_query, + out_opt_result_ptr); } /** Please see header for specification */ diff --git a/src/wrappers/fence.cpp b/src/wrappers/fence.cpp index 0e922049..aea1a154 100644 --- a/src/wrappers/fence.cpp +++ b/src/wrappers/fence.cpp @@ -21,12 +21,15 @@ // #include "misc/debug.h" +#include "misc/external_handle.h" #include "misc/fence_create_info.h" #include "misc/object_tracker.h" +#include "misc/struct_chainer.h" #include "wrappers/device.h" #include "wrappers/fence.h" #include + /* Please see header for specification */ Anvil::Fence::Fence(Anvil::FenceCreateInfoUniquePtr in_create_info_ptr) :DebugMarkerSupportProvider(in_create_info_ptr->get_device(), @@ -73,21 +76,268 @@ Anvil::FenceUniquePtr Anvil::Fence::create(Anvil::FenceCreateInfoUniquePtr in_cr return result_ptr; } +/* Please see header for specification */ +Anvil::ExternalHandleUniquePtr Anvil::Fence::export_to_external_handle(const Anvil::ExternalFenceHandleTypeBit& in_fence_handle_type) +{ + #if defined(_WIN32) + const auto invalid_handle = nullptr; + const bool is_autorelease_handle = Anvil::Utils::is_nt_handle(in_fence_handle_type); + const bool only_one_handle_ever_permitted = Anvil::Utils::is_nt_handle(in_fence_handle_type); + #else + const int invalid_handle = -1; + const bool is_autorelease_handle = true; + const bool only_one_handle_ever_permitted = false; + #endif + + ExternalHandleType result_handle = 0; + Anvil::ExternalHandleUniquePtr result_ptr; + + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_fence_win32() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_fence_win32() ); + + goto end; + } + } + #else + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_fence_fd() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_fence_fd() ); + + goto end; + } + } + #endif + + if (only_one_handle_ever_permitted && + m_external_fence_created_for_handle_type.find(in_fence_handle_type) != m_external_fence_created_for_handle_type.end() ) + { + anvil_assert_fail(); + + goto end; + } + + /* Go and try to open a new handle. */ + #if defined(_WIN32) + { + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_fence_win32_entrypoints(); + VkFenceGetWin32HandleInfoKHR info; + + anvil_assert(m_fence != VK_NULL_HANDLE); + + info.fence = m_fence; + info.handleType = static_cast(Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(in_fence_handle_type) ); + info.pNext = nullptr; + info.sType = VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR; + + if (entrypoints_ptr->vkGetFenceWin32HandleKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + { + anvil_assert_fail(); + + goto end; + } + } + #else + { + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_fence_fd_entrypoints(); + VkFenceGetFdInfoKHR info; + + anvil_assert(m_fence != VK_NULL_HANDLE); + + info.fence = m_fence; + info.handleType = static_cast(Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(in_fence_handle_type) ); + info.pNext = nullptr; + info.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR; + + if (entrypoints_ptr->vkGetFenceFdKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + { + anvil_assert_fail(); + + goto end; + } + } + #endif + + if (result_handle == invalid_handle) + { + anvil_assert(result_handle != invalid_handle); + + goto end; + } + + /* If this is necessary, cache the newly created handle so that we do not let the app attempt to re-create the external handle + * for the same Vulkan fence handle. + */ + if (only_one_handle_ever_permitted) + { + m_external_fence_created_for_handle_type[in_fence_handle_type] = true; + } + + result_ptr = Anvil::ExternalHandle::create(result_handle, + is_autorelease_handle); /* in_close_at_destruction_time */ + +end: + return result_ptr; +} + +#if defined(_WIN32) + bool Anvil::Fence::import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalFenceHandleTypeBit& in_handle_type, + const ExternalHandleType& in_opt_handle, + const std::wstring& in_opt_name) +#else + bool Anvil::Fence::import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalFenceHandleTypeBit& in_handle_type, + const ExternalHandleType& in_handle) +#endif +{ + #if defined(_WIN32) + const auto entrypoints_ptr = &m_device_ptr->get_extension_khr_external_fence_win32_entrypoints(); + #else + const auto entrypoints_ptr = &m_device_ptr->get_extension_khr_external_fence_fd_entrypoints(); + #endif + + bool result = false; + + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_device_ptr->get_extension_info()->khr_external_fence_win32() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_fence_win32() ); + + goto end; + } + } + #else + { + if (!m_device_ptr->get_extension_info()->khr_external_fence_fd() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_fence_fd() ); + + goto end; + } + } + #endif + + /* Proceed */ + #if defined(_WIN32) + { + VkImportFenceWin32HandleInfoKHR info_vk; + + info_vk.fence = m_fence; + info_vk.flags = (in_temporary_import) ? VK_FENCE_IMPORT_TEMPORARY_BIT_KHR + : 0; + info_vk.handle = in_opt_handle; + info_vk.handleType = static_cast(Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(in_handle_type) ); + info_vk.name = (in_opt_name.size() > 0) ? &in_opt_name.at(0) + : nullptr; + info_vk.pNext = nullptr; + info_vk.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR; + + result = (entrypoints_ptr->vkImportFenceWin32HandleKHR(m_device_ptr->get_device_vk(), + &info_vk) == VK_SUCCESS); + } + #else + { + VkImportFenceFdInfoKHR info_vk; + + info_vk.fd = in_handle; + info_vk.fence = m_fence; + info_vk.flags = (in_temporary_import) ? VK_FENCE_IMPORT_TEMPORARY_BIT_KHR + : 0; + info_vk.handleType = static_cast(Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(in_handle_type) ); + info_vk.pNext = nullptr; + info_vk.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR; + + result = (entrypoints_ptr->vkImportFenceFdKHR(m_device_ptr->get_device_vk(), + &info_vk) == VK_SUCCESS); + } + #endif +end: + return result; +} + bool Anvil::Fence::init() { - VkFenceCreateInfo fence_create_info; - VkResult result (VK_ERROR_INITIALIZATION_FAILED); + VkFenceCreateInfo fence_create_info; + VkResult result (VK_ERROR_INITIALIZATION_FAILED); + Anvil::StructChainer struct_chainer; + Anvil::StructChainUniquePtr struct_chain_ptr; - ANVIL_REDUNDANT_VARIABLE(result); + /* Sanity checks */ + if (m_create_info_ptr->get_exportable_external_fence_handle_types() != Anvil::EXTERNAL_FENCE_HANDLE_TYPE_NONE) + { + if (!m_device_ptr->get_extension_info()->khr_external_fence() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_fence() ); + + goto end; + } + } /* Spawn a new fence */ - fence_create_info.flags = (m_create_info_ptr->should_create_signalled() ) ? VK_FENCE_CREATE_SIGNALED_BIT - : 0u; - fence_create_info.pNext = nullptr; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + { + fence_create_info.flags = (m_create_info_ptr->should_create_signalled() ) ? VK_FENCE_CREATE_SIGNALED_BIT + : 0u; + fence_create_info.pNext = nullptr; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + + struct_chainer.append_struct(fence_create_info); + } + + if (m_create_info_ptr->get_exportable_external_fence_handle_types() != Anvil::EXTERNAL_FENCE_HANDLE_TYPE_NONE) + { + VkExportFenceCreateInfo create_info; + + create_info.handleTypes = Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(m_create_info_ptr->get_exportable_external_fence_handle_types() ); + create_info.pNext = nullptr; + create_info.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR; + + struct_chainer.append_struct(create_info); + } + + #if defined(_WIN32) + { + const Anvil::ExternalNTHandleInfo* nt_handle_info_ptr = nullptr; + + if (m_create_info_ptr->get_exportable_nt_handle_info(&nt_handle_info_ptr) ) + { + VkExportFenceWin32HandleInfoKHR handle_info; + + anvil_assert(nt_handle_info_ptr != nullptr); + anvil_assert(m_create_info_ptr->get_exportable_external_fence_handle_types() & Anvil::EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT); + + handle_info.dwAccess = nt_handle_info_ptr->access; + handle_info.name = (nt_handle_info_ptr->name.size() > 0) ? &nt_handle_info_ptr->name.at(0) + : nullptr; + handle_info.pAttributes = nt_handle_info_ptr->attributes_ptr; + handle_info.pNext = nullptr; + handle_info.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR; + + struct_chainer.append_struct(handle_info); + } + } + #endif + + struct_chain_ptr = struct_chainer.create_chain(); + if (struct_chain_ptr == nullptr) + { + anvil_assert(struct_chain_ptr != nullptr); + + goto end; + } result = vkCreateFence(m_device_ptr->get_device_vk(), - &fence_create_info, + struct_chain_ptr->get_root_struct(), nullptr, /* pAllocator */ &m_fence); @@ -97,6 +347,7 @@ bool Anvil::Fence::init() set_vk_handle(m_fence); } +end: return is_vk_call_successful(result); } diff --git a/src/wrappers/image.cpp b/src/wrappers/image.cpp index f74d2fb5..08917e13 100644 --- a/src/wrappers/image.cpp +++ b/src/wrappers/image.cpp @@ -24,6 +24,7 @@ #include "misc/debug.h" #include "misc/formats.h" #include "misc/image_create_info.h" +#include "misc/memory_block_create_info.h" #include "misc/object_tracker.h" #include "misc/struct_chainer.h" #include "misc/swapchain_create_info.h" @@ -125,13 +126,18 @@ void Anvil::Image::change_image_layout(Anvil::Queue* in_queue_p if (device_type == Anvil::DEVICE_TYPE_SINGLE_GPU) { - in_queue_ptr->submit_command_buffer_with_signal_wait_semaphores(transition_command_buffer_ptr.get(), - in_opt_n_set_semaphores, - in_opt_set_semaphore_ptrs, - in_opt_n_wait_semaphores, - in_opt_wait_semaphore_ptrs, - in_opt_wait_dst_stage_mask_ptrs, - true /* should_block */); + Anvil::CommandBufferBase* cmd_buffer_ptr = transition_command_buffer_ptr.get(); + + in_queue_ptr->submit( + Anvil::SubmitInfo::create(1, /* in_n_cmd_bufers */ + &cmd_buffer_ptr, + in_opt_n_set_semaphores, + in_opt_set_semaphore_ptrs, + in_opt_n_wait_semaphores, + in_opt_wait_semaphore_ptrs, + in_opt_wait_dst_stage_mask_ptrs, + true /* should_block */) + ); } } @@ -185,23 +191,6 @@ Anvil::ImageUniquePtr Anvil::Image::create(Anvil::ImageCreateInfoUniquePtr in_cr return result_ptr; } -bool Anvil::Image::do_sanity_checks_for_external_memory_handle_types(const Anvil::ExternalMemoryHandleTypeFlags& in_external_memory_handle_types) const -{ - bool result = true; - - if (in_external_memory_handle_types != 0) - { - if (!m_device_ptr->supports_external_memory_handles(in_external_memory_handle_types) ) - { - anvil_assert(!m_device_ptr->supports_external_memory_handles(in_external_memory_handle_types) ); - - result = false; - } - } - - return result; -} - /** Please see header for specification */ bool Anvil::Image::get_aspect_subresource_layout(VkImageAspectFlags in_aspect, uint32_t in_n_layer, @@ -285,19 +274,14 @@ bool Anvil::Image::init() { std::vector aspects_used; VkImageCreateFlags image_flags = 0; - VkImageFormatProperties image_format_props; + Anvil::ImageFormatProperties image_format_props; const auto memory_features = m_create_info_ptr->get_memory_features(); uint32_t n_queue_family_indices = 0; uint32_t queue_family_indices[3]; VkResult result = VK_ERROR_INITIALIZATION_FAILED; - bool result_bool = false; + bool result_bool = true; Anvil::StructChainer struct_chainer; - if (!do_sanity_checks_for_external_memory_handle_types(m_create_info_ptr->get_external_memory_handle_types() )) - { - goto end; - } - if ((memory_features & MEMORY_FEATURE_FLAG_MAPPABLE) == 0) { anvil_assert((memory_features & MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0); @@ -324,37 +308,35 @@ bool Anvil::Image::init() &n_queue_family_indices); /* Is the requested texture size valid? */ - result_bool = m_device_ptr->get_physical_device_image_format_properties(m_create_info_ptr->get_format (), - m_create_info_ptr->get_type_vk (), - m_create_info_ptr->get_tiling (), - m_create_info_ptr->get_usage_flags(), - 0, /* flags */ - image_format_props); - - if (!result_bool) + if (!m_device_ptr->get_physical_device_image_format_properties(Anvil::ImageFormatPropertiesQuery(m_create_info_ptr->get_format (), + m_create_info_ptr->get_type_vk (), + m_create_info_ptr->get_tiling (), + m_create_info_ptr->get_usage_flags (), + m_create_info_ptr->get_create_flags() ), + &image_format_props) ) { - anvil_assert(result_bool); + anvil_assert_fail(); goto end; } - anvil_assert(m_create_info_ptr->get_base_mip_width() <= image_format_props.maxExtent.width); + anvil_assert(m_create_info_ptr->get_base_mip_width() <= image_format_props.max_extent.width); if (m_create_info_ptr->get_base_mip_height() > 1) { - anvil_assert(m_create_info_ptr->get_base_mip_height() <= image_format_props.maxExtent.height); + anvil_assert(m_create_info_ptr->get_base_mip_height() <= image_format_props.max_extent.height); } if (m_create_info_ptr->get_base_mip_depth() > 1) { - anvil_assert(m_create_info_ptr->get_base_mip_depth() <= image_format_props.maxExtent.depth); + anvil_assert(m_create_info_ptr->get_base_mip_depth() <= image_format_props.max_extent.depth); } anvil_assert(m_create_info_ptr->get_n_layers() >= 1); if (m_create_info_ptr->get_n_layers() > 1) { - anvil_assert(m_create_info_ptr->get_n_layers() <= image_format_props.maxArrayLayers); + anvil_assert(m_create_info_ptr->get_n_layers() <= image_format_props.n_max_array_layers); } /* If multisample image is requested, make sure the number of samples is supported. */ @@ -362,7 +344,7 @@ bool Anvil::Image::init() if (m_create_info_ptr->get_sample_count() > 1) { - anvil_assert((image_format_props.sampleCounts & m_create_info_ptr->get_sample_count() ) != 0); + anvil_assert((image_format_props.sample_counts & m_create_info_ptr->get_sample_count() ) != 0); } /* Create the image object */ @@ -454,7 +436,7 @@ bool Anvil::Image::init() VkExternalMemoryImageCreateInfoKHR external_memory_image_create_info; const auto handle_types = m_create_info_ptr->get_external_memory_handle_types(); - external_memory_image_create_info.handleTypes = Anvil::Utils::convert_external_memory_handle_types_to_vk_external_memory_handle_type_flags(handle_types); + external_memory_image_create_info.handleTypes = Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(handle_types); external_memory_image_create_info.pNext = nullptr; external_memory_image_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR; @@ -593,11 +575,18 @@ bool Anvil::Image::init() if (m_create_info_ptr->get_type() == Anvil::ImageType::NONSPARSE_ALLOC) { /* Allocate memory for the image */ - auto memory_block_ptr = Anvil::MemoryBlock::create(m_device_ptr, - m_memory_reqs.memoryTypeBits, - m_memory_reqs.size, - m_create_info_ptr->get_memory_features(), - Anvil::Utils::convert_boolean_to_mt_safety_enum(is_mt_safe()) ); + Anvil::MemoryBlockUniquePtr memory_block_ptr; + + { + auto create_info_ptr = Anvil::MemoryBlockCreateInfo::create_regular(m_device_ptr, + m_memory_reqs.memoryTypeBits, + m_memory_reqs.size, + m_create_info_ptr->get_memory_features() ); + + create_info_ptr->set_mt_safety(Anvil::Utils::convert_boolean_to_mt_safety_enum(is_mt_safe()) ); + + memory_block_ptr = Anvil::MemoryBlock::create(std::move(create_info_ptr) ); + } if (memory_block_ptr == nullptr) { @@ -1210,7 +1199,7 @@ void Anvil::Image::on_memory_backing_opaque_update(VkDeviceSize in_resour if (in_memory_block_ptr != nullptr) { - anvil_assert(in_memory_block_ptr->get_size() <= in_memory_block_start_offset + in_size); + anvil_assert(in_memory_block_ptr->get_create_info_ptr()->get_size() <= in_memory_block_start_offset + in_size); } if (m_create_info_ptr->get_residency_scope() == Anvil::SPARSE_RESIDENCY_SCOPE_NONE) @@ -1929,7 +1918,14 @@ void Anvil::Image::upload_mipmaps(const std::vector* in_mipmaps_p temp_cmdbuf_ptr->stop_recording(); /* Execute the command buffer */ - universal_queue_ptr->submit_command_buffer(temp_cmdbuf_ptr.get(), - true /* should_block */); + { + Anvil::CommandBufferBase* cmd_buffer_raw_ptr = temp_cmdbuf_ptr.get(); + + universal_queue_ptr->submit( + Anvil::SubmitInfo::create_execute(&cmd_buffer_raw_ptr, + 1, /* in_n_cmd_buffers */ + true) /* should_block */ + ); + } } } \ No newline at end of file diff --git a/src/wrappers/instance.cpp b/src/wrappers/instance.cpp index 90f0429e..e9dc49db 100644 --- a/src/wrappers/instance.cpp +++ b/src/wrappers/instance.cpp @@ -276,6 +276,30 @@ void Anvil::Instance::enumerate_physical_devices() } } +/** Please see header for specification */ +const Anvil::ExtensionKHRExternalFenceCapabilitiesEntrypoints& Anvil::Instance::get_extension_khr_external_fence_capabilities_entrypoints() const +{ + anvil_assert(m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_fence_capabilities() ); + + return m_khr_external_fence_capabilities_entrypoints; +} + +/** Please see header for specification */ +const Anvil::ExtensionKHRExternalMemoryCapabilitiesEntrypoints& Anvil::Instance::get_extension_khr_external_memory_capabilities_entrypoints() const +{ + anvil_assert(m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_memory_capabilities() ); + + return m_khr_external_memory_capabilities_entrypoints; +} + +/** Please see header for specification */ +const Anvil::ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints& Anvil::Instance::get_extension_khr_external_semaphore_capabilities_entrypoints() const +{ + anvil_assert(m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_semaphore_capabilities() ); + + return m_khr_external_semaphore_capabilities_entrypoints; +} + /** Please see header for specification */ const Anvil::ExtensionKHRGetPhysicalDeviceProperties2& Anvil::Instance::get_extension_khr_get_physical_device_properties2_entrypoints() const { @@ -581,6 +605,30 @@ void Anvil::Instance::init_func_pointers() anvil_assert(m_khr_get_physical_device_properties2_entrypoints.vkGetPhysicalDeviceQueueFamilyProperties2KHR != nullptr); anvil_assert(m_khr_get_physical_device_properties2_entrypoints.vkGetPhysicalDeviceSparseImageFormatProperties2KHR != nullptr); } + + if (m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_fence_capabilities() ) + { + m_khr_external_fence_capabilities_entrypoints.vkGetPhysicalDeviceExternalFencePropertiesKHR = reinterpret_cast(vkGetInstanceProcAddr(m_instance, + "vkGetPhysicalDeviceExternalFencePropertiesKHR") ); + + anvil_assert(m_khr_external_fence_capabilities_entrypoints.vkGetPhysicalDeviceExternalFencePropertiesKHR!= nullptr); + } + + if (m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_memory_capabilities() ) + { + m_khr_external_memory_capabilities_entrypoints.vkGetPhysicalDeviceExternalBufferPropertiesKHR = reinterpret_cast(vkGetInstanceProcAddr(m_instance, + "vkGetPhysicalDeviceExternalBufferPropertiesKHR") ); + + anvil_assert(m_khr_external_memory_capabilities_entrypoints.vkGetPhysicalDeviceExternalBufferPropertiesKHR != nullptr); + } + + if (m_enabled_extensions_info_ptr->get_instance_extension_info()->khr_external_semaphore_capabilities() ) + { + m_khr_external_semaphore_capabilities_entrypoints.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = reinterpret_cast(vkGetInstanceProcAddr(m_instance, + "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR") ); + + anvil_assert(m_khr_external_semaphore_capabilities_entrypoints.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR!= nullptr); + } } /** Please see header for specification */ diff --git a/src/wrappers/memory_block.cpp b/src/wrappers/memory_block.cpp index 6dcc7787..b477ed28 100644 --- a/src/wrappers/memory_block.cpp +++ b/src/wrappers/memory_block.cpp @@ -21,6 +21,7 @@ // #include "misc/debug.h" +#include "misc/external_handle.h" #include "misc/object_tracker.h" #include "misc/struct_chainer.h" #include "wrappers/buffer.h" @@ -30,108 +31,51 @@ #include "wrappers/physical_device.h" /* Please see header for specification */ -Anvil::MemoryBlock::MemoryBlock(const Anvil::BaseDevice* in_device_ptr, - uint32_t in_allowed_memory_bits, - VkDeviceSize in_size, - Anvil::MemoryFeatureFlags in_memory_features, - bool in_mt_safe, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) - :MTSafetySupportProvider (in_mt_safe), - m_allowed_memory_bits (in_allowed_memory_bits), +Anvil::MemoryBlock::MemoryBlock(Anvil::MemoryBlockCreateInfoUniquePtr in_create_info_ptr) + :MTSafetySupportProvider (Anvil::Utils::convert_mt_safety_enum_to_boolean(in_create_info_ptr->get_mt_safety(), + in_create_info_ptr->get_device () )), m_backend_object (nullptr), - m_device_ptr (in_device_ptr), - m_external_memory_handle_types (in_external_memory_handle_types), m_gpu_data_map_count (0), m_gpu_data_ptr (nullptr), m_memory (VK_NULL_HANDLE), - m_memory_features (in_memory_features), - m_parent_memory_allocator_backend_ptr(nullptr), - m_parent_memory_block_ptr (nullptr), - m_size (in_size), - m_start_offset (0) + m_memory_type_index (in_create_info_ptr->get_memory_type_index() ), + m_parent_memory_allocator_backend_ptr(nullptr) { - /* Register the object */ - Anvil::ObjectTracker::get()->register_object(Anvil::OBJECT_TYPE_MEMORY_BLOCK, - this); -} - -/* Please see header for specification */ -Anvil::MemoryBlock::MemoryBlock(MemoryBlock* in_parent_memory_block_ptr, - VkDeviceSize in_start_offset, - VkDeviceSize in_size) - :MTSafetySupportProvider(false) -{ - anvil_assert(in_parent_memory_block_ptr != nullptr); - anvil_assert(in_parent_memory_block_ptr->m_gpu_data_ptr == nullptr); - - m_allowed_memory_bits = in_parent_memory_block_ptr->m_allowed_memory_bits; - m_backend_object = in_parent_memory_block_ptr->m_backend_object; - m_device_ptr = in_parent_memory_block_ptr->m_device_ptr; - m_external_memory_handle_types = in_parent_memory_block_ptr->m_external_memory_handle_types; - m_gpu_data_map_count = UINT32_MAX; - m_gpu_data_ptr = nullptr; - m_memory_features = in_parent_memory_block_ptr->m_memory_features; - m_memory = VK_NULL_HANDLE; - m_memory_type_index = UINT32_MAX; - m_on_release_callback_function = in_parent_memory_block_ptr->m_on_release_callback_function; - m_parent_memory_allocator_backend_ptr = in_parent_memory_block_ptr->m_parent_memory_allocator_backend_ptr; - m_parent_memory_block_ptr = in_parent_memory_block_ptr; - m_size = in_size; - m_start_offset = in_start_offset + m_parent_memory_block_ptr->m_start_offset; - - anvil_assert(m_start_offset >= m_parent_memory_block_ptr->m_start_offset); - anvil_assert(m_start_offset + m_size <= m_parent_memory_block_ptr->m_start_offset + m_parent_memory_block_ptr->m_size); + m_create_info_ptr = std::move(in_create_info_ptr); - /* Register the object */ - Anvil::ObjectTracker::get()->register_object(Anvil::OBJECT_TYPE_MEMORY_BLOCK, - this); -} - -/* Please see header for specification */ -Anvil::MemoryBlock::MemoryBlock(const Anvil::BaseDevice* in_device_ptr, - VkDeviceMemory in_memory, - uint32_t in_allowed_memory_bits, - Anvil::MemoryFeatureFlags in_memory_features, - uint32_t in_memory_type_index, - VkDeviceSize in_size, - VkDeviceSize in_start_offset, - OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) - :MTSafetySupportProvider(false) -{ - anvil_assert(in_on_release_callback_function != nullptr); - - m_allowed_memory_bits = in_allowed_memory_bits; - m_backend_object = nullptr; - m_device_ptr = in_device_ptr; - m_external_memory_handle_types = in_external_memory_handle_types; - m_gpu_data_map_count = 0; - m_gpu_data_ptr = nullptr; - m_memory_features = in_memory_features; - m_memory = in_memory; - m_memory_type_index = in_memory_type_index; - m_parent_memory_allocator_backend_ptr = nullptr; - m_parent_memory_block_ptr = nullptr; - m_on_release_callback_function = in_on_release_callback_function; - m_size = in_size; - m_start_offset = in_start_offset; + if (m_create_info_ptr->get_parent_memory_block() != nullptr) + { + m_start_offset = m_create_info_ptr->get_start_offset() + m_create_info_ptr->get_parent_memory_block()->m_start_offset; + } + else + { + m_start_offset = m_create_info_ptr->get_start_offset(); + } /* Register the object */ Anvil::ObjectTracker::get()->register_object(Anvil::OBJECT_TYPE_MEMORY_BLOCK, - this); + this); } /** Releases the underlying Vulkan memory object. */ Anvil::MemoryBlock::~MemoryBlock() { - if (m_parent_memory_block_ptr == nullptr) + auto on_release_callback_function = m_create_info_ptr->get_on_release_callback_function(); + + #ifdef _DEBUG { - anvil_assert(m_gpu_data_map_count.load() == 0); + auto parent_memory_block_ptr = m_create_info_ptr->get_parent_memory_block(); + + if (parent_memory_block_ptr == nullptr) + { + anvil_assert(m_gpu_data_map_count.load() == 0); + } } + #endif - if (m_on_release_callback_function != nullptr) + if (on_release_callback_function != nullptr) { - m_on_release_callback_function(this); + on_release_callback_function(this); } /* Unregister the object */ @@ -140,11 +84,11 @@ Anvil::MemoryBlock::~MemoryBlock() if (m_memory != VK_NULL_HANDLE) { - if (m_on_release_callback_function == nullptr) + if (on_release_callback_function == nullptr) { lock(); { - vkFreeMemory(m_device_ptr->get_device_vk(), + vkFreeMemory(m_create_info_ptr->get_device()->get_device_vk(), m_memory, nullptr /* pAllocator */); } @@ -158,9 +102,11 @@ Anvil::MemoryBlock::~MemoryBlock() /** Finishes the memory mapping process, opened earlier with a open_gpu_memory_access() call. */ void Anvil::MemoryBlock::close_gpu_memory_access() { - if (m_parent_memory_block_ptr != nullptr) + auto parent_memory_block_ptr = m_create_info_ptr->get_parent_memory_block(); + + if (parent_memory_block_ptr != nullptr) { - m_parent_memory_block_ptr->close_gpu_memory_access(); + parent_memory_block_ptr->close_gpu_memory_access(); } else { @@ -177,7 +123,7 @@ void Anvil::MemoryBlock::close_gpu_memory_access() else { /* This block will be entered for memory blocks instantiated without a memory allocator */ - vkUnmapMemory(m_device_ptr->get_device_vk(), + vkUnmapMemory(m_create_info_ptr->get_device()->get_device_vk(), m_memory); } } @@ -189,79 +135,157 @@ void Anvil::MemoryBlock::close_gpu_memory_access() } /* Please see header for specification */ -Anvil::MemoryBlockUniquePtr Anvil::MemoryBlock::create(const Anvil::BaseDevice* in_device_ptr, - uint32_t in_allowed_memory_bits, - VkDeviceSize in_size, - Anvil::MemoryFeatureFlags in_memory_features, - MTSafety in_mt_safety, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) +Anvil::MemoryBlockUniquePtr Anvil::MemoryBlock::create(Anvil::MemoryBlockCreateInfoUniquePtr in_create_info_ptr) { - const bool mt_safe = Anvil::Utils::convert_mt_safety_enum_to_boolean(in_mt_safety, - in_device_ptr); MemoryBlockUniquePtr result_ptr(nullptr, std::default_delete() ); + const auto type (in_create_info_ptr->get_type() ); result_ptr.reset( - new Anvil::MemoryBlock(in_device_ptr, - in_allowed_memory_bits, - in_size, - in_memory_features, - mt_safe, - in_external_memory_handle_types) + new Anvil::MemoryBlock( + std::move(in_create_info_ptr) + ) ); - if (!result_ptr->init() ) + if (result_ptr != nullptr) { - result_ptr.reset(); + if (type == Anvil::MemoryBlockType::REGULAR) + { + if (!result_ptr->init() ) + { + result_ptr.reset(); + } + } + else + if (type == Anvil::MemoryBlockType::DERIVED_WITH_CUSTOM_DELETE_PROC) + { + result_ptr->m_memory = result_ptr->m_create_info_ptr->get_memory(); + } } return result_ptr; } -/* Please see header for specification */ -Anvil::MemoryBlockUniquePtr Anvil::MemoryBlock::create_derived(MemoryBlock* in_parent_memory_block_ptr, - VkDeviceSize in_start_offset, - VkDeviceSize in_size) +Anvil::ExternalHandleUniquePtr Anvil::MemoryBlock::export_to_external_memory_handle(const Anvil::ExternalMemoryHandleTypeBit& in_memory_handle_type) { - MemoryBlockUniquePtr result_ptr(nullptr, - std::default_delete() ); + #if defined(_WIN32) + const auto invalid_handle = nullptr; + const bool is_autorelease_handle = Anvil::Utils::is_nt_handle(in_memory_handle_type); + const bool only_one_handle_ever_permitted = Anvil::Utils::is_nt_handle(in_memory_handle_type); + #else + const auto invalid_handle = -1; + const bool is_autorelease_handle = true; + const bool only_one_handle_ever_permitted = false; + #endif + + ExternalHandleType result_handle = invalid_handle; + Anvil::ExternalHandleUniquePtr result_returned_ptr; - result_ptr.reset( - new Anvil::MemoryBlock(in_parent_memory_block_ptr, - in_start_offset, - in_size) - ); + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_memory_win32() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_memory_win32() ); - return result_ptr; -} + goto end; + } + } + #else + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_memory_fd() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_memory_fd() ); -/* Please see header for specification */ -Anvil::MemoryBlockUniquePtr Anvil::MemoryBlock::create_derived_with_custom_delete_proc(const Anvil::BaseDevice* in_device_ptr, - VkDeviceMemory in_memory, - uint32_t in_allowed_memory_bits, - Anvil::MemoryFeatureFlags in_memory_features, - uint32_t in_memory_type_index, - VkDeviceSize in_size, - VkDeviceSize in_start_offset, - OnMemoryBlockReleaseCallbackFunction in_on_release_callback_function, - Anvil::ExternalMemoryHandleTypeFlags in_external_memory_handle_types) -{ - MemoryBlockUniquePtr result_ptr(nullptr, - std::default_delete() ); + goto end; + } + } + #endif - result_ptr.reset( - new Anvil::MemoryBlock(in_device_ptr, - in_memory, - in_allowed_memory_bits, - in_memory_features, - in_memory_type_index, - in_size, - in_start_offset, - in_on_release_callback_function, - in_external_memory_handle_types) - ); + if (m_create_info_ptr->get_type() != Anvil::MemoryBlockType::REGULAR) + { + anvil_assert(m_create_info_ptr->get_type() == Anvil::MemoryBlockType::REGULAR); - return result_ptr; + goto end; + } + + anvil_assert(m_create_info_ptr->get_parent_memory_block() == nullptr); + + /* Should we try to return a handle which has already been created for this memory block? */ + if (only_one_handle_ever_permitted) + { + auto map_iterator = m_external_handle_type_to_external_handle.find(in_memory_handle_type); + if (map_iterator != m_external_handle_type_to_external_handle.end() ) + { + result_returned_ptr = Anvil::ExternalHandleUniquePtr(map_iterator->second.get(), + [](Anvil::ExternalHandle*){} ); + + goto end; + } + } + + /* Apparently not, go and try to open the new handle then. */ + { + #if defined(_WIN32) + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_memory_win32_entrypoints(); + VkMemoryGetWin32HandleInfoKHR info; + #else + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_memory_fd_entrypoints(); + VkMemoryGetFdInfoKHR info; + #endif + + anvil_assert(m_memory != VK_NULL_HANDLE); + + info.handleType = static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(in_memory_handle_type) ); + info.memory = m_memory; + info.pNext = nullptr; + + #if defined(_WIN32) + { + info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; + } + #else + { + info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR; + } + #endif + + #if defined(_WIN32) + if (entrypoints_ptr->vkGetMemoryWin32HandleKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + #else + if (entrypoints_ptr->vkGetMemoryFdKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + #endif + { + goto end; + } + } + + /* Cache the newly created handle if it's a NT handle */ + if (only_one_handle_ever_permitted) + { + Anvil::ExternalHandleUniquePtr result_owned_ptr; + + result_owned_ptr = Anvil::ExternalHandle::create (result_handle, + is_autorelease_handle); /* in_close_at_destruction_time */ + result_returned_ptr = Anvil::ExternalHandleUniquePtr(result_owned_ptr.get(), + [](Anvil::ExternalHandle*){} ); + + m_external_handle_type_to_external_handle[in_memory_handle_type] = std::move(result_owned_ptr); + } + else + { + result_returned_ptr = Anvil::ExternalHandle::create(result_handle, + false); /* in_close_at_destruction_time */ + } + + anvil_assert(result_returned_ptr != nullptr); + +end: + return result_returned_ptr; } /** Returns index of a memory type which meets the specified requirements @@ -285,7 +309,7 @@ uint32_t Anvil::MemoryBlock::get_device_memory_type_index(uint32_t const bool is_host_cached_memory_required ((in_memory_features & MEMORY_FEATURE_FLAG_HOST_CACHED) != 0); const bool is_lazily_allocated_memory_required((in_memory_features & MEMORY_FEATURE_FLAG_LAZILY_ALLOCATED) != 0); const bool is_mappable_memory_required ((in_memory_features & MEMORY_FEATURE_FLAG_MAPPABLE) != 0); - const Anvil::MemoryTypes& memory_types (m_device_ptr->get_physical_device_memory_properties().types); + const Anvil::MemoryTypes& memory_types (get_create_info_ptr()->get_device()->get_physical_device_memory_properties().types); if (!is_mappable_memory_required) { @@ -335,9 +359,9 @@ bool Anvil::MemoryBlock::init() { VkMemoryAllocateInfo buffer_data_alloc_info; - buffer_data_alloc_info.allocationSize = m_size; - buffer_data_alloc_info.memoryTypeIndex = get_device_memory_type_index(m_allowed_memory_bits, - m_memory_features); + buffer_data_alloc_info.allocationSize = m_create_info_ptr->get_size(); + buffer_data_alloc_info.memoryTypeIndex = get_device_memory_type_index(m_create_info_ptr->get_allowed_memory_bits(), + m_create_info_ptr->get_memory_features () ); buffer_data_alloc_info.pNext = nullptr; buffer_data_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -346,21 +370,69 @@ bool Anvil::MemoryBlock::init() struct_chainer.append_struct(buffer_data_alloc_info); } - if (m_external_memory_handle_types != 0) + if (m_create_info_ptr->get_exportable_external_memory_handle_types() != Anvil::EXTERNAL_MEMORY_HANDLE_TYPE_NONE) { VkExportMemoryAllocateInfoKHR export_memory_alloc_info; - export_memory_alloc_info.handleTypes = Anvil::Utils::convert_external_memory_handle_types_to_vk_external_memory_handle_type_flags(m_external_memory_handle_types); + export_memory_alloc_info.handleTypes = Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(m_create_info_ptr->get_exportable_external_memory_handle_types() ); export_memory_alloc_info.pNext = nullptr; export_memory_alloc_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR; struct_chainer.append_struct(export_memory_alloc_info); + + { + const Anvil::ExternalMemoryHandleImportInfo* handle_import_info_ptr = nullptr; + + if (m_create_info_ptr->get_external_handle_import_info(&handle_import_info_ptr) ) + { + #if defined(_WIN32) + VkImportMemoryWin32HandleInfoKHR handle_info_khr; + #else + VkImportMemoryFdInfoKHR handle_info_khr; + #endif + + handle_info_khr.handleType = static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(static_cast(m_create_info_ptr->get_imported_external_memory_handle_type() )) ); + handle_info_khr.pNext = nullptr; + + #if defined(_WIN32) + handle_info_khr.handle = handle_import_info_ptr->handle; + handle_info_khr.name = (handle_import_info_ptr->name.size() > 0) ? handle_import_info_ptr->name.c_str() + : nullptr; + handle_info_khr.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR; + #else + handle_info_khr.fd = handle_import_info_ptr->handle; + handle_info_khr.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR; + #endif + + struct_chainer.append_struct(handle_info_khr); + } + } + + #if defined(_WIN32) + { + const Anvil::ExternalNTHandleInfo* nt_handle_import_info_ptr = nullptr; + + if (m_create_info_ptr->get_external_nt_handle_import_info(&nt_handle_import_info_ptr) ) + { + VkExportMemoryWin32HandleInfoKHR handle_info_khr; + + handle_info_khr.dwAccess = nt_handle_import_info_ptr->access; + handle_info_khr.name = (nt_handle_import_info_ptr->name.size() > 0) ? nt_handle_import_info_ptr->name.c_str() + : nullptr; + handle_info_khr.pAttributes = nt_handle_import_info_ptr->attributes_ptr; + handle_info_khr.pNext = nullptr; + handle_info_khr.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR; + + struct_chainer.append_struct(handle_info_khr); + } + } + #endif } { auto chain_ptr = struct_chainer.create_chain(); - result = vkAllocateMemory(m_device_ptr->get_device_vk(), + result = vkAllocateMemory(m_create_info_ptr->get_device()->get_device_vk(), chain_ptr->get_root_struct(), nullptr, /* pAllocator */ &m_memory); @@ -385,10 +457,12 @@ bool Anvil::MemoryBlock::intersects(const Anvil::MemoryBlock* in_memory_block_pt if (result) { - if (!(m_start_offset < in_memory_block_ptr->m_start_offset && - m_start_offset + m_size < in_memory_block_ptr->m_start_offset && - in_memory_block_ptr->m_start_offset < m_start_offset && - in_memory_block_ptr->m_start_offset + m_size < m_start_offset) ) + const auto size = m_create_info_ptr->get_size(); + + if (!(m_start_offset < in_memory_block_ptr->m_start_offset && + m_start_offset + size < in_memory_block_ptr->m_start_offset && + in_memory_block_ptr->m_start_offset < m_start_offset && + in_memory_block_ptr->m_start_offset + size < m_start_offset) ) { result = true; } @@ -406,14 +480,15 @@ bool Anvil::MemoryBlock::map(VkDeviceSize in_start_offset, VkDeviceSize in_size, void** out_opt_data_ptr) { - bool result = false; + const auto memory_features = m_create_info_ptr->get_memory_features(); + bool result = false; /* Sanity checks */ - if (m_parent_memory_block_ptr != nullptr) + if (m_create_info_ptr->get_parent_memory_block() != nullptr) { - result = m_parent_memory_block_ptr->map(m_start_offset + in_start_offset, - in_size, - out_opt_data_ptr); + result = m_create_info_ptr->get_parent_memory_block()->map(m_start_offset + in_start_offset, + in_size, + out_opt_data_ptr); } else { @@ -424,7 +499,7 @@ bool Anvil::MemoryBlock::map(VkDeviceSize in_start_offset, goto end; } - if ((m_memory_features & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) + if ((memory_features & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) { /* Make sure the mapped region is invalidated before letting the user read from it */ VkMappedMemoryRange mapped_memory_range; @@ -438,7 +513,7 @@ bool Anvil::MemoryBlock::map(VkDeviceSize in_start_offset, mapped_memory_range.size = in_size; mapped_memory_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - result_vk = vkInvalidateMappedMemoryRanges(m_device_ptr->get_device_vk(), + result_vk = vkInvalidateMappedMemoryRanges(m_create_info_ptr->get_device()->get_device_vk(), 1, /* memRangeCount */ &mapped_memory_range); anvil_assert_vk_call_succeeded(result_vk); @@ -465,15 +540,16 @@ bool Anvil::MemoryBlock::map(VkDeviceSize in_start_offset, **/ bool Anvil::MemoryBlock::open_gpu_memory_access() { - bool result (false); - VkResult result_vk; + const auto memory_features(m_create_info_ptr->get_memory_features() ); + bool result (false); + VkResult result_vk; /* Sanity checks */ - anvil_assert(m_parent_memory_block_ptr == nullptr); + anvil_assert(m_create_info_ptr->get_parent_memory_block() == nullptr); - if ((m_memory_features & Anvil::MEMORY_FEATURE_FLAG_MAPPABLE) == 0) + if ((memory_features & Anvil::MEMORY_FEATURE_FLAG_MAPPABLE) == 0) { - anvil_assert((m_memory_features & Anvil::MEMORY_FEATURE_FLAG_MAPPABLE) != 0); + anvil_assert((memory_features & Anvil::MEMORY_FEATURE_FLAG_MAPPABLE) != 0); goto end; } @@ -487,16 +563,16 @@ bool Anvil::MemoryBlock::open_gpu_memory_access() { result_vk = m_parent_memory_allocator_backend_ptr->map(m_backend_object, 0, /* in_start_offset */ - m_size, + m_create_info_ptr->get_size(), static_cast(&m_gpu_data_ptr) ); } else { /* This block will be entered for memory blocks instantiated without a memory allocator */ - result_vk = vkMapMemory(m_device_ptr->get_device_vk(), + result_vk = vkMapMemory(m_create_info_ptr->get_device()->get_device_vk(), m_memory, 0, /* offset */ - m_size, + m_create_info_ptr->get_size(), 0, /* flags */ static_cast(&m_gpu_data_ptr) ); } @@ -523,14 +599,14 @@ bool Anvil::MemoryBlock::read(VkDeviceSize in_start_offset, bool result(false); anvil_assert(in_size > 0); - anvil_assert(in_start_offset + in_size <= m_size); - anvil_assert(out_result_ptr != nullptr); + anvil_assert(in_start_offset + in_size <= m_create_info_ptr->get_size() ); + anvil_assert(out_result_ptr != nullptr); - if (m_parent_memory_block_ptr != nullptr) + if (m_create_info_ptr->get_parent_memory_block() != nullptr) { - result = m_parent_memory_block_ptr->read(m_start_offset + in_start_offset, - in_size, - out_result_ptr); + result = m_create_info_ptr->get_parent_memory_block()->read(m_start_offset + in_start_offset, + in_size, + out_result_ptr); } else { @@ -541,7 +617,7 @@ bool Anvil::MemoryBlock::read(VkDeviceSize in_start_offset, goto end; } - if ((m_memory_features & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) + if ((m_create_info_ptr->get_memory_features() & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) { VkMappedMemoryRange mapped_memory_range; VkResult result_vk (VK_ERROR_INITIALIZATION_FAILED); @@ -555,7 +631,7 @@ bool Anvil::MemoryBlock::read(VkDeviceSize in_start_offset, mapped_memory_range.size = in_size; mapped_memory_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - result_vk = vkInvalidateMappedMemoryRanges(m_device_ptr->get_device_vk(), + result_vk = vkInvalidateMappedMemoryRanges(m_create_info_ptr->get_device()->get_device_vk(), 1, /* memRangeCount */ &mapped_memory_range); anvil_assert_vk_call_succeeded(result_vk); @@ -579,9 +655,9 @@ bool Anvil::MemoryBlock::unmap() { bool result = false; - if (m_parent_memory_block_ptr != nullptr) + if (m_create_info_ptr->get_parent_memory_block() != nullptr) { - result = m_parent_memory_block_ptr->unmap(); + result = m_create_info_ptr->get_parent_memory_block()->unmap(); goto end; } @@ -611,14 +687,14 @@ bool Anvil::MemoryBlock::write(VkDeviceSize in_start_offset, bool result(false); anvil_assert(in_size > 0); - anvil_assert(in_start_offset + in_size <= in_start_offset + m_size); + anvil_assert(in_start_offset + in_size <= in_start_offset + m_create_info_ptr->get_size() ); anvil_assert(in_data != nullptr); - if (m_parent_memory_block_ptr != nullptr) + if (m_create_info_ptr->get_parent_memory_block() != nullptr) { - result = m_parent_memory_block_ptr->write(m_start_offset + in_start_offset, - in_size, - in_data); + result = m_create_info_ptr->get_parent_memory_block()->write(m_start_offset + in_start_offset, + in_size, + in_data); } else { @@ -631,7 +707,7 @@ bool Anvil::MemoryBlock::write(VkDeviceSize in_start_offset, in_data, static_cast(in_size)); - if ((m_memory_features & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) + if ((m_create_info_ptr->get_memory_features() & Anvil::MEMORY_FEATURE_FLAG_HOST_COHERENT) == 0) { VkMappedMemoryRange mapped_memory_range; VkResult result_vk (VK_ERROR_INITIALIZATION_FAILED); @@ -644,7 +720,7 @@ bool Anvil::MemoryBlock::write(VkDeviceSize in_start_offset, mapped_memory_range.size = in_size; mapped_memory_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - result_vk = vkFlushMappedMemoryRanges(m_device_ptr->get_device_vk(), + result_vk = vkFlushMappedMemoryRanges(m_create_info_ptr->get_device()->get_device_vk(), 1, /* memRangeCount */ &mapped_memory_range); anvil_assert_vk_call_succeeded(result_vk); diff --git a/src/wrappers/physical_device.cpp b/src/wrappers/physical_device.cpp index 2741b713..d998efd8 100644 --- a/src/wrappers/physical_device.cpp +++ b/src/wrappers/physical_device.cpp @@ -70,22 +70,15 @@ Anvil::PhysicalDevice::~PhysicalDevice() **/ bool Anvil::PhysicalDevice::init() { - const Anvil::ExtensionKHRGetPhysicalDeviceProperties2* gpdp2_entrypoints_ptr = nullptr; - VkPhysicalDeviceMemoryProperties memory_properties; - uint32_t n_extensions = 0; - uint32_t n_physical_device_layers = 0; - uint32_t n_physical_device_queues = 0; - bool result = true; - VkResult result_vk = VK_ERROR_INITIALIZATION_FAILED; - bool texture_gather_bias_lod_support = false; + VkPhysicalDeviceMemoryProperties memory_properties; + uint32_t n_extensions = 0; + uint32_t n_physical_device_layers = 0; + uint32_t n_physical_device_queues = 0; + bool result = true; + VkResult result_vk = VK_ERROR_INITIALIZATION_FAILED; anvil_assert(m_physical_device != VK_NULL_HANDLE); - if (m_instance_ptr->get_enabled_extensions_info()->khr_get_physical_device_properties2() ) - { - gpdp2_entrypoints_ptr = &m_instance_ptr->get_extension_khr_get_physical_device_properties2_entrypoints(); - } - /* Retrieve device extensions */ result_vk = vkEnumerateDeviceExtensionProperties(m_physical_device, nullptr, /* pLayerName */ @@ -234,69 +227,6 @@ bool Anvil::PhysicalDevice::init() m_khr_16_bit_storage_features_ptr.get () ); } - /* Retrieve device format properties */ - texture_gather_bias_lod_support = m_extension_info_ptr->get_device_extension_info()->amd_texture_gather_bias_lod(); - - for (VkFormat current_format = static_cast(1); /* skip the _UNDEFINED format */ - current_format < VK_FORMAT_RANGE_SIZE; - current_format = static_cast(current_format + 1)) - { - VkFormatProperties format_props; - - vkGetPhysicalDeviceFormatProperties(m_physical_device, - current_format, - &format_props); - - m_format_properties[current_format] = FormatProperties(format_props); - - /* Can this format be used with VK_AMD_texture_gather_bias_lod? */ - if (gpdp2_entrypoints_ptr != nullptr && - texture_gather_bias_lod_support) - { - VkPhysicalDeviceImageFormatInfo2KHR format_info; - Anvil::StructChainUniquePtr struct_chain_ptr; - Anvil::StructChainer struct_chainer; - Anvil::StructID texture_lod_gather_support_struct_id = UINT32_MAX; - - format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR; - format_info.pNext = nullptr; - format_info.format = current_format; - format_info.type = VK_IMAGE_TYPE_2D; // irrelevant - format_info.tiling = VK_IMAGE_TILING_LINEAR; // irrelevant - format_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; // irrelevant - format_info.flags = 0; // irrelevant - - { - VkImageFormatProperties2KHR image_format_props = {}; - - image_format_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR; - image_format_props.pNext = nullptr; - - struct_chainer.append_struct(image_format_props); - } - - { - VkTextureLODGatherFormatPropertiesAMD texture_lod_gather_support = {}; - - texture_lod_gather_support.sType = VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD; - texture_lod_gather_support.pNext = nullptr; - - texture_lod_gather_support_struct_id = struct_chainer.append_struct(texture_lod_gather_support); - } - - struct_chain_ptr = struct_chainer.create_chain(); - - if (gpdp2_entrypoints_ptr->vkGetPhysicalDeviceImageFormatProperties2KHR(m_physical_device, - &format_info, - struct_chain_ptr->get_root_struct() ) == VK_SUCCESS) - { - auto texture_lod_gather_support_ptr = struct_chain_ptr->get_struct_with_id(texture_lod_gather_support_struct_id); - - m_format_properties.at(current_format).supports_amd_texture_gather_bias_lod = (texture_lod_gather_support_ptr->supportsTextureGatherLODBiasAMD == VK_TRUE); - } - } - } - /* Retrieve additional device info */ if (m_instance_ptr->get_enabled_extensions_info()->khr_get_physical_device_properties2() ) { @@ -332,33 +262,9 @@ bool Anvil::PhysicalDevice::init() gpdp2_entrypoints.vkGetPhysicalDeviceProperties2KHR(m_physical_device, struct_chain_ptr->get_root_struct() ); - if (result_device_id_props_ptr->deviceLUIDValid) - { - static_assert(sizeof(m_device_LUID) == sizeof(result_device_id_props_ptr->deviceLUID), "Anvil asserts a LUID size different than the Vulkan header"); - - memcpy(m_device_LUID, - &result_device_id_props_ptr->deviceLUID, - sizeof(m_device_LUID) ); - - m_device_LUID_available = true; - } - else - { - m_device_LUID_available = false; - } - - static_assert(sizeof(m_device_UUID) == sizeof(result_device_id_props_ptr->deviceUUID), "Anvil asserts a UUID size different than the Vulkan header"); - static_assert(sizeof(m_driver_UUID) == sizeof(result_device_id_props_ptr->driverUUID), "Anvil asserts a UUID size different than the Vulkan header"); - - memcpy(m_device_UUID, - result_device_id_props_ptr->deviceUUID, - sizeof(m_device_UUID) ); - memcpy(m_driver_UUID, - result_device_id_props_ptr->driverUUID, - sizeof(m_driver_UUID) ); - - m_device_UUID_available = true; - m_driver_UUID_available = true; + m_khr_external_memory_capabilities_physical_device_id_properties_ptr.reset( + new KHRExternalMemoryCapabilitiesPhysicalDeviceIDProperties(*result_device_id_props_ptr) + ); } if (m_extension_info_ptr->get_device_extension_info()->amd_shader_core_properties() ) @@ -513,10 +419,11 @@ bool Anvil::PhysicalDevice::init() } } - m_properties = Anvil::PhysicalDeviceProperties(m_amd_shader_core_properties_ptr.get (), - m_core_properties_vk10_ptr.get (), - m_ext_descriptor_indexing_properties_ptr.get(), - m_khr_maintenance3_properties_ptr.get () ); + m_properties = Anvil::PhysicalDeviceProperties(m_amd_shader_core_properties_ptr.get (), + m_core_properties_vk10_ptr.get (), + m_ext_descriptor_indexing_properties_ptr.get (), + m_khr_external_memory_capabilities_physical_device_id_properties_ptr.get(), + m_khr_maintenance3_properties_ptr.get () ); /* Retrieve device queue data */ vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, @@ -590,6 +497,276 @@ bool Anvil::PhysicalDevice::init() return result; } +bool Anvil::PhysicalDevice::get_buffer_format_properties(const Anvil::BufferFormatPropertiesQuery& in_query, + Anvil::BufferFormatProperties* out_opt_result_ptr) const +{ + const Anvil::ExtensionKHRExternalMemoryCapabilitiesEntrypoints* emc_entrypoints_ptr = nullptr; + VkPhysicalDeviceExternalBufferInfoKHR input_struct; + VkExternalBufferPropertiesKHR result_struct; + bool result = false; + + if (!m_instance_ptr->get_enabled_extensions_info()->khr_external_memory_capabilities() ) + { + anvil_assert(m_instance_ptr->get_enabled_extensions_info()->khr_external_memory_capabilities() ); + + goto end; + } + else + { + emc_entrypoints_ptr = &m_instance_ptr->get_extension_khr_external_memory_capabilities_entrypoints(); + } + + input_struct.flags = Anvil::Utils::convert_buffer_create_flags_to_vk_buffer_create_flags(in_query.create_flags); + input_struct.handleType = static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(in_query.external_memory_handle_type) ); + input_struct.pNext = nullptr; + input_struct.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR; + input_struct.usage = in_query.usage_flags; + + result_struct.pNext = nullptr; + result_struct.sType = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR; + + emc_entrypoints_ptr->vkGetPhysicalDeviceExternalBufferPropertiesKHR(m_physical_device, + &input_struct, + &result_struct); + + if (out_opt_result_ptr != nullptr) + { + *out_opt_result_ptr = std::move(Anvil::BufferFormatProperties(ExternalMemoryProperties(result_struct.externalMemoryProperties) )); + } + + /* All done */ + result = true; + +end: + return result; +} + +bool Anvil::PhysicalDevice::get_fence_properties(const Anvil::FencePropertiesQuery& in_query, + Anvil::FenceProperties* out_opt_result_ptr) const +{ + const Anvil::ExtensionKHRExternalFenceCapabilitiesEntrypoints* entrypoints_ptr = nullptr; + VkPhysicalDeviceExternalFenceInfoKHR input_struct; + VkExternalFencePropertiesKHR result_struct; + bool result = false; + + if (!m_instance_ptr->get_enabled_extensions_info()->khr_external_fence_capabilities() ) + { + anvil_assert(m_instance_ptr->get_enabled_extensions_info()->khr_external_fence_capabilities() ); + + goto end; + } + else + { + entrypoints_ptr = &m_instance_ptr->get_extension_khr_external_fence_capabilities_entrypoints(); + } + + input_struct.handleType = static_cast(Anvil::Utils::convert_external_fence_handle_type_bits_to_vk_external_fence_handle_type_flags(in_query.external_fence_handle_type) ); + input_struct.pNext = nullptr; + input_struct.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR; + + result_struct.pNext = nullptr; + result_struct.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR; + + entrypoints_ptr->vkGetPhysicalDeviceExternalFencePropertiesKHR(m_physical_device, + &input_struct, + &result_struct); + + if (out_opt_result_ptr != nullptr) + { + *out_opt_result_ptr = std::move(Anvil::FenceProperties(ExternalFenceProperties(result_struct) )); + } + + /* All done */ + result = true; + +end: + return result; +} + +Anvil::FormatProperties Anvil::PhysicalDevice::get_format_properties(VkFormat in_format) const +{ + VkFormatProperties core_vk10_format_props; + + vkGetPhysicalDeviceFormatProperties(m_physical_device, + in_format, + &core_vk10_format_props); + + return Anvil::FormatProperties(core_vk10_format_props); +} + +/* Please see header for specification */ +bool Anvil::PhysicalDevice::get_image_format_properties(const ImageFormatPropertiesQuery& in_query, + Anvil::ImageFormatProperties* out_opt_result_ptr) const +{ + VkFormatProperties core_vk10_format_props; + VkImageFormatProperties core_vk10_image_format_properties; + Anvil::ExternalMemoryProperties external_handle_props; + const Anvil::ExtensionKHRGetPhysicalDeviceProperties2* gpdp2_entrypoints_ptr = nullptr; + bool result = false; + bool supports_amd_texture_gather_bias_lod = false; + + if (m_instance_ptr->get_enabled_extensions_info()->khr_get_physical_device_properties2() ) + { + gpdp2_entrypoints_ptr = &m_instance_ptr->get_extension_khr_get_physical_device_properties2_entrypoints(); + } + + /* Retrieve core VK1.0 information first. */ + vkGetPhysicalDeviceFormatProperties (m_physical_device, + in_query.format, + &core_vk10_format_props); + vkGetPhysicalDeviceImageFormatProperties(m_physical_device, + in_query.format, + in_query.image_type, + in_query.tiling, + in_query.usage_flags, + in_query.create_flags, + &core_vk10_image_format_properties); + + if (gpdp2_entrypoints_ptr != nullptr) + { + Anvil::StructID external_image_format_props_struct_id = UINT32_MAX; + Anvil::StructChainer input_struct_chainer; + auto instance_extensions_ptr = m_instance_ptr->get_enabled_extensions_info(); + Anvil::StructChainer output_struct_chainer; + Anvil::StructID texture_lod_gather_support_struct_id = UINT32_MAX; + + ANVIL_REDUNDANT_VARIABLE(instance_extensions_ptr); + + { + VkPhysicalDeviceImageFormatInfo2KHR format_info; + + format_info.flags = in_query.create_flags; + format_info.format = in_query.format; + format_info.pNext = nullptr; + format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR; + format_info.tiling = in_query.tiling; + format_info.type = in_query.image_type; + format_info.usage = in_query.usage_flags; + + input_struct_chainer.append_struct(format_info); + } + + { + VkImageFormatProperties2KHR image_format_props = {}; + + image_format_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR; + image_format_props.pNext = nullptr; + + output_struct_chainer.append_struct(image_format_props); + } + + if (m_extension_info_ptr->get_device_extension_info()->amd_texture_gather_bias_lod() ) + { + VkTextureLODGatherFormatPropertiesAMD texture_lod_gather_support = {}; + + texture_lod_gather_support.sType = VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD; + texture_lod_gather_support.pNext = nullptr; + + texture_lod_gather_support_struct_id = output_struct_chainer.append_struct(texture_lod_gather_support); + } + + if (in_query.external_memory_handle_type != EXTERNAL_MEMORY_HANDLE_TYPE_NONE) + { + anvil_assert(instance_extensions_ptr->khr_external_memory_capabilities() ); + + VkPhysicalDeviceExternalImageFormatInfoKHR external_image_format_info; + VkExternalImageFormatPropertiesKHR external_image_format_props; + + external_image_format_info.handleType = static_cast(Anvil::Utils::convert_external_memory_handle_type_bits_to_vk_external_memory_handle_type_flags(in_query.external_memory_handle_type) ); + external_image_format_info.pNext = nullptr; + external_image_format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR; + + external_image_format_props.pNext = nullptr; + external_image_format_props.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR; + + input_struct_chainer.append_struct(external_image_format_info); + + external_image_format_props_struct_id = output_struct_chainer.append_struct(external_image_format_props); + } + + auto input_struct_chain_ptr = input_struct_chainer.create_chain (); + auto output_struct_chain_ptr = output_struct_chainer.create_chain(); + + if (gpdp2_entrypoints_ptr->vkGetPhysicalDeviceImageFormatProperties2KHR(m_physical_device, + input_struct_chain_ptr->get_root_struct (), + output_struct_chain_ptr->get_root_struct() ) == VK_SUCCESS) + { + if (m_extension_info_ptr->get_device_extension_info()->amd_texture_gather_bias_lod() ) + { + /* Can this format be used with AMD_texture_lod_gather_bias? */ + auto texture_lod_gather_support_ptr = output_struct_chain_ptr->get_struct_with_id(texture_lod_gather_support_struct_id); + + supports_amd_texture_gather_bias_lod = (texture_lod_gather_support_ptr->supportsTextureGatherLODBiasAMD == VK_TRUE); + } + + if (in_query.external_memory_handle_type != EXTERNAL_MEMORY_HANDLE_TYPE_NONE) + { + auto image_format_props_ptr = output_struct_chain_ptr->get_struct_with_id(external_image_format_props_struct_id); + + external_handle_props = Anvil::ExternalMemoryProperties(image_format_props_ptr->externalMemoryProperties); + } + } + else + { + goto end; + } + } + + if (out_opt_result_ptr != nullptr) + { + *out_opt_result_ptr = Anvil::ImageFormatProperties(core_vk10_image_format_properties, + supports_amd_texture_gather_bias_lod, + external_handle_props); + } + + result = true; +end: + return result; +} + +/* Please see header for specification */ +bool Anvil::PhysicalDevice::get_semaphore_properties(const Anvil::SemaphorePropertiesQuery& in_query, + Anvil::SemaphoreProperties* out_opt_result_ptr) const +{ + const Anvil::ExtensionKHRExternalSemaphoreCapabilitiesEntrypoints* entrypoints_ptr = nullptr; + VkPhysicalDeviceExternalSemaphoreInfoKHR input_struct; + VkExternalSemaphorePropertiesKHR result_struct; + bool result = false; + + if (!m_instance_ptr->get_enabled_extensions_info()->khr_external_semaphore_capabilities() ) + { + anvil_assert(m_instance_ptr->get_enabled_extensions_info()->khr_external_semaphore_capabilities() ); + + goto end; + } + else + { + entrypoints_ptr = &m_instance_ptr->get_extension_khr_external_semaphore_capabilities_entrypoints(); + } + + input_struct.handleType = static_cast(Anvil::Utils::convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(in_query.external_semaphore_handle_type) ); + input_struct.pNext = nullptr; + input_struct.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR; + + result_struct.pNext = nullptr; + result_struct.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR; + + entrypoints_ptr->vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(m_physical_device, + &input_struct, + &result_struct); + + if (out_opt_result_ptr != nullptr) + { + *out_opt_result_ptr = std::move(Anvil::SemaphoreProperties(ExternalSemaphoreProperties(result_struct) )); + } + + /* All done */ + result = true; + +end: + return result; +} + /* Please see header for specification */ bool Anvil::PhysicalDevice::get_sparse_image_format_properties(VkFormat in_format, VkImageType in_type, diff --git a/src/wrappers/query_pool.cpp b/src/wrappers/query_pool.cpp index 3e6fd8af..baf8a8c3 100644 --- a/src/wrappers/query_pool.cpp +++ b/src/wrappers/query_pool.cpp @@ -36,7 +36,8 @@ Anvil::QueryPool::QueryPool(const Anvil::BaseDevice* in_device_ptr, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT), MTSafetySupportProvider (in_mt_safe), m_device_ptr (in_device_ptr), - m_n_max_indices (in_n_max_concurrent_queries) + m_n_max_indices (in_n_max_concurrent_queries), + m_query_type (in_query_type) { anvil_assert(in_query_type == VK_QUERY_TYPE_OCCLUSION || in_query_type == VK_QUERY_TYPE_TIMESTAMP); @@ -60,7 +61,8 @@ Anvil::QueryPool::QueryPool(const Anvil::BaseDevice* in_device_ptr, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT), MTSafetySupportProvider (in_mt_safe), m_device_ptr (in_device_ptr), - m_n_max_indices (in_n_max_concurrent_queries) + m_n_max_indices (in_n_max_concurrent_queries), + m_query_type (in_query_type) { init(in_query_type, in_query_flags, @@ -136,6 +138,84 @@ Anvil::QueryPoolUniquePtr Anvil::QueryPool::create_ps_query_pool(const Anvil::Ba return result_ptr; } +bool Anvil::QueryPool::get_query_pool_results_internal(const uint32_t& in_first_query_index, + const uint32_t& in_n_queries, + const QueryResultBits& in_query_props, + const bool& in_should_return_uint64, + void* out_results_ptr, + bool* out_all_query_results_retrieved_ptr) +{ + VkQueryResultFlags flags = 0; + uint32_t result_query_size = 0; + bool result = false; + VkResult result_vk; + + if (in_first_query_index + in_n_queries > m_n_max_indices) + { + anvil_assert(in_first_query_index + in_n_queries <= m_n_max_indices); + + goto end; + } + + if (in_should_return_uint64) + { + flags |= VK_QUERY_RESULT_64_BIT; + result_query_size = sizeof(uint64_t); + } + else + { + result_query_size = sizeof(uint32_t); + } + + if (in_query_props & Anvil::QUERY_RESULT_PARTIAL_BIT) + { + flags |= VK_QUERY_RESULT_PARTIAL_BIT; + + if (m_query_type == VK_QUERY_TYPE_TIMESTAMP) + { + anvil_assert(m_query_type != VK_QUERY_TYPE_TIMESTAMP); + + goto end; + } + } + + if (in_query_props & Anvil::QUERY_RESULT_WAIT_BIT) + { + flags |= VK_QUERY_RESULT_WAIT_BIT; + } + + if (in_query_props & Anvil::QUERY_RESULT_WITH_AVAILABILITY_BIT) + { + flags |= VK_QUERY_RESULT_WITH_AVAILABILITY_BIT; + result_query_size *= 2; + } + + /* Execute the request */ + result_vk = vkGetQueryPoolResults(m_device_ptr->get_device_vk(), + m_query_pool_vk, + in_first_query_index, + in_n_queries, + result_query_size * in_n_queries, + out_results_ptr, + (in_should_return_uint64) ? sizeof(uint64_t) : sizeof(uint32_t), + flags); + + if (in_query_props & Anvil::QUERY_RESULT_PARTIAL_BIT) + { + result = is_vk_call_successful(result_vk); + *out_all_query_results_retrieved_ptr = (result_vk == VK_SUCCESS); + } + else + { + result = is_vk_call_successful(result_vk); + *out_all_query_results_retrieved_ptr = (result); + } + + /* All done */ +end: + return result; +} + /* Please see header for specification */ void Anvil::QueryPool::init(VkQueryType in_query_type, VkFlags in_query_flags, diff --git a/src/wrappers/queue.cpp b/src/wrappers/queue.cpp index b0645dd1..b52c0f0d 100644 --- a/src/wrappers/queue.cpp +++ b/src/wrappers/queue.cpp @@ -438,11 +438,15 @@ VkResult Anvil::Queue::present(Anvil::Swapchain* in_swapchain_ptr, { static const VkPipelineStageFlags dst_stage_mask(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - m_device_ptr->get_universal_queue(0)->submit_command_buffer_with_wait_semaphores(nullptr, /* cmd_buffer_ptr */ - in_n_wait_semaphores, - in_wait_semaphore_ptrs, - &dst_stage_mask, - true); /* should_block */ + m_device_ptr->get_universal_queue(0)->submit( + SubmitInfo::create(nullptr, + 0, /* in_n_semaphores_to_signal */ + nullptr, /* in_opt_semaphore_to_signal_ptrs_ptr */ + in_n_wait_semaphores, + in_wait_semaphore_ptrs, + &dst_stage_mask, + true) /* in_should_block */ + ); for (uint32_t n_presentation = 0; n_presentation < 1; @@ -630,77 +634,126 @@ void Anvil::Queue::present_lock_unlock(uint32_t in_n_swapc } /** Please see header for specification */ -void Anvil::Queue::submit_command_buffers(uint32_t in_n_command_buffers, - Anvil::CommandBufferBase* const* in_opt_cmd_buffer_ptrs, - uint32_t in_n_semaphores_to_signal, - Anvil::Semaphore* const* in_opt_semaphore_to_signal_ptr_ptrs, - uint32_t in_n_semaphores_to_wait_on, - Anvil::Semaphore* const* in_opt_semaphore_to_wait_on_ptr_ptrs, - const VkPipelineStageFlags* in_opt_dst_stage_masks_to_wait_on_ptrs, - bool in_should_block, - Anvil::Fence* in_opt_fence_ptr) +void Anvil::Queue::submit(const Anvil::SubmitInfo& in_submit_info) { - bool needs_fence_reset(false); - VkResult result (VK_ERROR_INITIALIZATION_FAILED); - VkSubmitInfo submit_info; + Anvil::Fence* fence_ptr (in_submit_info.get_fence() ); + bool needs_fence_reset(false); + VkResult result (VK_ERROR_INITIALIZATION_FAILED); + Anvil::StructChainer struct_chainer; - std::vector cmd_buffers_vk (in_n_command_buffers); - std::vector signal_semaphores_vk(in_n_semaphores_to_signal); - std::vector wait_semaphores_vk (in_n_semaphores_to_wait_on); + std::vector cmd_buffers_vk (in_submit_info.get_n_command_buffers () ); + std::vector signal_semaphores_vk(in_submit_info.get_n_signal_semaphores() ); + std::vector wait_semaphores_vk (in_submit_info.get_n_wait_semaphores () ); ANVIL_REDUNDANT_VARIABLE(result); /* Prepare for the submission */ - for (uint32_t n_command_buffer = 0; - n_command_buffer < in_n_command_buffers; - ++n_command_buffer) + switch (in_submit_info.get_type() ) { - cmd_buffers_vk.at(n_command_buffer) = in_opt_cmd_buffer_ptrs[n_command_buffer]->get_command_buffer(); + case SubmissionType::SGPU: + { + VkSubmitInfo submit_info; + + for (uint32_t n_command_buffer = 0; + n_command_buffer < in_submit_info.get_n_command_buffers(); + ++n_command_buffer) + { + cmd_buffers_vk.at(n_command_buffer) = in_submit_info.get_command_buffers_sgpu()[n_command_buffer]->get_command_buffer(); + } + + for (uint32_t n_signal_semaphore = 0; + n_signal_semaphore < in_submit_info.get_n_signal_semaphores(); + ++n_signal_semaphore) + { + auto sem_ptr = in_submit_info.get_signal_semaphores_sgpu()[n_signal_semaphore]; + + signal_semaphores_vk.at(n_signal_semaphore) = sem_ptr->get_semaphore(); + } + + for (uint32_t n_wait_semaphore = 0; + n_wait_semaphore < in_submit_info.get_n_wait_semaphores(); + ++n_wait_semaphore) + { + wait_semaphores_vk.at(n_wait_semaphore) = in_submit_info.get_wait_semaphores_sgpu()[n_wait_semaphore]->get_semaphore(); + } + + submit_info.commandBufferCount = in_submit_info.get_n_command_buffers (); + submit_info.pCommandBuffers = (in_submit_info.get_n_command_buffers() != 0) ? &cmd_buffers_vk.at(0) : nullptr; + submit_info.pNext = nullptr; + submit_info.pSignalSemaphores = (in_submit_info.get_n_signal_semaphores() != 0) ? &signal_semaphores_vk.at(0) : nullptr; + submit_info.pWaitDstStageMask = in_submit_info.get_destination_stage_wait_masks(); + submit_info.pWaitSemaphores = (in_submit_info.get_n_wait_semaphores() != 0) ? &wait_semaphores_vk.at(0) : nullptr; + submit_info.signalSemaphoreCount = in_submit_info.get_n_signal_semaphores(); + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.waitSemaphoreCount = in_submit_info.get_n_wait_semaphores(); + + struct_chainer.append_struct(submit_info); + + break; + } + + default: + { + anvil_assert_fail(); + } } - for (uint32_t n_signal_semaphore = 0; - n_signal_semaphore < in_n_semaphores_to_signal; - ++n_signal_semaphore) + /* Any additional structs to chain? */ + #if defined(_WIN32) { - auto sem_ptr = in_opt_semaphore_to_signal_ptr_ptrs[n_signal_semaphore]; + const uint64_t* d3d12_fence_signal_semaphore_values_ptr = nullptr; + const uint64_t* d3d12_fence_wait_semaphore_values_ptr = nullptr; + + if (in_submit_info.get_d3d12_fence_semaphore_values(&d3d12_fence_signal_semaphore_values_ptr, + &d3d12_fence_wait_semaphore_values_ptr) ) + { + VkD3D12FenceSubmitInfoKHR fence_info; + + fence_info.pNext = nullptr; + fence_info.pSignalSemaphoreValues = d3d12_fence_signal_semaphore_values_ptr; + fence_info.pWaitSemaphoreValues = d3d12_fence_wait_semaphore_values_ptr; + fence_info.signalSemaphoreValuesCount = in_submit_info.get_n_signal_semaphores(); + fence_info.sType = VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR; + fence_info.waitSemaphoreValuesCount = in_submit_info.get_n_wait_semaphores(); - signal_semaphores_vk.at(n_signal_semaphore) = sem_ptr->get_semaphore(); + struct_chainer.append_struct(fence_info); + } } + #endif - for (uint32_t n_wait_semaphore = 0; - n_wait_semaphore < in_n_semaphores_to_wait_on; - ++n_wait_semaphore) + /* Go for it */ + if (fence_ptr == nullptr && + in_submit_info.get_should_block() ) { - wait_semaphores_vk.at(n_wait_semaphore) = in_opt_semaphore_to_wait_on_ptr_ptrs[n_wait_semaphore]->get_semaphore(); + fence_ptr = m_submit_fence_ptr.get(); + needs_fence_reset = true; } - submit_info.commandBufferCount = in_n_command_buffers; - submit_info.pCommandBuffers = (in_n_command_buffers != 0) ? &cmd_buffers_vk.at(0) : nullptr; - submit_info.pNext = nullptr; - submit_info.pSignalSemaphores = (in_n_semaphores_to_signal != 0) ? &signal_semaphores_vk.at(0) : nullptr; - submit_info.pWaitDstStageMask = in_opt_dst_stage_masks_to_wait_on_ptrs; - submit_info.pWaitSemaphores = (in_n_semaphores_to_wait_on != 0) ? &wait_semaphores_vk.at(0) : nullptr; - submit_info.signalSemaphoreCount = in_n_semaphores_to_signal; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.waitSemaphoreCount = in_n_semaphores_to_wait_on; - - /* Go for it */ - if (in_opt_fence_ptr == nullptr && - in_should_block) - { - in_opt_fence_ptr = m_submit_fence_ptr.get(); - needs_fence_reset = true; + switch (in_submit_info.get_type() ) + { + case SubmissionType::SGPU: + { + submit_command_buffers_lock_unlock(in_submit_info.get_n_command_buffers (), + in_submit_info.get_command_buffers_sgpu (), + in_submit_info.get_n_signal_semaphores (), + in_submit_info.get_signal_semaphores_sgpu(), + in_submit_info.get_n_wait_semaphores (), + in_submit_info.get_wait_semaphores_sgpu (), + fence_ptr, + true); /* in_should_lock */ + + break; + } + + default: + { + anvil_assert_fail(); + } } - submit_command_buffers_lock_unlock(in_n_command_buffers, - in_opt_cmd_buffer_ptrs, - in_n_semaphores_to_signal, - in_opt_semaphore_to_signal_ptr_ptrs, - in_n_semaphores_to_wait_on, - in_opt_semaphore_to_wait_on_ptr_ptrs, - in_opt_fence_ptr, - true); /* in_should_lock */ { + auto chain_ptr = struct_chainer.create_chain(); + if (needs_fence_reset) { m_submit_fence_ptr->reset(); @@ -708,31 +761,44 @@ void Anvil::Queue::submit_command_buffers(uint32_t in_n_ result = vkQueueSubmit(m_queue, 1, /* submitCount */ - &submit_info, - (in_opt_fence_ptr != nullptr) ? in_opt_fence_ptr->get_fence() - : VK_NULL_HANDLE); + chain_ptr->get_root_struct(), + (fence_ptr != nullptr) ? fence_ptr->get_fence() + : VK_NULL_HANDLE); - if (in_should_block) + if (in_submit_info.get_should_block() ) { /* Wait till initialization finishes GPU-side */ result = vkWaitForFences(m_device_ptr->get_device_vk(), 1, /* fenceCount */ - in_opt_fence_ptr->get_fence_ptr(), + fence_ptr->get_fence_ptr(), VK_TRUE, /* waitAll */ UINT64_MAX); /* timeout */ anvil_assert_vk_call_succeeded(result); } } - submit_command_buffers_lock_unlock(in_n_command_buffers, - in_opt_cmd_buffer_ptrs, - in_n_semaphores_to_signal, - in_opt_semaphore_to_signal_ptr_ptrs, - in_n_semaphores_to_wait_on, - in_opt_semaphore_to_wait_on_ptr_ptrs, - in_opt_fence_ptr, - false); /* in_should_lock */ + switch (in_submit_info.get_type() ) + { + case SubmissionType::SGPU: + { + submit_command_buffers_lock_unlock(in_submit_info.get_n_command_buffers (), + in_submit_info.get_command_buffers_sgpu (), + in_submit_info.get_n_signal_semaphores (), + in_submit_info.get_signal_semaphores_sgpu(), + in_submit_info.get_n_wait_semaphores (), + in_submit_info.get_wait_semaphores_sgpu (), + fence_ptr, + false); /* in_should_lock */ + + break; + } + + default: + { + anvil_assert_fail(); + } + } anvil_assert_vk_call_succeeded(result); } diff --git a/src/wrappers/semaphore.cpp b/src/wrappers/semaphore.cpp index ef2fe93f..c667b1b5 100644 --- a/src/wrappers/semaphore.cpp +++ b/src/wrappers/semaphore.cpp @@ -21,11 +21,14 @@ // #include "misc/debug.h" +#include "misc/external_handle.h" #include "misc/object_tracker.h" #include "misc/semaphore_create_info.h" +#include "misc/struct_chainer.h" #include "wrappers/device.h" #include "wrappers/semaphore.h" + /* Please see header for specification */ Anvil::Semaphore::Semaphore(Anvil::SemaphoreCreateInfoUniquePtr in_create_info_ptr) :DebugMarkerSupportProvider(in_create_info_ptr->get_device(), @@ -70,6 +73,199 @@ Anvil::SemaphoreUniquePtr Anvil::Semaphore::create(Anvil::SemaphoreCreateInfoUni return result_ptr; } +/* Please see header for specification */ +Anvil::ExternalHandleUniquePtr Anvil::Semaphore::export_to_external_handle(const Anvil::ExternalSemaphoreHandleTypeBit& in_semaphore_handle_type) +{ + #if defined(_WIN32) + const auto invalid_handle = nullptr; + const bool is_autorelease_handle = Anvil::Utils::is_nt_handle(in_semaphore_handle_type); + const bool only_one_handle_ever_permitted = Anvil::Utils::is_nt_handle(in_semaphore_handle_type); + #else + const int invalid_handle = -1; + const bool is_autorelease_handle = true; + const bool only_one_handle_ever_permitted = false; + #endif + + ExternalHandleType result_handle = invalid_handle; + Anvil::ExternalHandleUniquePtr result_ptr; + + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_semaphore_win32() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_semaphore_win32() ); + + goto end; + } + } + #else + { + if (!m_create_info_ptr->get_device()->get_extension_info()->khr_external_semaphore_fd() ) + { + anvil_assert(m_create_info_ptr->get_device()->get_extension_info()->khr_external_semaphore_fd() ); + + goto end; + } + } + #endif + + if (only_one_handle_ever_permitted && + m_external_semaphore_created_for_handle_type.find(in_semaphore_handle_type) != m_external_semaphore_created_for_handle_type.end() ) + { + anvil_assert_fail(); + + goto end; + } + + /* Go and try to open a new handle. */ + { + #if defined(_WIN32) + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_semaphore_win32_entrypoints(); + VkSemaphoreGetWin32HandleInfoKHR info; + #else + const auto entrypoints_ptr = &m_create_info_ptr->get_device()->get_extension_khr_external_semaphore_fd_entrypoints(); + VkSemaphoreGetFdInfoKHR info; + #endif + + + anvil_assert(m_semaphore != VK_NULL_HANDLE); + + info.handleType = static_cast(Anvil::Utils::convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(in_semaphore_handle_type) ); + info.pNext = nullptr; + info.semaphore = m_semaphore; + + #if defined(_WIN32) + { + info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR; + } + #else + { + info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR; + } + #endif + + #if defined(_WIN32) + if (entrypoints_ptr->vkGetSemaphoreWin32HandleKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + #else + if (entrypoints_ptr->vkGetSemaphoreFdKHR(m_create_info_ptr->get_device()->get_device_vk(), + &info, + &result_handle) != VK_SUCCESS) + #endif + { + anvil_assert_fail(); + + goto end; + } + + if (result_handle == invalid_handle) + { + anvil_assert(result_handle != invalid_handle); + + goto end; + } + } + + /* Cache the newly created handle if it's a NT handle */ + if (only_one_handle_ever_permitted) + { + m_external_semaphore_created_for_handle_type[in_semaphore_handle_type] = true; + } + + result_ptr = Anvil::ExternalHandle::create(result_handle, + is_autorelease_handle); /* in_close_at_destruction_time */ + +end: + return result_ptr; +} + +#if defined(_WIN32) + bool Anvil::Semaphore::import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalSemaphoreHandleTypeBit& in_handle_type, + const ExternalHandleType& in_opt_handle, + const std::wstring& in_opt_name) +#else + bool Anvil::Semaphore::import_from_external_handle(const bool& in_temporary_import, + const Anvil::ExternalSemaphoreHandleTypeBit& in_handle_type, + const ExternalHandleType& in_handle) +#endif +{ + #if defined(_WIN32) + const auto entrypoints_ptr = &m_device_ptr->get_extension_khr_external_semaphore_win32_entrypoints(); + #else + const auto entrypoints_ptr = &m_device_ptr->get_extension_khr_external_semaphore_fd_entrypoints(); + #endif + + bool result = false; + + /* Sanity checks */ + #if defined(_WIN32) + { + if (!m_device_ptr->get_extension_info()->khr_external_semaphore_win32() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_semaphore_win32() ); + + goto end; + } + } + #else + { + if (!m_device_ptr->get_extension_info()->khr_external_semaphore_fd() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_semaphore_fd() ); + + goto end; + } + } + #endif + + /* Proceed */ + { + #if defined(_WIN32) + VkImportSemaphoreWin32HandleInfoKHR info_vk; + #else + VkImportSemaphoreFdInfoKHR info_vk; + #endif + + info_vk.flags = (in_temporary_import) ? VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR + : 0; + info_vk.handleType = static_cast(Anvil::Utils::convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(in_handle_type) ); + info_vk.pNext = nullptr; + info_vk.semaphore = m_semaphore; + + #if defined(_WIN32) + { + info_vk.handle = in_opt_handle; + info_vk.name = (in_opt_name.size() > 0) ? &in_opt_name.at(0) + : nullptr; + info_vk.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR; + } + #else + { + info_vk.fd = in_handle; + info_vk.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; + } + #endif + + #if defined(_WIN32) + { + result = (entrypoints_ptr->vkImportSemaphoreWin32HandleKHR(m_device_ptr->get_device_vk(), + &info_vk) == VK_SUCCESS); + } + #else + { + result = (entrypoints_ptr->vkImportSemaphoreFdKHR(m_device_ptr->get_device_vk(), + &info_vk) == VK_SUCCESS); + } + #endif + } + +end: + return result; +} + /** Destroys the underlying Vulkan Semaphore instance. */ void Anvil::Semaphore::release_semaphore() { @@ -91,20 +287,55 @@ void Anvil::Semaphore::release_semaphore() /* Please see header for specification */ bool Anvil::Semaphore::reset() { - VkResult result (VK_ERROR_INITIALIZATION_FAILED); - VkSemaphoreCreateInfo semaphore_create_info; - - ANVIL_REDUNDANT_VARIABLE(result); + VkResult result (VK_ERROR_INITIALIZATION_FAILED); + Anvil::StructChainer struct_chainer; + Anvil::StructChainUniquePtr struct_chain_ptr; release_semaphore(); + /* Sanity checks */ + if (m_create_info_ptr->get_exportable_external_semaphore_handle_types() != Anvil::EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE) + { + if (!m_device_ptr->get_extension_info()->khr_external_semaphore() ) + { + anvil_assert(m_device_ptr->get_extension_info()->khr_external_semaphore() ); + + goto end; + } + } + /* Spawn a new semaphore */ - semaphore_create_info.flags = 0; - semaphore_create_info.pNext = nullptr; - semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + { + VkSemaphoreCreateInfo semaphore_create_info; + + semaphore_create_info.flags = 0; + semaphore_create_info.pNext = nullptr; + semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + struct_chainer.append_struct(semaphore_create_info); + } + + if (m_create_info_ptr->get_exportable_external_semaphore_handle_types() != Anvil::EXTERNAL_FENCE_HANDLE_TYPE_NONE) + { + VkExportSemaphoreCreateInfo create_info; + + create_info.handleTypes = Anvil::Utils::convert_external_semaphore_handle_type_bits_to_vk_external_semaphore_handle_type_flags(m_create_info_ptr->get_exportable_external_semaphore_handle_types() ); + create_info.pNext = nullptr; + create_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR; + + struct_chainer.append_struct(create_info); + } + + struct_chain_ptr = struct_chainer.create_chain(); + if (struct_chain_ptr == nullptr) + { + anvil_assert(struct_chain_ptr != nullptr); + + goto end; + } result = vkCreateSemaphore(m_device_ptr->get_device_vk(), - &semaphore_create_info, + struct_chain_ptr->get_root_struct(), nullptr, /* pAllocator */ &m_semaphore); @@ -114,5 +345,6 @@ bool Anvil::Semaphore::reset() set_vk_handle(m_semaphore); } +end: return is_vk_call_successful(result); } \ No newline at end of file diff --git a/src/wrappers/swapchain.cpp b/src/wrappers/swapchain.cpp index b3c12837..b6cb4dc3 100644 --- a/src/wrappers/swapchain.cpp +++ b/src/wrappers/swapchain.cpp @@ -170,10 +170,10 @@ uint32_t Anvil::Swapchain::acquire_image(Anvil::Semaphore* in_opt_semaphore_ptr, if (in_opt_semaphore_ptr != nullptr) { /* We need to set the semaphore manually in this scenario */ - m_device_ptr->get_universal_queue(0)->submit_command_buffer_with_signal_semaphores(nullptr, /* cmd_buffer_ptr */ - 1, /* n_semaphores_to_signal */ - &in_opt_semaphore_ptr, - true); /* should_block */ + m_device_ptr->get_universal_queue(0)->submit( + Anvil::SubmitInfo::create_signal(1, /* n_semaphores_to_signal */ + &in_opt_semaphore_ptr) + ); } result = m_n_acquire_counter_rounded;