diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index a6cfe3e0365..b6157dc8659 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -228,6 +228,7 @@ set(VULKAN_SRC vulkan/vk_storage_buffer.cc vulkan/vk_texture.cc vulkan/vk_timeline_semaphore.cc + vulkan/vk_to_string.cc vulkan/vk_uniform_buffer.cc vulkan/vk_vertex_attribute_object.cc vulkan/vk_vertex_buffer.cc @@ -269,6 +270,7 @@ set(VULKAN_SRC vulkan/vk_storage_buffer.hh vulkan/vk_texture.hh vulkan/vk_timeline_semaphore.hh + vulkan/vk_to_string.hh vulkan/vk_uniform_buffer.hh vulkan/vk_vertex_attribute_object.hh vulkan/vk_vertex_buffer.hh diff --git a/source/blender/gpu/vulkan/vk_common.cc b/source/blender/gpu/vulkan/vk_common.cc index d835897a1e0..4671c67c2e0 100644 --- a/source/blender/gpu/vulkan/vk_common.cc +++ b/source/blender/gpu/vulkan/vk_common.cc @@ -870,109 +870,4 @@ VkSamplerAddressMode to_vk_sampler_address_mode(const GPUSamplerExtendMode exten return VK_SAMPLER_ADDRESS_MODE_REPEAT; } -const char *to_string(VkObjectType type) -{ - - switch (type) { - case VK_OBJECT_TYPE_UNKNOWN: - return STRINGIFY_ARG(VK_OBJECT_TYPE_UNKNOWN); - case VK_OBJECT_TYPE_INSTANCE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_INSTANCE); - case VK_OBJECT_TYPE_PHYSICAL_DEVICE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PHYSICAL_DEVICE); - case VK_OBJECT_TYPE_DEVICE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DEVICE); - case VK_OBJECT_TYPE_QUEUE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_QUEUE); - case VK_OBJECT_TYPE_SEMAPHORE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SEMAPHORE); - case VK_OBJECT_TYPE_COMMAND_BUFFER: - return STRINGIFY_ARG(VK_OBJECT_TYPE_COMMAND_BUFFER); - case VK_OBJECT_TYPE_FENCE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_FENCE); - case VK_OBJECT_TYPE_DEVICE_MEMORY: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DEVICE_MEMORY); - case VK_OBJECT_TYPE_BUFFER: - return STRINGIFY_ARG(VK_OBJECT_TYPE_BUFFER); - case VK_OBJECT_TYPE_IMAGE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_IMAGE); - case VK_OBJECT_TYPE_EVENT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_EVENT); - case VK_OBJECT_TYPE_QUERY_POOL: - return STRINGIFY_ARG(VK_OBJECT_TYPE_QUERY_POOL); - case VK_OBJECT_TYPE_BUFFER_VIEW: - return STRINGIFY_ARG(VK_OBJECT_TYPE_BUFFER_VIEW); - case VK_OBJECT_TYPE_IMAGE_VIEW: - return STRINGIFY_ARG(VK_OBJECT_TYPE_IMAGE_VIEW); - case VK_OBJECT_TYPE_SHADER_MODULE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SHADER_MODULE); - case VK_OBJECT_TYPE_PIPELINE_CACHE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PIPELINE_CACHE); - case VK_OBJECT_TYPE_PIPELINE_LAYOUT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PIPELINE_LAYOUT); - case VK_OBJECT_TYPE_RENDER_PASS: - return STRINGIFY_ARG(VK_OBJECT_TYPE_RENDER_PASS); - case VK_OBJECT_TYPE_PIPELINE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PIPELINE); - case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); - case VK_OBJECT_TYPE_SAMPLER: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SAMPLER); - case VK_OBJECT_TYPE_DESCRIPTOR_POOL: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DESCRIPTOR_POOL); - case VK_OBJECT_TYPE_DESCRIPTOR_SET: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DESCRIPTOR_SET); - case VK_OBJECT_TYPE_FRAMEBUFFER: - return STRINGIFY_ARG(VK_OBJECT_TYPE_FRAMEBUFFER); - case VK_OBJECT_TYPE_COMMAND_POOL: - return STRINGIFY_ARG(VK_OBJECT_TYPE_COMMAND_POOL); - case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION); - case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE); - case VK_OBJECT_TYPE_SURFACE_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SURFACE_KHR); - case VK_OBJECT_TYPE_SWAPCHAIN_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_SWAPCHAIN_KHR); - case VK_OBJECT_TYPE_DISPLAY_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DISPLAY_KHR); - case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DISPLAY_MODE_KHR); - case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT); -#ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_OBJECT_TYPE_VIDEO_SESSION_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_VIDEO_SESSION_KHR); -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS - case VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR); -#endif - case VK_OBJECT_TYPE_CU_MODULE_NVX: - return STRINGIFY_ARG(VK_OBJECT_TYPE_CU_MODULE_NVX); - case VK_OBJECT_TYPE_CU_FUNCTION_NVX: - return STRINGIFY_ARG(VK_OBJECT_TYPE_CU_FUNCTION_NVX); - case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT); - case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR); - case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_VALIDATION_CACHE_EXT); - case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV: - return STRINGIFY_ARG(VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV); - case VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL); - case VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR: - return STRINGIFY_ARG(VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR); - case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV: - return STRINGIFY_ARG(VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV); - case VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT: - return STRINGIFY_ARG(VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT); - case VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA: - return STRINGIFY_ARG(VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA); - default: - BLI_assert_unreachable(); - } - return "NotFound"; -}; } // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_common.hh b/source/blender/gpu/vulkan/vk_common.hh index 489b0dad025..39414ec9e8c 100644 --- a/source/blender/gpu/vulkan/vk_common.hh +++ b/source/blender/gpu/vulkan/vk_common.hh @@ -55,7 +55,6 @@ VkIndexType to_vk_index_type(const GPUIndexBufType index_type); VkPrimitiveTopology to_vk_primitive_topology(const GPUPrimType prim_type); VkCullModeFlags to_vk_cull_mode_flags(const eGPUFaceCullTest cull_test); VkSamplerAddressMode to_vk_sampler_address_mode(const GPUSamplerExtendMode extend_mode); -const char *to_string(VkObjectType type); template VkObjectType to_vk_object_type(T /*vk_obj*/) { diff --git a/source/blender/gpu/vulkan/vk_debug.cc b/source/blender/gpu/vulkan/vk_debug.cc index f27aa5607ef..9792b0360ce 100644 --- a/source/blender/gpu/vulkan/vk_debug.cc +++ b/source/blender/gpu/vulkan/vk_debug.cc @@ -14,6 +14,7 @@ #include "vk_backend.hh" #include "vk_context.hh" #include "vk_debug.hh" +#include "vk_to_string.hh" static CLG_LogRef LOG = {"gpu.debug.vulkan"}; diff --git a/source/blender/gpu/vulkan/vk_to_string.cc b/source/blender/gpu/vulkan/vk_to_string.cc new file mode 100644 index 00000000000..3ac36722542 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_to_string.cc @@ -0,0 +1,713 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#include + +#include "vk_to_string.hh" + +namespace blender::gpu { +const char *to_string(const VkFilter vk_filter) +{ + switch (vk_filter) { + case VK_FILTER_NEAREST: + return STRINGIFY(VK_FILTER_NEAREST); + + case VK_FILTER_LINEAR: + return STRINGIFY(VK_FILTER_LINEAR); + + default: + break; + } + return STRINGIFY_ARG(vk_filter); +} + +const char *to_string(const VkImageLayout vk_image_layout) +{ + switch (vk_image_layout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + return STRINGIFY(VK_IMAGE_LAYOUT_UNDEFINED); + + case VK_IMAGE_LAYOUT_GENERAL: + return STRINGIFY(VK_IMAGE_LAYOUT_GENERAL); + + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return STRINGIFY(VK_IMAGE_LAYOUT_PREINITIALIZED); + + /* Extensions for VK_VERSION_1_1. */ + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL); + + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL); + + /* Extensions for VK_VERSION_1_2. */ + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL); + + case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL); + + case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: + return STRINGIFY(VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL); + + /* Extensions for VK_KHR_swapchain. */ + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return STRINGIFY(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + default: + break; + } + return STRINGIFY_ARG(vk_image_layout); +} + +const char *to_string(const VkIndexType vk_index_type) +{ + switch (vk_index_type) { + case VK_INDEX_TYPE_UINT16: + return STRINGIFY(VK_INDEX_TYPE_UINT16); + + case VK_INDEX_TYPE_UINT32: + return STRINGIFY(VK_INDEX_TYPE_UINT32); + + default: + break; + } + return STRINGIFY_ARG(vk_index_type); +} + +const char *to_string(const VkObjectType vk_object_type) +{ + switch (vk_object_type) { + case VK_OBJECT_TYPE_UNKNOWN: + return STRINGIFY(VK_OBJECT_TYPE_UNKNOWN); + + case VK_OBJECT_TYPE_INSTANCE: + return STRINGIFY(VK_OBJECT_TYPE_INSTANCE); + + case VK_OBJECT_TYPE_PHYSICAL_DEVICE: + return STRINGIFY(VK_OBJECT_TYPE_PHYSICAL_DEVICE); + + case VK_OBJECT_TYPE_DEVICE: + return STRINGIFY(VK_OBJECT_TYPE_DEVICE); + + case VK_OBJECT_TYPE_QUEUE: + return STRINGIFY(VK_OBJECT_TYPE_QUEUE); + + case VK_OBJECT_TYPE_SEMAPHORE: + return STRINGIFY(VK_OBJECT_TYPE_SEMAPHORE); + + case VK_OBJECT_TYPE_COMMAND_BUFFER: + return STRINGIFY(VK_OBJECT_TYPE_COMMAND_BUFFER); + + case VK_OBJECT_TYPE_FENCE: + return STRINGIFY(VK_OBJECT_TYPE_FENCE); + + case VK_OBJECT_TYPE_DEVICE_MEMORY: + return STRINGIFY(VK_OBJECT_TYPE_DEVICE_MEMORY); + + case VK_OBJECT_TYPE_BUFFER: + return STRINGIFY(VK_OBJECT_TYPE_BUFFER); + + case VK_OBJECT_TYPE_IMAGE: + return STRINGIFY(VK_OBJECT_TYPE_IMAGE); + + case VK_OBJECT_TYPE_EVENT: + return STRINGIFY(VK_OBJECT_TYPE_EVENT); + + case VK_OBJECT_TYPE_QUERY_POOL: + return STRINGIFY(VK_OBJECT_TYPE_QUERY_POOL); + + case VK_OBJECT_TYPE_BUFFER_VIEW: + return STRINGIFY(VK_OBJECT_TYPE_BUFFER_VIEW); + + case VK_OBJECT_TYPE_IMAGE_VIEW: + return STRINGIFY(VK_OBJECT_TYPE_IMAGE_VIEW); + + case VK_OBJECT_TYPE_SHADER_MODULE: + return STRINGIFY(VK_OBJECT_TYPE_SHADER_MODULE); + + case VK_OBJECT_TYPE_PIPELINE_CACHE: + return STRINGIFY(VK_OBJECT_TYPE_PIPELINE_CACHE); + + case VK_OBJECT_TYPE_PIPELINE_LAYOUT: + return STRINGIFY(VK_OBJECT_TYPE_PIPELINE_LAYOUT); + + case VK_OBJECT_TYPE_RENDER_PASS: + return STRINGIFY(VK_OBJECT_TYPE_RENDER_PASS); + + case VK_OBJECT_TYPE_PIPELINE: + return STRINGIFY(VK_OBJECT_TYPE_PIPELINE); + + case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: + return STRINGIFY(VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); + + case VK_OBJECT_TYPE_SAMPLER: + return STRINGIFY(VK_OBJECT_TYPE_SAMPLER); + + case VK_OBJECT_TYPE_DESCRIPTOR_POOL: + return STRINGIFY(VK_OBJECT_TYPE_DESCRIPTOR_POOL); + + case VK_OBJECT_TYPE_DESCRIPTOR_SET: + return STRINGIFY(VK_OBJECT_TYPE_DESCRIPTOR_SET); + + case VK_OBJECT_TYPE_FRAMEBUFFER: + return STRINGIFY(VK_OBJECT_TYPE_FRAMEBUFFER); + + case VK_OBJECT_TYPE_COMMAND_POOL: + return STRINGIFY(VK_OBJECT_TYPE_COMMAND_POOL); + + /* Extensions for VK_VERSION_1_1. */ + case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: + return STRINGIFY(VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION); + + case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: + return STRINGIFY(VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE); + + /* Extensions for VK_KHR_swapchain. */ + case VK_OBJECT_TYPE_SWAPCHAIN_KHR: + return STRINGIFY(VK_OBJECT_TYPE_SWAPCHAIN_KHR); + + default: + break; + } + return STRINGIFY_ARG(vk_object_type); +} + +const char *to_string(const VkPipelineBindPoint vk_pipeline_bind_point) +{ + switch (vk_pipeline_bind_point) { + case VK_PIPELINE_BIND_POINT_GRAPHICS: + return STRINGIFY(VK_PIPELINE_BIND_POINT_GRAPHICS); + + case VK_PIPELINE_BIND_POINT_COMPUTE: + return STRINGIFY(VK_PIPELINE_BIND_POINT_COMPUTE); + + default: + break; + } + return STRINGIFY_ARG(vk_pipeline_bind_point); +} + +const char *to_string(const VkSubpassContents vk_subpass_contents) +{ + switch (vk_subpass_contents) { + case VK_SUBPASS_CONTENTS_INLINE: + return STRINGIFY(VK_SUBPASS_CONTENTS_INLINE); + + case VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS: + return STRINGIFY(VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + + default: + break; + } + return STRINGIFY_ARG(vk_subpass_contents); +} + +std::string to_string_vk_access_flags(const VkAccessFlags vk_access_flags) +{ + std::stringstream ss; + + if (vk_access_flags & VK_ACCESS_INDIRECT_COMMAND_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_INDIRECT_COMMAND_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_INDEX_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_INDEX_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_UNIFORM_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_UNIFORM_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_SHADER_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_SHADER_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_SHADER_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_SHADER_WRITE_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_TRANSFER_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_TRANSFER_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_TRANSFER_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_TRANSFER_WRITE_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_HOST_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_HOST_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_HOST_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_HOST_WRITE_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_MEMORY_READ_BIT) { + ss << STRINGIFY(VK_ACCESS_MEMORY_READ_BIT) << ", "; + } + if (vk_access_flags & VK_ACCESS_MEMORY_WRITE_BIT) { + ss << STRINGIFY(VK_ACCESS_MEMORY_WRITE_BIT) << ", "; + } + + std::string result = ss.str(); + if (result.size() >= 2) { + result.erase(result.size() - 2, 2); + } + return result; +} + +std::string to_string_vk_dependency_flags(const VkDependencyFlags vk_dependency_flags) +{ + std::stringstream ss; + + if (vk_dependency_flags & VK_DEPENDENCY_BY_REGION_BIT) { + ss << STRINGIFY(VK_DEPENDENCY_BY_REGION_BIT) << ", "; + } + /* Extensions for VK_VERSION_1_1. */ + if (vk_dependency_flags & VK_DEPENDENCY_DEVICE_GROUP_BIT) { + ss << STRINGIFY(VK_DEPENDENCY_DEVICE_GROUP_BIT) << ", "; + } + if (vk_dependency_flags & VK_DEPENDENCY_VIEW_LOCAL_BIT) { + ss << STRINGIFY(VK_DEPENDENCY_VIEW_LOCAL_BIT) << ", "; + } + + std::string result = ss.str(); + if (result.size() >= 2) { + result.erase(result.size() - 2, 2); + } + return result; +} + +std::string to_string_vk_image_aspect_flags(const VkImageAspectFlags vk_image_aspect_flags) +{ + std::stringstream ss; + + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_COLOR_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_COLOR_BIT) << ", "; + } + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_DEPTH_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_DEPTH_BIT) << ", "; + } + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_STENCIL_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_STENCIL_BIT) << ", "; + } + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_METADATA_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_METADATA_BIT) << ", "; + } + /* Extensions for VK_VERSION_1_1. */ + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_PLANE_0_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_PLANE_0_BIT) << ", "; + } + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_PLANE_1_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_PLANE_1_BIT) << ", "; + } + if (vk_image_aspect_flags & VK_IMAGE_ASPECT_PLANE_2_BIT) { + ss << STRINGIFY(VK_IMAGE_ASPECT_PLANE_2_BIT) << ", "; + } + + std::string result = ss.str(); + if (result.size() >= 2) { + result.erase(result.size() - 2, 2); + } + return result; +} + +std::string to_string_vk_pipeline_stage_flags(const VkPipelineStageFlags vk_pipeline_stage_flags) +{ + std::stringstream ss; + + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_VERTEX_INPUT_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_VERTEX_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_TRANSFER_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_TRANSFER_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_HOST_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_HOST_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT) << ", "; + } + if (vk_pipeline_stage_flags & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) { + ss << STRINGIFY(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) << ", "; + } + + std::string result = ss.str(); + if (result.size() >= 2) { + result.erase(result.size() - 2, 2); + } + return result; +} + +std::string to_string_vk_shader_stage_flags(const VkShaderStageFlags vk_shader_stage_flags) +{ + std::stringstream ss; + + if (vk_shader_stage_flags & VK_SHADER_STAGE_VERTEX_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_VERTEX_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_GEOMETRY_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_GEOMETRY_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_FRAGMENT_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_FRAGMENT_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_COMPUTE_BIT) { + ss << STRINGIFY(VK_SHADER_STAGE_COMPUTE_BIT) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_ALL_GRAPHICS) { + ss << STRINGIFY(VK_SHADER_STAGE_ALL_GRAPHICS) << ", "; + } + if (vk_shader_stage_flags & VK_SHADER_STAGE_ALL) { + ss << STRINGIFY(VK_SHADER_STAGE_ALL) << ", "; + } + + std::string result = ss.str(); + if (result.size() >= 2) { + result.erase(result.size() - 2, 2); + } + return result; +} + +std::string to_string(const VkBufferCopy &vk_buffer_copy, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "src_offset=" << vk_buffer_copy.srcOffset; + ss << ", dst_offset=" << vk_buffer_copy.dstOffset; + ss << ", size=" << vk_buffer_copy.size; + + return ss.str(); +} + +std::string to_string(const VkBufferImageCopy &vk_buffer_image_copy, int indentation_level) +{ + std::stringstream ss; + ss << "buffer_offset=" << vk_buffer_image_copy.bufferOffset; + ss << ", buffer_row_length=" << vk_buffer_image_copy.bufferRowLength; + ss << ", buffer_image_height=" << vk_buffer_image_copy.bufferImageHeight; + ss << ", image_subresource=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_buffer_image_copy.imageSubresource, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", image_offset=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_buffer_image_copy.imageOffset, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", image_extent=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_buffer_image_copy.imageExtent, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + + return ss.str(); +} + +std::string to_string(const VkBufferMemoryBarrier &vk_buffer_memory_barrier, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "src_access_mask=" << to_string_vk_access_flags(vk_buffer_memory_barrier.srcAccessMask); + ss << ", dst_access_mask=" << to_string_vk_access_flags(vk_buffer_memory_barrier.dstAccessMask); + ss << ", buffer=" << vk_buffer_memory_barrier.buffer; + ss << ", offset=" << vk_buffer_memory_barrier.offset; + ss << ", size=" << vk_buffer_memory_barrier.size; + + return ss.str(); +} + +std::string to_string(const VkClearAttachment &vk_clear_attachment, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "aspect_mask=" << to_string_vk_image_aspect_flags(vk_clear_attachment.aspectMask); + ss << ", color_attachment=" << vk_clear_attachment.colorAttachment; + + return ss.str(); +} + +std::string to_string(const VkClearDepthStencilValue &vk_clear_depth_stencil_value, + int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "depth=" << vk_clear_depth_stencil_value.depth; + ss << ", stencil=" << vk_clear_depth_stencil_value.stencil; + + return ss.str(); +} + +std::string to_string(const VkClearRect &vk_clear_rect, int indentation_level) +{ + std::stringstream ss; + ss << "rect=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_clear_rect.rect, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", base_array_layer=" << vk_clear_rect.baseArrayLayer; + ss << ", layer_count=" << vk_clear_rect.layerCount; + + return ss.str(); +} + +std::string to_string(const VkExtent2D &vk_extent2_d, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "width=" << vk_extent2_d.width; + ss << ", height=" << vk_extent2_d.height; + + return ss.str(); +} + +std::string to_string(const VkExtent3D &vk_extent3_d, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "width=" << vk_extent3_d.width; + ss << ", height=" << vk_extent3_d.height; + ss << ", depth=" << vk_extent3_d.depth; + + return ss.str(); +} + +std::string to_string(const VkImageBlit &vk_image_blit, int indentation_level) +{ + std::stringstream ss; + ss << "src_subresource=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_blit.srcSubresource, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", dst_subresource=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_blit.dstSubresource, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + + return ss.str(); +} + +std::string to_string(const VkImageCopy &vk_image_copy, int indentation_level) +{ + std::stringstream ss; + ss << "src_subresource=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_copy.srcSubresource, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", src_offset=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_copy.srcOffset, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", dst_subresource=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_copy.dstSubresource, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", dst_offset=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_copy.dstOffset, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", extent=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_copy.extent, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + + return ss.str(); +} + +std::string to_string(const VkImageMemoryBarrier &vk_image_memory_barrier, int indentation_level) +{ + std::stringstream ss; + ss << "src_access_mask=" << to_string_vk_access_flags(vk_image_memory_barrier.srcAccessMask); + ss << ", dst_access_mask=" << to_string_vk_access_flags(vk_image_memory_barrier.dstAccessMask); + ss << ", old_layout=" << to_string(vk_image_memory_barrier.oldLayout); + ss << ", new_layout=" << to_string(vk_image_memory_barrier.newLayout); + ss << ", image=" << vk_image_memory_barrier.image; + ss << ", subresource_range=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_image_memory_barrier.subresourceRange, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + + return ss.str(); +} + +std::string to_string(const VkImageSubresourceLayers &vk_image_subresource_layers, + int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "aspect_mask=" << to_string_vk_image_aspect_flags(vk_image_subresource_layers.aspectMask); + ss << ", mip_level=" << vk_image_subresource_layers.mipLevel; + ss << ", base_array_layer=" << vk_image_subresource_layers.baseArrayLayer; + ss << ", layer_count=" << vk_image_subresource_layers.layerCount; + + return ss.str(); +} + +std::string to_string(const VkImageSubresourceRange &vk_image_subresource_range, + int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "aspect_mask=" << to_string_vk_image_aspect_flags(vk_image_subresource_range.aspectMask); + ss << ", base_mip_level=" << vk_image_subresource_range.baseMipLevel; + ss << ", level_count=" << vk_image_subresource_range.levelCount; + ss << ", base_array_layer=" << vk_image_subresource_range.baseArrayLayer; + ss << ", layer_count=" << vk_image_subresource_range.layerCount; + + return ss.str(); +} + +std::string to_string(const VkMemoryBarrier &vk_memory_barrier, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "src_access_mask=" << to_string_vk_access_flags(vk_memory_barrier.srcAccessMask); + ss << ", dst_access_mask=" << to_string_vk_access_flags(vk_memory_barrier.dstAccessMask); + + return ss.str(); +} + +std::string to_string(const VkOffset2D &vk_offset2_d, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "x=" << vk_offset2_d.x; + ss << ", y=" << vk_offset2_d.y; + + return ss.str(); +} + +std::string to_string(const VkOffset3D &vk_offset3_d, int indentation_level) +{ + UNUSED_VARS(indentation_level); + std::stringstream ss; + ss << "x=" << vk_offset3_d.x; + ss << ", y=" << vk_offset3_d.y; + ss << ", z=" << vk_offset3_d.z; + + return ss.str(); +} + +std::string to_string(const VkRect2D &vk_rect2_d, int indentation_level) +{ + std::stringstream ss; + ss << "offset=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_rect2_d.offset, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", extent=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_rect2_d.extent, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + + return ss.str(); +} + +std::string to_string(const VkRenderPassBeginInfo &vk_render_pass_begin_info, + int indentation_level) +{ + std::stringstream ss; + ss << "render_pass=" << vk_render_pass_begin_info.renderPass; + ss << ", framebuffer=" << vk_render_pass_begin_info.framebuffer; + ss << ", render_area=" + << "\n"; + ss << std::string(indentation_level * 2 + 2, ' ') + << to_string(vk_render_pass_begin_info.renderArea, indentation_level + 1); + ss << std::string(indentation_level * 2, ' '); + ss << ", clear_value_count=" << vk_render_pass_begin_info.clearValueCount; + ss << ", p_clear_values=" << vk_render_pass_begin_info.pClearValues; + + return ss.str(); +} + +} // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_to_string.hh b/source/blender/gpu/vulkan/vk_to_string.hh new file mode 100644 index 00000000000..b1e05134892 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_to_string.hh @@ -0,0 +1,49 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "vk_common.hh" + +namespace blender::gpu { +const char *to_string(VkFilter vk_filter); +const char *to_string(VkImageLayout vk_image_layout); +const char *to_string(VkIndexType vk_index_type); +const char *to_string(VkObjectType vk_object_type); +const char *to_string(VkPipelineBindPoint vk_pipeline_bind_point); +const char *to_string(VkSubpassContents vk_subpass_contents); +std::string to_string_vk_access_flags(VkAccessFlags vk_access_flags); +std::string to_string_vk_dependency_flags(VkDependencyFlags vk_dependency_flags); +std::string to_string_vk_image_aspect_flags(VkImageAspectFlags vk_image_aspect_flags); +std::string to_string_vk_pipeline_stage_flags(VkPipelineStageFlags vk_pipeline_stage_flags); +std::string to_string_vk_shader_stage_flags(VkShaderStageFlags vk_shader_stage_flags); +std::string to_string(const VkBufferCopy &vk_buffer_copy, int indentation_level = 0); +std::string to_string(const VkBufferImageCopy &vk_buffer_image_copy, int indentation_level = 0); +std::string to_string(const VkBufferMemoryBarrier &vk_buffer_memory_barrier, + int indentation_level = 0); +std::string to_string(const VkClearAttachment &vk_clear_attachment, int indentation_level = 0); +std::string to_string(const VkClearDepthStencilValue &vk_clear_depth_stencil_value, + int indentation_level = 0); +std::string to_string(const VkClearRect &vk_clear_rect, int indentation_level = 0); +std::string to_string(const VkExtent2D &vk_extent2_d, int indentation_level = 0); +std::string to_string(const VkExtent3D &vk_extent3_d, int indentation_level = 0); +std::string to_string(const VkImageBlit &vk_image_blit, int indentation_level = 0); +std::string to_string(const VkImageCopy &vk_image_copy, int indentation_level = 0); +std::string to_string(const VkImageMemoryBarrier &vk_image_memory_barrier, + int indentation_level = 0); +std::string to_string(const VkImageSubresourceLayers &vk_image_subresource_layers, + int indentation_level = 0); +std::string to_string(const VkImageSubresourceRange &vk_image_subresource_range, + int indentation_level = 0); +std::string to_string(const VkMemoryBarrier &vk_memory_barrier, int indentation_level = 0); +std::string to_string(const VkOffset2D &vk_offset2_d, int indentation_level = 0); +std::string to_string(const VkOffset3D &vk_offset3_d, int indentation_level = 0); +std::string to_string(const VkRect2D &vk_rect2_d, int indentation_level = 0); +std::string to_string(const VkRenderPassBeginInfo &vk_render_pass_begin_info, + int indentation_level = 0); +} // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_to_string.py b/source/blender/gpu/vulkan/vk_to_string.py new file mode 100644 index 00000000000..44eab8456f1 --- /dev/null +++ b/source/blender/gpu/vulkan/vk_to_string.py @@ -0,0 +1,394 @@ +""" +This script is used to generate parts of `vk_to_string.hh` and `vk_to_string.cc` based on the +vulkan API commands, features and extensions we use. + +When to use? + +Every time we use a new `vkCmd*` or new extension, we should re-generate to detect updates. +Extensions can alter enum types which we would use. + +How to use? + +Generate source code that can be copied in `vk_to_string.cc`: + `python3 vk_to_string.py ` +Generate source code that can be copied into `vk_to_string.hh`: + `python3 vk_to_string.py --header` + +Every vulkan installation contains a `vk.xml` which contains the specification in a machine +readable format. `vk.xml` is also part of the vulkan library in blender libs. + +The generated source code will be printed to the console. +""" +import argparse +import xml.etree.ElementTree as ET + + +# List of features blender uses. Features can extend enum flags. +FEATURES = [ + "VK_VERSION_1_0", + "VK_VERSION_1_1", + "VK_VERSION_1_2", +] +# List of extensions blender uses. These can extend enum flags. +EXTENSIONS = [ + "VK_KHR_swapchain", +] + +# List of vkCmd commands blender uses. +COMMANDS_TO_GEN = [ + "vkCmdClearColorImage", + "vkCmdClearDepthStencilImage", + "vkCmdClearAttachments", + + "vkCmdCopyImageToBuffer", + "vkCmdCopyBufferToImage", + "vkCmdCopyImage", + "vkCmdCopyBuffer", + + "vkCmdFillBuffer", + "vkCmdBlitImage", + + "vkCmdBindDescriptorSets", + "vkCmdPushConstants", + "vkCmdBindIndexBuffer", + "vkCmdBindVertexBuffers", + "vkCmdBindPipeline", + + "vkCmdBeginRenderPass", + "vkCmdEndRenderPass", + "vkCmdDraw", + "vkCmdDrawIndexed", + "vkCmdDrawIndirect", + "vkCmdDrawIndexedIndirect", + + "vkCmdDispatch", + "vkCmdDispatchIndirect", + + "vkCmdPipelineBarrier", +] + +DEFAULT_ENUMS_TO_GENERATE = [ + "VkObjectType" +] +ENUMS_TO_IGNORE = [ + "VkStructureType" +] + +# A list of struct members to ignore as they aren't supported or not useful. +MEMBERS_TO_IGNORE = [ + "sType", "pNext", + # Disabled as these are arrays. + "srcOffsets", "dstOffsets", + # Disabled as it is an union + "clearValue", + # Disabled as we don't use cross queue synchronization + "srcQueueFamilyIndex", "dstQueueFamilyIndex" +] + + +### Utils - Formatting ### +def to_lower_snake_case(string): + result = "" + for char in string: + if char.isupper() and len(result) != 0: + result += "_" + result += char.lower() + return result + + +### Commands ### +def extract_type_names(commands, r_types): + for command in commands: + for param in command.findall("param"): + param_type = param.findtext("type") + if param_type not in r_types: + r_types.append(param_type) + + +### Enumerations ### +def generate_enum_to_string_hpp(enum): + vk_name = enum.get("name") + result = "" + result += f"const char *to_string({vk_name} {to_lower_snake_case(vk_name)});\n" + return result + + +def generate_enum_to_string_cpp_case(elem): + result = "" + vk_elem_name = elem.get("name") + result += f" case {vk_elem_name}:\n" + result += f" return STRINGIFY({vk_elem_name});\n\n" + return result + + +def generate_enum_to_string_cpp(enum, features, extensions): + vk_name = enum.get("name") + vk_name_parameter = to_lower_snake_case(vk_name) + result = "" + result += f"const char *to_string(const {vk_name} {vk_name_parameter})\n" + result += "{\n" + result += f" switch ({vk_name_parameter}) {{\n" + for elem in enum.findall("enum"): + result += generate_enum_to_string_cpp_case(elem) + for feature in features: + enum_extensions = feature.findall(f"require/enum[@extends='{vk_name}']") + if not enum_extensions: + continue + feature_name = feature.get("name") + result += f" /* Extensions for {feature_name}. */\n" + for elem in enum_extensions: + result += generate_enum_to_string_cpp_case(elem) + for extension in extensions: + enum_extensions = extension.findall(f"require/enum[@extends='{vk_name}']") + if not enum_extensions: + continue + extension_name = extension.get("name") + result += f" /* Extensions for {extension_name}. */\n" + for elem in enum_extensions: + result += generate_enum_to_string_cpp_case(elem) + + result += " default:\n" + result += " break;\n" + + result += " }\n" + result += f" return STRINGIFY_ARG({vk_name_parameter});\n" + result += "}\n" + return result + + +### Bitflags ### +def generate_bitflag_to_string_hpp(vk_name): + vk_name_parameter = to_lower_snake_case(vk_name) + result = "" + result += f"std::string to_string_{vk_name_parameter}({vk_name} {to_lower_snake_case(vk_name)});\n" + return result + + +def generate_bitflag_to_string_cpp_case(vk_parameter_name, elem): + vk_elem_name = elem.get("name") + + result = "" + result += f" if ({vk_parameter_name} & {vk_elem_name}) {{\n" + result += f" ss << STRINGIFY({vk_elem_name}) << \", \";\n" + result += f" }}\n" + return result + + +def generate_bitflag_to_string_cpp(vk_name, enum, features, extensions): + vk_enum_name = enum.get("name") + vk_name_parameter = to_lower_snake_case(vk_name) + result = "" + result += f"std::string to_string_{vk_name_parameter}(const {vk_name} {vk_name_parameter})\n" + result += "{\n" + result += " std::stringstream ss;\n" + result += "\n" + for elem in enum.findall("enum"): + result += generate_bitflag_to_string_cpp_case(vk_name_parameter, elem) + for feature in features: + enum_extensions = feature.findall(f"require/enum[@extends='{vk_enum_name}']") + if not enum_extensions: + continue + feature_name = feature.get("name") + result += f" /* Extensions for {feature_name}. */\n" + for elem in enum_extensions: + result += generate_bitflag_to_string_cpp_case(vk_name_parameter, elem) + for extension in extensions: + enum_extensions = extension.findall(f"require/enum[@extends='{vk_enum_name}']") + if not enum_extensions: + continue + extension_name = extension.get("name") + result += f" /* Extensions for {extension_name}. */\n" + for elem in enum_extensions: + result += generate_bitflag_to_string_cpp_case(vk_name_parameter, elem) + + result += "\n" + result += f" std::string result = ss.str();\n" + result += f" if (result.size() >= 2) {{\n" + result += f" result.erase(result.size() - 2, 2);\n" + result += f" }}\n" + result += f" return result;\n" + result += "}\n" + return result + + +### Structs ### +def generate_struct_to_string_hpp(struct): + vk_name = struct.get("name") + vk_name_parameter = to_lower_snake_case(vk_name) + result = "" + result += f"std::string to_string(const {vk_name} &{vk_name_parameter}, int indentation_level=0);\n" + return result + + +def generate_struct_to_string_cpp(struct, flags_to_generate, enums_to_generate, structs_to_generate): + vk_name = struct.get("name") + vk_name_parameter = to_lower_snake_case(vk_name) + header = "" + header += f"std::string to_string(const {vk_name} &{vk_name_parameter}, int indentation_level)\n" + header += f"{{\n" + result = "" + result += f" std::stringstream ss;\n" + pre = "" + indentation_used = False + for member in struct.findall("member"): + member_type = member.findtext("type") + member_type_parameter = to_lower_snake_case(member_type) + member_name = member.findtext("name") + member_name_parameter = to_lower_snake_case(member_name) + if member_name in MEMBERS_TO_IGNORE: + continue + + result += f" ss << \"{pre}{member_name_parameter}=\" << " + if member_type in flags_to_generate: + result += f"to_string_{member_type_parameter}({vk_name_parameter}.{member_name})" + elif member_type in enums_to_generate: + result += f"to_string({vk_name_parameter}.{member_name})" + elif member_type in structs_to_generate: + result += f"\"\\n\";\n" + result += f" ss << std::string(indentation_level * 2 + 2, ' ') << to_string({vk_name_parameter}.{member_name}, indentation_level + 1);\n" + result += f" ss << std::string(indentation_level * 2, ' ')" + indentation_used = True + else: + result += f"{vk_name_parameter}.{member_name}" + result += ";\n" + pre = ", " + result += f"\n" + result += f" return ss.str();\n" + result += f"}}\n" + if not indentation_used: + header += " UNUSED_VARS(indentation_level);\n" + return header + result + + +# Parsing vk.xml +def parse_features(root): + # Find all features that we use. + features = [] + for feature_name in FEATURES: + feature = root.find(f"feature[@name='{feature_name}']") + assert(feature) + features.append(feature) + return features + + +def parse_extensions(root): + # Find all extensions that we use. + extensions = [] + for extension_name in EXTENSIONS: + extension = root.find(f"extensions/extension[@name='{extension_name}']") + assert(extension) + extensions.append(extension) + return extensions + + +def parse_all_commands(root): + commands = [] + for command in root.findall("commands/command"): + command_name = command.findtext("proto/name") + if command_name in COMMANDS_TO_GEN: + commands.append(command) + return commands + + +def parse_all_flags(root): + all_flags = {} + for flag_type in root.findall("types/type[@category='bitmask']"): + flag_type_name = flag_type.findtext("name") + flag_type_bits_name = flag_type.get("requires") + if flag_type_name and flag_type_bits_name: + all_flags[flag_type_name] = flag_type_bits_name + return all_flags + + +# Extraction of used data types. +def extract_used_types(root, commands, all_flags): + enums_to_generate = [] + enums_to_generate.extend(DEFAULT_ENUMS_TO_GENERATE) + + flags_to_generate = [] + structs_to_generate = [] + + types_undetermined = [] + extract_type_names(commands, types_undetermined) + while types_undetermined: + newly_found_types = [] + for type_name in types_undetermined: + if root.find(f"enums[@name='{type_name}']"): + if type_name not in enums_to_generate and type_name not in ENUMS_TO_IGNORE: + enums_to_generate.append(type_name) + elif type_name in all_flags and type_name not in flags_to_generate: + flags_to_generate.append(type_name) + elif type_name not in structs_to_generate: + struct = root.find(f"types/type[@category='struct'][@name='{type_name}']") + if struct: + structs_to_generate.append(type_name) + for member in struct.findall("member/type"): + newly_found_types.append(member.text) + + types_undetermined = newly_found_types + + enums_to_generate.sort() + flags_to_generate.sort() + structs_to_generate.sort() + + return (enums_to_generate, flags_to_generate, structs_to_generate) + + +def generate_to_string(vk_xml, header): + tree = ET.parse(vk_xml) + root = tree.getroot() + + commands = parse_all_commands(root) + features = parse_features(root) + extensions = parse_extensions(root) + all_flags = parse_all_flags(root) + + (enums_to_generate, flags_to_generate, structs_to_generate) = extract_used_types(root, commands, all_flags) + + vk_to_string = "" + + if header: + for enum_to_generate in enums_to_generate: + for enum in root.findall(f"enums[@name='{enum_to_generate}']"): + vk_to_string += generate_enum_to_string_hpp(enum) + for flag_to_generate in flags_to_generate: + enum_to_generate = all_flags[flag_to_generate] + for enum in root.findall(f"enums[@name='{enum_to_generate}']"): + vk_to_string += generate_bitflag_to_string_hpp(flag_to_generate) + for struct_to_generate in structs_to_generate: + struct = root.find(f"types/type[@category='struct'][@name='{struct_to_generate}']") + assert(struct) + vk_to_string += generate_struct_to_string_hpp(struct) + else: + for enum_to_generate in enums_to_generate: + for enum in root.findall(f"enums[@name='{enum_to_generate}']"): + vk_to_string += generate_enum_to_string_cpp(enum, features, extensions) + vk_to_string += "\n" + for flag_to_generate in flags_to_generate: + enum_to_generate = all_flags[flag_to_generate] + for enum in root.findall(f"enums[@name='{enum_to_generate}']"): + vk_to_string += generate_bitflag_to_string_cpp(flag_to_generate, enum, features, extensions) + vk_to_string += "\n" + + for struct_to_generate in structs_to_generate: + struct = root.find(f"types/type[@category='struct'][@name='{struct_to_generate}']") + assert(struct) + vk_to_string += generate_struct_to_string_cpp(struct, + flags_to_generate, + enums_to_generate, + structs_to_generate) + vk_to_string += "\n" + + print(vk_to_string) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + prog="vk_to_string.py", + description="Generator for vk_to_string.cc/hh", + ) + parser.add_argument("vk_xml", help="path to `vk.xml`") + parser.add_argument("--header", action='store_true', help="generate parts that belong to `vk_to_string.hh`") + args = parser.parse_args() + generate_to_string(**dict(args._get_kwargs()))