mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Add Vulkan backend
This commit is contained in:
parent
e572704963
commit
fbeba9eb5f
8
.github/workflows/build.yaml
vendored
8
.github/workflows/build.yaml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest, ubuntu-18.04]
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest, ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cmake-args: -G Ninja
|
||||
|
@ -23,7 +23,7 @@ jobs:
|
|||
env:
|
||||
CFLAGS: -Wdeclaration-after-statement -Werror
|
||||
CXXFLAGS: -Werror
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
cmake-path: /usr/bin/
|
||||
cmake-args: -G Ninja
|
||||
package-file: "*-linux_x86_64.tar.xz"
|
||||
|
@ -57,7 +57,7 @@ jobs:
|
|||
if: contains(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libvulkan-dev glslang-tools spirv-tools libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev -y
|
||||
|
||||
- name: Prepare Linux (fancy)
|
||||
if: contains(matrix.os, 'ubuntu') && matrix.fancy
|
||||
|
@ -78,7 +78,7 @@ jobs:
|
|||
if: contains(matrix.os, 'macOS')
|
||||
run: |
|
||||
brew update || true
|
||||
brew install pkg-config sdl2 ffmpeg python3 ninja
|
||||
brew install pkg-config sdl2 ffmpeg python3 ninja molten-vk vulkan-headers glslang spirv-tools
|
||||
brew upgrade freetype
|
||||
pip3 install dmgbuild
|
||||
sudo rm -rf /Library/Developer/CommandLineTools
|
||||
|
|
2
.github/workflows/clang-tidy.yml
vendored
2
.github/workflows/clang-tidy.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
- name: Install clang-tidy
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev clang-tidy -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev clang-tidy libvulkan-dev glslang-tools spirv-tools -y
|
||||
- name: Build with clang-tidy
|
||||
run: |
|
||||
mkdir clang-tidy
|
||||
|
|
2
.github/workflows/codeql-analysis.yaml
vendored
2
.github/workflows/codeql-analysis.yaml
vendored
|
@ -38,7 +38,7 @@ jobs:
|
|||
if: matrix.language == 'cpp'
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev libmariadbclient-dev libwebsockets-dev -y
|
||||
sudo apt-get install pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev libmariadbclient-dev libwebsockets-dev libvulkan-dev glslang-tools spirv-tools -y
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
2
.github/workflows/style.yml
vendored
2
.github/workflows/style.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
- name: Prepare
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install clang-format imagemagick ddnet-tools shellcheck pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev pylint3 python3-clang -y
|
||||
sudo apt-get install clang-format imagemagick ddnet-tools shellcheck pkg-config cmake ninja-build libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev libavcodec-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev libx264-dev pylint3 python3-clang libvulkan-dev glslang-tools spirv-tools -y
|
||||
mkdir release
|
||||
cd release
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDOWNLOAD_GTEST=OFF -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=. ..
|
||||
|
|
|
@ -93,9 +93,14 @@ else()
|
|||
endif()
|
||||
|
||||
set(AUTO_DEPENDENCIES_DEFAULT OFF)
|
||||
set(AUTO_VULKAN_BACKEND ON)
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
set(AUTO_DEPENDENCIES_DEFAULT ON)
|
||||
elseif(TARGET_OS STREQUAL "linux")
|
||||
if(TARGET_CPU_ARCHITECTURE STREQUAL "x86")
|
||||
set(AUTO_VULKAN_BACKEND OFF)
|
||||
endif()
|
||||
elseif(TARGET_OS STREQUAL "mac")
|
||||
set(AUTO_VULKAN_BACKEND OFF)
|
||||
endif()
|
||||
|
||||
option(WEBSOCKETS "Enable websockets support" OFF)
|
||||
|
@ -116,6 +121,7 @@ option(DISCORD "Enable Discord rich presence support" OFF)
|
|||
option(DISCORD_DYNAMIC "Enable discovering Discord rich presence libraries at runtime (Linux only)" OFF)
|
||||
option(PREFER_BUNDLED_LIBS "Prefer bundled libraries over system libraries" ${AUTO_DEPENDENCIES_DEFAULT})
|
||||
option(DEV "Don't generate stuff necessary for packaging" OFF)
|
||||
option(VULKAN "Enable the vulkan backend" ${AUTO_VULKAN_BACKEND})
|
||||
|
||||
option(EXCEPTION_HANDLING "Enable exception handling (only works with Windows as of now)" OFF)
|
||||
|
||||
|
@ -467,6 +473,15 @@ if(TARGET_OS AND TARGET_OS STREQUAL "mac")
|
|||
find_program(DMGBUILD dmgbuild)
|
||||
endif()
|
||||
|
||||
set(VULKAN_SHADER_FILE_LIST "" CACHE STRING "Vulkan shader file list")
|
||||
if(VULKAN)
|
||||
find_package(Vulkan)
|
||||
include(cmake/BuildVulkanShaders.cmake)
|
||||
else()
|
||||
set(VULKAN_LIBRARIES)
|
||||
set(VULKAN_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
message(STATUS "******** ${CMAKE_PROJECT_NAME} ********")
|
||||
set(TARGET "Target OS: ${TARGET_OS} ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
if(TARGET_OS STREQUAL "mac")
|
||||
|
@ -528,6 +543,10 @@ if(WEBSOCKETS)
|
|||
show_dependency_status("Websockets" WEBSOCKETS)
|
||||
endif()
|
||||
|
||||
if(VULKAN)
|
||||
show_dependency_status("Vulkan" VULKAN)
|
||||
endif()
|
||||
|
||||
if(CLIENT AND NOT(CURL_FOUND))
|
||||
message(SEND_ERROR "You must install Curl to compile DDNet")
|
||||
endif()
|
||||
|
@ -591,6 +610,10 @@ if(NOT(GTEST_FOUND))
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(VULKAN AND CLIENT AND NOT(VULKAN_FOUND))
|
||||
message(SEND_ERROR "You must install Vulkan libraries to compile the DDNet client")
|
||||
endif()
|
||||
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
set(PLATFORM_CLIENT)
|
||||
set(PLATFORM_CLIENT_LIBS opengl32 winmm)
|
||||
|
@ -1277,6 +1300,20 @@ set(EXPECTED_DATA
|
|||
shader/text.vert
|
||||
shader/tile.frag
|
||||
shader/tile.vert
|
||||
shader/vulkan/prim.frag
|
||||
shader/vulkan/prim.vert
|
||||
shader/vulkan/prim3d.frag
|
||||
shader/vulkan/prim3d.vert
|
||||
shader/vulkan/primex.frag
|
||||
shader/vulkan/primex.vert
|
||||
shader/vulkan/quad.frag
|
||||
shader/vulkan/quad.vert
|
||||
shader/vulkan/spritemulti.frag
|
||||
shader/vulkan/spritemulti.vert
|
||||
shader/vulkan/text.frag
|
||||
shader/vulkan/text.vert
|
||||
shader/vulkan/tile.frag
|
||||
shader/vulkan/tile.vert
|
||||
skins/Aoe4leg.png
|
||||
skins/PaladiN.png
|
||||
skins/antiantey.png
|
||||
|
@ -1422,6 +1459,7 @@ set(COPY_FILES
|
|||
${FFMPEG_COPY_FILES}
|
||||
${WEBSOCKETS_COPY_FILES}
|
||||
${DISCORDSDK_COPY_FILES}
|
||||
${VULKAN_COPY_FILES}
|
||||
${EXCEPTION_HANDLING_COPY_FILES}
|
||||
)
|
||||
file(COPY ${COPY_FILES} DESTINATION .)
|
||||
|
@ -1775,6 +1813,8 @@ if(CLIENT)
|
|||
backend/opengles/gles_class_defines.h
|
||||
backend/opengles/opengles_sl.cpp
|
||||
backend/opengles/opengles_sl_program.cpp
|
||||
backend/vulkan/backend_vulkan.cpp
|
||||
backend/vulkan/backend_vulkan.h
|
||||
backend_sdl.cpp
|
||||
backend_sdl.h
|
||||
blocklist_driver.cpp
|
||||
|
@ -1962,6 +2002,8 @@ if(CLIENT)
|
|||
${OPUS_LIBRARIES}
|
||||
${OGG_LIBRARIES}
|
||||
|
||||
${VULKAN_LIBRARIES}
|
||||
|
||||
${TARGET_STEAMAPI}
|
||||
|
||||
${PLATFORM_CLIENT_LIBS}
|
||||
|
@ -2033,6 +2075,8 @@ if(CLIENT)
|
|||
${FFMPEG_INCLUDE_DIRS}
|
||||
${DISCORDSDK_INCLUDE_DIRS}
|
||||
|
||||
${VULKAN_INCLUDE_DIRS}
|
||||
|
||||
${PLATFORM_CLIENT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
@ -2065,6 +2109,10 @@ if(CLIENT)
|
|||
target_compile_definitions(${TARGET_CLIENT} PRIVATE CONF_GLEW_HAS_CONTEXT_INIT)
|
||||
endif()
|
||||
|
||||
if(VULKAN)
|
||||
target_compile_definitions(${TARGET_CLIENT} PRIVATE CONF_BACKEND_VULKAN)
|
||||
endif()
|
||||
|
||||
list(APPEND TARGETS_OWN ${TARGET_CLIENT})
|
||||
list(APPEND TARGETS_LINK ${TARGET_CLIENT})
|
||||
endif()
|
||||
|
@ -2578,6 +2626,11 @@ set(CPACK_FILES
|
|||
storage.cfg
|
||||
${COPY_FILES}
|
||||
)
|
||||
|
||||
set(CPACK_GEN_FILES
|
||||
${VULKAN_SHADER_FILE_LIST}
|
||||
)
|
||||
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
list(APPEND CPACK_FILES other/config_directory.bat)
|
||||
endif()
|
||||
|
@ -2600,6 +2653,9 @@ if(NOT DEV)
|
|||
install(FILES other/icons/DDNet_${SIZE}x${SIZE}x32.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME ddnet.png COMPONENT client)
|
||||
install(FILES other/icons/DDNet-Server_${SIZE}x${SIZE}x32.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME ddnet-server.png COMPONENT server)
|
||||
endforeach()
|
||||
foreach(file ${VULKAN_SHADER_FILE_LIST})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/${file} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/ddnet/data/shader/vulkan COMPONENT client)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(DEV)
|
||||
|
@ -2610,7 +2666,8 @@ else()
|
|||
set(EXTRA_ARGS DESTINATION ${CPACK_PACKAGE_FILE_NAME} COMPONENT portable EXCLUDE_FROM_ALL)
|
||||
install(TARGETS ${CPACK_TARGETS} ${EXTRA_ARGS})
|
||||
install(DIRECTORY ${CPACK_DIRS} ${EXTRA_ARGS})
|
||||
install(FILES ${CPACK_FILES} ${EXTRA_ARGS})
|
||||
set(CPACK_FILES_TMP ${CPACK_FILES} ${CPACK_GEN_FILES})
|
||||
install(FILES ${CPACK_FILES_TMP} ${EXTRA_ARGS})
|
||||
endif()
|
||||
|
||||
set(PACKAGE_TARGETS)
|
||||
|
@ -2714,6 +2771,9 @@ foreach(ext zip tar.gz tar.xz)
|
|||
foreach(file ${CPACK_FILES})
|
||||
list(APPEND COPY_FILE_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/${file} ${TMPDIR}/)
|
||||
endforeach()
|
||||
foreach(file ${CPACK_GEN_FILES})
|
||||
list(APPEND COPY_FILE_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/${file} ${TMPDIR}/${file})
|
||||
endforeach()
|
||||
foreach(dir ${CPACK_DIRS})
|
||||
list(APPEND COPY_DIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/${dir} ${TMPDIR}/${dir})
|
||||
endforeach()
|
||||
|
@ -2761,6 +2821,7 @@ unset(CPACK_SOURCE_FILES_INVERTED)
|
|||
unset(CPACK_TARGETS)
|
||||
unset(CPACK_DIRS)
|
||||
unset(CPACK_FILES)
|
||||
unset(CPACK_GEN_FILES)
|
||||
|
||||
include(CPack)
|
||||
|
||||
|
|
12
README.md
12
README.md
|
@ -34,21 +34,21 @@ Dependencies on Linux / macOS
|
|||
|
||||
You can install the required libraries on your system, `touch CMakeLists.txt` and CMake will use the system-wide libraries by default. You can install all required dependencies and CMake on Debian or Ubuntu like this:
|
||||
|
||||
sudo apt install build-essential cmake git google-mock libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python libx264-dev libavfilter-dev libavdevice-dev libavformat-dev libavcodec-extra libavutil-dev
|
||||
sudo apt install build-essential cmake git google-mock libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python libx264-dev libavfilter-dev libavdevice-dev libavformat-dev libavcodec-extra libavutil-dev libvulkan-dev glslang-tools spirv-tools
|
||||
|
||||
Or on CentOS, RedHat and AlmaLinux like this:
|
||||
|
||||
sudo yum install gcc gcc-c++ make cmake git python2 gtest-devel gmock-devel libcurl-devel openssl-devel freetype-devel glew-devel libnotify-devel libogg-devel opus-devel opusfile-devel pnglite-devel SDL2-devel sqlite-devel wavpack-devel libx264-devel ffmpeg-devel
|
||||
sudo yum install gcc gcc-c++ make cmake git python2 gtest-devel gmock-devel libcurl-devel openssl-devel freetype-devel glew-devel libnotify-devel libogg-devel opus-devel opusfile-devel pnglite-devel SDL2-devel sqlite-devel wavpack-devel libx264-devel ffmpeg-devel vulkan-devel glslang spirv-tools
|
||||
|
||||
Or on Arch Linux like this:
|
||||
|
||||
sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack x264 ffmpeg
|
||||
sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack x264 ffmpeg vulkan-icd-loader vulkan-headers glslang spirv-tools
|
||||
|
||||
There is an [AUR package for pnglite](https://aur.archlinux.org/packages/pnglite/). For instructions on installing it, see [AUR packages installation instructions on ArchWiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
|
||||
|
||||
On macOS you can use [homebrew](https://brew.sh/) to install build dependencies like this:
|
||||
|
||||
brew install cmake freetype glew googletest opusfile SDL2 wavpack x264 ffmpeg
|
||||
brew install cmake freetype glew googletest opusfile SDL2 wavpack x264 ffmpeg molten-vk vulkan-headers glslang spirv-tools
|
||||
|
||||
If you don't want to use the system libraries, you can pass the `-DPREFER_BUNDLED_LIBS=ON` parameter to cmake.
|
||||
|
||||
|
@ -109,6 +109,10 @@ Whether to optimize for development, speeding up the compilation process a littl
|
|||
Whether to enable UPnP support for the server.
|
||||
You need to install `libminiupnpc-dev` on Debian, `miniupnpc` on Arch Linux.
|
||||
|
||||
* **-DVULKAN=[ON|OFF]** <br>
|
||||
Whether to enable the vulkan backend.
|
||||
On Windows you need to install the Vulkan SDK and set the `VULKAN_SDK` environment flag accordingly.
|
||||
|
||||
* **-GNinja** <br>
|
||||
Use the Ninja build system instead of Make. This automatically parallizes the build and is generally faster. Compile with `ninja` instead of `make`. Install Ninja with `sudo apt install ninja-build` on Debian, `sudo pacman -S --needed ninja` on Arch Linux.
|
||||
|
||||
|
|
175
cmake/BuildVulkanShaders.cmake
Normal file
175
cmake/BuildVulkanShaders.cmake
Normal file
|
@ -0,0 +1,175 @@
|
|||
find_program(GLSLANG_VALIDATOR_PROGRAM glslangValidator)
|
||||
find_program(SPIRV_OPTIMIZER_PROGRAM spirv-opt)
|
||||
|
||||
set(GLSLANG_VALIDATOR_PROGRAM_FOUND TRUE)
|
||||
if(NOT GLSLANG_VALIDATOR_PROGRAM)
|
||||
set(GLSLANG_VALIDATOR_PROGRAM_FOUND FALSE)
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
if(${TARGET_CPU_ARCHITECTURE} STREQUAL "x86_64")
|
||||
set(GLSLANG_VALIDATOR_PROGRAM "$ENV{VULKAN_SDK}/Bin/glslangValidator.exe")
|
||||
else()
|
||||
set(GLSLANG_VALIDATOR_PROGRAM "$ENV{VULKAN_SDK}/Bin32/glslangValidator.exe")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXISTS ${GLSLANG_VALIDATOR_PROGRAM})
|
||||
set(GLSLANG_VALIDATOR_PROGRAM_FOUND TRUE)
|
||||
elseif(${TARGET_CPU_ARCHITECTURE} STREQUAL "x86_64")
|
||||
set(GLSLANG_VALIDATOR_PROGRAM "${PROJECT_SOURCE_DIR}/ddnet-libs/vulkan/windows/lib64/glslangValidator.exe")
|
||||
if(EXISTS ${GLSLANG_VALIDATOR_PROGRAM})
|
||||
set(GLSLANG_VALIDATOR_PROGRAM_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${GLSLANG_VALIDATOR_PROGRAM_FOUND} EQUAL FALSE)
|
||||
message(FATAL_ERROR "glslangValidator binary was not found. Did you install the Vulkan SDK / packages ?")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SPIRV_OPTIMIZER_PROGRAM_FOUND TRUE)
|
||||
if(NOT SPIRV_OPTIMIZER_PROGRAM)
|
||||
set(SPIRV_OPTIMIZER_PROGRAM_FOUND FALSE)
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
if (${TARGET_CPU_ARCHITECTURE} STREQUAL "x86_64")
|
||||
set(SPIRV_OPTIMIZER_PROGRAM "$ENV{VULKAN_SDK}/Bin/spirv-opt.exe")
|
||||
else()
|
||||
set(SPIRV_OPTIMIZER_PROGRAM "$ENV{VULKAN_SDK}/Bin32/spirv-opt.exe")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXISTS ${SPIRV_OPTIMIZER_PROGRAM})
|
||||
set(SPIRV_OPTIMIZER_PROGRAM_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE GLSL_SHADER_FILES
|
||||
"data/shaders/vulkan/*.frag"
|
||||
"data/shaders/vulkan/*.vert"
|
||||
)
|
||||
|
||||
set(TMP_SHADER_SHA256_LIST "")
|
||||
foreach(GLSL_SHADER_FILE ${GLSL_SHADER_FILES})
|
||||
file(SHA256 ${FILE_NAME} TMP_FILE_SHA)
|
||||
set(TMP_SHADER_SHA256_LIST "${TMP_SHADER_SHA256_LIST}${TMP_FILE_SHA}")
|
||||
endforeach(GLSL_SHADER_FILE)
|
||||
|
||||
string(SHA256 GLSL_SHADER_SHA256 "${TMP_SHADER_SHA256_LIST}")
|
||||
set(GLSL_SHADER_SHA256 "${GLSL_SHADER_SHA256}@v1")
|
||||
|
||||
set(FOUND_MATCHING_SHA256_FILE FALSE)
|
||||
|
||||
if(EXISTS "${PROJECT_BINARY_DIR}/vulkan_shaders_sha256.txt")
|
||||
file(STRINGS "${PROJECT_BINARY_DIR}/vulkan_shaders_sha256.txt" VULKAN_SHADERS_SHA256_FILE_CONTENT)
|
||||
if("${VULKAN_SHADERS_SHA256_FILE_CONTENT}" STREQUAL "${GLSL_SHADER_SHA256}")
|
||||
set(FOUND_MATCHING_SHA256_FILE TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(TW_VULKAN_VERSION "vulkan100")
|
||||
|
||||
set(GLSLANG_VALIDATOR_COMMAND_LIST)
|
||||
set(GLSLANG_VALIDATOR_DELETE_LIST)
|
||||
set(SPIRV_OPTIMIZER_COMMAND_LIST)
|
||||
function(generate_shader_file FILE_ARGS1 FILE_ARGS2 FILE_NAME FILE_OUTPUT_NAME)
|
||||
set(FILE_TMP_NAME_POSTFIX "")
|
||||
if(SPIRV_OPTIMIZER_PROGRAM_FOUND)
|
||||
set(FILE_TMP_NAME_POSTFIX ".tmp")
|
||||
endif()
|
||||
list(APPEND GLSLANG_VALIDATOR_COMMAND_LIST COMMAND ${GLSLANG_VALIDATOR_PROGRAM} --client ${TW_VULKAN_VERSION} ${FILE_ARGS1} ${FILE_ARGS2} ${FILE_NAME} -o "${PROJECT_BINARY_DIR}/${FILE_OUTPUT_NAME}${FILE_TMP_NAME_POSTFIX}")
|
||||
if(SPIRV_OPTIMIZER_PROGRAM_FOUND)
|
||||
list(APPEND SPIRV_OPTIMIZER_COMMAND_LIST COMMAND ${SPIRV_OPTIMIZER_PROGRAM} -O "${PROJECT_BINARY_DIR}/${FILE_OUTPUT_NAME}${FILE_TMP_NAME_POSTFIX}" -o "${PROJECT_BINARY_DIR}/${FILE_OUTPUT_NAME}")
|
||||
list(APPEND GLSLANG_VALIDATOR_DELETE_LIST "${PROJECT_BINARY_DIR}/${FILE_OUTPUT_NAME}${FILE_TMP_NAME_POSTFIX}")
|
||||
endif()
|
||||
file(RELATIVE_PATH TMP_SHADER_FILE_REL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/${FILE_OUTPUT_NAME}")
|
||||
list(APPEND VULKAN_SHADER_FILE_LIST "${FILE_OUTPUT_NAME}")
|
||||
set(VULKAN_SHADER_FILE_LIST ${VULKAN_SHADER_FILE_LIST} PARENT_SCOPE)
|
||||
set(GLSLANG_VALIDATOR_DELETE_LIST ${GLSLANG_VALIDATOR_DELETE_LIST} PARENT_SCOPE)
|
||||
set(SPIRV_OPTIMIZER_COMMAND_LIST ${SPIRV_OPTIMIZER_COMMAND_LIST} PARENT_SCOPE)
|
||||
set(GLSLANG_VALIDATOR_COMMAND_LIST ${GLSLANG_VALIDATOR_COMMAND_LIST} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(NOT FOUND_MATCHING_SHA256_FILE)
|
||||
message(STATUS "Building vulkan shaders")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/data/shader/vulkan/")
|
||||
|
||||
unset(VULKAN_SHADER_FILE_LIST CACHE)
|
||||
|
||||
# primitives
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim.frag" "data/shader/vulkan/prim.frag.spv")
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim.frag" "data/shader/vulkan/prim_textured.frag.spv")
|
||||
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim.vert" "data/shader/vulkan/prim.vert.spv")
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim.vert" "data/shader/vulkan/prim_textured.vert.spv")
|
||||
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim3d.frag" "data/shader/vulkan/prim3d.frag.spv")
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim3d.frag" "data/shader/vulkan/prim3d_textured.frag.spv")
|
||||
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim3d.vert" "data/shader/vulkan/prim3d.vert.spv")
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/prim3d.vert" "data/shader/vulkan/prim3d_textured.vert.spv")
|
||||
|
||||
# text
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/text.frag" "data/shader/vulkan/text.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/text.vert" "data/shader/vulkan/text.vert.spv")
|
||||
|
||||
# quad container
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.frag" "data/shader/vulkan/primex.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.vert" "data/shader/vulkan/primex.vert.spv")
|
||||
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.frag" "data/shader/vulkan/primex_rotationless.frag.spv")
|
||||
generate_shader_file("-DTW_ROTATIONLESS" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.vert" "data/shader/vulkan/primex_rotationless.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.frag" "data/shader/vulkan/primex_tex.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.vert" "data/shader/vulkan/primex_tex.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.frag" "data/shader/vulkan/primex_tex_rotationless.frag.spv")
|
||||
generate_shader_file("-DTW_ROTATIONLESS" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/primex.vert" "data/shader/vulkan/primex_tex_rotationless.vert.spv")
|
||||
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/spritemulti.frag" "data/shader/vulkan/spritemulti.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/spritemulti.vert" "data/shader/vulkan/spritemulti.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_PUSH_CONST" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/spritemulti.frag" "data/shader/vulkan/spritemulti_push.frag.spv")
|
||||
generate_shader_file("-DTW_PUSH_CONST" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/spritemulti.vert" "data/shader/vulkan/spritemulti_push.vert.spv")
|
||||
|
||||
# tile layer
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TILE_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile_textured.frag.spv")
|
||||
generate_shader_file("-DTW_TILE_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile_textured.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TILE_BORDER" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile_border.frag.spv")
|
||||
generate_shader_file("-DTW_TILE_BORDER" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile_border.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TILE_BORDER" "-DTW_TILE_TEXTURED" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile_border_textured.frag.spv")
|
||||
generate_shader_file("-DTW_TILE_BORDER" "-DTW_TILE_TEXTURED" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile_border_textured.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TILE_BORDER_LINE" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile_border_line.frag.spv")
|
||||
generate_shader_file("-DTW_TILE_BORDER_LINE" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile_border_line.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_TILE_BORDER_LINE" "-DTW_TILE_TEXTURED" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.frag" "data/shader/vulkan/tile_border_line_textured.frag.spv")
|
||||
generate_shader_file("-DTW_TILE_BORDER_LINE" "-DTW_TILE_TEXTURED" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/tile.vert" "data/shader/vulkan/tile_border_line_textured.vert.spv")
|
||||
|
||||
# quad layer
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.frag" "data/shader/vulkan/quad.frag.spv")
|
||||
generate_shader_file("" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.vert" "data/shader/vulkan/quad.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_PUSH_CONST" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.frag" "data/shader/vulkan/quad_push.frag.spv")
|
||||
generate_shader_file("-DTW_PUSH_CONST" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.vert" "data/shader/vulkan/quad_push.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_QUAD_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.frag" "data/shader/vulkan/quad_textured.frag.spv")
|
||||
generate_shader_file("-DTW_QUAD_TEXTURED" "" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.vert" "data/shader/vulkan/quad_textured.vert.spv")
|
||||
|
||||
generate_shader_file("-DTW_QUAD_TEXTURED" "-DTW_PUSH_CONST" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.frag" "data/shader/vulkan/quad_push_textured.frag.spv")
|
||||
generate_shader_file("-DTW_QUAD_TEXTURED" "-DTW_PUSH_CONST" "${PROJECT_SOURCE_DIR}/data/shader/vulkan/quad.vert" "data/shader/vulkan/quad_push_textured.vert.spv")
|
||||
|
||||
execute_process(${GLSLANG_VALIDATOR_COMMAND_LIST})
|
||||
if(SPIRV_OPTIMIZER_PROGRAM_FOUND)
|
||||
execute_process(${SPIRV_OPTIMIZER_COMMAND_LIST})
|
||||
file(REMOVE ${GLSLANG_VALIDATOR_DELETE_LIST})
|
||||
endif()
|
||||
|
||||
set(VULKAN_SHADER_FILE_LIST ${VULKAN_SHADER_FILE_LIST} CACHE STRING "Vulkan shader file list" FORCE)
|
||||
|
||||
message(STATUS "Finished building vulkan shaders")
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/vulkan_shaders_sha256.txt" "${GLSL_SHADER_SHA256}")
|
||||
endif()
|
61
cmake/FindVulkan.cmake
Normal file
61
cmake/FindVulkan.cmake
Normal file
|
@ -0,0 +1,61 @@
|
|||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_VULKAN vulkan)
|
||||
if(PC_VULKAN_FOUND)
|
||||
set(VULKAN_INCLUDE_DIRS "${PC_VULKAN_INCLUDE_DIRS}")
|
||||
set(VULKAN_LIBRARIES "${PC_VULKAN_LIBRARIES}")
|
||||
set(VULKAN_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT VULKAN_FOUND)
|
||||
if(TARGET_OS STREQUAL "android")
|
||||
find_library(VULKAN_LIBRARIES
|
||||
NAMES vulkan
|
||||
)
|
||||
|
||||
find_path(
|
||||
VULKAN_INCLUDE_DIRS
|
||||
NAMES vulkan/vulkan.h
|
||||
)
|
||||
elseif(TARGET_OS STREQUAL "mac")
|
||||
find_library(VULKAN_LIBRARIES
|
||||
NAMES MoltenVK
|
||||
)
|
||||
|
||||
find_path(
|
||||
VULKAN_INCLUDE_DIRS
|
||||
NAMES vulkan/vulkan.h
|
||||
)
|
||||
else()
|
||||
set_extra_dirs_lib(VULKAN vulkan)
|
||||
find_library(VULKAN_LIBRARIES
|
||||
NAMES vulkan vulkan-1
|
||||
HINTS ${HINTS_VULKAN_LIBDIR} ${PC_VULKAN_LIBDIR} ${PC_VULKAN_LIBRARY_DIRS}
|
||||
PATHS ${PATHS_VULKAN_LIBDIR}
|
||||
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
|
||||
)
|
||||
|
||||
set_extra_dirs_include(VULKAN vulkan "${VULKAN_LIBRARIES}")
|
||||
find_path(
|
||||
VULKAN_INCLUDE_DIRS
|
||||
NAMES vulkan/vulkan.h
|
||||
HINTS ${HINTS_VULKAN_INCLUDEDIR} ${PC_VULKAN_INCLUDEDIR} ${PC_VULKAN_INCLUDE_DIRS}
|
||||
PATHS ${PATHS_VULKAN_INCLUDEDIR}
|
||||
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(VULKAN_INCLUDE_DIRS AND VULKAN_LIBRARIES)
|
||||
set(VULKAN_FOUND TRUE)
|
||||
else(VULKAN_INCLUDE_DIRS AND VULKAN_LIBRARIES)
|
||||
set(VULKAN_FOUND FALSE)
|
||||
endif(VULKAN_INCLUDE_DIRS AND VULKAN_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
is_bundled(VULKAN_BUNDLED "${VULKAN_LIBRARIES}")
|
||||
if(VULKAN_BUNDLED)
|
||||
set(VULKAN_COPY_FILES "${EXTRA_VULKAN_LIBDIR}/vulkan-1.dll")
|
||||
endif()
|
||||
endif()
|
Binary file not shown.
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 55 KiB |
Binary file not shown.
Before Width: | Height: | Size: 103 B After Width: | Height: | Size: 114 B |
20
data/shader/vulkan/prim.frag
Normal file
20
data/shader/vulkan/prim.frag
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
#ifdef TW_TEXTURED
|
||||
layout(binding = 0) uniform sampler2D gTextureSampler;
|
||||
#endif
|
||||
|
||||
layout(location = 0) noperspective in vec2 texCoord;
|
||||
layout(location = 1) noperspective in vec4 vertColor;
|
||||
|
||||
layout(location = 0) out vec4 FragClr;
|
||||
void main()
|
||||
{
|
||||
#ifdef TW_TEXTURED
|
||||
vec4 tex = texture(gTextureSampler, texCoord);
|
||||
FragClr = tex * vertColor;
|
||||
#else
|
||||
FragClr = vertColor;
|
||||
#endif
|
||||
}
|
20
data/shader/vulkan/prim.vert
Normal file
20
data/shader/vulkan/prim.vert
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
layout (location = 1) in vec2 inVertexTexCoord;
|
||||
layout (location = 2) in vec4 inVertexColor;
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) mat4x2 gPos;
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective out vec2 texCoord;
|
||||
layout (location = 1) noperspective out vec4 vertColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0);
|
||||
texCoord = inVertexTexCoord;
|
||||
vertColor = vec4(inVertexColor);
|
||||
}
|
24
data/shader/vulkan/prim3d.frag
Normal file
24
data/shader/vulkan/prim3d.frag
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
#ifdef TW_TEXTURED
|
||||
layout (binding = 0) uniform sampler2DArray gTextureSampler;
|
||||
#endif
|
||||
|
||||
layout (location = 0) noperspective in vec4 oVertColor;
|
||||
#ifdef TW_TEXTURED
|
||||
layout (location = 1) noperspective in vec3 oTexCoord;
|
||||
#endif
|
||||
|
||||
layout (location = 0) out vec4 FragClr;
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef TW_TEXTURED
|
||||
vec4 TexColor = texture(gTextureSampler, oTexCoord.xyz).rgba;
|
||||
FragClr = TexColor.rgba * oVertColor.rgba;
|
||||
#else
|
||||
FragClr = oVertColor.rgba;
|
||||
#endif
|
||||
}
|
||||
|
24
data/shader/vulkan/prim3d.vert
Normal file
24
data/shader/vulkan/prim3d.vert
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
layout (location = 1) in vec4 inVertexColor;
|
||||
layout (location = 2) in vec3 inVertexTexCoord;
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) mat4x2 gPos;
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective out vec4 oVertColor;
|
||||
#ifdef TW_TEXTURED
|
||||
layout (location = 1) noperspective out vec3 oTexCoord;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0);
|
||||
#ifdef TW_TEXTURED
|
||||
oTexCoord = inVertexTexCoord;
|
||||
#endif
|
||||
oVertColor = inVertexColor;
|
||||
}
|
24
data/shader/vulkan/primex.frag
Normal file
24
data/shader/vulkan/primex.frag
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
#ifdef TW_TEXTURED
|
||||
layout(binding = 0) uniform sampler2D gTextureSampler;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform SVertexColorBO {
|
||||
layout(offset = 48) vec4 gVerticesColor;
|
||||
} gColorBO;
|
||||
|
||||
layout (location = 0) noperspective in vec2 texCoord;
|
||||
layout (location = 1) noperspective in vec4 vertColor;
|
||||
|
||||
layout (location = 0) out vec4 FragClr;
|
||||
void main()
|
||||
{
|
||||
#ifdef TW_TEXTURED
|
||||
vec4 tex = texture(gTextureSampler, texCoord);
|
||||
FragClr = tex * vertColor * gColorBO.gVerticesColor;
|
||||
#else
|
||||
FragClr = vertColor * gColorBO.gVerticesColor;
|
||||
#endif
|
||||
}
|
33
data/shader/vulkan/primex.vert
Normal file
33
data/shader/vulkan/primex.vert
Normal file
|
@ -0,0 +1,33 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
layout (location = 1) in vec2 inVertexTexCoord;
|
||||
layout (location = 2) in vec4 inVertexColor;
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) mat4x2 gPos;
|
||||
#ifndef TW_ROTATIONLESS
|
||||
layout(offset = 32) vec2 gCenter;
|
||||
layout(offset = 40) float gRotation;
|
||||
#endif
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective out vec2 texCoord;
|
||||
layout (location = 1) noperspective out vec4 vertColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 FinalPos = vec2(inVertex.xy);
|
||||
#ifndef TW_ROTATIONLESS
|
||||
float X = FinalPos.x - gPosBO.gCenter.x;
|
||||
float Y = FinalPos.y - gPosBO.gCenter.y;
|
||||
|
||||
FinalPos.x = X * cos(gPosBO.gRotation) - Y * sin(gPosBO.gRotation) + gPosBO.gCenter.x;
|
||||
FinalPos.y = X * sin(gPosBO.gRotation) + Y * cos(gPosBO.gRotation) + gPosBO.gCenter.y;
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(FinalPos, 0.0, 1.0), 0.0, 1.0);
|
||||
texCoord = inVertexTexCoord;
|
||||
vertColor = inVertexColor;
|
||||
}
|
62
data/shader/vulkan/quad.frag
Normal file
62
data/shader/vulkan/quad.frag
Normal file
|
@ -0,0 +1,62 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
layout (set = 0, binding = 0) uniform sampler2D gTextureSampler;
|
||||
#endif
|
||||
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
#define UBOSetIndex 1
|
||||
#else
|
||||
#define UBOSetIndex 0
|
||||
#endif
|
||||
|
||||
struct SQuadUniformEl {
|
||||
vec4 gVertColor;
|
||||
vec2 gOffset;
|
||||
float gRotation;
|
||||
};
|
||||
|
||||
#ifndef TW_PUSH_CONST
|
||||
#define TW_MAX_QUADS 256
|
||||
|
||||
layout (std140, set = UBOSetIndex, binding = 1) uniform SOffBO {
|
||||
uniform SQuadUniformEl gUniEls[TW_MAX_QUADS];
|
||||
} gQuadBO;
|
||||
#else
|
||||
#define gQuadBO gPosBO
|
||||
#define QuadIndex 0
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) uniform mat4x2 gPos;
|
||||
#ifdef TW_PUSH_CONST
|
||||
layout(offset = 32) uniform SQuadUniformEl gUniEls[1];
|
||||
layout(offset = 64) uniform int gQuadOffset;
|
||||
#else
|
||||
layout(offset = 32) uniform int gQuadOffset;
|
||||
#endif
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective in vec4 QuadColor;
|
||||
#ifndef TW_PUSH_CONST
|
||||
layout (location = 1) flat in int QuadIndex;
|
||||
#endif
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
#ifndef TW_PUSH_CONST
|
||||
layout (location = 2) noperspective in vec2 TexCoord;
|
||||
#else
|
||||
layout (location = 1) noperspective in vec2 TexCoord;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
layout (location = 0) out vec4 FragClr;
|
||||
void main()
|
||||
{
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
vec4 TexColor = texture(gTextureSampler, TexCoord);
|
||||
FragClr = TexColor * QuadColor * gQuadBO.gUniEls[QuadIndex].gVertColor;
|
||||
#else
|
||||
FragClr = QuadColor * gQuadBO.gUniEls[QuadIndex].gVertColor;
|
||||
#endif
|
||||
}
|
83
data/shader/vulkan/quad.vert
Normal file
83
data/shader/vulkan/quad.vert
Normal file
|
@ -0,0 +1,83 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec4 inVertex;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
layout (location = 2) in vec2 inVertexTexCoord;
|
||||
#endif
|
||||
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
#define UBOSetIndex 1
|
||||
#else
|
||||
#define UBOSetIndex 0
|
||||
#endif
|
||||
|
||||
struct SQuadUniformEl {
|
||||
vec4 gVertColor;
|
||||
vec2 gOffset;
|
||||
float gRotation;
|
||||
};
|
||||
|
||||
#ifndef TW_PUSH_CONST
|
||||
#define TW_MAX_QUADS 256
|
||||
|
||||
layout (std140, set = UBOSetIndex, binding = 1) uniform SOffBO {
|
||||
uniform SQuadUniformEl gUniEls[TW_MAX_QUADS];
|
||||
} gQuadBO;
|
||||
#else
|
||||
#define gQuadBO gPosBO
|
||||
#define TmpQuadIndex 0
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) uniform mat4x2 gPos;
|
||||
#ifdef TW_PUSH_CONST
|
||||
layout(offset = 32) uniform SQuadUniformEl gUniEls[1];
|
||||
layout(offset = 64) uniform int gQuadOffset;
|
||||
#else
|
||||
layout(offset = 32) uniform int gQuadOffset;
|
||||
#endif
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective out vec4 QuadColor;
|
||||
#ifndef TW_PUSH_CONST
|
||||
layout (location = 1) flat out int QuadIndex;
|
||||
#endif
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
#ifndef TW_PUSH_CONST
|
||||
layout (location = 2) noperspective out vec2 TexCoord;
|
||||
#else
|
||||
layout (location = 1) noperspective out vec2 TexCoord;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 FinalPos = vec2(inVertex.xy);
|
||||
|
||||
#ifndef TW_PUSH_CONST
|
||||
int TmpQuadIndex = int(gl_VertexIndex / 4) - gPosBO.gQuadOffset;
|
||||
#endif
|
||||
|
||||
if(gQuadBO.gUniEls[TmpQuadIndex].gRotation != 0.0)
|
||||
{
|
||||
float X = FinalPos.x - inVertex.z;
|
||||
float Y = FinalPos.y - inVertex.w;
|
||||
|
||||
FinalPos.x = X * cos(gQuadBO.gUniEls[TmpQuadIndex].gRotation) - Y * sin(gQuadBO.gUniEls[TmpQuadIndex].gRotation) + inVertex.z;
|
||||
FinalPos.y = X * sin(gQuadBO.gUniEls[TmpQuadIndex].gRotation) + Y * cos(gQuadBO.gUniEls[TmpQuadIndex].gRotation) + inVertex.w;
|
||||
}
|
||||
|
||||
FinalPos.x = FinalPos.x / 1024.0 + gQuadBO.gUniEls[TmpQuadIndex].gOffset.x;
|
||||
FinalPos.y = FinalPos.y / 1024.0 + gQuadBO.gUniEls[TmpQuadIndex].gOffset.y;
|
||||
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(FinalPos, 0.0, 1.0), 0.0, 1.0);
|
||||
QuadColor = inColor;
|
||||
#ifndef TW_PUSH_CONST
|
||||
QuadIndex = TmpQuadIndex;
|
||||
#endif
|
||||
#ifdef TW_QUAD_TEXTURED
|
||||
TexCoord = inVertexTexCoord;
|
||||
#endif
|
||||
}
|
13
data/shader/vulkan/quadbo.vertfrag
Normal file
13
data/shader/vulkan/quadbo.vertfrag
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
struct SQuadUniformEl {
|
||||
vec4 gVertColor;
|
||||
vec2 gOffset;
|
||||
float gRotation;
|
||||
};
|
||||
|
||||
#define TW_MAX_QUADS 256
|
||||
|
||||
layout (std140, set = 2, binding = 2) uniform SOffBO {
|
||||
uniform SQuadUniformEl gUniEls[TW_MAX_QUADS];
|
||||
} gQuadBO;
|
||||
|
23
data/shader/vulkan/spritemulti.frag
Normal file
23
data/shader/vulkan/spritemulti.frag
Normal file
|
@ -0,0 +1,23 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (set = 0, binding = 0) uniform sampler2D gTextureSampler;
|
||||
|
||||
layout(push_constant) uniform SVertexColorBO {
|
||||
#ifdef TW_PUSH_CONST
|
||||
layout(offset = 64) vec4 gVerticesColor;
|
||||
#else
|
||||
layout(offset = 48) vec4 gVerticesColor;
|
||||
#endif
|
||||
} gColorBO;
|
||||
|
||||
layout (location = 0) noperspective in vec2 texCoord;
|
||||
layout (location = 1) noperspective in vec4 vertColor;
|
||||
|
||||
layout (location = 0) out vec4 FragClr;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex = texture(gTextureSampler, texCoord);
|
||||
FragClr = tex * vertColor * gColorBO.gVerticesColor;
|
||||
}
|
50
data/shader/vulkan/spritemulti.vert
Normal file
50
data/shader/vulkan/spritemulti.vert
Normal file
|
@ -0,0 +1,50 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
layout (location = 1) in vec2 inVertexTexCoord;
|
||||
layout (location = 2) in vec4 inVertexColor;
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) uniform mat4x2 gPos;
|
||||
layout(offset = 32) uniform vec2 gCenter;
|
||||
#ifdef TW_PUSH_CONST
|
||||
layout(offset = 48) uniform vec4 gRSP[1];
|
||||
#endif
|
||||
} gPosBO;
|
||||
|
||||
#ifndef TW_PUSH_CONST
|
||||
layout (std140, set = 1, binding = 1) uniform SRSPBO {
|
||||
vec4 gRSP[512];
|
||||
} gRSPBO;
|
||||
#define RSPIndex gl_InstanceIndex
|
||||
#else
|
||||
#define gRSPBO gPosBO
|
||||
#define RSPIndex 0
|
||||
#endif
|
||||
|
||||
layout (location = 0) noperspective out vec2 texCoord;
|
||||
layout (location = 1) noperspective out vec4 vertColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 FinalPos = vec2(inVertex.xy);
|
||||
if(gRSPBO.gRSP[RSPIndex].w != 0.0)
|
||||
{
|
||||
float X = FinalPos.x - gPosBO.gCenter.x;
|
||||
float Y = FinalPos.y - gPosBO.gCenter.y;
|
||||
|
||||
FinalPos.x = X * cos(gRSPBO.gRSP[RSPIndex].w) - Y * sin(gRSPBO.gRSP[RSPIndex].w) + gPosBO.gCenter.x;
|
||||
FinalPos.y = X * sin(gRSPBO.gRSP[RSPIndex].w) + Y * cos(gRSPBO.gRSP[RSPIndex].w) + gPosBO.gCenter.y;
|
||||
}
|
||||
|
||||
FinalPos.x *= gRSPBO.gRSP[RSPIndex].z;
|
||||
FinalPos.y *= gRSPBO.gRSP[RSPIndex].z;
|
||||
|
||||
FinalPos.x += gRSPBO.gRSP[RSPIndex].x;
|
||||
FinalPos.y += gRSPBO.gRSP[RSPIndex].y;
|
||||
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(FinalPos, 0.0, 1.0), 0.0, 1.0);
|
||||
texCoord = inVertexTexCoord;
|
||||
vertColor = inVertexColor;
|
||||
}
|
43
data/shader/vulkan/text.frag
Normal file
43
data/shader/vulkan/text.frag
Normal file
|
@ -0,0 +1,43 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(binding = 0) uniform sampler2D gTextSampler;
|
||||
layout(binding = 1) uniform sampler2D gTextOutlineSampler;
|
||||
|
||||
layout(push_constant) uniform SFragConstBO {
|
||||
layout(offset = 48) uniform vec4 gVertColor;
|
||||
layout(offset = 64) uniform vec4 gVertOutlineColor;
|
||||
} gFragConst;
|
||||
|
||||
layout (location = 0) noperspective in vec2 texCoord;
|
||||
layout (location = 1) noperspective in vec4 outVertColor;
|
||||
|
||||
layout(location = 0) out vec4 FragClr;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textColor = gFragConst.gVertColor * outVertColor * vec4(1.0, 1.0, 1.0, texture(gTextSampler, texCoord).r);
|
||||
vec4 textOutlineTex = gFragConst.gVertOutlineColor * vec4(1.0, 1.0, 1.0, texture(gTextOutlineSampler, texCoord).r);
|
||||
|
||||
// ratio between the two textures
|
||||
float OutlineBlend = (1.0 - textColor.a);
|
||||
|
||||
// since the outline is always black, or even if it has decent colors, it can be just added to the actual color
|
||||
// without loosing any or too much color
|
||||
|
||||
// lerp isn't commutative, so add the color the fragment looses by lerping
|
||||
// this reduces the chance of false color calculation if the text is transparent
|
||||
|
||||
// first get the right color
|
||||
vec4 textOutlineFrag = vec4(textOutlineTex.rgb * textOutlineTex.a, textOutlineTex.a) * OutlineBlend;
|
||||
vec3 textFrag = (textColor.rgb * textColor.a);
|
||||
vec3 finalFragColor = textOutlineFrag.rgb + textFrag;
|
||||
|
||||
float RealAlpha = (textOutlineFrag.a + textColor.a);
|
||||
|
||||
// simply add the color we will loose through blending
|
||||
if(RealAlpha > 0.0)
|
||||
FragClr = vec4(finalFragColor / RealAlpha, RealAlpha);
|
||||
else
|
||||
FragClr = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
22
data/shader/vulkan/text.vert
Normal file
22
data/shader/vulkan/text.vert
Normal file
|
@ -0,0 +1,22 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
layout (location = 1) in vec2 inVertexTexCoord;
|
||||
layout (location = 2) in vec4 inVertexColor;
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) mat4x2 gPos;
|
||||
layout(offset = 32) float gTextureSize;
|
||||
} gPosBO;
|
||||
|
||||
layout (location = 0) noperspective out vec2 texCoord;
|
||||
layout (location = 1) noperspective out vec4 outVertColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0);
|
||||
|
||||
texCoord = vec2(inVertexTexCoord.x / gPosBO.gTextureSize, inVertexTexCoord.y / gPosBO.gTextureSize);
|
||||
outVertColor = inVertexColor;
|
||||
}
|
25
data/shader/vulkan/tile.frag
Normal file
25
data/shader/vulkan/tile.frag
Normal file
|
@ -0,0 +1,25 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
layout(binding = 0) uniform sampler2DArray gTextureSampler;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform SVertexColorBO {
|
||||
layout(offset = 64) uniform vec4 gVertColor;
|
||||
} gColorBO;
|
||||
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
layout (location = 0) noperspective in vec3 TexCoord;
|
||||
#endif
|
||||
|
||||
layout (location = 0) out vec4 FragClr;
|
||||
void main()
|
||||
{
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
vec4 TexColor = texture(gTextureSampler, TexCoord.xyz);
|
||||
FragClr = TexColor * gColorBO.gVertColor;
|
||||
#else
|
||||
FragClr = gColorBO.gVertColor;
|
||||
#endif
|
||||
}
|
49
data/shader/vulkan/tile.vert
Normal file
49
data/shader/vulkan/tile.vert
Normal file
|
@ -0,0 +1,49 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 inVertex;
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
layout (location = 1) in vec3 inVertexTexCoord;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform SPosBO {
|
||||
layout(offset = 0) uniform mat4x2 gPos;
|
||||
|
||||
#if defined(TW_TILE_BORDER) || defined(TW_TILE_BORDER_LINE)
|
||||
layout(offset = 32) uniform vec2 gDir;
|
||||
layout(offset = 40) uniform vec2 gOffset;
|
||||
#endif
|
||||
|
||||
#if defined(TW_TILE_BORDER)
|
||||
layout(offset = 48) uniform int gJumpIndex;
|
||||
#endif
|
||||
} gPosBO;
|
||||
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
layout (location = 0) noperspective out vec3 TexCoord;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(TW_TILE_BORDER)
|
||||
vec4 VertPos = vec4(inVertex, 0.0, 1.0);
|
||||
int XCount = gl_InstanceIndex - (int(gl_InstanceIndex/gPosBO.gJumpIndex) * gPosBO.gJumpIndex);
|
||||
int YCount = (int(gl_InstanceIndex/gPosBO.gJumpIndex));
|
||||
VertPos.x += gPosBO.gOffset.x + gPosBO.gDir.x * float(XCount);
|
||||
VertPos.y += gPosBO.gOffset.y + gPosBO.gDir.y * float(YCount);
|
||||
|
||||
gl_Position = vec4(gPosBO.gPos * VertPos, 0.0, 1.0);
|
||||
#elif defined(TW_TILE_BORDER_LINE)
|
||||
vec4 VertPos = vec4(inVertex.x + gPosBO.gOffset.x, inVertex.y + gPosBO.gOffset.y, 0.0, 1.0);
|
||||
VertPos.x += gPosBO.gDir.x * float(gl_InstanceIndex);
|
||||
VertPos.y += gPosBO.gDir.y * float(gl_InstanceIndex);
|
||||
|
||||
gl_Position = vec4(gPosBO.gPos * VertPos, 0.0, 1.0);
|
||||
#else
|
||||
gl_Position = vec4(gPosBO.gPos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef TW_TILE_TEXTURED
|
||||
TexCoord = inVertexTexCoord;
|
||||
#endif
|
||||
}
|
|
@ -104,7 +104,8 @@ function build_for_type() {
|
|||
-DTOOLS=OFF \
|
||||
-DDEV=TRUE \
|
||||
-DCMAKE_CROSSCOMPILING=ON \
|
||||
-DPREFER_BUNDLED_LIBS=ON
|
||||
-DPREFER_BUNDLED_LIBS=ON \
|
||||
-DVULKAN=ON
|
||||
(
|
||||
cd "build_android/$_ANDROID_SUB_BUILD_DIR/$1" || exit 1
|
||||
cmake --build . --target DDNet
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
virtual ~CCommandProcessorFragment_GLBase() = default;
|
||||
virtual bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand) = 0;
|
||||
|
||||
virtual void StartCommands(size_t CommandCount) {}
|
||||
virtual void StartCommands(size_t CommandCount, size_t EstimatedRenderCallCount) {}
|
||||
virtual void EndCommands() {}
|
||||
|
||||
enum
|
||||
|
|
|
@ -1005,8 +1005,10 @@ void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand
|
|||
#endif
|
||||
}
|
||||
|
||||
void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand)
|
||||
void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand)
|
||||
{
|
||||
*pCommand->m_pSwapped = false;
|
||||
|
||||
// fetch image data
|
||||
GLint aViewport[4] = {0, 0, 0, 0};
|
||||
glGetIntegerv(GL_VIEWPORT, aViewport);
|
||||
|
@ -1088,8 +1090,8 @@ bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::SCommand
|
|||
case CCommandBuffer::CMD_RENDER_TEX3D:
|
||||
Cmd_RenderTex3D(static_cast<const CCommandBuffer::SCommand_RenderTex3D *>(pBaseCommand));
|
||||
break;
|
||||
case CCommandBuffer::CMD_SCREENSHOT:
|
||||
Cmd_Screenshot(static_cast<const CCommandBuffer::SCommand_Screenshot *>(pBaseCommand));
|
||||
case CCommandBuffer::CMD_TRY_SWAP_AND_SCREENSHOT:
|
||||
Cmd_Screenshot(static_cast<const CCommandBuffer::SCommand_TrySwapAndScreenshot *>(pBaseCommand));
|
||||
break;
|
||||
case CCommandBuffer::CMD_UPDATE_VIEWPORT:
|
||||
Cmd_Update_Viewport(static_cast<const CCommandBuffer::SCommand_Update_Viewport *>(pBaseCommand));
|
||||
|
@ -1971,6 +1973,7 @@ void CCommandProcessorFragment_OpenGL2::Cmd_CreateBufferContainer(const CCommand
|
|||
{
|
||||
SBufferContainer Container;
|
||||
Container.m_ContainerInfo.m_Stride = 0;
|
||||
Container.m_ContainerInfo.m_VertBufferBindingIndex = -1;
|
||||
m_BufferContainers.push_back(Container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ protected:
|
|||
virtual void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand);
|
||||
virtual void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand);
|
||||
virtual void Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) { dbg_assert(false, "Call of unsupported Cmd_RenderTex3D"); }
|
||||
virtual void Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand);
|
||||
virtual void Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand);
|
||||
|
||||
virtual void Cmd_Update_Viewport(const CCommandBuffer::SCommand_Update_Viewport *pCommand);
|
||||
virtual void Cmd_Finish(const CCommandBuffer::SCommand_Finish *pCommand);
|
||||
|
@ -139,7 +139,6 @@ class CCommandProcessorFragment_OpenGL2 : public CCommandProcessorFragment_OpenG
|
|||
{
|
||||
struct SBufferContainer
|
||||
{
|
||||
SBufferContainer() {}
|
||||
SBufferContainerInfo m_ContainerInfo;
|
||||
};
|
||||
std::vector<SBufferContainer> m_BufferContainers;
|
||||
|
|
|
@ -1042,6 +1042,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferContainer(const CComma
|
|||
{
|
||||
SBufferContainer Container;
|
||||
Container.m_ContainerInfo.m_Stride = 0;
|
||||
Container.m_ContainerInfo.m_VertBufferBindingIndex = -1;
|
||||
m_BufferContainers.push_back(Container);
|
||||
}
|
||||
}
|
||||
|
|
7060
src/engine/client/backend/vulkan/backend_vulkan.cpp
Normal file
7060
src/engine/client/backend/vulkan/backend_vulkan.cpp
Normal file
File diff suppressed because it is too large
Load diff
12
src/engine/client/backend/vulkan/backend_vulkan.h
Normal file
12
src/engine/client/backend/vulkan/backend_vulkan.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef ENGINE_CLIENT_BACKEND_VULKAN_BACKEND_VULKAN_H
|
||||
#define ENGINE_CLIENT_BACKEND_VULKAN_BACKEND_VULKAN_H
|
||||
|
||||
#include <base/detect.h>
|
||||
#include <engine/client/backend_sdl.h>
|
||||
|
||||
static constexpr int gs_BackendVulkanMajor = 1;
|
||||
static constexpr int gs_BackendVulkanMinor = 0;
|
||||
|
||||
CCommandProcessorFragment_GLBase *CreateVulkanCommandProcessorFragment();
|
||||
|
||||
#endif
|
|
@ -68,10 +68,10 @@ void CGraphicsBackend_Threaded::ThreadFunc(void *pUser)
|
|||
std::unique_lock<std::mutex> Lock(pSelf->m_BufferSwapMutex);
|
||||
// notify, that the thread started
|
||||
pSelf->m_Started = true;
|
||||
pSelf->m_BufferDoneCond.notify_all();
|
||||
pSelf->m_BufferSwapCond.notify_all();
|
||||
while(!pSelf->m_Shutdown)
|
||||
{
|
||||
pSelf->m_BufferSwapCond.wait(Lock);
|
||||
pSelf->m_BufferSwapCond.wait(Lock, [&pSelf] { return pSelf->m_pBuffer != nullptr || pSelf->m_Shutdown; });
|
||||
if(pSelf->m_pBuffer)
|
||||
{
|
||||
#ifdef CONF_PLATFORM_MACOS
|
||||
|
@ -81,7 +81,7 @@ void CGraphicsBackend_Threaded::ThreadFunc(void *pUser)
|
|||
|
||||
pSelf->m_pBuffer = nullptr;
|
||||
pSelf->m_BufferInProcess.store(false, std::memory_order_relaxed);
|
||||
pSelf->m_BufferDoneCond.notify_all();
|
||||
pSelf->m_BufferSwapCond.notify_all();
|
||||
|
||||
#if defined(CONF_VIDEORECORDER)
|
||||
if(IVideo::Current())
|
||||
|
@ -100,16 +100,18 @@ CGraphicsBackend_Threaded::CGraphicsBackend_Threaded()
|
|||
|
||||
void CGraphicsBackend_Threaded::StartProcessor(ICommandProcessor *pProcessor)
|
||||
{
|
||||
dbg_assert(m_Shutdown, "Processor was already not shut down.");
|
||||
m_Shutdown = false;
|
||||
m_pProcessor = pProcessor;
|
||||
std::unique_lock<std::mutex> Lock(m_BufferSwapMutex);
|
||||
m_Thread = thread_init(ThreadFunc, this, "Graphics thread");
|
||||
// wait for the thread to start
|
||||
m_BufferDoneCond.wait(Lock, [this]() -> bool { return m_Started; });
|
||||
m_BufferSwapCond.wait(Lock, [this]() -> bool { return m_Started; });
|
||||
}
|
||||
|
||||
void CGraphicsBackend_Threaded::StopProcessor()
|
||||
{
|
||||
dbg_assert(!m_Shutdown, "Processor was already shut down.");
|
||||
m_Shutdown = true;
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(m_BufferSwapMutex);
|
||||
|
@ -140,8 +142,7 @@ bool CGraphicsBackend_Threaded::IsIdle() const
|
|||
void CGraphicsBackend_Threaded::WaitForIdle()
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(m_BufferSwapMutex);
|
||||
while(m_pBuffer != nullptr)
|
||||
m_BufferDoneCond.wait(Lock);
|
||||
m_BufferSwapCond.wait(Lock, [this]() { return m_pBuffer == nullptr; });
|
||||
}
|
||||
|
||||
// ------------ CCommandProcessorFragment_General
|
||||
|
@ -236,7 +237,7 @@ bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::SCommand *p
|
|||
|
||||
void CCommandProcessor_SDL_GL::RunBuffer(CCommandBuffer *pBuffer)
|
||||
{
|
||||
m_pGLBackend->StartCommands(pBuffer->m_CommandCount);
|
||||
m_pGLBackend->StartCommands(pBuffer->m_CommandCount, pBuffer->m_RenderCallCount);
|
||||
|
||||
for(CCommandBuffer::SCommand *pCommand = pBuffer->Head(); pCommand; pCommand = pCommand->m_pNext)
|
||||
{
|
||||
|
@ -560,10 +561,8 @@ static int IsVersionSupportedGlew(EBackendType BackendType, int VersionMajor, in
|
|||
|
||||
EBackendType CGraphicsBackend_SDL_GL::DetectBackend()
|
||||
{
|
||||
// TODO
|
||||
return BACKEND_TYPE_VULKAN;
|
||||
EBackendType RetBackendType = BACKEND_TYPE_OPENGL;
|
||||
const char *pEnvDriver = getenv("DDNET_DRIVER");
|
||||
const char *pEnvDriver = SDL_getenv("DDNET_DRIVER");
|
||||
if(pEnvDriver && str_comp_nocase(pEnvDriver, "GLES") == 0)
|
||||
RetBackendType = BACKEND_TYPE_OPENGL_ES;
|
||||
else if(pEnvDriver && str_comp_nocase(pEnvDriver, "Vulkan") == 0)
|
||||
|
@ -581,9 +580,15 @@ EBackendType CGraphicsBackend_SDL_GL::DetectBackend()
|
|||
else if(str_comp_nocase(pConfBackend, "OpenGL") == 0)
|
||||
RetBackendType = BACKEND_TYPE_OPENGL;
|
||||
}
|
||||
#if !defined(CONF_BACKEND_VULKAN)
|
||||
RetBackendType = BACKEND_TYPE_OPENGL;
|
||||
#endif
|
||||
#if !defined(CONF_BACKEND_OPENGL_ES) && !defined(CONF_BACKEND_OPENGL_ES3)
|
||||
if(RetBackendType == BACKEND_TYPE_OPENGL_ES)
|
||||
RetBackendType = BACKEND_TYPE_OPENGL;
|
||||
#elif defined(CONF_BACKEND_OPENGL_ES)
|
||||
if(RetBackendType == BACKEND_TYPE_OPENGL)
|
||||
RetBackendType = BACKEND_TYPE_OPENGL_ES;
|
||||
#endif
|
||||
return RetBackendType;
|
||||
}
|
||||
|
@ -635,9 +640,11 @@ void CGraphicsBackend_SDL_GL::ClampDriverVersion(EBackendType BackendType)
|
|||
}
|
||||
else if(BackendType == BACKEND_TYPE_VULKAN)
|
||||
{
|
||||
g_Config.m_GfxGLMajor = 1;
|
||||
g_Config.m_GfxGLMinor = 1;
|
||||
#if defined(CONF_BACKEND_VULKAN)
|
||||
g_Config.m_GfxGLMajor = gs_BackendVulkanMajor;
|
||||
g_Config.m_GfxGLMinor = gs_BackendVulkanMinor;
|
||||
g_Config.m_GfxGLPatch = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,50 +660,81 @@ bool CGraphicsBackend_SDL_GL::IsModernAPI(EBackendType BackendType)
|
|||
return false;
|
||||
}
|
||||
|
||||
void CGraphicsBackend_SDL_GL::GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch)
|
||||
bool CGraphicsBackend_SDL_GL::GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType)
|
||||
{
|
||||
if(m_BackendType == BACKEND_TYPE_OPENGL)
|
||||
if(BackendType == BACKEND_TYPE_AUTO)
|
||||
BackendType = m_BackendType;
|
||||
if(BackendType == BACKEND_TYPE_OPENGL)
|
||||
{
|
||||
pName = "OpenGL";
|
||||
if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_LEGACY)
|
||||
{
|
||||
Major = 1;
|
||||
Minor = 4;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
else if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_DEFAULT)
|
||||
{
|
||||
Major = 3;
|
||||
Minor = 0;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
else if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_MODERN)
|
||||
{
|
||||
Major = 3;
|
||||
Minor = 3;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(m_BackendType == BACKEND_TYPE_OPENGL_ES)
|
||||
else if(BackendType == BACKEND_TYPE_OPENGL_ES)
|
||||
{
|
||||
pName = "GLES";
|
||||
#ifdef CONF_BACKEND_OPENGL_ES
|
||||
if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_LEGACY)
|
||||
{
|
||||
Major = 1;
|
||||
Minor = 0;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
else if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_DEFAULT)
|
||||
{
|
||||
Major = 3;
|
||||
Minor = 0;
|
||||
Patch = 0;
|
||||
// there isn't really a default one
|
||||
return false;
|
||||
}
|
||||
else if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_MODERN)
|
||||
#endif
|
||||
#ifdef CONF_BACKEND_OPENGL_ES3
|
||||
if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_MODERN)
|
||||
{
|
||||
Major = 3;
|
||||
Minor = 0;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(BackendType == BACKEND_TYPE_VULKAN)
|
||||
{
|
||||
pName = "Vulkan";
|
||||
#ifdef CONF_BACKEND_VULKAN
|
||||
if(DriverAgeType == GRAPHICS_DRIVER_AGE_TYPE_DEFAULT)
|
||||
{
|
||||
Major = gs_BackendVulkanMajor;
|
||||
Minor = gs_BackendVulkanMinor;
|
||||
Patch = 0;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void DisplayToVideoMode(CVideoMode *pVMode, SDL_DisplayMode *pMode, int HiDPIScale, int RefreshRate)
|
||||
|
@ -830,12 +868,19 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
dbg_msg("gfx", "unable to init SDL video: %s", SDL_GetError());
|
||||
return EGraphicsBackendErrorCodes::GRAPHICS_BACKEND_ERROR_CODE_SDL_INIT_FAILED;
|
||||
}
|
||||
#if defined(CONF_FAMILY_WINDOWS) && defined(CONF_BACKEND_VULKAN)
|
||||
SDL_Vulkan_LoadLibrary("libvulkan-1.dll");
|
||||
#endif
|
||||
}
|
||||
|
||||
EBackendType OldBackendType = m_BackendType;
|
||||
m_BackendType = DetectBackend();
|
||||
// little fallback for Vulkan
|
||||
if(OldBackendType != BACKEND_TYPE_AUTO)
|
||||
{
|
||||
if(m_BackendType == BACKEND_TYPE_VULKAN)
|
||||
{
|
||||
SDL_setenv("DDNET_DRIVER", "OpenGL", 1);
|
||||
m_BackendType = DetectBackend();
|
||||
}
|
||||
}
|
||||
|
||||
ClampDriverVersion(m_BackendType);
|
||||
|
||||
|
@ -918,7 +963,7 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
|
||||
// set flags
|
||||
int SdlFlags = SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS;
|
||||
SdlFlags |= (m_BackendType == BACKEND_TYPE_OPENGL || m_BackendType == BACKEND_TYPE_OPENGL_ES) ? SDL_WINDOW_OPENGL : SDL_WINDOW_VULKAN;
|
||||
SdlFlags |= (IsOpenGLFamilyBackend) ? SDL_WINDOW_OPENGL : SDL_WINDOW_VULKAN;
|
||||
if(Flags & IGraphicsBackend::INITFLAG_HIGHDPI)
|
||||
SdlFlags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
if(Flags & IGraphicsBackend::INITFLAG_RESIZABLE)
|
||||
|
@ -981,6 +1026,9 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
if(m_pWindow == NULL)
|
||||
{
|
||||
dbg_msg("gfx", "unable to create window: %s", SDL_GetError());
|
||||
if(m_BackendType == BACKEND_TYPE_VULKAN)
|
||||
return EGraphicsBackendErrorCodes::GRAPHICS_BACKEND_ERROR_CODE_GL_CONTEXT_FAILED;
|
||||
else
|
||||
return EGraphicsBackendErrorCodes::GRAPHICS_BACKEND_ERROR_CODE_SDL_WINDOW_CREATE_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1013,7 +1061,7 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
InitError = IsVersionSupportedGlew(m_BackendType, g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch, GlewMajor, GlewMinor, GlewPatch);
|
||||
|
||||
// SDL_GL_GetDrawableSize reports HiDPI resolution even with SDL_WINDOW_ALLOW_HIGHDPI not set, which is wrong
|
||||
if(SdlFlags & SDL_WINDOW_ALLOW_HIGHDPI)
|
||||
if(SdlFlags & SDL_WINDOW_ALLOW_HIGHDPI && IsOpenGLFamilyBackend)
|
||||
SDL_GL_GetDrawableSize(m_pWindow, pCurrentWidth, pCurrentHeight);
|
||||
else
|
||||
SDL_GetWindowSize(m_pWindow, pCurrentWidth, pCurrentHeight);
|
||||
|
@ -1039,6 +1087,7 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
}
|
||||
|
||||
// start the command processor
|
||||
dbg_assert(m_pProcessor == nullptr, "Processor was not cleaned up properly.");
|
||||
m_pProcessor = new CCommandProcessor_SDL_GL(m_BackendType, g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch);
|
||||
StartProcessor(m_pProcessor);
|
||||
|
||||
|
@ -1124,7 +1173,7 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
|
|||
// stop and delete the processor
|
||||
StopProcessor();
|
||||
delete m_pProcessor;
|
||||
m_pProcessor = 0;
|
||||
m_pProcessor = nullptr;
|
||||
|
||||
if(m_GLContext)
|
||||
SDL_GL_DeleteContext(m_GLContext);
|
||||
|
@ -1188,7 +1237,7 @@ int CGraphicsBackend_SDL_GL::Shutdown()
|
|||
// stop and delete the processor
|
||||
StopProcessor();
|
||||
delete m_pProcessor;
|
||||
m_pProcessor = 0;
|
||||
m_pProcessor = nullptr;
|
||||
|
||||
SDL_GL_DeleteContext(m_GLContext);
|
||||
SDL_DestroyWindow(m_pWindow);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <base/detect.h>
|
||||
|
||||
#include "engine/graphics.h"
|
||||
#include "graphics_defines.h"
|
||||
|
||||
#include "blocklist_driver.h"
|
||||
|
@ -70,9 +71,8 @@ private:
|
|||
ICommandProcessor *m_pProcessor;
|
||||
std::mutex m_BufferSwapMutex;
|
||||
std::condition_variable m_BufferSwapCond;
|
||||
std::condition_variable m_BufferDoneCond;
|
||||
CCommandBuffer *m_pBuffer;
|
||||
std::atomic_bool m_Shutdown;
|
||||
std::atomic_bool m_Shutdown = true;
|
||||
bool m_Started = false;
|
||||
std::atomic_bool m_BufferInProcess;
|
||||
void *m_Thread;
|
||||
|
@ -90,13 +90,6 @@ public:
|
|||
bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand);
|
||||
};
|
||||
|
||||
enum EBackendType
|
||||
{
|
||||
BACKEND_TYPE_OPENGL = 0,
|
||||
BACKEND_TYPE_OPENGL_ES,
|
||||
BACKEND_TYPE_VULKAN,
|
||||
};
|
||||
|
||||
struct SBackendCapabilites
|
||||
{
|
||||
bool m_TileBuffering;
|
||||
|
@ -183,7 +176,7 @@ class CGraphicsBackend_SDL_GL : public CGraphicsBackend_Threaded
|
|||
{
|
||||
SDL_Window *m_pWindow = NULL;
|
||||
SDL_GLContext m_GLContext;
|
||||
ICommandProcessor *m_pProcessor;
|
||||
ICommandProcessor *m_pProcessor = nullptr;
|
||||
std::atomic<uint64_t> m_TextureMemoryUsage{0};
|
||||
std::atomic<uint64_t> m_BufferMemoryUsage{0};
|
||||
std::atomic<uint64_t> m_StreamMemoryUsage{0};
|
||||
|
@ -201,7 +194,7 @@ class CGraphicsBackend_SDL_GL : public CGraphicsBackend_Threaded
|
|||
char m_aVersionString[gs_GPUInfoStringSize] = {};
|
||||
char m_aRendererString[gs_GPUInfoStringSize] = {};
|
||||
|
||||
EBackendType m_BackendType;
|
||||
EBackendType m_BackendType = BACKEND_TYPE_AUTO;
|
||||
|
||||
char m_aErrorString[256];
|
||||
|
||||
|
@ -241,7 +234,7 @@ public:
|
|||
virtual void WindowDestroyNtf(uint32_t WindowID);
|
||||
virtual void WindowCreateNtf(uint32_t WindowID);
|
||||
|
||||
virtual void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch);
|
||||
virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType);
|
||||
virtual bool IsConfigModernAPI() { return IsModernAPI(m_BackendType); }
|
||||
virtual bool UseTrianglesAsQuad() { return m_Capabilites.m_TrianglesAsQuads; }
|
||||
virtual bool HasTileBuffering() { return m_Capabilites.m_TileBuffering; }
|
||||
|
|
|
@ -496,7 +496,7 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig
|
|||
void *pTmpData = malloc(MemSize);
|
||||
if(!ConvertToRGBA((uint8_t *)pTmpData, (const uint8_t *)pData, Width, Height, Format))
|
||||
{
|
||||
dbg_msg("graphics", "converted image %s to RGBA, consider making its file format using RGBA", pTexName);
|
||||
dbg_msg("graphics", "converted image %s to RGBA, consider making its file format RGBA", pTexName);
|
||||
}
|
||||
Cmd.m_pData = pTmpData;
|
||||
|
||||
|
@ -624,7 +624,7 @@ bool CGraphics_Threaded::UpdateTextTexture(CTextureHandle TextureID, int x, int
|
|||
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to update text texture.");
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType)
|
||||
|
@ -739,7 +739,7 @@ bool CGraphics_Threaded::CheckImageDivisibility(const char *pFileName, CImageInf
|
|||
|
||||
bool CGraphics_Threaded::IsImageFormatRGBA(const char *pFileName, CImageInfo &Img)
|
||||
{
|
||||
if(Img.m_Format != CImageInfo::FORMAT_RGBA && Img.m_Format != CImageInfo::FORMAT_ALPHA)
|
||||
if(Img.m_Format != CImageInfo::FORMAT_RGBA)
|
||||
{
|
||||
SWarning NewWarning;
|
||||
char aText[128];
|
||||
|
@ -787,14 +787,17 @@ void CGraphics_Threaded::KickCommandBuffer()
|
|||
m_pCommandBuffer->Reset();
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::ScreenshotDirect()
|
||||
bool CGraphics_Threaded::ScreenshotDirect()
|
||||
{
|
||||
// add swap command
|
||||
CImageInfo Image;
|
||||
mem_zero(&Image, sizeof(Image));
|
||||
|
||||
CCommandBuffer::SCommand_Screenshot Cmd;
|
||||
bool DidSwap = false;
|
||||
|
||||
CCommandBuffer::SCommand_TrySwapAndScreenshot Cmd;
|
||||
Cmd.m_pImage = &Image;
|
||||
Cmd.m_pSwapped = &DidSwap;
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to take screenshot.");
|
||||
|
||||
|
@ -826,6 +829,8 @@ void CGraphics_Threaded::ScreenshotDirect()
|
|||
|
||||
free(Image.m_pData);
|
||||
}
|
||||
|
||||
return DidSwap;
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::TextureSet(CTextureHandle TextureID)
|
||||
|
@ -834,13 +839,14 @@ void CGraphics_Threaded::TextureSet(CTextureHandle TextureID)
|
|||
m_State.m_Texture = TextureID.Id();
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::Clear(float r, float g, float b)
|
||||
void CGraphics_Threaded::Clear(float r, float g, float b, bool ForceClearNow)
|
||||
{
|
||||
CCommandBuffer::SCommand_Clear Cmd;
|
||||
Cmd.m_Color.r = r;
|
||||
Cmd.m_Color.g = g;
|
||||
Cmd.m_Color.b = b;
|
||||
Cmd.m_Color.a = 0;
|
||||
Cmd.m_ForceClear = ForceClearNow || m_IsForcedViewport;
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to clear graphics.");
|
||||
}
|
||||
|
@ -1218,25 +1224,25 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pTe
|
|||
}
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffet)
|
||||
void CGraphics_Threaded::RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffset)
|
||||
{
|
||||
if(NumIndicesOffet == 0)
|
||||
if(NumIndicesOffset == 0)
|
||||
return;
|
||||
|
||||
// add the VertexArrays and draw
|
||||
CCommandBuffer::SCommand_RenderTileLayer Cmd;
|
||||
Cmd.m_State = m_State;
|
||||
Cmd.m_IndicesDrawNum = NumIndicesOffet;
|
||||
Cmd.m_IndicesDrawNum = NumIndicesOffset;
|
||||
Cmd.m_BufferContainerIndex = BufferContainerIndex;
|
||||
mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color));
|
||||
|
||||
void *Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffet);
|
||||
void *Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffset);
|
||||
if(Data == 0x0)
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffet);
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffset);
|
||||
if(Data == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
|
@ -1244,18 +1250,18 @@ void CGraphics_Threaded::RenderTileLayer(int BufferContainerIndex, float *pColor
|
|||
}
|
||||
}
|
||||
Cmd.m_pIndicesOffsets = (char **)Data;
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffet));
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffset));
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffet);
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffset);
|
||||
if(Data == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
return false;
|
||||
}
|
||||
Cmd.m_pIndicesOffsets = (char **)Data;
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffet));
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffset));
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for render command"))
|
||||
|
@ -1263,9 +1269,10 @@ void CGraphics_Threaded::RenderTileLayer(int BufferContainerIndex, float *pColor
|
|||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pIndicesOffsets, pOffsets, sizeof(char *) * NumIndicesOffet);
|
||||
mem_copy(Cmd.m_pDrawCount, IndicedVertexDrawNum, sizeof(unsigned int) * NumIndicesOffet);
|
||||
mem_copy(Cmd.m_pIndicesOffsets, pOffsets, sizeof(char *) * NumIndicesOffset);
|
||||
mem_copy(Cmd.m_pDrawCount, IndicedVertexDrawNum, sizeof(unsigned int) * NumIndicesOffset);
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(NumIndicesOffset);
|
||||
// todo max indices group check!!
|
||||
}
|
||||
|
||||
|
@ -1294,6 +1301,8 @@ void CGraphics_Threaded::RenderBorderTiles(int BufferContainerIndex, float *pCol
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::RenderBorderTileLines(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, unsigned int IndexDrawNum, unsigned int RedrawNum)
|
||||
|
@ -1321,6 +1330,8 @@ void CGraphics_Threaded::RenderBorderTileLines(int BufferContainerIndex, float *
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, int QuadNum, int QuadOffset)
|
||||
|
@ -1356,6 +1367,8 @@ void CGraphics_Threaded::RenderQuadLayer(int BufferContainerIndex, SQuadRenderIn
|
|||
}
|
||||
|
||||
mem_copy(Cmd.m_pQuadInfo, pQuadInfo, sizeof(SQuadRenderInfo) * QuadNum);
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(((QuadNum - 1) / gs_GraphicsMaxQuadsRenderCount) + 1);
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::RenderText(int BufferContainerIndex, int TextQuadNum, int TextureSize, int TextureTextIndex, int TextureTextOutlineIndex, float *pTextColor, float *pTextoutlineColor)
|
||||
|
@ -1378,6 +1391,8 @@ void CGraphics_Threaded::RenderText(int BufferContainerIndex, int TextQuadNum, i
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
|
||||
int CGraphics_Threaded::CreateQuadContainer(bool AutomaticUpload)
|
||||
|
@ -1594,6 +1609,8 @@ void CGraphics_Threaded::RenderQuadContainer(int ContainerIndex, int QuadOffset,
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1671,6 +1688,8 @@ void CGraphics_Threaded::RenderQuadContainerEx(int ContainerIndex, int QuadOffse
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1815,6 +1834,9 @@ void CGraphics_Threaded::RenderQuadContainerAsSpriteMultiple(int ContainerIndex,
|
|||
}
|
||||
|
||||
mem_copy(Cmd.m_pRenderInfo, pRenderInfo, sizeof(IGraphics::SRenderSpriteInfo) * DrawCount);
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(((DrawCount - 1) / gs_GraphicsMaxParticlesRenderCount) + 1);
|
||||
|
||||
WrapNormal();
|
||||
}
|
||||
else
|
||||
|
@ -2235,6 +2257,37 @@ int CGraphics_Threaded::IssueInit()
|
|||
return r;
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::AdjustViewport(bool SendViewportChangeToBackend)
|
||||
{
|
||||
// adjust the viewport to only allow certain aspect ratios
|
||||
// keep this in sync with backend_vulkan GetSwapImageSize's check
|
||||
if(m_ScreenHeight > 4 * m_ScreenWidth / 5)
|
||||
{
|
||||
m_IsForcedViewport = true;
|
||||
m_ScreenHeight = 4 * m_ScreenWidth / 5;
|
||||
|
||||
if(SendViewportChangeToBackend)
|
||||
{
|
||||
CCommandBuffer::SCommand_Update_Viewport Cmd;
|
||||
Cmd.m_X = 0;
|
||||
Cmd.m_Y = 0;
|
||||
Cmd.m_Width = m_ScreenWidth;
|
||||
Cmd.m_Height = m_ScreenHeight;
|
||||
Cmd.m_ByResize = true;
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add resize command"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsForcedViewport = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::AddBackEndWarningIfExists()
|
||||
{
|
||||
const char *pErrStr = m_pBackend->GetErrorString();
|
||||
|
@ -2354,6 +2407,16 @@ int CGraphics_Threaded::InitWindow()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// at the very end, just try to set to gl 1.4
|
||||
{
|
||||
g_Config.m_GfxGLMajor = 1;
|
||||
g_Config.m_GfxGLMinor = 4;
|
||||
g_Config.m_GfxGLPatch = 0;
|
||||
|
||||
if(IssueInit() == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbg_msg("gfx", "out of ideas. failed to init graphics");
|
||||
|
||||
return -1;
|
||||
|
@ -2413,6 +2476,8 @@ int CGraphics_Threaded::Init()
|
|||
str_format(aBuf, sizeof(aBuf), "GPU version: %s", GetVersionString());
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gfx", aBuf, GPUInfoPrintColor);
|
||||
|
||||
AdjustViewport(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2460,6 +2525,7 @@ bool CGraphics_Threaded::SetWindowScreen(int Index)
|
|||
}
|
||||
|
||||
m_pBackend->GetViewportSize(m_ScreenWidth, m_ScreenHeight);
|
||||
AdjustViewport(true);
|
||||
m_ScreenHiDPIScale = m_ScreenWidth / (float)g_Config.m_GfxScreenWidth;
|
||||
return true;
|
||||
}
|
||||
|
@ -2475,6 +2541,7 @@ void CGraphics_Threaded::Move(int x, int y)
|
|||
const int CurScreen = m_pBackend->GetWindowScreen();
|
||||
m_pBackend->UpdateDisplayMode(CurScreen);
|
||||
m_pBackend->GetViewportSize(m_ScreenWidth, m_ScreenHeight);
|
||||
AdjustViewport(true);
|
||||
m_ScreenHiDPIScale = m_ScreenWidth / (float)g_Config.m_GfxScreenWidth;
|
||||
}
|
||||
|
||||
|
@ -2511,9 +2578,7 @@ void CGraphics_Threaded::GotResized(int w, int h, int RefreshRate)
|
|||
// if the size change event is triggered, set all parameters and change the viewport
|
||||
m_pBackend->GetViewportSize(m_ScreenWidth, m_ScreenHeight);
|
||||
|
||||
// adjust the viewport to only allow certain aspect ratios
|
||||
if(m_ScreenHeight > 4 * m_ScreenWidth / 5)
|
||||
m_ScreenHeight = 4 * m_ScreenWidth / 5;
|
||||
AdjustViewport(false);
|
||||
|
||||
m_ScreenRefreshRate = RefreshRate;
|
||||
|
||||
|
@ -2635,14 +2700,16 @@ void CGraphics_Threaded::Swap()
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: screenshot support
|
||||
bool TookScreenshotAndSwapped = false;
|
||||
|
||||
if(m_DoScreenshot)
|
||||
{
|
||||
if(WindowActive())
|
||||
ScreenshotDirect();
|
||||
TookScreenshotAndSwapped = ScreenshotDirect();
|
||||
m_DoScreenshot = false;
|
||||
}
|
||||
|
||||
if(!TookScreenshotAndSwapped)
|
||||
{
|
||||
// add swap command
|
||||
CCommandBuffer::SCommand_Swap Cmd;
|
||||
|
|
|
@ -61,6 +61,7 @@ class CCommandBuffer
|
|||
public:
|
||||
CBuffer m_CmdBuffer;
|
||||
size_t m_CommandCount = 0;
|
||||
size_t m_RenderCallCount = 0;
|
||||
|
||||
CBuffer m_DataBuffer;
|
||||
|
||||
|
@ -128,7 +129,7 @@ public:
|
|||
|
||||
// misc
|
||||
CMD_VSYNC,
|
||||
CMD_SCREENSHOT,
|
||||
CMD_TRY_SWAP_AND_SCREENSHOT,
|
||||
CMD_UPDATE_VIEWPORT,
|
||||
|
||||
// in Android a window that minimizes gets destroyed
|
||||
|
@ -213,6 +214,7 @@ public:
|
|||
SCommand_Clear() :
|
||||
SCommand(CMD_CLEAR) {}
|
||||
SColorf m_Color;
|
||||
bool m_ForceClear;
|
||||
};
|
||||
|
||||
struct SCommand_Signal : public SCommand
|
||||
|
@ -477,11 +479,12 @@ public:
|
|||
void *m_pOffset;
|
||||
};
|
||||
|
||||
struct SCommand_Screenshot : public SCommand
|
||||
struct SCommand_TrySwapAndScreenshot : public SCommand
|
||||
{
|
||||
SCommand_Screenshot() :
|
||||
SCommand(CMD_SCREENSHOT) {}
|
||||
SCommand_TrySwapAndScreenshot() :
|
||||
SCommand(CMD_TRY_SWAP_AND_SCREENSHOT) {}
|
||||
CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well
|
||||
bool *m_pSwapped;
|
||||
};
|
||||
|
||||
struct SCommand_Swap : public SCommand
|
||||
|
@ -663,6 +666,12 @@ public:
|
|||
m_DataBuffer.Reset();
|
||||
|
||||
m_CommandCount = 0;
|
||||
m_RenderCallCount = 0;
|
||||
}
|
||||
|
||||
void AddRenderCalls(size_t RenderCallCountToAdd)
|
||||
{
|
||||
m_RenderCallCount += RenderCallCountToAdd;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -733,7 +742,7 @@ public:
|
|||
virtual bool IsIdle() const = 0;
|
||||
virtual void WaitForIdle() = 0;
|
||||
|
||||
virtual void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) {}
|
||||
virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) = 0;
|
||||
// checks if the current values of the config are a graphics modern API
|
||||
virtual bool IsConfigModernAPI() { return false; }
|
||||
virtual bool UseTrianglesAsQuad() { return false; }
|
||||
|
@ -806,6 +815,10 @@ class CGraphics_Threaded : public IEngineGraphics
|
|||
|
||||
std::vector<SWarning> m_Warnings;
|
||||
|
||||
// is a non full windowed (in a sense that the viewport won't include the whole window),
|
||||
// forced viewport, so that it justifies our UI ratio needs
|
||||
bool m_IsForcedViewport = false;
|
||||
|
||||
struct SVertexArrayInfo
|
||||
{
|
||||
SVertexArrayInfo() :
|
||||
|
@ -906,6 +919,8 @@ class CGraphics_Threaded : public IEngineGraphics
|
|||
|
||||
void AddBackEndWarningIfExists();
|
||||
|
||||
void AdjustViewport(bool SendViewportChangeToBackend);
|
||||
|
||||
int IssueInit();
|
||||
int InitWindow();
|
||||
|
||||
|
@ -962,11 +977,11 @@ public:
|
|||
void CopyTextureBufferSub(uint8_t *pDestBuffer, uint8_t *pSourceBuffer, int FullWidth, int FullHeight, int ColorChannelCount, int SubOffsetX, int SubOffsetY, int SubCopyWidth, int SubCopyHeight) override;
|
||||
void CopyTextureFromTextureBufferSub(uint8_t *pDestBuffer, int DestWidth, int DestHeight, uint8_t *pSourceBuffer, int SrcWidth, int SrcHeight, int ColorChannelCount, int SrcSubOffsetX, int SrcSubOffsetY, int SrcSubCopyWidth, int SrcSubCopyHeight) override;
|
||||
|
||||
void ScreenshotDirect();
|
||||
bool ScreenshotDirect();
|
||||
|
||||
void TextureSet(CTextureHandle TextureID) override;
|
||||
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Clear(float r, float g, float b, bool ForceClearNow = false) override;
|
||||
|
||||
void QuadsBegin() override;
|
||||
void QuadsEnd() override;
|
||||
|
@ -1197,12 +1212,14 @@ public:
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCommandBuffer->AddRenderCalls(1);
|
||||
}
|
||||
|
||||
void FlushVertices(bool KeepVertices = false) override;
|
||||
void FlushVerticesTex3D() override;
|
||||
|
||||
void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffet) override;
|
||||
void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffset) override;
|
||||
void RenderBorderTiles(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, int JumpIndex, unsigned int DrawNum) override;
|
||||
void RenderBorderTileLines(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, unsigned int IndexDrawNum, unsigned int RedrawNum) override;
|
||||
void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, int QuadNum, int QuadOffset) override;
|
||||
|
@ -1261,7 +1278,7 @@ public:
|
|||
|
||||
SWarning *GetCurWarning() override;
|
||||
|
||||
void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) override { m_pBackend->GetDriverVersion(DriverAgeType, Major, Minor, Patch); }
|
||||
bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) override { return m_pBackend->GetDriverVersion(DriverAgeType, Major, Minor, Patch, pName, BackendType); }
|
||||
bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }
|
||||
bool IsTileBufferingEnabled() override { return m_GLTileBufferingEnabled; }
|
||||
bool IsQuadBufferingEnabled() override { return m_GLQuadBufferingEnabled; }
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
|
||||
void TextureSet(CTextureHandle TextureID) override{};
|
||||
|
||||
void Clear(float r, float g, float b) override{};
|
||||
void Clear(float r, float g, float b, bool ForceClearNow = false) override{};
|
||||
|
||||
void QuadsBegin() override{};
|
||||
void QuadsEnd() override{};
|
||||
|
@ -138,7 +138,7 @@ public:
|
|||
void FlushVertices(bool KeepVertices = false) override{};
|
||||
void FlushVerticesTex3D() override{};
|
||||
|
||||
void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffet) override{};
|
||||
void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffset) override{};
|
||||
void RenderBorderTiles(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, int JumpIndex, unsigned int DrawNum) override{};
|
||||
void RenderBorderTileLines(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, unsigned int IndexDrawNum, unsigned int RedrawNum) override{};
|
||||
void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, int QuadNum, int QuadOffset) override{};
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
|
||||
SWarning *GetCurWarning() override { return NULL; }
|
||||
|
||||
void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) override {}
|
||||
bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) override { return false; }
|
||||
bool IsConfigModernAPI() override { return false; }
|
||||
bool IsTileBufferingEnabled() override { return false; }
|
||||
bool IsQuadBufferingEnabled() override { return false; }
|
||||
|
|
|
@ -42,6 +42,8 @@ struct SQuadRenderInfo
|
|||
float m_aColor[4];
|
||||
float m_aOffsets[2];
|
||||
float m_Rotation;
|
||||
// allows easier upload for uniform buffers because of the alignment requirements
|
||||
float m_Padding;
|
||||
};
|
||||
|
||||
struct SGraphicTile
|
||||
|
@ -151,11 +153,28 @@ struct GL_SVertexTex3DStream
|
|||
GL_STexCoord3D m_Tex;
|
||||
};
|
||||
|
||||
static constexpr size_t gs_GraphicsMaxQuadsRenderCount = 256;
|
||||
static constexpr size_t gs_GraphicsMaxParticlesRenderCount = 512;
|
||||
|
||||
enum EGraphicsDriverAgeType
|
||||
{
|
||||
GRAPHICS_DRIVER_AGE_TYPE_LEGACY = 0,
|
||||
GRAPHICS_DRIVER_AGE_TYPE_DEFAULT,
|
||||
GRAPHICS_DRIVER_AGE_TYPE_MODERN,
|
||||
|
||||
GRAPHICS_DRIVER_AGE_TYPE_COUNT,
|
||||
};
|
||||
|
||||
enum EBackendType
|
||||
{
|
||||
BACKEND_TYPE_OPENGL = 0,
|
||||
BACKEND_TYPE_OPENGL_ES,
|
||||
BACKEND_TYPE_VULKAN,
|
||||
|
||||
// special value to tell the backend to identify the current backend
|
||||
BACKEND_TYPE_AUTO,
|
||||
|
||||
BACKEND_TYPE_COUNT,
|
||||
};
|
||||
|
||||
struct STWGraphicGPU
|
||||
|
@ -235,7 +254,8 @@ public:
|
|||
virtual void WindowDestroyNtf(uint32_t WindowID) = 0;
|
||||
virtual void WindowCreateNtf(uint32_t WindowID) = 0;
|
||||
|
||||
virtual void Clear(float r, float g, float b) = 0;
|
||||
// ForceClearNow forces the backend to trigger a clear, even at performance cost, else it might be delayed by one frame
|
||||
virtual void Clear(float r, float g, float b, bool ForceClearNow = false) = 0;
|
||||
|
||||
virtual void ClipEnable(int x, int y, int w, int h) = 0;
|
||||
virtual void ClipDisable() = 0;
|
||||
|
@ -291,7 +311,7 @@ public:
|
|||
virtual void FlushVerticesTex3D() = 0;
|
||||
|
||||
// specific render functions
|
||||
virtual void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffet) = 0;
|
||||
virtual void RenderTileLayer(int BufferContainerIndex, float *pColor, char **pOffsets, unsigned int *IndicedVertexDrawNum, size_t NumIndicesOffset) = 0;
|
||||
virtual void RenderBorderTiles(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, int JumpIndex, unsigned int DrawNum) = 0;
|
||||
virtual void RenderBorderTileLines(int BufferContainerIndex, float *pColor, char *pIndexBufferOffset, float *pOffset, float *pDir, unsigned int IndexDrawNum, unsigned int RedrawNum) = 0;
|
||||
virtual void RenderQuadLayer(int BufferContainerIndex, SQuadRenderInfo *pQuadInfo, int QuadNum, int QuadOffset) = 0;
|
||||
|
@ -315,7 +335,8 @@ public:
|
|||
virtual void DeleteBufferContainer(int ContainerIndex, bool DestroyAllBO = true) = 0;
|
||||
virtual void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) = 0;
|
||||
|
||||
virtual void GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch) = 0;
|
||||
// returns true if the driver age type is supported, passing BACKEND_TYPE_AUTO for BackendType will query the values for the currently used backend
|
||||
virtual bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) = 0;
|
||||
virtual bool IsConfigModernAPI() = 0;
|
||||
virtual bool IsTileBufferingEnabled() = 0;
|
||||
virtual bool IsQuadBufferingEnabled() = 0;
|
||||
|
@ -440,6 +461,7 @@ public:
|
|||
virtual void NotifyWindow() = 0;
|
||||
|
||||
// be aware that this function should only be called from the graphics thread, and even then you should really know what you are doing
|
||||
// this function always returns the pixels in RGB
|
||||
virtual TGLBackendReadPresentedImageData &GetReadPresentedImageDataFuncUnsafe() = 0;
|
||||
|
||||
virtual SWarning *GetCurWarning() = 0;
|
||||
|
|
|
@ -178,7 +178,7 @@ MACRO_CONFIG_INT(DbgCurl, dbg_curl, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "D
|
|||
MACRO_CONFIG_INT(DbgPref, dbg_pref, 0, 0, 1, CFGFLAG_SERVER, "Performance outputs")
|
||||
MACRO_CONFIG_INT(DbgGraphs, dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
|
||||
MACRO_CONFIG_INT(DbgHitch, dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
|
||||
MACRO_CONFIG_INT(DbgGfx, dbg_gfx, 0, 0, 4, CFGFLAG_CLIENT, "Show graphic library warnings and errors, if the GPU supports it (0: none, 1: minimal, 2: affects performance, 3: verbose, 4: all")
|
||||
MACRO_CONFIG_INT(DbgGfx, dbg_gfx, 0, 0, 4, CFGFLAG_CLIENT, "Show graphic library warnings and errors, if the GPU supports it (0: none, 1: minimal, 2: affects performance, 3: verbose, 4: all)")
|
||||
#ifdef CONF_DEBUG
|
||||
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress systems (Debug build only)")
|
||||
MACRO_CONFIG_INT(DbgStressNetwork, dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress network (Debug build only)")
|
||||
|
@ -418,7 +418,7 @@ MACRO_CONFIG_STR(Gfx3DTextureAnalysisRenderer, gfx_3d_texture_analysis_renderer,
|
|||
MACRO_CONFIG_STR(Gfx3DTextureAnalysisVersion, gfx_3d_texture_analysis_version, 128, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The version on which the analysis was performed")
|
||||
|
||||
MACRO_CONFIG_STR(GfxGPUName, gfx_gpu_name, 256, "auto", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The GPU's name, which will be selected by the backend. (if supported by the backend)")
|
||||
MACRO_CONFIG_STR(GfxBackend, gfx_backend, 256, "auto", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The backend to use (e.g. opengl or vulkan)")
|
||||
MACRO_CONFIG_STR(GfxBackend, gfx_backend, 256, "OpenGL", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The backend to use (e.g. OpenGL or Vulkan)")
|
||||
MACRO_CONFIG_INT(GfxRenderThreadCount, gfx_render_thread_count, 3, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Number of threads the backend can use for rendering. (note: the value can be ignored by the backend)")
|
||||
|
||||
MACRO_CONFIG_INT(GfxDriverIsBlocked, gfx_driver_is_blocked, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "If 1, the current driver is in a blocked error state.")
|
||||
|
|
|
@ -844,6 +844,7 @@ void CMapLayers::OnMapLoad()
|
|||
// then create the buffer container
|
||||
SBufferContainerInfo ContainerInfo;
|
||||
ContainerInfo.m_Stride = (DoTextureCoords ? (sizeof(float) * 2 + sizeof(vec3)) : 0);
|
||||
ContainerInfo.m_VertBufferBindingIndex = BufferObjectIndex;
|
||||
ContainerInfo.m_Attributes.emplace_back();
|
||||
SBufferContainerInfo::SAttribute *pAttr = &ContainerInfo.m_Attributes.back();
|
||||
pAttr->m_DataTypeCount = 2;
|
||||
|
@ -946,6 +947,7 @@ void CMapLayers::OnMapLoad()
|
|||
// then create the buffer container
|
||||
SBufferContainerInfo ContainerInfo;
|
||||
ContainerInfo.m_Stride = (Textured ? (sizeof(STmpQuadTextured) / 4) : (sizeof(STmpQuad) / 4));
|
||||
ContainerInfo.m_VertBufferBindingIndex = BufferObjectIndex;
|
||||
ContainerInfo.m_Attributes.emplace_back();
|
||||
SBufferContainerInfo::SAttribute *pAttr = &ContainerInfo.m_Attributes.back();
|
||||
pAttr->m_DataTypeCount = 4;
|
||||
|
@ -1401,6 +1403,17 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
|
|||
Rot = aChannels[2] / 180.0f * pi;
|
||||
}
|
||||
|
||||
bool NeedsFlush = QuadsRenderCount == gs_GraphicsMaxQuadsRenderCount || !(aColor[3] > 0);
|
||||
|
||||
if(NeedsFlush)
|
||||
{
|
||||
// render quads of the current offset directly(cancel batching)
|
||||
Graphics()->RenderQuadLayer(Visuals.m_BufferContainerIndex, &s_QuadRenderInfo[0], QuadsRenderCount, CurQuadOffset);
|
||||
QuadsRenderCount = 0;
|
||||
// since this quad is ignored, the offset is the next quad
|
||||
CurQuadOffset = i + 1;
|
||||
}
|
||||
|
||||
if(aColor[3] > 0)
|
||||
{
|
||||
SQuadRenderInfo &QInfo = s_QuadRenderInfo[QuadsRenderCount++];
|
||||
|
@ -1409,14 +1422,6 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
|
|||
QInfo.m_aOffsets[1] = OffsetY;
|
||||
QInfo.m_Rotation = Rot;
|
||||
}
|
||||
else
|
||||
{
|
||||
// render quads of the current offset directly(cancel batching)
|
||||
Graphics()->RenderQuadLayer(Visuals.m_BufferContainerIndex, &s_QuadRenderInfo[0], QuadsRenderCount, CurQuadOffset);
|
||||
QuadsRenderCount = 0;
|
||||
// since this quad is ignored, the offset is the next quad
|
||||
CurQuadOffset = i + 1;
|
||||
}
|
||||
}
|
||||
Graphics()->RenderQuadLayer(Visuals.m_BufferContainerIndex, &s_QuadRenderInfo[0], QuadsRenderCount, CurQuadOffset);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <array>
|
||||
|
||||
CMenusKeyBinder CMenus::m_Binder;
|
||||
|
||||
CMenusKeyBinder::CMenusKeyBinder()
|
||||
|
@ -1100,9 +1102,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
static CVideoMode s_aModes[MAX_RESOLUTIONS];
|
||||
static int s_NumNodes = Graphics()->GetVideoModes(s_aModes, MAX_RESOLUTIONS, g_Config.m_GfxScreen);
|
||||
static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples;
|
||||
static int s_GfxModernGLVersion = Graphics()->IsConfigModernAPI();
|
||||
static int s_GfxEnableTextureUnitOptimization = g_Config.m_GfxEnableTextureUnitOptimization;
|
||||
static int s_GfxUsePreinitBuffer = g_Config.m_GfxUsePreinitBuffer;
|
||||
static bool s_GfxBackendChanged = false;
|
||||
static int s_GfxHighdpi = g_Config.m_GfxHighdpi;
|
||||
static int s_InitDisplayAllVideoModes = g_Config.m_GfxDisplayAllVideoModes;
|
||||
|
||||
|
@ -1185,6 +1185,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
aWindowModeIDs[i] = &s_aWindowModeIDs[i];
|
||||
static int s_WindowModeDropDownState = 0;
|
||||
|
||||
static int s_OldSelectedBackend = -1;
|
||||
|
||||
OldSelected = (g_Config.m_GfxFullscreen ? (g_Config.m_GfxFullscreen == 1 ? 4 : (g_Config.m_GfxFullscreen == 2 ? 3 : 2)) : (g_Config.m_GfxBorderless ? 1 : 0));
|
||||
|
||||
const int NewWindowMode = RenderDropDown(s_WindowModeDropDownState, &MainView, OldSelected, aWindowModeIDs, pWindowModes, s_NumWindowMode, &s_NumWindowMode, s_ScrollValueDrop);
|
||||
|
@ -1244,46 +1246,6 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
if(DoButton_CheckBox(&g_Config.m_GfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button))
|
||||
g_Config.m_GfxHighDetail ^= 1;
|
||||
|
||||
bool IsModernGL = Graphics()->IsConfigModernAPI();
|
||||
|
||||
// only promote modern GL in menu settings if the driver isn't on the blocklist already
|
||||
if(g_Config.m_GfxDriverIsBlocked == 0)
|
||||
{
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxGLMajor, Localize("Use modern OpenGL"), IsModernGL, &Button))
|
||||
{
|
||||
CheckSettings = true;
|
||||
if(IsModernGL)
|
||||
{
|
||||
Graphics()->GetDriverVersion(GRAPHICS_DRIVER_AGE_TYPE_DEFAULT, g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch);
|
||||
IsModernGL = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Graphics()->GetDriverVersion(GRAPHICS_DRIVER_AGE_TYPE_MODERN, g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch);
|
||||
IsModernGL = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(IsModernGL)
|
||||
{
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxUsePreinitBuffer, Localize("Preinit VBO (iGPUs only)"), g_Config.m_GfxUsePreinitBuffer, &Button))
|
||||
{
|
||||
CheckSettings = true;
|
||||
g_Config.m_GfxUsePreinitBuffer ^= 1;
|
||||
}
|
||||
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxEnableTextureUnitOptimization, Localize("Multiple texture units (disable for macOS)"), g_Config.m_GfxEnableTextureUnitOptimization, &Button))
|
||||
{
|
||||
CheckSettings = true;
|
||||
g_Config.m_GfxEnableTextureUnitOptimization ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxHighdpi, Localize("Use high DPI"), g_Config.m_GfxHighdpi, &Button))
|
||||
{
|
||||
|
@ -1291,16 +1253,6 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
g_Config.m_GfxHighdpi ^= 1;
|
||||
}
|
||||
|
||||
// check if the new settings require a restart
|
||||
if(CheckSettings)
|
||||
{
|
||||
m_NeedRestartGraphics = !(s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
|
||||
s_GfxModernGLVersion == (int)IsModernGL &&
|
||||
s_GfxUsePreinitBuffer == g_Config.m_GfxUsePreinitBuffer &&
|
||||
s_GfxEnableTextureUnitOptimization == g_Config.m_GfxEnableTextureUnitOptimization &&
|
||||
s_GfxHighdpi == g_Config.m_GfxHighdpi);
|
||||
}
|
||||
|
||||
MainView.HSplitTop(20.0f, &Label, &MainView);
|
||||
Label.VSplitLeft(160.0f, &Label, &Button);
|
||||
if(g_Config.m_GfxRefreshRate)
|
||||
|
@ -1322,13 +1274,143 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
MainView.y = HSLBar.y;
|
||||
MainView.h = MainView.h - MainView.y;
|
||||
|
||||
// Backend list
|
||||
struct SMenuBackendInfo
|
||||
{
|
||||
int m_Major = 0;
|
||||
int m_Minor = 0;
|
||||
int m_Patch = 0;
|
||||
const char *m_pBackendName = "";
|
||||
bool m_Found = false;
|
||||
};
|
||||
std::array<std::array<SMenuBackendInfo, EGraphicsDriverAgeType::GRAPHICS_DRIVER_AGE_TYPE_COUNT>, EBackendType::BACKEND_TYPE_COUNT> aaSupportedBackends{};
|
||||
uint32_t FoundBackendCount = 0;
|
||||
for(uint32_t i = 0; i < BACKEND_TYPE_COUNT; ++i)
|
||||
{
|
||||
if(EBackendType(i) == BACKEND_TYPE_AUTO)
|
||||
continue;
|
||||
for(uint32_t n = 0; n < GRAPHICS_DRIVER_AGE_TYPE_COUNT; ++n)
|
||||
{
|
||||
auto &Info = aaSupportedBackends[i][n];
|
||||
if(Graphics()->GetDriverVersion(EGraphicsDriverAgeType(n), Info.m_Major, Info.m_Minor, Info.m_Patch, Info.m_pBackendName, EBackendType(i)))
|
||||
{
|
||||
// don't count blocked opengl drivers
|
||||
if(EBackendType(i) != BACKEND_TYPE_OPENGL || EGraphicsDriverAgeType(n) == GRAPHICS_DRIVER_AGE_TYPE_LEGACY || g_Config.m_GfxDriverIsBlocked == 0)
|
||||
{
|
||||
Info.m_Found = true;
|
||||
++FoundBackendCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(FoundBackendCount > 1)
|
||||
{
|
||||
MainView.HSplitTop(10.0f, nullptr, &MainView);
|
||||
MainView.HSplitTop(20.0f, &Text, &MainView);
|
||||
UI()->DoLabelScaled(&Text, Localize("Renderer"), 16.0f, TEXTALIGN_CENTER);
|
||||
|
||||
static float s_ScrollValueDropBackend = 0;
|
||||
static int s_BackendDropDownState = 0;
|
||||
|
||||
static std::vector<std::unique_ptr<int>> vBackendIDs;
|
||||
static std::vector<const void *> vBackendIDPtrs;
|
||||
static std::vector<std::string> vBackendIDNames;
|
||||
static std::vector<const char *> vBackendIDNamesCStr;
|
||||
static std::vector<SMenuBackendInfo> vBackendInfos;
|
||||
|
||||
size_t BackendCount = FoundBackendCount + 1;
|
||||
vBackendIDs.resize(BackendCount);
|
||||
vBackendIDPtrs.resize(BackendCount);
|
||||
vBackendIDNames.resize(BackendCount);
|
||||
vBackendIDNamesCStr.resize(BackendCount);
|
||||
vBackendInfos.resize(BackendCount);
|
||||
|
||||
char aTmpBackendName[256];
|
||||
|
||||
auto IsInfoDefault = [](const SMenuBackendInfo &CheckInfo) {
|
||||
return str_comp_nocase(CheckInfo.m_pBackendName, "OpenGL") == 0 && CheckInfo.m_Major == 3 && CheckInfo.m_Minor == 0 && CheckInfo.m_Patch == 0;
|
||||
};
|
||||
|
||||
int OldSelectedBackend = -1;
|
||||
uint32_t CurCounter = 0;
|
||||
for(uint32_t i = 0; i < BACKEND_TYPE_COUNT; ++i)
|
||||
{
|
||||
for(uint32_t n = 0; n < GRAPHICS_DRIVER_AGE_TYPE_COUNT; ++n)
|
||||
{
|
||||
auto &Info = aaSupportedBackends[i][n];
|
||||
if(Info.m_Found)
|
||||
{
|
||||
if(vBackendIDs[CurCounter].get() == nullptr)
|
||||
vBackendIDs[CurCounter] = std::make_unique<int>();
|
||||
vBackendIDPtrs[CurCounter] = vBackendIDs[CurCounter].get();
|
||||
|
||||
{
|
||||
bool IsDefault = IsInfoDefault(Info);
|
||||
str_format(aTmpBackendName, sizeof(aTmpBackendName), "%s (%d.%d.%d)%s%s", Info.m_pBackendName, Info.m_Major, Info.m_Minor, Info.m_Patch, IsDefault ? " - " : "", IsDefault ? Localize("default") : "");
|
||||
vBackendIDNames[CurCounter] = aTmpBackendName;
|
||||
vBackendIDNamesCStr[CurCounter] = vBackendIDNames[CurCounter].c_str();
|
||||
if(str_comp_nocase(Info.m_pBackendName, g_Config.m_GfxBackend) == 0 && g_Config.m_GfxGLMajor == Info.m_Major && g_Config.m_GfxGLMinor == Info.m_Minor && g_Config.m_GfxGLPatch == Info.m_Patch)
|
||||
{
|
||||
OldSelectedBackend = CurCounter;
|
||||
}
|
||||
|
||||
vBackendInfos[CurCounter] = Info;
|
||||
}
|
||||
++CurCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(OldSelectedBackend != -1)
|
||||
{
|
||||
// no custom selected
|
||||
BackendCount -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// custom selected one
|
||||
if(vBackendIDs[CurCounter].get() == nullptr)
|
||||
vBackendIDs[CurCounter] = std::make_unique<int>();
|
||||
vBackendIDPtrs[CurCounter] = vBackendIDs[CurCounter].get();
|
||||
|
||||
str_format(aTmpBackendName, sizeof(aTmpBackendName), "%s (%s %d.%d.%d)", Localize("custom"), g_Config.m_GfxBackend, g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch);
|
||||
vBackendIDNames[CurCounter] = aTmpBackendName;
|
||||
vBackendIDNamesCStr[CurCounter] = vBackendIDNames[CurCounter].c_str();
|
||||
OldSelectedBackend = CurCounter;
|
||||
|
||||
vBackendInfos[CurCounter].m_pBackendName = "custom";
|
||||
vBackendInfos[CurCounter].m_Major = g_Config.m_GfxGLMajor;
|
||||
vBackendInfos[CurCounter].m_Minor = g_Config.m_GfxGLMinor;
|
||||
vBackendInfos[CurCounter].m_Patch = g_Config.m_GfxGLPatch;
|
||||
}
|
||||
|
||||
if(s_OldSelectedBackend == -1)
|
||||
s_OldSelectedBackend = OldSelectedBackend;
|
||||
|
||||
static int s_BackendCount = 0;
|
||||
s_BackendCount = BackendCount;
|
||||
|
||||
const int NewBackend = RenderDropDown(s_BackendDropDownState, &MainView, OldSelectedBackend, vBackendIDPtrs.data(), vBackendIDNamesCStr.data(), s_BackendCount, &s_BackendCount, s_ScrollValueDropBackend);
|
||||
if(OldSelectedBackend != NewBackend)
|
||||
{
|
||||
str_copy(g_Config.m_GfxBackend, vBackendInfos[NewBackend].m_pBackendName, sizeof(g_Config.m_GfxBackend));
|
||||
g_Config.m_GfxGLMajor = vBackendInfos[NewBackend].m_Major;
|
||||
g_Config.m_GfxGLMinor = vBackendInfos[NewBackend].m_Minor;
|
||||
g_Config.m_GfxGLPatch = vBackendInfos[NewBackend].m_Patch;
|
||||
|
||||
CheckSettings = true;
|
||||
s_GfxBackendChanged = s_OldSelectedBackend != NewBackend;
|
||||
}
|
||||
}
|
||||
|
||||
// GPU list
|
||||
const auto &GPUList = Graphics()->GetGPUs();
|
||||
if(GPUList.m_GPUs.size() > 1)
|
||||
{
|
||||
MainView.HSplitTop(10.0f, nullptr, &MainView);
|
||||
MainView.HSplitTop(20.0f, &Text, &MainView);
|
||||
UI()->DoLabelScaled(&Text, Localize("Graphic cards"), 16.0f, TEXTALIGN_CENTER);
|
||||
UI()->DoLabelScaled(&Text, Localize("Graphics cards"), 16.0f, TEXTALIGN_CENTER);
|
||||
|
||||
static float s_ScrollValueDropGPU = 0;
|
||||
static int s_GPUDropDownState = 0;
|
||||
|
@ -1348,7 +1430,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
for(size_t i = 0; i < GPUCount; ++i)
|
||||
{
|
||||
if(vGPUIDs[i].get() == nullptr)
|
||||
vGPUIDs[i] = std::unique_ptr<int>(new int());
|
||||
vGPUIDs[i] = std::make_unique<int>();
|
||||
vGPUIDPtrs[i] = vGPUIDs[i].get();
|
||||
if(i == 0)
|
||||
{
|
||||
|
@ -1381,6 +1463,14 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
str_copy(g_Config.m_GfxGPUName, GPUList.m_GPUs[NewGPU - 1].m_Name, sizeof(g_Config.m_GfxGPUName));
|
||||
}
|
||||
}
|
||||
|
||||
// check if the new settings require a restart
|
||||
if(CheckSettings)
|
||||
{
|
||||
m_NeedRestartGraphics = !(s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
|
||||
!s_GfxBackendChanged &&
|
||||
s_GfxHighdpi == g_Config.m_GfxHighdpi);
|
||||
}
|
||||
}
|
||||
|
||||
void CMenus::RenderSettingsSound(CUIRect MainView)
|
||||
|
|
|
@ -231,7 +231,7 @@ void CParticles::RenderGroup(int Group)
|
|||
// the current position, respecting the size, is inside the viewport, render it, else ignore
|
||||
if(ParticleIsVisibleOnScreen(p, Size))
|
||||
{
|
||||
if(LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != m_aParticles[i].m_Color.a || LastQuadOffset != QuadOffset)
|
||||
if((size_t)CurParticleRenderCount == gs_GraphicsMaxParticlesRenderCount || LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != m_aParticles[i].m_Color.a || LastQuadOffset != QuadOffset)
|
||||
{
|
||||
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[LastQuadOffset - SPRITE_PART_SLICE]);
|
||||
Graphics()->RenderQuadContainerAsSpriteMultiple(m_ParticleQuadContainerIndex, LastQuadOffset, CurParticleRenderCount, s_aParticleRenderInfo);
|
||||
|
|
|
@ -5666,7 +5666,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
|
|||
void CEditor::Render()
|
||||
{
|
||||
// basic start
|
||||
Graphics()->Clear(1.0f, 0.0f, 1.0f);
|
||||
Graphics()->Clear(0.0f, 0.0f, 0.0f);
|
||||
CUIRect View = *UI()->Screen();
|
||||
UI()->MapScreen();
|
||||
|
||||
|
|
Loading…
Reference in a new issue