Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl4
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl6
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/clipbound_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_curve_wire_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl6
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/motion_path_point_vert.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl2
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h12
-rw-r--r--source/blender/draw/intern/draw_manager.c2
-rw-r--r--source/blender/draw/intern/draw_manager_data.c2
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c2
-rw-r--r--source/blender/draw/intern/shaders/common_fullscreen_vert.glsl2
-rw-r--r--source/blender/draw/intern/shaders/common_hair_lib.glsl6
-rw-r--r--source/blender/draw/intern/shaders/common_hair_refine_vert.glsl2
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl4
-rw-r--r--source/blender/draw/tests/draw_testing.cc24
-rw-r--r--source/blender/draw/tests/draw_testing.hh1
-rw-r--r--source/blender/draw/tests/performance_test.cc223
-rw-r--r--source/blender/draw/tests/shaders_test.cc6
-rw-r--r--source/blender/gpu/CMakeLists.txt55
-rw-r--r--source/blender/gpu/GPU_context.h9
-rw-r--r--source/blender/gpu/intern/gpu_backend.hh4
-rw-r--r--source/blender/gpu/intern/gpu_context.cc39
-rw-r--r--source/blender/gpu/opengl/gl_backend.hh17
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc3
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl4
-rw-r--r--source/blender/gpu/tests/gpu_shader_builtin_test.cc1
-rw-r--r--source/blender/gpu/tests/gpu_shader_compiler_test.cc29
-rw-r--r--source/blender/gpu/tests/gpu_testing.cc5
-rw-r--r--source/blender/gpu/tests/gpu_testing.hh39
-rw-r--r--source/blender/gpu/vulkan/vk_backend.cc142
-rw-r--r--source/blender/gpu/vulkan/vk_backend.hh123
-rw-r--r--source/blender/gpu/vulkan/vk_batch.hh64
-rw-r--r--source/blender/gpu/vulkan/vk_context.cc164
-rw-r--r--source/blender/gpu/vulkan/vk_context.hh100
-rw-r--r--source/blender/gpu/vulkan/vk_drawlist.hh57
-rw-r--r--source/blender/gpu/vulkan/vk_framebuffer.cc78
-rw-r--r--source/blender/gpu/vulkan/vk_framebuffer.hh114
-rw-r--r--source/blender/gpu/vulkan/vk_immediate.hh49
-rw-r--r--source/blender/gpu/vulkan/vk_index_buffer.hh46
-rw-r--r--source/blender/gpu/vulkan/vk_primitive.hh53
-rw-r--r--source/blender/gpu/vulkan/vk_query.hh42
-rw-r--r--source/blender/gpu/vulkan/vk_shader.cc281
-rw-r--r--source/blender/gpu/vulkan/vk_shader.hh115
-rw-r--r--source/blender/gpu/vulkan/vk_shader_interface.hh60
-rw-r--r--source/blender/gpu/vulkan/vk_shader_log.cc65
-rw-r--r--source/blender/gpu/vulkan/vk_state.hh61
-rw-r--r--source/blender/gpu/vulkan/vk_texture.cc154
-rw-r--r--source/blender/gpu/vulkan/vk_texture.hh290
-rw-r--r--source/blender/gpu/vulkan/vk_uniform_buffer.hh52
-rw-r--r--source/blender/gpu/vulkan/vk_vertex_buffer.hh77
-rw-r--r--source/blender/python/generic/bgl.c21
-rw-r--r--source/blender/render/intern/pipeline.c2
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c20
78 files changed, 2724 insertions, 104 deletions
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index d6cabbc1236..d9cb8f44bb7 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -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 \
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index b8ca22d33d3..f3f1655f9e4 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -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
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 9a85037ac77..a9bdbb76ebb 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -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);
}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
index f349806d37e..1d552019370 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
@@ -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;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
index c9af2753baa..93225a75cda 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
@@ -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];
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
index 6fefe1319bd..fcadf9dbd82 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
@@ -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 */
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
index 588cd402bb3..4b79ca97e7c 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
@@ -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;
}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
index b70747ecec3..0bc735591ca 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
@@ -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
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
index 07734d19972..31eda3670e9 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 36a52e05a4a..8db831255cd 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -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);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl
index 0c5260a9ec4..34b28f1f5b8 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl
@@ -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));
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
index 8cf8ba121ed..3118e488efc 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/overlay/shaders/clipbound_vert.glsl b/source/blender/draw/engines/overlay/shaders/clipbound_vert.glsl
index 1bfa5dadc32..532b7abc433 100644
--- a/source/blender/draw/engines/overlay/shaders/clipbound_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/clipbound_vert.glsl
@@ -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.
diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_wire_vert.glsl
index 5dd8e579db3..190516efb78 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_curve_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_curve_wire_vert.glsl
@@ -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);
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
index 5aa7fe78e4e..070de772723 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
@@ -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;
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
index 944eb41058e..95c90b16551 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
index 1f3a23324bb..d137286c63e 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
index 59c9d0a665d..a93a5b56e08 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
@@ -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
diff --git a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
index 91f45329018..d00b9a01f70 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl b/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl
index 7486f287a79..35475905a0e 100644
--- a/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/motion_path_line_vert.glsl
@@ -28,7 +28,7 @@ void main()
ssPos = proj(gl_Position);
- int frame = gl_VertexID + cacheStart;
+ int frame = gl_VertexIndex + cacheStart;
float intensity; /* how faint */
diff --git a/source/blender/draw/engines/overlay/shaders/motion_path_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/motion_path_point_vert.glsl
index 14335eb1b99..8fd89414aea 100644
--- a/source/blender/draw/engines/overlay/shaders/motion_path_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/motion_path_point_vert.glsl
@@ -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;
}
diff --git a/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl
index f714646fe40..243c900b5a7 100644
--- a/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/volume_gridlines_vert.glsl
@@ -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);
diff --git a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
index 174b31b6816..7ed93033682 100644
--- a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
@@ -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
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index 060b7a957c1..fa32ef9e31b 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -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
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl
index 07734d19972..31eda3670e9 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl
@@ -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);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 220a7f37c3d..205feba7eb1 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -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);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 1d9bc607590..8f2727cc751 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -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();
}
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index c98ecc8ac00..42d61c881b0 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -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)
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 83d0030f89b..a69a185f3d4 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -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);
diff --git a/source/blender/draw/intern/shaders/common_fullscreen_vert.glsl b/source/blender/draw/intern/shaders/common_fullscreen_vert.glsl
index 8a7fb97d98c..9fdee29cbd9 100644
--- a/source/blender/draw/intern/shaders/common_fullscreen_vert.glsl
+++ b/source/blender/draw/intern/shaders/common_fullscreen_vert.glsl
@@ -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);
diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl
index 6cc7f09a852..20763d70794 100644
--- a/source/blender/draw/intern/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl
@@ -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.
diff --git a/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl b/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
index 371d43827b9..151bdf69032 100644
--- a/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
+++ b/source/blender/draw/intern/shaders/common_hair_refine_vert.glsl
@@ -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;
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index a980b87821a..269be150fb7 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -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
diff --git a/source/blender/draw/tests/draw_testing.cc b/source/blender/draw/tests/draw_testing.cc
index 45a857e7577..5087e7e494d 100644
--- a/source/blender/draw/tests/draw_testing.cc
+++ b/source/blender/draw/tests/draw_testing.cc
@@ -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
diff --git a/source/blender/draw/tests/draw_testing.hh b/source/blender/draw/tests/draw_testing.hh
index 00f0ac5bab7..74712c10d49 100644
--- a/source/blender/draw/tests/draw_testing.hh
+++ b/source/blender/draw/tests/draw_testing.hh
@@ -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) \
diff --git a/source/blender/draw/tests/performance_test.cc b/source/blender/draw/tests/performance_test.cc
new file mode 100644
index 00000000000..6d22039e907
--- /dev/null
+++ b/source/blender/draw/tests/performance_test.cc
@@ -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
diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc
index ef702821a59..e955e2edf62 100644
--- a/source/blender/draw/tests/shaders_test.cc
+++ b/source/blender/draw/tests/shaders_test.cc
@@ -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)
{
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 4868096e594..e7b543ef8f3 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -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()
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index 82f13424502..9939f844ff8 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -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 *);
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index 73792215569..c0774c3b61e 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -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;
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 943a6151ced..2748dffd95f 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -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,16 +182,21 @@ 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);
break;
diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh
index e9dcdffced0..bb220a699ae 100644
--- a/source/blender/gpu/opengl/gl_backend.hh
+++ b/source/blender/gpu/opengl/gl_backend.hh
@@ -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_);
};
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 66a1bd5ceb7..6c9e54608c3 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -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;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl
index d20ddcd27c0..f85cea69880 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl
@@ -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;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
index bdc0d37a7ae..f76c590e961 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
@@ -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;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
index ab9c30505c2..d3cca9e0d84 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
@@ -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;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
index 8325568988c..fb7920972bd 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -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;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
index b5036b51d9d..2162f3433ce 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -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);
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
index 768638e5229..62e9ffde5a2 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -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);
diff --git a/source/blender/gpu/tests/gpu_shader_builtin_test.cc b/source/blender/gpu/tests/gpu_shader_builtin_test.cc
index 523a7e5b881..dfb1f6bad2a 100644
--- a/source/blender/gpu/tests/gpu_shader_builtin_test.cc
+++ b/source/blender/gpu/tests/gpu_shader_builtin_test.cc
@@ -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
diff --git a/source/blender/gpu/tests/gpu_shader_compiler_test.cc b/source/blender/gpu/tests/gpu_shader_compiler_test.cc
new file mode 100644
index 00000000000..37eb4608cb6
--- /dev/null
+++ b/source/blender/gpu/tests/gpu_shader_compiler_test.cc
@@ -0,0 +1,29 @@
+/* Apache License, Version 2.0 */
+
+#include "gpu_testing.hh"
+#include "shader_compiler.hh"
+
+namespace blender::gpu::tests {
+
+#ifdef WITH_VULKAN
+TEST_F(GPUVulkanTest, shader_compiler)
+{
+ std::string 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;
+}
+#endif
+
+} // namespace blender::gpu::tests \ No newline at end of file
diff --git a/source/blender/gpu/tests/gpu_testing.cc b/source/blender/gpu/tests/gpu_testing.cc
index 7fd473069c2..0f8ef02d9ed 100644
--- a/source/blender/gpu/tests/gpu_testing.cc
+++ b/source/blender/gpu/tests/gpu_testing.cc
@@ -2,6 +2,7 @@
#include "testing/testing.h"
+#include "BKE_global.h"
#include "CLG_log.h"
#include "GPU_context.h"
@@ -17,9 +18,9 @@ void GPUTest::SetUp()
GHOST_GLSettings glSettings = {0};
CLG_init();
ghost_system = GHOST_CreateSystem();
- ghost_context = GHOST_CreateOpenGLContext(ghost_system, glSettings);
+ ghost_context = GHOST_CreateOpenGLContext(ghost_system, draw_context_type, glSettings);
GHOST_ActivateOpenGLContext(ghost_context);
- context = GPU_context_create(nullptr);
+ context = GPU_context_create(NULL, ghost_context);
GPU_init();
}
diff --git a/source/blender/gpu/tests/gpu_testing.hh b/source/blender/gpu/tests/gpu_testing.hh
index c45770cb94e..cd13eb85bd1 100644
--- a/source/blender/gpu/tests/gpu_testing.hh
+++ b/source/blender/gpu/tests/gpu_testing.hh
@@ -2,6 +2,8 @@
#include "GHOST_C-api.h"
+#include "BKE_global.h"
+
struct GPUContext;
namespace blender::gpu {
@@ -33,13 +35,42 @@ class GPUOpenGLTest : public GPUTest {
public:
GPUOpenGLTest() : GPUTest(GHOST_kDrawingContextTypeOpenGL)
{
+ G.debug &= ~G_DEBUG_VK_CONTEXT;
}
};
-#define GPU_TEST(test_name) \
- TEST_F(GPUOpenGLTest, test_name) \
- { \
- test_##test_name(); \
+#ifdef WITH_VULKAN
+
+class GPUVulkanTest : public GPUTest {
+ public:
+ GPUVulkanTest() : GPUTest(GHOST_kDrawingContextTypeVulkan)
+ {
+ G.debug |= G_DEBUG_VK_CONTEXT;
}
+};
+
+#endif
+
+#ifdef WITH_VULKAN
+
+# define GPU_TEST(test_name) \
+ TEST_F(GPUOpenGLTest, test_name) \
+ { \
+ test_##test_name(); \
+ } \
+ TEST_F(GPUVulkanTest, test_name) \
+ { \
+ test_##test_name(); \
+ }
+
+#else /* WITH_VULKAN */
+
+# define GPU_TEST(test_name) \
+ TEST_F(GPUOpenGLTest, test_name) \
+ { \
+ test_##test_name(); \
+ }
+
+#endif /* WITH_VULKAN */
} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc
new file mode 100644
index 00000000000..1c75e0dc193
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_backend.cc
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "BKE_global.h"
+
+#include "gpu_capabilities_private.hh"
+#include "gpu_platform_private.hh"
+
+#include "vk_backend.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Platform
+ * \{ */
+
+static std::string api_version_get(VkPhysicalDeviceProperties &properties)
+{
+ uint32_t major = VK_VERSION_MAJOR(properties.driverVersion);
+ uint32_t minor = VK_VERSION_MINOR(properties.driverVersion);
+ uint32_t patch = VK_VERSION_PATCH(properties.driverVersion);
+
+ std::stringstream version;
+ version << major << "." << minor << "." << patch;
+ return version.str();
+}
+
+enum class VendorID : uint32_t {
+ AMD = 0x1002,
+ Intel = 0x1F96,
+ NVIDIA = 0x10de,
+};
+static constexpr StringRef VENDOR_NAME_AMD = "Advanced Micro Devices";
+static constexpr StringRef VENDOR_NAME_INTEL = "Intel";
+static constexpr StringRef VENDOR_NAME_NVIDIA = "NVIDIA";
+static constexpr StringRef VENDOR_NAME_UNKNOWN = "Unknown";
+
+static constexpr StringRef vendor_name_get(VendorID vendor_id)
+{
+ switch (vendor_id) {
+ case VendorID::AMD:
+ return VENDOR_NAME_AMD;
+ case VendorID::Intel:
+ return VENDOR_NAME_INTEL;
+ case VendorID::NVIDIA:
+ return VENDOR_NAME_NVIDIA;
+ }
+ return VENDOR_NAME_UNKNOWN;
+}
+
+static VendorID vendor_id_get(VkPhysicalDeviceProperties &properties)
+{
+ return static_cast<VendorID>(properties.vendorID);
+}
+
+void VKBackend::platform_init(void)
+{
+ BLI_assert(!GPG.initialized);
+
+ VKContext *context = VKContext::get();
+ VkPhysicalDeviceProperties physical_device_properties;
+ VkPhysicalDevice physical_device = context->physical_device_get();
+ vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);
+ const VendorID vendor_id = vendor_id_get(physical_device_properties);
+ const std::string vendor = vendor_name_get(vendor_id);
+ const std::string renderer = physical_device_properties.deviceName;
+ const std::string version = api_version_get(physical_device_properties).c_str();
+ eGPUDeviceType device = GPU_DEVICE_ANY;
+ eGPUOSType os = GPU_OS_ANY;
+ eGPUDriverType driver = GPU_DRIVER_ANY;
+ eGPUSupportLevel support_level = GPU_SUPPORT_LEVEL_SUPPORTED;
+
+#ifdef _WIN32
+ os = GPU_OS_WIN;
+#elif defined(__APPLE__)
+ os = GPU_OS_MAC;
+#else
+ os = GPU_OS_UNIX;
+#endif
+
+ /* TODO(jbakker): extract the driver type. */
+ if (vendor_id == VendorID::AMD) {
+ device = GPU_DEVICE_ATI;
+ }
+ else if (vendor_id == VendorID::Intel) {
+ device = GPU_DEVICE_INTEL;
+ }
+ else if (vendor_id == VendorID::NVIDIA) {
+ device = GPU_DEVICE_NVIDIA;
+ }
+
+ GPG.init(device, os, driver, support_level, vendor.c_str(), renderer.c_str(), version.c_str());
+}
+
+void VKBackend::platform_exit(void)
+{
+ BLI_assert(GPG.initialized);
+ GPG.clear();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Capabilities
+ * \{ */
+
+void VKBackend::capabilities_init(void)
+{
+ /* Common Capabilities. */
+ GCaps.max_texture_size = 2048;
+ GCaps.max_texture_layers = 64;
+ GCaps.max_textures_frag = 16;
+ GCaps.max_textures_vert = 16;
+ GCaps.max_textures_geom = 16;
+ GCaps.max_textures = 46;
+ GCaps.mem_stats_support = false;
+ GCaps.shader_image_load_store_support = false;
+}
+
+/** \} */
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_backend.hh b/source/blender/gpu/vulkan/vk_backend.hh
new file mode 100644
index 00000000000..d189f7158e7
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_backend.hh
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_backend.hh"
+
+#include "vk_batch.hh"
+#include "vk_context.hh"
+#include "vk_drawlist.hh"
+#include "vk_framebuffer.hh"
+#include "vk_index_buffer.hh"
+#include "vk_query.hh"
+#include "vk_shader.hh"
+#include "vk_texture.hh"
+#include "vk_uniform_buffer.hh"
+#include "vk_vertex_buffer.hh"
+
+namespace blender {
+namespace gpu {
+
+class VKBackend : public GPUBackend {
+ public:
+ ~VKBackend()
+ {
+ VKBackend::platform_exit();
+ }
+
+ void init() override
+ {
+ /* platform_init needs to go first. */
+ VKBackend::platform_init();
+
+ VKBackend::capabilities_init();
+ }
+
+ static VKBackend *get(void)
+ {
+ return static_cast<VKBackend *>(GPUBackend::get());
+ };
+
+ void samplers_update(void) override{};
+ void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override{};
+
+ Context *context_alloc(void *ghost_window, void *ghost_context) override
+ {
+ return new VKContext(ghost_window, ghost_context);
+ };
+
+ Batch *batch_alloc(void) override
+ {
+ return new VKBatch();
+ };
+
+ DrawList *drawlist_alloc(int list_length) override
+ {
+ return new VKDrawList(list_length);
+ };
+
+ FrameBuffer *framebuffer_alloc(const char *name) override
+ {
+ return new VKFrameBuffer(name);
+ };
+
+ IndexBuf *indexbuf_alloc(void) override
+ {
+ return new VKIndexBuf();
+ };
+
+ QueryPool *querypool_alloc(void) override
+ {
+ return new VKQueryPool();
+ };
+
+ Shader *shader_alloc(const char *name) override
+ {
+ return new VKShader(name);
+ };
+
+ Texture *texture_alloc(const char *name) override
+ {
+ return new VKTexture(name);
+ };
+
+ UniformBuf *uniformbuf_alloc(int size, const char *name) override
+ {
+ return new VKUniformBuf(size, name);
+ };
+
+ VertBuf *vertbuf_alloc(void) override
+ {
+ return new VKVertBuf();
+ };
+
+ private:
+ static void platform_init(void);
+ static void platform_exit(void);
+
+ static void capabilities_init(void);
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_batch.hh b/source/blender/gpu/vulkan/vk_batch.hh
new file mode 100644
index 00000000000..84be5a91b0b
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_batch.hh
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU geometry batch
+ * Contains VAOs + VBOs + Shader representing a drawable entity.
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_batch_private.hh"
+
+#include "vk_index_buffer.hh"
+#include "vk_vertex_buffer.hh"
+
+namespace blender {
+namespace gpu {
+
+class VKBatch : public Batch {
+ public:
+ VKBatch(){};
+ ~VKBatch(){};
+
+ void draw(int v_first, int v_count, int i_first, int i_count) override{};
+
+ /* Convenience getters. */
+ VKIndexBuf *elem_(void) const
+ {
+ return static_cast<VKIndexBuf *>(unwrap(elem));
+ }
+ VKVertBuf *verts_(const int index) const
+ {
+ return static_cast<VKVertBuf *>(unwrap(verts[index]));
+ }
+ VKVertBuf *inst_(const int index) const
+ {
+ return static_cast<VKVertBuf *>(unwrap(inst[index]));
+ }
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKBatch");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_context.cc b/source/blender/gpu/vulkan/vk_context.cc
new file mode 100644
index 00000000000..c19a68cd4f4
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_context.cc
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "GHOST_C-api.h"
+
+#include "vk_framebuffer.hh"
+#include "vk_immediate.hh"
+#include "vk_state.hh"
+
+#include "vk_context.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Constructor / Destructor
+ * \{ */
+
+VKContext::VKContext(void *ghost_window, void *ghost_context)
+{
+ ghost_window_ = ghost_window;
+
+ if (ghost_window != nullptr) {
+ ghost_context = GHOST_GetDrawingContext((GHOST_WindowHandle)ghost_window);
+ }
+
+ state_manager = new VKStateManager();
+ imm = new VKImmediate();
+
+ GHOST_GetVulkanHandles((GHOST_ContextHandle)ghost_context,
+ &instance_,
+ &physical_device_,
+ &device_,
+ &graphic_queue_familly_);
+
+ vkGetDeviceQueue(device_, graphic_queue_familly_, 0, &graphic_queue_);
+
+ {
+ VkCommandPoolCreateInfo info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
+ info.queueFamilyIndex = graphic_queue_familly_;
+ vkCreateCommandPool(device_, &info, nullptr, &graphic_cmd_pool_);
+ }
+
+ /* For offscreen contexts. Default framebuffer is empty. */
+ active_fb = back_left = new VKFrameBuffer("back_left");
+
+ {
+ VmaAllocatorCreateInfo info = {};
+ /* TODO use same vulkan version as GHOST. */
+ info.vulkanApiVersion = VK_API_VERSION_1_0;
+ info.physicalDevice = physical_device_;
+ info.device = device_;
+ info.instance = instance_;
+ vmaCreateAllocator(&info, &mem_allocator_);
+ }
+}
+
+VKContext::~VKContext()
+{
+ vkDestroyCommandPool(device_, graphic_cmd_pool_, nullptr);
+ vmaDestroyAllocator(mem_allocator_);
+}
+
+void VKContext::activate()
+{
+ if (ghost_window_) {
+ VkImage image; /* TODO will be used for reading later... */
+ VkFramebuffer framebuffer;
+ VkCommandBuffer command_buffer;
+ VkRenderPass render_pass;
+ VkExtent2D extent;
+ uint32_t fb_id;
+
+ GHOST_GetVulkanBackbuffer((GHOST_WindowHandle)ghost_window_,
+ &image,
+ &framebuffer,
+ &command_buffer,
+ &render_pass,
+ &extent,
+ &fb_id);
+
+ if (fb_id != fb_id_) {
+ /* Recreate the gpu::VKFrameBuffer wrapper after every swap. */
+ delete back_left;
+ }
+
+ back_left = new VKFrameBuffer("back_left", framebuffer, command_buffer, render_pass, extent);
+ active_fb = back_left;
+ }
+
+ immActivate();
+}
+
+void VKContext::deactivate()
+{
+ immDeactivate();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Command buffers
+ * \{ */
+
+VkCommandBuffer VKContext::single_use_command_buffer_begin(void)
+{
+ VkCommandBuffer cmd_buf;
+ {
+ VkCommandBufferAllocateInfo info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
+ info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ info.commandPool = graphic_cmd_pool_;
+ info.commandBufferCount = 1;
+ vkAllocateCommandBuffers(device_, &info, &cmd_buf);
+ }
+ {
+ VkCommandBufferBeginInfo info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
+ info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ vkBeginCommandBuffer(cmd_buf, &info);
+ }
+ return cmd_buf;
+}
+
+void VKContext::single_use_command_buffer_end(VkCommandBuffer cmd_buf)
+{
+ vkEndCommandBuffer(cmd_buf);
+
+ this->submit_and_wait(cmd_buf);
+
+ vkFreeCommandBuffers(device_, graphic_cmd_pool_, 1, &cmd_buf);
+}
+
+void VKContext::submit_and_wait(VkCommandBuffer cmd_buf)
+{
+ {
+ VkSubmitInfo info = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
+ info.commandBufferCount = 1;
+ info.pCommandBuffers = &cmd_buf;
+ vkQueueSubmit(graphic_queue_, 1, &info, VK_NULL_HANDLE);
+ }
+ vkQueueWaitIdle(graphic_queue_);
+}
+
+/** \} */
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh
new file mode 100644
index 00000000000..0a78ef356c6
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_context.hh
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_context_private.hh"
+
+#include "vk_mem_alloc.h"
+
+#include <vulkan/vulkan.h>
+
+#include "vk_state.hh"
+
+namespace blender {
+namespace gpu {
+
+class VKContext : public Context {
+ public:
+ /** Capabilities. */
+ /** Extensions. */
+ /** Workarounds. */
+
+ private:
+ /** Copies of the handles owned by the GHOST context. */
+ VkInstance instance_ = VK_NULL_HANDLE;
+ VkPhysicalDevice physical_device_ = VK_NULL_HANDLE;
+ VkDevice device_ = VK_NULL_HANDLE;
+ VkQueue graphic_queue_ = VK_NULL_HANDLE;
+ uint32_t graphic_queue_familly_ = 0;
+
+ /** Command pool for graphics. */
+ VkCommandPool graphic_cmd_pool_ = VK_NULL_HANDLE;
+ /** Allocator used for texture and buffers. */
+ VmaAllocator mem_allocator_ = VK_NULL_HANDLE;
+ /** Last used framebuffer ghost UUID.
+ * This is used to detect when to recreate the #VKFrameBuffer. */
+ uint32_t fb_id_ = -1;
+
+ public:
+ VKContext(void *ghost_window, void *ghost_context);
+ ~VKContext();
+
+ void activate(void) override;
+ void deactivate(void) override;
+
+ void flush(void) override{};
+ void finish(void) override{};
+
+ void memory_statistics_get(int *total_mem, int *free_mem) override{};
+
+ static VKContext *get(void)
+ {
+ return static_cast<VKContext *>(Context::get());
+ }
+
+ VkDevice device_get(void) const
+ {
+ return device_;
+ }
+
+ VkPhysicalDevice physical_device_get() const
+ {
+ return physical_device_;
+ }
+
+ VmaAllocator mem_allocator_get(void) const
+ {
+ return mem_allocator_;
+ }
+
+ /* Command buffers */
+ VkCommandBuffer single_use_command_buffer_begin(void);
+ void single_use_command_buffer_end(VkCommandBuffer cmd_buf);
+ void submit_and_wait(VkCommandBuffer cmd_buf);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKContext")
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_drawlist.hh b/source/blender/gpu/vulkan/vk_drawlist.hh
new file mode 100644
index 00000000000..3989a1f8ab9
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_drawlist.hh
@@ -0,0 +1,57 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Implementation of Multi Draw Indirect using OpenGL.
+ * Fallback if the needed extensions are not supported.
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_sys_types.h"
+
+#include "GPU_batch.h"
+
+#include "gpu_drawlist_private.hh"
+
+#include "vk_context.hh"
+
+namespace blender {
+namespace gpu {
+
+/**
+ * Implementation of Multi Draw Indirect using OpenGL.
+ **/
+class VKDrawList : public DrawList {
+ public:
+ VKDrawList(int length){};
+ ~VKDrawList(){};
+
+ void append(GPUBatch *batch, int i_first, int i_count) override{};
+ void submit(void) override{};
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKDrawList");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_framebuffer.cc b/source/blender/gpu/vulkan/vk_framebuffer.cc
new file mode 100644
index 00000000000..5335af373be
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_framebuffer.cc
@@ -0,0 +1,78 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "BLI_vector.hh"
+
+#include "vk_context.hh"
+#include "vk_texture.hh"
+
+#include "vk_framebuffer.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Creation & Deletion
+ * \{ */
+
+VKFrameBuffer::VKFrameBuffer(const char *name) : FrameBuffer(name)
+{
+ /* Just-In-Time init. See #VKFrameBuffer::init(). */
+ immutable_ = false;
+}
+
+VKFrameBuffer::VKFrameBuffer(const char *name,
+ VkFramebuffer framebuffer,
+ VkCommandBuffer command_buffer,
+ VkRenderPass render_pass,
+ VkExtent2D extent)
+ : FrameBuffer(name)
+{
+ immutable_ = true;
+ /* Never update an internal frame-buffer. */
+ dirty_attachments_ = false;
+ width_ = extent.width;
+ height_ = extent.height;
+ vk_fb_ = framebuffer;
+
+ viewport_[0] = scissor_[0] = 0;
+ viewport_[1] = scissor_[1] = 0;
+ viewport_[2] = scissor_[2] = width_;
+ viewport_[3] = scissor_[3] = height_;
+}
+
+VKFrameBuffer::~VKFrameBuffer()
+{
+ if (!immutable_ && vk_fb_ != VK_NULL_HANDLE) {
+ vkDestroyFramebuffer(vk_device_, vk_fb_, NULL);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Config
+ * \{ */
+
+/** \} */
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_framebuffer.hh b/source/blender/gpu/vulkan/vk_framebuffer.hh
new file mode 100644
index 00000000000..abe92abfe8c
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_framebuffer.hh
@@ -0,0 +1,114 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Encapsulation of Framebuffer states (attached textures, viewport, scissors).
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include <vulkan/vulkan.h>
+
+#include "gpu_framebuffer_private.hh"
+
+namespace blender::gpu {
+
+class VKContext;
+
+#define VK_MAX_ATTACHMENT (GPU_FB_MAX_COLOR_ATTACHMENT + 1)
+
+/**
+ * Implementation of FrameBuffer object using Vulkan.
+ **/
+class VKFrameBuffer : public FrameBuffer {
+ private:
+ /* Vulkan object handle. */
+ VkFramebuffer vk_fb_ = VK_NULL_HANDLE;
+ /* Vulkan device who created the handle. */
+ VkDevice vk_device_ = VK_NULL_HANDLE;
+ /* Base render pass used for framebuffer creation. */
+ VkRenderPass render_pass_ = VK_NULL_HANDLE;
+ /* Number of layers if the attachments are layered textures. */
+ int depth_ = 1;
+ /** Internal frame-buffers are immutable. */
+ bool immutable_;
+
+ public:
+ /**
+ * Create a conventional framebuffer to attach texture to.
+ **/
+ VKFrameBuffer(const char *name);
+
+ /**
+ * Special frame-buffer encapsulating internal window frame-buffer.
+ * This just act as a wrapper, the actual allocations are done by GHOST_ContextVK.
+ **/
+ VKFrameBuffer(const char *name,
+ VkFramebuffer framebuffer,
+ VkCommandBuffer command_buffer,
+ VkRenderPass render_pass,
+ VkExtent2D extent);
+
+ ~VKFrameBuffer();
+
+ void bind(bool enabled_srgb) override{};
+
+ bool check(char err_out[256]) override
+ {
+ return true;
+ };
+
+ void clear(eGPUFrameBufferBits buffers,
+ const float clear_col[4],
+ float clear_depth,
+ uint clear_stencil) override{};
+ void clear_multi(const float (*clear_cols)[4]) override{};
+ void clear_attachment(GPUAttachmentType type,
+ eGPUDataFormat data_format,
+ const void *clear_value) override{};
+
+ void read(eGPUFrameBufferBits planes,
+ eGPUDataFormat format,
+ const int area[4],
+ int channel_len,
+ int slot,
+ void *r_data) override{};
+
+ void blit_to(eGPUFrameBufferBits planes,
+ int src_slot,
+ FrameBuffer *dst,
+ int dst_slot,
+ int dst_offset_x,
+ int dst_offset_y) override{};
+
+ private:
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKFrameBuffer");
+};
+
+/* -------------------------------------------------------------------- */
+/** \name Enums Conversion
+ * \{ */
+
+/** \} */
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_immediate.hh b/source/blender/gpu/vulkan/vk_immediate.hh
new file mode 100644
index 00000000000..587c77b4aaa
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_immediate.hh
@@ -0,0 +1,49 @@
+/*
+ * 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) 2016 by Mike Erwin.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Mimics old style opengl immediate mode drawing.
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_immediate_private.hh"
+
+namespace blender::gpu {
+
+class VKImmediate : public Immediate {
+ private:
+ uchar data_[4 * 1024 * 1024];
+
+ public:
+ VKImmediate(){};
+ ~VKImmediate(){};
+
+ uchar *begin(void) override
+ {
+ return data_;
+ };
+ void end(void) override{};
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_index_buffer.hh b/source/blender/gpu/vulkan/vk_index_buffer.hh
new file mode 100644
index 00000000000..8e1428c66f3
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_index_buffer.hh
@@ -0,0 +1,46 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_index_buffer_private.hh"
+
+namespace blender::gpu {
+
+class VKIndexBuf : public IndexBuf {
+ public:
+ ~VKIndexBuf(){};
+
+ void bind_as_ssbo(uint binding) override{};
+
+ const uint32_t *read() const override
+ {
+ return nullptr;
+ };
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKIndexBuf")
+};
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_primitive.hh b/source/blender/gpu/vulkan/vk_primitive.hh
new file mode 100644
index 00000000000..fbc28388b3a
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_primitive.hh
@@ -0,0 +1,53 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Encapsulation of Framebuffer states (attached textures, viewport, scissors).
+ */
+
+#pragma once
+
+#include "BLI_assert.h"
+
+#include "GPU_primitive.h"
+
+namespace blender::gpu {
+
+static inline GLenum to_gl(GPUPrimType prim_type)
+{
+ BLI_assert(prim_type != GPU_PRIM_NONE);
+ switch (prim_type) {
+ default:
+ case GPU_PRIM_POINTS:
+ case GPU_PRIM_LINES:
+ case GPU_PRIM_LINE_STRIP:
+ case GPU_PRIM_LINE_LOOP:
+ case GPU_PRIM_TRIS:
+ case GPU_PRIM_TRI_STRIP:
+ case GPU_PRIM_TRI_FAN:
+ case GPU_PRIM_LINES_ADJ:
+ case GPU_PRIM_LINE_STRIP_ADJ:
+ case GPU_PRIM_TRIS_ADJ:
+ return 0;
+ };
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_query.hh b/source/blender/gpu/vulkan/vk_query.hh
new file mode 100644
index 00000000000..f6579339329
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_query.hh
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "gpu_query.hh"
+
+namespace blender::gpu {
+
+class VKQueryPool : public QueryPool {
+ public:
+ ~VKQueryPool(){};
+
+ void init(GPUQueryType type) override{};
+
+ void begin_query(void) override{};
+ void end_query(void) override{};
+
+ void get_occlusion_result(MutableSpan<uint32_t> r_values) override{};
+};
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc
new file mode 100644
index 00000000000..4f2af6093af
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader.cc
@@ -0,0 +1,281 @@
+/*
+ * 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 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_shader.hh"
+
+#include <string>
+
+#include "BLI_vector.hh"
+
+#include "shader_compiler.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Shader stages
+ * \{ */
+
+constexpr StringRef SHADER_STAGE_VERTEX_SHADER = "vertex";
+constexpr StringRef SHADER_STAGE_GEOMETRY_SHADER = "geometry";
+constexpr StringRef SHADER_STAGE_FRAGMENT_SHADER = "fragment";
+constexpr StringRef SHADER_STAGE_COMPUTE_SHADER = "compute";
+
+std::ostream &operator<<(std::ostream &os, const VKShaderStageType &stage)
+{
+ switch (stage) {
+ case VKShaderStageType::VertexShader:
+ os << SHADER_STAGE_VERTEX_SHADER;
+ break;
+ case VKShaderStageType::GeometryShader:
+ os << SHADER_STAGE_GEOMETRY_SHADER;
+ break;
+ case VKShaderStageType::FragmentShader:
+ os << SHADER_STAGE_FRAGMENT_SHADER;
+ break;
+ case VKShaderStageType::ComputeShader:
+ os << SHADER_STAGE_COMPUTE_SHADER;
+ break;
+ }
+ return os;
+}
+
+static shader_compiler::SourceType to_source_type(VKShaderStageType stage)
+{
+ switch (stage) {
+ case VKShaderStageType::VertexShader:
+ return shader_compiler::SourceType::GlslVertexShader;
+ break;
+ case VKShaderStageType::GeometryShader:
+ return shader_compiler::SourceType::GlslGeometryShader;
+ break;
+ case VKShaderStageType::FragmentShader:
+ return shader_compiler::SourceType::GlslFragmentShader;
+ break;
+ case VKShaderStageType::ComputeShader:
+ return shader_compiler::SourceType::GlslComputeShader;
+ break;
+ }
+ BLI_assert(!"Unknown VKShaderStageType.");
+ return shader_compiler::SourceType::GlslVertexShader;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Construction/Destruction
+ * \{ */
+
+VKShader::VKShader(const char *name) : Shader(name)
+{
+ interface = new VKShaderInterface();
+ context_ = VKContext::get();
+};
+
+VKShader::~VKShader()
+{
+ VkDevice device = context_->device_get();
+ if (vertex_shader_ != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(device, vertex_shader_, nullptr);
+ vertex_shader_ = VK_NULL_HANDLE;
+ }
+ if (geometry_shader_ != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(device, geometry_shader_, nullptr);
+ geometry_shader_ = VK_NULL_HANDLE;
+ }
+ if (fragment_shader_ != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(device, fragment_shader_, nullptr);
+ fragment_shader_ = VK_NULL_HANDLE;
+ }
+ if (compute_shader_ != VK_NULL_HANDLE) {
+ vkDestroyShaderModule(device, compute_shader_, nullptr);
+ compute_shader_ = VK_NULL_HANDLE;
+ }
+
+ context_ = nullptr;
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Compilation
+ * \{ */
+
+static std::string to_stage_name(VKShaderStageType stage)
+{
+ std::stringstream ss;
+ ss << stage;
+ return ss.str();
+}
+
+static std::string to_stage_name(StringRef name, VKShaderStageType stage)
+{
+ std::stringstream ss;
+ ss << name << "." << stage;
+ return ss.str();
+}
+
+static std::string combine_sources(Span<const char *> sources)
+{
+ std::stringstream combined;
+ for (int i = 0; i < sources.size(); i++) {
+ combined << sources[i];
+ }
+ return combined.str();
+}
+static char *glsl_patch_get()
+{
+ static char patch[512] = "\0";
+ if (patch[0] != '\0') {
+ return patch;
+ }
+
+ size_t slen = 0;
+ /* Version need to go first. */
+ STR_CONCAT(patch, slen, "#version 330\n");
+
+ BLI_assert(slen < sizeof(patch));
+ return patch;
+}
+
+std::unique_ptr<std::vector<uint32_t>> VKShader::compile_source(Span<const char *> sources,
+ VKShaderStageType stage)
+{
+ std::string stage_name = to_stage_name(name, stage);
+
+ std::string source = combine_sources(sources);
+
+ shader_compiler::Compiler *compiler = shader_compiler::Compiler::create_default();
+ shader_compiler::Job job;
+ job.name = stage_name;
+ job.source = source;
+ job.compilation_target = shader_compiler::TargetType::SpirV;
+ job.source_type = to_source_type(stage);
+
+ shader_compiler::Result *result = compiler->compile(job);
+
+ if (!result) {
+ return std::make_unique<std::vector<uint32_t>>();
+ }
+
+ /* Log compilation errors/warnings. */
+ if (!result->error_log.empty()) {
+ const char *error_log = result->error_log.c_str();
+ std::vector<char> error(error_log, error_log + result->error_log.size() + 1);
+ VKLogParser parser;
+ print_log(sources,
+ error.data(),
+ to_stage_name(stage).c_str(),
+ result->status_code == shader_compiler::StatusCode::CompilationError,
+ &parser);
+ BLI_assert(!"Failed to compile shader!");
+ }
+
+ /* Retrieve compiled code. */
+ std::unique_ptr<std::vector<uint32_t>> bin = std::make_unique<std::vector<uint32_t>>();
+ switch (result->status_code) {
+ case shader_compiler::StatusCode::Ok:
+ bin = std::make_unique<std::vector<uint32_t>>(std::move(result->bin));
+ break;
+ case shader_compiler::StatusCode::CompilationError:
+ break;
+ }
+
+ delete result;
+ delete compiler;
+ return bin;
+}
+
+VkShaderModule VKShader::create_shader_module(MutableSpan<const char *> sources,
+ VKShaderStageType stage)
+{
+ /* Patch the shader code using the first source slot. */
+ sources[0] = glsl_patch_get();
+
+ std::unique_ptr<std::vector<uint32_t>> code = compile_source(sources, stage);
+ if (!code || code->size() == 0) {
+ compilation_failed_ = true;
+ return VK_NULL_HANDLE;
+ }
+
+ VkDevice device = context_->device_get();
+ VkShaderModuleCreateInfo shader_info = {};
+ shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shader_info.codeSize = code->size();
+ shader_info.pCode = reinterpret_cast<const uint32_t *>(code->data());
+
+ VkShaderModule shader_module;
+ if (vkCreateShaderModule(device, &shader_info, nullptr, &shader_module) != VK_SUCCESS) {
+ return VK_NULL_HANDLE;
+ }
+
+ return shader_module;
+}
+
+void VKShader::vertex_shader_from_glsl(MutableSpan<const char *> sources)
+{
+#ifdef WITH_VULKAN_SHADER_COMPILATION
+ vertex_shader_ = this->create_shader_module(sources, VKShaderStageType::VertexShader);
+#endif
+}
+
+void VKShader::geometry_shader_from_glsl(MutableSpan<const char *> sources)
+{
+#ifdef WITH_VULKAN_SHADER_COMPILATION
+ geometry_shader_ = this->create_shader_module(sources, VKShaderStageType::GeometryShader);
+#endif
+}
+
+void VKShader::fragment_shader_from_glsl(MutableSpan<const char *> sources)
+{
+#ifdef WITH_VULKAN_SHADER_COMPILATION
+ fragment_shader_ = this->create_shader_module(sources, VKShaderStageType::FragmentShader);
+#endif
+}
+
+void VKShader::compute_shader_from_glsl(MutableSpan<const char *> sources)
+{
+#ifdef WITH_VULKAN_SHADER_COMPILATION
+ compute_shader_ = this->create_shader_module(sources, VKShaderStageType::ComputeShader);
+#endif
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Linking
+ * \{ */
+
+bool VKShader::finalize(void)
+{
+#ifdef WITH_VULKAN_SHADER_COMPILATION
+ if (compilation_failed_) {
+ return false;
+ }
+#endif
+
+ return true;
+};
+
+/** \} */
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_shader.hh b/source/blender/gpu/vulkan/vk_shader.hh
new file mode 100644
index 00000000000..6376b17079d
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader.hh
@@ -0,0 +1,115 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include <vulkan/vulkan.h>
+
+#include "gpu_shader_private.hh"
+
+/* TODO move this deps to the .cc file. */
+#include "vk_context.hh"
+#include "vk_shader_interface.hh"
+
+namespace blender {
+namespace gpu {
+
+enum class VKShaderStageType {
+ VertexShader,
+ GeometryShader,
+ FragmentShader,
+ ComputeShader,
+};
+
+std::ostream &operator<<(std::ostream &os, const VKShaderStageType &stage);
+
+/**
+ * Implementation of shader compilation and uniforms handling using OpenGL.
+ **/
+class VKShader : public Shader {
+ private:
+ VKContext *context_ = nullptr;
+
+ VkShaderModule vertex_shader_ = VK_NULL_HANDLE;
+ VkShaderModule geometry_shader_ = VK_NULL_HANDLE;
+ VkShaderModule fragment_shader_ = VK_NULL_HANDLE;
+ VkShaderModule compute_shader_ = VK_NULL_HANDLE;
+
+ /** True if any shader failed to compile. */
+ bool compilation_failed_ = false;
+
+ public:
+ VKShader(const char *name);
+ ~VKShader();
+
+ void vertex_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void geometry_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void fragment_shader_from_glsl(MutableSpan<const char *> sources) override;
+ void compute_shader_from_glsl(MutableSpan<const char *> sources) override;
+ /* Return true on success. */
+ bool finalize(void);
+
+ void transform_feedback_names_set(Span<const char *> name_list,
+ const eGPUShaderTFBType geom_type) override{};
+ bool transform_feedback_enable(GPUVertBuf *buf) override
+ {
+ return true;
+ };
+ void transform_feedback_disable(void) override{};
+
+ void bind(void) override{};
+ void unbind(void) override{};
+
+ void uniform_float(int location, int comp_len, int array_size, const float *data) override{};
+ void uniform_int(int location, int comp_len, int array_size, const int *data) override{};
+
+ void vertformat_from_shader(GPUVertFormat *format) const override{};
+
+ int program_handle_get() const override
+ {
+ return 0;
+ }
+
+ private:
+ std::unique_ptr<std::vector<uint32_t>> compile_source(Span<const char *> sources,
+ VKShaderStageType stage);
+ VkShaderModule create_shader_module(MutableSpan<const char *> sources, VKShaderStageType stage);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKShader");
+};
+
+class VKLogParser : public GPULogParser {
+ public:
+ char *parse_line(char *log_line, GPULogItem &log_item) override;
+
+ protected:
+ char *skip_name_and_stage(char *log_line);
+ char *skip_severity_keyword(char *log_line, GPULogItem &log_item);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("GLLogParser");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_shader_interface.hh b/source/blender/gpu/vulkan/vk_shader_interface.hh
new file mode 100644
index 00000000000..b9047f44cf9
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader_interface.hh
@@ -0,0 +1,60 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ *
+ * Structure detailing needed vertex inputs and resources for a specific shader.
+ * A shader interface can be shared between two similar shaders.
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_shader_interface.hh"
+
+namespace blender::gpu {
+
+class GLVaoCache;
+
+/**
+ * Implementation of Shader interface using OpenGL.
+ **/
+class VKShaderInterface : public ShaderInterface {
+ public:
+ VKShaderInterface()
+ {
+ inputs_ = (ShaderInput *)MEM_callocN(sizeof(*inputs_), __func__);
+ name_buffer_ = (char *)MEM_callocN(1, __func__);
+ for (int i = 0; i < GPU_NUM_UNIFORMS; i++) {
+ builtins_[i] = 0;
+ }
+ for (int i = 0; i < GPU_NUM_UNIFORM_BLOCKS; i++) {
+ builtin_blocks_[i] = 0;
+ }
+ };
+ ~VKShaderInterface(){};
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKShaderInterface");
+};
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_shader_log.cc b/source/blender/gpu/vulkan/vk_shader_log.cc
new file mode 100644
index 00000000000..2958adef903
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_shader_log.cc
@@ -0,0 +1,65 @@
+/*
+ * 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 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_shader.hh"
+
+#include "GPU_platform.h"
+
+namespace blender::gpu {
+
+char *VKLogParser::parse_line(char *log_line, GPULogItem &log_item)
+{
+ log_line = skip_name_and_stage(log_line);
+ log_line = skip_separators(log_line, ":");
+
+ /* Parse error line & char numbers. */
+ if (at_number(log_line)) {
+ char *error_line_number_end;
+ log_item.cursor.row = parse_number(log_line, &error_line_number_end);
+ log_line = error_line_number_end;
+ }
+ log_line = skip_separators(log_line, ": ");
+
+ /* Skip to message. Avoid redundant info. */
+ log_line = skip_severity_keyword(log_line, log_item);
+ log_line = skip_separators(log_line, ": ");
+
+ return log_line;
+}
+
+char *VKLogParser::skip_name_and_stage(char *log_line)
+{
+ char *name_skip = skip_until(log_line, '.');
+ if (name_skip == log_line) {
+ return log_line;
+ }
+
+ return skip_until(name_skip, ':');
+}
+
+char *VKLogParser::skip_severity_keyword(char *log_line, GPULogItem &log_item)
+{
+ return skip_severity(log_line, log_item, "error", "warning");
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_state.hh b/source/blender/gpu/vulkan/vk_state.hh
new file mode 100644
index 00000000000..a6513f8ea1e
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_state.hh
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "gpu_state_private.hh"
+
+namespace blender {
+namespace gpu {
+
+/**
+ * State manager keeping track of the draw state and applying it before drawing.
+ * Opengl Implementation.
+ **/
+class VKStateManager : public StateManager {
+ public:
+ VKStateManager(){};
+
+ void apply_state(void) override{};
+ void force_state(void) override{};
+
+ void issue_barrier(eGPUBarrier barrier_bits) override{};
+
+ void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) override{};
+ void texture_unbind(Texture *tex) override{};
+ void texture_unbind_all(void) override{};
+
+ void image_bind(Texture *tex, int unit) override{};
+ void image_unbind(Texture *tex) override{};
+ void image_unbind_all(void) override{};
+
+ void texture_unpack_row_length_set(uint len) override{};
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKStateManager")
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc
new file mode 100644
index 00000000000..d9cf15739c5
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_texture.cc
@@ -0,0 +1,154 @@
+/*
+ * 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 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "vk_context.hh"
+
+#include "vk_texture.hh"
+
+namespace blender::gpu {
+
+VKTexture::VKTexture(const char *name) : Texture(name)
+{
+ context_ = VKContext::get();
+}
+
+VKTexture::~VKTexture(void)
+{
+ VkDevice device = context_->device_get();
+ for (VkImageView view : views_) {
+ if (view != VK_NULL_HANDLE) {
+ vkDestroyImageView(device, view, nullptr);
+ }
+ }
+ if (vk_image_ != VK_NULL_HANDLE) {
+ vkDestroyImage(device, vk_image_, nullptr);
+ }
+}
+
+bool VKTexture::init_internal(void)
+{
+ VmaAllocator mem_allocator = context_->mem_allocator_get();
+ {
+ /* Usage very rough for now to support same level of interaction as OpenGL in a simple way.
+ * TODO(fclem) improve this. */
+ VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
+ usage |= (format_flag_ & GPU_FORMAT_DEPTH) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ VkImageCreateInfo info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
+ info.imageType = to_vk_image_type(type_);
+ info.extent.width = static_cast<uint32_t>(w_);
+ info.extent.height = static_cast<uint32_t>(h_);
+ info.extent.depth = static_cast<uint32_t>(d_);
+ /* TODO(fclem) mipmap support. */
+ info.mipLevels = 1;
+ info.arrayLayers = this->layer_count();
+ info.format = to_vk(format_);
+ info.samples = VK_SAMPLE_COUNT_1_BIT;
+ info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ /* TODO(fclem) improve this. */
+ info.tiling = VK_IMAGE_TILING_LINEAR;
+ info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ info.usage = usage;
+ info.flags = 0;
+
+ views_.resize(info.mipLevels * (info.arrayLayers + 1), VK_NULL_HANDLE);
+
+ VmaAllocationCreateInfo alloc_info = {};
+ alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ alloc_info.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ alloc_info.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ alloc_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+ vmaCreateImage(mem_allocator, &info, &alloc_info, &vk_image_, &vk_allocation_, nullptr);
+ }
+
+ return true;
+}
+
+void VKTexture::update_sub(
+ int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data)
+{
+}
+
+void VKTexture::swizzle_set(const char swizzle_mask[4])
+{
+ vk_swizzle_.r = swizzle_to_vk(swizzle_mask[0]);
+ vk_swizzle_.g = swizzle_to_vk(swizzle_mask[1]);
+ vk_swizzle_.b = swizzle_to_vk(swizzle_mask[2]);
+ vk_swizzle_.a = swizzle_to_vk(swizzle_mask[3]);
+
+ /* The swizzling changed, we need to reconstruct all views. */
+ VkDevice device = context_->device_get();
+ for (VkImageView view : views_) {
+ if (view != VK_NULL_HANDLE) {
+ /* WARNING: This is potentially unsafe since the views might already be in used.
+ * In practice, swizzle_set is always used just after initialization or before usage. */
+ vkDestroyImageView(device, view, nullptr);
+ view = VK_NULL_HANDLE;
+ }
+ }
+}
+
+VkImageView VKTexture::create_image_view(int mip, int layer)
+{
+ VkDevice device = context_->device_get();
+
+ VkImageSubresourceRange range;
+ range.aspectMask = to_vk(format_flag_);
+ range.baseMipLevel = (mip > -1) ? mip : 0;
+ range.baseArrayLayer = (layer > -1) ? layer : 0;
+ range.levelCount = (mip > -1) ? 1 : VK_REMAINING_MIP_LEVELS;
+ range.layerCount = (layer > -1) ? 1 : VK_REMAINING_ARRAY_LAYERS;
+
+ VkImageViewCreateInfo info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
+ info.flags = 0;
+ info.image = vk_image_;
+ info.viewType = to_vk_image_view_type(type_);
+ info.format = vk_format_;
+ info.components = vk_swizzle_;
+ info.subresourceRange = range;
+
+ VkImageView view;
+ vkCreateImageView(device, &info, nullptr, &view);
+ return view;
+}
+
+VkImageView VKTexture::vk_image_view_get(int mip)
+{
+ return this->vk_image_view_get(mip, -1);
+}
+
+VkImageView VKTexture::vk_image_view_get(int mip, int layer)
+{
+ int view_id = mip * (layer_count() + 1) + layer + 1;
+ VkImageView view = views_[view_id];
+ if (view == VK_NULL_HANDLE) {
+ views_[view_id] = view = this->create_image_view(mip, layer);
+ }
+ return view;
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/vulkan/vk_texture.hh b/source/blender/gpu/vulkan/vk_texture.hh
new file mode 100644
index 00000000000..a79d6242dd8
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_texture.hh
@@ -0,0 +1,290 @@
+
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU Framebuffer
+ * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
+ * multiple FBO's may be created.
+ * - actual FBO creation & config is deferred until GPU_framebuffer_bind or
+ * GPU_framebuffer_check_valid to allow creation & config while another
+ * opengl context is bound (since FBOs are not shared between ogl contexts).
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include <vulkan/vulkan.h>
+
+#include "BLI_assert.h"
+#include "BLI_vector.hh"
+
+#include "gpu_texture_private.hh"
+
+struct GPUFrameBuffer;
+
+namespace blender {
+namespace gpu {
+
+class VKTexture : public Texture {
+ protected:
+ /* Vulkan context who created the object. */
+ VKContext *context_ = nullptr;
+ /* Vulkan object handle. */
+ VkImage vk_image_ = VK_NULL_HANDLE;
+ /* GPU Memory allocated by this object. */
+ VmaAllocation vk_allocation_ = VK_NULL_HANDLE;
+ /* Vulkan format used to initialize the texture. */
+ VkFormat vk_format_ = VK_FORMAT_MAX_ENUM;
+ /* Image views for each mipmap and each layer. */
+ Vector<VkImageView> views_;
+ /* Swizzle state. */
+ VkComponentMapping vk_swizzle_ = {VK_COMPONENT_SWIZZLE_IDENTITY,
+ VK_COMPONENT_SWIZZLE_IDENTITY,
+ VK_COMPONENT_SWIZZLE_IDENTITY,
+ VK_COMPONENT_SWIZZLE_IDENTITY};
+
+ public:
+ VKTexture(const char *name);
+ ~VKTexture();
+
+ void update_sub(
+ int mip, int offset[3], int extent[3], eGPUDataFormat type, const void *data) override;
+
+ void generate_mipmap(void) override{};
+ void copy_to(Texture *dst) override{};
+ void clear(eGPUDataFormat format, const void *data) override{};
+ void swizzle_set(const char swizzle_mask[4]) override;
+ void mip_range_set(int min, int max) override{};
+ void *read(int mip, eGPUDataFormat type) override
+ {
+ /* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
+ int extent[3] = {1, 1, 1};
+ this->mip_size_get(mip, extent);
+
+ size_t sample_len = extent[0] * extent[1] * extent[2];
+ size_t sample_size = to_bytesize(format_, type);
+ size_t texture_size = sample_len * sample_size;
+ return MEM_callocN(texture_size, __func__);
+ };
+
+ /* TODO(fclem) Legacy. Should be removed at some point. */
+ uint gl_bindcode_get(void) const override
+ {
+ return 0;
+ };
+
+ /* Vulkan specific functions. */
+ VkImageView vk_image_view_get(int mip);
+ VkImageView vk_image_view_get(int mip, int layer);
+
+ VkFormat vk_format_get(void) const
+ {
+ return this->vk_format_;
+ }
+
+ protected:
+ bool init_internal(void) override;
+ bool init_internal(GPUVertBuf *vbo) override
+ {
+ return true;
+ };
+
+ VkImageView create_image_view(int mip, int layer);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKTexture")
+};
+
+inline VkImageType to_vk_image_type(eGPUTextureType type)
+{
+ switch (type & (GPU_TEXTURE_1D | GPU_TEXTURE_2D | GPU_TEXTURE_3D)) {
+ case GPU_TEXTURE_1D:
+ return VK_IMAGE_TYPE_1D;
+ case GPU_TEXTURE_2D:
+ return VK_IMAGE_TYPE_2D;
+ case GPU_TEXTURE_3D:
+ return VK_IMAGE_TYPE_3D;
+ default:
+ BLI_assert(!"Wrong enum!");
+ return VK_IMAGE_TYPE_MAX_ENUM;
+ }
+}
+
+inline VkImageViewType to_vk_image_view_type(eGPUTextureType type)
+{
+ switch (type) {
+ case GPU_TEXTURE_1D:
+ return VK_IMAGE_VIEW_TYPE_1D;
+ case GPU_TEXTURE_2D:
+ return VK_IMAGE_VIEW_TYPE_2D;
+ case GPU_TEXTURE_3D:
+ return VK_IMAGE_VIEW_TYPE_3D;
+ case GPU_TEXTURE_CUBE:
+ return VK_IMAGE_VIEW_TYPE_CUBE;
+ case GPU_TEXTURE_1D_ARRAY:
+ return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
+ case GPU_TEXTURE_2D_ARRAY:
+ return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+ case GPU_TEXTURE_CUBE_ARRAY:
+ return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
+ default:
+ BLI_assert(!"Wrong enum!");
+ return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
+ }
+}
+
+inline VkImageAspectFlags to_vk(eGPUTextureFormatFlag flag)
+{
+ if (flag & GPU_FORMAT_DEPTH) {
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+ }
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+}
+
+inline VkComponentSwizzle swizzle_to_vk(const char swizzle)
+{
+ switch (swizzle) {
+ default:
+ case 'x':
+ case 'r':
+ return VK_COMPONENT_SWIZZLE_R;
+ case 'y':
+ case 'g':
+ return VK_COMPONENT_SWIZZLE_G;
+ case 'z':
+ case 'b':
+ return VK_COMPONENT_SWIZZLE_B;
+ case 'w':
+ case 'a':
+ return VK_COMPONENT_SWIZZLE_A;
+ case '0':
+ return VK_COMPONENT_SWIZZLE_ZERO;
+ case '1':
+ return VK_COMPONENT_SWIZZLE_ONE;
+ }
+}
+
+inline VkFormat to_vk(eGPUTextureFormat format)
+{
+ switch (format) {
+ /* Formats texture & renderbuffer */
+ case GPU_RGBA8UI:
+ return VK_FORMAT_R8G8B8A8_UINT;
+ case GPU_RGBA8I:
+ return VK_FORMAT_R8G8B8A8_SINT;
+ case GPU_RGBA8:
+ return VK_FORMAT_R8G8B8A8_UNORM;
+ case GPU_RGBA32UI:
+ return VK_FORMAT_R32G32B32A32_UINT;
+ case GPU_RGBA32I:
+ return VK_FORMAT_R32G32B32A32_SINT;
+ case GPU_RGBA32F:
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+ case GPU_RGBA16UI:
+ return VK_FORMAT_R16G16B16A16_UINT;
+ case GPU_RGBA16I:
+ return VK_FORMAT_R16G16B16A16_SINT;
+ case GPU_RGBA16F:
+ return VK_FORMAT_R16G16B16A16_SFLOAT;
+ case GPU_RGBA16:
+ return VK_FORMAT_R16G16B16A16_UNORM;
+ case GPU_RG8UI:
+ return VK_FORMAT_R8G8_UINT;
+ case GPU_RG8I:
+ return VK_FORMAT_R8G8_SINT;
+ case GPU_RG8:
+ return VK_FORMAT_R8G8_UNORM;
+ case GPU_RG32UI:
+ return VK_FORMAT_R32G32_UINT;
+ case GPU_RG32I:
+ return VK_FORMAT_R32G32_SINT;
+ case GPU_RG32F:
+ return VK_FORMAT_R32G32_SFLOAT;
+ case GPU_RG16UI:
+ return VK_FORMAT_R16G16_UINT;
+ case GPU_RG16I:
+ return VK_FORMAT_R16G16_SINT;
+ case GPU_RG16F:
+ return VK_FORMAT_R16G16_SFLOAT;
+ case GPU_RG16:
+ return VK_FORMAT_R16G16_UNORM;
+ case GPU_R8UI:
+ return VK_FORMAT_R8_UINT;
+ case GPU_R8I:
+ return VK_FORMAT_R8_SINT;
+ case GPU_R8:
+ return VK_FORMAT_R8_UNORM;
+ case GPU_R32UI:
+ return VK_FORMAT_R32_UINT;
+ case GPU_R32I:
+ return VK_FORMAT_R32_SINT;
+ case GPU_R32F:
+ return VK_FORMAT_R32_SFLOAT;
+ case GPU_R16UI:
+ return VK_FORMAT_R16_UINT;
+ case GPU_R16I:
+ return VK_FORMAT_R16_SINT;
+ case GPU_R16F:
+ return VK_FORMAT_R16_SFLOAT;
+ case GPU_R16:
+ return VK_FORMAT_R16_UNORM;
+ /* Special formats texture & renderbuffer */
+ case GPU_RGB10_A2:
+ return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
+ case GPU_R11F_G11F_B10F:
+ return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
+ case GPU_DEPTH32F_STENCIL8:
+ return VK_FORMAT_D32_SFLOAT_S8_UINT;
+ case GPU_DEPTH24_STENCIL8:
+ return VK_FORMAT_D24_UNORM_S8_UINT;
+ case GPU_SRGB8_A8:
+ return VK_FORMAT_A8B8G8R8_SRGB_PACK32;
+ /* Texture only format */
+ case GPU_RGB16F:
+ return VK_FORMAT_R16G16B16_SFLOAT;
+ /* Special formats texture only */
+ case GPU_SRGB8_A8_DXT1:
+ return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
+ case GPU_SRGB8_A8_DXT3:
+ return VK_FORMAT_BC2_SRGB_BLOCK;
+ case GPU_SRGB8_A8_DXT5:
+ return VK_FORMAT_BC3_SRGB_BLOCK;
+ case GPU_RGBA8_DXT1:
+ return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
+ case GPU_RGBA8_DXT3:
+ return VK_FORMAT_BC2_UNORM_BLOCK;
+ case GPU_RGBA8_DXT5:
+ return VK_FORMAT_BC3_UNORM_BLOCK;
+ /* Depth Formats */
+ case GPU_DEPTH_COMPONENT32F:
+ return VK_FORMAT_D32_SFLOAT;
+ case GPU_DEPTH_COMPONENT24:
+ return VK_FORMAT_X8_D24_UNORM_PACK32;
+ case GPU_DEPTH_COMPONENT16:
+ return VK_FORMAT_D16_UNORM;
+ }
+ BLI_assert(!"Unable to convert to vulkan textureformat.");
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+}
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_uniform_buffer.hh b/source/blender/gpu/vulkan/vk_uniform_buffer.hh
new file mode 100644
index 00000000000..36e231c5bf7
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_uniform_buffer.hh
@@ -0,0 +1,52 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_uniform_buffer_private.hh"
+
+namespace blender {
+namespace gpu {
+
+/**
+ * Implementation of Uniform Buffers using OpenGL.
+ **/
+class VKUniformBuf : public UniformBuf {
+ public:
+ VKUniformBuf(size_t size, const char *name) : UniformBuf(size, name){};
+ ~VKUniformBuf(){};
+
+ void update(const void *data) override{};
+ void bind(int slot) override{};
+ void unbind(void) override{};
+
+ private:
+ void init(void);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKUniformBuf");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh
new file mode 100644
index 00000000000..43d8ecbabaf
--- /dev/null
+++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh
@@ -0,0 +1,77 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_vertex_buffer_private.hh"
+
+namespace blender {
+namespace gpu {
+
+class VKVertBuf : public VertBuf {
+ friend class VKTexture; /* For buffer texture. */
+
+ public:
+ void bind_as_ssbo(uint binding) override{};
+
+ void update_sub(uint start, uint len, void *data) override{};
+ const void *read() const override
+ {
+ return nullptr;
+ };
+ void *unmap(const void *mapped_data) const override{return nullptr;};
+
+ protected:
+ void acquire_data(void) override
+ {
+ MEM_SAFE_FREE(data);
+ data = (uchar *)MEM_mallocN(sizeof(uchar) * this->size_alloc_get(), __func__);
+ };
+ void resize_data(void) override
+ {
+ data = (uchar *)MEM_reallocN(data, sizeof(uchar) * this->size_alloc_get());
+ };
+ void release_data(void) override
+ {
+ MEM_SAFE_FREE(data);
+ };
+ void upload_data(void) override
+ {
+ if (usage_ == GPU_USAGE_STATIC) {
+ MEM_SAFE_FREE(data);
+ }
+ };
+ void duplicate_data(VertBuf *dst) override
+ {
+ if (data != nullptr) {
+ dst->data = (uchar *)MEM_dupallocN(data);
+ }
+ };
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("VKVertBuf");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index e416727fa70..ef6625d2cc6 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -29,6 +29,8 @@
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
+#include "BKE_global.h"
+
#include "GPU_state.h"
#include "../generic/py_capi_utils.h"
@@ -1116,6 +1118,25 @@ static PyObject *Buffer_repr(Buffer *self)
ret_ret_##ret; \
}
+#ifdef WITH_VULKAN
+# undef BGL_Wrap
+# define BGL_Wrap(funcname, ret, arg_list) \
+ static PyObject *Method_##funcname(PyObject *UNUSED(self), PyObject *args) \
+ { \
+ arg_def arg_list; \
+ ret_def_##ret; \
+ if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
+ return NULL; \
+ } \
+ if (G.debug & G_DEBUG_VK_CONTEXT) { \
+ return NULL; \
+ } \
+ GPU_bgl_start(); \
+ ret_set_##ret gl##funcname(arg_var arg_list); \
+ ret_ret_##ret; \
+ }
+#endif
+
/* GL_VERSION_1_0 */
BGL_Wrap(BlendFunc, void, (GLenum, GLenum));
BGL_Wrap(Clear, void, (GLbitfield));
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index 1bf0dfe079c..7d9b5b90d62 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -977,7 +977,7 @@ void *RE_gl_context_get(Render *re)
void *RE_gpu_context_get(Render *re)
{
if (re->gpu_context == NULL) {
- re->gpu_context = GPU_context_create(NULL);
+ re->gpu_context = GPU_context_create(NULL, re->gl_context);
}
return re->gpu_context;
}
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 640fef82085..905f9ff1353 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -1564,7 +1564,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
// GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
/* initialize OpenGL immediate mode */
- g_WS.gpu_context = GPU_context_create(g_WS.ghost_window);
+ g_WS.gpu_context = GPU_context_create(g_WS.ghost_window, NULL);
GPU_init();
/* initialize the font */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 320047652df..a13fedd2283 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -551,6 +551,13 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
glSettings.flags |= GHOST_glDebugContext;
}
+ GHOST_TDrawingContextType contextType = GHOST_kDrawingContextTypeOpenGL;
+#ifdef WITH_VULKAN
+ if (G.debug & G_DEBUG_VK_CONTEXT) {
+ contextType = GHOST_kDrawingContextTypeVulkan;
+ }
+#endif
+
int scr_w, scr_h;
wm_get_desktopsize(&scr_w, &scr_h);
int posy = (scr_h - win->posy - win->sizey);
@@ -568,11 +575,11 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
win->sizey,
(GHOST_TWindowState)win->windowstate,
is_dialog,
- GHOST_kDrawingContextTypeOpenGL,
+ contextType,
glSettings);
if (ghostwin) {
- win->gpuctx = GPU_context_create(ghostwin);
+ win->gpuctx = GPU_context_create(ghostwin, NULL);
/* needed so we can detect the graphics card below */
GPU_init();
@@ -2445,12 +2452,19 @@ void *WM_opengl_context_create(void)
BLI_assert(BLI_thread_is_main());
BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get());
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeOpenGL;
+
+#ifdef WITH_VULKAN
+ if (G.debug & G_DEBUG_VK_CONTEXT) {
+ type = GHOST_kDrawingContextTypeVulkan;
+ }
+#endif
GHOST_GLSettings glSettings = {0};
if (G.debug & G_DEBUG_GPU) {
glSettings.flags |= GHOST_glDebugContext;
}
- return GHOST_CreateOpenGLContext(g_system, GHOST_kDrawingContextTypeOpenGL, glSettings);
+ return GHOST_CreateOpenGLContext(g_system, type, glSettings);
}
void WM_opengl_context_dispose(void *context)