1
1

Compare commits

...

92 Commits

Author SHA1 Message Date
b40787115b GHOST: Device discovery API.
Still wip.
2021-11-23 15:29:11 +01:00
fc502a8710 Merge branch 'temp-ghost-vulkan-backend' into tmp-vulkan 2021-11-23 14:01:01 +01:00
d944b969f0 Merge branch 'master' into temp-ghost-vulkan-backend 2021-11-23 13:23:50 +01:00
8e43757834 GHOST: Vulkan Backend.
This adds a vulkan backend to GHOST. Still WIP, we should decide what
would be the minimum requirement to land in master.

Differential Revision: https://developer.blender.org/D13155
2021-11-12 09:22:56 +01:00
b65df10346 Merge branch 'master' into tmp-vulkan 2021-11-09 10:34:41 +01:00
8bf8db8ca2 Vulkan: Add support for wayland. 2021-07-06 10:42:45 +02:00
5bd7a2c416 Fix merge conflict. Missing parameter when creating EGLContext. 2021-07-06 09:02:29 +02:00
8c3e8d0eb6 Vulkan: Clean-up platform build support
This polishes up the build support for WITH_VULKAN
the find_package calls were moved to the appropriate
place in the platform cmake files.

For windows the required binaries are copied to
the binary folder.

Windows support relies on D11678 landing and
libraries being added to SVN and will automatically
disable WITH_VULKAN when they are not found.
2021-06-30 18:01:36 -06:00
8bfdec76c0 Vulkan: Fix uninitialized ram in VKTexture
The ram being uninitialised caused issues in
VKTexture's destructor which tests for
VK_NULL_HANDLE. The nvidia driver did not
enjoy being fed a bogus pointer and crashed.
2021-06-30 10:53:00 -06:00
9cc5075680 Ghost: Fix unresolved merge conflict
Introduced by rBddd64ba0
2021-06-30 10:48:59 -06:00
2ea8725339 Vulkan: Retrieve platform information.
Retrieve device platform information for `GPUPlatformGlobal`.
As vulkan needs a physical device it was moved from the GPUBackend
constructor to an init method that is called when an initial context
is created.

Still need to find out how to extract the driver type.
2021-06-29 16:51:10 +02:00
a55bbedc06 Merge branch 'master' into tmp-vulkan 2021-06-29 09:59:34 +02:00
5d52da2e65 Vulkan: Compiler log parsing.
For the vulkan backend we control the compiler and therefore the log
parsing is much simpler then the OpenGL parsers.

This patch formats the log to a better readable/debuggable format so
developers can quickly detect what needs to be done.
2021-06-28 16:59:11 +02:00
25b341a4ae Vulkan: Fix double free of shader interface.
interface is allocated by a subclass but freed by the parent class.
Might consider a uniqueptr here.
2021-06-28 15:56:46 +02:00
dfa5bc25ae Vulkan: Enabled GPU tests. 2021-06-28 15:51:16 +02:00
ddd64ba03a Merge branch 'master' into tmp-vulkan 2021-06-28 15:46:45 +02:00
0b3caae8a7 Merge commit 'master@{1-day-ago}' into tmp-vulkan 2021-06-28 15:17:51 +02:00
b1d5950471 Merge commit 'master@{1-weeks-ago}' into tmp-vulkan 2021-06-28 15:04:27 +02:00
99886f91a9 Merge commit 'master@{2-weeks-ago}' into tmp-vulkan 2021-06-28 15:04:21 +02:00
fa00caba88 Merge commit 'master@{3-weeks-ago}' into tmp-vulkan 2021-06-28 14:57:20 +02:00
f853163a54 Merge commit 'master@{4-weeks-ago}' into tmp-vulkan 2021-06-28 14:47:30 +02:00
87492f93a4 Merge commit 'master@{5-weeks-ago}' into tmp-vulkan 2021-06-28 14:27:59 +02:00
6152113b45 Merge commit 'master@{6-weeks-ago}' into tmp-vulkan 2021-06-28 14:06:11 +02:00
2741a4106a Merge commit 'master@{7-weeks-ago}' into tmp-vulkan 2021-06-28 13:51:33 +02:00
3420792ea8 Merge commit 'master@{8-weeks-ago}' into tmp-vulkan 2021-06-28 13:35:48 +02:00
3eaddb4da8 Merge commit 'master@{9-weeks-ago}' into tmp-vulkan 2021-06-28 13:35:39 +02:00
1a85a68a5e Merge commit 'master@{10-weeks-ago}' into tmp-vulkan 2021-06-28 13:25:24 +02:00
adba79a04f Merge commit 'master@{11-weeks-ago}' into tmp-vulkan 2021-06-28 13:15:10 +02:00
c73894ea5b Merge commit 'master@{12-weeks-ago}' into tmp-vulkan 2021-06-28 13:05:21 +02:00
48360afb10 Merge commit 'master@{3-months-ago}' into tmp-vulkan 2021-06-28 12:37:05 +02:00
0493a32803 Initial SpirV log parsing.
Still work in progress.
2021-06-25 16:53:07 +02:00
79346fd72e Moved shader compilation flag to cmake.
Migration of the shaders can take a long time. During this time it
you won't be able to start most GPU tests or Blender. This switch
will enable the compilation of the shader to other developments
can still happen.

`WITH_VULKAN_SHADER_COMPILATION` Default is OFF. Enable when migrating
shaders.
2021-06-25 16:01:05 +02:00
44c875f59a Vulkan: Patched gl_VertexID to gl_VertexIndex. 2021-06-25 15:52:02 +02:00
a68be3b3c2 ShaderCompiler: Use CPP strings to improve API. 2021-06-25 15:28:19 +02:00
c124606d70 Vulkan: Compile Shader Modules.
Shaders are expected to fail as they need to be converted to Vulkan. Dy default the compilation is turned off. Enable VULKAN_SHADER_COMPILATION to activate shader module compilation.
2021-06-25 14:38:50 +02:00
975b09e3e7 ShaderCompiler: Split code per target type.
No functional changes.
2021-06-25 11:01:59 +02:00
15ac620204 Added Vulkan test cases.
Added counterparts of the shader test cases for vulkan.
Fixing an issue where the OpenGL context was created when using a vulkan
backend.
2021-06-25 10:48:07 +02:00
983f61e9c5 Add test case to compile builtin shaders.
When using the vulkan backend it crashes. Will look into this later this
week.
2021-06-23 17:07:33 +02:00
ed959cd912 Cleanup: Added license headers. 2021-06-23 14:14:14 +02:00
193a17474e Added shader compiler abstration.
The shader_compiler is an abstration layer for in case we need to switch
between other shader compilers in the future.

The shader compiler uses a CPP Api as it will only be accessed from GPU
module.

```
  const char *source = "#version 450\nvoid main() {}";
  shader_compiler::Compiler *compiler = shader_compiler::Compiler::create_default();
  shader_compiler::Job job;
  job.source = source;
  job.name = __func__;
  job.source_type = shader_compiler::SourceType::GlslComputeShader;
  job.compilation_target = shader_compiler::TargetType::SpirV;

  shader_compiler::Result *result = compiler->compile(job);
  EXPECT_EQ(result->type, shader_compiler::TargetType::SpirV);
  EXPECT_EQ(result->status_code, shader_compiler::StatusCode::Ok);
  EXPECT_GT(result->bin.size(), 0);
  EXPECT_EQ(result->error_log, "");
  delete result;
  delete compiler;
```

The CMakeFiles need some attention as it currently works when linking to
the shaderlib_combined. On linux it picks up the shaderlib from the
vulkan SDK, eventually it needs to pick up from our prebuild libraries.
2021-06-23 14:04:44 +02:00
5b246fd4b3 Vulkan: Fix offscreen context creation.
On linux both the display and window should be available to create a
window surface. Only the display was checked making it fail later on
when creating a present queue.
2021-06-22 09:22:28 +02:00
f7d7a5aad7 Cleanup: Silence compilation warning. 2021-06-21 15:13:09 +02:00
8b68ee3a17 Vulkan: Fix compilation error. 2021-06-18 15:12:26 +02:00
230b24159e Vulkan: remove VK_ERROR_INCOMPATIBLE_VERSION_KHR
It has been removed from the SDK since version 1.1.18.
2021-06-18 15:10:56 +02:00
a5a01cc0c3 Performance: GPU Batch Baseline TestCase.
When using a dense mesh and transforming a small number of verts the mesh received a copy-on-write signal. This will free all GPU batches. No reuse is currently possible.
This patch adds a test case that can be used as a baseline to optimize the cache construction in the draw module.

Differential Revision: https://developer.blender.org/D11255
2021-05-17 11:16:27 +02:00
e7b3a7028b Merge branch 'master' into tmp-vulkan 2021-03-11 20:17:32 +01:00
fced6f19be Attempt 2 to silence warning. 2021-03-12 00:41:13 +05:30
402e19ddc8 Attempt to silence warning. 2021-03-12 00:37:55 +05:30
af2bc8be40 Vulkan: Implementation of VKTexture
Implementation is a first draft and needs to be refined over time.
2021-03-11 16:56:33 +01:00
72bce1be8e Vulkan: Bypass BGL when running with the vulkan backend
This avoids a crash at startup.
2021-03-11 16:55:12 +01:00
d390f01e48 Vulkan: Fix crash because of null active framebuffer 2021-03-11 16:02:01 +01:00
0956a5134a Vulkan: Add allocator and command pool to VKContext
This allows memory backed object (Textures, VertexBuffers, ...) to be created.
Also adds functions for one time use command buffers.
2021-03-11 16:01:27 +01:00
9a08daae92 GPUContext: Pass GHOST context handle for GPUContext creation
This is because we need to have a direct reference to the context to get
the vulkan resources.
2021-03-11 15:38:39 +01:00
dd4405121c GHOST: Window: Add drawing context handle getter
This is in order to retrieve the vulkan/gl context from a window handle.
2021-03-11 14:53:06 +01:00
b996cc6440 GHOST: Vulkan: Add compile time option to bypass required features
This makes it possible to test the vulkan implementation on all platforms
(mainly MacOS) even if all required features are not supported.
2021-03-11 14:14:14 +01:00
0bcd24c0c4 Vulkan: Add basic implementation of textures
Adds basic texture creation and update as well as texture view support
for attachements.
2021-03-11 13:41:05 +01:00
12e88ee722 Vulkan: Fix compilation after merging 2021-03-11 13:37:39 +01:00
b908c3fa0a VulkanMemoryAllocator: Add new extern library
This library is used to simplify memory allocation / management for Vulkan.
2021-03-11 13:02:02 +01:00
ef8e53c15b GHOST: Vulkan: Fix compilation error 2021-03-07 17:50:43 +01:00
639829ea1a Merge branch 'master' into tmp-vulkan 2021-03-07 17:28:39 +01:00
0ef5c14de0 Merge branch 'master' into tmp-vulkan
# Conflicts:
#	source/blender/blenkernel/BKE_global.h
#	source/blender/gpu/intern/gpu_context.cc
#	source/blender/windowmanager/intern/wm_window.c
#	source/creator/creator_args.c
2021-03-07 17:22:48 +01:00
26fd1c71e1 VK: Initial Base implementation 2020-11-13 22:30:40 +01:00
de062ffd10 Merge branch 'master' into tmp-vulkan
# Conflicts:
#	CMakeLists.txt
2020-09-16 22:05:35 +02:00
fc0f409911 VK: Avoid asserts in debug builds. 2020-09-16 22:04:03 +02:00
c72e6c25d7 GHOST: X11: Enable debug context for vulkan in offscreen contexts 2020-09-16 22:03:34 +02:00
816bd8bed6 GHOST: Vulkan: Rework support for MSVC
This removes designated initializer because not supported by MSVC for our
current C++ version.

Fixes some other compile errors and add usage of the `ContextVK` context in
the Win32 backend.
2020-09-16 22:01:04 +02:00
47613a40f5 VK: OSX: Use debug context and use METAL_SURFACE instead of MACOS_SURFACE 2020-09-13 03:37:35 +02:00
ea5a70973d VK: Make the placeholder backend work
Now we get a green window without a crash
2020-09-13 03:36:22 +02:00
70c0f652de Cleanup: Vulkan: Unused header and avoid duplicated code 2020-09-13 01:53:43 +02:00
e70dcde88b Vulkan: OSX: Use vulkan context for offscreen context 2020-09-13 01:52:57 +02:00
6d82ae3581 Vulkan: Fix compilation on OSX
This was caused by an internal metal type. The fix is a
workaround since I could not find the right solution.
2020-09-13 01:52:03 +02:00
99fc68bf6a GPU: Add Vulkan empty implementation
This does not even builds! WHY?
2020-09-13 00:44:15 +02:00
3efdb3f232 GHOST: Vulkan: Add MoltenVK Backend on osx
This is still highly experimental.
2020-09-13 00:43:43 +02:00
193cebd3c2 Merge branch 'master' into tmp-vulkan 2020-09-12 19:50:22 +02:00
bdeca237ff Merge branch 'master' into tmp-vulkan
# Conflicts:
#	CMakeLists.txt
#	intern/ghost/GHOST_C-api.h
#	intern/ghost/GHOST_ISystem.h
#	intern/ghost/intern/GHOST_C-api.cpp
#	intern/ghost/intern/GHOST_System.h
#	intern/ghost/intern/GHOST_SystemCocoa.h
#	intern/ghost/intern/GHOST_SystemCocoa.mm
#	intern/ghost/intern/GHOST_SystemNULL.h
#	intern/ghost/intern/GHOST_SystemSDL.cpp
#	intern/ghost/intern/GHOST_SystemSDL.h
#	intern/ghost/intern/GHOST_SystemWayland.cpp
#	intern/ghost/intern/GHOST_SystemWayland.h
#	intern/ghost/intern/GHOST_SystemWin32.cpp
#	intern/ghost/intern/GHOST_SystemWin32.h
#	intern/ghost/intern/GHOST_SystemX11.cpp
#	intern/ghost/intern/GHOST_SystemX11.h
#	source/blender/blenkernel/BKE_global.h
#	source/blender/windowmanager/intern/wm_window.c
2020-09-12 19:05:59 +02:00
a08d242acd GPU: Vulkan: Add creator arg to enable vulkan drawing
The creator arg is meant to support more than vulkan or opengl.

This currently fails because there is no GPU backend separation.

Note that we use G.debug with a debug flag to know what context type to
create. This will need to be cleaned later.
2020-07-24 22:08:37 +02:00
5629ff5f69 GHOST: Vulkan: Support window resizing 2020-07-24 19:53:01 +02:00
eb23ecd1b3 GHOST: Vulkan: Style Cleanup 2020-07-24 18:51:08 +02:00
a02da40732 GHOST: Vulkan: Better debug messages 2020-07-24 18:30:05 +02:00
bd0c1d8c53 GHOST: Vulkan: Remove swap interval functions 2020-07-24 17:48:31 +02:00
73b585b0b2 GHOST: Vulkan: Add Test command buffers and sync primitives 2020-07-24 17:00:06 +02:00
b549b1f477 GHOST: Vulkan: Add ImageView, Framebuffer and default RenderPass 2020-07-24 02:13:40 +02:00
c155c10888 GHOST: Vulkan: Add swapchain creation 2020-07-24 00:42:44 +02:00
bc86701b58 Merge branch 'master' into tmp-vulkan 2020-07-23 16:41:42 +02:00
6dc1d823ba Ghost: Vulkan: Add surface creation 2020-07-23 17:05:17 +02:00
392e744ed5 Merge branch 'master' into tmp-vulkan 2020-07-23 15:11:46 +02:00
f56af0b899 GHOST: Vulkan: Add logical device creation 2020-07-20 14:02:05 +02:00
78cbcccf34 GHOST: Vulkan: Add physical device & queue family selection 2020-07-20 13:23:41 +02:00
b671b33871 GHOST: Vulkan: Add instance creation 2020-07-19 22:59:57 +02:00
be9dc493a4 GHOST: Add barebone vulkan context for X11
The context does nothing. For now it always fail and will always
fallback to opengl.
2020-07-19 02:53:07 +02:00
8dec7e5219 Vulkan: Add CMake inclusion
We need to bump minimum version to 3.7 for FindVulkan.cmake to be
available.
2020-07-19 02:53:06 +02:00
b79e7f92bf Fix T78977 GPU: blf fonts are not gamma corrected 2020-07-18 04:25:56 +02:00
130 changed files with 24942 additions and 209 deletions

View File

@@ -514,9 +514,13 @@ if(UNIX AND NOT APPLE)
endif()
# Vulkan
option(WITH_VULKAN "Enable Vulkan backend (Experimental)" OFF)
option(WITH_VULKAN_SHADER_COMPILATION "Temporary flag to enable vulkan shader compilation needed to continue development during the migration of GLSL to Vulkan." OFF)
# OpenGL
option(WITH_OPENGL "When off limits visibility of the opengl headers to just bf_gpu and gawain (temporary option for development purposes)" ON)
option(WITH_OPENGL "When off limits visibility of the opengl headers to just bf_gpu (temporary option for development purposes)" ON)
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
@@ -526,6 +530,7 @@ mark_as_advanced(
WITH_GLEW_ES
WITH_GL_EGL
WITH_GL_PROFILE_ES20
WITH_VULKAN_SHADER_COMPILATION
)
if(WIN32)
@@ -1126,6 +1131,18 @@ if(WITH_OPENVDB)
list(APPEND OPENVDB_LIBRARIES ${BOOST_LIBRARIES} ${TBB_LIBRARIES})
endif()
#-----------------------------------------------------------------------------
# Configure Vulkan.
if(WITH_VULKAN)
list(APPEND BLENDER_GL_LIBRARIES ${Vulkan_LIBRARY})
add_definitions(-DWITH_VULKAN)
if(WITH_VULKAN_SHADER_COMPILATION)
add_definitions(-DWITH_VULKAN_SHADER_COMPILATION)
endif()
endif()
#-----------------------------------------------------------------------------
# Configure OpenGL.

View File

@@ -0,0 +1,66 @@
# - Find SHADERC library
# Find the native Haru includes and library
# This module defines
# SHADERC_INCLUDE_DIRS, where to find hpdf.h, set when
# SHADERC_INCLUDE_DIR is found.
# SHADERC_LIBRARIES, libraries to link against to use Haru.
# SHADERC_ROOT_DIR, The base directory to search for Haru.
# This can also be an environment variable.
# SHADERC_FOUND, If false, do not try to use Haru.
#
# also defined, but not for general use are
# SHADERC_LIBRARY, where to find the Haru library.
#=============================================================================
# Copyright 2021 Blender Foundation.
#
# Distributed under the OSI-approved BSD 3-Clause License,
# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If SHADERC_ROOT_DIR was defined in the environment, use it.
if(NOT SHADERC_ROOT_DIR AND NOT $ENV{SHADERC_ROOT_DIR} STREQUAL "")
set(SHADERC_ROOT_DIR $ENV{SHADERC_ROOT_DIR})
endif()
set(_shaderc_SEARCH_DIRS
${SHADERC_ROOT_DIR}
/opt/lib/haru
)
find_path(SHADERC_INCLUDE_DIR
NAMES
shaderc.hpp
HINTS
${_shaderc_SEARCH_DIRS}
PATH_SUFFIXES
include/shaderc
include
)
find_library(SHADERC_LIBRARY
NAMES
shaderc_combined
shaderc
HINTS
${_shaderc_SEARCH_DIRS}
PATH_SUFFIXES
lib64 lib
)
# Handle the QUIETLY and REQUIRED arguments and set SHADERC_FOUND to TRUE if
# all listed variables are TRUE.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ShaderC DEFAULT_MSG SHADERC_LIBRARY SHADERC_INCLUDE_DIR)
if(SHADERC_FOUND)
set(SHADERC_LIBRARIES ${SHADERC_LIBRARY})
set(SHADERC_INCLUDE_DIRS ${SHADERC_INCLUDE_DIR})
endif()
mark_as_advanced(
SHADERC_INCLUDE_DIR
SHADERC_LIBRARY
)
unset(_shaderc_SEARCH_DIRS)

View File

@@ -102,6 +102,11 @@ find_package_wrapper(ZLIB REQUIRED)
find_package_wrapper(Zstd REQUIRED)
find_package_wrapper(Freetype REQUIRED)
if(WITH_VULKAN)
find_package_wrapper(Vulkan REQUIRED)
find_package(ShaderC REQUIRED)
endif()
if(WITH_PYTHON)
# No way to set py35, remove for now.
# find_package(PythonLibs)

View File

@@ -874,5 +874,32 @@ if(WITH_HARU)
endif()
endif()
if(WITH_VULKAN)
if(EXISTS ${LIBDIR}/vulkan)
set(Vulkan_FOUND On)
set(Vulkan_ROOT_DIR ${LIBDIR}/vulkan)
set(Vulkan_INCLUDE_DIR ${Vulkan_ROOT_DIR}/include)
set(Vulkan_INCLUDE_DIRS ${Vulkan_INCLUDE_DIR})
set(Vulkan_LIBRARY ${Vulkan_ROOT_DIR}/lib/vulkan-1.lib)
set(Vulkan_LIBRARIES ${Vulkan_LIBRARY})
else()
message(WARNING "vulkan was not found, disabling WITH_VULKAN")
set(WITH_VULKAN OFF)
endif()
endif()
if(WITH_VULKAN)
if(EXISTS ${LIBDIR}/shaderc)
set(SHADERC_ROOT_DIR ${LIBDIR}/shaderc)
set(SHADERC_INCLUDE_DIR ${SHADERC_ROOT_DIR}/include)
set(SHADERC_INCLUDE_DIRS ${SHADERC_INCLUDE_DIR})
set(SHADERC_LIBRARY optimized ${SHADERC_ROOT_DIR}/lib/shaderc_shared.lib debug ${SHADERC_ROOT_DIR}/lib/shaderc_shared_d.lib)
set(SHADERC_LIBRARIES ${SHADERC_LIBRARY})
else()
message(WARNING "shaderc was not found, disabling WITH_VULKAN")
set(WITH_VULKAN OFF)
endif()
endif()
set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include)
set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib)

View File

@@ -116,3 +116,7 @@ endif()
if (WITH_COMPOSITOR)
add_subdirectory(smaa_areatex)
endif()
if(WITH_VULKAN)
add_subdirectory(vulkan_memory_allocator)
endif()

View File

@@ -0,0 +1,42 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2012, Blender Foundation
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
set(INC
.
)
set(INC_SYS
${Vulkan_INCLUDE_DIRS}
)
set(SRC
vk_mem_alloc_impl.cc
vk_mem_alloc.h
)
blender_add_lib(extern_vulkan_memory_allocator "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(extern_vulkan_memory_allocator
PRIVATE "-Wno-nullability-completeness"
)
endif()

View File

@@ -0,0 +1,19 @@
Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,5 @@
Project: VulkanMemoryAllocator
URL: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
License: MIT
Upstream version: 4b047fd
Local modifications: None

134
extern/vulkan_memory_allocator/README.md vendored Normal file
View File

@@ -0,0 +1,134 @@
# Vulkan Memory Allocator
Easy to integrate Vulkan memory allocation library.
**Documentation:** See [Vulkan Memory Allocator](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/) (generated from Doxygen-style comments in [src/vk_mem_alloc.h](src/vk_mem_alloc.h))
**License:** MIT. See [LICENSE.txt](LICENSE.txt)
**Changelog:** See [CHANGELOG.md](CHANGELOG.md)
**Product page:** [Vulkan Memory Allocator on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
**Build status:**
- Windows: [![Build status](https://ci.appveyor.com/api/projects/status/4vlcrb0emkaio2pn/branch/master?svg=true)](https://ci.appveyor.com/project/adam-sawicki-amd/vulkanmemoryallocator/branch/master)
- Linux: [![Build Status](https://travis-ci.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.svg?branch=master)](https://travis-ci.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
# Problem
Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several reasons:
- It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.
- There is additional level of indirection: `VkDeviceMemory` is allocated separately from creating `VkBuffer`/`VkImage` and they must be bound together.
- Driver must be queried for supported memory heaps and memory types. Different IHVs provide different types of it.
- It is recommended practice to allocate bigger chunks of memory and assign parts of them to particular resources.
# Features
This library can help game developers to manage memory allocations and resource creation by offering some higher-level functions:
1. Functions that help to choose correct and optimal memory type based on intended usage of the memory.
- Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.
2. Functions that allocate memory blocks, reserve and return parts of them (`VkDeviceMemory` + offset + size) to the user.
- Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, respects all the rules of alignment and buffer/image granularity.
3. Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.
Additional features:
- Well-documented - description of all functions and structures provided, along with chapters that contain general description and example code.
- Thread-safety: Library is designed to be used in multithreaded code. Access to a single device memory block referred by different buffers and textures (binding, mapping) is synchronized internally.
- Configuration: Fill optional members of CreateInfo structure to provide custom CPU memory allocator, pointers to Vulkan functions and other parameters.
- Customization: Predefine appropriate macros to provide your own implementation of all external facilities used by the library, from assert, mutex, and atomic, to vector and linked list.
- Support for memory mapping, reference-counted internally. Support for persistently mapped memory: Just allocate with appropriate flag and you get access to mapped pointer.
- Support for non-coherent memory. Functions that flush/invalidate memory. `nonCoherentAtomSize` is respected automatically.
- Support for resource aliasing (overlap).
- Support for sparse binding and sparse residency: Convenience functions that allocate or free multiple memory pages at once.
- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size) and allocate memory out of it.
- Linear allocator: Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
- Support for Vulkan 1.0, 1.1, 1.2.
- Support for extensions (and equivalent functionality included in new Vulkan versions):
- VK_EXT_memory_budget: Used internally if available to query for current usage and budget. If not available, it falls back to an estimation based on memory heap sizes.
- VK_KHR_dedicated_allocation: Just enable it and it will be used automatically by the library.
- VK_AMD_device_coherent_memory
- VK_KHR_buffer_device_address
- Defragmentation of GPU and CPU memory: Let the library move data around to free some memory blocks and make your allocations better compacted.
- Lost allocations: Allocate memory with appropriate flags and let the library remove allocations that are not used for many frames to make room for new ones.
- Statistics: Obtain detailed statistics about the amount of memory used, unused, number of allocated blocks, number of allocations etc. - globally, per memory heap, and per memory type.
- Debug annotations: Associate string with name or opaque pointer to your own data with every allocation.
- JSON dump: Obtain a string in JSON format with detailed map of internal state, including list of allocations and gaps between them.
- Convert this JSON dump into a picture to visualize your memory. See [tools/VmaDumpVis](tools/VmaDumpVis/README.md).
- Debugging incorrect memory usage: Enable initialization of all allocated memory with a bit pattern to detect usage of uninitialized or freed memory. Enable validation of a magic number before and after every allocation to detect out-of-bounds memory corruption.
- Record and replay sequence of calls to library functions to a file to check correctness, measure performance, and gather statistics.
# Prequisites
- Self-contained C++ library in single header file. No external dependencies other than standard C and C++ library and of course Vulkan. STL containers are not used by default.
- Public interface in C, in same convention as Vulkan API. Implementation in C++.
- Error handling implemented by returning `VkResult` error codes - same way as in Vulkan.
- Interface documented using Doxygen-style comments.
- Platform-independent, but developed and tested on Windows using Visual Studio. Continuous integration setup for Windows and Linux. Used also on Android, MacOS, and other platforms.
# Example
Basic usage of this library is very simple. Advanced features are optional. After you created global `VmaAllocator` object, a complete code needed to create a buffer may look like this:
```cpp
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = 65536;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VkBuffer buffer;
VmaAllocation allocation;
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
```
With this one function call:
1. `VkBuffer` is created.
2. `VkDeviceMemory` block is allocated if needed.
3. An unused region of the memory block is bound to this buffer.
`VmaAllocation` is an object that represents memory assigned to this buffer. It can be queried for parameters like Vulkan memory handle and offset.
# Binaries
The release comes with precompiled binary executables for "VulkanSample" application which contains test suite and "VmaReplay" tool. They are compiled using Visual Studio 2019, so they require appropriate libraries to work, including "MSVCP140.dll", "VCRUNTIME140.dll", "VCRUNTIME140_1.dll". If their launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), "x64" version.
# Read more
See **[Documentation](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/)**.
# Software using this library
- **[Detroit: Become Human](https://gpuopen.com/learn/porting-detroit-3/)**
- **[Vulkan Samples](https://github.com/LunarG/VulkanSamples)** - official Khronos Vulkan samples. License: Apache-style.
- **[Anvil](https://github.com/GPUOpen-LibrariesAndSDKs/Anvil)** - cross-platform framework for Vulkan. License: MIT.
- **[Filament](https://github.com/google/filament)** - physically based rendering engine for Android, Windows, Linux and macOS, from Google. Apache License 2.0.
- **[Atypical Games - proprietary game engine](https://developer.samsung.com/galaxy-gamedev/gamedev-blog/infinitejet.html)**
- **[Flax Engine](https://flaxengine.com/)**
- **[Lightweight Java Game Library (LWJGL)](https://www.lwjgl.org/)** - includes binding of the library for Java. License: BSD.
- **[PowerVR SDK](https://github.com/powervr-graphics/Native_SDK)** - C++ cross-platform 3D graphics SDK, from Imagination. License: MIT.
- **[Skia](https://github.com/google/skia)** - complete 2D graphic library for drawing Text, Geometries, and Images, from Google.
- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
- **[VK9](https://github.com/disks86/VK9)** - Direct3D 9 compatibility layer using Vulkan. Zlib lincese.
- **[vkDOOM3](https://github.com/DustinHLand/vkDOOM3)** - Vulkan port of GPL DOOM 3 BFG Edition. License: GNU GPL.
- **[vkQuake2](https://github.com/kondrak/vkQuake2)** - vanilla Quake 2 with Vulkan support. License: GNU GPL.
- **[Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers)** from ARM. License: MIT.
- **[RPCS3](https://github.com/RPCS3/rpcs3)** - PlayStation 3 emulator/debugger. License: GNU GPLv2.
[Many other projects on GitHub](https://github.com/search?q=AMD_VULKAN_MEMORY_ALLOCATOR_H&type=Code) and some game development studios that use Vulkan in their games.
# See also
- **[D3D12 Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator)** - equivalent library for Direct3D 12. License: MIT.
- **[Awesome Vulkan](https://github.com/vinjn/awesome-vulkan)** - a curated list of awesome Vulkan libraries, debuggers and resources.
- **[VulkanMemoryAllocator-Hpp](https://github.com/malte-v/VulkanMemoryAllocator-Hpp)** - C++ binding for this library. License: CC0-1.0.
- **[PyVMA](https://github.com/realitix/pyvma)** - Python wrapper for this library. Author: Jean-Sébastien B. (@realitix). License: Apache 2.0.
- **[vk-mem](https://github.com/gwihlidal/vk-mem-rs)** - Rust binding for this library. Author: Graham Wihlidal. License: Apache 2.0 or MIT.
- **[Haskell bindings](https://hackage.haskell.org/package/VulkanMemoryAllocator)**, **[github](https://github.com/expipiplus1/vulkan/tree/master/VulkanMemoryAllocator)** - Haskell bindings for this library. Author: Joe Hermaszewski (@expipiplus1). License BSD-3-Clause.
- **[vma_sample_sdl](https://github.com/rextimmy/vma_sample_sdl)** - SDL port of the sample app of this library (with the goal of running it on multiple platforms, including MacOS). Author: @rextimmy. License: MIT.
- **[vulkan-malloc](https://github.com/dylanede/vulkan-malloc)** - Vulkan memory allocation library for Rust. Based on version 1 of this library. Author: Dylan Ede (@dylanede). License: MIT / Apache 2.0.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"

View File

@@ -85,3 +85,7 @@ endif()
if(UNIX AND NOT APPLE)
add_subdirectory(libc_compat)
endif()
if(WITH_VULKAN)
add_subdirectory(shader_compiler)
endif()

View File

@@ -89,6 +89,18 @@ set(LIB
${GLEW_LIBRARY}
)
if(WITH_VULKAN)
list(APPEND SRC
intern/GHOST_ContextVK.cpp
intern/GHOST_ContextVK.h
)
list(APPEND INC_SYS
${Vulkan_INCLUDE_DIRS}
)
endif()
if(WITH_GHOST_DEBUG)
list(APPEND SRC
intern/GHOST_EventPrinter.cpp

View File

@@ -195,6 +195,7 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
* \return A handle to the new context ( == NULL if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
@@ -542,6 +543,13 @@ extern int GHOST_GetValid(GHOST_WindowHandle windowhandle);
*/
extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle);
/**
* Returns the drawing context used in this window.
* \param windowhandle: The handle to the window.
* \return The window drawing context.
*/
extern GHOST_ContextHandle GHOST_GetDrawingContext(GHOST_WindowHandle windowhandle);
/**
* Tries to install a rendering context in this window.
* \param windowhandle: The handle to the window.
@@ -1159,6 +1167,50 @@ int GHOST_XrGetControllerModelData(GHOST_XrContextHandle xr_context,
#endif /* WITH_XR_OPENXR */
#ifdef WITH_VULKAN
/**
* Return vulkan handles for the given context.
*/
void GHOST_GetVulkanHandles(GHOST_ContextHandle context,
void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_familly);
/**
* Return vulkan backbuffer resources handles for the given window.
*/
void GHOST_GetVulkanBackbuffer(GHOST_WindowHandle windowhandle,
void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id);
/**
* \brief Query vulkan devices.
*
* \returns a device list handle or NULL when there is no vulkan available.
*/
GHOST_VulkanDeviceListHandle GHOST_QueryVulkanDevices(GHOST_ContextHandle system);
/**
* \brief Destroy the given device list.
*/
GHOST_TSuccess GHOST_DestroyVulkanDeviceList(GHOST_VulkanDeviceListHandle device_list_handle);
/**
* \brief Get an item from the given device list.
*
* \returns GHOST_kSuccess when device is loaded. GHOST_kFailure when the given device_list_handle
* is incorrect or the given index is out of range.
*/
GHOST_TSuccess GHOST_GetVulkanDeviceListItem(GHOST_VulkanDeviceListHandle device_list_handle,
int64_t index,
GHOST_VulkanPhysicalDevice *r_device);
#endif
#ifdef __cplusplus
}

View File

@@ -56,6 +56,11 @@ class GHOST_IContext {
virtual unsigned int getDefaultFramebuffer() = 0;
virtual GHOST_TSuccess getVulkanHandles(void *, void *, void *, uint32_t *) = 0;
virtual GHOST_TSuccess getVulkanBackbuffer(
void *, void *, void *, void *, void *, uint32_t *) = 0;
virtual GHOST_TSuccess swapBuffers() = 0;
#ifdef WITH_CXX_GUARDEDALLOC

View File

@@ -265,7 +265,8 @@ class GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings) = 0;
/**
* Dispose of a context.

View File

@@ -30,6 +30,8 @@
#include <stdlib.h>
#include <string>
class GHOST_IContext;
/**
* Interface for GHOST windows.
*
@@ -71,6 +73,12 @@ class GHOST_IWindow {
*/
virtual GHOST_TDrawingContextType getDrawingContextType() = 0;
/**
* Returns the type of drawing context used in this window.
* \return The current type of drawing context.
*/
virtual GHOST_IContext *getDrawingContext() = 0;
/**
* Tries to install a rendering context in this window.
* \param type: The type of rendering context installed.
@@ -218,6 +226,18 @@ class GHOST_IWindow {
*/
virtual unsigned int getDefaultFramebuffer() = 0;
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void * /*image*/,
void * /*framebuffer*/,
void * /*command_buffer*/,
void * /*render_pass*/,
void * /*extent*/,
uint32_t * /*fb_id*/) = 0;
/**
* Invalidates the contents of this window.
* \return Indication of success.

View File

@@ -29,6 +29,10 @@
# include "MEM_guardedalloc.h"
#endif
#ifdef WITH_VULKAN
# include "vulkan/vulkan.h"
#endif
#if defined(WITH_CXX_GUARDEDALLOC) && defined(__cplusplus)
# define GHOST_DECLARE_HANDLE(name) \
typedef struct name##__ { \
@@ -145,6 +149,9 @@ typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWind
typedef enum {
GHOST_kDrawingContextTypeNone = 0,
GHOST_kDrawingContextTypeOpenGL,
#ifdef WITH_VULKAN
GHOST_kDrawingContextTypeVulkan,
#endif
#ifdef WIN32
GHOST_kDrawingContextTypeD3D,
#endif
@@ -782,3 +789,20 @@ typedef struct GHOST_XrControllerModelData {
} GHOST_XrControllerModelData;
#endif /* WITH_XR_OPENXR */
#ifdef WITH_VULKAN
GHOST_DECLARE_HANDLE(GHOST_VulkanDeviceListHandle);
typedef struct GHOST_VulkanPhysicalDeviceID {
uint32_t vendor_id;
uint32_t device_id;
int32_t index;
} GHOST_VulkanPhysicalDeviceID;
typedef struct GHOST_VulkanPhysicalDevice {
GHOST_VulkanPhysicalDeviceID device_id;
VkPhysicalDeviceProperties device_properties;
} GHOST_VulkanPhysicalDevice;
#endif

View File

@@ -35,6 +35,9 @@
# include "GHOST_IXrContext.h"
# include "intern/GHOST_XrSession.h"
#endif
#ifdef WITH_VULKAN
# include "intern/GHOST_ContextVK.h"
#endif
#include "intern/GHOST_CallbackEventConsumer.h"
#include "intern/GHOST_XrException.h"
@@ -137,11 +140,12 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
}
GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
return (GHOST_ContextHandle)system->createOffscreenContext(glSettings);
return (GHOST_ContextHandle)system->createOffscreenContext(type, glSettings);
}
GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
@@ -493,6 +497,13 @@ GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowh
return window->getDrawingContextType();
}
GHOST_ContextHandle GHOST_GetDrawingContext(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
return (GHOST_ContextHandle)window->getDrawingContext();
}
GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
GHOST_TDrawingContextType type)
{
@@ -1105,3 +1116,74 @@ int GHOST_XrGetControllerModelData(GHOST_XrContextHandle xr_contexthandle,
}
#endif /* WITH_XR_OPENXR */
#ifdef WITH_VULKAN
/**
* Return vulkan handles for the given context.
*/
void GHOST_GetVulkanHandles(GHOST_ContextHandle contexthandle,
void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_familly)
{
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
context->getVulkanHandles(r_instance, r_physical_device, r_device, r_graphic_queue_familly);
}
/**
* Return vulkan backbuffer resources handles for the given window.
*/
void GHOST_GetVulkanBackbuffer(GHOST_WindowHandle windowhandle,
void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
window->getVulkanBackbuffer(image, framebuffer, command_buffer, render_pass, extent, fb_id);
}
/**
* \brief Query vulkan devices.
*
* \returns a device list handle or NULL when there is no vulkan available.
*/
GHOST_VulkanDeviceListHandle GHOST_QueryVulkanDevices(GHOST_ContextHandle contexthandle)
{
GHOST_ContextVK *context = (GHOST_ContextVK *)contexthandle;
return (GHOST_VulkanDeviceListHandle)context->queryDevices();
}
/**
* \brief Destroy the given device list.
*/
GHOST_TSuccess GHOST_DestroyVulkanDeviceList(GHOST_VulkanDeviceListHandle device_list_handle)
{
if (device_list_handle == nullptr) {
return GHOST_kFailure;
}
GHOST_ContextVK::destroyDeviceList((GHOST_VulkanDeviceList *)device_list_handle);
return GHOST_kSuccess;
}
/**
* \brief Get an item from the given device list.
*
* \returns GHOST_kSuccess when device is loaded. GHOST_kFailure when the given device_list_handle
* is incorrect or the given index is out of range.
*/
GHOST_TSuccess GHOST_GetVulkanDeviceListItem(GHOST_VulkanDeviceListHandle device_list_handle,
int64_t index,
GHOST_VulkanPhysicalDevice *r_device)
{
return GHOST_kFailure;
}
#endif /* WITH_VULKAN */

View File

@@ -135,6 +135,33 @@ class GHOST_Context : public GHOST_IContext {
return 0;
}
/**
* Gets the Vulkan context related resource handles.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess getVulkanHandles(void * /*r_instance*/,
void * /*r_physical_device*/,
void * /*r_device*/,
uint32_t * /*r_graphic_queue_familly*/)
{
return GHOST_kFailure;
};
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
virtual GHOST_TSuccess getVulkanBackbuffer(void * /*image*/,
void * /*framebuffer*/,
void * /*command_buffer*/,
void * /*render_pass*/,
void * /*extent*/,
uint32_t * /*fb_id*/)
{
return GHOST_kFailure;
}
protected:
void initContextGLEW();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2014 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup GHOST
*/
#ifndef __GHOST_CONTEXTVK_H__
#define __GHOST_CONTEXTVK_H__
#include "GHOST_Context.h"
#ifdef _WIN32
# include "GHOST_SystemWin32.h"
#elif defined(__APPLE__)
# include "GHOST_SystemCocoa.h"
#else
# include "GHOST_SystemX11.h"
# ifdef WITH_GHOST_WAYLAND
# include "GHOST_SystemWayland.h"
# else
# define wl_surface void
# define wl_display void
# endif
#endif
#include <vector>
#ifdef __APPLE__
# include <MoltenVK/vk_mvk_moltenvk.h>
#else
# include <vulkan/vulkan.h>
#endif
#ifndef GHOST_OPENGL_VK_CONTEXT_FLAGS
/* leave as convenience define for the future */
# define GHOST_OPENGL_VK_CONTEXT_FLAGS 0
#endif
#ifndef GHOST_OPENGL_VK_RESET_NOTIFICATION_STRATEGY
# define GHOST_OPENGL_VK_RESET_NOTIFICATION_STRATEGY 0
#endif
typedef enum {
GHOST_kVulkanPlatformX11 = 0,
#ifdef WITH_GHOST_WAYLAND
GHOST_kVulkanPlatformWayland,
#endif
} GHOST_TVulkanPlatformType;
struct GHOST_VulkanDeviceList {
std::vector<GHOST_VulkanPhysicalDevice> m_devices;
};
class GHOST_ContextVK : public GHOST_Context {
/* XR code needs low level graphics data to send to OpenXR. */
// friend class GHOST_XrGraphicsBindingOpenGL;
public:
/**
* Constructor.
*/
GHOST_ContextVK(bool stereoVisual,
#ifdef _WIN32
HWND hwnd,
#elif defined(__APPLE__)
/* FIXME CAMetalLayer but have issue with linking. */
void *metal_layer,
#else
GHOST_TVulkanPlatformType platform,
/* X11 */
Window window,
Display *display,
/* Wayland */
wl_surface *wayland_surface,
wl_display *wayland_display,
#endif
int contextMajorVersion,
int contextMinorVersion,
int m_debug);
/**
* Destructor.
*/
~GHOST_ContextVK();
/**
* Swaps front and back buffers of a window.
* \return A boolean success indicator.
*/
GHOST_TSuccess swapBuffers();
/**
* Activates the drawing context of this window.
* \return A boolean success indicator.
*/
GHOST_TSuccess activateDrawingContext();
/**
* Release the drawing context of the calling thread.
* \return A boolean success indicator.
*/
GHOST_TSuccess releaseDrawingContext();
/**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
GHOST_TSuccess initializeDrawingContext();
/**
* Removes references to native handles from this context and then returns
* \return GHOST_kSuccess if it is OK for the parent to release the handles and
* GHOST_kFailure if releasing the handles will interfere with sharing
*/
GHOST_TSuccess releaseNativeHandles();
/**
* Gets the Vulkan context related resource handles.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanHandles(void *r_instance,
void *r_physical_device,
void *r_device,
uint32_t *r_graphic_queue_familly);
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id);
/**
* Sets the swap interval for swapBuffers.
* \param interval The swap interval to use.
* \return A boolean success indicator.
*/
GHOST_TSuccess setSwapInterval(int /* interval */)
{
return GHOST_kFailure;
}
/**
* Gets the current swap interval for swapBuffers.
* \param intervalOut Variable to store the swap interval if it can be read.
* \return Whether the swap interval can be read.
*/
GHOST_TSuccess getSwapInterval(int &)
{
return GHOST_kFailure;
};
GHOST_VulkanDeviceList *queryDevices();
static void destroyDeviceList(GHOST_VulkanDeviceList *device_list);
private:
#ifdef _WIN32
HWND m_hwnd;
#elif defined(__APPLE__)
/* FIXME CAMetalLayer but have issue with linking. */
void *m_metal_layer;
#else /* Linux */
GHOST_TVulkanPlatformType m_platform;
/* X11 */
Display *m_display;
Window m_window;
/* Wayland */
wl_surface *m_wayland_surface;
wl_display *m_wayland_display;
#endif
const int m_context_major_version;
const int m_context_minor_version;
const int m_debug;
VkInstance m_instance;
VkPhysicalDevice m_physical_device;
VkDevice m_device;
VkCommandPool m_command_pool;
uint32_t m_queue_family_graphic;
uint32_t m_queue_family_present;
VkQueue m_graphic_queue;
VkQueue m_present_queue;
/* For display only. */
VkSurfaceKHR m_surface;
VkSwapchainKHR m_swapchain;
std::vector<VkImage> m_swapchain_images;
std::vector<VkImageView> m_swapchain_image_views;
std::vector<VkFramebuffer> m_swapchain_framebuffers;
std::vector<VkCommandBuffer> m_command_buffers;
VkRenderPass m_render_pass;
VkExtent2D m_render_extent;
std::vector<VkSemaphore> m_image_available_semaphores;
std::vector<VkSemaphore> m_render_finished_semaphores;
std::vector<VkFence> m_in_flight_fences;
std::vector<VkFence> m_in_flight_images;
/** frame modulo swapchain_len. Used as index for sync objects. */
int m_currentFrame = 0;
/** Image index in the swapchain. Used as index for render objects. */
uint32_t m_currentImage = 0;
/** Used to unique framebuffer ids to return when swapchain is recreated. */
uint32_t m_swapchain_id = 0;
const char *getPlatformSpecificSurfaceExtension() const;
GHOST_TSuccess pickPhysicalDevice(std::vector<const char *> required_exts);
GHOST_TSuccess createSwapchain(void);
GHOST_TSuccess destroySwapchain(void);
GHOST_TSuccess createCommandBuffers(void);
GHOST_TSuccess recordCommandBuffers(void);
};
#endif // __GHOST_CONTEXTVK_H__

View File

@@ -117,7 +117,8 @@ class GHOST_System : public GHOST_ISystem {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
virtual GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) = 0;
virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings) = 0;
/**
* Returns whether a window is valid.

View File

@@ -116,7 +116,8 @@ class GHOST_SystemCocoa : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
* Dispose of a context.

View File

@@ -34,6 +34,10 @@
#include "GHOST_ContextCGL.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#ifdef WITH_INPUT_NDOF
# include "GHOST_NDOFManagerCocoa.h"
#endif
@@ -764,8 +768,21 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
#ifdef WITH_VULKAN
if (type == GHOST_kDrawingContextTypeVulkan) {
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 0, debug_context);
if (context->initializeDrawingContext()) {
return context;
}
delete context;
type = GHOST_kDrawingContextTypeOpenGL;
}
#endif
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL);
if (context->initializeDrawingContext())
return context;

View File

@@ -81,7 +81,8 @@ class GHOST_SystemNULL : public GHOST_System {
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
{ /* nop */
}
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType /* type */,
GHOST_GLSettings glSettings)
{
return NULL;
}

View File

@@ -139,7 +139,8 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
return SDL_GetNumVideoDisplays();
}
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_TDrawingContextType /* type */,
GHOST_GLSettings glSettings)
{
GHOST_Context *context = new GHOST_ContextSDL(0,
NULL,

View File

@@ -72,7 +72,8 @@ class GHOST_SystemSDL : public GHOST_System {
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
GHOST_TSuccess disposeContext(GHOST_IContext *context);

View File

@@ -30,6 +30,10 @@
#include "GHOST_ContextEGL.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#include <EGL/egl.h>
#include <wayland-egl.h>
@@ -1588,55 +1592,75 @@ void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &hei
getMainDisplayDimensions(width, height);
}
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
/* Create new off-screen window. */
wl_surface *os_surface = wl_compositor_create_surface(compositor());
wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1));
#if defined(WITH_VULKAN)
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
d->os_surfaces.push_back(os_surface);
d->os_egl_windows.push_back(os_egl_window);
if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformWayland, 0, NULL, NULL, d->display, 1, 0, debug_context);
GHOST_Context *context;
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
}
}
#else
(void)glSettings;
#endif
if (type == GHOST_kDrawingContextTypeOpenGL) {
/* Create new off-screen window. */
wl_surface *os_surface = wl_compositor_create_surface(compositor());
wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1));
d->os_surfaces.push_back(os_surface);
d->os_egl_windows.push_back(os_egl_window);
GHOST_Context *context;
for (int minor = 6; minor >= 0; --minor) {
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
4,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext())
return context;
else
delete context;
}
for (int minor = 6; minor >= 0; --minor) {
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
4,
minor,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext())
if (context->initializeDrawingContext()) {
return context;
else
}
else {
delete context;
}
GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
}
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
}
GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
return nullptr;
}

View File

@@ -73,7 +73,8 @@ class GHOST_SystemWayland : public GHOST_System {
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override;
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings) override;
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings) override;
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;

View File

@@ -50,7 +50,15 @@
#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
#include "GHOST_ContextWGL.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextWGL.h"
#endif
#ifdef WITH_INPUT_NDOF
# include "GHOST_NDOFManagerWin32.h"
@@ -263,10 +271,26 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
#if defined(WITH_VULKAN)
/* Vulkan does not need a window. */
if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(false, (HWND)0, 1, 0, debug_context);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
return NULL;
}
}
#endif
GHOST_Context *context;
HWND wnd = CreateWindowA("STATIC",

View File

@@ -142,7 +142,8 @@ class GHOST_SystemWin32 : public GHOST_System {
* Never explicitly delete the window, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
* Dispose of a context.

View File

@@ -48,6 +48,10 @@
#include "GHOST_Debug.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
# include <EGL/eglext.h>
@@ -394,7 +398,8 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSettings)
GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
/* During development:
* try 4.x compatibility profile
@@ -408,46 +413,97 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
#if defined(WITH_GL_PROFILE_CORE)
{
const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
if (version_major != NULL && version_major[0] == '1') {
fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
abort();
#if defined(WITH_VULKAN)
if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 0, debug_context);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
}
}
#endif
const int profile_mask =
if (type == GHOST_kDrawingContextTypeOpenGL) {
/* Final Blender 2.8:
* try 4.x core profile
* try 3.3 core profile
* no fallbacks. */
#if defined(WITH_GL_PROFILE_CORE)
{
const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
if (version_major != NULL && version_major[0] == '1') {
fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
abort();
}
}
#endif
const int profile_mask =
#ifdef WITH_GL_EGL
# if defined(WITH_GL_PROFILE_CORE)
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
# elif defined(WITH_GL_PROFILE_COMPAT)
EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
# else
# error // must specify either core or compat at build time
# endif
#else
# if defined(WITH_GL_PROFILE_CORE)
GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
# elif defined(WITH_GL_PROFILE_COMPAT)
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
# else
# error // must specify either core or compat at build time
# endif
#endif
GHOST_Context *context;
GHOST_Context *context;
for (int minor = 5; minor >= 0; --minor) {
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
4,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS |
(false ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
#else
context = new GHOST_ContextGLX(false,
(Window)NULL,
m_display,
(GLXFBConfig)NULL,
profile_mask,
4,
minor,
GHOST_OPENGL_GLX_CONTEXT_FLAGS |
(false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
#endif
if (context->initializeDrawingContext())
return context;
else
delete context;
}
for (int minor = 5; minor >= 0; --minor) {
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
4,
minor,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS |
(debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
@@ -458,49 +514,21 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
m_display,
(GLXFBConfig)NULL,
profile_mask,
4,
minor,
3,
3,
GHOST_OPENGL_GLX_CONTEXT_FLAGS |
(debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
#endif
if (context->initializeDrawingContext())
if (context->initializeDrawingContext()) {
return context;
else
}
else {
delete context;
}
}
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS |
(debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
#else
context = new GHOST_ContextGLX(false,
(Window)NULL,
m_display,
(GLXFBConfig)NULL,
profile_mask,
3,
3,
GHOST_OPENGL_GLX_CONTEXT_FLAGS |
(debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
#endif
if (context->initializeDrawingContext())
return context;
else
delete context;
return NULL;
}

View File

@@ -152,7 +152,8 @@ class GHOST_SystemX11 : public GHOST_System {
* Never explicitly delete the context, use #disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings);
GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
* Dispose of a context.

View File

@@ -26,7 +26,7 @@
#include "GHOST_IWindow.h"
class GHOST_Context;
#include "GHOST_Context.h"
/**
* Platform independent implementation of GHOST_IWindow.
@@ -94,6 +94,22 @@ class GHOST_Window : public GHOST_IWindow {
return m_context != NULL;
}
/**
* Gets the Vulkan framebuffer related resource handles associated with the Vulkan context.
* Needs to be called after each swap events as the framebuffer will change.
* \return A boolean success indicator.
*/
GHOST_TSuccess getVulkanBackbuffer(void *image,
void *framebuffer,
void *command_buffer,
void *render_pass,
void *extent,
uint32_t *fb_id)
{
return m_context->getVulkanBackbuffer(
image, framebuffer, command_buffer, render_pass, extent, fb_id);
};
/**
* Returns the associated OS object/handle
* \return The associated OS object/handle
@@ -229,6 +245,12 @@ class GHOST_Window : public GHOST_IWindow {
*/
inline GHOST_TDrawingContextType getDrawingContextType();
/**
* Returns the drawing context used in this window.
* \return The drawing context.
*/
inline GHOST_IContext *getDrawingContext();
/**
* Tries to install a rendering context in this window.
* Child classes do not need to overload this method,
@@ -411,6 +433,11 @@ inline GHOST_TDrawingContextType GHOST_Window::getDrawingContextType()
return m_drawingContextType;
}
inline GHOST_IContext *GHOST_Window::getDrawingContext()
{
return m_context;
}
inline bool GHOST_Window::getCursorVisibility() const
{
return m_cursorVisible;

View File

@@ -24,6 +24,10 @@
#include "GHOST_ContextCGL.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#include <Cocoa/Cocoa.h>
#include <Metal/Metal.h>
#include <QuartzCore/QuartzCore.h>
@@ -819,8 +823,21 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
#ifdef WITH_VULKAN
if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual, m_metalLayer, 1, 0, true);
if (context->initializeDrawingContext()) {
return context;
}
delete context;
/* Fallback to opengl. */
type = GHOST_kDrawingContextTypeOpenGL;
}
#endif
if (type == GHOST_kDrawingContextTypeOpenGL) {
GHOST_Context *context = new GHOST_ContextCGL(
m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView);

View File

@@ -26,6 +26,9 @@
#include "GHOST_ContextEGL.h"
#include "GHOST_ContextNone.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#include <wayland-egl.h>
@@ -554,6 +557,21 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
break;
#if defined(WITH_VULKAN)
case GHOST_kDrawingContextTypeVulkan:
context = new GHOST_ContextVK(m_wantStereoVisual,
GHOST_kVulkanPlatformWayland,
0,
NULL,
w->surface,
m_system->display(),
1,
0,
false);
break;
#endif
}
return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;

View File

@@ -30,8 +30,15 @@
#include "utf_winfunc.h"
#include "utfconv.h"
#include "GHOST_ContextWGL.h"
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#if defined(WITH_GL_EGL)
# include "GHOST_ContextEGL.h"
#else
# include "GHOST_ContextWGL.h"
#endif
#ifdef WIN32_COMPOSITING
# include <Dwmapi.h>
#endif
@@ -615,6 +622,18 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
return context;
}
#if defined(WITH_VULKAN)
else if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(false, m_hWnd, 1, 0, m_debug_context);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
}
}
#endif
return NULL;
}

View File

@@ -38,6 +38,10 @@
# include "GHOST_DropTargetX11.h"
#endif
#if defined(WITH_VULKAN)
# include "GHOST_ContextVK.h"
#endif
#ifdef WITH_GL_EGL
# include "GHOST_ContextEGL.h"
# include <EGL/eglext.h>
@@ -1273,8 +1277,38 @@ GHOST_WindowX11::~GHOST_WindowX11()
GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
#if defined(WITH_VULKAN)
if (type == GHOST_kDrawingContextTypeVulkan) {
/* Vulkan port
* try vulkan
* fallback to OGL */
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual,
GHOST_kVulkanPlatformX11,
m_window,
m_display,
NULL,
NULL,
1,
0,
m_is_debug_context);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
}
fprintf(stderr, "Error! Unsupported graphics card or driver.\n");
fprintf(stderr, "A graphics card and driver with support for Vulkan 1.0.\n");
fprintf(stderr, "You can try the `--debug-gpu' option to have more information.\n");
fprintf(stderr, "The program will now close.\n");
fflush(stderr);
exit(1);
}
#endif
if (type == GHOST_kDrawingContextTypeOpenGL) {
/* During development:
* - Try 4.x compatibility profile.
* - Try 3.3 compatibility profile.

View File

@@ -266,6 +266,8 @@ class GHOST_WindowX11 : public GHOST_Window {
XIC m_xic;
#endif
GHOST_TDrawingContextType m_context_type;
bool m_valid_setup;
bool m_is_debug_context;

View File

@@ -332,7 +332,7 @@ MainWindow *mainwindow_new(MultiTestApp *app)
if (win) {
MainWindow *mw = MEM_callocN(sizeof(*mw), "mainwindow_new");
mw->gpu_context = GPU_context_create(win);
mw->gpu_context = GPU_context_create(win, NULL);
GPU_init();
mw->app = app;
@@ -589,7 +589,7 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app)
if (win) {
LoggerWindow *lw = MEM_callocN(sizeof(*lw), "loggerwindow_new");
lw->gpu_context = GPU_context_create(win);
lw->gpu_context = GPU_context_create(win, NULL);
GPU_init();
int bbox[2][2];
@@ -791,7 +791,7 @@ ExtraWindow *extrawindow_new(MultiTestApp *app)
if (win) {
ExtraWindow *ew = MEM_callocN(sizeof(*ew), "mainwindow_new");
ew->gpu_context = GPU_context_create(win);
ew->gpu_context = GPU_context_create(win, NULL);
GPU_init();
ew->app = app;

View File

@@ -0,0 +1,44 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2012, Blender Foundation
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
set(INC
.
../guardedalloc
)
set(INC_SYS
${SHADERC_INCLUDE_DIRS}
)
set(SRC
intern/Compiler.cc
intern/Result.cc
intern/shaderc/ShaderCCompiler.cc
intern/shaderc/ShaderCResult.cc
shader_compiler.hh
)
set(LIB
${SHADERC_LIBRARIES}
)
blender_add_lib(bf_intern_shadercompiler "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -0,0 +1,32 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#include "shader_compiler.hh"
#include "intern/shaderc/ShaderCCompiler.hh"
namespace shader_compiler {
Compiler *Compiler::create_default()
{
Compiler *compiler = new shaderc::ShaderCCompiler();
return compiler;
}
} // namespace shader_compiler

View File

@@ -0,0 +1,29 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#include "shader_compiler.hh"
namespace shader_compiler {
void Result::init(const Job &job)
{
type = job.compilation_target;
}
} // namespace shader_compiler

View File

@@ -0,0 +1,92 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#include "ShaderCCompiler.hh"
#include "ShaderCResult.hh"
#include "shaderc/shaderc.hpp"
namespace shader_compiler::shaderc {
ShaderCCompiler::ShaderCCompiler()
{
}
ShaderCCompiler::~ShaderCCompiler()
{
}
void ShaderCCompiler::set_optimization_level(::shaderc::CompileOptions options,
const OptimizationLevel new_value)
{
switch (new_value) {
case OptimizationLevel::NotOptimized:
options.SetOptimizationLevel(shaderc_optimization_level_zero);
break;
case OptimizationLevel::SizeOptimized:
options.SetOptimizationLevel(shaderc_optimization_level_size);
break;
case OptimizationLevel::SpeedOptimized:
options.SetOptimizationLevel(shaderc_optimization_level_performance);
break;
}
}
shaderc_shader_kind ShaderCCompiler::get_source_kind(SourceType source_type)
{
switch (source_type) {
case SourceType::GlslVertexShader:
return shaderc_glsl_vertex_shader;
case SourceType::GlslGeometryShader:
return shaderc_glsl_geometry_shader;
case SourceType::GlslFragmentShader:
return shaderc_glsl_fragment_shader;
case SourceType::GlslComputeShader:
return shaderc_glsl_compute_shader;
}
return shaderc_glsl_vertex_shader;
}
ShaderCResult *ShaderCCompiler::compile_spirv(const Job &job)
{
::shaderc::CompileOptions options;
set_optimization_level(options, job.optimization_level);
shaderc_shader_kind kind = get_source_kind(job.source_type);
::shaderc::SpvCompilationResult shaderc_result = compiler_.CompileGlslToSpv(
job.source.c_str(), kind, job.name.c_str(), options);
ShaderCResult *result = new ShaderCResult();
result->init(job, shaderc_result);
return result;
}
Result *ShaderCCompiler::compile(const Job &job)
{
switch (job.compilation_target) {
case TargetType::SpirV:
return compile_spirv(job);
break;
}
return nullptr;
}
} // namespace shader_compiler::shaderc

View File

@@ -0,0 +1,48 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#pragma once
#include "shader_compiler.hh"
#include "shaderc/shaderc.hpp"
namespace shader_compiler::shaderc {
class ShaderCResult;
class ShaderCCompiler : public Compiler {
private:
::shaderc::Compiler compiler_;
public:
ShaderCCompiler();
~ShaderCCompiler() override;
Result *compile(const Job &job) override;
private:
ShaderCResult *compile_spirv(const Job &job);
static void set_optimization_level(::shaderc::CompileOptions options,
const OptimizationLevel new_value);
static shaderc_shader_kind get_source_kind(SourceType source_type);
};
} // namespace shader_compiler::shaderc

View File

@@ -0,0 +1,58 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#include "ShaderCResult.hh"
namespace shader_compiler::shaderc {
void ShaderCResult::init(const Job &job, ::shaderc::SpvCompilationResult &shaderc_result)
{
Result::init(job);
status_code = status_code_from(shaderc_result);
switch (status_code) {
case StatusCode::Ok:
bin = {shaderc_result.cbegin(), shaderc_result.cend()};
break;
case StatusCode::CompilationError:
error_log = shaderc_result.GetErrorMessage();
break;
}
}
StatusCode ShaderCResult::status_code_from(::shaderc::SpvCompilationResult &shaderc_result)
{
if (shaderc_result.GetCompilationStatus() != shaderc_compilation_status_success) {
return StatusCode::CompilationError;
}
return StatusCode::Ok;
}
std::vector<uint32_t> ShaderCResult::bin_from(::shaderc::SpvCompilationResult &shaderc_result)
{
return {shaderc_result.cbegin(), shaderc_result.cend()};
}
std::string ShaderCResult::error_log_from(::shaderc::SpvCompilationResult &shaderc_result)
{
return shaderc_result.GetErrorMessage();
}
} // namespace shader_compiler::shaderc

View File

@@ -0,0 +1,39 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#pragma once
#include "shader_compiler.hh"
#include "shaderc/shaderc.hpp"
namespace shader_compiler::shaderc {
class ShaderCResult : public Result {
public:
void init(const Job &job, ::shaderc::SpvCompilationResult &shaderc_result);
private:
StatusCode status_code_from(::shaderc::SpvCompilationResult &shaderc_result);
std::string error_log_from(::shaderc::SpvCompilationResult &shaderc_result);
std::vector<uint32_t> bin_from(::shaderc::SpvCompilationResult &shaderc_result);
};
} // namespace shader_compiler::shaderc

View File

@@ -0,0 +1,106 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2021 by Blender Foundation.
* All rights reserved.
*/
#pragma once
#include <stdint.h>
#include <string>
#include <vector>
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
namespace shader_compiler {
enum class SourceType {
GlslVertexShader,
GlslGeometryShader,
GlslFragmentShader,
GlslComputeShader,
};
enum class TargetType {
SpirV,
// SpirVAssembly,
};
enum class OptimizationLevel {
NotOptimized,
SizeOptimized,
SpeedOptimized,
};
enum class StatusCode {
Ok,
CompilationError,
};
class Job;
class Result;
class Compiler {
protected:
Compiler(){};
public:
virtual ~Compiler(){};
static Compiler *create_default();
virtual Result *compile(const Job &job) = 0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("ShadeCompiler:Compiler")
#endif
};
class Job {
public:
std::string name;
std::string source;
SourceType source_type;
TargetType compilation_target;
OptimizationLevel optimization_level = OptimizationLevel::NotOptimized;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("ShaderCompiler:Job")
#endif
};
class Result {
public:
TargetType type;
StatusCode status_code;
std::string error_log;
std::vector<uint32_t> bin;
virtual ~Result(){};
protected:
void init(const Job &job);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("ShaderCompiler:Result")
#endif
};
void init();
void free();
} // namespace shader_compiler

View File

@@ -158,7 +158,8 @@ enum {
G_DEBUG_XR = (1 << 19), /* XR/OpenXR messages */
G_DEBUG_XR_TIME = (1 << 20), /* XR/OpenXR timing messages */
G_DEBUG_GHOST = (1 << 21), /* Debug GHOST module. */
G_DEBUG_GHOST = (1 << 21), /* Debug GHOST module. */
G_DEBUG_VK_CONTEXT = (1 << 22), /* not a debug flag, TODO move it. */
};
#define G_DEBUG_ALL \

View File

@@ -530,7 +530,7 @@ if(WITH_GTESTS)
set(TEST_SRC
tests/draw_testing.cc
tests/shaders_test.cc
tests/performance_test.cc
tests/draw_testing.hh
)
set(TEST_INC

View File

@@ -612,7 +612,7 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
if (lbake->gl_context) {
DRW_opengl_render_context_enable(lbake->gl_context);
if (lbake->gpu_context == NULL) {
lbake->gpu_context = GPU_context_create(NULL);
lbake->gpu_context = GPU_context_create(NULL, lbake->gl_context);
}
DRW_gpu_render_context_enable(lbake->gpu_context);
}

View File

@@ -59,7 +59,7 @@ void main()
{
ivec2 tex_size = textureSize(cocBuffer, 0);
int t_id = gl_VertexID / 3; /* Triangle Id */
int t_id = gl_VertexIndex / 3; /* Triangle Id */
/* Some math to get the target pixel. */
ivec2 texelco = ivec2(t_id % spritePerRow, t_id / spritePerRow) * 2;
@@ -118,7 +118,7 @@ void main()
*/
/* Generate Triangle : less memory fetches from a VBO */
int v_id = gl_VertexID % 3; /* Vertex Id */
int v_id = gl_VertexIndex % 3; /* Vertex Id */
gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */
gl_Position.y = float(v_id % 2) * extend - 1.0;
gl_Position.z = 0.0;

View File

@@ -30,8 +30,8 @@ const vec2 pos[6] = vec2[6](vec2(-1.0, -1.0),
void main()
{
pid = 1 + (gl_VertexID / 6); /* +1 for the world */
int vert_id = gl_VertexID % 6;
pid = 1 + (gl_VertexIndex / 6); /* +1 for the world */
int vert_id = gl_VertexIndex % 6;
quadCoord = pos[vert_id];

View File

@@ -23,8 +23,8 @@ const vec2 pos[6] = vec2[6](vec2(-1.0, -1.0),
void main()
{
int cell_id = gl_VertexID / 6;
int vert_id = gl_VertexID % 6;
int cell_id = gl_VertexIndex / 6;
int vert_id = gl_VertexIndex % 6;
vec3 ls_cell_location;
/* Keep in sync with update_irradiance_probe */

View File

@@ -4,9 +4,9 @@ out vec2 vPos;
void main()
{
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
vPos.x = -1.0 + float((v & 1) << 2);
vPos.y = -1.0 + float((v & 2) << 1);
instance = gl_VertexID / 3;
instance = gl_VertexIndex / 3;
}

View File

@@ -8,8 +8,8 @@ RESOURCE_ID_VARYING
void main()
{
/* Generate Triangle : less memory fetches from a VBO */
int v_id = gl_VertexID % 3; /* Vertex Id */
int t_id = gl_VertexID / 3; /* Triangle Id */
int v_id = gl_VertexIndex % 3; /* Vertex Id */
int t_id = gl_VertexIndex / 3; /* Triangle Id */
/* Crappy diagram
* ex 1

View File

@@ -5,7 +5,7 @@ out vec4 offset[3];
void main()
{
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
float x = -1.0 + float((v & 1) << 2);
float y = -1.0 + float((v & 2) << 1);
gl_Position = vec4(x, y, 1.0, 1.0);

View File

@@ -245,7 +245,7 @@ in vec4 col1;
in vec4 col2;
in vec4 fcol1;
/* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation
* considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) */
* considers gl_VertexIndex and gl_InstanceID as vertex attribute. (see T74536) */
# define stroke_id1 ma1.y
# define point_id1 ma1.z
# define thickness1 pos1.w
@@ -408,8 +408,8 @@ void stroke_vertex()
mat4 model_mat = model_matrix_get();
/* Avoid using a vertex attribute for quad positioning. */
float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
float x = float(gl_VertexIndex & 1) * 2.0 - 1.0; /* [-1..1] */
float y = float(gl_VertexIndex & 2) - 1.0; /* [-1..1] */
bool use_curr = is_dot || (x == -1.0);

View File

@@ -4,7 +4,7 @@ uniform vec4 gpModelMatrix[4];
void main()
{
mat4 model_matrix = mat4(gpModelMatrix[0], gpModelMatrix[1], gpModelMatrix[2], gpModelMatrix[3]);
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
float x = -1.0 + float((v & 1) << 2);
float y = -1.0 + float((v & 2) << 1);
gl_Position = ViewProjectionMatrix * (model_matrix * vec4(x, y, 0.0, 1.0));

View File

@@ -3,7 +3,7 @@ out vec2 uvs;
void main()
{
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
float x = float((v & 1) << 2);
float y = float((v & 2) << 1);
gl_Position = vec4(x - 1.0, y - 1.0, 1.0, 1.0);

View File

@@ -3,7 +3,7 @@ uniform vec3 boundbox[8];
void main()
{
vec3 world_pos = boundbox[gl_VertexID];
vec3 world_pos = boundbox[gl_VertexIndex];
gl_Position = point_world_to_ndc(world_pos);
/* Result in a position at 1.0 (far plane). Small epsilon to avoid precision issue.

View File

@@ -16,7 +16,7 @@ void main()
float flip = (gl_InstanceID != 0) ? -1.0 : 1.0;
if (gl_VertexID % 2 == 0) {
if (gl_VertexIndex % 2 == 0) {
final_pos += normalSize * rad * (flip * nor - tan);
}

View File

@@ -14,8 +14,8 @@ void main()
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec2 pos;
pos.x = float(gl_VertexID % 2);
pos.y = float(gl_VertexID / 2) / float(halfLineCount - 1);
pos.x = float(gl_VertexIndex % 2);
pos.y = float(gl_VertexIndex / 2) / float(halfLineCount - 1);
if (pos.y > 1.0) {
pos.xy = pos.yx;

View File

@@ -17,7 +17,7 @@ void main()
vec4 pos_4d = ModelMatrix * vec4(local_pos + screen_pos, 1.0);
gl_Position = ViewProjectionMatrix * pos_4d;
/* Manual stipple: one segment out of 2 is transparent. */
finalColor = ((gl_VertexID & 1) == 0) ? colorSkinRoot : vec4(0.0);
finalColor = ((gl_VertexIndex & 1) == 0) ? colorSkinRoot : vec4(0.0);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(pos_4d.xyz);

View File

@@ -37,9 +37,9 @@ void main()
vec3 ls_cell_location;
/* Keep in sync with update_irradiance_probe */
ls_cell_location.z = float(gl_VertexID % grid_resolution.z);
ls_cell_location.y = float((gl_VertexID / grid_resolution.z) % grid_resolution.y);
ls_cell_location.x = float(gl_VertexID / (grid_resolution.z * grid_resolution.y));
ls_cell_location.z = float(gl_VertexIndex % grid_resolution.z);
ls_cell_location.y = float((gl_VertexIndex / grid_resolution.z) % grid_resolution.y);
ls_cell_location.x = float(gl_VertexIndex / (grid_resolution.z * grid_resolution.y));
ls_cell_location += 0.5;
ls_cell_location /= vec3(grid_resolution);

View File

@@ -225,7 +225,7 @@ void main()
/* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
* wire to at least create one fragment that will pass the occlusion query. */
/* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexIndex % 2 == 0) ? -1.0 : 1.0);
#endif
#ifdef USE_WORLD_CLIP_PLANES

View File

@@ -21,7 +21,7 @@ void main()
/* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
* wire to at least create one fragment that will pass the occlusion query. */
/* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexIndex % 2 == 0) ? -1.0 : 1.0);
#endif
stipple_coord = stipple_start = screen_position(gl_Position);

View File

@@ -28,7 +28,7 @@ void main()
ssPos = proj(gl_Position);
int frame = gl_VertexID + cacheStart;
int frame = gl_VertexIndex + cacheStart;
float intensity; /* how faint */

View File

@@ -21,14 +21,14 @@ void main()
gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
gl_PointSize = float(pointSize + 2);
int frame = gl_VertexID + cacheStart;
int frame = gl_VertexIndex + cacheStart;
bool use_custom_color = customColor.x >= 0.0;
finalColor = (use_custom_color) ? vec4(customColor, 1.0) : vec4(1.0);
/* Bias to reduce z fighting with the path */
gl_Position.z -= 1e-4;
if (gl_VertexID % stepSize == 0) {
if (gl_VertexIndex % stepSize == 0) {
gl_PointSize = float(pointSize) + 4;
}

View File

@@ -61,7 +61,7 @@ vec4 flag_to_color(uint flag)
void main()
{
int cell = gl_VertexID / 8;
int cell = gl_VertexIndex / 8;
mat3 rot_mat = mat3(0.0);
vec3 cell_offset = vec3(0.5);
@@ -113,7 +113,7 @@ void main()
#endif
vec3 pos = domainOriginOffset + cellSize * (vec3(cell_co + adaptiveCellOffset) + cell_offset);
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 8]];
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexIndex % 8]];
pos += rotated_pos * cellSize;
vec3 world_pos = point_object_to_world(pos);

View File

@@ -118,11 +118,11 @@ vec3 get_vector_mac(ivec3 cell_co)
void main()
{
#ifdef USE_NEEDLE
int cell = gl_VertexID / 12;
int cell = gl_VertexIndex / 12;
#elif defined(USE_MAC)
int cell = gl_VertexID / 6;
int cell = gl_VertexIndex / 6;
#else
int cell = gl_VertexID / 2;
int cell = gl_VertexIndex / 2;
#endif
ivec3 volume_size = textureSize(velocityX, 0);
@@ -156,7 +156,7 @@ void main()
vec3 color;
vector = (isCellCentered) ? get_vector_mac(cell_co) : get_vector(cell_co);
switch (gl_VertexID % 6) {
switch (gl_VertexIndex % 6) {
case 0: /* Tail of X component. */
pos.x += (drawMACX) ? -0.5 * cellSize.x : 0.0;
color = vec3(1.0, 0.0, 0.0); /* red */
@@ -201,12 +201,12 @@ void main()
mat3 rot_mat = rotation_from_vector(vector);
# ifdef USE_NEEDLE
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexID % 12]];
vec3 rotated_pos = rot_mat * corners[indices[gl_VertexIndex % 12]];
pos += rotated_pos * vector_length * displaySize * cellSize;
# else
vec3 rotated_pos = rot_mat * vec3(0.0, 0.0, 1.0);
pos += ((gl_VertexID % 2) == 1) ? rotated_pos * vector_length * displaySize * cellSize :
vec3(0.0);
pos += ((gl_VertexIndex % 2) == 1) ? rotated_pos * vector_length * displaySize * cellSize :
vec3(0.0);
# endif
#endif

View File

@@ -156,7 +156,7 @@ void main()
#ifdef SELECT_EDGES
/* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
* wire to at least create one fragment that will pass the occlusion query. */
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexIndex % 2 == 0) ? -1.0 : 1.0);
#endif
#ifdef USE_WORLD_CLIP_PLANES

View File

@@ -5,7 +5,7 @@ out vec4 offset[3];
void main()
{
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
float x = -1.0 + float((v & 1) << 2);
float y = -1.0 + float((v & 2) << 1);
gl_Position = vec4(x, y, 1.0, 1.0);

View File

@@ -22,6 +22,12 @@
#pragma once
#include "BKE_mesh_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct GPUBatch;
struct GPUIndexBuf;
struct GPUMaterial;
@@ -41,12 +47,6 @@ struct PointCloud;
struct Volume;
struct bGPdata;
#include "BKE_mesh_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode);
void DRW_mball_batch_cache_validate(struct MetaBall *mb);

View File

@@ -3108,7 +3108,7 @@ void DRW_opengl_context_create(void)
DST.gl_context = WM_opengl_context_create();
WM_opengl_context_activate(DST.gl_context);
/* Be sure to create gpu_context too. */
DST.gpu_context = GPU_context_create(NULL);
DST.gpu_context = GPU_context_create(NULL, DST.gl_context);
/* So we activate the window's one afterwards. */
wm_window_reset_drawable();
}

View File

@@ -1299,6 +1299,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1);
}
#ifndef WITH_VULKAN /* This is needed until we have proper shader interfaces for vulkan. */
/* Not supported. */
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
@@ -1311,6 +1312,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1);
#endif
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)

View File

@@ -265,7 +265,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
}
else {
comp->gl_context = WM_opengl_context_create();
comp->gpu_context = GPU_context_create(NULL);
comp->gpu_context = GPU_context_create(NULL, comp->gl_context);
GPU_context_active_set(NULL);
WM_opengl_context_activate(DST.gl_context);

View File

@@ -3,7 +3,7 @@ out vec4 uvcoordsvar;
void main()
{
int v = gl_VertexID % 3;
int v = gl_VertexIndex % 3;
float x = -1.0 + float((v & 1) << 2);
float y = -1.0 + float((v & 2) << 1);
gl_Position = vec4(x, y, 1.0, 1.0);

View File

@@ -126,12 +126,12 @@ void hair_get_interp_attrs(
int hair_get_strand_id(void)
{
return gl_VertexID / (hairStrandsRes * hairThicknessRes);
return gl_VertexIndex / (hairStrandsRes * hairThicknessRes);
}
int hair_get_base_id(void)
{
return gl_VertexID / hairThicknessRes;
return gl_VertexIndex / hairThicknessRes;
}
/* Copied from cycles. */
@@ -199,7 +199,7 @@ void hair_get_pos_tan_binor_time(bool is_persp,
thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time);
if (hairThicknessRes > 1) {
thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1);
thick_time = float(gl_VertexIndex % hairThicknessRes) / float(hairThicknessRes - 1);
thick_time = thickness * (thick_time * 2.0 - 1.0);
/* Take object scale into account.

View File

@@ -19,7 +19,7 @@ void main(void)
finalColor = hair_interp_data(data0, data1, data2, data3, weights);
#ifdef TF_WORKAROUND
int id = gl_VertexID - idOffset;
int id = gl_VertexIndex - idOffset;
gl_Position.x = ((float(id % targetWidth) + 0.5) / float(targetWidth)) * 2.0 - 1.0;
gl_Position.y = ((float(id / targetWidth) + 0.5) / float(targetHeight)) * 2.0 - 1.0;
gl_Position.z = 0.0;

View File

@@ -201,10 +201,10 @@ uniform mat4 ModelMatrixInverse;
#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz)
#define point_world_to_view(p) ((ViewMatrix * vec4(p, 1.0)).xyz)
/* Due to some shader compiler bug, we somewhat need to access gl_VertexID
/* Due to some shader compiler bug, we somewhat need to access gl_VertexIndex
* to make vertex shaders work. even if it's actually dead code. */
#ifdef GPU_INTEL
# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID);
# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexIndex);
#else
# define GPU_INTEL_VERTEX_SHADER_WORKAROUND
#endif

View File

@@ -4,6 +4,12 @@
#include "GPU_shader.h"
#include "IMB_imbuf.h"
#include "BKE_appdir.h"
#include "BKE_idtype.h"
#include "DRW_engine.h"
#include "draw_manager_testing.h"
namespace blender::draw {
@@ -12,7 +18,25 @@ namespace blender::draw {
void DrawOpenGLTest::SetUp()
{
GPUOpenGLTest::SetUp();
/* Initialize color management. Required to construct a scene creation depends on it. */
BKE_idtype_init();
BKE_appdir_init();
IMB_init();
DRW_engines_register();
DRW_draw_state_init_gtests(GPU_SHADER_CFG_DEFAULT);
}
void DrawOpenGLTest::TearDown()
{
DRW_engines_free();
IMB_exit();
BKE_appdir_exit();
GPUTest::TearDown();
}
} // namespace blender::draw

View File

@@ -8,6 +8,7 @@ namespace blender::draw {
class DrawOpenGLTest : public blender::gpu::GPUOpenGLTest {
public:
void SetUp() override;
void TearDown() override;
};
#define DRAW_TEST(test_name) \

View File

@@ -0,0 +1,223 @@
/* Apache License, Version 2.0 */
#include "testing/testing.h"
#include "draw_testing.hh"
#include "intern/draw_manager_testing.h"
#include "DRW_engine.h"
#include "draw_cache_impl.h"
#include "BKE_editmesh.h"
#include "BKE_idtype.h"
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_scene.h"
#include "BLI_rand.hh"
#include "BLI_task.h"
#include "ED_mesh.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "GPU_context.h"
#include "GPU_init_exit.h"
#include "GPU_shader.h"
#include "engines/eevee/eevee_private.h"
#include "engines/gpencil/gpencil_engine.h"
#include "engines/image/image_private.hh"
#include "engines/overlay/overlay_private.h"
#include "engines/workbench/workbench_private.h"
namespace blender::draw {
/**
* During investigation or executing in a profiler it is handly to disable multithreading. This can
* be done by setting RUN_SINGLE_THREADED to true.
*
* Default(false) => run multithreaded
*/
constexpr bool RUN_SINGLE_THREADED = false;
class DrawCacheTest : public DrawOpenGLTest {
protected:
TaskGraph *task_graph;
public:
void SetUp() override
{
DrawOpenGLTest::SetUp();
if (RUN_SINGLE_THREADED) {
BLI_system_num_threads_override_set(1);
}
task_graph = BLI_task_graph_create();
}
void TearDown() override
{
BLI_task_graph_free(task_graph);
if (RUN_SINGLE_THREADED) {
BLI_system_num_threads_override_set(0);
}
DrawOpenGLTest::TearDown();
}
};
class DrawCachePerformanceTest : public DrawCacheTest {
protected:
Scene scene = {{nullptr}};
Object ob_mesh = {{nullptr}};
Mesh mesh = {{nullptr}};
BMesh *bm = nullptr;
RandomNumberGenerator rng;
public:
void SetUp() override
{
DrawCacheTest::SetUp();
IDType_ID_SCE.init_data(&scene.id);
IDType_ID_OB.init_data(&ob_mesh.id);
IDType_ID_ME.init_data(&mesh.id);
ob_mesh.type = OB_MESH;
ob_mesh.data = &mesh;
EDBM_mesh_make(&ob_mesh, SCE_SELECT_VERTEX, false);
bm = mesh.edit_mesh->bm;
/* Ensure batch cache is available. */
DRW_mesh_batch_cache_validate(&mesh);
}
void TearDown() override
{
EDBM_mesh_free_data(mesh.edit_mesh);
bm = nullptr;
IDType_ID_ME.free_data(&mesh.id);
IDType_ID_OB.free_data(&ob_mesh.id);
IDType_ID_SCE.free_data(&scene.id);
DrawCacheTest::TearDown();
}
protected:
/**
* Build a test mesh with given number of polygons.
* Each polygon is created from 3 random generated verts.
*/
void build_mesh(size_t num_polygons)
{
add_polygons_to_bm(num_polygons);
/* Make sure mesh_eval_final is up to date (inline depsgraph evaluation). See
* `editbmesh_calc_modifiers`. */
mesh.edit_mesh->mesh_eval_final = BKE_mesh_from_bmesh_for_eval_nomain(
mesh.edit_mesh->bm, nullptr, &mesh);
mesh.edit_mesh->mesh_eval_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
mesh.edit_mesh, nullptr, nullptr, &mesh);
BKE_editmesh_looptri_calc(mesh.edit_mesh);
}
/**
* Check if the given GPUBatch is filled.
*/
void expect_filled(GPUBatch *batch)
{
EXPECT_NE(batch->elem, nullptr);
}
/**
* Check if the given GPUBatch is filled.
*/
void expect_empty(GPUBatch *batch)
{
EXPECT_EQ(batch->elem, nullptr);
for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN; i++) {
EXPECT_EQ(batch->verts[i], nullptr);
}
}
private:
/**
* Create a new random vert in BMesh.
*/
BMVert *add_random_vert_to_bm()
{
float co[3] = {(rng.get_float() - 0.5f) * 10.0f,
(rng.get_float() - 0.5f) * 10.0f,
(rng.get_float() - 0.5f) * 10.0f};
BMVert *result = BM_vert_create(bm, co, nullptr, BM_CREATE_NOP);
return result;
}
/**
* Add `num_polygons` polygons to the BMesh.
*/
void add_polygons_to_bm(size_t num_polygons)
{
/* Use 3 verts per face to skip triangulation. */
const int verts_per_face = 3;
for (int i = 0; i < num_polygons; i++) {
BMVert *verts[verts_per_face];
for (int j = 0; j < verts_per_face; j++) {
verts[j] = add_random_vert_to_bm();
}
BM_face_create_verts(bm, verts, verts_per_face, nullptr, BM_CREATE_NOP, true);
}
}
};
/**
* Base line benchmark simulating edit mesh vertice transform of a large mesh.
*
* In Blender 2.93 the whole cache would be freed so the baseline is to recalculate
* all needed caches.
*/
TEST_F(DrawCachePerformanceTest, edit_mesh_performance_baseline_293)
{
/* Approximates a subdivided cube 7 times in faces. */
const int num_polygons = 100000;
const int num_benchmark_loops = 32;
/* Create a bmesh object in edit mode. */
build_mesh(num_polygons);
for (int i = 0; i < num_benchmark_loops; i++) {
/* Invalidate caches.
* In reality the mesh gets a copy on write signal and frees the cache (mesh_data_free). */
BKE_mesh_batch_cache_dirty_tag_cb(&mesh, BKE_MESH_BATCH_DIRTY_ALL);
DRW_mesh_batch_cache_validate(&mesh);
/* Request caches. */
GPUBatch *batch_triangles = DRW_mesh_batch_cache_get_edit_triangles(&mesh);
GPUBatch *batch_vertices = DRW_mesh_batch_cache_get_edit_vertices(&mesh);
GPUBatch *batch_edges = DRW_mesh_batch_cache_get_edit_edges(&mesh);
GPUBatch *batch_vnors = DRW_mesh_batch_cache_get_edit_vnors(&mesh);
GPUBatch *batch_lnors = DRW_mesh_batch_cache_get_edit_lnors(&mesh);
GPUBatch *batch_facedots = DRW_mesh_batch_cache_get_edit_facedots(&mesh);
/* Check if caches are empty. */
expect_empty(batch_triangles);
expect_empty(batch_vertices);
expect_empty(batch_edges);
expect_empty(batch_vnors);
expect_empty(batch_lnors);
expect_empty(batch_facedots);
/* Update caches. */
DRW_mesh_batch_cache_create_requested(task_graph, &ob_mesh, &mesh, &scene, false, true);
BLI_task_graph_work_and_wait(task_graph);
/* Check if caches are filled. */
expect_filled(batch_triangles);
expect_filled(batch_vertices);
expect_filled(batch_edges);
expect_filled(batch_vnors);
expect_filled(batch_lnors);
expect_filled(batch_facedots);
}
}
} // namespace blender::draw

View File

@@ -162,6 +162,7 @@ DRAW_TEST(workbench_glsl_shaders)
static void test_gpencil_glsl_shaders()
{
EXPECT_NE(GPENCIL_shader_antialiasing(0), nullptr);
EXPECT_NE(GPENCIL_shader_antialiasing(1), nullptr);
EXPECT_NE(GPENCIL_shader_antialiasing(2), nullptr);
@@ -185,6 +186,7 @@ DRAW_TEST(gpencil_glsl_shaders)
static void test_image_glsl_shaders()
{
IMAGE_shader_library_ensure();
EXPECT_NE(IMAGE_shader_image_get(false), nullptr);
@@ -289,7 +291,7 @@ static void test_overlay_glsl_shaders()
}
DRAW_TEST(overlay_glsl_shaders)
static void test_eevee_glsl_shaders_static()
static void test_eevee_glsl_shaders()
{
EEVEE_shaders_material_shaders_init();
@@ -378,7 +380,7 @@ static void test_eevee_glsl_shaders_static()
EXPECT_NE(EEVEE_shaders_effect_reflection_resolve_sh_get(), nullptr);
EEVEE_shaders_free();
}
DRAW_TEST(eevee_glsl_shaders_static)
DRAW_TEST(eevee_glsl_shaders)
static void test_draw_shaders(eParticleRefineShaderType sh_type)
{

View File

@@ -30,6 +30,7 @@ set(INC
.
intern
opengl
vulkan
../blenkernel
../blenlib
../bmesh
@@ -191,6 +192,49 @@ set(LIB
${BLENDER_GL_LIBRARIES}
)
if(WITH_VULKAN)
list(APPEND INC_SYS
${Vulkan_INCLUDE_DIRS}
)
list(APPEND LIB
extern_vulkan_memory_allocator
bf_intern_shadercompiler
${SHADERC_LIBRARIES}
)
list(APPEND INC
../../../extern/vulkan_memory_allocator
../../../intern/shader_compiler
)
list(APPEND SRC
vulkan/vk_backend.cc
vulkan/vk_context.cc
vulkan/vk_framebuffer.cc
vulkan/vk_texture.cc
vulkan/vk_shader_log.cc
vulkan/vk_shader.cc
vulkan/vk_backend.hh
vulkan/vk_batch.hh
vulkan/vk_context.hh
vulkan/vk_drawlist.hh
vulkan/vk_framebuffer.hh
vulkan/vk_immediate.hh
vulkan/vk_index_buffer.hh
vulkan/vk_primitive.hh
vulkan/vk_query.hh
vulkan/vk_shader_interface.hh
vulkan/vk_shader.hh
vulkan/vk_state.hh
vulkan/vk_texture.hh
vulkan/vk_uniform_buffer.hh
vulkan/vk_vertex_buffer.hh
)
endif()
if(NOT WITH_SYSTEM_GLEW)
list(APPEND LIB
${BLENDER_GLEW_LIBRARIES}
@@ -391,6 +435,12 @@ endif()
blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(bf_gpu
PRIVATE "-Wno-nullability-completeness"
)
endif()
if(CXX_WARN_NO_SUGGEST_OVERRIDE)
target_compile_options(bf_gpu PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wsuggest-override>)
endif()
@@ -399,8 +449,8 @@ if(WITH_GTESTS)
if(WITH_OPENGL_DRAW_TESTS)
set(TEST_SRC
tests/gpu_testing.cc
tests/gpu_index_buffer_test.cc
tests/gpu_shader_compiler_test.cc
tests/gpu_shader_builtin_test.cc
tests/gpu_shader_test.cc
@@ -408,10 +458,11 @@ if(WITH_GTESTS)
)
set(TEST_INC
"../../../intern/ghost/"
"../../../intern/shader_compiler/"
)
set(TEST_LIB
)
include(GTestTesting)
blender_add_test_lib(bf_gpu_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}")
endif()

View File

@@ -35,15 +35,20 @@ extern "C" {
typedef enum eGPUBackendType {
GPU_BACKEND_NONE = 0,
GPU_BACKEND_OPENGL,
#ifdef WITH_VULKAN
GPU_BACKEND_VULKAN,
#endif
} eGPUBackendType;
void GPU_backend_init(eGPUBackendType backend);
void GPU_backend_create(eGPUBackendType backend);
void GPU_backend_exit(void);
/** Opaque type hiding blender::gpu::Context. */
typedef struct GPUContext GPUContext;
GPUContext *GPU_context_create(void *ghost_window);
/* Only one of them must be set. */
/* TODO(fclem) clean this mess. */
GPUContext *GPU_context_create(void *ghost_window, void *ghost_context);
void GPU_context_discard(GPUContext *);
void GPU_context_active_set(GPUContext *);

View File

@@ -46,10 +46,12 @@ class GPUBackend {
static GPUBackend *get(void);
virtual void init() = 0;
virtual void samplers_update(void) = 0;
virtual void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) = 0;
virtual Context *context_alloc(void *ghost_window) = 0;
virtual Context *context_alloc(void *ghost_window, void *ghost_context) = 0;
virtual Batch *batch_alloc(void) = 0;
virtual DrawList *drawlist_alloc(int list_length) = 0;

View File

@@ -34,6 +34,8 @@
#include "BLI_assert.h"
#include "BLI_utildefines.h"
#include "BKE_global.h"
#include "GPU_context.h"
#include "GPU_framebuffer.h"
@@ -49,6 +51,11 @@
# include "gl_context.hh"
#endif
#ifdef WITH_VULKAN
# include "vk_backend.hh"
# include "vk_context.hh"
#endif
#include <mutex>
#include <vector>
@@ -96,16 +103,27 @@ Context *Context::get()
/* -------------------------------------------------------------------- */
GPUContext *GPU_context_create(void *ghost_window)
GPUContext *GPU_context_create(void *ghost_window, void *ghost_context)
{
bool backend_created = false;
if (GPUBackend::get() == nullptr) {
/* TODO: move where it make sense. */
GPU_backend_init(GPU_BACKEND_OPENGL);
/* FIXME We should get the context type from ghost instead of guessing it. */
eGPUBackendType type = GPU_BACKEND_OPENGL;
#ifdef WITH_VULKAN
if (G.debug & G_DEBUG_VK_CONTEXT) {
type = GPU_BACKEND_VULKAN;
}
#endif
backend_created = true;
GPU_backend_create(type);
}
Context *ctx = GPUBackend::get()->context_alloc(ghost_window);
GPUBackend *backend = GPUBackend::get();
Context *ctx = backend->context_alloc(ghost_window, ghost_context);
GPU_context_active_set(wrap(ctx));
if (backend_created) {
backend->init();
}
return wrap(ctx);
}
@@ -164,15 +182,20 @@ void GPU_context_main_unlock(void)
static GPUBackend *g_backend;
void GPU_backend_init(eGPUBackendType backend_type)
void GPU_backend_create(eGPUBackendType backend_type)
{
BLI_assert(g_backend == nullptr);
switch (backend_type) {
#if WITH_OPENGL_BACKEND
#ifdef WITH_OPENGL_BACKEND
case GPU_BACKEND_OPENGL:
g_backend = new GLBackend;
break;
#endif
#ifdef WITH_VULKAN
case GPU_BACKEND_VULKAN:
g_backend = new VKBackend;
break;
#endif
default:
BLI_assert(0);

View File

@@ -47,7 +47,14 @@ class GLBackend : public GPUBackend {
GLSharedOrphanLists shared_orphan_list_;
public:
GLBackend()
~GLBackend()
{
GLTexture::samplers_free();
GLBackend::platform_exit();
}
void init() override
{
/* platform_init needs to go first. */
GLBackend::platform_init();
@@ -55,12 +62,6 @@ class GLBackend : public GPUBackend {
GLBackend::capabilities_init();
GLTexture::samplers_init();
}
~GLBackend()
{
GLTexture::samplers_free();
GLBackend::platform_exit();
}
static GLBackend *get(void)
{
@@ -72,7 +73,7 @@ class GLBackend : public GPUBackend {
GLTexture::samplers_update();
};
Context *context_alloc(void *ghost_window) override
Context *context_alloc(void *ghost_window, void *UNUSED(ghost_context)) override
{
return new GLContext(ghost_window, shared_orphan_list_);
};

View File

@@ -109,6 +109,9 @@ static char *glsl_patch_default_get()
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]);
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]);
/* Converting Vulkan GLSL to OpenGL GLSL. */
STR_CONCAT(patch, slen, "#define gl_VertexIndex gl_VertexID\n");
BLI_assert(slen < sizeof(patch));
return patch;
}

View File

@@ -11,7 +11,7 @@ out vec2 uv;
void main()
{
int corner_id = (gl_VertexID / cornerLen) % 4;
int corner_id = (gl_VertexIndex / cornerLen) % 4;
vec2 final_pos = pos * scale;

View File

@@ -19,7 +19,7 @@ void main()
vec4 tex = calls_data[gl_InstanceID * 3 + 1];
finalColor = calls_data[gl_InstanceID * 3 + 2];
/* Use pos to select the right swizzle (instead of gl_VertexID)
/* Use pos to select the right swizzle (instead of gl_VertexIndex)
* in order to workaround an OSX driver bug. */
if (pos == vec2(0.0, 0.0)) {
rect.xy = rect.xz;

View File

@@ -13,15 +13,15 @@ void main()
{
vec2 uv;
vec2 co;
if (gl_VertexID == 0) {
if (gl_VertexIndex == 0) {
co = rect_geom.xy;
uv = rect_icon.xy;
}
else if (gl_VertexID == 1) {
else if (gl_VertexIndex == 1) {
co = rect_geom.xw;
uv = rect_icon.xw;
}
else if (gl_VertexID == 2) {
else if (gl_VertexIndex == 2) {
co = rect_geom.zw;
uv = rect_icon.zw;
}

View File

@@ -114,7 +114,7 @@ void main(void)
float expand_dist = (uv.y * 2.0 - 1.0);
colorGradient = expand_dist;
if (gl_VertexID < MID_VERTEX) {
if (gl_VertexIndex < MID_VERTEX) {
/* Shadow pass */
finalColor = colShadow;
}

View File

@@ -108,8 +108,8 @@ vec2 do_widget(void)
vec2 do_tria()
{
int vidx = gl_VertexID % 4;
bool tria2 = gl_VertexID > 7;
int vidx = gl_VertexIndex % 4;
bool tria2 = gl_VertexIndex > 7;
vec2 pos;
float size = (tria2) ? -tria2Size : tria1Size;
@@ -204,7 +204,7 @@ vec2 do_tria()
void main()
{
discardFac = discardFactor;
bool is_tria = (gl_VertexID > 3);
bool is_tria = (gl_VertexIndex > 3);
vec2 pos = (is_tria) ? do_tria() : do_widget();
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);

View File

@@ -20,8 +20,8 @@ void main()
interp_size = int(glyph_size.x < 0) + int(glyph_size.y < 0);
/* Quad expension using instanced rendering. */
float x = float(gl_VertexID % 2);
float y = float(gl_VertexID / 2);
float x = float(gl_VertexIndex % 2);
float y = float(gl_VertexIndex / 2);
vec2 quad = vec2(x, y);
vec2 interp_offset = float(interp_size) / abs(pos.zw - pos.xy);

View File

@@ -88,7 +88,6 @@ static void test_shader_builtin()
test_compile_builtin_shader(GPU_SHADER_2D_UV_FACES_STRETCH_AREA, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE, GPU_SHADER_CFG_DEFAULT);
}
GPU_TEST(shader_builtin)
} // namespace blender::gpu::tests

Some files were not shown because too many files have changed in this diff Show More