2024-11-01 16:55:46 +08:00
# include "RenderAPI.h"
# include "PlatformBase.h"
# if SUPPORT_VULKAN
2024-11-22 12:09:31 +08:00
# include <string>
2024-11-01 16:55:46 +08:00
# include <map>
# include <vector>
2025-03-14 17:42:21 +08:00
# include <set>
2024-11-01 16:55:46 +08:00
# include <math.h>
2024-11-22 12:09:31 +08:00
# include <algorithm>
2024-11-01 16:55:46 +08:00
// This plugin does not link to the Vulkan loader, easier to support multiple APIs and systems that don't have Vulkan support
# define VK_NO_PROTOTYPES
# include "Unity/IUnityGraphicsVulkan.h"
2024-11-22 12:09:31 +08:00
# define UNITY_USED_VULKAN_API_FUNCTIONS(apply) \
apply ( vkCreateInstance ) ; \
apply ( vkCmdBeginRenderPass ) ; \
apply ( vkCreateBuffer ) ; \
apply ( vkGetPhysicalDeviceMemoryProperties ) ; \
apply ( vkGetBufferMemoryRequirements ) ; \
apply ( vkMapMemory ) ; \
apply ( vkBindBufferMemory ) ; \
apply ( vkAllocateMemory ) ; \
apply ( vkDestroyBuffer ) ; \
apply ( vkFreeMemory ) ; \
apply ( vkUnmapMemory ) ; \
apply ( vkQueueWaitIdle ) ; \
apply ( vkDeviceWaitIdle ) ; \
apply ( vkCmdCopyBufferToImage ) ; \
apply ( vkFlushMappedMemoryRanges ) ; \
apply ( vkCreatePipelineLayout ) ; \
apply ( vkCreateShaderModule ) ; \
apply ( vkDestroyShaderModule ) ; \
apply ( vkCreateGraphicsPipelines ) ; \
apply ( vkCmdBindPipeline ) ; \
apply ( vkCmdDraw ) ; \
apply ( vkCmdPushConstants ) ; \
apply ( vkCmdBindVertexBuffers ) ; \
apply ( vkDestroyPipeline ) ; \
apply ( vkCmdSetFragmentShadingRateKHR ) ; \
apply ( vkCmdBindDescriptorSets ) ; \
apply ( vkCreateDevice ) ; \
apply ( vkGetPhysicalDeviceFeatures2 ) ; \
apply ( vkGetPhysicalDeviceProperties2 ) ; \
apply ( vkEnumerateDeviceExtensionProperties ) ; \
apply ( vkGetPhysicalDeviceProperties2KHR ) ; \
2025-03-14 17:42:21 +08:00
apply ( vkCreateRenderPass ) ; \
apply ( vkCreateRenderPass2KHR ) ; \
2024-11-01 16:55:46 +08:00
apply ( vkDestroyPipelineLayout ) ;
# define VULKAN_DEFINE_API_FUNCPTR(func) static PFN_##func func
VULKAN_DEFINE_API_FUNCPTR ( vkGetInstanceProcAddr ) ;
UNITY_USED_VULKAN_API_FUNCTIONS ( VULKAN_DEFINE_API_FUNCPTR ) ;
# undef VULKAN_DEFINE_API_FUNCPTR
2024-11-22 12:09:31 +08:00
# if OHOS
# include "xengine/xeg_vulkan_adaptive_vrs.h"
# include "xengine/xeg_vulkan_spatial_upscale.h"
# include "xengine/xeg_vulkan_extension.h"
# endif
extern void unityLog ( const char * msg ) ;
2024-11-01 16:55:46 +08:00
enum VRSPluginShadingRate
{
X1_PER_PIXEL ,
X1_PER_2X1_PIXELS ,
X1_PER_1X2_PIXELS ,
X1_PER_2X2_PIXELS ,
X1_PER_4X2_PIXELS ,
X1_PER_2X4_PIXELS ,
X1_PER_4X4_PIXELS ,
} ;
2024-11-22 12:09:31 +08:00
static VkExtent2D vrs_argment_size_table [ ] = {
VkExtent2D { 1 , 1 } ,
VkExtent2D { 2 , 1 } ,
VkExtent2D { 1 , 2 } ,
VkExtent2D { 2 , 2 } ,
VkExtent2D { 4 , 2 } ,
VkExtent2D { 2 , 4 } ,
VkExtent2D { 4 , 4 } ,
2024-11-01 16:55:46 +08:00
} ;
2024-11-22 12:09:31 +08:00
static VkExtent2D vrs_fragment_size = vrs_argment_size_table [ 0 ] ;
2024-11-01 16:55:46 +08:00
static bool vrs_enable ;
2025-03-14 17:42:21 +08:00
static int cur_vrs_Index = 0 ;
static bool blend_state_hook_enable ;
2024-11-01 16:55:46 +08:00
static void LoadVulkanAPI ( PFN_vkGetInstanceProcAddr getInstanceProcAddr , VkInstance instance )
{
2024-11-22 12:09:31 +08:00
unityLog ( " LoadVulkanAPI called. " ) ;
2024-11-01 16:55:46 +08:00
if ( ! vkGetInstanceProcAddr & & getInstanceProcAddr )
vkGetInstanceProcAddr = getInstanceProcAddr ;
2024-11-22 12:09:31 +08:00
if ( ! vkCreateInstance )
vkCreateInstance = ( PFN_vkCreateInstance ) vkGetInstanceProcAddr ( VK_NULL_HANDLE , " vkCreateInstance " ) ;
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
# define LOAD_VULKAN_FUNC(fn) \
if ( ! fn ) \
fn = ( PFN_ # # fn ) vkGetInstanceProcAddr ( instance , # fn )
2024-11-01 16:55:46 +08:00
UNITY_USED_VULKAN_API_FUNCTIONS ( LOAD_VULKAN_FUNC ) ;
# undef LOAD_VULKAN_FUNC
}
2024-11-22 12:09:31 +08:00
static VKAPI_ATTR void VKAPI_CALL Hook_vkCmdBeginRenderPass ( VkCommandBuffer commandBuffer , const VkRenderPassBeginInfo * pRenderPassBegin , VkSubpassContents contents )
2024-11-01 16:55:46 +08:00
{
// Change this to 'true' to override the clear color with green
2024-11-22 12:09:31 +08:00
const bool allowOverrideClearColor = false ;
2024-11-01 16:55:46 +08:00
if ( pRenderPassBegin - > clearValueCount < = 16 & & pRenderPassBegin - > clearValueCount > 0 & & allowOverrideClearColor )
{
VkClearValue clearValues [ 16 ] = { } ;
memcpy ( clearValues , pRenderPassBegin - > pClearValues , pRenderPassBegin - > clearValueCount * sizeof ( VkClearValue ) ) ;
VkRenderPassBeginInfo patchedBeginInfo = * pRenderPassBegin ;
patchedBeginInfo . pClearValues = clearValues ;
for ( unsigned int i = 0 ; i < pRenderPassBegin - > clearValueCount - 1 ; + + i )
{
clearValues [ i ] . color . float32 [ 0 ] = 0.0 ;
clearValues [ i ] . color . float32 [ 1 ] = 1.0 ;
clearValues [ i ] . color . float32 [ 2 ] = 0.0 ;
clearValues [ i ] . color . float32 [ 3 ] = 1.0 ;
}
vkCmdBeginRenderPass ( commandBuffer , & patchedBeginInfo , contents ) ;
}
else
{
vkCmdBeginRenderPass ( commandBuffer , pRenderPassBegin , contents ) ;
}
}
2024-11-22 12:09:31 +08:00
static VKAPI_ATTR VkResult VKAPI_CALL Hook_vkCreateInstance ( const VkInstanceCreateInfo * pCreateInfo , const VkAllocationCallbacks * pAllocator , VkInstance * pInstance )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
unityLog ( " Hook_vkCreateInstance called. " ) ;
2024-11-01 16:55:46 +08:00
if ( pCreateInfo - > ppEnabledExtensionNames )
{
for ( size_t i = 0 ; i < pCreateInfo - > enabledExtensionCount ; i + + )
{
2024-11-22 12:09:31 +08:00
unityLog ( pCreateInfo - > ppEnabledExtensionNames [ i ] ) ;
2024-11-01 16:55:46 +08:00
}
}
vkCreateInstance = ( PFN_vkCreateInstance ) vkGetInstanceProcAddr ( VK_NULL_HANDLE , " vkCreateInstance " ) ;
VkResult result = vkCreateInstance ( pCreateInfo , pAllocator , pInstance ) ;
if ( result = = VK_SUCCESS )
LoadVulkanAPI ( vkGetInstanceProcAddr , * pInstance ) ;
2024-11-22 12:09:31 +08:00
2024-11-01 16:55:46 +08:00
return result ;
}
2024-11-22 12:09:31 +08:00
static VKAPI_ATTR VkResult VKAPI_CALL Hook_vkCreateDevice ( VkPhysicalDevice physicalDevice , const VkDeviceCreateInfo * pCreateInfo , const VkAllocationCallbacks * pAllocator , VkDevice * pDevice )
2024-11-01 16:55:46 +08:00
{
if ( pCreateInfo - > pNext )
{
2024-11-22 12:09:31 +08:00
unityLog ( " pCreateInfo->pNext " ) ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
return vkCreateDevice ( physicalDevice , pCreateInfo , pAllocator , pDevice ) ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
static VKAPI_ATTR void VKAPI_CALL Hook_vkCmdBindDescriptorSets ( VkCommandBuffer commandBuffer , VkPipelineBindPoint pipelineBindPoint ,
VkPipelineLayout layout , uint32_t firstSet ,
uint32_t descriptorSetCount , const VkDescriptorSet * pDescriptorSets ,
uint32_t dynamicOffsetCount , const uint32_t * pDynamicOffsets )
2024-11-01 16:55:46 +08:00
{
if ( vrs_enable )
{
2025-03-14 17:42:21 +08:00
VkExtent2D fragment_size = vrs_argment_size_table [ cur_vrs_Index ] ;
2024-11-01 16:55:46 +08:00
VkFragmentShadingRateCombinerOpKHR combiner_ops [ 2 ] ;
// If shading rate from attachment is enabled, we set the combiner, so that the values from the attachment are used
// Combiner for pipeline (A) and primitive (B) - Not used in this sample
combiner_ops [ 0 ] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR ;
// Combiner for pipeline (A) and attachment (B), replace the pipeline default value (fragment_size) with the fragment sizes stored in the attachment
combiner_ops [ 1 ] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR ;
vkCmdSetFragmentShadingRateKHR ( commandBuffer , & fragment_size , combiner_ops ) ;
}
vkCmdBindDescriptorSets ( commandBuffer , pipelineBindPoint , layout , firstSet , descriptorSetCount , pDescriptorSets , dynamicOffsetCount , pDynamicOffsets ) ;
}
static VKAPI_ATTR void VKAPI_CALL Hook_vkCmdBindPipeline ( VkCommandBuffer commandBuffer , VkPipelineBindPoint pipelineBindPoint , VkPipeline pipeline )
{
2024-11-22 12:09:31 +08:00
// if (vrs_enable)
//{
2025-03-14 17:42:21 +08:00
// VkExtent2D fragment_size = vrs_argment_size_table[cur_vrs_Index];
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
// VkFragmentShadingRateCombinerOpKHR combiner_ops[2];
// // If shading rate from attachment is enabled, we set the combiner, so that the values from the attachment are used
// // Combiner for pipeline (A) and primitive (B) - Not used in this sample
// combiner_ops[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR;
// // Combiner for pipeline (A) and attachment (B), replace the pipeline default value (fragment_size) with the fragment sizes stored in the attachment
// combiner_ops[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR;
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
// vkCmdSetFragmentShadingRateKHR(commandBuffer, &fragment_size, combiner_ops);
//}
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
vkCmdBindPipeline ( commandBuffer , pipelineBindPoint , pipeline ) ;
2024-11-01 16:55:46 +08:00
}
2025-03-14 17:42:21 +08:00
// static VKAPI_ATTR VkResult VKAPI_CALL Hook_vkCreateRenderPass(
// VkDevice device,
// const VkRenderPassCreateInfo* pCreateInfo,
// const VkAllocationCallbacks* pAllocator,
// VkRenderPass* pRenderPass
// )
// {
// auto ret = vkCreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
// char buf[80];
// sprintf(buf, "vkCreateRenderPass---1: %p \n", *pRenderPass);
// unityLog(buf);
// return ret;
// }
2025-04-02 17:11:10 +08:00
static std : : set < void * > need_create_pso_renderpasses ;
2025-03-14 17:42:21 +08:00
static std : : set < void * > created_pipeline_shader_module ;
static VKAPI_ATTR VkResult VKAPI_CALL Hook_vkCreateRenderPass2KHR (
VkDevice device ,
const VkRenderPassCreateInfo2 * pCreateInfo ,
const VkAllocationCallbacks * pAllocator ,
VkRenderPass * pRenderPass
)
{
//if (blend_state_hook_enable)
//{
// unityLog("Hook_vkCreateRenderPass called.");
// if (pCreateInfo->attachmentCount == 2)
// {
// const_cast<VkRenderPassCreateInfo2*>(pCreateInfo)->attachmentCount = 3;
// VkAttachmentDescription2 color_attachments[] = {
// pCreateInfo->pAttachments[0],
// pCreateInfo->pAttachments[0],
// pCreateInfo->pAttachments[1],
// };
// const_cast<VkRenderPassCreateInfo2*>(pCreateInfo)->pAttachments = color_attachments;
// const_cast<VkSubpassDescription2*>(pCreateInfo->pSubpasses)->colorAttachmentCount = 2;
// VkAttachmentReference2 color_attachment_refs[] = {
// pCreateInfo->pSubpasses->pColorAttachments[0],
// pCreateInfo->pSubpasses->pColorAttachments[0],
// };
// color_attachment_refs[1].attachment = 1;
// const_cast<VkSubpassDescription2*>(pCreateInfo->pSubpasses)->pColorAttachments = color_attachment_refs;
// }
//}
auto ret = vkCreateRenderPass2KHR ( device , pCreateInfo , pAllocator , pRenderPass ) ;
if ( const_cast < VkRenderPassCreateInfo2 * > ( pCreateInfo ) - > attachmentCount > 2 )
{
2025-04-02 17:11:10 +08:00
need_create_pso_renderpasses . insert ( * pRenderPass ) ;
2025-03-14 17:42:21 +08:00
}
return ret ;
}
2025-04-02 17:11:10 +08:00
2025-03-14 17:42:21 +08:00
static VKAPI_ATTR VkResult VKAPI_CALL Hook_vkCreateGraphicsPipelines (
VkDevice device ,
VkPipelineCache pipelineCache ,
uint32_t createInfoCount ,
const VkGraphicsPipelineCreateInfo * pCreateInfos ,
const VkAllocationCallbacks * pAllocator ,
VkPipeline * pPipelines )
{
if ( blend_state_hook_enable )
{
VkResult ret ;
auto shader_module = pCreateInfos - > pStages [ 1 ] . module ;
2025-04-02 17:11:10 +08:00
auto cur_pass = pCreateInfos - > renderPass ;
2025-03-14 17:42:21 +08:00
if ( ! created_pipeline_shader_module . contains ( shader_module ) )
{
created_pipeline_shader_module . insert ( shader_module ) ;
2025-04-02 17:11:10 +08:00
for ( const auto i : need_create_pso_renderpasses )
2025-03-14 17:42:21 +08:00
{
const_cast < VkGraphicsPipelineCreateInfo * > ( pCreateInfos ) - > renderPass = static_cast < VkRenderPass > ( i ) ;
char buf [ 80 ] ;
sprintf ( buf , " vkCreateGraphicsPipelines---: %p : %p \n " , pCreateInfos - > pStages [ 1 ] . module , pCreateInfos - > renderPass ) ;
unityLog ( buf ) ;
ret = vkCreateGraphicsPipelines ( device , pipelineCache , createInfoCount , pCreateInfos , pAllocator , pPipelines ) ;
}
}
2025-04-02 17:11:10 +08:00
// const_cast<VkGraphicsPipelineCreateInfo*>(pCreateInfos)->renderPass = static_cast<VkRenderPass>(cur_pass);
// ret = vkCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
2025-03-14 17:42:21 +08:00
return ret ;
}
return vkCreateGraphicsPipelines ( device , pipelineCache , createInfoCount , pCreateInfos , pAllocator , pPipelines ) ;
}
2024-11-22 12:09:31 +08:00
static int FindMemoryTypeIndex ( VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties , VkMemoryRequirements const & memoryRequirements , VkMemoryPropertyFlags memoryPropertyFlags )
2024-11-01 16:55:46 +08:00
{
uint32_t memoryTypeBits = memoryRequirements . memoryTypeBits ;
2025-03-14 17:42:21 +08:00
// Search memtypes to find first cur_vrs_Index with those properties
2024-11-01 16:55:46 +08:00
for ( uint32_t memoryTypeIndex = 0 ; memoryTypeIndex < VK_MAX_MEMORY_TYPES ; + + memoryTypeIndex )
{
if ( ( memoryTypeBits & 1 ) = = 1 )
{
// Type is available, does it match user properties?
if ( ( physicalDeviceMemoryProperties . memoryTypes [ memoryTypeIndex ] . propertyFlags & memoryPropertyFlags ) = = memoryPropertyFlags )
return memoryTypeIndex ;
}
memoryTypeBits > > = 1 ;
}
return - 1 ;
}
2024-11-22 12:09:31 +08:00
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL Hook_vkGetInstanceProcAddr ( VkInstance device , const char * funcName )
2024-11-01 16:55:46 +08:00
{
if ( ! funcName )
return NULL ;
2024-11-22 12:09:31 +08:00
unityLog ( funcName ) ;
# define INTERCEPT(fn) \
if ( strcmp ( funcName , # fn ) = = 0 ) \
return ( PFN_vkVoidFunction ) & Hook_ # # fn
2024-11-01 16:55:46 +08:00
INTERCEPT ( vkCreateInstance ) ;
INTERCEPT ( vkCreateDevice ) ;
INTERCEPT ( vkCmdBindPipeline ) ;
INTERCEPT ( vkCmdBindDescriptorSets ) ;
2025-03-14 17:42:21 +08:00
INTERCEPT ( vkCreateGraphicsPipelines ) ;
INTERCEPT ( vkCreateRenderPass2KHR ) ;
2024-11-01 16:55:46 +08:00
# undef INTERCEPT
2024-11-22 12:09:31 +08:00
2024-11-01 16:55:46 +08:00
return ( PFN_vkVoidFunction ) vkGetInstanceProcAddr ( device , funcName ) ;
}
2024-11-22 12:09:31 +08:00
static PFN_vkGetInstanceProcAddr UNITY_INTERFACE_API InterceptVulkanInitialization ( PFN_vkGetInstanceProcAddr getInstanceProcAddr , void * )
2024-11-01 16:55:46 +08:00
{
vkGetInstanceProcAddr = getInstanceProcAddr ;
return Hook_vkGetInstanceProcAddr ;
}
2024-11-22 12:09:31 +08:00
extern " C " void RenderAPI_Vulkan_OnPluginLoad ( IUnityInterfaces * interfaces )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
if ( IUnityGraphicsVulkanV2 * vulkanInterface = interfaces - > Get < IUnityGraphicsVulkanV2 > ( ) )
2024-11-01 16:55:46 +08:00
{
vulkanInterface - > AddInterceptInitialization ( InterceptVulkanInitialization , NULL , 0 ) ;
}
2024-11-22 12:09:31 +08:00
else if ( IUnityGraphicsVulkan * vulkanInterface = interfaces - > Get < IUnityGraphicsVulkan > ( ) )
2024-11-01 16:55:46 +08:00
{
vulkanInterface - > InterceptInitialization ( InterceptVulkanInitialization , NULL ) ;
}
}
struct VulkanBuffer
{
VkBuffer buffer ;
VkDeviceMemory deviceMemory ;
2024-11-22 12:09:31 +08:00
void * mapped ;
2024-11-01 16:55:46 +08:00
VkDeviceSize sizeInBytes ;
VkDeviceSize deviceMemorySize ;
VkMemoryPropertyFlags deviceMemoryFlags ;
} ;
2024-11-22 12:09:31 +08:00
class RenderAPI_Vulkan : public RenderAPI
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
public :
RenderAPI_Vulkan ( ) ;
virtual ~ RenderAPI_Vulkan ( ) { }
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
virtual void processDeviceEvent ( UnityGfxDeviceEventType type , IUnityInterfaces * interfaces ) override ;
virtual bool getUsesReverseZ ( ) override { return true ; }
2024-11-01 16:55:46 +08:00
2024-12-18 17:53:48 +08:00
virtual void enableVRS ( void * data ) override ;
2024-11-22 12:09:31 +08:00
virtual void disableVRS ( ) override ;
2024-11-01 16:55:46 +08:00
2024-11-22 14:45:23 +08:00
virtual void enableFGExtrapolation ( void * data ) override ;
2024-11-22 12:09:31 +08:00
virtual void preFGExtrapolation ( ) override ;
virtual bool doFGExtrapolation ( void * src , void * data , void * dst ) override ;
virtual void postFGExtrapolation ( ) override ;
virtual void disableFGExtrapolation ( ) override ;
2024-11-01 16:55:46 +08:00
2025-04-02 17:11:10 +08:00
virtual void SetVKPSOHook ( bool enable ) override ;
2024-11-01 16:55:46 +08:00
private :
typedef std : : vector < VulkanBuffer > VulkanBuffers ;
typedef std : : map < unsigned long long , VulkanBuffers > DeleteQueue ;
private :
2024-11-22 12:09:31 +08:00
bool createVulkanBuffer ( size_t bytes , VulkanBuffer * buffer , VkBufferUsageFlags usage ) ;
void immediateDestroyVulkanBuffer ( const VulkanBuffer & buffer ) ;
void safeDestroy ( unsigned long long frameNumber , const VulkanBuffer & buffer ) ;
void garbageCollect ( bool force = false ) ;
virtual void initSupportFeature ( ) override ;
2024-11-01 16:55:46 +08:00
private :
2024-11-22 12:09:31 +08:00
IUnityGraphicsVulkan * unity_vulkan ;
UnityVulkanInstance unity_vk_instance ;
2024-11-01 16:55:46 +08:00
std : : map < unsigned long long , VulkanBuffers > m_DeleteQueue ;
} ;
2024-11-22 12:09:31 +08:00
RenderAPI * CreateRenderAPI_Vulkan ( )
2024-11-01 16:55:46 +08:00
{
return new RenderAPI_Vulkan ( ) ;
}
RenderAPI_Vulkan : : RenderAPI_Vulkan ( )
2024-11-22 12:09:31 +08:00
: unity_vulkan ( NULL )
2024-11-01 16:55:46 +08:00
{
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : processDeviceEvent ( UnityGfxDeviceEventType type , IUnityInterfaces * interfaces )
2024-11-01 16:55:46 +08:00
{
switch ( type )
{
case kUnityGfxDeviceEventInitialize :
2024-11-22 12:09:31 +08:00
unityLog ( " ProcessDeviceEvent called. kUnityGfxDeviceEventInitialize " ) ;
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
unity_vulkan = interfaces - > Get < IUnityGraphicsVulkan > ( ) ;
unity_vk_instance = unity_vulkan - > Instance ( ) ;
2024-11-01 16:55:46 +08:00
// Make sure Vulkan API functions are loaded
2024-11-22 12:09:31 +08:00
LoadVulkanAPI ( unity_vk_instance . getInstanceProcAddr , unity_vk_instance . instance ) ;
2024-11-01 16:55:46 +08:00
UnityVulkanPluginEventConfig config_1 ;
config_1 . graphicsQueueAccess = kUnityVulkanGraphicsQueueAccess_DontCare ;
config_1 . renderPassPrecondition = kUnityVulkanRenderPass_EnsureInside ;
config_1 . flags = kUnityVulkanEventConfigFlag_EnsurePreviousFrameSubmission | kUnityVulkanEventConfigFlag_ModifiesCommandBuffersState ;
2024-11-22 12:09:31 +08:00
unity_vulkan - > ConfigureEvent ( 1 , & config_1 ) ;
2024-11-01 16:55:46 +08:00
// alternative way to intercept API
2024-11-22 12:09:31 +08:00
unity_vulkan - > InterceptVulkanAPI ( " vkCmdBeginRenderPass " , ( PFN_vkVoidFunction ) Hook_vkCmdBeginRenderPass ) ;
initSupportFeature ( ) ;
2024-11-01 16:55:46 +08:00
break ;
case kUnityGfxDeviceEventShutdown :
2024-11-22 12:09:31 +08:00
unityLog ( " ProcessDeviceEvent called. kUnityGfxDeviceEventShutdown " ) ;
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
if ( unity_vk_instance . device ! = VK_NULL_HANDLE )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
garbageCollect ( true ) ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
unity_vulkan = NULL ;
unity_vk_instance = UnityVulkanInstance ( ) ;
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
break ;
default :
2024-11-01 16:55:46 +08:00
break ;
}
}
2024-11-22 12:09:31 +08:00
bool RenderAPI_Vulkan : : createVulkanBuffer ( size_t sizeInBytes , VulkanBuffer * buffer , VkBufferUsageFlags usage )
2024-11-01 16:55:46 +08:00
{
if ( sizeInBytes = = 0 )
return false ;
VkBufferCreateInfo bufferCreateInfo ;
bufferCreateInfo . sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO ;
bufferCreateInfo . pNext = NULL ;
2024-11-22 12:09:31 +08:00
bufferCreateInfo . pQueueFamilyIndices = & unity_vk_instance . queueFamilyIndex ;
2024-11-01 16:55:46 +08:00
bufferCreateInfo . queueFamilyIndexCount = 1 ;
bufferCreateInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
bufferCreateInfo . usage = usage ;
bufferCreateInfo . flags = 0 ;
bufferCreateInfo . size = sizeInBytes ;
* buffer = VulkanBuffer ( ) ;
2024-11-22 12:09:31 +08:00
if ( vkCreateBuffer ( unity_vk_instance . device , & bufferCreateInfo , NULL , & buffer - > buffer ) ! = VK_SUCCESS )
2024-11-01 16:55:46 +08:00
return false ;
VkPhysicalDeviceMemoryProperties physicalDeviceProperties ;
2024-11-22 12:09:31 +08:00
vkGetPhysicalDeviceMemoryProperties ( unity_vk_instance . physicalDevice , & physicalDeviceProperties ) ;
2024-11-01 16:55:46 +08:00
VkMemoryRequirements memoryRequirements ;
2024-11-22 12:09:31 +08:00
vkGetBufferMemoryRequirements ( unity_vk_instance . device , buffer - > buffer , & memoryRequirements ) ;
2024-11-01 16:55:46 +08:00
const int memoryTypeIndex = FindMemoryTypeIndex ( physicalDeviceProperties , memoryRequirements , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ) ;
if ( memoryTypeIndex < 0 )
{
2024-11-22 12:09:31 +08:00
immediateDestroyVulkanBuffer ( * buffer ) ;
2024-11-01 16:55:46 +08:00
return false ;
}
VkMemoryAllocateInfo memoryAllocateInfo ;
memoryAllocateInfo . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
memoryAllocateInfo . pNext = NULL ;
memoryAllocateInfo . memoryTypeIndex = memoryTypeIndex ;
memoryAllocateInfo . allocationSize = memoryRequirements . size ;
2024-11-22 12:09:31 +08:00
if ( vkAllocateMemory ( unity_vk_instance . device , & memoryAllocateInfo , NULL , & buffer - > deviceMemory ) ! = VK_SUCCESS )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
immediateDestroyVulkanBuffer ( * buffer ) ;
2024-11-01 16:55:46 +08:00
return false ;
}
2024-11-22 12:09:31 +08:00
if ( vkMapMemory ( unity_vk_instance . device , buffer - > deviceMemory , 0 , VK_WHOLE_SIZE , 0 , & buffer - > mapped ) ! = VK_SUCCESS )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
immediateDestroyVulkanBuffer ( * buffer ) ;
2024-11-01 16:55:46 +08:00
return false ;
}
2024-11-22 12:09:31 +08:00
if ( vkBindBufferMemory ( unity_vk_instance . device , buffer - > buffer , buffer - > deviceMemory , 0 ) ! = VK_SUCCESS )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
immediateDestroyVulkanBuffer ( * buffer ) ;
2024-11-01 16:55:46 +08:00
return false ;
}
buffer - > sizeInBytes = sizeInBytes ;
buffer - > deviceMemoryFlags = physicalDeviceProperties . memoryTypes [ memoryTypeIndex ] . propertyFlags ;
buffer - > deviceMemorySize = memoryAllocateInfo . allocationSize ;
return true ;
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : immediateDestroyVulkanBuffer ( const VulkanBuffer & buffer )
2024-11-01 16:55:46 +08:00
{
if ( buffer . buffer ! = VK_NULL_HANDLE )
2024-11-22 12:09:31 +08:00
vkDestroyBuffer ( unity_vk_instance . device , buffer . buffer , NULL ) ;
2024-11-01 16:55:46 +08:00
if ( buffer . mapped & & buffer . deviceMemory ! = VK_NULL_HANDLE )
2024-11-22 12:09:31 +08:00
vkUnmapMemory ( unity_vk_instance . device , buffer . deviceMemory ) ;
2024-11-01 16:55:46 +08:00
if ( buffer . deviceMemory ! = VK_NULL_HANDLE )
2024-11-22 12:09:31 +08:00
vkFreeMemory ( unity_vk_instance . device , buffer . deviceMemory , NULL ) ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : safeDestroy ( unsigned long long frameNumber , const VulkanBuffer & buffer )
2024-11-01 16:55:46 +08:00
{
m_DeleteQueue [ frameNumber ] . push_back ( buffer ) ;
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : garbageCollect ( bool force /*= false*/ )
2024-11-01 16:55:46 +08:00
{
UnityVulkanRecordingState recordingState ;
if ( force )
recordingState . safeFrameNumber = ~ 0ull ;
2024-11-22 12:09:31 +08:00
else if ( ! unity_vulkan - > CommandRecordingState ( & recordingState , kUnityVulkanGraphicsQueueAccess_DontCare ) )
return ;
2024-11-01 16:55:46 +08:00
DeleteQueue : : iterator it = m_DeleteQueue . begin ( ) ;
while ( it ! = m_DeleteQueue . end ( ) )
{
if ( it - > first < = recordingState . safeFrameNumber )
{
for ( size_t i = 0 ; i < it - > second . size ( ) ; + + i )
2024-11-22 12:09:31 +08:00
immediateDestroyVulkanBuffer ( it - > second [ i ] ) ;
2024-11-01 16:55:46 +08:00
m_DeleteQueue . erase ( it + + ) ;
}
else
+ + it ;
}
}
2024-11-22 12:09:31 +08:00
# if OHOS
void checkXEngine ( VkPhysicalDevice physic_device , SupportFeatureList & fl )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
std : : vector < std : : string > supported_extensions ;
uint32_t property_cnt ;
HMS_XEG_EnumerateDeviceExtensionProperties ( physic_device , & property_cnt , nullptr ) ;
if ( property_cnt > 0 )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
std : : vector < XEG_ExtensionProperties > properties ( property_cnt ) ;
if ( HMS_XEG_EnumerateDeviceExtensionProperties ( physic_device , & property_cnt ,
& properties . front ( ) ) = = VK_SUCCESS )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
for ( auto ext : properties )
{
supported_extensions . push_back ( ext . extensionName ) ;
}
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
}
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
if ( std : : find ( supported_extensions . begin ( ) , supported_extensions . end ( ) , XEG_SPATIAL_UPSCALE_EXTENSION_NAME ) ! =
supported_extensions . end ( ) )
{
fl [ GraphicsFeature : : HW_SPATIAL_SR ] = true ;
}
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
if ( std : : find ( supported_extensions . begin ( ) , supported_extensions . end ( ) , XEG_ADAPTIVE_VRS_EXTENSION_NAME ) ! =
supported_extensions . end ( ) )
{
fl [ GraphicsFeature : : HW_ADAPTIVE_VRS ] = true ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
}
# endif
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : initSupportFeature ( )
{
auto physic_device = unity_vk_instance . physicalDevice ;
uint32_t extension_cnt ;
vkEnumerateDeviceExtensionProperties ( physic_device , nullptr , & extension_cnt , nullptr ) ;
std : : vector < VkExtensionProperties > available_extensions ( extension_cnt ) ;
vkEnumerateDeviceExtensionProperties ( physic_device , nullptr , & extension_cnt , available_extensions . data ( ) ) ;
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_feature { } ;
vrs_feature . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR ;
VkPhysicalDeviceFeatures2 features2 { } ;
features2 . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 ;
features2 . pNext = & vrs_feature ;
vkGetPhysicalDeviceFeatures2 ( physic_device , & features2 ) ;
support_features [ GraphicsFeature : : VRS_DRAW ] = vrs_feature . pipelineFragmentShadingRate ;
support_features [ GraphicsFeature : : VRS_PRIMITIVE ] = vrs_feature . primitiveFragmentShadingRate ;
support_features [ GraphicsFeature : : VRS_ATTACHMENT ] = vrs_feature . attachmentFragmentShadingRate ;
# if OHOS
checkXEngine ( physic_device , support_features ) ;
# endif
// char buf[40];
// sprintf(buf, "initSupportFeature VRS %d %d %d \n", (int)support_vrs_draw, (int)support_vrs_primitive, (int)support_vrs_attachment);
// unityLog(buf);
2024-11-01 16:55:46 +08:00
}
2024-12-18 17:53:48 +08:00
void RenderAPI_Vulkan : : enableVRS ( void * data )
2024-11-01 16:55:46 +08:00
{
2024-12-18 17:53:48 +08:00
int vrs_enum = * ( int * ) data ;
2025-03-14 17:42:21 +08:00
cur_vrs_Index = vrs_enum ;
2024-12-18 17:53:48 +08:00
vrs_fragment_size = vrs_argment_size_table [ vrs_enum ] ;
2024-11-22 12:09:31 +08:00
vrs_enable = true ;
}
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : disableVRS ( )
{
vrs_enable = false ;
}
2024-11-01 16:55:46 +08:00
2024-12-11 17:42:08 +08:00
void RenderAPI_Vulkan : : enableFGExtrapolation ( void * data )
2024-11-22 12:09:31 +08:00
{
}
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : preFGExtrapolation ( )
{
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
bool RenderAPI_Vulkan : : doFGExtrapolation ( void * src , void * data , void * dst )
2024-11-01 16:55:46 +08:00
{
2024-11-22 12:09:31 +08:00
// ???
// unity_vulkan->EnsureOutsideRenderPass();
2024-11-01 16:55:46 +08:00
UnityVulkanImage image ;
2024-11-22 12:09:31 +08:00
if ( unity_vulkan - > AccessTexture ( src , UnityVulkanWholeImage , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
VK_PIPELINE_STAGE_TRANSFER_BIT , VK_ACCESS_TRANSFER_WRITE_BIT , kUnityVulkanResourceAccess_PipelineBarrier , & image ) )
{
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
}
return false ;
2024-11-01 16:55:46 +08:00
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : postFGExtrapolation ( )
2024-11-01 16:55:46 +08:00
{
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Vulkan : : disableFGExtrapolation ( )
2024-11-01 16:55:46 +08:00
{
}
2025-03-14 17:42:21 +08:00
2025-04-02 17:11:10 +08:00
void RenderAPI_Vulkan : : SetVKPSOHook ( bool enable )
2025-03-14 17:42:21 +08:00
{
blend_state_hook_enable = enable ;
}
2024-11-01 16:55:46 +08:00
# endif // #if SUPPORT_VULKAN