// Unity Native Plugin API copyright © 2015 Unity Technologies ApS // // Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). // // Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. #pragma once #include "IUnityInterface.h" #ifndef UNITY_VULKAN_HEADER #define UNITY_VULKAN_HEADER #endif #include UNITY_VULKAN_HEADER struct UnityVulkanInstance { VkPipelineCache pipelineCache; // Unity's pipeline cache is serialized to disk VkInstance instance; VkPhysicalDevice physicalDevice; VkDevice device; VkQueue graphicsQueue; PFN_vkGetInstanceProcAddr getInstanceProcAddr; // vkGetInstanceProcAddr of the Vulkan loader, same as the one passed to UnityVulkanInitCallback unsigned int queueFamilyIndex; void* reserved[8]; }; struct UnityVulkanMemory { VkDeviceMemory memory; // Vulkan memory handle VkDeviceSize offset; // offset within memory VkDeviceSize size; // size in bytes, may be less than the total size of memory; void* mapped; // pointer to mapped memory block, NULL if not mappable, offset is already applied, remaining block still has at least the given size. VkMemoryPropertyFlags flags; // Vulkan memory properties unsigned int memoryTypeIndex; // index into VkPhysicalDeviceMemoryProperties::memoryTypes void* reserved[4]; }; enum UnityVulkanResourceAccessMode { // Does not imply any pipeline barriers, should only be used to query resource attributes kUnityVulkanResourceAccess_ObserveOnly, // Handles layout transition and barriers kUnityVulkanResourceAccess_PipelineBarrier, // Recreates the backing resource (VkBuffer/VkImage) but keeps the previous one alive if it's in use kUnityVulkanResourceAccess_Recreate, }; struct UnityVulkanImage { UnityVulkanMemory memory; // memory that backs the image VkImage image; // Vulkan image handle VkImageLayout layout; // current layout, may change resource access VkImageAspectFlags aspect; VkImageUsageFlags usage; VkFormat format; VkExtent3D extent; VkImageTiling tiling; VkImageType type; VkSampleCountFlagBits samples; int layers; int mipCount; void* reserved[4]; }; struct UnityVulkanBuffer { UnityVulkanMemory memory; // memory that backs the buffer VkBuffer buffer; // Vulkan buffer handle size_t sizeInBytes; // size of the buffer in bytes, may be less than memory size VkBufferUsageFlags usage; void* reserved[4]; }; struct UnityVulkanRecordingState { VkCommandBuffer commandBuffer; // Vulkan command buffer that is currently recorded by Unity VkCommandBufferLevel commandBufferLevel; VkRenderPass renderPass; // Current render pass, a compatible one or VK_NULL_HANDLE VkFramebuffer framebuffer; // Current framebuffer or VK_NULL_HANDLE int subPassIndex; // index of the current sub pass, -1 if not inside a render pass // Resource life-time tracking counters, only relevant for resources allocated by the plugin unsigned long long currentFrameNumber; // can be used to track lifetime of own resources unsigned long long safeFrameNumber; // all resources that were used in this frame (or before) are safe to be released void* reserved[4]; }; enum UnityVulkanEventRenderPassPreCondition { // Don't care about the state on Unity's current command buffer // This is the default precondition kUnityVulkanRenderPass_DontCare, // Make sure that there is currently RenderPass in progress. // There are no guarantees about the currently bound descriptor sets, vertex buffers, index buffers and pipeline objects // Unity does however set dynamic pipeline set VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR based on the current settings // If used in combination with the SRP RenderPass API the resuls is undefined kUnityVulkanRenderPass_EnsureInside, // Make sure that there is currently no RenderPass in progress. // This allows e.g. resource uploads. // Ends the current render pass (and resumes it afterwards if needed) // If used in combination with the SRP RenderPass API the resuls is undefined. kUnityVulkanRenderPass_EnsureOutside }; enum UnityVulkanGraphicsQueueAccess { // No queue acccess, no work must be submitted to UnityVulkanInstance::graphicsQueue from the plugin event callback kUnityVulkanGraphicsQueueAccess_DontCare, // Make sure that Unity worker threads don't access the Vulkan graphics queue // This disables access to the current Unity command buffer kUnityVulkanGraphicsQueueAccess_Allow, }; enum UnityVulkanEventConfigFlagBits { kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission = (1 << 0), // default: set kUnityVulkanEventConfigFlag_FlushCommandBuffers = (1 << 1), // submit existing command buffers, default: not set kUnityVulkanEventConfigFlag_SyncWorkerThreads = (1 << 2), // wait for worker threads to finish, default: not set kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState = (1 << 3), // should be set when descriptor set bindings, vertex buffer bindings, etc are changed (default: set) }; struct UnityVulkanPluginEventConfig { UnityVulkanEventRenderPassPreCondition renderPassPrecondition; UnityVulkanGraphicsQueueAccess graphicsQueueAccess; uint32_t flags; }; // Constant that can be used to reference the whole image const VkImageSubresource* const UnityVulkanWholeImage = NULL; // callback function, see InterceptInitialization typedef PFN_vkGetInstanceProcAddr(UNITY_INTERFACE_API * UnityVulkanInitCallback)(PFN_vkGetInstanceProcAddr getInstanceProcAddr, void* userdata); enum UnityVulkanSwapchainMode { kUnityVulkanSwapchainMode_Default, kUnityVulkanSwapchainMode_Offscreen }; struct UnityVulkanSwapchainConfiguration { UnityVulkanSwapchainMode mode; }; enum { kUnityVulkanInitCallbackMaxPriority = 0x7FFFFFFF }; UNITY_DECLARE_INTERFACE(IUnityGraphicsVulkanV2) { // Vulkan API hooks // // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) // Unity will call 'func' when initializing the Vulkan API // The 'getInstanceProcAddr' passed to the callback is the function pointer from the Vulkan Loader // The function pointer returned from UnityVulkanInitCallback may be a different implementation // This allows intercepting all Vulkan API calls // This function is equivalent to calling `AddInterceptInitialization` with a priority of `kUnityVulkanInitCallbackMaxPriority` // // Most rules/restrictions for implementing a Vulkan layer apply // Returns true on success, false on failure (typically because it is used too late) bool(UNITY_INTERFACE_API * InterceptInitialization)(UnityVulkanInitCallback func, void* userdata); // Intercept Vulkan API function of the given name with the given function // In contrast to InterceptInitialization this interface can be used at any time // The user must handle all synchronization // Generally this cannot be used to wrap Vulkan object because there might because there may already be non-wrapped instances // returns the previous function pointer PFN_vkVoidFunction(UNITY_INTERFACE_API * InterceptVulkanAPI)(const char* name, PFN_vkVoidFunction func); // Change the precondition for a specific user-defined event // Should be called during initialization void(UNITY_INTERFACE_API * ConfigureEvent)(int eventID, const UnityVulkanPluginEventConfig * pluginEventConfig); // Access the Vulkan instance and render queue created by Unity // UnityVulkanInstance does not change between kUnityGfxDeviceEventInitialize and kUnityGfxDeviceEventShutdown UnityVulkanInstance(UNITY_INTERFACE_API * Instance)(); // Access the current command buffer // // outCommandRecordingState is invalidated by any resource access calls. // queueAccess must be kUnityVulkanGraphicsQueueAccess_Allow when called from from a AccessQueue callback or from a event that is configured for queue access. // Otherwise queueAccess must be kUnityVulkanGraphicsQueueAccess_DontCare. bool(UNITY_INTERFACE_API * CommandRecordingState)(UnityVulkanRecordingState * outCommandRecordingState, UnityVulkanGraphicsQueueAccess queueAccess); // Resource access // // Using the following resource query APIs will mark the resources as used for the current frame. // Pipeline barriers will be inserted when needed. // // Resource access APIs may record commands, so the current UnityVulkanRecordingState is invalidated // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow) // or from a AccessQueue callback of an event bool(UNITY_INTERFACE_API * AccessTexture)(void* nativeTexture, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessRenderBufferTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessRenderBufferResolveTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessBuffer)(void* nativeBuffer, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanBuffer * outBuffer); // Control current state of render pass // // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow, UnityVulkanGraphicsQueueAccess_FlushAndAllow) // or from a AccessQueue callback of an event // See kUnityVulkanRenderPass_EnsureInside, kUnityVulkanRenderPass_EnsureOutside void(UNITY_INTERFACE_API * EnsureOutsideRenderPass)(); void(UNITY_INTERFACE_API * EnsureInsideRenderPass)(); // Allow command buffer submission to the the Vulkan graphics queue from the given UnityRenderingEventAndData callback. // This is an alternative to using ConfigureEvent with kUnityVulkanGraphicsQueueAccess_Allow. // // eventId and userdata are passed to the callback // This may or may not be called synchronously or from the submission thread. // If flush is true then all Unity command buffers of this frame are submitted before UnityQueueAccessCallback void(UNITY_INTERFACE_API * AccessQueue)(UnityRenderingEventAndData, int eventId, void* userData, bool flush); // Configure swapchains that are created by Unity. // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) bool(UNITY_INTERFACE_API * ConfigureSwapchain)(const UnityVulkanSwapchainConfiguration * swapChainConfig); // see AccessTexture // Accepts UnityTextureID (UnityRenderingExtTextureUpdateParamsV2::textureID, UnityRenderingExtCustomBlitParams::source) bool(UNITY_INTERFACE_API * AccessTextureByID)(UnityTextureID textureID, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); // Vulkan API hooks // // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) // Unity will call 'func' when initializing the Vulkan API // The 'getInstanceProcAddr' passed to the callback is the function pointer from the Vulkan Loader // The function pointer returned from UnityVulkanInitCallback may be a different implementation // This allows intercepting all Vulkan API calls // The priority is used to sort multiple callbacks such that the highest priority will be called last // with the original Vulkan loader implementation of vkGetInstanceProcAddress passed in as 'getInstanceProcAddr'. // A priority value of `kUnityVulkanInitCallbackMaxPriority` is used to force a callback to be called immediately before // the original Vulkan loader implementation of `vkGetInstanceProcAddress`. Only one callback can be registered with a // priority of `kUnityVulkanInitCallbackMaxPriority`, if one already exists it will be replaced. // Passing a priority value of `kUnityVulkanInitCallbackMaxPriority` is equivalent to calling the `InterceptInitialization` method. // // Most rules/restrictions for implementing a Vulkan layer apply // Returns true on success, false on failure (typically because it is used too late) bool(UNITY_INTERFACE_API * AddInterceptInitialization)(UnityVulkanInitCallback func, void* userdata, int32_t priority); // Remove vulkan intercept initialization callback. // Removal will not take effect until the next time vulkan is initialized. bool(UNITY_INTERFACE_API * RemoveInterceptInitialization)(UnityVulkanInitCallback func); }; UNITY_REGISTER_INTERFACE_GUID(0x329334C09DCA4787ULL, 0xB347DD92A0097FFCULL, IUnityGraphicsVulkanV2) UNITY_DECLARE_INTERFACE(IUnityGraphicsVulkan) { // Vulkan API hooks // // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) // Unity will call 'func' when initializing the Vulkan API // The 'getInstanceProcAddr' passed to the callback is the function pointer from the Vulkan Loader // The function pointer returned from UnityVulkanInitCallback may be a different implementation // This allows intercepting all Vulkan API calls // // Most rules/restrictions for implementing a Vulkan layer apply // Returns true on success, false on failure (typically because it is used too late) bool(UNITY_INTERFACE_API * InterceptInitialization)(UnityVulkanInitCallback func, void* userdata); // Intercept Vulkan API function of the given name with the given function // In contrast to InterceptInitialization this interface can be used at any time // The user must handle all synchronization // Generally this cannot be used to wrap Vulkan object because there might because there may already be non-wrapped instances // returns the previous function pointer PFN_vkVoidFunction(UNITY_INTERFACE_API * InterceptVulkanAPI)(const char* name, PFN_vkVoidFunction func); // Change the precondition for a specific user-defined event // Should be called during initialization void(UNITY_INTERFACE_API * ConfigureEvent)(int eventID, const UnityVulkanPluginEventConfig * pluginEventConfig); // Access the Vulkan instance and render queue created by Unity // UnityVulkanInstance does not change between kUnityGfxDeviceEventInitialize and kUnityGfxDeviceEventShutdown UnityVulkanInstance(UNITY_INTERFACE_API * Instance)(); // Access the current command buffer // // outCommandRecordingState is invalidated by any resource access calls. // queueAccess must be kUnityVulkanGraphicsQueueAccess_Allow when called from from a AccessQueue callback or from a event that is configured for queue access. // Otherwise queueAccess must be kUnityVulkanGraphicsQueueAccess_DontCare. bool(UNITY_INTERFACE_API * CommandRecordingState)(UnityVulkanRecordingState * outCommandRecordingState, UnityVulkanGraphicsQueueAccess queueAccess); // Resource access // // Using the following resource query APIs will mark the resources as used for the current frame. // Pipeline barriers will be inserted when needed. // // Resource access APIs may record commands, so the current UnityVulkanRecordingState is invalidated // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow) // or from a AccessQueue callback of an event bool(UNITY_INTERFACE_API * AccessTexture)(void* nativeTexture, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessRenderBufferTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessRenderBufferResolveTexture)(UnityRenderBuffer nativeRenderBuffer, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); bool(UNITY_INTERFACE_API * AccessBuffer)(void* nativeBuffer, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanBuffer * outBuffer); // Control current state of render pass // // Must not be called from event callbacks configured for queue access (UnityVulkanGraphicsQueueAccess_Allow, UnityVulkanGraphicsQueueAccess_FlushAndAllow) // or from a AccessQueue callback of an event // See kUnityVulkanRenderPass_EnsureInside, kUnityVulkanRenderPass_EnsureOutside void(UNITY_INTERFACE_API * EnsureOutsideRenderPass)(); void(UNITY_INTERFACE_API * EnsureInsideRenderPass)(); // Allow command buffer submission to the the Vulkan graphics queue from the given UnityRenderingEventAndData callback. // This is an alternative to using ConfigureEvent with kUnityVulkanGraphicsQueueAccess_Allow. // // eventId and userdata are passed to the callback // This may or may not be called synchronously or from the submission thread. // If flush is true then all Unity command buffers of this frame are submitted before UnityQueueAccessCallback void(UNITY_INTERFACE_API * AccessQueue)(UnityRenderingEventAndData, int eventId, void* userData, bool flush); // Configure swapchains that are created by Unity. // Must be called before kUnityGfxDeviceEventInitialize (preload plugin) bool(UNITY_INTERFACE_API * ConfigureSwapchain)(const UnityVulkanSwapchainConfiguration * swapChainConfig); // see AccessTexture // Accepts UnityTextureID (UnityRenderingExtTextureUpdateParamsV2::textureID, UnityRenderingExtCustomBlitParams::source) bool(UNITY_INTERFACE_API * AccessTextureByID)(UnityTextureID textureID, const VkImageSubresource * subResource, VkImageLayout layout, VkPipelineStageFlags pipelineStageFlags, VkAccessFlags accessFlags, UnityVulkanResourceAccessMode accessMode, UnityVulkanImage * outImage); }; UNITY_REGISTER_INTERFACE_GUID(0x95355348d4ef4e11ULL, 0x9789313dfcffcc87ULL, IUnityGraphicsVulkan)