Vulkan: to_string for used vulkan types

Every vulkan installation has a vk.xml file containing the vulkan specification
in a machine readable fasion.

This PR uses the vk.xml to generate to_string functions for data types blender uses.
When updating to a new specification or when changing features/extensions we
should re-generate the to_string functions.

The generator is implemented in `vk_to_string.py`.

Pull Request: https://projects.blender.org/blender/blender/pulls/119880
This commit is contained in:
Jeroen Bakker 2024-03-26 11:35:16 +01:00
parent df9b3d35a2
commit e811785f37
7 changed files with 1159 additions and 106 deletions

View File

@ -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

View File

@ -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

View File

@ -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<typename T> VkObjectType to_vk_object_type(T /*vk_obj*/)
{

View File

@ -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"};

View File

@ -0,0 +1,713 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include <sstream>
#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

View File

@ -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

View File

@ -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 <path-to-vk-xml>`
Generate source code that can be copied into `vk_to_string.hh`:
`python3 vk_to_string.py <path-to-vk-xml> --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()))