From 763151a96b7cd13a5e0d0040befdaaedd9589e2a Mon Sep 17 00:00:00 2001 From: Ilya Doroshenko Date: Fri, 1 May 2026 00:13:46 +0200 Subject: [PATCH 01/18] Add Video extension with DX12/Vulkan support and codegen Introduced a new Video extension with CMake integration, C/C++ API headers, and backend implementations for DirectX 12 and Vulkan. Updated the code generator to support handle constructors with custom parameters from XML, enabling automatic generation of extension handle constructors. Added XML spec files for the Video extension, new headers for enums and handles, and backend-specific implementation files. Improved code generation for function parameters and enhanced parsing of blocks in handle definitions. Comprehensive documentation was added for all new types and functions. --- docs/video/enum/video_codec_enum.h | 54 ++++++++ docs/video/enum/video_codec_flags_enum.h | 56 ++++++++ ...estroy_video_decoding_extension_function.h | 44 +++++++ .../init_video_decoding_extension_function.h | 70 ++++++++++ ...eo_decoding_extension_supported_function.h | 58 +++++++++ .../handle/video_decoding_extension_handle.h | 28 ++++ examples/CMakeLists.txt | 1 + examples/video/CMakeLists.txt | 17 +++ examples/video/entry_main.cpp | 120 ++++++++++++++++++ generator/function.cpp | 64 +++------- generator/generator.cpp | 46 +++++++ generator/generator.hpp | 1 + generator/handle.cpp | 82 +++++++++++- src/CMakeLists.txt | 2 +- src/extensions/CMakeLists.txt | 6 + src/extensions/video/CMakeLists.txt | 116 +++++++++++++++++ .../video/video/dx12/dx12_types.hpp | 30 +++++ .../video/video/dx12/dx12_video.cpp | 84 ++++++++++++ src/extensions/video/video/generated/c_api.h | 104 +++++++++++++++ .../video/video/generated/cpp_api.hpp | 112 ++++++++++++++++ .../video/video/generated/dx12_convert.hpp | 15 +++ .../video/video/generated/vk_convert.hpp | 15 +++ .../video/video/vulkan/vk_types.hpp | 30 +++++ .../video/video/vulkan/vk_video.cpp | 102 +++++++++++++++ src/extensions/video/wisdom/wisdom_video.h | 65 ++++++++++ src/extensions/video/wisdom/wisdom_video.hpp | 45 +++++++ xml/spec_template.xml | 26 ++++ xml/video.xml | 37 ++++++ 28 files changed, 1377 insertions(+), 53 deletions(-) create mode 100644 docs/video/enum/video_codec_enum.h create mode 100644 docs/video/enum/video_codec_flags_enum.h create mode 100644 docs/video/func/destroy_video_decoding_extension_function.h create mode 100644 docs/video/func/init_video_decoding_extension_function.h create mode 100644 docs/video/func/video_decoding_extension_supported_function.h create mode 100644 docs/video/handle/video_decoding_extension_handle.h create mode 100644 examples/video/CMakeLists.txt create mode 100644 examples/video/entry_main.cpp create mode 100644 src/extensions/video/CMakeLists.txt create mode 100644 src/extensions/video/video/dx12/dx12_types.hpp create mode 100644 src/extensions/video/video/dx12/dx12_video.cpp create mode 100644 src/extensions/video/video/generated/c_api.h create mode 100644 src/extensions/video/video/generated/cpp_api.hpp create mode 100644 src/extensions/video/video/generated/dx12_convert.hpp create mode 100644 src/extensions/video/video/generated/vk_convert.hpp create mode 100644 src/extensions/video/video/vulkan/vk_types.hpp create mode 100644 src/extensions/video/video/vulkan/vk_video.cpp create mode 100644 src/extensions/video/wisdom/wisdom_video.h create mode 100644 src/extensions/video/wisdom/wisdom_video.hpp create mode 100644 xml/spec_template.xml create mode 100644 xml/video.xml diff --git a/docs/video/enum/video_codec_enum.h b/docs/video/enum/video_codec_enum.h new file mode 100644 index 00000000..66badfb1 --- /dev/null +++ b/docs/video/enum/video_codec_enum.h @@ -0,0 +1,54 @@ +/** + * @struct WisVideoCodec WisVideoCodec + * @ingroup Enumerations Video + * + * @section WisVideoCodec_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * C version: + * ```c + * // Provided by Wisdom 0.7.1. + * typedef enum WisVideoCodec { + * WisVideoCodecNone = 0, + * WisVideoCodecH264 = (1u << 0), + * WisVideoCodecH265 = (1u << 1), + * WisVideoCodecAV1 = (1u << 2), + * WisVideoCodecVP9 = (1u << 3), + * } WisVideoCodec; + * ``` + * C++ version: + * ```cpp + * namespace wis{ + * // Provided by Wisdom 0.7.1. + * enum class VideoCodec : uint32_t { + * None = 0, + * H264 = (1u << 0), + * H265 = (1u << 1), + * AV1 = (1u << 2), + * VP9 = (1u << 3), + * }; + * } + * ``` + * \endcond + * + * @section WisVideoCodec_descr Description + *
+ * \cond WIS_GEN_DESC + * Video codec flags. Used to request and check supported codecs. + * + * Values: + * - `WisVideoCodecNone = 0`: No video is requested. The extension will not initialize. + * - `WisVideoCodecH264 = (1 << 0)`: H.264 video codec. + * - `WisVideoCodecH265 = (1 << 1)`: H.265 video codec. + * - `WisVideoCodecAV1 = (1 << 2)`: AV1 video codec. + * - `WisVideoCodecVP9 = (1 << 3)`: VP9 video codec. + * \endcond + * + * + * @section WisVideoCodec_see_also See Also + *
+ * + * \cond WIS_GEN_REFS + * \endcond + */ diff --git a/docs/video/enum/video_codec_flags_enum.h b/docs/video/enum/video_codec_flags_enum.h new file mode 100644 index 00000000..b879d707 --- /dev/null +++ b/docs/video/enum/video_codec_flags_enum.h @@ -0,0 +1,56 @@ +/** + * @struct WisVideoCodecFlags WisVideoCodecFlags + * @ingroup Enumerations Video + * + * @section WisVideoCodecFlags_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * C version: + * ```c + * // Provided by Wisdom 0.7.1. + * typedef enum WisVideoCodecFlags { + * WisVideoCodecFlagsNone = 0, + * WisVideoCodecFlagsH264 = (1u << 0), + * WisVideoCodecFlagsH265 = (1u << 1), + * WisVideoCodecFlagsAV1 = (1u << 2), + * WisVideoCodecFlagsVP9 = (1u << 3), + * } WisVideoCodecFlags; + * ``` + * C++ version: + * ```cpp + * namespace wis{ + * // Provided by Wisdom 0.7.1. + * enum class VideoCodecFlags : uint32_t { + * None = 0, + * H264 = (1u << 0), + * H265 = (1u << 1), + * AV1 = (1u << 2), + * VP9 = (1u << 3), + * }; + * } + * ``` + * \endcond + * + * @section WisVideoCodecFlags_descr Description + *
+ * \cond WIS_GEN_DESC + * Video codec flags. Used to request and check supported codecs. + * + * Values: + * - `WisVideoCodecFlagsNone = 0`: No video is requested. The extension will not initialize. + * - `WisVideoCodecFlagsH264 = (1 << 0)`: H.264 video codec. + * - `WisVideoCodecFlagsH265 = (1 << 1)`: H.265 video codec. + * - `WisVideoCodecFlagsAV1 = (1 << 2)`: AV1 video codec. + * - `WisVideoCodecFlagsVP9 = (1 << 3)`: VP9 video codec. + * \endcond + * + * + * @section WisVideoCodecFlags_see_also See Also + *
+ * + * \cond WIS_GEN_REFS + * @see Functions: + * wisInitVideoDecodingExtension + * \endcond + */ diff --git a/docs/video/func/destroy_video_decoding_extension_function.h b/docs/video/func/destroy_video_decoding_extension_function.h new file mode 100644 index 00000000..c4787aeb --- /dev/null +++ b/docs/video/func/destroy_video_decoding_extension_function.h @@ -0,0 +1,44 @@ +/** + * @struct wisDestroyVideoDecodingExtension + * @ingroup Functions Video + * + * + * @section wisDestroyVideoDecodingExtension_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * C Version: + * ```c + * // Provided by Wisdom 0.7.1. + * void wisDestroyVideoDecodingExtension(WisVideoDecodingExtension* self); + * ``` + *
+ * C Implementation Specific Version: + * ```c + * // Provided by Wisdom 0.7.1. + * void wisVKDestroyVideoDecodingExtension(WisVKVideoDecodingExtension* self); + * + * // Provided by Wisdom 0.7.1. + * void wisDX12DestroyVideoDecodingExtension(WisDX12VideoDecodingExtension* self); + * ``` + *
+ * + * \endcond + * + * @section wisDestroyVideoDecodingExtension_memb Parameters + *
+ * \cond WIS_GEN_DESC + * - **this** `self` self is a pointer to the valid WisVideoDecodingExtension instance. + * \endcond + * + * @section wisDestroyVideoDecodingExtension_descr Description + *
+ * + * \cond WIS_GEN_WIS_IDS + * \endcond + * + * @section wisDestroyVideoDecodingExtension_see_also See Also + *
+ * \cond WIS_GEN_REFS + * \endcond + */ diff --git a/docs/video/func/init_video_decoding_extension_function.h b/docs/video/func/init_video_decoding_extension_function.h new file mode 100644 index 00000000..ff3c9672 --- /dev/null +++ b/docs/video/func/init_video_decoding_extension_function.h @@ -0,0 +1,70 @@ +/** + * @struct wisInitVideoDecodingExtension + * @ingroup Functions Video + * + * + * @section wisInitVideoDecodingExtension_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * C Version: + * ```c + * // Provided by Wisdom 0.7.1. + * void wisInitVideoDecodingExtension(WisVideoDecodingExtension* self, + * WisVideoCodecFlags request_codecs); + * ``` + *
+ * C Implementation Specific Version: + * ```c + * // Provided by Wisdom 0.7.1. + * void wisVKInitVideoDecodingExtension(WisVKVideoDecodingExtension* self, + * WisVideoCodecFlags request_codecs); + * + * // Provided by Wisdom 0.7.1. + * void wisDX12InitVideoDecodingExtension(WisDX12VideoDecodingExtension* self, + * WisVideoCodecFlags request_codecs); + * ``` + *
+ * + * C++ Version: + * ```cpp + * namespace wis{ + * // Provided by Wisdom 0.7.1. + * VideoDecodingExtension::VideoDecodingExtension(wis::VideoCodecFlags request_codecs) noexcept; + * } + * ``` + *
+ * C++ Implementation Specific Version: + * ```cpp + * namespace wis{ + * // Provided by Wisdom 0.7.1. + * VKVideoDecodingExtension::VKVideoDecodingExtension(wis::VideoCodecFlags request_codecs) noexcept; + * + * // Provided by Wisdom 0.7.1. + * DX12VideoDecodingExtension::DX12VideoDecodingExtension(wis::VideoCodecFlags request_codecs) noexcept; + * } + * ``` + *
+ * \endcond + * + * @section wisInitVideoDecodingExtension_memb Parameters + *
+ * \cond WIS_GEN_DESC + * - **this** `self` is a pointer to uninitialized WisVideoDecodingExtension instance memory. It will be initialized by + * this function. + * **note** The corresponding destroy function is `wisDestroyVideoDecodingExtension`. + * - `request_codecs` Bitmask of requested video codecs. The extension will attempt to initialize with support for these + * codecs. + * \endcond + * + * @section wisInitVideoDecodingExtension_descr Description + *
+ * + * \cond WIS_GEN_WIS_IDS + * \endcond + * + * @section wisInitVideoDecodingExtension_see_also See Also + *
+ * \cond WIS_GEN_REFS + * \endcond + */ diff --git a/docs/video/func/video_decoding_extension_supported_function.h b/docs/video/func/video_decoding_extension_supported_function.h new file mode 100644 index 00000000..d86aafb4 --- /dev/null +++ b/docs/video/func/video_decoding_extension_supported_function.h @@ -0,0 +1,58 @@ +/** + * @struct wisVideoDecodingExtensionSupported + * @ingroup Functions Video + * + * + * @section wisVideoDecodingExtensionSupported_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * * C Version: + * ```c + * // Provided by Wisdom 0.7.1. + * bool wisVideoDecodingExtensionSupported(WisVideoDecodingExtension* self); + * ``` + *
+ * C Implementation Specific Version: + * ```c + * // Provided by Wisdom 0.7.1. + * bool wisVKVideoDecodingExtensionSupported(WisVKVideoDecodingExtension* self); + * + * // Provided by Wisdom 0.7.1. + * bool wisDX12VideoDecodingExtensionSupported(WisDX12VideoDecodingExtension* self); + * ``` + *
+ * + * C++ Version: + * ```cpp + * namespace wis + * ``` + *
+ * C++ Implementation Specific Version: + * ```cpp + * namespace wis + * ``` + *
+ * + * \endcond + * + * @section wisVideoDecodingExtensionSupported_memb Parameters + *
+ * \cond WIS_GEN_DESC + * * - **this** `self` self is a pointer to the valid WisVideoDecodingExtension instance. + * + * - **return** true if raytracing is supported, false otherwise. + * + * \endcond + * + * @section wisVideoDecodingExtensionSupported_descr Description + *
+ * + * \cond WIS_GEN_WIS_IDS + * \endcond + * + * @section wisVideoDecodingExtensionSupported_see_also See Also + *
+ * \cond WIS_GEN_REFS + * \endcond + */ diff --git a/docs/video/handle/video_decoding_extension_handle.h b/docs/video/handle/video_decoding_extension_handle.h new file mode 100644 index 00000000..4320c425 --- /dev/null +++ b/docs/video/handle/video_decoding_extension_handle.h @@ -0,0 +1,28 @@ +/** + * @struct WisVideoDecodingExtension + * @ingroup Handles Video + * + * + * @section WisVideoDecodingExtension_spec Specification + *
+ * + * \cond WIS_GEN_CODE + * Vulkan Version: + * ```c + * // Provided by Wisdom 0.7.1. + * WIS_DEFINE_VK_DEVICE_EXT_HANDLE(WisVKVideoDecodingExtension,4); + * ``` + * DX12 Version: + * ```c + * // Provided by Wisdom 0.7.1. + * WIS_DEFINE_DX12_DEVICE_EXT_HANDLE(WisDX12VideoDecodingExtension,2); + * ``` + * \endcond + * + * @section WisVideoDecodingExtension_see_also See Also + *
+ * \cond WIS_GEN_REFS + * @see Functions: + * wisDestroyVideoDecodingExtension, wisInitVideoDecodingExtension, wisVideoDecodingExtensionSupported + * \endcond + */ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b6ed90c5..153c85d8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -52,3 +52,4 @@ add_example_suite(backend) add_example_suite(compute_particles_c) add_example_suite(hello_triangle) add_example_suite(multisampling) +add_example_suite(video) diff --git a/examples/video/CMakeLists.txt b/examples/video/CMakeLists.txt new file mode 100644 index 00000000..e083ade8 --- /dev/null +++ b/examples/video/CMakeLists.txt @@ -0,0 +1,17 @@ +project(video-${POSTFIX}) + +set(CPP_SOURCES entry_main.cpp) + +add_executable(${PROJECT_NAME}-cpp ${CPP_SOURCES}) +target_link_libraries( + ${PROJECT_NAME}-cpp PUBLIC wis::wisdom-headers wis::wisdom-platform-headers wis::wisdom-video-headers + SDL3::SDL3 example_backend_cpp-${POSTFIX}) +set_target_properties( + ${PROJECT_NAME}-cpp PROPERTIES CXX_STANDARD 23 RUNTIME_OUTPUT_DIRECTORY + ${EXAMPLE_BIN_OUTPUT}) +target_compile_definitions(${PROJECT_NAME}-cpp PUBLIC ${ADD_DEFINITIONS}) +add_dependencies(${PROJECT_NAME}-cpp copy_sdl wis_test_compile_shaders) + +if(POSTFIX STREQUAL "dx12" AND WISDOM_USE_AGILITY_SDK) + wis_install_agility_win32(TARGET ${PROJECT_NAME}-cpp PATCH_EXE) +endif() diff --git a/examples/video/entry_main.cpp b/examples/video/entry_main.cpp new file mode 100644 index 00000000..34e10b84 --- /dev/null +++ b/examples/video/entry_main.cpp @@ -0,0 +1,120 @@ +#include +#include + +static bool check_result(wis::Result result, const char* where) +{ + if (result.status == wis::Status::Ok) { + return true; + } + + std::printf( + "%s failed: %d, platform_code: %d, error: %s\n", + where, + static_cast(result.status), + result.platform_code, + result.error ? result.error : "None" + ); + return false; +} + +class Application +{ + static void log_callback(wis::Severity severity, const char* message, uint64_t, void*) + { + const char* severity_str = "UNKNOWN"; + switch (severity) { + case wis::Severity::Verbose: + severity_str = "VERBOSE"; + break; + case wis::Severity::Info: + severity_str = "INFO"; + break; + case wis::Severity::Warning: + severity_str = "WARNING"; + break; + case wis::Severity::Error: + severity_str = "ERROR"; + break; + case wis::Severity::Fatal: + severity_str = "FATAL"; + break; + default: + break; + } + + std::printf("[%s] %s\n", severity_str, message ? message : ""); + } + +public: + Application() + : video_extension{wis::VideoCodecFlags::AV1} + , device{CreateDevice()} + {} + +private: + wis::Device CreateDevice() + { + wis::Device device{}; + wis::Result result{}; + + wis::DebugDesc debug_desc = { + .enable_debug_layer = false, + .callback = log_callback, + }; + + wis::Instance instance = wis::CreateInstance(&debug_desc, {}, result); + if (!check_result(result, "CreateInstance")) { + return device; + } + + // Query adapters + wis::AdapterQuery adapters = instance.QueryAdapters(wis::AdapterPreference::Performance, result); + if (!check_result(result, "QueryAdapters")) { + return device; + } + + // Cycle through adapters and create device + wis::DeviceExtensionHeader* extensions[] = {&video_extension}; + wis::CommandQueueDesc queue_descs[] = { + {wis::CommandQueueType::VideoDecode, wis::CommandQueuePriority::Normal}, + }; + wis::DeviceRequirements requirements{ + .queue_descs = {queue_descs}, + .extensions = {extensions}, + }; + + for (size_t i = 0; i < adapters.GetAdapterCount(); ++i) { + device = adapters.CreateDevice(i, requirements, result); + if (result.status == wis::Status::Ok) { + // Get adapter description for logging purposes + wis::AdapterDesc adapter_desc = adapters.GetAdapterDesc(i, result); + std::printf( + "Successfully created device for adapter: %s, vendor_id: %u, device_id: %u\n", + adapter_desc.description.data(), + adapter_desc.vendor_id, + adapter_desc.device_id + ); + + break; + } + } + + if (video_extension.Supported()) { + std::printf("Video decoding is supported on this device.\n"); + } else { + std::printf("Video decoding is not supported on this device.\n"); + } + + return device; + } + +private: + wis::VideoDecodingExtension video_extension; + wis::Device device; +}; + +int main() +{ + Application app; + return 0; +} diff --git a/generator/function.cpp b/generator/function.cpp index 236204eb..b8a4f651 100644 --- a/generator/function.cpp +++ b/generator/function.cpp @@ -388,7 +388,18 @@ std::string Generator::MakeCPPFunctionProto( } max_arg_length = std::max(max_arg_length, type_str.length()); } - + if ((func.modifier & Modifier::Construct) != 0) { + return std::format( + "{}{}{}{}({}{}){} noexcept;\n", + func_prefix, + xclass_code, + func_prefix, + std::string_view(xclass_code.begin(), xclass_code.end() - 2), + params, + post_return, + func.modifier & Modifier::Const ? " const" : "" + ); + } return std::format( "{}{} {}{}{}({}{}){} noexcept;\n", pre_decl, @@ -468,49 +479,6 @@ std::string Generator::MakeCPPFunctionImpl( std::string body = "{\n"; constexpr static std::string_view arg_prefix = ",\n "; - auto set_params = [&]() { - for (size_t i = 0; i < func.parameters.size(); ++i) { - auto& p = func.parameters[i]; - - if (p.modifier & Modifier::Span) { - body += std::format( - "reinterpret_cast<{}>({}.data()), {}.size()", - GetMemberTypeString(p, backend), - p.name, - p.name - ); - i++; // skip next parameter (the size) - if (i < func.parameters.size() - 1) { - body += arg_prefix; - } - continue; - } - - switch (GetType(p.type)) { - case TypeKind::Enum: - case TypeKind::Bitmask: - body += std::format("static_cast<{}>({})", GetMemberTypeString(p, backend), p.name); - break; - case TypeKind::None: - case TypeKind::View: - case TypeKind::Base: - body += p.name; - break; - default: - if (p.modifier & Modifier::Reference) { - body += std::format("reinterpret_cast<{}>(&{})", GetMemberTypeString(p, backend), p.name); - break; - } - body += std::format("reinterpret_cast<{}>({})", GetMemberTypeString(p, backend), p.name); - break; - } - - if (i < func.parameters.size() - 1) { - body += arg_prefix; - } - } - }; - switch (func.return_type.GetKind()) { case ReturnTypeKind::ResultAndValue: { auto ret_value_name = func.return_type.opt_name.empty() @@ -530,7 +498,7 @@ std::string Generator::MakeCPPFunctionImpl( body += arg_prefix; } - set_params(); + body += GetFunctionCallParameters(func, backend); auto ret_type = GetType(func.return_type.type); @@ -557,7 +525,7 @@ std::string Generator::MakeCPPFunctionImpl( if (func.parameters.size() > 0 && !func.this_type.empty()) { body += arg_prefix; } - set_params(); + body += GetFunctionCallParameters(func, backend); body += ");\n"; body += " return wis::Result{ static_cast(wis_result.status), wis_result.platform_code, " "wis_result.error };\n"; @@ -595,7 +563,7 @@ std::string Generator::MakeCPPFunctionImpl( if (func.parameters.size() > 0 && !func.this_type.empty()) { body += arg_prefix; } - set_params(); + body += GetFunctionCallParameters(func, backend); body += "));\n"; } break; case ReturnTypeKind::Void: { @@ -604,7 +572,7 @@ std::string Generator::MakeCPPFunctionImpl( if (func.parameters.size() > 0 && !func.this_type.empty()) { body += arg_prefix; } - set_params(); + body += GetFunctionCallParameters(func, backend); body += ");\n"; } break; default: diff --git a/generator/generator.cpp b/generator/generator.cpp index 885075a3..09f04530 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp @@ -1931,3 +1931,49 @@ std::string Generator::GetRefs(std::string_view for_type) } return refs; } + +std::string Generator::GetFunctionCallParameters(const WisFunction& func, Backend backend) { + constexpr static std::string_view arg_prefix = ",\n "; + std::string body; + for (size_t i = 0; i < func.parameters.size(); ++i) { + auto& p = func.parameters[i]; + + if (p.modifier & Modifier::Span) { + body += std::format( + "reinterpret_cast<{}>({}.data()), {}.size()", + GetMemberTypeString(p, backend), + p.name, + p.name + ); + i++; // skip next parameter (the size) + if (i < func.parameters.size() - 1) { + body += arg_prefix; + } + continue; + } + + switch (GetType(p.type)) { + case TypeKind::Enum: + case TypeKind::Bitmask: + body += std::format("static_cast<{}>({})", GetMemberTypeString(p, backend), p.name); + break; + case TypeKind::None: + case TypeKind::View: + case TypeKind::Base: + body += p.name; + break; + default: + if (p.modifier & Modifier::Reference) { + body += std::format("reinterpret_cast<{}>(&{})", GetMemberTypeString(p, backend), p.name); + break; + } + body += std::format("reinterpret_cast<{}>({})", GetMemberTypeString(p, backend), p.name); + break; + } + + if (i < func.parameters.size() - 1) { + body += arg_prefix; + } + } + return body; +} diff --git a/generator/generator.hpp b/generator/generator.hpp index 077328f2..ed81b818 100644 --- a/generator/generator.hpp +++ b/generator/generator.hpp @@ -151,6 +151,7 @@ class Generator void TryMakeRef(std::string_view type, std::string_view from); void TryMakeRef(std::string_view type, FunctionKey from); std::string GetRefs(std::string_view for_type); + std::string GetFunctionCallParameters(const WisFunction& func, Backend backend); static Backend ParseBackend(std::string_view backend) noexcept; static ImplOs GetImplOs(std::string_view os) noexcept; diff --git a/generator/handle.cpp b/generator/handle.cpp index 337050a2..4214ad93 100644 --- a/generator/handle.cpp +++ b/generator/handle.cpp @@ -87,6 +87,40 @@ void Generator::ParseHandles(tinyxml2::XMLElement* types) create.modifier = Modifier::Construct; create.version = version; create.doc = create_doc; + + if (auto* init = type->FirstChildElement("init")) { + if (auto* vers = init->FindAttribute("version")) { + create.version = vers->Value(); + } + + if (auto* doc = init->FindAttribute("doc")) { + create.doc = doc->Value(); + } + + // Parse parameters + for (auto* param = init->FirstChildElement("arg"); param; param = param->NextSiblingElement("arg")) { + auto& p = create.parameters.emplace_back(); + p.type = param->FindAttribute("type")->Value(); + + if (auto* name_attr = param->FindAttribute("name")) { + p.name = name_attr->Value(); + } else { + throw std::runtime_error(std::format("Function {} has a parameter with no name.", create_name)); + } + if (auto* def = param->FindAttribute("default")) { + p.default_value = def->Value(); + } + if (auto* mod = param->FindAttribute("mod")) { + p.modifier = GetModifiers(mod->Value()); + } + if (auto* doc = param->FindAttribute("doc")) { + p.doc = doc->Value(); + } + create.FilterBackend(GetTypeBackendSupport(p.type)); + TryMakeRef(p.type, create_key); + } + } + create.FilterBackend(ref.GetBackend()); type_map[iref] = TypeKind::Function; module_map[active_module_name].functions_in_order.emplace_back(create_key); @@ -196,9 +230,7 @@ std::string Generator::MakeCPPHandle(const WisHandle& s, Backend backend, DocKin std::string ctor_decl; // Use constructor from base - if (s.extends != Extends::None) { - ctor_decl += std::format("{}{}() noexcept\n:ImplType(wis::in_place)\n{{\n ", impl_string, s.name); - } else { + if (s.extends == Extends::None) { ctor_decl += " using ImplType::ImplType;\n"; } std::string st_decl2 = "public:\n"; @@ -242,7 +274,49 @@ std::string Generator::MakeCPPHandle(const WisHandle& s, Backend backend, DocKin continue; } if (func_ref.modifier & Modifier::Construct) { - ctor_decl += std::format(" ::{}(GetStorage());\n }}\n", c_name); + // Build the init function parameter list for the constructor + std::string params; + std::string args = "GetStorage(), " + GetFunctionCallParameters(func_ref, backend); + bool last_was_span = false; + for (size_t i = 0; i < func_ref.parameters.size(); ++i) { + if (last_was_span) { + last_was_span = false; + continue; + } + + const auto& p = func_ref.parameters[i]; + if (p.modifier & Modifier::Span) { + last_was_span = true; + } + + std::string type_str = GetMemberTypeString(p, backend); + params += std::format("{} {}", type_str, p.name); + + // edge case for spans - if last argument was a span, skip the next one (the size) + // That means we need to check if i + $) + +target_link_libraries(wisdom-video-headers INTERFACE wis::wisdom-headers) +target_compile_definitions( + wisdom-video-headers INTERFACE WISDOM_VIDEO_STATIC=1) + +install( + TARGETS wisdom-video-headers + EXPORT wisdom-video-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Platform library target +if(WISDOM_BUILD_STATIC) + add_library(wisdom-video STATIC ${WISDOM_VIDEO_SOURCES}) + add_library(wis::wisdom-video ALIAS wisdom-video) + + target_link_libraries(wisdom-video PRIVATE wisdom) + target_compile_definitions(wisdom-video PUBLIC WISDOM_VIDEO_STATIC=1) + target_include_directories( + wisdom-video PUBLIC $ + $) + + set_target_properties( + wisdom-video PROPERTIES CXX_STANDARD 20 + DEBUG_POSTFIX d) + + install( + TARGETS wisdom-video + EXPORT wisdom-video-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() + +if(WISDOM_BUILD_SHARED) + add_library(wisdom-video-shared SHARED ${WISDOM_VIDEO_SOURCES}) + add_library(wis::wisdom-video-shared ALIAS wisdom-video-shared) + + target_link_libraries(wisdom-video-shared PRIVATE wisdom-shared) + target_include_directories( + wisdom-video-shared + PUBLIC $ + $) + target_compile_definitions( + wisdom-video-shared + PUBLIC WISDOM_VIDEO_SHARED_LIBRARY=1 + PRIVATE video_shared_EXPORTS=1) + + set_target_properties( + wisdom-video-shared + PROPERTIES CXX_STANDARD 20 + POSITION_INDEPENDENT_CODE ON + DEBUG_POSTFIX d) + + include(GenerateExportHeader) + generate_export_header( + wisdom-video-shared + BASE_NAME + WISDOM_VIDEO + EXPORT_MACRO_NAME + WISDOM_VIDEO_API + EXPORT_FILE_NAME + ${CMAKE_CURRENT_SOURCE_DIR}/video/generated/wisdom_exports.h + STATIC_DEFINE + WISDOM_VIDEO_STATIC + INCLUDE_GUARD_NAME + WISDOM_VIDEO_EXPORTS_H) + + install( + TARGETS wisdom-video-shared + EXPORT wisdom-video-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/video/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/video) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom) + +install( + EXPORT wisdom-video-targets + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom + NAMESPACE wis:: + FILE wisdom-video-targets.cmake) \ No newline at end of file diff --git a/src/extensions/video/video/dx12/dx12_types.hpp b/src/extensions/video/video/dx12/dx12_types.hpp new file mode 100644 index 00000000..d29b54d0 --- /dev/null +++ b/src/extensions/video/video/dx12/dx12_types.hpp @@ -0,0 +1,30 @@ +#ifndef WIS_DX12_VIDEO_TYPES_HPP +#define WIS_DX12_VIDEO_TYPES_HPP +#ifndef __cplusplus +# error "This header requires C++" +#endif // __cplusplus + +namespace wis { +//---------------------------------------------------------------------------------------------------------------------- +namespace detail {} // namespace detail + +namespace impl { +struct DX12VideoDecodingExtensionImpl { + DX12DeviceExtensionHeader header; + WisVideoCodecFlags supported_codecs; + ID3D12Device10* device; +}; + + +} // namespace impl +} // namespace wis + +// Include implementation for header-only mode +#ifdef WISDOM_HEADER_ONLY +# if !WIS_HAS_CPP20 && !defined(WISDOM_LANG_DISABLE_CHECK) +# error "C++20 is required to build wisdom as header-only library" +# endif // !WIS_HAS_CPP20 +# include "dx12_video.cpp" + +#endif // WISDOM_HEADER_ONLY +#endif // WIS_DX12_VIDEO_TYPES_HPP diff --git a/src/extensions/video/video/dx12/dx12_video.cpp b/src/extensions/video/video/dx12/dx12_video.cpp new file mode 100644 index 00000000..35b636ee --- /dev/null +++ b/src/extensions/video/video/dx12/dx12_video.cpp @@ -0,0 +1,84 @@ +#ifndef WIS_DX12_VIDEO_CPP +#define WIS_DX12_VIDEO_CPP + +#include +#include