Compare commits
89 Commits
geometry-n
...
temp-vulka
Author | SHA1 | Date | |
---|---|---|---|
192719bdca | |||
275bbb8a4c | |||
3a4d2df7b1 | |||
c14af6b4d7 | |||
f676dbebf5 | |||
320659068a | |||
1cdcfa3a89 | |||
248299fc95 | |||
a8a7b84659 | |||
f1b4dce33e | |||
0ae912a28a | |||
f5f1ac9f03 | |||
5033453735 | |||
da4b09ac6f | |||
df3c418866 | |||
f23b870def | |||
94e1e694bc | |||
78abdcf31e | |||
99e4bfd5e4 | |||
794ce2a08f | |||
67b3796723 | |||
f1d9fe95e8 | |||
bbbe5a3894 | |||
b1ba82ba97 | |||
db6db0b754 | |||
642bba24a9 | |||
244f61e9e9 | |||
12b9ebc690 | |||
49723cca42 | |||
8781886cf7 | |||
37ee9595a0 | |||
be1dce8dfb | |||
2d6dfbf038 | |||
7214298cd1 | |||
63084dc7dd | |||
42645b33d6 | |||
cf52e4a07f | |||
4a3cbfd90e | |||
dc973dfa28 | |||
bf3eea036d | |||
8244f55530 | |||
cfb44574d9 | |||
c836b7e603 | |||
a246ad9559 | |||
36127e042b | |||
94a98b9365 | |||
5ca4e9e545 | |||
8a3329e72b | |||
7d7a39d00b | |||
74bfeec1a5 | |||
1273af7a01 | |||
e2d18eda75 | |||
bfa1f2d351 | |||
1effef805e | |||
6f1197c6b9 | |||
23503dec99 | |||
b43e11deda | |||
d45bbff511 | |||
9b467c591d | |||
0bc4eb987c | |||
648158dfbd | |||
fc0b8cb085 | |||
b3254da333 | |||
72e5cbf0c7 | |||
44ad59592b | |||
72b395a7e6 | |||
041900ae95 | |||
b271ed8ac9 | |||
6ccd38ea90 | |||
7d691969e6 | |||
1a47f3ae17 | |||
7211f3ab5b | |||
fad06751a6 | |||
0fae43efb2 | |||
31ecc30283 | |||
d64d789174 | |||
975e9020cb | |||
d2c6a27f58 | |||
6ca82bbf34 | |||
86868a4bcc | |||
5db147c5be | |||
39db9b836b | |||
b0800197e6 | |||
16f5cda14a | |||
50e0d346f1 | |||
7cd24fb70a | |||
1b04b5cf08 | |||
18ba57ddb6 | |||
ed2b382490 |
@@ -105,9 +105,10 @@ if(WITH_VULKAN_BACKEND)
|
||||
set(VULKAN_ROOT_DIR ${LIBDIR}/vulkan/macOS)
|
||||
set(VULKAN_INCLUDE_DIR ${VULKAN_ROOT_DIR}/include)
|
||||
set(VULKAN_LIBRARY ${VULKAN_ROOT_DIR}/lib/libvulkan.1.dylib)
|
||||
set(SHADERC_LIBRARY ${VULKAN_ROOT_DIR}/lib/libshaderc_combined.a)
|
||||
|
||||
set(VULKAN_INCLUDE_DIRS ${VULKAN_INCLUDE_DIR} ${MOLTENVK_INCLUDE_DIRS})
|
||||
set(VULKAN_LIBRARIES ${VULKAN_LIBRARY} ${MOLTENVK_LIBRARIES})
|
||||
set(VULKAN_LIBRARIES ${VULKAN_LIBRARY} ${SHADERC_LIBRARY} ${MOLTENVK_LIBRARIES})
|
||||
else()
|
||||
message(WARNING "Vulkan SDK was not found, disabling WITH_VULKAN_BACKEND")
|
||||
set(WITH_VULKAN_BACKEND OFF)
|
||||
|
@@ -20,9 +20,9 @@ vec3 compute_chromatic_distortion_scale(float distance_squared)
|
||||
/* Compute the image coordinates after distortion by the given distortion scale computed by the
|
||||
* compute_distortion_scale function. Note that the function expects centered normalized UV
|
||||
* coordinates but outputs non-centered image coordinates. */
|
||||
vec2 compute_distorted_uv(vec2 uv, float scale)
|
||||
vec2 compute_distorted_uv(vec2 uv, float uv_scale)
|
||||
{
|
||||
return (uv * scale + 0.5) * texture_size(input_tx) - 0.5;
|
||||
return (uv * uv_scale + 0.5) * texture_size(input_tx) - 0.5;
|
||||
}
|
||||
|
||||
/* Compute the number of integration steps that should be used to approximate the distorted pixel
|
||||
|
@@ -1,35 +1,35 @@
|
||||
/* A shorthand for 1D textureSize with a zero LOD. */
|
||||
int texture_size(sampler1D sampler)
|
||||
int texture_size(sampler1D sampler_1d)
|
||||
{
|
||||
return textureSize(sampler, 0);
|
||||
return textureSize(sampler_1d, 0);
|
||||
}
|
||||
|
||||
/* A shorthand for 1D texelFetch with zero LOD and bounded access clamped to border. */
|
||||
vec4 texture_load(sampler1D sampler, int x)
|
||||
vec4 texture_load(sampler1D sampler_1d, int x)
|
||||
{
|
||||
const int texture_bound = texture_size(sampler) - 1;
|
||||
return texelFetch(sampler, clamp(x, 0, texture_bound), 0);
|
||||
const int texture_bound = texture_size(sampler_1d) - 1;
|
||||
return texelFetch(sampler_1d, clamp(x, 0, texture_bound), 0);
|
||||
}
|
||||
|
||||
/* A shorthand for 2D textureSize with a zero LOD. */
|
||||
ivec2 texture_size(sampler2D sampler)
|
||||
ivec2 texture_size(sampler2D sampler_2d)
|
||||
{
|
||||
return textureSize(sampler, 0);
|
||||
return textureSize(sampler_2d, 0);
|
||||
}
|
||||
|
||||
/* A shorthand for 2D texelFetch with zero LOD and bounded access clamped to border. */
|
||||
vec4 texture_load(sampler2D sampler, ivec2 texel)
|
||||
vec4 texture_load(sampler2D sampler_2d, ivec2 texel)
|
||||
{
|
||||
const ivec2 texture_bounds = texture_size(sampler) - ivec2(1);
|
||||
return texelFetch(sampler, clamp(texel, ivec2(0), texture_bounds), 0);
|
||||
const ivec2 texture_bounds = texture_size(sampler_2d) - ivec2(1);
|
||||
return texelFetch(sampler_2d, clamp(texel, ivec2(0), texture_bounds), 0);
|
||||
}
|
||||
|
||||
/* A shorthand for 2D texelFetch with zero LOD and a fallback value for out-of-bound access. */
|
||||
vec4 texture_load(sampler2D sampler, ivec2 texel, vec4 fallback)
|
||||
vec4 texture_load(sampler2D sampler_2d, ivec2 texel, vec4 fallback)
|
||||
{
|
||||
const ivec2 texture_bounds = texture_size(sampler) - ivec2(1);
|
||||
const ivec2 texture_bounds = texture_size(sampler_2d) - ivec2(1);
|
||||
if (any(lessThan(texel, ivec2(0))) || any(greaterThan(texel, texture_bounds))) {
|
||||
return fallback;
|
||||
}
|
||||
return texelFetch(sampler, texel, 0);
|
||||
return texelFetch(sampler_2d, texel, 0);
|
||||
}
|
||||
|
@@ -9,7 +9,9 @@
|
||||
* dragging larger headers into the createInfo pipeline which would cause problems.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef GPU_SHADER
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/* Hierarchical Z down-sampling. */
|
||||
#define HIZ_MIP_COUNT 8
|
||||
|
@@ -26,7 +26,7 @@ shared uint bg_min_coc;
|
||||
shared uint bg_max_coc;
|
||||
shared uint bg_min_intersectable_coc;
|
||||
|
||||
const uint dof_tile_large_coc_uint = floatBitsToUint(dof_tile_large_coc);
|
||||
uint dof_tile_large_coc_uint = floatBitsToUint(dof_tile_large_coc);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@@ -13,8 +13,12 @@ vec2 proj(vec4 pos)
|
||||
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
|
||||
}
|
||||
|
||||
#define SET_INTENSITY(A, B, C, min, max) \
|
||||
(((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min)
|
||||
float calc_intensity(int segment_start, int segment_current, int segment_end, float min, float max)
|
||||
{
|
||||
return ((1.0 - (float(segment_end - segment_current) / float(segment_end - segment_start))) *
|
||||
(max - min)) +
|
||||
min;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -39,10 +43,10 @@ void main()
|
||||
else {
|
||||
/* black - before frameCurrent */
|
||||
if (selected) {
|
||||
intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75);
|
||||
intensity = calc_intensity(frameStart, frame, frameCurrent, 0.25, 0.75);
|
||||
}
|
||||
else {
|
||||
intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92);
|
||||
intensity = calc_intensity(frameStart, frame, frameCurrent, 0.68, 0.92);
|
||||
}
|
||||
interp.color.rgb = mix(colorWire.rgb, blend_base, intensity);
|
||||
}
|
||||
@@ -55,10 +59,10 @@ void main()
|
||||
else {
|
||||
/* blue - after frameCurrent */
|
||||
if (selected) {
|
||||
intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75);
|
||||
intensity = calc_intensity(frameCurrent, frame, frameEnd, 0.25, 0.75);
|
||||
}
|
||||
else {
|
||||
intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92);
|
||||
intensity = calc_intensity(frameCurrent, frame, frameEnd, 0.68, 0.92);
|
||||
}
|
||||
|
||||
interp.color.rgb = mix(colorBonePose.rgb, blend_base, intensity);
|
||||
|
@@ -5,5 +5,6 @@ void main()
|
||||
{
|
||||
vData.pos = pos;
|
||||
vData.frontPosition = point_object_to_ndc(pos);
|
||||
vData.backPosition = point_object_to_ndc(pos + lightDirection * lightDistance);
|
||||
vec3 back_pos = pos + lightDirection * lightDistance;
|
||||
vData.backPosition = point_object_to_ndc(back_pos);
|
||||
}
|
||||
|
@@ -569,7 +569,7 @@ SamplerState PointSampler
|
||||
# define SMAAGather(tex, coord) tex.Gather(LinearSampler, coord, 0)
|
||||
# endif
|
||||
#endif
|
||||
#if defined(SMAA_GLSL_3) || defined(SMAA_GLSL_4) || defined(GPU_METAL)
|
||||
#if defined(SMAA_GLSL_3) || defined(SMAA_GLSL_4) || defined(GPU_METAL) || defined(GPU_VULKAN)
|
||||
# define SMAATexture2D(tex) sampler2D tex
|
||||
# define SMAATexturePass2D(tex) tex
|
||||
# define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
|
||||
@@ -583,8 +583,28 @@ SamplerState PointSampler
|
||||
# define lerp(a, b, t) mix(a, b, t)
|
||||
# define saturate(a) clamp(a, 0.0, 1.0)
|
||||
# if defined(SMAA_GLSL_4)
|
||||
# define mad(a, b, c) fma(a, b, c)
|
||||
# define SMAAGather(tex, coord) textureGather(tex, coord)
|
||||
# endif
|
||||
# if defined(SMAA_GLSL_4)
|
||||
# define mad(a, b, c) fma(a, b, c)
|
||||
# elif defined(GPU_VULKAN)
|
||||
/* NOTE(Vulkan) mad macro doesn't work, define each override as work-around. */
|
||||
vec4 mad(vec4 a, vec4 b, vec4 c)
|
||||
{
|
||||
return fma(a, b, c);
|
||||
}
|
||||
vec3 mad(vec3 a, vec3 b, vec3 c)
|
||||
{
|
||||
return fma(a, b, c);
|
||||
}
|
||||
vec2 mad(vec2 a, vec2 b, vec2 c)
|
||||
{
|
||||
return fma(a, b, c);
|
||||
}
|
||||
float mad(float a, float b, float c)
|
||||
{
|
||||
return fma(a, b, c);
|
||||
}
|
||||
# else
|
||||
# define mad(a, b, c) (a * b + c)
|
||||
# endif
|
||||
|
@@ -234,12 +234,28 @@ uniform mat4 ModelMatrixInverse;
|
||||
(ProjectionMatrix * (ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)))
|
||||
#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz)
|
||||
#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz)
|
||||
#define point_view_to_ndc(p) (ProjectionMatrix * vec4(p, 1.0))
|
||||
#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz)
|
||||
#define point_view_to_world(p) ((ViewMatrixInverse * vec4(p, 1.0)).xyz)
|
||||
#define point_world_to_ndc(p) (ProjectionMatrix * (ViewMatrix * vec4(p, 1.0)))
|
||||
#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz)
|
||||
#define point_world_to_view(p) ((ViewMatrix * vec4(p, 1.0)).xyz)
|
||||
|
||||
vec4 point_view_to_ndc(vec3 p)
|
||||
{
|
||||
return ProjectionMatrix * vec4(p, 1.0);
|
||||
}
|
||||
|
||||
vec3 point_view_to_world(vec3 p)
|
||||
{
|
||||
return (ViewMatrixInverse * vec4(p, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec4 point_world_to_ndc(vec3 p)
|
||||
{
|
||||
return ProjectionMatrix * (ViewMatrix * vec4(p, 1.0));
|
||||
}
|
||||
|
||||
vec3 point_world_to_view(vec3 p)
|
||||
{
|
||||
return (ViewMatrix * vec4(p, 1.0)).xyz;
|
||||
}
|
||||
|
||||
/* Due to some shader compiler bug, we somewhat need to access gl_VertexID
|
||||
* to make vertex shaders work. even if it's actually dead code. */
|
||||
|
@@ -43,6 +43,7 @@ set(INC
|
||||
|
||||
set(INC_SYS
|
||||
${Epoxy_INCLUDE_DIRS}
|
||||
${VULKAN_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(SRC
|
||||
@@ -197,6 +198,7 @@ set(VULKAN_SRC
|
||||
vulkan/vk_pixel_buffer.cc
|
||||
vulkan/vk_query.cc
|
||||
vulkan/vk_shader.cc
|
||||
vulkan/vk_shader_log.cc
|
||||
vulkan/vk_storage_buffer.cc
|
||||
vulkan/vk_texture.cc
|
||||
vulkan/vk_uniform_buffer.cc
|
||||
@@ -212,6 +214,7 @@ set(VULKAN_SRC
|
||||
vulkan/vk_pixel_buffer.hh
|
||||
vulkan/vk_query.hh
|
||||
vulkan/vk_shader.hh
|
||||
vulkan/vk_shader_log.hh
|
||||
vulkan/vk_storage_buffer.hh
|
||||
vulkan/vk_texture.hh
|
||||
vulkan/vk_uniform_buffer.hh
|
||||
@@ -275,6 +278,7 @@ endif()
|
||||
|
||||
set(LIB
|
||||
${Epoxy_LIBRARIES}
|
||||
${VULKAN_LIBRARIES}
|
||||
)
|
||||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
|
@@ -98,6 +98,9 @@ static void standard_defines(Vector<const char *> &sources)
|
||||
case GPU_BACKEND_METAL:
|
||||
sources.append("#define GPU_METAL\n");
|
||||
break;
|
||||
case GPU_BACKEND_VULKAN:
|
||||
sources.append("#define GPU_VULKAN\n");
|
||||
break;
|
||||
default:
|
||||
BLI_assert(false && "Invalid GPU Backend Type");
|
||||
break;
|
||||
|
@@ -54,6 +54,12 @@ void ShaderBuilder::init()
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
case GPU_BACKEND_VULKAN:
|
||||
glSettings.context_type = GHOST_kDrawingContextTypeVulkan;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
@@ -100,6 +106,9 @@ int main(int argc, const char *argv[])
|
||||
backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
backends_to_validate.append({"Vulkan", GPU_BACKEND_VULKAN});
|
||||
#endif
|
||||
for (NamedBackend &backend : backends_to_validate) {
|
||||
GPU_backend_type_selection_set(backend.backend);
|
||||
@@ -114,6 +123,9 @@ int main(int argc, const char *argv[])
|
||||
printf("Shader compilation failed for %s backend\n", backend.name.c_str());
|
||||
exit_code = 1;
|
||||
}
|
||||
else {
|
||||
printf("%s backend shader compilation succeeded.\n", backend.name.c_str());
|
||||
}
|
||||
builder.exit();
|
||||
}
|
||||
|
||||
|
@@ -1,40 +1,25 @@
|
||||
#ifdef USE_WORLD_CLIP_PLANES
|
||||
# if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER)
|
||||
|
||||
# ifndef USE_GPU_SHADER_CREATE_INFO
|
||||
uniform vec4 WorldClipPlanes[6];
|
||||
# endif
|
||||
|
||||
# define _world_clip_planes_calc_clip_distance(wpos, _clipplanes) \
|
||||
{ \
|
||||
vec4 _pos = vec4(wpos, 1.0); \
|
||||
gl_ClipDistance[0] = dot(_clipplanes[0], _pos); \
|
||||
gl_ClipDistance[1] = dot(_clipplanes[1], _pos); \
|
||||
gl_ClipDistance[2] = dot(_clipplanes[2], _pos); \
|
||||
gl_ClipDistance[3] = dot(_clipplanes[3], _pos); \
|
||||
gl_ClipDistance[4] = dot(_clipplanes[4], _pos); \
|
||||
gl_ClipDistance[5] = dot(_clipplanes[5], _pos); \
|
||||
}
|
||||
|
||||
/* When all shaders are builtin shaders are migrated this could be applied directly. */
|
||||
# ifdef USE_GPU_SHADER_CREATE_INFO
|
||||
# define WorldClipPlanes clipPlanes.world
|
||||
# else
|
||||
uniform vec4 WorldClipPlanes[6];
|
||||
# endif
|
||||
/* HACK Dirty hack to be able to override the definition in common_view_lib.glsl.
|
||||
* Not doing this would require changing the include order in every shaders. */
|
||||
# define world_clip_planes_calc_clip_distance(wpos) \
|
||||
_world_clip_planes_calc_clip_distance(wpos, WorldClipPlanes)
|
||||
|
||||
void world_clip_planes_calc_clip_distance(vec3 wpos)
|
||||
{
|
||||
vec4 pos = vec4(wpos, 1.0);
|
||||
|
||||
gl_ClipDistance[0] = dot(WorldClipPlanes[0], pos);
|
||||
gl_ClipDistance[1] = dot(WorldClipPlanes[1], pos);
|
||||
gl_ClipDistance[2] = dot(WorldClipPlanes[2], pos);
|
||||
gl_ClipDistance[3] = dot(WorldClipPlanes[3], pos);
|
||||
gl_ClipDistance[4] = dot(WorldClipPlanes[4], pos);
|
||||
gl_ClipDistance[5] = dot(WorldClipPlanes[5], pos);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
# define world_clip_planes_set_clip_distance(c) \
|
||||
{ \
|
||||
gl_ClipDistance[0] = (c)[0]; \
|
||||
gl_ClipDistance[1] = (c)[1]; \
|
||||
gl_ClipDistance[2] = (c)[2]; \
|
||||
gl_ClipDistance[3] = (c)[3]; \
|
||||
gl_ClipDistance[4] = (c)[4]; \
|
||||
gl_ClipDistance[5] = (c)[5]; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -5,6 +5,7 @@
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "gpu_capabilities_private.hh"
|
||||
#include "gpu_platform_private.hh"
|
||||
|
||||
#include "vk_batch.hh"
|
||||
@@ -144,4 +145,18 @@ void VKBackend::render_step()
|
||||
{
|
||||
}
|
||||
|
||||
shaderc::Compiler &VKBackend::get_shaderc_compiler()
|
||||
{
|
||||
return shaderc_compiler_;
|
||||
}
|
||||
|
||||
void VKBackend::capabilities_init(VKContext &context)
|
||||
{
|
||||
/* Reset all capabilities from previous context. */
|
||||
GCaps = {};
|
||||
GCaps.compute_shader_support = true;
|
||||
GCaps.shader_storage_buffer_objects_support = true;
|
||||
GCaps.shader_image_load_store_support = true;
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
@@ -9,9 +9,21 @@
|
||||
|
||||
#include "gpu_backend.hh"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <MoltenVK/vk_mvk_moltenvk.h>
|
||||
#else
|
||||
# include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#include "shaderc/shaderc.hpp"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
class VKContext;
|
||||
|
||||
class VKBackend : public GPUBackend {
|
||||
private:
|
||||
shaderc::Compiler shaderc_compiler_;
|
||||
|
||||
public:
|
||||
VKBackend()
|
||||
{
|
||||
@@ -50,6 +62,10 @@ class VKBackend : public GPUBackend {
|
||||
void render_end() override;
|
||||
void render_step() override;
|
||||
|
||||
shaderc::Compiler &get_shaderc_compiler();
|
||||
|
||||
static void capabilities_init(VKContext &context);
|
||||
|
||||
private:
|
||||
static void init_platform();
|
||||
static void platform_exit();
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "vk_context.hh"
|
||||
|
||||
#include "vk_backend.hh"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
namespace blender::gpu {
|
||||
@@ -32,6 +34,8 @@ VKContext::VKContext(void *ghost_window, void *ghost_context)
|
||||
info.device = device_;
|
||||
info.instance = instance_;
|
||||
vmaCreateAllocator(&info, &mem_allocator_);
|
||||
|
||||
VKBackend::capabilities_init(*this);
|
||||
}
|
||||
|
||||
VKContext::~VKContext()
|
||||
|
@@ -47,6 +47,16 @@ class VKContext : public Context {
|
||||
void debug_group_begin(const char *, int) override;
|
||||
void debug_group_end() override;
|
||||
|
||||
static VKContext *get(void)
|
||||
{
|
||||
return static_cast<VKContext *>(Context::get());
|
||||
}
|
||||
|
||||
VkDevice device_get() const
|
||||
{
|
||||
return device_;
|
||||
}
|
||||
|
||||
VmaAllocator mem_allocator_get() const
|
||||
{
|
||||
return mem_allocator_;
|
||||
|
@@ -7,26 +7,679 @@
|
||||
|
||||
#include "vk_shader.hh"
|
||||
|
||||
#include "vk_backend.hh"
|
||||
#include "vk_shader_log.hh"
|
||||
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
using namespace blender::gpu::shader;
|
||||
|
||||
extern "C" char datatoc_glsl_shader_defines_glsl[];
|
||||
|
||||
namespace blender::gpu {
|
||||
void VKShader::vertex_shader_from_glsl(MutableSpan<const char *> /*sources*/)
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Create Info
|
||||
* \{ */
|
||||
|
||||
static const char *to_string(const Interpolation &interp)
|
||||
{
|
||||
switch (interp) {
|
||||
case Interpolation::SMOOTH:
|
||||
return "smooth";
|
||||
case Interpolation::FLAT:
|
||||
return "flat";
|
||||
case Interpolation::NO_PERSPECTIVE:
|
||||
return "noperspective";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void VKShader::geometry_shader_from_glsl(MutableSpan<const char *> /*sources*/)
|
||||
static const char *to_string(const Type &type)
|
||||
{
|
||||
switch (type) {
|
||||
case Type::FLOAT:
|
||||
return "float";
|
||||
case Type::VEC2:
|
||||
return "vec2";
|
||||
case Type::VEC3:
|
||||
return "vec3";
|
||||
case Type::VEC4:
|
||||
return "vec4";
|
||||
case Type::MAT3:
|
||||
return "mat3";
|
||||
case Type::MAT4:
|
||||
return "mat4";
|
||||
case Type::UINT:
|
||||
return "uint";
|
||||
case Type::UVEC2:
|
||||
return "uvec2";
|
||||
case Type::UVEC3:
|
||||
return "uvec3";
|
||||
case Type::UVEC4:
|
||||
return "uvec4";
|
||||
case Type::INT:
|
||||
return "int";
|
||||
case Type::IVEC2:
|
||||
return "ivec2";
|
||||
case Type::IVEC3:
|
||||
return "ivec3";
|
||||
case Type::IVEC4:
|
||||
return "ivec4";
|
||||
case Type::BOOL:
|
||||
return "bool";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void VKShader::fragment_shader_from_glsl(MutableSpan<const char *> /*sources*/)
|
||||
static const char *to_string(const eGPUTextureFormat &type)
|
||||
{
|
||||
switch (type) {
|
||||
case GPU_RGBA8UI:
|
||||
return "rgba8ui";
|
||||
case GPU_RGBA8I:
|
||||
return "rgba8i";
|
||||
case GPU_RGBA8:
|
||||
return "rgba8";
|
||||
case GPU_RGBA32UI:
|
||||
return "rgba32ui";
|
||||
case GPU_RGBA32I:
|
||||
return "rgba32i";
|
||||
case GPU_RGBA32F:
|
||||
return "rgba32f";
|
||||
case GPU_RGBA16UI:
|
||||
return "rgba16ui";
|
||||
case GPU_RGBA16I:
|
||||
return "rgba16i";
|
||||
case GPU_RGBA16F:
|
||||
return "rgba16f";
|
||||
case GPU_RGBA16:
|
||||
return "rgba16";
|
||||
case GPU_RG8UI:
|
||||
return "rg8ui";
|
||||
case GPU_RG8I:
|
||||
return "rg8i";
|
||||
case GPU_RG8:
|
||||
return "rg8";
|
||||
case GPU_RG32UI:
|
||||
return "rg32ui";
|
||||
case GPU_RG32I:
|
||||
return "rg32i";
|
||||
case GPU_RG32F:
|
||||
return "rg32f";
|
||||
case GPU_RG16UI:
|
||||
return "rg16ui";
|
||||
case GPU_RG16I:
|
||||
return "rg16i";
|
||||
case GPU_RG16F:
|
||||
return "rg16f";
|
||||
case GPU_RG16:
|
||||
return "rg16";
|
||||
case GPU_R8UI:
|
||||
return "r8ui";
|
||||
case GPU_R8I:
|
||||
return "r8i";
|
||||
case GPU_R8:
|
||||
return "r8";
|
||||
case GPU_R32UI:
|
||||
return "r32ui";
|
||||
case GPU_R32I:
|
||||
return "r32i";
|
||||
case GPU_R32F:
|
||||
return "r32f";
|
||||
case GPU_R16UI:
|
||||
return "r16ui";
|
||||
case GPU_R16I:
|
||||
return "r16i";
|
||||
case GPU_R16F:
|
||||
return "r16f";
|
||||
case GPU_R16:
|
||||
return "r16";
|
||||
case GPU_R11F_G11F_B10F:
|
||||
return "r11f_g11f_b10f";
|
||||
case GPU_RGB10_A2:
|
||||
return "rgb10_a2";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void VKShader::compute_shader_from_glsl(MutableSpan<const char *> /*sources*/)
|
||||
static const char *to_string(const PrimitiveIn &layout)
|
||||
{
|
||||
switch (layout) {
|
||||
case PrimitiveIn::POINTS:
|
||||
return "points";
|
||||
case PrimitiveIn::LINES:
|
||||
return "lines";
|
||||
case PrimitiveIn::LINES_ADJACENCY:
|
||||
return "lines_adjacency";
|
||||
case PrimitiveIn::TRIANGLES:
|
||||
return "triangles";
|
||||
case PrimitiveIn::TRIANGLES_ADJACENCY:
|
||||
return "triangles_adjacency";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *to_string(const PrimitiveOut &layout)
|
||||
{
|
||||
switch (layout) {
|
||||
case PrimitiveOut::POINTS:
|
||||
return "points";
|
||||
case PrimitiveOut::LINE_STRIP:
|
||||
return "line_strip";
|
||||
case PrimitiveOut::TRIANGLE_STRIP:
|
||||
return "triangle_strip";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *to_string(const DepthWrite &value)
|
||||
{
|
||||
switch (value) {
|
||||
case DepthWrite::ANY:
|
||||
return "depth_any";
|
||||
case DepthWrite::GREATER:
|
||||
return "depth_greater";
|
||||
case DepthWrite::LESS:
|
||||
return "depth_less";
|
||||
default:
|
||||
return "depth_unchanged";
|
||||
}
|
||||
}
|
||||
|
||||
static void print_image_type(std::ostream &os,
|
||||
const ImageType &type,
|
||||
const ShaderCreateInfo::Resource::BindType bind_type)
|
||||
{
|
||||
switch (type) {
|
||||
case ImageType::INT_BUFFER:
|
||||
case ImageType::INT_1D:
|
||||
case ImageType::INT_1D_ARRAY:
|
||||
case ImageType::INT_2D:
|
||||
case ImageType::INT_2D_ARRAY:
|
||||
case ImageType::INT_3D:
|
||||
case ImageType::INT_CUBE:
|
||||
case ImageType::INT_CUBE_ARRAY:
|
||||
os << "i";
|
||||
break;
|
||||
case ImageType::UINT_BUFFER:
|
||||
case ImageType::UINT_1D:
|
||||
case ImageType::UINT_1D_ARRAY:
|
||||
case ImageType::UINT_2D:
|
||||
case ImageType::UINT_2D_ARRAY:
|
||||
case ImageType::UINT_3D:
|
||||
case ImageType::UINT_CUBE:
|
||||
case ImageType::UINT_CUBE_ARRAY:
|
||||
os << "u";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
os << "image";
|
||||
}
|
||||
else {
|
||||
os << "sampler";
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ImageType::FLOAT_BUFFER:
|
||||
case ImageType::INT_BUFFER:
|
||||
case ImageType::UINT_BUFFER:
|
||||
os << "Buffer";
|
||||
break;
|
||||
case ImageType::FLOAT_1D:
|
||||
case ImageType::FLOAT_1D_ARRAY:
|
||||
case ImageType::INT_1D:
|
||||
case ImageType::INT_1D_ARRAY:
|
||||
case ImageType::UINT_1D:
|
||||
case ImageType::UINT_1D_ARRAY:
|
||||
os << "1D";
|
||||
break;
|
||||
case ImageType::FLOAT_2D:
|
||||
case ImageType::FLOAT_2D_ARRAY:
|
||||
case ImageType::INT_2D:
|
||||
case ImageType::INT_2D_ARRAY:
|
||||
case ImageType::UINT_2D:
|
||||
case ImageType::UINT_2D_ARRAY:
|
||||
case ImageType::SHADOW_2D:
|
||||
case ImageType::SHADOW_2D_ARRAY:
|
||||
case ImageType::DEPTH_2D:
|
||||
case ImageType::DEPTH_2D_ARRAY:
|
||||
os << "2D";
|
||||
break;
|
||||
case ImageType::FLOAT_3D:
|
||||
case ImageType::INT_3D:
|
||||
case ImageType::UINT_3D:
|
||||
os << "3D";
|
||||
break;
|
||||
case ImageType::FLOAT_CUBE:
|
||||
case ImageType::FLOAT_CUBE_ARRAY:
|
||||
case ImageType::INT_CUBE:
|
||||
case ImageType::INT_CUBE_ARRAY:
|
||||
case ImageType::UINT_CUBE:
|
||||
case ImageType::UINT_CUBE_ARRAY:
|
||||
case ImageType::SHADOW_CUBE:
|
||||
case ImageType::SHADOW_CUBE_ARRAY:
|
||||
case ImageType::DEPTH_CUBE:
|
||||
case ImageType::DEPTH_CUBE_ARRAY:
|
||||
os << "Cube";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ImageType::FLOAT_1D_ARRAY:
|
||||
case ImageType::FLOAT_2D_ARRAY:
|
||||
case ImageType::FLOAT_CUBE_ARRAY:
|
||||
case ImageType::INT_1D_ARRAY:
|
||||
case ImageType::INT_2D_ARRAY:
|
||||
case ImageType::INT_CUBE_ARRAY:
|
||||
case ImageType::UINT_1D_ARRAY:
|
||||
case ImageType::UINT_2D_ARRAY:
|
||||
case ImageType::UINT_CUBE_ARRAY:
|
||||
case ImageType::SHADOW_2D_ARRAY:
|
||||
case ImageType::SHADOW_CUBE_ARRAY:
|
||||
case ImageType::DEPTH_2D_ARRAY:
|
||||
case ImageType::DEPTH_CUBE_ARRAY:
|
||||
os << "Array";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ImageType::SHADOW_2D:
|
||||
case ImageType::SHADOW_2D_ARRAY:
|
||||
case ImageType::SHADOW_CUBE:
|
||||
case ImageType::SHADOW_CUBE_ARRAY:
|
||||
os << "Shadow";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
os << " ";
|
||||
}
|
||||
|
||||
static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifiers)
|
||||
{
|
||||
if (bool(qualifiers & Qualifier::NO_RESTRICT) == false) {
|
||||
os << "restrict ";
|
||||
}
|
||||
if (bool(qualifiers & Qualifier::READ) == false) {
|
||||
os << "writeonly ";
|
||||
}
|
||||
if (bool(qualifiers & Qualifier::WRITE) == false) {
|
||||
os << "readonly ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
os << "layout(binding = " << res.slot;
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
os << ", " << to_string(res.image.format);
|
||||
}
|
||||
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
|
||||
os << ", std140";
|
||||
}
|
||||
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
|
||||
os << ", std430";
|
||||
}
|
||||
os << ") ";
|
||||
|
||||
int64_t array_offset;
|
||||
StringRef name_no_array;
|
||||
|
||||
switch (res.bind_type) {
|
||||
case ShaderCreateInfo::Resource::BindType::SAMPLER:
|
||||
os << "uniform ";
|
||||
print_image_type(os, res.sampler.type, res.bind_type);
|
||||
os << res.sampler.name << ";\n";
|
||||
break;
|
||||
case ShaderCreateInfo::Resource::BindType::IMAGE:
|
||||
os << "uniform ";
|
||||
print_qualifier(os, res.image.qualifiers);
|
||||
print_image_type(os, res.image.type, res.bind_type);
|
||||
os << res.image.name << ";\n";
|
||||
break;
|
||||
case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER:
|
||||
array_offset = res.uniformbuf.name.find_first_of("[");
|
||||
name_no_array = (array_offset == -1) ? res.uniformbuf.name :
|
||||
StringRef(res.uniformbuf.name.c_str(), array_offset);
|
||||
os << "uniform " << name_no_array << " { " << res.uniformbuf.type_name << " _"
|
||||
<< res.uniformbuf.name << "; };\n";
|
||||
break;
|
||||
case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:
|
||||
array_offset = res.storagebuf.name.find_first_of("[");
|
||||
name_no_array = (array_offset == -1) ? res.storagebuf.name :
|
||||
StringRef(res.storagebuf.name.c_str(), array_offset);
|
||||
print_qualifier(os, res.storagebuf.qualifiers);
|
||||
os << "buffer ";
|
||||
os << name_no_array << " { " << res.storagebuf.type_name << " _" << res.storagebuf.name
|
||||
<< "; };\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_resource_alias(std::ostream &os, const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
int64_t array_offset;
|
||||
StringRef name_no_array;
|
||||
|
||||
switch (res.bind_type) {
|
||||
case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER:
|
||||
array_offset = res.uniformbuf.name.find_first_of("[");
|
||||
name_no_array = (array_offset == -1) ? res.uniformbuf.name :
|
||||
StringRef(res.uniformbuf.name.c_str(), array_offset);
|
||||
os << "#define " << name_no_array << " (_" << name_no_array << ")\n";
|
||||
break;
|
||||
case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:
|
||||
array_offset = res.storagebuf.name.find_first_of("[");
|
||||
name_no_array = (array_offset == -1) ? res.storagebuf.name :
|
||||
StringRef(res.storagebuf.name.c_str(), array_offset);
|
||||
os << "#define " << name_no_array << " (_" << name_no_array << ")\n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline int get_location_count(const Type &type)
|
||||
{
|
||||
if (type == shader::Type::MAT4) {
|
||||
return 4;
|
||||
}
|
||||
else if (type == shader::Type::MAT3) {
|
||||
return 3;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_interface(std::ostream &os,
|
||||
const std::string &prefix,
|
||||
const StageInterfaceInfo &iface,
|
||||
int &location,
|
||||
const StringRefNull &suffix = "")
|
||||
{
|
||||
if (iface.instance_name.is_empty()) {
|
||||
for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
|
||||
os << "layout(location=" << location << ") " << prefix << " " << to_string(inout.interp)
|
||||
<< " " << to_string(inout.type) << " " << inout.name << ";\n";
|
||||
location += get_location_count(inout.type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string struct_name = prefix + iface.name;
|
||||
std::string iface_attribute;
|
||||
if (iface.instance_name.is_empty()) {
|
||||
iface_attribute = "iface_";
|
||||
}
|
||||
else {
|
||||
iface_attribute = iface.instance_name;
|
||||
}
|
||||
std::string flat = "";
|
||||
if (prefix == "in") {
|
||||
flat = "flat ";
|
||||
}
|
||||
const bool add_defines = iface.instance_name.is_empty();
|
||||
|
||||
os << "struct " << struct_name << " {\n";
|
||||
for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
|
||||
os << " " << to_string(inout.type) << " " << inout.name << ";\n";
|
||||
}
|
||||
os << "};\n";
|
||||
os << "layout(location=" << location << ") " << prefix << " " << flat << struct_name << " "
|
||||
<< iface_attribute << suffix << ";\n";
|
||||
|
||||
if (add_defines) {
|
||||
for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
|
||||
os << "#define " << inout.name << " (" << iface_attribute << "." << inout.name << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
|
||||
location += get_location_count(inout.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
|
||||
{
|
||||
std::stringstream ss;
|
||||
/* Prototype for the original main. */
|
||||
ss << "\n";
|
||||
ss << "void main_function_();\n";
|
||||
/* Wrapper to the main function in order to inject code processing on globals. */
|
||||
ss << "void main() {\n";
|
||||
ss << pre_main;
|
||||
ss << " main_function_();\n";
|
||||
ss << post_main;
|
||||
ss << "}\n";
|
||||
/* Rename the original main. */
|
||||
ss << "#define main main_function_\n";
|
||||
ss << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static const std::string to_stage_name(shaderc_shader_kind stage)
|
||||
{
|
||||
switch (stage) {
|
||||
case shaderc_vertex_shader:
|
||||
return std::string("vertex");
|
||||
case shaderc_geometry_shader:
|
||||
return std::string("geometry");
|
||||
case shaderc_fragment_shader:
|
||||
return std::string("fragment");
|
||||
case shaderc_compute_shader:
|
||||
return std::string("compute");
|
||||
|
||||
default:
|
||||
BLI_assert_msg(false, "Do not know how to convert shaderc_shader_kind to stage name.");
|
||||
break;
|
||||
}
|
||||
return std::string("unknown stage");
|
||||
}
|
||||
|
||||
static char *glsl_patch_get()
|
||||
{
|
||||
static char patch[2048] = "\0";
|
||||
if (patch[0] != '\0') {
|
||||
return patch;
|
||||
}
|
||||
|
||||
size_t slen = 0;
|
||||
/* Version need to go first. */
|
||||
STR_CONCAT(patch, slen, "#version 450\n");
|
||||
STR_CONCAT(patch, slen, "#define gl_VertexID gl_VertexIndex\n");
|
||||
STR_CONCAT(patch, slen, "#define gpu_BaseInstance (0)\n");
|
||||
STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceIndex)\n");
|
||||
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
|
||||
|
||||
STR_CONCAT(patch, slen, "#define gl_InstanceID gpu_InstanceIndex\n");
|
||||
|
||||
STR_CONCAT(patch, slen, "#define DFDX_SIGN 1.0\n");
|
||||
STR_CONCAT(patch, slen, "#define DFDY_SIGN 1.0\n");
|
||||
|
||||
/* GLSL Backend Lib. */
|
||||
STR_CONCAT(patch, slen, datatoc_glsl_shader_defines_glsl);
|
||||
|
||||
BLI_assert(slen < sizeof(patch));
|
||||
return patch;
|
||||
}
|
||||
|
||||
static std::string combine_sources(Span<const char *> sources)
|
||||
{
|
||||
char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size());
|
||||
return std::string(sources_combined);
|
||||
}
|
||||
|
||||
Vector<uint32_t> VKShader::compile_glsl_to_spirv(Span<const char *> sources,
|
||||
shaderc_shader_kind stage)
|
||||
{
|
||||
std::string combined_sources = combine_sources(sources);
|
||||
VKBackend &backend = static_cast<VKBackend &>(*VKBackend::get());
|
||||
shaderc::Compiler &compiler = backend.get_shaderc_compiler();
|
||||
shaderc::CompileOptions options;
|
||||
options.SetOptimizationLevel(shaderc_optimization_level_performance);
|
||||
|
||||
shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(
|
||||
combined_sources, stage, name, options);
|
||||
if (module.GetNumErrors() != 0 || module.GetNumWarnings() != 0) {
|
||||
std::string log = module.GetErrorMessage();
|
||||
Vector<char> logcstr(log.c_str(), log.c_str() + log.size() + 1);
|
||||
|
||||
VKLogParser parser;
|
||||
print_log(sources,
|
||||
logcstr.data(),
|
||||
to_stage_name(stage).c_str(),
|
||||
module.GetCompilationStatus() != shaderc_compilation_status_success,
|
||||
&parser);
|
||||
}
|
||||
|
||||
if (module.GetCompilationStatus() != shaderc_compilation_status_success) {
|
||||
compilation_failed_ = true;
|
||||
return Vector<uint32_t>();
|
||||
}
|
||||
|
||||
return Vector<uint32_t>(module.cbegin(), module.cend());
|
||||
}
|
||||
|
||||
void VKShader::build_shader_module(Span<uint32_t> spirv_module, VkShaderModule *r_shader_module)
|
||||
{
|
||||
VkShaderModuleCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
create_info.codeSize = spirv_module.size() * sizeof(uint32_t);
|
||||
create_info.pCode = spirv_module.data();
|
||||
|
||||
VKContext &context = *static_cast<VKContext *>(VKContext::get());
|
||||
|
||||
VkResult result = vkCreateShaderModule(
|
||||
context.device_get(), &create_info, nullptr, r_shader_module);
|
||||
if (result != VK_SUCCESS) {
|
||||
compilation_failed_ = true;
|
||||
*r_shader_module = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
VKShader::VKShader(const char *name) : Shader(name)
|
||||
{
|
||||
context_ = VKContext::get();
|
||||
}
|
||||
|
||||
VKShader::~VKShader()
|
||||
{
|
||||
VkDevice device = context_->device_get();
|
||||
if (vertex_module_ != VK_NULL_HANDLE) {
|
||||
vkDestroyShaderModule(device, vertex_module_, nullptr);
|
||||
vertex_module_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (geometry_module_ != VK_NULL_HANDLE) {
|
||||
vkDestroyShaderModule(device, geometry_module_, nullptr);
|
||||
geometry_module_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (fragment_module_ != VK_NULL_HANDLE) {
|
||||
vkDestroyShaderModule(device, fragment_module_, nullptr);
|
||||
fragment_module_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (compute_module_ != VK_NULL_HANDLE) {
|
||||
vkDestroyShaderModule(device, compute_module_, nullptr);
|
||||
compute_module_ = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void VKShader::build_shader_module(MutableSpan<const char *> sources,
|
||||
shaderc_shader_kind stage,
|
||||
VkShaderModule *r_shader_module)
|
||||
{
|
||||
BLI_assert_msg(ELEM(stage,
|
||||
shaderc_vertex_shader,
|
||||
shaderc_geometry_shader,
|
||||
shaderc_fragment_shader,
|
||||
shaderc_compute_shader),
|
||||
"Only forced ShaderC shader kinds are supported.");
|
||||
sources[0] = glsl_patch_get();
|
||||
Vector<uint32_t> spirv_module = compile_glsl_to_spirv(sources, stage);
|
||||
build_shader_module(spirv_module, &compute_module_);
|
||||
}
|
||||
|
||||
void VKShader::vertex_shader_from_glsl(MutableSpan<const char *> sources)
|
||||
{
|
||||
build_shader_module(sources, shaderc_vertex_shader, &vertex_module_);
|
||||
}
|
||||
|
||||
void VKShader::geometry_shader_from_glsl(MutableSpan<const char *> sources)
|
||||
{
|
||||
build_shader_module(sources, shaderc_geometry_shader, &geometry_module_);
|
||||
}
|
||||
|
||||
void VKShader::fragment_shader_from_glsl(MutableSpan<const char *> sources)
|
||||
{
|
||||
build_shader_module(sources, shaderc_fragment_shader, &fragment_module_);
|
||||
}
|
||||
|
||||
void VKShader::compute_shader_from_glsl(MutableSpan<const char *> sources)
|
||||
{
|
||||
build_shader_module(sources, shaderc_compute_shader, &compute_module_);
|
||||
}
|
||||
|
||||
bool VKShader::finalize(const shader::ShaderCreateInfo * /*info*/)
|
||||
{
|
||||
return false;
|
||||
if (compilation_failed_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vertex_module_ != VK_NULL_HANDLE) {
|
||||
BLI_assert(fragment_module_ != VK_NULL_HANDLE);
|
||||
BLI_assert(compute_module_ == VK_NULL_HANDLE);
|
||||
|
||||
VkPipelineShaderStageCreateInfo vertex_stage_info = {};
|
||||
vertex_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
vertex_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vertex_stage_info.module = vertex_module_;
|
||||
vertex_stage_info.pName = "main";
|
||||
pipeline_infos_.append(vertex_stage_info);
|
||||
|
||||
if (geometry_module_ != VK_NULL_HANDLE) {
|
||||
VkPipelineShaderStageCreateInfo geo_stage_info = {};
|
||||
geo_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
geo_stage_info.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
geo_stage_info.module = geometry_module_;
|
||||
geo_stage_info.pName = "main";
|
||||
pipeline_infos_.append(geo_stage_info);
|
||||
}
|
||||
VkPipelineShaderStageCreateInfo fragment_stage_info = {};
|
||||
fragment_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
fragment_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fragment_stage_info.module = fragment_module_;
|
||||
fragment_stage_info.pName = "main";
|
||||
pipeline_infos_.append(fragment_stage_info);
|
||||
}
|
||||
else {
|
||||
BLI_assert(vertex_module_ == VK_NULL_HANDLE);
|
||||
BLI_assert(geometry_module_ == VK_NULL_HANDLE);
|
||||
BLI_assert(fragment_module_ == VK_NULL_HANDLE);
|
||||
BLI_assert(compute_module_ != VK_NULL_HANDLE);
|
||||
|
||||
VkPipelineShaderStageCreateInfo compute_stage_info = {};
|
||||
compute_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
compute_stage_info.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
compute_stage_info.module = geometry_module_;
|
||||
compute_stage_info.pName = "main";
|
||||
pipeline_infos_.append(compute_stage_info);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VKShader::transform_feedback_names_set(Span<const char *> /*name_list*/,
|
||||
@@ -64,34 +717,222 @@ void VKShader::uniform_int(int /*location*/,
|
||||
{
|
||||
}
|
||||
|
||||
std::string VKShader::resources_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
return std::string();
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "\n/* Pass Resources. */\n";
|
||||
for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
|
||||
print_resource(ss, res);
|
||||
}
|
||||
for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
|
||||
print_resource_alias(ss, res);
|
||||
}
|
||||
|
||||
ss << "\n/* Batch Resources. */\n";
|
||||
for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
|
||||
print_resource(ss, res);
|
||||
}
|
||||
for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
|
||||
print_resource_alias(ss, res);
|
||||
}
|
||||
|
||||
if (!info.push_constants_.is_empty()) {
|
||||
ss << "\n/* Push Constants. */\n";
|
||||
ss << "layout(push_constant) uniform constants\n";
|
||||
ss << "{\n";
|
||||
for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
|
||||
ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
|
||||
if (uniform.array_size > 0) {
|
||||
ss << "[" << uniform.array_size << "]";
|
||||
}
|
||||
ss << ";\n";
|
||||
}
|
||||
ss << "} PushConstants;\n";
|
||||
for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
|
||||
ss << "#define " << uniform.name << " (PushConstants.pc_" << uniform.name << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
ss << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
return std::string();
|
||||
std::stringstream ss;
|
||||
std::string post_main;
|
||||
|
||||
ss << "\n/* Inputs. */\n";
|
||||
for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
|
||||
ss << "layout(location = " << attr.index << ") ";
|
||||
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
|
||||
}
|
||||
/* NOTE(D4490): Fix a bug where shader without any vertex attributes do not behave correctly.
|
||||
*/
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL) &&
|
||||
info.vertex_inputs_.is_empty()) {
|
||||
ss << "in float gpu_dummy_workaround;\n";
|
||||
}
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
int location = 0;
|
||||
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
||||
print_interface(ss, "out", *iface, location);
|
||||
}
|
||||
if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) {
|
||||
/* Need this for stable barycentric. */
|
||||
ss << "flat out vec4 gpu_pos_flat;\n";
|
||||
ss << "out vec4 gpu_pos;\n";
|
||||
|
||||
post_main += " gpu_pos = gpu_pos_flat = gl_Position;\n";
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
if (post_main.empty() == false) {
|
||||
std::string pre_main;
|
||||
ss << main_function_wrapper(pre_main, post_main);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
return std::string();
|
||||
std::stringstream ss;
|
||||
std::string pre_main;
|
||||
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
const Vector<StageInterfaceInfo *> &in_interfaces = info.geometry_source_.is_empty() ?
|
||||
info.vertex_out_interfaces_ :
|
||||
info.geometry_out_interfaces_;
|
||||
int location = 0;
|
||||
for (const StageInterfaceInfo *iface : in_interfaces) {
|
||||
print_interface(ss, "in", *iface, location);
|
||||
}
|
||||
if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) {
|
||||
std::cout << "native" << std::endl;
|
||||
/* NOTE(fclem): This won't work with geometry shader. Hopefully, we don't need geometry
|
||||
* shader workaround if this extension/feature is detected. */
|
||||
ss << "\n/* Stable Barycentric Coordinates. */\n";
|
||||
ss << "flat in vec4 gpu_pos_flat;\n";
|
||||
ss << "__explicitInterpAMD in vec4 gpu_pos;\n";
|
||||
/* Globals. */
|
||||
ss << "vec3 gpu_BaryCoord;\n";
|
||||
ss << "vec3 gpu_BaryCoordNoPersp;\n";
|
||||
ss << "\n";
|
||||
ss << "vec2 stable_bary_(vec2 in_bary) {\n";
|
||||
ss << " vec3 bary = vec3(in_bary, 1.0 - in_bary.x - in_bary.y);\n";
|
||||
ss << " if (interpolateAtVertexAMD(gpu_pos, 0) == gpu_pos_flat) { return bary.zxy; }\n";
|
||||
ss << " if (interpolateAtVertexAMD(gpu_pos, 2) == gpu_pos_flat) { return bary.yzx; }\n";
|
||||
ss << " return bary.xyz;\n";
|
||||
ss << "}\n";
|
||||
ss << "\n";
|
||||
ss << "vec4 gpu_position_at_vertex(int v) {\n";
|
||||
ss << " if (interpolateAtVertexAMD(gpu_pos, 0) == gpu_pos_flat) { v = (v + 2) % 3; }\n";
|
||||
ss << " if (interpolateAtVertexAMD(gpu_pos, 2) == gpu_pos_flat) { v = (v + 1) % 3; }\n";
|
||||
ss << " return interpolateAtVertexAMD(gpu_pos, v);\n";
|
||||
ss << "}\n";
|
||||
|
||||
pre_main += " gpu_BaryCoord = stable_bary_(gl_BaryCoordSmoothAMD);\n";
|
||||
pre_main += " gpu_BaryCoordNoPersp = stable_bary_(gl_BaryCoordNoPerspAMD);\n";
|
||||
}
|
||||
if (info.early_fragment_test_) {
|
||||
ss << "layout(early_fragment_tests) in;\n";
|
||||
}
|
||||
ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n";
|
||||
ss << "\n/* Outputs. */\n";
|
||||
for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) {
|
||||
ss << "layout(location = " << output.index;
|
||||
switch (output.blend) {
|
||||
case DualBlend::SRC_0:
|
||||
ss << ", index = 0";
|
||||
break;
|
||||
case DualBlend::SRC_1:
|
||||
ss << ", index = 1";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ss << ") ";
|
||||
ss << "out " << to_string(output.type) << " " << output.name << ";\n";
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
if (pre_main.empty() == false) {
|
||||
std::string post_main;
|
||||
ss << main_function_wrapper(pre_main, post_main);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string VKShader::geometry_interface_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
std::string VKShader::geometry_interface_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
return std::string();
|
||||
int max_verts = info.geometry_layout_.max_vertices;
|
||||
int invocations = info.geometry_layout_.invocations;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "\n/* Geometry Layout. */\n";
|
||||
ss << "layout(" << to_string(info.geometry_layout_.primitive_in);
|
||||
if (invocations != -1) {
|
||||
ss << ", invocations = " << invocations;
|
||||
}
|
||||
ss << ") in;\n";
|
||||
|
||||
ss << "layout(" << to_string(info.geometry_layout_.primitive_out)
|
||||
<< ", max_vertices = " << max_verts << ") out;\n";
|
||||
ss << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string VKShader::geometry_layout_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInfo *> &ifaces,
|
||||
const StringRefNull &name)
|
||||
{
|
||||
return std::string();
|
||||
for (auto *iface : ifaces) {
|
||||
if (iface->instance_name == name) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string VKShader::compute_layout_declare(const shader::ShaderCreateInfo & /*info*/) const
|
||||
std::string VKShader::geometry_layout_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
return std::string();
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
int location = 0;
|
||||
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
||||
bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
|
||||
iface->instance_name) != nullptr;
|
||||
const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]";
|
||||
print_interface(ss, "in", *iface, location, suffix);
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
|
||||
bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
|
||||
iface->instance_name) != nullptr;
|
||||
const char *suffix = (has_matching_input_iface) ? "_out" : "";
|
||||
print_interface(ss, "out", *iface, location, suffix);
|
||||
}
|
||||
ss << "\n";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string VKShader::compute_layout_declare(const shader::ShaderCreateInfo &info) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "\n/* Compute Layout. */\n";
|
||||
ss << "layout(local_size_x = " << info.compute_layout_.local_size_x;
|
||||
if (info.compute_layout_.local_size_y != -1) {
|
||||
ss << ", local_size_y = " << info.compute_layout_.local_size_y;
|
||||
}
|
||||
if (info.compute_layout_.local_size_z != -1) {
|
||||
ss << ", local_size_z = " << info.compute_layout_.local_size_z;
|
||||
}
|
||||
ss << ") in;\n";
|
||||
ss << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int VKShader::program_handle_get() const
|
||||
|
@@ -9,13 +9,26 @@
|
||||
|
||||
#include "gpu_shader_private.hh"
|
||||
|
||||
#include "vk_backend.hh"
|
||||
#include "vk_context.hh"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
class VKShader : public Shader {
|
||||
private:
|
||||
VKContext *context_ = nullptr;
|
||||
VkShaderModule vertex_module_ = VK_NULL_HANDLE;
|
||||
VkShaderModule geometry_module_ = VK_NULL_HANDLE;
|
||||
VkShaderModule fragment_module_ = VK_NULL_HANDLE;
|
||||
VkShaderModule compute_module_ = VK_NULL_HANDLE;
|
||||
bool compilation_failed_ = false;
|
||||
Vector<VkPipelineShaderStageCreateInfo> pipeline_infos_;
|
||||
|
||||
public:
|
||||
VKShader(const char *name) : Shader(name)
|
||||
{
|
||||
}
|
||||
VKShader(const char *name);
|
||||
virtual ~VKShader();
|
||||
|
||||
void vertex_shader_from_glsl(MutableSpan<const char *> sources) override;
|
||||
void geometry_shader_from_glsl(MutableSpan<const char *> sources) override;
|
||||
@@ -43,6 +56,13 @@ class VKShader : public Shader {
|
||||
|
||||
/* DEPRECATED: Kept only because of BGL API. */
|
||||
int program_handle_get() const override;
|
||||
|
||||
private:
|
||||
Vector<uint32_t> compile_glsl_to_spirv(Span<const char *> sources, shaderc_shader_kind kind);
|
||||
void build_shader_module(Span<uint32_t> spirv_module, VkShaderModule *r_shader_module);
|
||||
void build_shader_module(MutableSpan<const char *> sources,
|
||||
shaderc_shader_kind stage,
|
||||
VkShaderModule *r_shader_module);
|
||||
};
|
||||
|
||||
} // namespace blender::gpu
|
44
source/blender/gpu/vulkan/vk_shader_log.cc
Normal file
44
source/blender/gpu/vulkan/vk_shader_log.cc
Normal file
@@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2022 Blender Foundation. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#include "vk_shader_log.hh"
|
||||
|
||||
#include "GPU_platform.h"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
char *VKLogParser::parse_line(char *log_line, GPULogItem &log_item)
|
||||
{
|
||||
log_line = skip_name(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(char *log_line)
|
||||
{
|
||||
return skip_until(log_line, ':');
|
||||
}
|
||||
|
||||
char *VKLogParser::skip_severity_keyword(char *log_line, GPULogItem &log_item)
|
||||
{
|
||||
return skip_severity(log_line, log_item, "error", "warning");
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
16
source/blender/gpu/vulkan/vk_shader_log.hh
Normal file
16
source/blender/gpu/vulkan/vk_shader_log.hh
Normal file
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2022 Blender Foundation. All rights reserved. */
|
||||
|
||||
#include "gpu_shader_private.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
class VKLogParser : public GPULogParser {
|
||||
public:
|
||||
char *parse_line(char *log_line, GPULogItem &log_item) override;
|
||||
|
||||
protected:
|
||||
char *skip_name(char *log_line);
|
||||
char *skip_severity_keyword(char *log_line, GPULogItem &log_item);
|
||||
};
|
||||
} // namespace blender::gpu
|
Reference in New Issue
Block a user