Trying to create VkFFT native plugin for Unity but it is crashing as soon as I hit the play button. #218
Unanswered
anupkumar8245
asked this question in
Q&A
Replies: 1 comment
-
|
Hello, I think the issue is that in your launchParams you need to specify the buffer field with a pointer to your main working buffer. The isInputFormatted option enables initial reading from the inputBuffer and isOutputFormatted enables final writing to the outputBuffer, but the main work happens in the buffer. Hope this solves the issue. Best regards, |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I am trying to implement the VkFFT for native plugin for Unity but unity is crashing as soon as I hit the play button for version1 of VkFFTPlugin.cpp or getting the error of [Native]: VkFFTAppend FAILED: 2004 for version2 of VkFFTPluing.cpp. The files are attached for reference. Can anybody help If you have tried this for Unity.
=============================VkFFTPlugin.cpp (v1)==============================
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
#include "IUnityGraphicsVulkan.h"
#include <vulkan/vulkan.h>
#include
#include
#include // For hex printing
#define VKFFT_BACKEND 0
#include "vkFFT/vkFFT.h"
// --- GLOBALS ---
static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityGraphics* s_Graphics = nullptr;
static IUnityGraphicsVulkan* s_GraphicsVulkan = nullptr;
static VkFFTApplication app = {};
static bool isInitialized = false;
// Handles
static VkDevice g_Device = VK_NULL_HANDLE;
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
static VkQueue g_Queue = VK_NULL_HANDLE;
static VkCommandPool g_CommandPool = VK_NULL_HANDLE;
static VkFence g_Fence = VK_NULL_HANDLE;
static VkBuffer inputBuffer = VK_NULL_HANDLE;
static VkBuffer outputBuffer = VK_NULL_HANDLE;
static size_t bufferSize = 0;
// Debugging
typedef void (DebugCallback)(const char message);
static DebugCallback s_DebugLog = nullptr;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RegisterDebugCallback(DebugCallback callback) {
s_DebugLog = callback;
}
void LogToUnity(const std::string& msg) {
if (s_DebugLog) s_DebugLog(msg.c_str());
}
// Helper to print pointer address
template
std::string Hex(T val) {
std::stringstream ss;
ss << std::hex << (uint64_t)val;
return "0x" + ss.str();
}
// --------------------------------------------------------------------------
// INIT
// --------------------------------------------------------------------------
void InitVkFFT() {
if (isInitialized || !s_GraphicsVulkan) return;
}
// --------------------------------------------------------------------------
// RENDER LOOP
// --------------------------------------------------------------------------
static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
{
if (!s_GraphicsVulkan) return;
}
// --------------------------------------------------------------------------
// UNLOAD
// --------------------------------------------------------------------------
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
if (isInitialized) {
deleteVkFFT(&app);
isInitialized = false;
}
if (g_Fence) vkDestroyFence(g_Device, g_Fence, nullptr);
if (g_CommandPool) vkDestroyCommandPool(g_Device, g_CommandPool, nullptr);
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) {
s_UnityInterfaces = unityInterfaces;
s_Graphics = s_UnityInterfaces->Get();
s_GraphicsVulkan = s_UnityInterfaces->Get();
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetBuffers(void* inputPtr, void* outputPtr, int size) {
inputBuffer = (VkBuffer)inputPtr;
outputBuffer = (VkBuffer)outputPtr;
bufferSize = size;
// Reset if size changes
if (isInitialized) {
deleteVkFFT(&app);
isInitialized = false;
// Note: We don't destroy the Pool/Fence here, we reuse them.
}
}
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() {
return OnRenderEvent;
}
extern "C" __declspec(dllexport) int TestFunction() { return 999; }
====================================VkFFTPlugin.cpp (v2)==============================
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
#include "IUnityGraphicsVulkan.h"
#include <vulkan/vulkan.h>
#include
#include
#include // For hex printing
#define VKFFT_BACKEND 0
#include "vkFFT/vkFFT.h"
// --- GLOBALS ---
static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityGraphics* s_Graphics = nullptr;
static IUnityGraphicsVulkan* s_GraphicsVulkan = nullptr;
static VkFFTApplication app = {};
static bool isInitialized = false;
// Handles
static VkDevice g_Device = VK_NULL_HANDLE;
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
static VkQueue g_Queue = VK_NULL_HANDLE;
static VkCommandPool g_CommandPool = VK_NULL_HANDLE;
static VkFence g_Fence = VK_NULL_HANDLE;
static VkBuffer inputBuffer = VK_NULL_HANDLE;
static VkBuffer outputBuffer = VK_NULL_HANDLE;
static size_t bufferSize = 0;
// Debugging
typedef void (DebugCallback)(const char message);
static DebugCallback s_DebugLog = nullptr;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RegisterDebugCallback(DebugCallback callback) {
s_DebugLog = callback;
}
void LogToUnity(const std::string& msg) {
if (s_DebugLog) s_DebugLog(msg.c_str());
}
// Helper to print pointer address
template
std::string Hex(T val) {
std::stringstream ss;
ss << std::hex << (uint64_t)val;
return "0x" + ss.str();
}
// --------------------------------------------------------------------------
// INIT
// --------------------------------------------------------------------------
void InitVkFFT() {
if (isInitialized || !s_GraphicsVulkan) return;
}
// --------------------------------------------------------------------------
// RENDER LOOP
// --------------------------------------------------------------------------
static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
{
if (!s_GraphicsVulkan) return;
}
// --------------------------------------------------------------------------
// UNLOAD
// --------------------------------------------------------------------------
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
if (isInitialized) {
deleteVkFFT(&app);
isInitialized = false;
}
if (g_Fence) vkDestroyFence(g_Device, g_Fence, nullptr);
if (g_CommandPool) vkDestroyCommandPool(g_Device, g_CommandPool, nullptr);
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) {
s_UnityInterfaces = unityInterfaces;
s_Graphics = s_UnityInterfaces->Get();
s_GraphicsVulkan = s_UnityInterfaces->Get();
}
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetBuffers(void* inputPtr, void* outputPtr, int size) {
inputBuffer = (VkBuffer)inputPtr;
outputBuffer = (VkBuffer)outputPtr;
bufferSize = size;
// Reset if size changes
if (isInitialized) {
deleteVkFFT(&app);
isInitialized = false;
// Note: We don't destroy the Pool/Fence here, we reuse them.
}
}
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() {
return OnRenderEvent;
}
extern "C" __declspec(dllexport) int TestFunction() { return 996; }
===================================CMakeLists.txt======================================
cmake_minimum_required(VERSION 3.10)
project(VkFFTPlugin)
1. Setup Vulkan SDK
if(NOT DEFINED ENV{VULKAN_SDK})
message(FATAL_ERROR "VULKAN_SDK environment variable is not set.")
endif()
file(TO_CMAKE_PATH "$ENV{VULKAN_SDK}" VULKAN_SDK_PATH)
message(STATUS "Using Vulkan SDK at: ${VULKAN_SDK_PATH}")
2. Setup Source
set(SOURCES src/VkFFTPlugin.cpp)
add_library(VkFFTPlugin SHARED ${SOURCES})
3. Include Directories
target_include_directories(VkFFTPlugin PRIVATE
${VULKAN_SDK_PATH}/Include #Vulkan API
${CMAKE_SOURCE_DIR}/include # For vkFFT/vkFFT.h, VkFFT headers
${CMAKE_SOURCE_DIR}/include/Unity # Unity native plugin headers
$ENV{VULKAN_SDK}/Include/glslang/Include
)
4. Link Directories (Where the .lib files are)
target_link_directories(VkFFTPlugin PRIVATE ${VULKAN_SDK_PATH}/Lib)
5. Link Libraries (MANUAL FORCE LINK), required because: VkFFT compile shaders at runtime, Needs SPIRV optimizer and validator
The order matters!
target_link_libraries(VkFFTPlugin PRIVATE
vulkan-1
glslang
MachineIndependent
GenericCodeGen
SPIRV
SPIRV-Tools # <-- Added
SPIRV-Tools-opt # <-- Added
)
6. Definitions
target_compile_definitions(VkFFTPlugin PRIVATE
WIN32
VK_USE_PLATFORM_WIN32_KHR
)
7. Auto-Copy to Unity, This makes Unity instantly see: Updated dll, No Manual Copying
add_custom_command(TARGET VkFFTPlugin POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:VkFFTPlugin>
"${CMAKE_SOURCE_DIR}/../UnityProject/Assets/Plugins/x86_64/$<TARGET_FILE_NAME:VkFFTPlugin>"
)
==================================VkFFT.cs (Unity C# code)=================================
using UnityEngine;
using System;
using System.Runtime.InteropServices;
using UnityEngine.Rendering;
public class VkFFT : MonoBehaviour
{
//// 1. Import functions from your DLL
//[DllImport("VkFFTPlugin")]
//private static extern void SetBuffers(IntPtr input, IntPtr output, int size);
}
Beta Was this translation helpful? Give feedback.
All reactions