2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <shaderc/shaderc.h>
21 #include "libavutil/mem.h"
22 #include "vulkan_spirv.h"
24 static int shdc_shader_compile(FFVulkanContext
*s
, FFVkSPIRVCompiler
*ctx
,
25 FFVulkanShader
*shd
, uint8_t **data
,
26 size_t *size
, const char *entrypoint
,
29 int loglevel
, err
, warn
, ret
;
30 const char *status
, *message
;
31 shaderc_compilation_result_t res
;
32 static const char *shdc_result
[] = {
33 [shaderc_compilation_status_success
] = "success",
34 [shaderc_compilation_status_invalid_stage
] = "invalid stage",
35 [shaderc_compilation_status_compilation_error
] = "error",
36 [shaderc_compilation_status_internal_error
] = "internal error",
37 [shaderc_compilation_status_null_result_object
] = "no result",
38 [shaderc_compilation_status_invalid_assembly
] = "invalid assembly",
40 static const shaderc_shader_kind shdc_kind
[] = {
41 [VK_SHADER_STAGE_VERTEX_BIT
] = shaderc_glsl_vertex_shader
,
42 [VK_SHADER_STAGE_FRAGMENT_BIT
] = shaderc_glsl_fragment_shader
,
43 [VK_SHADER_STAGE_COMPUTE_BIT
] = shaderc_glsl_compute_shader
,
44 [VK_SHADER_STAGE_MESH_BIT_EXT
] = shaderc_mesh_shader
,
45 [VK_SHADER_STAGE_TASK_BIT_EXT
] = shaderc_task_shader
,
46 [VK_SHADER_STAGE_RAYGEN_BIT_KHR
] = shaderc_raygen_shader
,
47 [VK_SHADER_STAGE_ANY_HIT_BIT_KHR
] = shaderc_anyhit_shader
,
48 [VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
] = shaderc_closesthit_shader
,
49 [VK_SHADER_STAGE_MISS_BIT_KHR
] = shaderc_miss_shader
,
50 [VK_SHADER_STAGE_INTERSECTION_BIT_KHR
] = shaderc_intersection_shader
,
51 [VK_SHADER_STAGE_CALLABLE_BIT_KHR
] = shaderc_callable_shader
,
54 shaderc_compile_options_t opts
= shaderc_compile_options_initialize();
57 return AVERROR(ENOMEM
);
59 shaderc_compile_options_set_target_env(opts
, shaderc_target_env_vulkan
,
60 shaderc_env_version_vulkan_1_3
);
61 shaderc_compile_options_set_target_spirv(opts
, shaderc_spirv_version_1_6
);
63 /* If either extension is set, turn on debug info */
64 if (s
->extensions
& (FF_VK_EXT_DEBUG_UTILS
| FF_VK_EXT_RELAXED_EXTENDED_INSTR
))
65 shaderc_compile_options_set_generate_debug_info(opts
);
67 if (s
->extensions
& FF_VK_EXT_DEBUG_UTILS
)
68 shaderc_compile_options_set_optimization_level(opts
,
69 shaderc_optimization_level_zero
);
71 shaderc_compile_options_set_optimization_level(opts
,
72 shaderc_optimization_level_performance
);
74 res
= shaderc_compile_into_spv((shaderc_compiler_t
)ctx
->priv
,
75 shd
->src
.str
, strlen(shd
->src
.str
),
76 shdc_kind
[shd
->stage
],
77 shd
->name
, entrypoint
, opts
);
78 shaderc_compile_options_release(opts
);
80 ret
= shaderc_result_get_compilation_status(res
);
81 err
= shaderc_result_get_num_errors(res
);
82 warn
= shaderc_result_get_num_warnings(res
);
83 message
= shaderc_result_get_error_message(res
);
85 if (ret
!= shaderc_compilation_status_success
&& !err
)
88 loglevel
= err
? AV_LOG_ERROR
: warn
? AV_LOG_WARNING
: AV_LOG_TRACE
;
90 ff_vk_shader_print(s
, shd
, loglevel
);
91 if (message
&& (err
|| warn
))
92 av_log(s
, loglevel
, "%s\n", message
);
93 status
= ret
< FF_ARRAY_ELEMS(shdc_result
) ? shdc_result
[ret
] : "unknown";
94 av_log(s
, loglevel
, "shaderc compile status '%s' (%d errors, %d warnings)\n",
98 return AVERROR(EINVAL
);
100 *data
= (uint8_t *)shaderc_result_get_bytes(res
);
101 *size
= shaderc_result_get_length(res
);
107 static void shdc_shader_free(FFVkSPIRVCompiler
*ctx
, void **opaque
)
109 if (!opaque
|| !*opaque
)
112 shaderc_result_release((shaderc_compilation_result_t
)*opaque
);
116 static void shdc_uninit(FFVkSPIRVCompiler
**ctx
)
118 FFVkSPIRVCompiler
*s
;
125 shaderc_compiler_release((shaderc_compiler_t
)s
->priv
);
129 FFVkSPIRVCompiler
*ff_vk_shaderc_init(void)
131 FFVkSPIRVCompiler
*ret
= av_mallocz(sizeof(*ret
));
135 ret
->compile_shader
= shdc_shader_compile
;
136 ret
->free_shader
= shdc_shader_free
;
137 ret
->uninit
= shdc_uninit
;
139 ret
->priv
= (void *)shaderc_compiler_initialize();