Compare commits
11
Commits
10e5d7e28c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
136853328a | ||
|
|
9536dbc550 | ||
|
|
466e0345b8 | ||
|
|
4a726321e9 | ||
|
|
f308900207 | ||
|
|
6c6dd5626c | ||
|
|
9a168facec | ||
|
|
fe61e58a50 | ||
|
|
ae10643d04 | ||
|
|
cd8e61933f | ||
|
|
4ad7eb3622 |
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
.cache
|
.cache
|
||||||
.build
|
.build
|
||||||
|
cmake-build
|
||||||
vendor/vulkan
|
vendor/vulkan
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
+401
@@ -0,0 +1,401 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
|
||||||
|
project(window_renderer_test VERSION 0.1.0 LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(WR_FETCH_MISSING_DEPENDENCIES
|
||||||
|
"Download and build dependencies (SDL3, Vulkan, Slang) that are not installed" ON)
|
||||||
|
option(WR_COMPILE_SHADERS
|
||||||
|
"Compile the Slang shader during the build (requires slangc)" ON)
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SDL3
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
find_package(SDL3 3.2 CONFIG QUIET)
|
||||||
|
|
||||||
|
if(NOT SDL3_FOUND)
|
||||||
|
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SDL3 was not found. Install SDL3, or configure with "
|
||||||
|
"-DWR_FETCH_MISSING_DEPENDENCIES=ON.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "SDL3 not found; fetching and building it from source")
|
||||||
|
|
||||||
|
# Build a static SDL3 so the result does not depend on a system SDL3
|
||||||
|
# runtime being present when the application is run.
|
||||||
|
set(SDL_SHARED OFF CACHE BOOL "Build the SDL3 shared library")
|
||||||
|
set(SDL_STATIC ON CACHE BOOL "Build the SDL3 static library")
|
||||||
|
set(SDL_TEST_LIBRARY OFF CACHE BOOL "Build the SDL3 test library")
|
||||||
|
set(SDL_TESTS OFF CACHE BOOL "Build the SDL3 tests")
|
||||||
|
set(SDL_EXAMPLES OFF CACHE BOOL "Build the SDL3 examples")
|
||||||
|
set(SDL_INSTALL OFF CACHE BOOL "Enable SDL3 install rules")
|
||||||
|
|
||||||
|
FetchContent_Declare(SDL3
|
||||||
|
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
||||||
|
GIT_TAG release-3.4.18
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(SDL3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Vulkan headers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
find_package(Vulkan QUIET)
|
||||||
|
|
||||||
|
if(Vulkan_FOUND AND Vulkan_INCLUDE_DIRS)
|
||||||
|
set(WR_VULKAN_INCLUDE_DIRS ${Vulkan_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Vulkan headers were not found. Install the Vulkan SDK, or configure "
|
||||||
|
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Vulkan headers not found; fetching Vulkan-Headers")
|
||||||
|
|
||||||
|
FetchContent_Declare(vulkan_headers
|
||||||
|
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||||
|
GIT_TAG vulkan-sdk-1.4.350.0
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(vulkan_headers)
|
||||||
|
|
||||||
|
set(WR_VULKAN_INCLUDE_DIRS ${vulkan_headers_SOURCE_DIR}/include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# volk (Vulkan meta-loader)
|
||||||
|
#
|
||||||
|
# volk is not guaranteed to be shipped with Vulkan headers. The project
|
||||||
|
# includes <volk/volk.h>, so a fetched volk checkout is placed in a generated
|
||||||
|
# include directory with the expected layout.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
find_path(WR_VOLK_INCLUDE_DIR
|
||||||
|
NAMES volk/volk.h
|
||||||
|
HINTS ${WR_VULKAN_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
find_file(WR_VOLK_SOURCE_FILE
|
||||||
|
NAMES volk.c
|
||||||
|
HINTS ${WR_VULKAN_INCLUDE_DIRS}
|
||||||
|
PATH_SUFFIXES volk
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT WR_VOLK_INCLUDE_DIR OR NOT WR_VOLK_SOURCE_FILE)
|
||||||
|
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"volk was not found in the Vulkan headers. Install volk, or configure "
|
||||||
|
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "volk not found; fetching it")
|
||||||
|
|
||||||
|
FetchContent_Declare(volk
|
||||||
|
GIT_REPOSITORY https://github.com/zeux/volk.git
|
||||||
|
GIT_TAG vulkan-sdk-1.4.350.0
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
SOURCE_SUBDIR _disable_add_subdirectory
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(volk)
|
||||||
|
|
||||||
|
set(WR_VOLK_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include)
|
||||||
|
file(MAKE_DIRECTORY ${WR_VOLK_INCLUDE_DIR}/volk)
|
||||||
|
configure_file(
|
||||||
|
${volk_SOURCE_DIR}/volk.h
|
||||||
|
${WR_VOLK_INCLUDE_DIR}/volk/volk.h
|
||||||
|
COPYONLY
|
||||||
|
)
|
||||||
|
set(WR_VOLK_SOURCE_FILE ${volk_SOURCE_DIR}/volk.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Vulkan Memory Allocator (VMA)
|
||||||
|
#
|
||||||
|
# VMA is not part of the Vulkan headers either. The project includes
|
||||||
|
# <vma/vk_mem_alloc.h>, so a fetched copy is placed in the same generated
|
||||||
|
# include directory.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
find_path(WR_VMA_INCLUDE_DIR
|
||||||
|
NAMES vma/vk_mem_alloc.h
|
||||||
|
HINTS ${WR_VULKAN_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT WR_VMA_INCLUDE_DIR)
|
||||||
|
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Vulkan Memory Allocator (VMA) was not found. Install VMA, or configure "
|
||||||
|
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Vulkan Memory Allocator not found; fetching it")
|
||||||
|
|
||||||
|
FetchContent_Declare(vma
|
||||||
|
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||||
|
GIT_TAG v3.5.0
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
SOURCE_SUBDIR _disable_add_subdirectory
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(vma)
|
||||||
|
|
||||||
|
set(WR_VMA_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include)
|
||||||
|
file(MAKE_DIRECTORY ${WR_VMA_INCLUDE_DIR}/vma)
|
||||||
|
configure_file(
|
||||||
|
${vma_SOURCE_DIR}/include/vk_mem_alloc.h
|
||||||
|
${WR_VMA_INCLUDE_DIR}/vma/vk_mem_alloc.h
|
||||||
|
COPYONLY
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Application
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
add_executable(main
|
||||||
|
src/main.c
|
||||||
|
src/wapp/wapp.c
|
||||||
|
src/config/config_src.c
|
||||||
|
src/window/window_src.c
|
||||||
|
src/gpu/gpu_c_src.c
|
||||||
|
src/gpu/gpu_cc_src.cpp
|
||||||
|
${WR_VOLK_SOURCE_FILE}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(main PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${WR_VULKAN_INCLUDE_DIRS}
|
||||||
|
${WR_VOLK_INCLUDE_DIR}
|
||||||
|
${WR_VMA_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(main PRIVATE
|
||||||
|
WP_DEBUG_ASSERT
|
||||||
|
CGLM_DEFINE_PRINTS
|
||||||
|
USE_SDL_WINDOW_BACKEND
|
||||||
|
USE_VULKAN_RENDER_BACKEND
|
||||||
|
VK_NO_PROTOTYPES
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
target_compile_options(main PRIVATE
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:-Wno-nullability-completeness>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(main PRIVATE
|
||||||
|
SDL3::SDL3
|
||||||
|
${CMAKE_DL_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries(main PRIVATE m)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Shaders
|
||||||
|
#
|
||||||
|
# The application loads "shaders/shader.spv" relative to its working directory,
|
||||||
|
# so the SPIR-V output is placed in <build-dir>/shaders.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if(WR_COMPILE_SHADERS)
|
||||||
|
find_program(SLANGC_EXECUTABLE NAMES slangc)
|
||||||
|
|
||||||
|
if(NOT SLANGC_EXECUTABLE AND WR_FETCH_MISSING_DEPENDENCIES)
|
||||||
|
# Download the prebuilt Slang release instead of requiring the user to
|
||||||
|
# install the compiler. Asset names and hashes come from the pinned
|
||||||
|
# GitHub release below.
|
||||||
|
set(WR_SLANG_VERSION "2026.20")
|
||||||
|
|
||||||
|
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" WR_SLANG_ARCH)
|
||||||
|
if(WR_SLANG_ARCH MATCHES "^(x86_64|amd64|x64)$")
|
||||||
|
set(WR_SLANG_ARCH "x86_64")
|
||||||
|
elseif(WR_SLANG_ARCH MATCHES "^(aarch64|arm64|arm64e)$")
|
||||||
|
set(WR_SLANG_ARCH "aarch64")
|
||||||
|
else()
|
||||||
|
set(WR_SLANG_ARCH "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(WR_SLANG_OS "linux")
|
||||||
|
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
set(WR_SLANG_OS "macos")
|
||||||
|
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(WR_SLANG_OS "windows")
|
||||||
|
else()
|
||||||
|
set(WR_SLANG_OS "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WR_SLANG_OS AND WR_SLANG_ARCH)
|
||||||
|
set(WR_SLANG_PLATFORM "${WR_SLANG_OS}-${WR_SLANG_ARCH}")
|
||||||
|
else()
|
||||||
|
set(WR_SLANG_PLATFORM "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WR_SLANG_PLATFORM STREQUAL "linux-x86_64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-linux-x86_64-glibc-2.28.tar.gz")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"84ebd777968caceea26b21bfd014341078be6047be6c5a963a69f984f896cebd")
|
||||||
|
elseif(WR_SLANG_PLATFORM STREQUAL "linux-aarch64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-linux-aarch64-glibc-2.28.tar.gz")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"9959d741713162efdbd863ff6d32400432b6e103eae3a9ee0afbdba6a00c6a9e")
|
||||||
|
elseif(WR_SLANG_PLATFORM STREQUAL "macos-x86_64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-macos-x86_64.tar.gz")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"b4f01f615dc625f60c593d7d0a4bbd38e05dfa2a34bfd3973017c309d866feaa")
|
||||||
|
elseif(WR_SLANG_PLATFORM STREQUAL "macos-aarch64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-macos-aarch64.tar.gz")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"07fa8833fdbb343c3674c84fdd885910f495f3daaaa0c732b32980151e8b58c4")
|
||||||
|
elseif(WR_SLANG_PLATFORM STREQUAL "windows-x86_64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-windows-x86_64.zip")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"e6dd32bbddf1720ebb4e679d55e9635ce792865a5bd84f3d2cd9af28647c0174")
|
||||||
|
elseif(WR_SLANG_PLATFORM STREQUAL "windows-aarch64")
|
||||||
|
set(WR_SLANG_ASSET
|
||||||
|
"slang-${WR_SLANG_VERSION}-windows-aarch64.zip")
|
||||||
|
set(WR_SLANG_SHA256
|
||||||
|
"4f18a7e76a59969bc9bf6ea596bd9e496a3c689af173990ae028b18f03e1ac1a")
|
||||||
|
else()
|
||||||
|
set(WR_SLANG_ASSET "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WR_SLANG_ASSET)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"slangc was not found, and no prebuilt Slang archive is available "
|
||||||
|
"for ${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR}. "
|
||||||
|
"Install the Slang compiler, or configure with "
|
||||||
|
"-DWR_COMPILE_SHADERS=OFF.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(WR_SLANG_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/slang")
|
||||||
|
set(WR_SLANG_ARCHIVE
|
||||||
|
"${WR_SLANG_DOWNLOAD_DIR}/${WR_SLANG_ASSET}")
|
||||||
|
set(WR_SLANG_URL
|
||||||
|
"https://github.com/shader-slang/slang/releases/download/v${WR_SLANG_VERSION}/${WR_SLANG_ASSET}")
|
||||||
|
|
||||||
|
if(EXISTS "${WR_SLANG_ARCHIVE}")
|
||||||
|
file(SHA256 "${WR_SLANG_ARCHIVE}" WR_SLANG_ACTUAL_SHA256)
|
||||||
|
if(NOT WR_SLANG_ACTUAL_SHA256 STREQUAL WR_SLANG_SHA256)
|
||||||
|
message(STATUS "Removing corrupt Slang archive")
|
||||||
|
file(REMOVE "${WR_SLANG_ARCHIVE}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${WR_SLANG_ARCHIVE}")
|
||||||
|
message(STATUS "Downloading Slang ${WR_SLANG_VERSION} for ${WR_SLANG_PLATFORM}")
|
||||||
|
file(DOWNLOAD
|
||||||
|
"${WR_SLANG_URL}"
|
||||||
|
"${WR_SLANG_ARCHIVE}"
|
||||||
|
EXPECTED_HASH SHA256=${WR_SLANG_SHA256}
|
||||||
|
STATUS WR_SLANG_DOWNLOAD_STATUS
|
||||||
|
TLS_VERIFY ON
|
||||||
|
)
|
||||||
|
list(GET WR_SLANG_DOWNLOAD_STATUS 0 WR_SLANG_DOWNLOAD_CODE)
|
||||||
|
list(GET WR_SLANG_DOWNLOAD_STATUS 1 WR_SLANG_DOWNLOAD_MESSAGE)
|
||||||
|
if(NOT WR_SLANG_DOWNLOAD_CODE EQUAL 0)
|
||||||
|
file(REMOVE "${WR_SLANG_ARCHIVE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Failed to download Slang from ${WR_SLANG_URL}: "
|
||||||
|
"${WR_SLANG_DOWNLOAD_MESSAGE}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(WR_SLANG_EXECUTABLE
|
||||||
|
"${WR_SLANG_DOWNLOAD_DIR}/bin/slangc.exe")
|
||||||
|
else()
|
||||||
|
set(WR_SLANG_EXECUTABLE
|
||||||
|
"${WR_SLANG_DOWNLOAD_DIR}/bin/slangc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${WR_SLANG_EXECUTABLE}")
|
||||||
|
message(STATUS "Extracting Slang ${WR_SLANG_VERSION}")
|
||||||
|
file(ARCHIVE_EXTRACT
|
||||||
|
INPUT "${WR_SLANG_ARCHIVE}"
|
||||||
|
DESTINATION "${WR_SLANG_DOWNLOAD_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${WR_SLANG_EXECUTABLE}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The Slang archive did not contain bin/slangc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(SLANGC_EXECUTABLE "${WR_SLANG_EXECUTABLE}")
|
||||||
|
message(STATUS "Using downloaded Slang compiler: ${SLANGC_EXECUTABLE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT SLANGC_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"slangc was not found. Install the Slang compiler, configure with "
|
||||||
|
"-DWR_FETCH_MISSING_DEPENDENCIES=ON to download it, or configure with "
|
||||||
|
"-DWR_COMPILE_SHADERS=OFF.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(WR_SHADER_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/shaders/shader.slang)
|
||||||
|
set(WR_SHADER_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/shaders)
|
||||||
|
set(WR_SHADER_OUTPUT ${WR_SHADER_OUTPUT_DIR}/shader.spv)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${WR_SHADER_OUTPUT}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${WR_SHADER_OUTPUT_DIR}
|
||||||
|
COMMAND ${SLANGC_EXECUTABLE}
|
||||||
|
${WR_SHADER_SOURCE}
|
||||||
|
-entry vertMain
|
||||||
|
-entry fragMain
|
||||||
|
-o ${WR_SHADER_OUTPUT}
|
||||||
|
DEPENDS ${WR_SHADER_SOURCE}
|
||||||
|
COMMENT "Compiling shader.slang"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(shaders ALL DEPENDS ${WR_SHADER_OUTPUT})
|
||||||
|
add_dependencies(main shaders)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Assets
|
||||||
|
#
|
||||||
|
# The application loads "assets/collections.png" relative to its working
|
||||||
|
# directory, so the assets directory is copied into <build-dir>/assets.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
set(WR_ASSETS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/assets)
|
||||||
|
set(WR_ASSETS_DEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/assets)
|
||||||
|
|
||||||
|
if(EXISTS ${WR_ASSETS_SOURCE_DIR})
|
||||||
|
add_custom_target(copy_assets ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${WR_ASSETS_SOURCE_DIR}
|
||||||
|
${WR_ASSETS_DEST_DIR}
|
||||||
|
COMMENT "Copying assets"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
add_dependencies(main copy_assets)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(run
|
||||||
|
COMMAND $<TARGET_FILE:main>
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
DEPENDS main
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
||||||
|
|
||||||
|
if(TARGET shaders)
|
||||||
|
add_dependencies(run shaders)
|
||||||
|
endif()
|
||||||
@@ -26,6 +26,7 @@ OBJDIR = $(BUILDDIR)/obj
|
|||||||
COBJDIR = $(OBJDIR)/c
|
COBJDIR = $(OBJDIR)/c
|
||||||
CXXOBJDIR = $(OBJDIR)/cxx
|
CXXOBJDIR = $(OBJDIR)/cxx
|
||||||
SHADER_OUTDIR = $(BUILDDIR)/shaders
|
SHADER_OUTDIR = $(BUILDDIR)/shaders
|
||||||
|
ASSETS_DIR = assets
|
||||||
|
|
||||||
ifeq ($(WND_BKND), SDL)
|
ifeq ($(WND_BKND), SDL)
|
||||||
CFLAGS += -DUSE_SDL_WINDOW_BACKEND
|
CFLAGS += -DUSE_SDL_WINDOW_BACKEND
|
||||||
@@ -47,7 +48,7 @@ OUT_NAME = main
|
|||||||
OUT = $(BUILDDIR)/$(OUT_NAME)
|
OUT = $(BUILDDIR)/$(OUT_NAME)
|
||||||
SHADER_OUT = $(SHADER_OUTDIR)/shader.spv
|
SHADER_OUT = $(SHADER_OUTDIR)/shader.spv
|
||||||
|
|
||||||
build: $(OUT) $(SHADER_OUT)
|
build: $(OUT) $(SHADER_OUT) copy-assets
|
||||||
|
|
||||||
$(OUT): $(OBJS)
|
$(OUT): $(OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o "$@" $^ $(LDLIBS)
|
$(CXX) $(LDFLAGS) -o "$@" $^ $(LDLIBS)
|
||||||
@@ -68,8 +69,11 @@ $(SHADER_OUT): $(SHADER_SRC)
|
|||||||
@mkdir -p $(SHADER_OUTDIR)
|
@mkdir -p $(SHADER_OUTDIR)
|
||||||
$(SLANGC) $(SHADER_SRC) $(SLANGC_FLAGS) -o $(SHADER_OUT)
|
$(SLANGC) $(SHADER_SRC) $(SLANGC_FLAGS) -o $(SHADER_OUT)
|
||||||
|
|
||||||
|
copy-assets:
|
||||||
|
@cp -r $(ASSETS_DIR) $(BUILDDIR)
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@cd $(BUILDDIR) && ./$(OUT_NAME)
|
@cd $(BUILDDIR) && VK_LAYER_MESSAGE_ID_FILTER=0x8adbf7e3,0x8b6f2f9a ./$(OUT_NAME)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(BUILD_ROOT)
|
@rm -rf $(BUILD_ROOT)
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
# Window/Renderer Test
|
# Window/Renderer Test
|
||||||
|
|
||||||
A window and a custom renderer implementation using wrappers around SDL3 and Vulkan with ability to add support for other APIs
|
A window and a custom renderer implementation using wrappers around SDL3 and Vulkan with ability to add support for other APIs.
|
||||||
|
|
||||||
|
## Cloning the repo
|
||||||
|
|
||||||
|
```console
|
||||||
|
git clone --recursive http://git.thewizardapprentice.com/abdelrahman/window_renderer_test.git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Run the following commands to build the code
|
||||||
|
|
||||||
|
```console
|
||||||
|
cmake -S . -B cmake-build && cmake --build cmake-build
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run using the following command
|
||||||
|
|
||||||
|
```console
|
||||||
|
cd cmake-build && ./main && cd ../
|
||||||
|
```
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
+24
-6
@@ -354,6 +354,13 @@ typedef struct GpuBufferCreateRequest {
|
|||||||
GpuBufferUsage usage;
|
GpuBufferUsage usage;
|
||||||
} GpuBufferCreateRequest;
|
} GpuBufferCreateRequest;
|
||||||
|
|
||||||
|
typedef struct GpuBufferFlushRequest {
|
||||||
|
GpuBuffer buffer;
|
||||||
|
GpuDevice *device;
|
||||||
|
u64 offset;
|
||||||
|
u64 size;
|
||||||
|
} GpuBufferFlushRequest;
|
||||||
|
|
||||||
typedef struct GpuFence GpuFence;
|
typedef struct GpuFence GpuFence;
|
||||||
typedef GpuFence **GpuFencePtrArray;
|
typedef GpuFence **GpuFencePtrArray;
|
||||||
|
|
||||||
@@ -1159,12 +1166,21 @@ typedef struct GpuCmdDispatchBaseRequest {
|
|||||||
u32 group_count_z;
|
u32 group_count_z;
|
||||||
} GpuCmdDispatchBaseRequest;
|
} GpuCmdDispatchBaseRequest;
|
||||||
|
|
||||||
typedef struct GpuQueueSubmitRequest {
|
typedef struct GpuBufferImageCopy {
|
||||||
GpuSemaphorePtrArray wait_semaphores;
|
GpuImageSubresourceLayers image_subresource;
|
||||||
GpuPipelineStageFlagsArray wait_dst_stage_masks;
|
GpuOffset3d image_offset;
|
||||||
GpuCommandBufferPtrArray command_buffers;
|
GpuExtent3d image_extent;
|
||||||
GpuSemaphorePtrArray signal_semaphores;
|
u64 buffer_offset;
|
||||||
} GpuQueueSubmitRequest;
|
} GpuBufferImageCopy;
|
||||||
|
typedef GpuBufferImageCopy *GpuBufferImageCopyArray;
|
||||||
|
|
||||||
|
typedef struct GpuCmdCopyBufferToImageRequest {
|
||||||
|
GpuCommandBuffer *command_buffer;
|
||||||
|
GpuBuffer *src_buffer;
|
||||||
|
GpuImage *dst_image;
|
||||||
|
GpuImageLayout dst_image_layout;
|
||||||
|
GpuBufferImageCopyArray copy_regions;
|
||||||
|
} GpuCmdCopyBufferToImageRequest;
|
||||||
|
|
||||||
GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request);
|
GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request);
|
||||||
GpuPhysicalDevice gpuFindPhysicalDevice(const WpAllocator *allocator, const WpAllocator *temp,
|
GpuPhysicalDevice gpuFindPhysicalDevice(const WpAllocator *allocator, const WpAllocator *temp,
|
||||||
@@ -1192,6 +1208,7 @@ GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator
|
|||||||
ivec3s gpuGetImageSize(GpuImage *image);
|
ivec3s gpuGetImageSize(GpuImage *image);
|
||||||
GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request);
|
GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request);
|
||||||
void gpuDestroyBuffer(GpuBuffer *buffer);
|
void gpuDestroyBuffer(GpuBuffer *buffer);
|
||||||
|
void gpuFlushBuffer(GpuBufferFlushRequest request);
|
||||||
GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device);
|
GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device);
|
||||||
void gpuDestroyFence(GpuFence *fence);
|
void gpuDestroyFence(GpuFence *fence);
|
||||||
void gpuResetFences(const WpAllocator *temp, GpuResetFencesRequest request);
|
void gpuResetFences(const WpAllocator *temp, GpuResetFencesRequest request);
|
||||||
@@ -1244,6 +1261,7 @@ void gpuCmdDraw(GpuCmdDrawRequest request);
|
|||||||
void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request);
|
void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request);
|
||||||
void gpuCmdDispatch(GpuCmdDispatchRequest request);
|
void gpuCmdDispatch(GpuCmdDispatchRequest request);
|
||||||
void gpuCmdDispatchBase(GpuCmdDispatchBaseRequest request);
|
void gpuCmdDispatchBase(GpuCmdDispatchBaseRequest request);
|
||||||
|
void gpuCmdCopyBufferToImage(const WpAllocator *temp, GpuCmdCopyBufferToImageRequest request);
|
||||||
|
|
||||||
#ifdef WP_PLATFORM_CPP
|
#ifdef WP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
+178
-5
@@ -7,9 +7,9 @@
|
|||||||
#include "../../window/window_inc.h"
|
#include "../../window/window_inc.h"
|
||||||
#include "../../wapp/wapp.h"
|
#include "../../wapp/wapp.h"
|
||||||
#include "../../cglm/struct.h"
|
#include "../../cglm/struct.h"
|
||||||
#include <stdio.h>
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "../../stb_image/stb_image.h"
|
#include "../../stb_image/stb_image.h"
|
||||||
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef USE_SDL_WINDOW_BACKEND
|
#ifdef USE_SDL_WINDOW_BACKEND
|
||||||
@@ -77,6 +77,7 @@ typedef VkRenderingAttachmentInfo *VkRenderingAttachmen
|
|||||||
typedef VkSemaphoreSubmitInfo *VkSemaphoreSubmitInfoArray;
|
typedef VkSemaphoreSubmitInfo *VkSemaphoreSubmitInfoArray;
|
||||||
typedef VkCommandBufferSubmitInfo *VkCommandBufferSubmitInfoArray;
|
typedef VkCommandBufferSubmitInfo *VkCommandBufferSubmitInfoArray;
|
||||||
typedef VkImageBlit2 *VkImageBlit2Array;
|
typedef VkImageBlit2 *VkImageBlit2Array;
|
||||||
|
typedef VkBufferImageCopy *VkBufferImageCopyArray;
|
||||||
|
|
||||||
struct GpuInstance {
|
struct GpuInstance {
|
||||||
VkInstance vk_instance;
|
VkInstance vk_instance;
|
||||||
@@ -315,10 +316,13 @@ wp_intern VkAttachmentStoreOp vkAttachmentStoreOpFromGpuAttachmentStore
|
|||||||
wp_intern GpuAttachmentStoreOp gpuAttachmentStoreOpFromVkAttachmentStoreOp(VkAttachmentStoreOp op);
|
wp_intern GpuAttachmentStoreOp gpuAttachmentStoreOpFromVkAttachmentStoreOp(VkAttachmentStoreOp op);
|
||||||
wp_intern VkResolveModeFlagBits vkResolveModeFlagsFromGpuResolveModeFlags(GpuResolveModeFlags flags);
|
wp_intern VkResolveModeFlagBits vkResolveModeFlagsFromGpuResolveModeFlags(GpuResolveModeFlags flags);
|
||||||
wp_intern GpuResolveModeFlags gpuResolveModeFlagsFromVkResolveModeFlags(VkResolveModeFlags flags);
|
wp_intern GpuResolveModeFlags gpuResolveModeFlagsFromVkResolveModeFlags(VkResolveModeFlags flags);
|
||||||
|
wp_intern u32 calcMaxMipLevelsForSize(ivec3s size);
|
||||||
|
|
||||||
GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request) {
|
GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request) {
|
||||||
assertWithLogger(volkInitialize() == VK_SUCCESS, &logger, "Failed to initialise volk");
|
assertWithLogger(volkInitialize() == VK_SUCCESS, &logger, "Failed to initialise volk");
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(true);
|
||||||
|
|
||||||
VpProfileProperties profile = {
|
VpProfileProperties profile = {
|
||||||
.profileName = VP_TEST_WINDOW_RENDERER_NAME,
|
.profileName = VP_TEST_WINDOW_RENDERER_NAME,
|
||||||
.specVersion = VP_TEST_WINDOW_RENDERER_SPEC_VERSION,
|
.specVersion = VP_TEST_WINDOW_RENDERER_SPEC_VERSION,
|
||||||
@@ -857,6 +861,8 @@ GpuSampler *gpuCreateSampler(const WpAllocator *allocator, GpuSamplerCreateReque
|
|||||||
|
|
||||||
wpLogDebug(&logger, wpStr8Lit("Created Vulkan sampler"));
|
wpLogDebug(&logger, wpStr8Lit("Created Vulkan sampler"));
|
||||||
|
|
||||||
|
output->device = request.device;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,6 +875,7 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req
|
|||||||
GpuImage *output = wpMemAllocatorAlloc(allocator, sizeof(GpuImage));
|
GpuImage *output = wpMemAllocatorAlloc(allocator, sizeof(GpuImage));
|
||||||
assertWithLogger(output != NULL, &logger, "Failed to allocate image");
|
assertWithLogger(output != NULL, &logger, "Failed to allocate image");
|
||||||
|
|
||||||
|
u32 mip_levels = min(calcMaxMipLevelsForSize(request.size), request.subresource.level_count);
|
||||||
VkFormat format = vkFormatFromGpuFormat(request.format);
|
VkFormat format = vkFormatFromGpuFormat(request.format);
|
||||||
VkImageCreateInfo image_create_info = {
|
VkImageCreateInfo image_create_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||||
@@ -877,7 +884,7 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req
|
|||||||
.extent = (VkExtent3D){ .width = request.size.x,
|
.extent = (VkExtent3D){ .width = request.size.x,
|
||||||
.height = request.size.y,
|
.height = request.size.y,
|
||||||
.depth = request.size.z },
|
.depth = request.size.z },
|
||||||
.mipLevels = request.subresource.level_count,
|
.mipLevels = mip_levels,
|
||||||
.arrayLayers = request.subresource.layer_count,
|
.arrayLayers = request.subresource.layer_count,
|
||||||
.samples = vkSampleCountFromGpuSampleCount(request.samples),
|
.samples = vkSampleCountFromGpuSampleCount(request.samples),
|
||||||
.tiling = vkImageTilingFromGpuImageTiling(request.tiling),
|
.tiling = vkImageTilingFromGpuImageTiling(request.tiling),
|
||||||
@@ -888,8 +895,24 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req
|
|||||||
.initialLayout = vkImageLayoutFromGpuImageLayout(request.layout),
|
.initialLayout = vkImageLayoutFromGpuImageLayout(request.layout),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if the image requires a dedicated allocation
|
||||||
|
VkMemoryDedicatedRequirements dedicated_memory_reqs = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
||||||
|
};
|
||||||
|
VkMemoryRequirements2 memory_reqs = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||||
|
.pNext = &dedicated_memory_reqs,
|
||||||
|
};
|
||||||
|
VkDeviceImageMemoryRequirements image_memory_reqs = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS,
|
||||||
|
.pCreateInfo = &image_create_info,
|
||||||
|
};
|
||||||
|
vkGetDeviceImageMemoryRequirements(request.device->vk_device, &image_memory_reqs, &memory_reqs);
|
||||||
|
|
||||||
|
b8 requires_dedicated_memory = dedicated_memory_reqs.requiresDedicatedAllocation ||
|
||||||
|
dedicated_memory_reqs.prefersDedicatedAllocation;
|
||||||
VmaAllocationCreateInfo alloc_create_info = {
|
VmaAllocationCreateInfo alloc_create_info = {
|
||||||
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
|
.flags = requires_dedicated_memory ? VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT : 0,
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -932,11 +955,14 @@ GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator, const WpAllocator *
|
|||||||
wpStr8CopyToCstr(buf, &request.filename, request.filename.size + 1);
|
wpStr8CopyToCstr(buf, &request.filename, request.filename.size + 1);
|
||||||
|
|
||||||
i32 width, height, channels;
|
i32 width, height, channels;
|
||||||
const u8 *data = stbi_load(buf, &width, &height, &channels, 4);
|
i32 requested_channels = 4;
|
||||||
|
const u8 *data = stbi_load(buf, &width, &height, &channels, requested_channels);
|
||||||
assertWithLogger(data != NULL, &logger, "Failed to load image data");
|
assertWithLogger(data != NULL, &logger, "Failed to load image data");
|
||||||
|
|
||||||
|
GpuDevice *device = request.command_pool->device;
|
||||||
|
|
||||||
GpuImageCreateRequest img_request = {
|
GpuImageCreateRequest img_request = {
|
||||||
.device = request.command_pool->device,
|
.device = device,
|
||||||
.size = { .x = width, .y = height, .z = 1 },
|
.size = { .x = width, .y = height, .z = 1 },
|
||||||
.type = GPU_IMAGE_TYPE_2D,
|
.type = GPU_IMAGE_TYPE_2D,
|
||||||
.format = GPU_FORMAT_R8G8B8A8_SRGB,
|
.format = GPU_FORMAT_R8G8B8A8_SRGB,
|
||||||
@@ -954,8 +980,114 @@ GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator, const WpAllocator *
|
|||||||
};
|
};
|
||||||
GpuImage *output = gpuCreateImage(allocator, img_request);
|
GpuImage *output = gpuCreateImage(allocator, img_request);
|
||||||
|
|
||||||
|
u64 data_size = width * height * requested_channels * sizeof(u8);
|
||||||
|
GpuBufferCreateRequest temp_buf_request = {
|
||||||
|
.device = device,
|
||||||
|
.size = data_size,
|
||||||
|
.usage = GPU_BUFFER_USAGE_TRANSFER_SRC,
|
||||||
|
};
|
||||||
|
GpuBuffer temp_storage = gpuCreateBuffer(allocator, temp_buf_request);
|
||||||
|
memcpy(temp_storage.cpu_mapping, data, data_size);
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = temp_storage });
|
||||||
|
|
||||||
stbi_image_free((void *)data);
|
stbi_image_free((void *)data);
|
||||||
|
|
||||||
|
GpuCommandBufferAllocateRequest cb_request = {
|
||||||
|
.pool = request.command_pool,
|
||||||
|
.buffer_count = 1,
|
||||||
|
};
|
||||||
|
GpuCommandBufferPtrArray cbs = gpuAllocateCommandBuffers(allocator, temp, cb_request);
|
||||||
|
GpuCommandBuffer *cb = cbs[0];
|
||||||
|
|
||||||
|
gpuBeginCommandBuffer((GpuCommandBufferBeginRequest){ .command_buffer = cb, .one_time_submit = true });
|
||||||
|
|
||||||
|
GpuImageMemoryBarrier image_barrier = {
|
||||||
|
.image = output,
|
||||||
|
.src_stage_mask = GPU_PIPELINE_STAGE_NONE,
|
||||||
|
.src_access_mask = GPU_ACCESS_NONE,
|
||||||
|
.dst_stage_mask = GPU_PIPELINE_STAGE_TRANSFER,
|
||||||
|
.dst_access_mask = GPU_ACCESS_TRANSFER_WRITE,
|
||||||
|
.old_layout = GPU_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
.new_layout = GPU_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.subresource = {
|
||||||
|
.aspect = GPU_IMAGE_ASPECT_COLOR,
|
||||||
|
.level_count = 1,
|
||||||
|
.layer_count = 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GpuCmdPipelineBarrierRequest barrier_req = {
|
||||||
|
.command_buffer = cb,
|
||||||
|
.info = (GpuDependencyInfo){
|
||||||
|
.image_memory_barriers = wpArray(GpuImageMemoryBarrier, image_barrier),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
gpuCmdPipelineBarrier(temp, barrier_req);
|
||||||
|
|
||||||
|
GpuCmdCopyBufferToImageRequest copy_req = {
|
||||||
|
.command_buffer = cb,
|
||||||
|
.src_buffer = &temp_storage,
|
||||||
|
.dst_image = output,
|
||||||
|
.dst_image_layout = GPU_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.copy_regions = wpArray(
|
||||||
|
GpuBufferImageCopy,
|
||||||
|
(GpuBufferImageCopy){
|
||||||
|
.image_subresource = { .layer_count = 1, .aspect_mask = GPU_IMAGE_ASPECT_COLOR },
|
||||||
|
.image_extent = { .width = width, .height = height, .depth = 1 },
|
||||||
|
}
|
||||||
|
),
|
||||||
|
};
|
||||||
|
gpuCmdCopyBufferToImage(temp, copy_req);
|
||||||
|
|
||||||
|
image_barrier = (GpuImageMemoryBarrier){
|
||||||
|
.image = output,
|
||||||
|
.src_stage_mask = GPU_PIPELINE_STAGE_TRANSFER,
|
||||||
|
.src_access_mask = GPU_ACCESS_TRANSFER_WRITE,
|
||||||
|
.dst_stage_mask = GPU_PIPELINE_STAGE_FRAGMENT_SHADER,
|
||||||
|
.dst_access_mask = GPU_ACCESS_SHADER_READ,
|
||||||
|
.old_layout = GPU_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.new_layout = GPU_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,
|
||||||
|
.subresource = {
|
||||||
|
.aspect = GPU_IMAGE_ASPECT_COLOR,
|
||||||
|
.level_count = 1,
|
||||||
|
.layer_count = 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
barrier_req = (GpuCmdPipelineBarrierRequest){
|
||||||
|
.command_buffer = cb,
|
||||||
|
.info = (GpuDependencyInfo){
|
||||||
|
.image_memory_barriers = wpArray(GpuImageMemoryBarrier, image_barrier),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
gpuCmdPipelineBarrier(temp, barrier_req);
|
||||||
|
|
||||||
|
gpuEndCommandBuffer(cb);
|
||||||
|
|
||||||
|
GpuFence *fence = gpuCreateFence(allocator, device);
|
||||||
|
|
||||||
|
GpuResetFencesRequest reset_req = {
|
||||||
|
.device = device,
|
||||||
|
.fences = wpArray(GpuFence *, fence)
|
||||||
|
};
|
||||||
|
gpuResetFences(temp, reset_req);
|
||||||
|
|
||||||
|
GpuCommandBuffersSubmitRequest submit_req = {
|
||||||
|
.device = device,
|
||||||
|
.command_buffers = cbs,
|
||||||
|
.fence = fence,
|
||||||
|
};
|
||||||
|
gpuSubmitCommandBuffers(temp, submit_req);
|
||||||
|
|
||||||
|
GpuWaitForFencesRequest wait_req = {
|
||||||
|
.device = device,
|
||||||
|
.fences = wpArray(GpuFence *, fence),
|
||||||
|
.timeout = UINT64_MAX,
|
||||||
|
};
|
||||||
|
gpuWaitForFences(temp, wait_req);
|
||||||
|
|
||||||
|
gpuDestroyFence(fence);
|
||||||
|
gpuDestroyBuffer(&temp_storage);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,6 +1151,13 @@ void gpuDestroyBuffer(GpuBuffer *buffer) {
|
|||||||
buffer->size = 0;
|
buffer->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gpuFlushBuffer(GpuBufferFlushRequest request) {
|
||||||
|
u64 size = request.size > 0 ? request.size : VK_WHOLE_SIZE;
|
||||||
|
VkResult vk_result = vmaFlushAllocation(request.device->allocator, request.buffer.internal->allocation,
|
||||||
|
request.offset, size);
|
||||||
|
assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to flush buffer");
|
||||||
|
}
|
||||||
|
|
||||||
GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device) {
|
GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device) {
|
||||||
GpuFence *fence = wpMemAllocatorAlloc(allocator, sizeof(GpuFence));
|
GpuFence *fence = wpMemAllocatorAlloc(allocator, sizeof(GpuFence));
|
||||||
assertWithLogger(fence != NULL, &logger, "Failed to allocate fence internal");
|
assertWithLogger(fence != NULL, &logger, "Failed to allocate fence internal");
|
||||||
@@ -2168,6 +2307,35 @@ void gpuCmdDispatchBase(GpuCmdDispatchBaseRequest request) {
|
|||||||
request.group_count_z);
|
request.group_count_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gpuCmdCopyBufferToImage(const WpAllocator *temp, GpuCmdCopyBufferToImageRequest request) {
|
||||||
|
u64 region_count = wpArrayCount(request.copy_regions);
|
||||||
|
VkBufferImageCopyArray copy_regions = wpArrayAllocCapacity(VkBufferImageCopy, temp, region_count,
|
||||||
|
WP_ARRAY_INIT_FILLED);
|
||||||
|
assertWithLogger(copy_regions != NULL, &logger, "Failed to allocate temp copy buffer to image arrays");
|
||||||
|
|
||||||
|
for (u64 i = 0; i < region_count; ++i) {
|
||||||
|
copy_regions[i] = (VkBufferImageCopy){
|
||||||
|
.bufferOffset = request.copy_regions[i].buffer_offset,
|
||||||
|
.imageSubresource = (VkImageSubresourceLayers){
|
||||||
|
.aspectMask = vkImageAspectFromGpuImageAspect(request.copy_regions[i].image_subresource.aspect_mask),
|
||||||
|
.baseArrayLayer = request.copy_regions[i].image_subresource.base_array_layer,
|
||||||
|
.layerCount = request.copy_regions[i].image_subresource.layer_count,
|
||||||
|
.mipLevel = request.copy_regions[i].image_subresource.mip_level,
|
||||||
|
},
|
||||||
|
.imageOffset = (VkOffset3D){ .x = request.copy_regions[i].image_offset.x,
|
||||||
|
.y = request.copy_regions[i].image_offset.y,
|
||||||
|
.z = request.copy_regions[i].image_offset.z },
|
||||||
|
.imageExtent = (VkExtent3D){ .width = request.copy_regions[i].image_extent.width,
|
||||||
|
.height = request.copy_regions[i].image_extent.height,
|
||||||
|
.depth = request.copy_regions[i].image_extent.depth },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdCopyBufferToImage(request.command_buffer->vk_buffer, request.src_buffer->internal->vk_buffer,
|
||||||
|
request.dst_image->vk_image, vkImageLayoutFromGpuImageLayout(request.dst_image_layout),
|
||||||
|
wpArrayCount(copy_regions), copy_regions);
|
||||||
|
}
|
||||||
|
|
||||||
wp_intern VkExtensions getInstanceExtensions(void) {
|
wp_intern VkExtensions getInstanceExtensions(void) {
|
||||||
Config config = configGet();
|
Config config = configGet();
|
||||||
VkExtensions output = {0};
|
VkExtensions output = {0};
|
||||||
@@ -3555,3 +3723,8 @@ wp_intern GpuResolveModeFlags gpuResolveModeFlagsFromVkResolveModeFlags(VkResolv
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wp_intern u32 calcMaxMipLevelsForSize(ivec3s size) {
|
||||||
|
f32 max_dim = max(max(size.x, size.y), size.z);
|
||||||
|
return (u32)(floorf(log2f(max_dim)) + 1.0f);
|
||||||
|
}
|
||||||
+201
-91
@@ -20,16 +20,19 @@ enum Errors {
|
|||||||
typedef struct Vertex {
|
typedef struct Vertex {
|
||||||
vec3s position;
|
vec3s position;
|
||||||
vec3s color;
|
vec3s color;
|
||||||
|
vec2s uv;
|
||||||
} Vertex;
|
} Vertex;
|
||||||
typedef Vertex *VertexArray;
|
typedef Vertex *VertexArray;
|
||||||
|
|
||||||
|
typedef vec3s *Vec3sArray;
|
||||||
|
|
||||||
typedef struct ShaderData {
|
typedef struct ShaderData {
|
||||||
mat4s mvp;
|
mat4s mvp;
|
||||||
} ShaderData;
|
} ShaderData;
|
||||||
|
typedef ShaderData *ShaderDataArray;
|
||||||
|
|
||||||
typedef struct Camera {
|
typedef struct Camera {
|
||||||
vec3s position;
|
vec3s position;
|
||||||
vec3s target;
|
|
||||||
vec3s up;
|
vec3s up;
|
||||||
} Camera;
|
} Camera;
|
||||||
|
|
||||||
@@ -43,31 +46,33 @@ typedef struct Projection {
|
|||||||
wp_intern const VertexArray vertices = wpArray(
|
wp_intern const VertexArray vertices = wpArray(
|
||||||
Vertex,
|
Vertex,
|
||||||
(Vertex){
|
(Vertex){
|
||||||
.position = (vec3s){ .x = 0.0f, .y = 0.5f, .z = 0.0f },
|
.position = (vec3s){ .x = -0.5f, .y = -0.5f, .z = 0.0f },
|
||||||
.color = (vec3s){ .r = 1.0f, .g = 0.0f, .b = 0.0f },
|
.color = (vec3s){ .r = 1.0f, .g = 1.0f, .b = 1.0f },
|
||||||
|
.uv = (vec2s){ .x = 0.0f, .y = 0.0f },
|
||||||
},
|
},
|
||||||
(Vertex){
|
(Vertex){
|
||||||
.position = (vec3s){ .x = -0.5f, .y = -0.5f, .z = 0.0f },
|
.position = (vec3s){ .x = -0.5f, .y = 0.5f, .z = 0.0f },
|
||||||
.color = (vec3s){ .r = 0.0f, .g = 1.0f, .b = 0.0f },
|
.color = (vec3s){ .r = 1.0f, .g = 1.0f, .b = 1.0f },
|
||||||
|
.uv = (vec2s){ .x = 0.0f, .y = 1.0f },
|
||||||
},
|
},
|
||||||
(Vertex){
|
(Vertex){
|
||||||
.position = (vec3s){ .x = 0.5f, .y = -0.5f, .z = 0.0f },
|
.position = (vec3s){ .x = 0.5f, .y = -0.5f, .z = 0.0f },
|
||||||
.color = (vec3s){ .r = 0.0f, .g = 0.0f, .b = 1.0f },
|
.color = (vec3s){ .r = 1.0f, .g = 1.0f, .b = 1.0f },
|
||||||
|
.uv = (vec2s){ .x = 1.0f, .y = 0.0f },
|
||||||
},
|
},
|
||||||
(Vertex){
|
(Vertex){
|
||||||
.position = (vec3s){ .x = 0.25f, .y = 0.5f, .z = -1.0f },
|
.position = (vec3s){ .x = 0.5f, .y = 0.5f, .z = 0.0f },
|
||||||
.color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f },
|
.color = (vec3s){ .r = 1.0f, .g = 1.0f, .b = 1.0f },
|
||||||
|
.uv = (vec2s){ .x = 1.0f, .y = 1.0f },
|
||||||
},
|
},
|
||||||
(Vertex){
|
);
|
||||||
.position = (vec3s){ .x = -0.25f, .y = -0.5f, .z = -1.0f },
|
wp_intern const WpU16Array indices = wpArray(
|
||||||
.color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f },
|
u16,
|
||||||
},
|
0, 1, 2,
|
||||||
(Vertex){
|
1, 3, 2,
|
||||||
.position = (vec3s){ .x = 0.75f, .y = -0.5f, .z = -1.0f },
|
|
||||||
.color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f },
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
wp_intern mat4s calculateModelViewProjection(vec3s translation, Camera camera, Projection projection);
|
||||||
wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj);
|
wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj);
|
||||||
|
|
||||||
i32 main(void) {
|
i32 main(void) {
|
||||||
@@ -129,17 +134,21 @@ i32 main(void) {
|
|||||||
wpStr8Format(&msg, "Created swapchain %p with %" PRIu64 " images", swapchain, swapchain_image_count);
|
wpStr8Format(&msg, "Created swapchain %p with %" PRIu64 " images", swapchain, swapchain_image_count);
|
||||||
wpLogInfo(&logger, msg);
|
wpLogInfo(&logger, msg);
|
||||||
|
|
||||||
u64 vertices_size = sizeof(Vertex) * wpArrayCount(vertices);
|
u64 vertices_size = wpArrayItemSize(vertices) * wpArrayCount(vertices);
|
||||||
|
u64 indices_size = wpArrayItemSize(indices) * wpArrayCount(indices);
|
||||||
GpuBufferCreateRequest vert_idx_buf_request = {
|
GpuBufferCreateRequest vert_idx_buf_request = {
|
||||||
.device = device,
|
.device = device,
|
||||||
.usage = GPU_BUFFER_USAGE_VERTEX_BUFFER,
|
.usage = GPU_BUFFER_USAGE_VERTEX_BUFFER | GPU_BUFFER_USAGE_INDEX_BUFFER,
|
||||||
.size = vertices_size,
|
.size = vertices_size + indices_size,
|
||||||
};
|
};
|
||||||
GpuBuffer vertex_buffer = gpuCreateBuffer(&arena, vert_idx_buf_request);
|
GpuBuffer vert_idx_buffer = gpuCreateBuffer(&arena, vert_idx_buf_request);
|
||||||
memcpy(vertex_buffer.cpu_mapping, vertices, vertices_size);
|
void *idx_buf_start = (void *)((uptr)vert_idx_buffer.cpu_mapping + vertices_size);
|
||||||
|
memcpy(vert_idx_buffer.cpu_mapping, vertices, vertices_size);
|
||||||
|
memcpy(idx_buf_start, indices, indices_size);
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = vert_idx_buffer });
|
||||||
|
|
||||||
wpStr8Format(&msg, "Created buffer with size %" PRIu64 " (CPU: %p, GPU: %" PRIu64 ")",
|
wpStr8Format(&msg, "Created buffer with size %" PRIu64 " (CPU: %p, GPU: %" PRIu64 ")",
|
||||||
vertex_buffer.size, vertex_buffer.cpu_mapping, vertex_buffer.gpu_device_address);
|
vert_idx_buffer.size, vert_idx_buffer.cpu_mapping, vert_idx_buffer.gpu_device_address);
|
||||||
wpLogInfo(&logger, msg);
|
wpLogInfo(&logger, msg);
|
||||||
|
|
||||||
GpuCommandPool *pool = gpuCreateCommandPool(&arena, device);
|
GpuCommandPool *pool = gpuCreateCommandPool(&arena, device);
|
||||||
@@ -162,10 +171,21 @@ i32 main(void) {
|
|||||||
|
|
||||||
GpuLoadImageFromFileRequest load_img_req = {
|
GpuLoadImageFromFileRequest load_img_req = {
|
||||||
.command_pool = pool,
|
.command_pool = pool,
|
||||||
.filename = wpStr8LitRo("/home/abdelrahman/Pictures/800px-Trumpets02262006.jpg"),
|
.filename = wpStr8LitRo("assets/collections.png"),
|
||||||
};
|
};
|
||||||
GpuImage *texture = gpuLoadImageFromFile(&arena, &temp_arena, load_img_req);
|
GpuImage *texture = gpuLoadImageFromFile(&arena, &temp_arena, load_img_req);
|
||||||
|
|
||||||
|
GpuSamplerCreateRequest sampler_req = {
|
||||||
|
.device = device,
|
||||||
|
.min_filter = GPU_FILTER_LINEAR,
|
||||||
|
.mag_filter = GPU_FILTER_LINEAR,
|
||||||
|
.address_mode_u = GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
.address_mode_v = GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
.address_mode_w = GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
.mipmap_mode = GPU_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
|
};
|
||||||
|
GpuSampler *sampler = gpuCreateSampler(&arena, sampler_req);
|
||||||
|
|
||||||
GpuShaderCreateRequest shader_request = {
|
GpuShaderCreateRequest shader_request = {
|
||||||
.device = device,
|
.device = device,
|
||||||
.code = (void *)code,
|
.code = (void *)code,
|
||||||
@@ -176,15 +196,19 @@ i32 main(void) {
|
|||||||
|
|
||||||
wpFileClose(spirv);
|
wpFileClose(spirv);
|
||||||
|
|
||||||
|
Vec3sArray translations = wpArray(
|
||||||
|
vec3s,
|
||||||
|
(vec3s){},
|
||||||
|
(vec3s){ .x = 1.0f, .z = -3.0f },
|
||||||
|
);
|
||||||
|
|
||||||
GpuBufferCreateRequest shader_data_req = { .device = device,
|
GpuBufferCreateRequest shader_data_req = { .device = device,
|
||||||
.size = sizeof(ShaderData),
|
.size = sizeof(ShaderData) * wpArrayCount(translations),
|
||||||
.usage = GPU_BUFFER_USAGE_STORAGE_BUFFER |
|
.usage = GPU_BUFFER_USAGE_STORAGE_BUFFER };
|
||||||
GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS };
|
|
||||||
GpuBuffer shader_data = gpuCreateBuffer(&arena, shader_data_req);
|
GpuBuffer shader_data = gpuCreateBuffer(&arena, shader_data_req);
|
||||||
|
|
||||||
Camera camera = {
|
Camera camera = {
|
||||||
.position = { .x = 0.0f, .y = 0.0f, .z = 2.0f },
|
.position = { .x = 0.0f, .y = 0.0f, .z = 2.0f },
|
||||||
.target = { 0 },
|
|
||||||
.up = { 0.0f, 1.0f, 0.0f },
|
.up = { 0.0f, 1.0f, 0.0f },
|
||||||
};
|
};
|
||||||
Projection projection = {
|
Projection projection = {
|
||||||
@@ -193,22 +217,89 @@ i32 main(void) {
|
|||||||
.near = 0.1f,
|
.near = 0.1f,
|
||||||
.far = 100.0f,
|
.far = 100.0f,
|
||||||
};
|
};
|
||||||
ShaderData data = {
|
|
||||||
.mvp = modelViewProjection(
|
ShaderDataArray data = wpArray(
|
||||||
glms_mat4_identity(),
|
ShaderData,
|
||||||
glms_lookat(camera.position, camera.target, camera.up),
|
(ShaderData){
|
||||||
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
.mvp = calculateModelViewProjection(translations[0], camera, projection),
|
||||||
|
},
|
||||||
|
(ShaderData){
|
||||||
|
.mvp = calculateModelViewProjection(translations[1], camera, projection),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
memcpy(shader_data.cpu_mapping, data, wpArrayItemSize(data) * wpArrayCount(data));
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = shader_data });
|
||||||
|
|
||||||
|
GpuDescriptorPoolSizeArray pool_sizes = wpArray(
|
||||||
|
GpuDescriptorPoolSize,
|
||||||
|
(GpuDescriptorPoolSize){ .type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER, .count = 1 },
|
||||||
|
(GpuDescriptorPoolSize){ .type = GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .count = 1 }
|
||||||
|
);
|
||||||
|
GpuDescriptorPoolCreateRequest desc_pool_req = {
|
||||||
|
.descriptor_pool_sizes = pool_sizes,
|
||||||
|
.device = device,
|
||||||
|
.max_sets = 20,
|
||||||
|
};
|
||||||
|
GpuDescriptorPool *desc_pool = gpuCreateDescriptorPool(&arena, desc_pool_req);
|
||||||
|
|
||||||
|
GpuDescriptorSetBindingArray bindings = wpArray(
|
||||||
|
GpuDescriptorSetBinding,
|
||||||
|
(GpuDescriptorSetBinding){
|
||||||
|
.binding = 0,
|
||||||
|
.type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stages = GPU_SHADER_STAGE_VERTEX,
|
||||||
|
},
|
||||||
|
(GpuDescriptorSetBinding){
|
||||||
|
.binding = 1,
|
||||||
|
.type = GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptor_count = 1,
|
||||||
|
.stages = GPU_SHADER_STAGE_FRAGMENT,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
GpuDescriptorSetLayoutCreateRequest desc_set_layout_req = {
|
||||||
|
.device = device,
|
||||||
|
.bindings = bindings,
|
||||||
|
};
|
||||||
|
GpuDescriptorSetLayout *desc_set_layout = gpuCreateDescriptorSetLayout(&arena, &temp_arena, desc_set_layout_req);
|
||||||
|
|
||||||
|
GpuDescriptorSetAllocateRequest desc_sets_req = {
|
||||||
|
.pool = desc_pool,
|
||||||
|
.layouts = wpArray(GpuDescriptorSetLayout *, desc_set_layout),
|
||||||
|
};
|
||||||
|
GpuDescriptorSetPtrArray descriptor_sets = gpuAllocateDescriptorSets(&arena, &temp_arena, desc_sets_req);
|
||||||
|
|
||||||
|
GpuDescriptorSetWriteInfo shader_data_write_info = {
|
||||||
|
.set = descriptor_sets[0],
|
||||||
|
.descriptor_type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.dst_binding = 0,
|
||||||
|
.buffer_infos = wpArray(
|
||||||
|
GpuDescriptorBufferInfo,
|
||||||
|
(GpuDescriptorBufferInfo){ .buffer = &shader_data },
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData));
|
GpuDescriptorSetWriteInfo texture_write_info = {
|
||||||
|
.set = descriptor_sets[0],
|
||||||
GpuPushConstantRange push_constants = {
|
.descriptor_type = GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
.stages = GPU_SHADER_STAGE_VERTEX,
|
.dst_binding = 1,
|
||||||
.size = sizeof(shader_data.gpu_device_address),
|
.image_infos = wpArray(
|
||||||
|
GpuDescriptorImageInfo,
|
||||||
|
(GpuDescriptorImageInfo){
|
||||||
|
.image = texture,
|
||||||
|
.image_layout = GPU_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,
|
||||||
|
.sampler = sampler,
|
||||||
|
}
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
GpuDescriptorSetWriteRequest desc_set_req = {
|
||||||
|
.device = device,
|
||||||
|
.write_infos = wpArray(GpuDescriptorSetWriteInfo, shader_data_write_info, texture_write_info),
|
||||||
|
};
|
||||||
|
gpuWriteDescriptorSets(&temp_arena, desc_set_req);
|
||||||
|
|
||||||
GpuPipelineLayoutCreateRequest graphics_pipeline_layout_request = {
|
GpuPipelineLayoutCreateRequest graphics_pipeline_layout_request = {
|
||||||
.device = device,
|
.device = device,
|
||||||
.push_constants = wpArray(GpuPushConstantRange, push_constants),
|
.descriptor_set_layouts = wpArray(GpuDescriptorSetLayout *, desc_set_layout),
|
||||||
};
|
};
|
||||||
GpuPipelineLayout *layout = gpuCreatePipelineLayout(&arena, &temp_arena, graphics_pipeline_layout_request);
|
GpuPipelineLayout *layout = gpuCreatePipelineLayout(&arena, &temp_arena, graphics_pipeline_layout_request);
|
||||||
|
|
||||||
@@ -231,6 +322,12 @@ i32 main(void) {
|
|||||||
.offset = offsetof(Vertex, color),
|
.offset = offsetof(Vertex, color),
|
||||||
.format = GPU_FORMAT_R32G32B32_SFLOAT,
|
.format = GPU_FORMAT_R32G32B32_SFLOAT,
|
||||||
},
|
},
|
||||||
|
(GpuVertexInputAttribute){
|
||||||
|
.location = 2,
|
||||||
|
.binding = 0,
|
||||||
|
.offset = offsetof(Vertex, uv),
|
||||||
|
.format = GPU_FORMAT_R32G32_SFLOAT,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
GpuPipelineVertexInputStateInfo vert_info = {
|
GpuPipelineVertexInputStateInfo vert_info = {
|
||||||
.bindings = wpArray(GpuVertexInputBinding, vert_binding),
|
.bindings = wpArray(GpuVertexInputBinding, vert_binding),
|
||||||
@@ -304,6 +401,35 @@ i32 main(void) {
|
|||||||
.timeout = UINT64_MAX });
|
.timeout = UINT64_MAX });
|
||||||
gpuResetFences(&temp_arena, (GpuResetFencesRequest){ .device = device, .fences = fences });
|
gpuResetFences(&temp_arena, (GpuResetFencesRequest){ .device = device, .fences = fences });
|
||||||
|
|
||||||
|
if (windowIsKeyPressed(KEYBOARD_KEY_UP)) {
|
||||||
|
camera.position.z -= 0.01f;
|
||||||
|
data[0].mvp = calculateModelViewProjection(translations[0], camera, projection);
|
||||||
|
data[1].mvp = calculateModelViewProjection(translations[1], camera, projection);
|
||||||
|
memcpy(shader_data.cpu_mapping, data, wpArrayItemSize(data) * wpArrayCount(data));
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = shader_data });
|
||||||
|
}
|
||||||
|
if (windowIsKeyPressed(KEYBOARD_KEY_DOWN)) {
|
||||||
|
camera.position.z += 0.01f;
|
||||||
|
data[0].mvp = calculateModelViewProjection(translations[0], camera, projection);
|
||||||
|
data[1].mvp = calculateModelViewProjection(translations[1], camera, projection);
|
||||||
|
memcpy(shader_data.cpu_mapping, data, wpArrayItemSize(data) * wpArrayCount(data));
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = shader_data });
|
||||||
|
}
|
||||||
|
if (windowIsKeyPressed(KEYBOARD_KEY_RIGHT)) {
|
||||||
|
camera.position.x += 0.01f;
|
||||||
|
data[0].mvp = calculateModelViewProjection(translations[0], camera, projection);
|
||||||
|
data[1].mvp = calculateModelViewProjection(translations[1], camera, projection);
|
||||||
|
memcpy(shader_data.cpu_mapping, data, wpArrayItemSize(data) * wpArrayCount(data));
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = shader_data });
|
||||||
|
}
|
||||||
|
if (windowIsKeyPressed(KEYBOARD_KEY_LEFT)) {
|
||||||
|
camera.position.x -= 0.01f;
|
||||||
|
data[0].mvp = calculateModelViewProjection(translations[0], camera, projection);
|
||||||
|
data[1].mvp = calculateModelViewProjection(translations[1], camera, projection);
|
||||||
|
memcpy(shader_data.cpu_mapping, data, wpArrayItemSize(data) * wpArrayCount(data));
|
||||||
|
gpuFlushBuffer((GpuBufferFlushRequest){ .device = device, .buffer = shader_data });
|
||||||
|
}
|
||||||
|
|
||||||
GpuSwapchainAcquireImageResult acquire_result = gpuAcquireNextSwapchainImage(
|
GpuSwapchainAcquireImageResult acquire_result = gpuAcquireNextSwapchainImage(
|
||||||
(GpuSwapchainAcquireImageRequest){
|
(GpuSwapchainAcquireImageRequest){
|
||||||
.swapchain = swapchain,
|
.swapchain = swapchain,
|
||||||
@@ -387,15 +513,6 @@ i32 main(void) {
|
|||||||
};
|
};
|
||||||
gpuCmdBeginRendering(&temp_arena, render_request);
|
gpuCmdBeginRendering(&temp_arena, render_request);
|
||||||
|
|
||||||
GpuCmdPushConstantsRequest push_const_req = {
|
|
||||||
.command_buffer = buffers[0],
|
|
||||||
.layout = layout,
|
|
||||||
.stage_flags = GPU_SHADER_STAGE_VERTEX,
|
|
||||||
.values = &shader_data.gpu_device_address,
|
|
||||||
.total_size_in_bytes = sizeof(shader_data.gpu_device_address),
|
|
||||||
};
|
|
||||||
gpuCmdPushConstants(push_const_req);
|
|
||||||
|
|
||||||
GpuViewportArray viewports = wpArray(
|
GpuViewportArray viewports = wpArray(
|
||||||
GpuViewport,
|
GpuViewport,
|
||||||
(GpuViewport){ .x = 0, .y = 0,
|
(GpuViewport){ .x = 0, .y = 0,
|
||||||
@@ -416,18 +533,34 @@ i32 main(void) {
|
|||||||
|
|
||||||
GpuCmdBindVertexBuffersRequest vert_bind_req = {
|
GpuCmdBindVertexBuffersRequest vert_bind_req = {
|
||||||
.command_buffer = buffers[0],
|
.command_buffer = buffers[0],
|
||||||
.vertex_buffers = wpArray(GpuBuffer, vertex_buffer),
|
.vertex_buffers = wpArray(GpuBuffer, vert_idx_buffer),
|
||||||
.offsets = wpArray(u64, 0),
|
.offsets = wpArray(u64, 0),
|
||||||
};
|
};
|
||||||
gpuCmdBindVertexBuffers(&temp_arena, vert_bind_req);
|
gpuCmdBindVertexBuffers(&temp_arena, vert_bind_req);
|
||||||
|
|
||||||
|
GpuCmdBindIndexBufferRequest idx_bind_req = {
|
||||||
|
.index_buffer = vert_idx_buffer,
|
||||||
|
.command_buffer = buffers[0],
|
||||||
|
.offset = vertices_size,
|
||||||
|
.index_type = GPU_INDEX_TYPE_UINT16,
|
||||||
|
};
|
||||||
|
gpuCmdBindIndexBuffer(idx_bind_req);
|
||||||
|
|
||||||
|
GpuCmdBindDescriptorSetsRequest bind_desc_sets_req = {
|
||||||
|
.command_buffer = buffers[0],
|
||||||
|
.layout = layout,
|
||||||
|
.sets = descriptor_sets,
|
||||||
|
.bind_point = GPU_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
};
|
||||||
|
gpuCmdBindDescriptorSets(&temp_arena, bind_desc_sets_req);
|
||||||
|
|
||||||
gpuCmdBindPipeline((GpuCmdBindPipelineRequest){ .command_buffer = buffers[0],
|
gpuCmdBindPipeline((GpuCmdBindPipelineRequest){ .command_buffer = buffers[0],
|
||||||
.bind_point = GPU_PIPELINE_BIND_POINT_GRAPHICS,
|
.bind_point = GPU_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
.pipeline = pipelines[0] });
|
.pipeline = pipelines[0] });
|
||||||
|
|
||||||
gpuCmdDraw((GpuCmdDrawRequest){ .command_buffer = buffers[0],
|
gpuCmdDrawIndexed((GpuCmdDrawIndexedRequest){ .command_buffer = buffers[0],
|
||||||
.vertex_count = wpArrayCount(vertices),
|
.instance_count = wpArrayCount(translations),
|
||||||
.instance_count = 1 });
|
.index_count = wpArrayCount(indices) });
|
||||||
|
|
||||||
gpuCmdEndRendering(buffers[0]);
|
gpuCmdEndRendering(buffers[0]);
|
||||||
|
|
||||||
@@ -470,45 +603,6 @@ i32 main(void) {
|
|||||||
.swapchain_infos = wpArray(GpuSwpachainPresentInfo, present_info),
|
.swapchain_infos = wpArray(GpuSwpachainPresentInfo, present_info),
|
||||||
};
|
};
|
||||||
gpuPresentSwapchains(&temp_arena, present_request);
|
gpuPresentSwapchains(&temp_arena, present_request);
|
||||||
|
|
||||||
if (windowIsKeyPressed(KEYBOARD_KEY_UP)) {
|
|
||||||
camera.position.z -= 0.01f;
|
|
||||||
data.mvp = modelViewProjection(
|
|
||||||
glms_mat4_identity(),
|
|
||||||
glms_lookat(camera.position, camera.target, camera.up),
|
|
||||||
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
|
||||||
);
|
|
||||||
memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData));
|
|
||||||
}
|
|
||||||
if (windowIsKeyPressed(KEYBOARD_KEY_DOWN)) {
|
|
||||||
camera.position.z += 0.01f;
|
|
||||||
data.mvp = modelViewProjection(
|
|
||||||
glms_mat4_identity(),
|
|
||||||
glms_lookat(camera.position, camera.target, camera.up),
|
|
||||||
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
|
||||||
);
|
|
||||||
memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData));
|
|
||||||
}
|
|
||||||
if (windowIsKeyPressed(KEYBOARD_KEY_RIGHT)) {
|
|
||||||
camera.position.x += 0.01f;
|
|
||||||
camera.target.x += 0.01f;
|
|
||||||
data.mvp = modelViewProjection(
|
|
||||||
glms_mat4_identity(),
|
|
||||||
glms_lookat(camera.position, camera.target, camera.up),
|
|
||||||
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
|
||||||
);
|
|
||||||
memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData));
|
|
||||||
}
|
|
||||||
if (windowIsKeyPressed(KEYBOARD_KEY_LEFT)) {
|
|
||||||
camera.position.x -= 0.01f;
|
|
||||||
camera.target.x -= 0.01f;
|
|
||||||
data.mvp = modelViewProjection(
|
|
||||||
glms_mat4_identity(),
|
|
||||||
glms_lookat(camera.position, camera.target, camera.up),
|
|
||||||
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
|
||||||
);
|
|
||||||
memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpuDeviceWaitIdle(device);
|
gpuDeviceWaitIdle(device);
|
||||||
@@ -521,11 +615,14 @@ i32 main(void) {
|
|||||||
gpuDestroyPipeline(pipelines[i]);
|
gpuDestroyPipeline(pipelines[i]);
|
||||||
}
|
}
|
||||||
gpuDestroyPipelineLayout(layout);
|
gpuDestroyPipelineLayout(layout);
|
||||||
|
gpuDestroyDescriptorSetLayout(desc_set_layout);
|
||||||
|
gpuDestroyDescriptorPool(desc_pool);
|
||||||
gpuDestroyBuffer(&shader_data);
|
gpuDestroyBuffer(&shader_data);
|
||||||
gpuDestroyShader(shader);
|
gpuDestroyShader(shader);
|
||||||
|
gpuDestroySampler(sampler);
|
||||||
gpuDestroyImage(texture);
|
gpuDestroyImage(texture);
|
||||||
gpuDestroyCommandPool(pool);
|
gpuDestroyCommandPool(pool);
|
||||||
gpuDestroyBuffer(&vertex_buffer);
|
gpuDestroyBuffer(&vert_idx_buffer);
|
||||||
gpuDestroySwapchain(swapchain);
|
gpuDestroySwapchain(swapchain);
|
||||||
gpuDestroySurface(surface);
|
gpuDestroySurface(surface);
|
||||||
gpuDestroyDevice(device);
|
gpuDestroyDevice(device);
|
||||||
@@ -542,6 +639,19 @@ i32 main(void) {
|
|||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wp_intern mat4s calculateModelViewProjection(vec3s translation, Camera camera, Projection projection) {
|
||||||
|
vec3s target = {
|
||||||
|
.x = camera.position.x,
|
||||||
|
.y = camera.position.y,
|
||||||
|
.z = camera.position.z - 2.0f
|
||||||
|
};
|
||||||
|
return modelViewProjection(
|
||||||
|
glms_translate(glms_mat4_identity(), translation),
|
||||||
|
glms_lookat(camera.position, target, camera.up),
|
||||||
|
glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj) {
|
wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj) {
|
||||||
// Matrix to flip the Y-axis since in Vulkan Y points down
|
// Matrix to flip the Y-axis since in Vulkan Y points down
|
||||||
mat4s clip = {
|
mat4s clip = {
|
||||||
|
|||||||
@@ -1,26 +1,33 @@
|
|||||||
struct VSInput {
|
struct VSInput {
|
||||||
float3 Pos;
|
float3 Pos;
|
||||||
float3 Color;
|
float3 Color;
|
||||||
|
float2 Uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderData {
|
struct ShaderData {
|
||||||
float4x4 mvp;
|
float4x4 mvp;
|
||||||
};
|
};
|
||||||
|
StructuredBuffer<ShaderData> data;
|
||||||
|
|
||||||
|
Sampler2D texture;
|
||||||
|
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
float3 Color;
|
|
||||||
float4 sv_position : SV_Position;
|
float4 sv_position : SV_Position;
|
||||||
|
float3 Color;
|
||||||
|
float2 Uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
[shader("vertex")]
|
[shader("vertex")]
|
||||||
VertexOutput vertMain(VSInput input, uniform ShaderData *data, uint vid : SV_VertexID) {
|
VertexOutput vertMain(VSInput input, uint idx: SV_InstanceID) {
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
|
output.sv_position = mul(data[idx].mvp, float4(input.Pos, 1.0));
|
||||||
output.Color = input.Color;
|
output.Color = input.Color;
|
||||||
output.sv_position = mul(data->mvp, float4(input.Pos, 1.0));
|
output.Uv = input.Uv;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
[shader("fragment")]
|
[shader("fragment")]
|
||||||
float4 fragMain(VertexOutput inVert) : SV_Target {
|
float4 fragMain(VertexOutput inVert) : SV_Target {
|
||||||
return float4(inVert.Color, 1.0);
|
float4 color = texture.Sample(inVert.Uv) * float4(inVert.Color, 1.0f);
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
Submodule vendor/wapp updated: 741566fafd...5687cb512c.
Reference in new issue
Block a user