666 lines
24 KiB
C++
Raw Normal View History

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>
#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); \
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;
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)
{
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)
//{
// 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
}
// 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;
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);
}
return ret;
}
2025-04-02 17:11:10 +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;
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)
{
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);
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;
// 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);
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
}
2025-04-24 10:48:58 +08:00
// 查询是否支持时域AI超分
if (std::find(supported_extensions.begin(), supported_extensions.end(), XEG_TEMPORAL_UPSCALE_EXTENSION_NAME) ==
supported_extensions.end())
{
fl[GraphicsFeature::HW_AI_TEMPORAL_SR] = true;
}
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;
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-04-02 17:11:10 +08:00
void RenderAPI_Vulkan::SetVKPSOHook(bool enable)
{
blend_state_hook_enable = enable;
}
2024-11-01 16:55:46 +08:00
#endif // #if SUPPORT_VULKAN