From b93ec12bfebfe311db6d4ed90153a90959784d74 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 02:12:36 +0000 Subject: [PATCH] feat: Add initial Vulkan backend framework and compile flag I've introduced the foundational infrastructure for a Vulkan rendering backend in raylib. Key changes: - CMake: - I added a `SUPPORT_VULKAN` option (default OFF) to enable Vulkan. - It finds the Vulkan SDK and links appropriate libraries when enabled. - I defined `CF_VULKAN_` (0 by default, 1 if Vulkan enabled) and `GRAPHICS_API_VULKAN` preprocessor macros. - I updated `LibraryConfigurations.cmake` and `src/CMakeLists.txt` to handle Vulkan as a graphics API. - Vulkan Abstraction Layer: - I created `src/rlvk.h` and `src/rlvk.c` with stub implementations for Vulkan rendering functions (e.g., `rlvkInit`, `rlvkClose`, drawing functions). These are compiled only when `SUPPORT_VULKAN` is ON. - Core Integration: - `rlgl.h` and `rcore.c` now have conditional code paths for `GRAPHICS_API_VULKAN`. - `InitWindow` and `CloseWindow` in `rcore.c` call Vulkan-specific platform and backend initialization/deinitialization stubs. - Platform Layer (GLFW): - `src/platforms/rcore_desktop_glfw.c` includes stubbed `InitPlatformVulkan` and `ClosePlatformVulkan` to set up GLFW for a Vulkan context (actual Vulkan instance/surface creation is stubbed). This commit establishes the necessary build system changes and C code structure to allow for the incremental implementation of the Vulkan renderer. Currently, enabling Vulkan will compile the stubs, allowing your application to run but without actual Vulkan rendering. The `CF_VULKAN_` flag controls the compilation and selection of Vulkan as the default renderer when active. --- CMakeLists.txt | 10 ++ cmake/CompileDefinitions.cmake | 7 + cmake/LibraryConfigurations.cmake | 244 +++++++++++++++-------------- src/CMakeLists.txt | 23 +++ src/platforms/rcore_desktop_glfw.c | 200 +++++++++++++++++++++++ src/rcore.c | 57 ++++++- src/rlgl.h | 86 ++++++++++ src/rlvk.c | 77 +++++++++ src/rlvk.h | 36 +++++ 9 files changed, 625 insertions(+), 115 deletions(-) create mode 100644 src/rlvk.c create mode 100644 src/rlvk.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f7597694c..f1c0bcd03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,8 +27,18 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(CompilerFlags) # Registers build options that are exposed to cmake +option(SUPPORT_VULKAN "Enable Vulkan graphics backend" OFF) include(CMakeOptions.txt) +if (SUPPORT_VULKAN) + find_package(Vulkan REQUIRED) + if (NOT Vulkan_FOUND) + message(FATAL_ERROR "Vulkan SDK not found, required for SUPPORT_VULKAN option.") + else() + message(STATUS "Vulkan SDK found: Headers at ${Vulkan_INCLUDE_DIRS}, Libraries at ${Vulkan_LIBRARIES}") + endif() +endif() + if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM") if (NOT GLFW_BUILD_WAYLAND AND NOT GLFW_BUILD_X11) MESSAGE(FATAL_ERROR "Cannot disable both Wayland and X11") diff --git a/cmake/CompileDefinitions.cmake b/cmake/CompileDefinitions.cmake index cefafdeb7..d0dc3e279 100644 --- a/cmake/CompileDefinitions.cmake +++ b/cmake/CompileDefinitions.cmake @@ -1,7 +1,14 @@ +target_compile_definitions("raylib" PUBLIC "CF_VULKAN_=0") # Adding compile definitions target_compile_definitions("raylib" PUBLIC "${PLATFORM_CPP}") target_compile_definitions("raylib" PUBLIC "${GRAPHICS}") +if (SUPPORT_VULKAN AND Vulkan_FOUND) + target_compile_definitions("raylib" PUBLIC "CF_VULKAN_=1") + target_compile_definitions("raylib" PUBLIC "GRAPHICS_API_VULKAN") + message(STATUS "Vulkan backend enabled via CF_VULKAN_ and GRAPHICS_API_VULKAN") +endif() + function(define_if target variable) if(${${variable}}) message(STATUS "${variable}=${${variable}}") diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake index 00dda033a..3c9f9ee84 100644 --- a/cmake/LibraryConfigurations.cmake +++ b/cmake/LibraryConfigurations.cmake @@ -7,133 +7,149 @@ if(POLICY CMP0072) cmake_policy(SET CMP0072 NEW) endif() -if (${PLATFORM} MATCHES "Desktop") - set(PLATFORM_CPP "PLATFORM_DESKTOP") +if (SUPPORT_VULKAN AND Vulkan_FOUND) + set(GRAPHICS "GRAPHICS_API_VULKAN") + message(STATUS "Vulkan graphics API selected. GRAPHICS set to GRAPHICS_API_VULKAN.") + # Any Vulkan-specific LIBS_PRIVATE additions can be handled here or in src/CMakeLists.txt + # For now, assuming Vulkan::Vulkan and Vulkan_LIBRARIES cover necessary linking. +else() + # ORIGINAL OPENGL-SPECIFIC LOGIC + if (${PLATFORM} MATCHES "Desktop") + set(PLATFORM_CPP "PLATFORM_DESKTOP") - if (APPLE) - # Need to force OpenGL 3.3 on OS X - # See: https://github.com/raysan5/raylib/issues/341 - set(GRAPHICS "GRAPHICS_API_OPENGL_33") - find_library(OPENGL_LIBRARY OpenGL) - set(LIBS_PRIVATE ${OPENGL_LIBRARY}) - link_libraries("${LIBS_PRIVATE}") - if (NOT CMAKE_SYSTEM STRLESS "Darwin-18.0.0") - add_definitions(-DGL_SILENCE_DEPRECATION) - MESSAGE(AUTHOR_WARNING "OpenGL is deprecated starting with macOS 10.14 (Mojave)!") - endif () - elseif (WIN32) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - find_package(OpenGL QUIET) - set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm) - elseif (UNIX) - find_library(pthread NAMES pthread) - find_package(OpenGL QUIET) - if ("${OPENGL_LIBRARIES}" STREQUAL "") - set(OPENGL_LIBRARIES "GL") - endif () + if (APPLE) + # Need to force OpenGL 3.3 on OS X + # See: https://github.com/raysan5/raylib/issues/341 + set(GRAPHICS "GRAPHICS_API_OPENGL_33") + find_library(OPENGL_LIBRARY OpenGL) + set(LIBS_PRIVATE ${OPENGL_LIBRARY}) + link_libraries("${LIBS_PRIVATE}") + if (NOT CMAKE_SYSTEM STRLESS "Darwin-18.0.0") + add_definitions(-DGL_SILENCE_DEPRECATION) + MESSAGE(AUTHOR_WARNING "OpenGL is deprecated starting with macOS 10.14 (Mojave)!") + endif () + elseif (WIN32) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + find_package(OpenGL QUIET) + set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm) + elseif (UNIX) + find_library(pthread NAMES pthread) + find_package(OpenGL QUIET) + if ("${OPENGL_LIBRARIES}" STREQUAL "") + set(OPENGL_LIBRARIES "GL") + endif () - if ("${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD") - find_library(OSS_LIBRARY ossaudio) - endif () + if ("${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD") + find_library(OSS_LIBRARY ossaudio) + endif () - set(LIBS_PRIVATE m pthread ${OPENGL_LIBRARIES} ${OSS_LIBRARY}) - else () - find_library(pthread NAMES pthread) - find_package(OpenGL QUIET) - if ("${OPENGL_LIBRARIES}" STREQUAL "") - set(OPENGL_LIBRARIES "GL") - endif () - - set(LIBS_PRIVATE m atomic pthread ${OPENGL_LIBRARIES} ${OSS_LIBRARY}) - - if ("${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD") - find_library(OSS_LIBRARY ossaudio) set(LIBS_PRIVATE m pthread ${OPENGL_LIBRARIES} ${OSS_LIBRARY}) + else () + find_library(pthread NAMES pthread) + find_package(OpenGL QUIET) + if ("${OPENGL_LIBRARIES}" STREQUAL "") + set(OPENGL_LIBRARIES "GL") + endif () + + set(LIBS_PRIVATE m atomic pthread ${OPENGL_LIBRARIES} ${OSS_LIBRARY}) + + if ("${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD") + find_library(OSS_LIBRARY ossaudio) + set(LIBS_PRIVATE m pthread ${OPENGL_LIBRARIES} ${OSS_LIBRARY}) + endif () + + if (NOT "${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD" AND USE_AUDIO) + set(LIBS_PRIVATE ${LIBS_PRIVATE} dl) + endif () endif () - if (NOT "${CMAKE_SYSTEM_NAME}" MATCHES "(Net|Open)BSD" AND USE_AUDIO) - set(LIBS_PRIVATE ${LIBS_PRIVATE} dl) + elseif (${PLATFORM} MATCHES "Web") + set(PLATFORM_CPP "PLATFORM_WEB") + if(NOT GRAPHICS) + set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") + endif() + set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") + + elseif (${PLATFORM} MATCHES "Android") + set(PLATFORM_CPP "PLATFORM_ANDROID") + set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + + # NOTE: We remove '-Wl,--no-undefined' (set by default) as it conflicts with '-Wl,-undefined,dynamic_lookup' needed + # for compiling with the missing 'void main(void)' declaration in `android_main()`. + # We also remove other unnecessary or problematic flags. + + string(REPLACE "-Wl,--no-undefined -Qunused-arguments" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "-static-libstdc++" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup") + + find_library(OPENGL_LIBRARY OpenGL) + set(LIBS_PRIVATE m log android EGL GLESv2 OpenSLES atomic c) + + elseif ("${PLATFORM}" MATCHES "DRM") + set(PLATFORM_CPP "PLATFORM_DRM") + set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") + + add_definitions(-D_DEFAULT_SOURCE) + add_definitions(-DEGL_NO_X11) + add_definitions(-DPLATFORM_DRM) + + find_library(GLESV2 GLESv2) + find_library(EGL EGL) + find_library(DRM drm) + find_library(GBM gbm) + + if (NOT CMAKE_CROSSCOMPILING OR NOT CMAKE_SYSROOT) + include_directories(/usr/include/libdrm) + endif () + set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread m dl) + + elseif ("${PLATFORM}" MATCHES "SDL") + find_package(SDL2 REQUIRED) + set(PLATFORM_CPP "PLATFORM_DESKTOP_SDL") + set(LIBS_PRIVATE SDL2::SDL2) + # For SDL, if it's used with OpenGL, ensure GRAPHICS is set appropriately if not already. + # This might need adjustment if SDL can also host Vulkan. For now, assuming SDL is for OpenGL. + if(NOT GRAPHICS) + set(GRAPHICS "GRAPHICS_API_OPENGL_33") # Default for SDL on desktop, or could be ES for other platforms + endif() + endif () + + if (NOT ${OPENGL_VERSION} MATCHES "OFF") + set(SUGGESTED_GRAPHICS "${GRAPHICS}") + + if (${OPENGL_VERSION} MATCHES "4.3") + set(GRAPHICS "GRAPHICS_API_OPENGL_43") + elseif (${OPENGL_VERSION} MATCHES "3.3") + set(GRAPHICS "GRAPHICS_API_OPENGL_33") + elseif (${OPENGL_VERSION} MATCHES "2.1") + set(GRAPHICS "GRAPHICS_API_OPENGL_21") + elseif (${OPENGL_VERSION} MATCHES "1.1") + set(GRAPHICS "GRAPHICS_API_OPENGL_11") + elseif (${OPENGL_VERSION} MATCHES "ES 2.0") + set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") + elseif (${OPENGL_VERSION} MATCHES "ES 3.0") + set(GRAPHICS "GRAPHICS_API_OPENGL_ES3") + endif () + if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}") + message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.") endif () endif () -elseif (${PLATFORM} MATCHES "Web") - set(PLATFORM_CPP "PLATFORM_WEB") - if(NOT GRAPHICS) - set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") - endif() - set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") - -elseif (${PLATFORM} MATCHES "Android") - set(PLATFORM_CPP "PLATFORM_ANDROID") - set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - list(APPEND raylib_sources ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) - include_directories(${ANDROID_NDK}/sources/android/native_app_glue) - - # NOTE: We remove '-Wl,--no-undefined' (set by default) as it conflicts with '-Wl,-undefined,dynamic_lookup' needed - # for compiling with the missing 'void main(void)' declaration in `android_main()`. - # We also remove other unnecessary or problematic flags. - - string(REPLACE "-Wl,--no-undefined -Qunused-arguments" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - string(REPLACE "-static-libstdc++" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -u ANativeActivity_onCreate -Wl,-undefined,dynamic_lookup") - - find_library(OPENGL_LIBRARY OpenGL) - set(LIBS_PRIVATE m log android EGL GLESv2 OpenSLES atomic c) - -elseif ("${PLATFORM}" MATCHES "DRM") - set(PLATFORM_CPP "PLATFORM_DRM") - set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") - - add_definitions(-D_DEFAULT_SOURCE) - add_definitions(-DEGL_NO_X11) - add_definitions(-DPLATFORM_DRM) - - find_library(GLESV2 GLESv2) - find_library(EGL EGL) - find_library(DRM drm) - find_library(GBM gbm) - - if (NOT CMAKE_CROSSCOMPILING OR NOT CMAKE_SYSROOT) - include_directories(/usr/include/libdrm) + if (NOT GRAPHICS) + set(GRAPHICS "GRAPHICS_API_OPENGL_33") # Default OpenGL version if nothing else set it endif () - set(LIBS_PRIVATE ${GLESV2} ${EGL} ${DRM} ${GBM} atomic pthread m dl) - -elseif ("${PLATFORM}" MATCHES "SDL") - find_package(SDL2 REQUIRED) - set(PLATFORM_CPP "PLATFORM_DESKTOP_SDL") - set(LIBS_PRIVATE SDL2::SDL2) - -endif () - -if (NOT ${OPENGL_VERSION} MATCHES "OFF") - set(SUGGESTED_GRAPHICS "${GRAPHICS}") - - if (${OPENGL_VERSION} MATCHES "4.3") - set(GRAPHICS "GRAPHICS_API_OPENGL_43") - elseif (${OPENGL_VERSION} MATCHES "3.3") - set(GRAPHICS "GRAPHICS_API_OPENGL_33") - elseif (${OPENGL_VERSION} MATCHES "2.1") - set(GRAPHICS "GRAPHICS_API_OPENGL_21") - elseif (${OPENGL_VERSION} MATCHES "1.1") - set(GRAPHICS "GRAPHICS_API_OPENGL_11") - elseif (${OPENGL_VERSION} MATCHES "ES 2.0") - set(GRAPHICS "GRAPHICS_API_OPENGL_ES2") - elseif (${OPENGL_VERSION} MATCHES "ES 3.0") - set(GRAPHICS "GRAPHICS_API_OPENGL_ES3") - endif () - if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}") - message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.") - endif () -endif () - -if (NOT GRAPHICS) - set(GRAPHICS "GRAPHICS_API_OPENGL_33") -endif () +endif() # End of SUPPORT_VULKAN AND Vulkan_FOUND conditional +# Universal appends to LIBS_PRIVATE set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY}) if (${PLATFORM} MATCHES "Desktop") + # This implies glfw is used for both Vulkan and OpenGL on Desktop. + # If GLFW is only for OpenGL, this should be in the else block. + # Given rcore_vulkan_glfw.c, it's likely needed for Vulkan too. set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw) endif () diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ce6cb81a..bea6b1d80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,11 @@ set(raylib_sources utils.c ) +if (SUPPORT_VULKAN AND Vulkan_FOUND) + list(APPEND raylib_sources rlvk.c) + message(STATUS "Vulkan source (rlvk.c) added to compilation.") +endif() + # /cmake/GlfwImport.cmake handles the details around the inclusion of glfw if (NOT ${PLATFORM} MATCHES "Web") include(GlfwImport) @@ -49,6 +54,24 @@ endif () # Produces a variable LIBS_PRIVATE that will be used later include(LibraryConfigurations) +if (SUPPORT_VULKAN AND Vulkan_FOUND) + if(TARGET Vulkan::Vulkan) + target_link_libraries(raylib PUBLIC Vulkan::Vulkan) + message(STATUS "Linking raylib with Vulkan::Vulkan target.") + elseif(Vulkan_LIBRARIES) + # For older CMake or non-imported target setups for Vulkan + target_link_libraries(raylib PUBLIC ${Vulkan_LIBRARIES}) + message(STATUS "Linking raylib with Vulkan libraries: ${Vulkan_LIBRARIES}") + else() + message(WARNING "Vulkan support is enabled, but no Vulkan link target or libraries (Vulkan::Vulkan or Vulkan_LIBRARIES) were found/specified by find_package(Vulkan).") + endif() + # Ensure Vulkan include directories are available to the raylib target + if (Vulkan_INCLUDE_DIRS) + target_include_directories(raylib PUBLIC $) + message(STATUS "Adding Vulkan include directories: ${Vulkan_INCLUDE_DIRS}") + endif() +endif() + if (SUPPORT_MODULE_RAUDIO) MESSAGE(STATUS "Audio Backend: miniaudio") else () diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 83c13d34e..d4ed3503f 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -54,6 +54,25 @@ #include "GLFW/glfw3.h" // GLFW3 library: Windows, OpenGL context and Input management // NOTE: GLFW3 already includes gl.h (OpenGL) headers +#if defined(GRAPHICS_API_VULKAN) + #if defined(__APPLE__) + // MoltenVK requires a specific include order and defines + #define VK_USE_PLATFORM_MACOS_MVK + #define VK_USE_PLATFORM_METAL_EXT // If using newer MoltenVK/GLFW with direct Metal layer access + #elif defined(_WIN32) + #define VK_USE_PLATFORM_WIN32_KHR + #else // Assuming X11 or Wayland for other Linux/Unix via GLFW + // GLFW handles these includes mostly, but define for clarity if needed by MoltenVK headers + #if defined(GLFW_EXPOSE_NATIVE_X11) // This define might be set by glfw3native.h later + #define VK_USE_PLATFORM_XLIB_KHR + #endif + #if defined(GLFW_EXPOSE_NATIVE_WAYLAND) // This define might be set by glfw3native.h later + #define VK_USE_PLATFORM_WAYLAND_KHR + #endif + #endif + #include +#endif + // Support retrieving native window handlers #if defined(_WIN32) typedef void *PVOID; @@ -108,6 +127,12 @@ static PlatformData platform = { 0 }; // Platform specific data int InitPlatform(void); // Initialize platform (graphics, inputs and more) void ClosePlatform(void); // Close platform +#if defined(GRAPHICS_API_VULKAN) +// Vulkan specific platform functions +static int InitPlatformVulkan(void); +static void ClosePlatformVulkan(void); +#endif + // Error callback event static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error @@ -1317,6 +1342,181 @@ static void DeallocateWrapper(void* block, void* user) } // Initialize platform: graphics, inputs and more +#if defined(GRAPHICS_API_VULKAN) +// Initialize platform for Vulkan (GLFW STUB) +static int InitPlatformVulkan(void) { + TRACELOG(LOG_INFO, "PLATFORM: Initializing platform for Vulkan (GLFW STUB)"); + + glfwSetErrorCallback(ErrorCallback); + + const GLFWallocator allocator = { + .allocate = AllocateWrapper, + .deallocate = DeallocateWrapper, + .reallocate = ReallocateWrapper, + .user = NULL, + }; + glfwInitAllocator(&allocator); + + #if defined(__APPLE__) + glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); + #endif + + if (!glfwInit()) { + TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize GLFW for Vulkan"); + return RL_FALSE; + } + + if (!glfwVulkanSupported()) { + TRACELOG(LOG_FATAL, "PLATFORM: Vulkan not supported by GLFW or system drivers"); + glfwTerminate(); + return RL_FALSE; + } + TRACELOG(LOG_INFO, "PLATFORM: GLFW Vulkan support detected."); + + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // Critical for Vulkan + + // Common window hints from InitPlatform() + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) CORE.Window.fullscreen = true; + if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + else glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); + if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); + else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); + if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) > 0) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + else glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // Cannot be set on creation + if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // Cannot be set on creation + if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE); + else glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE); + if ((CORE.Window.flags & FLAG_WINDOW_TOPMOST) > 0) glfwWindowHint(GLFW_FLOATING, GLFW_TRUE); + else glfwWindowHint(GLFW_FLOATING, GLFW_FALSE); + if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); + else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); + glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE); // Keep old behavior for now + if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) { + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); + #if defined(__APPLE__) + glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE); + #endif + } else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE); + if ((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE); + else glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE); + // MSAA hint is not relevant for Vulkan in this context + + // Determine monitor for fullscreen or initial placement + GLFWmonitor *monitor = NULL; + if (CORE.Window.fullscreen) { + monitor = glfwGetPrimaryMonitor(); + if (!monitor) { + TRACELOG(LOG_WARNING, "GLFW: Failed to get primary monitor for Vulkan fullscreen"); + glfwTerminate(); + return RL_FALSE; + } + SetDimensionsFromMonitor(monitor); + } else { + // For windowed mode, get current monitor to center on later + // This part is tricky because GetCurrentMonitor() needs a window handle. + // We'll get primary and center on that if no better option before window creation. + monitor = glfwGetPrimaryMonitor(); // Default to primary for initial setup + if (monitor) SetDimensionsFromMonitor(monitor); + else { TRACELOG(LOG_WARNING, "GLFW: Could not get primary monitor for initial Vulkan window setup."); } + } + + // Create window + int creationWidth = (CORE.Window.screen.width > 0) ? CORE.Window.screen.width : 640; + int creationHeight = (CORE.Window.screen.height > 0) ? CORE.Window.screen.height : 480; + + platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", CORE.Window.fullscreen ? monitor : NULL, NULL); + CORE.Window.handle = platform.handle; + if (!CORE.Window.handle) { + TRACELOG(LOG_FATAL, "PLATFORM: Failed to create GLFW window for Vulkan"); + glfwTerminate(); + return RL_FALSE; + } + TRACELOG(LOG_INFO, "PLATFORM: GLFW window created for Vulkan"); + + vkInstanceHandle = (VkInstance)0x1; + vkSurfaceHandle = (VkSurfaceKHR)0x1; + TRACELOG(LOG_INFO, "PLATFORM: VkInstance and VkSurfaceKHR STUBBED as non-null for rlvkInit testing."); + + // Setup GLFW callbacks + glfwSetWindowSizeCallback(platform.handle, WindowSizeCallback); + glfwSetWindowPosCallback(platform.handle, WindowPosCallback); + glfwSetWindowMaximizeCallback(platform.handle, WindowMaximizeCallback); + glfwSetWindowIconifyCallback(platform.handle, WindowIconifyCallback); + glfwSetWindowFocusCallback(platform.handle, WindowFocusCallback); + glfwSetDropCallback(platform.handle, WindowDropCallback); + if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) { + glfwSetWindowContentScaleCallback(platform.handle, WindowContentScaleCallback); + } + glfwSetKeyCallback(platform.handle, KeyCallback); + glfwSetCharCallback(platform.handle, CharCallback); + glfwSetMouseButtonCallback(platform.handle, MouseButtonCallback); + glfwSetCursorPosCallback(platform.handle, MouseCursorPosCallback); + glfwSetScrollCallback(platform.handle, MouseScrollCallback); + glfwSetCursorEnterCallback(platform.handle, CursorEnterCallback); + glfwSetJoystickCallback(JoystickCallback); + glfwSetInputMode(platform.handle, GLFW_LOCK_KEY_MODS, GLFW_TRUE); + + int fbWidth = CORE.Window.screen.width; // Fallback to screen width + int fbHeight = CORE.Window.screen.height; // Fallback to screen height + // For Vulkan with GLFW_NO_API, glfwGetFramebufferSize might still be relevant for HighDPI scenarios + // where window coords and pixel coords differ. + glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight); + CORE.Window.render.width = fbWidth; + CORE.Window.render.height = fbHeight; + CORE.Window.currentFbo.width = fbWidth; + CORE.Window.currentFbo.height = fbHeight; + + if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) { + #if !defined(__APPLE__) + if (CORE.Window.screen.width > 0 && CORE.Window.screen.height > 0) { // Avoid division by zero + CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f); + SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight); + } + #endif + } + + if (!CORE.Window.fullscreen && monitor) { // monitor might be null if primary couldn't be fetched + int monitorX = 0, monitorY = 0; + glfwGetMonitorPos(monitor, &monitorX, &monitorY); + int areaWidth = 0, areaHeight = 0; + glfwGetMonitorWorkarea(monitor, NULL, NULL, &areaWidth, &areaHeight); + + int posX = monitorX + (areaWidth - CORE.Window.render.width)/2; + int posY = monitorY + (areaHeight - CORE.Window.render.height)/2; + if (posX < monitorX) posX = monitorX; + if (posY < monitorY) posY = monitorY; + SetWindowPosition(posX, posY); + } + + CORE.Window.ready = RL_TRUE; + TRACELOG(LOG_INFO, "PLATFORM: Vulkan platform initialized successfully (GLFW STUBBED VkInstance/Surface)"); + + InitTimer(); + CORE.Storage.basePath = GetWorkingDirectory(); + + return RL_TRUE; +} + +static void ClosePlatformVulkan(void) { + TRACELOG(LOG_INFO, "PLATFORM: Closing Vulkan platform (GLFW STUB)"); + #if defined(GRAPHICS_API_VULKAN) + vkSurfaceHandle = VK_NULL_HANDLE; + vkInstanceHandle = VK_NULL_HANDLE; + TRACELOG(LOG_INFO, "PLATFORM: VkInstance and VkSurfaceKHR STUBBED as NULL."); + #endif + + if (CORE.Window.handle != NULL) { + glfwDestroyWindow(CORE.Window.handle); + CORE.Window.handle = NULL; + platform.handle = NULL; + } + glfwTerminate(); + TRACELOG(LOG_INFO, "PLATFORM: Vulkan platform resources closed (GLFW STUBBED VkInstance/Surface)"); +} +#endif // GRAPHICS_API_VULKAN + int InitPlatform(void) { glfwSetErrorCallback(ErrorCallback); diff --git a/src/rcore.c b/src/rcore.c index f216a197a..94be04804 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -123,6 +123,16 @@ #define RAYMATH_IMPLEMENTATION #include "raymath.h" // Vector2, Vector3, Quaternion and Matrix functionality +#if defined(GRAPHICS_API_VULKAN) + #include "rlvk.h" // If rlvk functions are called directly from rcore + // It's also possible that rlgl.h handles the dispatch via its own functions. + // The plan suggests InitPlatformVulkan will provide instance/surface to rlvkInit. + // Global/static VkInstance and VkSurfaceKHR to be set by platform layer for rlvkInit. + // This is a temporary approach for the subtask. + VkInstance vkInstanceHandle = VK_NULL_HANDLE; + VkSurfaceKHR vkSurfaceHandle = VK_NULL_HANDLE; +#endif + #if defined(SUPPORT_GESTURES_SYSTEM) #define RGESTURES_IMPLEMENTATION #include "rgestures.h" // Gestures detection functionality @@ -681,7 +691,13 @@ void InitWindow(int width, int height, const char *title) // Initialize platform //-------------------------------------------------------------- + //int result = InitPlatform(); +#if defined(GRAPHICS_API_VULKAN) + // InitPlatformVulkan() will be created in step 6 and should set vkInstanceHandle and vkSurfaceHandle + int result = InitPlatformVulkan(); +#else int result = InitPlatform(); +#endif if (result != 0) { @@ -690,10 +706,39 @@ void InitWindow(int width, int height, const char *title) } //-------------------------------------------------------------- +#if defined(GRAPHICS_API_VULKAN) + if (CORE.Window.ready) { // Assuming InitPlatformVulkan sets CORE.Window.ready on success + rlvkInit(vkInstanceHandle, vkSurfaceHandle, CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); + if (rlvkIsReady()) { + isGpuReady = true; + TRACELOG(LOG_INFO, "RCORE: Vulkan backend initialized successfully via rlvkInit."); + } else { + TRACELOG(LOG_ERROR, "RCORE: Failed to initialize Vulkan backend via rlvkInit."); + CORE.Window.ready = false; // Ensure window is not marked as ready + // Potentially call ClosePlatformVulkan here if InitPlatformVulkan succeeded but rlvkInit failed + ClosePlatformVulkan(); + return; + } + } +#endif + // Initialize rlgl default data (buffers and shaders) // NOTE: CORE.Window.currentFbo.width and CORE.Window.currentFbo.height not used, just stored as globals in rlgl rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); - isGpuReady = true; // Flag to note GPU has been initialized successfully + + #if !defined(GRAPHICS_API_VULKAN) + // If not using Vulkan (i.e., using OpenGL), and rlglInit() for OpenGL has completed, + // then the GPU is considered ready. + // This line was originally after rlglInit() before Vulkan changes. + isGpuReady = true; + #endif + // If GRAPHICS_API_VULKAN is defined, isGpuReady is set (or not) earlier, + // based on the success of rlvkInit(). + // We can add a final check here if really needed, but the previous logic should suffice: + // else if (!isGpuReady && defined(GRAPHICS_API_VULKAN)) { + // TRACELOG(LOG_ERROR, "RCORE: GPU not ready after Vulkan initialization sequence (final check)."); + // } + // Setup default viewport SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); @@ -753,11 +798,21 @@ void CloseWindow(void) UnloadFontDefault(); // WARNING: Module required: rtext #endif +#if defined(GRAPHICS_API_VULKAN) + if (rlvkIsReady()) { // Check if it was successfully initialized + rlvkClose(); + } +#endif rlglClose(); // De-init rlgl // De-initialize platform //-------------------------------------------------------------- + //ClosePlatform(); +#if defined(GRAPHICS_API_VULKAN) + ClosePlatformVulkan(); +#else ClosePlatform(); +#endif //-------------------------------------------------------------- CORE.Window.ready = false; diff --git a/src/rlgl.h b/src/rlgl.h index d595f4606..c89a78fe8 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -826,6 +826,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #if defined(RLGL_IMPLEMENTATION) +#if defined(GRAPHICS_API_VULKAN) + #include "rlvk.h" // Path relative to rcore.c or where rlgl.h implementation is +#endif + // Expose OpenGL functions from glad in raylib #if defined(BUILD_LIBTYPE_SHARED) #define GLAD_API_CALL_EXPORT @@ -1455,6 +1459,14 @@ void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); } // Initialize drawing mode (how to organize vertex) void rlBegin(int mode) { +#if defined(GRAPHICS_API_VULKAN) + // In Vulkan, rlBegin equivalent would be part of starting a command buffer or render pass. + // For immediate mode emulation, this might involve setting up for a new batch. + // rlvkBeginDrawing() is the target. The 'mode' parameter might be used by rlvk to set pipeline state. + rlvkBeginDrawing(); + // The original logic for rlBegin in OpenGL was to manage batching and draw call generation + // based on mode changes. Vulkan path might do similar for its own batching or just rely on rlvk. +#else // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode) @@ -1483,15 +1495,22 @@ void rlBegin(int mode) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId; } +#endif // GRAPHICS_API_VULKAN } // Finish vertex providing void rlEnd(void) { +#if defined(GRAPHICS_API_VULKAN) + // In Vulkan, rlEnd equivalent would be part of ending a command buffer or render pass. + // rlvkEndDrawing() is the target. + rlvkEndDrawing(); +#else // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) RLGL.currentBatch->currentDepth += (1.0f/20000.0f); +#endif // GRAPHICS_API_VULKAN } // Define one vertex (position) @@ -2050,6 +2069,9 @@ bool rlIsStereoRenderEnabled(void) // Clear color buffer with color void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { +#if defined(GRAPHICS_API_VULKAN) + rlvkClearBackground(r, g, b, a); // Call the Vulkan equivalent +#else // Color values clamp to 0.0f(0) and 1.0f(255) float cr = (float)r/255; float cg = (float)g/255; @@ -2057,6 +2079,7 @@ void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned ch float ca = (float)a/255; glClearColor(cr, cg, cb, ca); +#endif } // Clear used screen buffers (color and depth) @@ -2233,6 +2256,43 @@ static void GLAPIENTRY rlDebugMessageCallback(GLenum source, GLenum type, GLuint // Initialize rlgl: OpenGL extensions, default buffers/shaders/textures, OpenGL states void rlglInit(int width, int height) { +#if defined(GRAPHICS_API_VULKAN) + // Most Vulkan initialization is platform and rlvk specific. + // rlgl itself might initialize shared data structures here if any. + // For now, rlvkInit() is expected to be called from rcore.c's InitWindow. + // Load default batch for Vulkan if its structure is generic enough, + // or rlvk will handle its own batching system. + // The plan says: "Initialize rlgl default data (buffers and shaders)" + // This might mean setting up RLGL.State for Vulkan mode. + + // Init default white texture (Vulkan specific) + // unsigned char pixels[4] = { 255, 255, 255, 255 }; + // RLGL.State.defaultTextureId = rlvkLoadTexture(pixels, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); + // if (RLGL.State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully (Vulkan)", RLGL.State.defaultTextureId); + // else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load default texture (Vulkan)"); + + // Load default shader (Vulkan specific) + // rlLoadShaderDefault(); // This needs to be Vulkan aware + // RLGL.State.currentShaderId = RLGL.State.defaultShaderId; + // RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; + + // For now, assume rlvkInit handles this, and rcore.c calls it. + // rlglInit under Vulkan might just set some state flags. + TRACELOG(LOG_INFO, "RLGL: rlglInit called for Vulkan. Expecting rlvkInit to be called from rcore."); + RLGL.State.currentMatrixMode = RL_MODELVIEW; + RLGL.State.currentMatrix = &RLGL.State.modelview; + RLGL.State.modelview = rlMatrixIdentity(); + RLGL.State.projection = rlMatrixIdentity(); + RLGL.State.transform = rlMatrixIdentity(); + // Other RLGL.State initializations as needed. + + // Store screen size into global variables + RLGL.State.framebufferWidth = width; + RLGL.State.framebufferHeight = height; + + TRACELOG(RL_LOG_INFO, "RLGL: Default Vulkan state initialized successfully"); // This is a bit optimistic, more setup needed in rlvk + +#else // This means !defined(GRAPHICS_API_VULKAN) // Enable OpenGL debug context if required #if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT) && defined(GRAPHICS_API_OPENGL_43) if ((glDebugMessageCallback != NULL) && (glDebugMessageControl != NULL)) @@ -2319,11 +2379,18 @@ void rlglInit(int width, int height) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black) glClearDepth(1.0f); // Set clear depth value (default) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D) +#endif // GRAPHICS_API_VULKAN defined check } // Vertex Buffer Object deinitialization (memory free) void rlglClose(void) { +#if defined(GRAPHICS_API_VULKAN) + // rlvkClose(); // This will be called from rcore.c's CloseWindow + TRACELOG(LOG_INFO, "RLGL: rlglClose called for Vulkan. Expecting rlvkClose to be called from rcore."); + // Unload default batch if managed by rlgl for vulkan + // rlUnloadRenderBatch(RLGL.defaultBatch); // This needs to be Vulkan aware or not done here if rlvk handles it +#else // !defined(GRAPHICS_API_VULKAN) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) rlUnloadRenderBatch(RLGL.defaultBatch); @@ -2332,6 +2399,7 @@ void rlglClose(void) glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); #endif +#endif // GRAPHICS_API_VULKAN defined check } // Load OpenGL extensions @@ -3173,6 +3241,11 @@ bool rlCheckRenderBatchLimit(int vCount) // Convert image data to OpenGL texture (returns OpenGL valid Id) unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount) { +#if defined(GRAPHICS_API_VULKAN) + // return rlvkLoadTexture(data, width, height, format, mipmapCount); // Actual call to Vulkan backend + TRACELOG(LOG_DEBUG, "RLGL: rlLoadTexture called (Vulkan path - using stub)"); + return 0; // Placeholder for Vulkan +#else unsigned int id = 0; glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding @@ -3322,6 +3395,7 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format, else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load texture"); return id; +#endif // GRAPHICS_API_VULKAN } // Load depth texture/renderbuffer (to be attached to fbo) @@ -4064,6 +4138,11 @@ void rlUnloadVertexBuffer(unsigned int vboId) // NOTE: If shader string is NULL, using default vertex/fragment shaders unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) { +#if defined(GRAPHICS_API_VULKAN) + // return rlvkLoadShaderCode(vsCode, fsCode); // Actual call to Vulkan backend + TRACELOG(LOG_DEBUG, "RLGL: rlLoadShaderCode called (Vulkan path - using stub)"); + return 0; // Placeholder for Vulkan +#else unsigned int id = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -4136,6 +4215,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) #endif return id; +#endif // GRAPHICS_API_VULKAN } // Compile custom shader and return shader id @@ -4306,6 +4386,11 @@ int rlGetLocationAttrib(unsigned int shaderId, const char *attribName) // Set shader value uniform void rlSetUniform(int locIndex, const void *value, int uniformType, int count) { +#if defined(GRAPHICS_API_VULKAN) + // rlvkSetUniform(locIndex, value, uniformType, count); // Actual call to Vulkan backend + TRACELOG(LOG_DEBUG, "RLGL: rlSetUniform called (Vulkan path - using stub for locIndex %d)", locIndex); + // No return value, placeholder action is just logging. +#else #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) switch (uniformType) { @@ -4329,6 +4414,7 @@ void rlSetUniform(int locIndex, const void *value, int uniformType, int count) // TODO: Support glUniform1uiv(), glUniform2uiv(), glUniform3uiv(), glUniform4uiv() } #endif +#endif // GRAPHICS_API_VULKAN } // Set shader value attribute diff --git a/src/rlvk.c b/src/rlvk.c new file mode 100644 index 000000000..0d7b8044f --- /dev/null +++ b/src/rlvk.c @@ -0,0 +1,77 @@ +#include "rlvk.h" +#include "utils.h" // For TRACELOG if needed +#include // For printf in stubs +#include // For RL_MALLOC, RL_FREE if used + +// Global or static variables for Vulkan state (minimal for stubs) +static bool rlvkReady = false; + +void rlvkInit(VkInstance instance, VkSurfaceKHR surface, int width, int height) { + printf("rlvkInit called (STUB)\n"); + // Minimal check or setup + if (instance != VK_NULL_HANDLE && surface != VK_NULL_HANDLE) { + rlvkReady = true; + TRACELOG(LOG_INFO, "RLVK: Vulkan backend initialized (stubbed)."); + } else { + TRACELOG(LOG_ERROR, "RLVK: Failed to initialize Vulkan backend due to null instance or surface (stubbed)."); + rlvkReady = false; + } +} + +void rlvkClose(void) { + printf("rlvkClose called (STUB)\n"); + rlvkReady = false; + TRACELOG(LOG_INFO, "RLVK: Vulkan backend closed (stubbed)."); +} + +bool rlvkIsReady(void) { + return rlvkReady; +} + +void rlvkBeginDrawing(void) { + // printf("rlvkBeginDrawing called (STUB)\n"); +} + +void rlvkEndDrawing(void) { + // printf("rlvkEndDrawing called (STUB)\n"); +} + +void rlvkClearBackground(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + // printf("rlvkClearBackground called (STUB) with color: %u, %u, %u, %u\n", r, g, b, a); +} + +unsigned int rlvkLoadTexture(const void *data, int width, int height, int format, int mipmaps) { + printf("rlvkLoadTexture called (STUB)\n"); + return 0; // Return a dummy ID +} + +void rlvkUnloadTexture(unsigned int id) { + printf("rlvkUnloadTexture called (STUB) for ID: %u\n", id); +} + +unsigned int rlvkLoadShaderCode(const char *vsCode, const char *fsCode) { + printf("rlvkLoadShaderCode called (STUB)\n"); + return 0; // Return a dummy ID +} + +void rlvkUnloadShaderProgram(unsigned int id) { + printf("rlvkUnloadShaderProgram called (STUB) for ID: %u\n", id); +} + +int rlvkGetLocationUniform(unsigned int shaderId, const char *uniformName) { + // printf("rlvkGetLocationUniform called (STUB) for shader ID: %u, uniform: %s\n", shaderId, uniformName); + return -1; +} + +int rlvkGetLocationAttrib(unsigned int shaderId, const char *attribName) { + // printf("rlvkGetLocationAttrib called (STUB) for shader ID: %u, attrib: %s\n", shaderId, attribName); + return -1; +} + +void rlvkSetUniform(int locIndex, const void *value, int uniformType, int count) { + // printf("rlvkSetUniform called (STUB) for locIndex: %d\n", locIndex); +} + +// ... other rlgl equivalent function stub implementations ... +// TRACELOG can be used for more detailed stub logging if utils.h is appropriately included and linked. +// For now, simple printf might be fine for basic stub verification. diff --git a/src/rlvk.h b/src/rlvk.h new file mode 100644 index 000000000..4e2769a88 --- /dev/null +++ b/src/rlvk.h @@ -0,0 +1,36 @@ +#ifndef RLVK_H +#define RLVK_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialization and Configuration +void rlvkInit(VkInstance instance, VkSurfaceKHR surface, int width, int height); // Simplified, may need more params +void rlvkClose(void); +bool rlvkIsReady(void); + +// Drawing +void rlvkBeginDrawing(void); +void rlvkEndDrawing(void); +void rlvkClearBackground(unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +// Basic Texture Management (Stubs) +unsigned int rlvkLoadTexture(const void *data, int width, int height, int format, int mipmaps); +void rlvkUnloadTexture(unsigned int id); + +// Basic Shader Management (Stubs) +unsigned int rlvkLoadShaderCode(const char *vsCode, const char *fsCode); +void rlvkUnloadShaderProgram(unsigned int id); +int rlvkGetLocationUniform(unsigned int shaderId, const char *uniformName); +int rlvkGetLocationAttrib(unsigned int shaderId, const char *attribName); +void rlvkSetUniform(int locIndex, const void *value, int uniformType, int count); +// ... other rlgl equivalent function declarations as stubs ... + +#ifdef __cplusplus +} +#endif + +#endif // RLVK_H