2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
2018-08-30 01:56:08 +10:00
|
|
|
*/
|
|
|
|
|
|
2025-10-16 19:12:16 +02:00
|
|
|
#include "BLI_colorspace.hh"
|
2022-07-29 08:37:57 +02:00
|
|
|
#include "BLI_math_matrix.h"
|
2025-10-16 19:12:16 +02:00
|
|
|
#include "BLI_math_matrix_types.hh"
|
Cleanup: fewer iostreams related includes from BLI/BKE headers
Including <iostream> or similar headers is quite expensive, since it
also pulls in things like <locale> and so on. In many BLI headers,
iostreams are only used to implement some sort of "debug print",
or an operator<< for ostream.
Change some of the commonly used places to instead include <iosfwd>,
which is the standard way of forward-declaring iostreams related
classes, and move the actual debug-print / operator<< implementations
into .cc files.
This is not done for templated classes though (it would be possible
to provide explicit operator<< instantiations somewhere in the
source file, but that would lead to hard-to-figure-out linker error
whenever someone would add a different template type). There, where
possible, I changed from full <iostream> include to only the needed
<ostream> part.
For Span<T>, I just removed print_as_lines since it's not used by
anything. It could be moved into a .cc file using a similar approach
as above if needed.
Doing full blender build changes include counts this way:
- <iostream> 1986 -> 978
- <sstream> 2880 -> 925
It does not affect the total build time much though, mostly because
towards the end of it there's just several CPU cores finishing
compiling OpenVDB related source files.
Pull Request: https://projects.blender.org/blender/blender/pulls/111046
2023-08-11 12:27:56 +03:00
|
|
|
#include "BLI_string.h"
|
2017-09-27 18:03:00 +02:00
|
|
|
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "GPU_capabilities.hh"
|
|
|
|
|
#include "GPU_debug.hh"
|
|
|
|
|
#include "GPU_matrix.hh"
|
|
|
|
|
#include "GPU_platform.hh"
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2024-10-07 12:54:10 +02:00
|
|
|
#include "glsl_preprocess/glsl_preprocess.hh"
|
|
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
#include "gpu_backend.hh"
|
2020-08-09 00:52:45 +02:00
|
|
|
#include "gpu_context_private.hh"
|
2025-06-06 14:39:51 +02:00
|
|
|
#include "gpu_profile_report.hh"
|
2022-01-17 14:45:22 +01:00
|
|
|
#include "gpu_shader_create_info.hh"
|
|
|
|
|
#include "gpu_shader_create_info_private.hh"
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "gpu_shader_dependency_private.hh"
|
2020-08-14 15:20:35 +02:00
|
|
|
#include "gpu_shader_private.hh"
|
2016-09-16 17:18:19 +02:00
|
|
|
|
2022-01-17 14:45:22 +01:00
|
|
|
#include <string>
|
|
|
|
|
|
2020-07-29 16:07:51 +02:00
|
|
|
extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
|
2020-07-28 20:04:15 +02:00
|
|
|
|
2022-01-17 14:45:22 +01:00
|
|
|
namespace blender::gpu {
|
|
|
|
|
|
|
|
|
|
std::string Shader::defines_declare(const shader::ShaderCreateInfo &info) const
|
|
|
|
|
{
|
|
|
|
|
std::string defines;
|
|
|
|
|
for (const auto &def : info.defines_) {
|
|
|
|
|
defines += "#define ";
|
|
|
|
|
defines += def[0];
|
|
|
|
|
defines += " ";
|
|
|
|
|
defines += def[1];
|
|
|
|
|
defines += "\n";
|
|
|
|
|
}
|
|
|
|
|
return defines;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::gpu
|
|
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
using namespace blender;
|
|
|
|
|
using namespace blender::gpu;
|
2018-08-02 18:31:38 +02:00
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Creation / Destruction
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
Shader::Shader(const char *sh_name)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(this->name, sh_name);
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
Shader::~Shader()
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2025-05-20 12:43:58 +02:00
|
|
|
BLI_assert_msg(Context::get() == nullptr || Context::get()->shader != this,
|
|
|
|
|
"Shader must be unbound from context before being freed");
|
2020-08-20 13:32:51 -04:00
|
|
|
delete interface;
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
static void standard_defines(Vector<StringRefNull> &sources)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2023-12-11 13:54:57 -05:00
|
|
|
BLI_assert(sources.is_empty());
|
2024-01-12 14:28:50 +01:00
|
|
|
/* Version and specialization constants needs to be first.
|
|
|
|
|
* Exact values will be added by implementation. */
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("version");
|
2024-01-12 14:28:50 +01:00
|
|
|
sources.append("/* specialization_constants */");
|
2022-01-17 14:45:22 +01:00
|
|
|
/* Define to identify code usage in shading language. */
|
|
|
|
|
sources.append("#define GPU_SHADER\n");
|
2015-12-06 21:20:19 +01:00
|
|
|
/* some useful defines to detect GPU type */
|
2019-04-22 09:32:37 +10:00
|
|
|
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define GPU_ATI\n");
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
|
|
|
|
else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define GPU_NVIDIA\n");
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
|
|
|
|
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define GPU_INTEL\n");
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
2024-04-04 16:24:20 +02:00
|
|
|
else if (GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
|
|
|
|
sources.append("#define GPU_APPLE\n");
|
|
|
|
|
}
|
2019-03-09 16:42:44 +01:00
|
|
|
/* some useful defines to detect OS type */
|
2019-04-22 09:32:37 +10:00
|
|
|
if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_WIN, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define OS_WIN\n");
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
|
|
|
|
else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define OS_MAC\n");
|
2019-04-22 09:32:37 +10:00
|
|
|
}
|
|
|
|
|
else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
|
2020-08-14 15:20:35 +02:00
|
|
|
sources.append("#define OS_UNIX\n");
|
2020-07-28 20:04:15 +02:00
|
|
|
}
|
2022-03-22 12:44:26 +01:00
|
|
|
/* API Definition */
|
2025-09-15 15:11:02 +02:00
|
|
|
GPUBackendType backend = GPU_backend_get_type();
|
2022-03-22 12:44:26 +01:00
|
|
|
switch (backend) {
|
|
|
|
|
case GPU_BACKEND_OPENGL:
|
|
|
|
|
sources.append("#define GPU_OPENGL\n");
|
|
|
|
|
break;
|
2022-09-01 22:22:32 +02:00
|
|
|
case GPU_BACKEND_METAL:
|
|
|
|
|
sources.append("#define GPU_METAL\n");
|
|
|
|
|
break;
|
2022-12-12 12:22:38 +01:00
|
|
|
case GPU_BACKEND_VULKAN:
|
|
|
|
|
sources.append("#define GPU_VULKAN\n");
|
|
|
|
|
break;
|
2022-03-22 12:44:26 +01:00
|
|
|
default:
|
2024-04-03 14:24:39 +11:00
|
|
|
BLI_assert_msg(false, "Invalid GPU Backend Type");
|
2022-03-22 12:44:26 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2020-04-14 20:44:45 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_free(blender::gpu::Shader *shader)
|
2020-08-14 15:20:35 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
delete shader;
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
/** \} */
|
2017-09-27 18:03:00 +02:00
|
|
|
|
2020-08-14 15:20:35 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Creation utils
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-02-01 13:42:00 +01:00
|
|
|
const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name)
|
|
|
|
|
{
|
|
|
|
|
return gpu_shader_create_info_get(info_name);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-12 18:28:27 -03:00
|
|
|
bool GPU_shader_create_info_check_error(const GPUShaderCreateInfo *_info, char r_error[128])
|
|
|
|
|
{
|
|
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info);
|
|
|
|
|
std::string error = info.check_error();
|
|
|
|
|
if (error.length() == 0) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(r_error, error.c_str(), 128);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *GPU_shader_create_from_info_name(const char *info_name)
|
2022-01-25 14:22:44 +01:00
|
|
|
{
|
|
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
const GPUShaderCreateInfo *_info = gpu_shader_create_info_get(info_name);
|
|
|
|
|
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info);
|
|
|
|
|
if (!info.do_static_compilation_) {
|
2024-11-01 20:00:31 +01:00
|
|
|
std::cerr << "Warning: Trying to compile \"" << info.name_
|
2023-08-09 18:15:26 +02:00
|
|
|
<< "\" which was not marked for static compilation.\n";
|
2022-01-25 14:22:44 +01:00
|
|
|
}
|
|
|
|
|
return GPU_shader_create_from_info(_info);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
|
2022-01-17 14:45:22 +01:00
|
|
|
{
|
|
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info);
|
2025-08-11 09:34:28 +02:00
|
|
|
return GPUBackend::get()->get_compiler()->compile(info, false);
|
2022-01-17 14:45:22 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-16 18:49:21 +02:00
|
|
|
std::string GPU_shader_preprocess_source(StringRefNull original)
|
2024-10-07 12:54:10 +02:00
|
|
|
{
|
2025-01-14 10:51:24 +01:00
|
|
|
if (original.is_empty()) {
|
|
|
|
|
return original;
|
|
|
|
|
}
|
2024-10-12 13:48:45 +02:00
|
|
|
gpu::shader::Preprocessor processor;
|
2024-10-11 18:52:34 +02:00
|
|
|
return processor.process(original);
|
2024-10-07 12:54:10 +02:00
|
|
|
};
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *GPU_shader_create_from_info_python(const GPUShaderCreateInfo *_info)
|
2024-10-07 12:54:10 +02:00
|
|
|
{
|
|
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
ShaderCreateInfo &info = *const_cast<ShaderCreateInfo *>(
|
|
|
|
|
reinterpret_cast<const ShaderCreateInfo *>(_info));
|
|
|
|
|
|
|
|
|
|
std::string vertex_source_original = info.vertex_source_generated;
|
|
|
|
|
std::string fragment_source_original = info.fragment_source_generated;
|
|
|
|
|
std::string geometry_source_original = info.geometry_source_generated;
|
|
|
|
|
std::string compute_source_original = info.compute_source_generated;
|
|
|
|
|
|
2025-04-16 18:49:21 +02:00
|
|
|
info.vertex_source_generated = GPU_shader_preprocess_source(info.vertex_source_generated);
|
|
|
|
|
info.fragment_source_generated = GPU_shader_preprocess_source(info.fragment_source_generated);
|
|
|
|
|
info.geometry_source_generated = GPU_shader_preprocess_source(info.geometry_source_generated);
|
|
|
|
|
info.compute_source_generated = GPU_shader_preprocess_source(info.compute_source_generated);
|
2024-10-07 12:54:10 +02:00
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *result = GPUBackend::get()->get_compiler()->compile(info, false);
|
2024-10-07 12:54:10 +02:00
|
|
|
|
|
|
|
|
info.vertex_source_generated = vertex_source_original;
|
|
|
|
|
info.fragment_source_generated = fragment_source_original;
|
|
|
|
|
info.geometry_source_generated = geometry_source_original;
|
|
|
|
|
info.compute_source_generated = compute_source_original;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-29 19:43:02 +02:00
|
|
|
BatchHandle GPU_shader_batch_create_from_infos(Span<const GPUShaderCreateInfo *> infos,
|
|
|
|
|
CompilationPriority priority)
|
2024-06-05 18:45:57 +02:00
|
|
|
{
|
|
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
Span<const ShaderCreateInfo *> &infos_ = reinterpret_cast<Span<const ShaderCreateInfo *> &>(
|
|
|
|
|
infos);
|
2025-05-29 19:43:02 +02:00
|
|
|
return GPUBackend::get()->get_compiler()->batch_compile(infos_, priority);
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_shader_batch_is_ready(BatchHandle handle)
|
|
|
|
|
{
|
2025-05-08 18:16:47 +02:00
|
|
|
return GPUBackend::get()->get_compiler()->batch_is_ready(handle);
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
Vector<blender::gpu::Shader *> GPU_shader_batch_finalize(BatchHandle &handle)
|
2024-06-05 18:45:57 +02:00
|
|
|
{
|
2025-05-08 18:16:47 +02:00
|
|
|
Vector<Shader *> result = GPUBackend::get()->get_compiler()->batch_finalize(handle);
|
2025-08-11 09:34:28 +02:00
|
|
|
return reinterpret_cast<Vector<blender::gpu::Shader *> &>(result);
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-12 19:54:03 +02:00
|
|
|
void GPU_shader_batch_cancel(BatchHandle &handle)
|
|
|
|
|
{
|
|
|
|
|
GPUBackend::get()->get_compiler()->batch_cancel(handle);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 20:06:27 +02:00
|
|
|
bool GPU_shader_batch_is_compiling()
|
|
|
|
|
{
|
|
|
|
|
return GPUBackend::get()->get_compiler()->is_compiling();
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-22 17:53:22 +02:00
|
|
|
void GPU_shader_batch_wait_for_all()
|
|
|
|
|
{
|
|
|
|
|
GPUBackend::get()->get_compiler()->wait_for_all();
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-15 08:13:44 +01:00
|
|
|
void GPU_shader_compile_static()
|
|
|
|
|
{
|
|
|
|
|
printf("Compiling all static GPU shaders. This process takes a while.\n");
|
|
|
|
|
gpu_shader_create_info_compile("");
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-16 14:03:14 +02:00
|
|
|
void GPU_shader_cache_dir_clear_old()
|
|
|
|
|
{
|
|
|
|
|
GPUBackend::get()->shader_cache_dir_clear_old();
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Binding
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_bind(blender::gpu::Shader *gpu_shader,
|
|
|
|
|
const shader::SpecializationConstants *constants_state)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
Shader *shader = gpu_shader;
|
2016-09-27 19:38:35 +02:00
|
|
|
|
2025-05-19 17:42:55 +02:00
|
|
|
BLI_assert_msg(constants_state != nullptr || shader->constants->is_empty(),
|
|
|
|
|
"Shader requires specialization constants but none was passed");
|
|
|
|
|
|
2020-09-08 04:12:12 +02:00
|
|
|
Context *ctx = Context::get();
|
2020-08-09 00:52:45 +02:00
|
|
|
|
|
|
|
|
if (ctx->shader != shader) {
|
|
|
|
|
ctx->shader = shader;
|
2025-05-19 17:42:55 +02:00
|
|
|
shader->bind(constants_state);
|
2020-08-21 13:48:34 +02:00
|
|
|
GPU_matrix_bind(gpu_shader);
|
2025-05-07 16:42:01 +02:00
|
|
|
Shader::set_srgb_uniform(ctx, gpu_shader);
|
2025-10-16 19:12:16 +02:00
|
|
|
/* Blender working color space do not change during the drawing of the frame.
|
|
|
|
|
* So we can just set the uniform once. */
|
|
|
|
|
Shader::set_scene_linear_to_xyz_uniform(gpu_shader);
|
2020-08-09 00:52:45 +02:00
|
|
|
}
|
2021-05-02 00:09:43 +10:00
|
|
|
else {
|
2025-05-19 17:42:55 +02:00
|
|
|
if (constants_state) {
|
|
|
|
|
shader->bind(constants_state);
|
2024-01-12 14:28:50 +01:00
|
|
|
}
|
2025-05-07 16:42:01 +02:00
|
|
|
if (ctx->shader_builtin_srgb_is_dirty) {
|
|
|
|
|
Shader::set_srgb_uniform(ctx, gpu_shader);
|
2021-05-02 00:09:43 +10:00
|
|
|
}
|
|
|
|
|
if (GPU_matrix_dirty_get()) {
|
|
|
|
|
GPU_matrix_bind(gpu_shader);
|
|
|
|
|
}
|
2020-08-11 01:31:40 +02:00
|
|
|
}
|
2024-07-19 15:48:00 +02:00
|
|
|
#if GPU_SHADER_PRINTF_ENABLE
|
2024-11-08 20:00:54 +01:00
|
|
|
if (!ctx->printf_buf.is_empty()) {
|
|
|
|
|
GPU_storagebuf_bind(ctx->printf_buf.last(), GPU_SHADER_PRINTF_SLOT);
|
2024-07-19 15:48:00 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2021-12-29 18:51:10 -05:00
|
|
|
void GPU_shader_unbind()
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2020-09-08 04:12:12 +02:00
|
|
|
Context *ctx = Context::get();
|
2025-05-20 12:43:58 +02:00
|
|
|
if (ctx == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#ifndef NDEBUG
|
2020-08-14 15:20:35 +02:00
|
|
|
if (ctx->shader) {
|
2020-09-08 03:34:47 +02:00
|
|
|
ctx->shader->unbind();
|
2020-08-14 15:20:35 +02:00
|
|
|
}
|
2020-08-09 00:52:45 +02:00
|
|
|
#endif
|
2025-05-20 12:43:58 +02:00
|
|
|
ctx->shader = nullptr;
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *GPU_shader_get_bound()
|
2022-12-01 15:33:54 +01:00
|
|
|
{
|
|
|
|
|
Context *ctx = Context::get();
|
|
|
|
|
if (ctx) {
|
2025-08-11 09:34:28 +02:00
|
|
|
return ctx->shader;
|
2022-12-01 15:33:54 +01:00
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
2021-09-13 16:12:12 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Shader name
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
const char *GPU_shader_get_name(blender::gpu::Shader *shader)
|
2021-09-13 16:12:12 +10:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
return shader->name_get().c_str();
|
2021-09-13 16:12:12 +10:00
|
|
|
}
|
|
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-02-14 21:51:03 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Shader cache warming
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_set_parent(blender::gpu::Shader *shader, blender::gpu::Shader *parent)
|
2023-02-14 21:51:03 +01:00
|
|
|
{
|
|
|
|
|
BLI_assert(shader != nullptr);
|
|
|
|
|
BLI_assert(shader != parent);
|
|
|
|
|
if (shader != parent) {
|
2025-08-11 09:34:28 +02:00
|
|
|
Shader *shd_child = shader;
|
|
|
|
|
Shader *shd_parent = parent;
|
2023-02-14 21:51:03 +01:00
|
|
|
shd_child->parent_set(shd_parent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_warm_cache(blender::gpu::Shader *shader, int limit)
|
2023-02-14 21:51:03 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
shader->warm_cache(limit);
|
2023-02-14 21:51:03 +01:00
|
|
|
}
|
|
|
|
|
|
2021-09-13 16:12:12 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-12-28 05:34:38 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Assign specialization constants.
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
const shader::SpecializationConstants &GPU_shader_get_default_constant_state(
|
|
|
|
|
blender::gpu::Shader *sh)
|
2025-05-19 17:42:55 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
return *sh->constants;
|
2025-05-19 17:42:55 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-28 05:34:38 +01:00
|
|
|
void Shader::specialization_constants_init(const shader::ShaderCreateInfo &info)
|
|
|
|
|
{
|
|
|
|
|
using namespace shader;
|
2025-05-19 17:42:55 +02:00
|
|
|
shader::SpecializationConstants constants_tmp;
|
2024-06-07 18:45:31 +02:00
|
|
|
for (const SpecializationConstant &sc : info.specialization_constants_) {
|
2025-05-19 17:42:55 +02:00
|
|
|
constants_tmp.types.append(sc.type);
|
|
|
|
|
constants_tmp.values.append(sc.value);
|
2023-12-28 05:34:38 +01:00
|
|
|
}
|
2025-05-19 17:42:55 +02:00
|
|
|
constants = std::make_unique<const shader::SpecializationConstants>(std::move(constants_tmp));
|
2023-12-28 05:34:38 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-20 18:02:44 +02:00
|
|
|
SpecializationBatchHandle GPU_shader_batch_specializations(
|
2025-05-29 19:43:02 +02:00
|
|
|
blender::Span<ShaderSpecialization> specializations, CompilationPriority priority)
|
2024-06-07 18:45:31 +02:00
|
|
|
{
|
2025-05-29 19:43:02 +02:00
|
|
|
return GPUBackend::get()->get_compiler()->precompile_specializations(specializations, priority);
|
2024-06-20 18:02:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GPU_shader_batch_specializations_is_ready(SpecializationBatchHandle &handle)
|
|
|
|
|
{
|
2025-05-08 18:16:47 +02:00
|
|
|
return GPUBackend::get()->get_compiler()->specialization_batch_is_ready(handle);
|
2024-06-07 18:45:31 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-12 19:54:03 +02:00
|
|
|
void GPU_shader_batch_specializations_cancel(SpecializationBatchHandle &handle)
|
|
|
|
|
{
|
|
|
|
|
GPUBackend::get()->get_compiler()->batch_cancel(handle);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 05:34:38 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Uniforms / Resource location
|
|
|
|
|
* \{ */
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_uniform(blender::gpu::Shader *shader, const char *name)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
const ShaderInput *uniform = interface->uniform_get(name);
|
2017-04-13 18:37:26 -04:00
|
|
|
return uniform ? uniform->location : -1;
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_constant(blender::gpu::Shader *shader, const char *name)
|
2023-12-28 05:34:38 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2023-12-28 05:34:38 +01:00
|
|
|
const ShaderInput *constant = interface->constant_get(name);
|
|
|
|
|
return constant ? constant->location : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_builtin_uniform(blender::gpu::Shader *shader, int builtin)
|
2017-10-08 15:49:25 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
return interface->uniform_builtin((GPUUniformBuiltin)builtin);
|
2020-06-04 13:43:28 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_ssbo_binding(blender::gpu::Shader *shader, const char *name)
|
2021-05-26 16:49:17 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2021-05-26 16:49:17 +02:00
|
|
|
const ShaderInput *ssbo = interface->ssbo_get(name);
|
|
|
|
|
return ssbo ? ssbo->location : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_uniform_block(blender::gpu::Shader *shader, const char *name)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
const ShaderInput *ubo = interface->ubo_get(name);
|
2017-10-06 14:57:21 +02:00
|
|
|
return ubo ? ubo->location : -1;
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_ubo_binding(blender::gpu::Shader *shader, const char *name)
|
2020-06-02 18:14:28 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
const ShaderInput *ubo = interface->ubo_get(name);
|
2020-06-02 18:14:28 +02:00
|
|
|
return ubo ? ubo->binding : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_sampler_binding(blender::gpu::Shader *shader, const char *name)
|
2020-06-02 18:14:28 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
const ShaderInput *tex = interface->uniform_get(name);
|
2020-06-02 18:14:28 +02:00
|
|
|
return tex ? tex->binding : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
uint GPU_shader_get_attribute_len(const blender::gpu::Shader *shader)
|
2022-09-01 08:21:10 -03:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2025-07-17 15:54:12 +02:00
|
|
|
return interface->valid_bindings_get(interface->inputs_, interface->attr_len_);
|
2022-09-01 08:21:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
uint GPU_shader_get_ssbo_input_len(const blender::gpu::Shader *shader)
|
2024-12-11 12:30:16 -03:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2024-12-11 12:30:16 -03:00
|
|
|
return interface->ssbo_len_;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
int GPU_shader_get_attribute(const blender::gpu::Shader *shader, const char *name)
|
2020-07-28 20:04:15 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2020-08-20 13:05:22 +02:00
|
|
|
const ShaderInput *attr = interface->attr_get(name);
|
2020-07-28 20:04:15 +02:00
|
|
|
return attr ? attr->location : -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
bool GPU_shader_get_attribute_info(const blender::gpu::Shader *shader,
|
2022-09-01 08:21:10 -03:00
|
|
|
int attr_location,
|
|
|
|
|
char r_name[256],
|
|
|
|
|
int *r_type)
|
|
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2022-09-01 08:21:10 -03:00
|
|
|
|
|
|
|
|
const ShaderInput *attr = interface->attr_get(attr_location);
|
|
|
|
|
if (!attr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(r_name, interface->input_name_get(attr), 256);
|
|
|
|
|
*r_type = attr->location != -1 ? interface->attr_types_[attr->location] : -1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
bool GPU_shader_get_ssbo_input_info(const blender::gpu::Shader *shader,
|
|
|
|
|
int ssbo_location,
|
|
|
|
|
char r_name[256])
|
2024-12-11 12:30:16 -03:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
const ShaderInterface *interface = shader->interface;
|
2024-12-11 12:30:16 -03:00
|
|
|
|
|
|
|
|
const ShaderInput *ssbo_input = interface->ssbo_get(ssbo_location);
|
|
|
|
|
if (!ssbo_input) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(r_name, interface->input_name_get(ssbo_input), 256);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Uniforms setters
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-02-12 23:39:48 +01:00
|
|
|
void GPU_shader_uniform_float_ex(
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *shader, int loc, int len, int array_size, const float *value)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
shader->uniform_float(loc, len, array_size, value);
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-12 23:39:48 +01:00
|
|
|
void GPU_shader_uniform_int_ex(
|
2025-08-11 09:34:28 +02:00
|
|
|
blender::gpu::Shader *shader, int loc, int len, int array_size, const int *value)
|
2020-08-14 15:20:35 +02:00
|
|
|
{
|
2025-08-11 09:34:28 +02:00
|
|
|
shader->uniform_int(loc, len, array_size, value);
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_int_ex(sh, loc, 1, 1, &value);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_1b(blender::gpu::Shader *sh, const char *name, bool value)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
|
|
|
|
GPU_shader_uniform_1i(sh, name, value ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_2f(blender::gpu::Shader *sh, const char *name, float x, float y)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
|
|
|
|
const float data[2] = {x, y};
|
|
|
|
|
GPU_shader_uniform_2fv(sh, name, data);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_3f(blender::gpu::Shader *sh, const char *name, float x, float y, float z)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
|
|
|
|
const float data[3] = {x, y, z};
|
|
|
|
|
GPU_shader_uniform_3fv(sh, name, data);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_4f(
|
|
|
|
|
blender::gpu::Shader *sh, const char *name, float x, float y, float z, float w)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
|
|
|
|
const float data[4] = {x, y, z, w};
|
|
|
|
|
GPU_shader_uniform_4fv(sh, name, data);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 1, 1, &value);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_2fv(blender::gpu::Shader *sh, const char *name, const float data[2])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 2, 1, data);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_3fv(blender::gpu::Shader *sh, const char *name, const float data[3])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 3, 1, data);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_4fv(blender::gpu::Shader *sh, const char *name, const float data[4])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 4, 1, data);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_2iv(blender::gpu::Shader *sh, const char *name, const int data[2])
|
2022-07-29 08:37:57 +02:00
|
|
|
{
|
|
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_int_ex(sh, loc, 2, 1, data);
|
2022-07-29 08:37:57 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_3iv(blender::gpu::Shader *sh, const char *name, const int data[3])
|
2024-11-27 17:37:04 +01:00
|
|
|
{
|
|
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
|
|
|
|
GPU_shader_uniform_int_ex(sh, loc, 3, 1, data);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_mat4(blender::gpu::Shader *sh, const char *name, const float data[4][4])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 16, 1, (const float *)data);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_mat3_as_mat4(blender::gpu::Shader *sh,
|
|
|
|
|
const char *name,
|
|
|
|
|
const float data[3][3])
|
2022-07-29 08:37:57 +02:00
|
|
|
{
|
|
|
|
|
float matrix[4][4];
|
|
|
|
|
copy_m4_m3(matrix, data);
|
|
|
|
|
GPU_shader_uniform_mat4(sh, name, matrix);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_1f_array(blender::gpu::Shader *sh,
|
|
|
|
|
const char *name,
|
|
|
|
|
int len,
|
|
|
|
|
const float *val)
|
2023-12-13 12:52:49 +02:00
|
|
|
{
|
|
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
|
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 1, len, val);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_2fv_array(blender::gpu::Shader *sh,
|
|
|
|
|
const char *name,
|
|
|
|
|
int len,
|
|
|
|
|
const float (*val)[2])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 2, len, (const float *)val);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void GPU_shader_uniform_4fv_array(blender::gpu::Shader *sh,
|
|
|
|
|
const char *name,
|
|
|
|
|
int len,
|
|
|
|
|
const float (*val)[4])
|
2020-08-11 15:59:02 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
const int loc = GPU_shader_get_uniform(sh, name);
|
2023-02-12 23:39:48 +01:00
|
|
|
GPU_shader_uniform_float_ex(sh, loc, 4, len, (const float *)val);
|
2020-08-11 15:59:02 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/** \} */
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
namespace blender::gpu {
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
2020-07-30 08:31:25 +10:00
|
|
|
/** \name sRGB Rendering Workaround
|
2020-07-28 20:04:15 +02:00
|
|
|
*
|
2020-07-30 08:31:25 +10:00
|
|
|
* The viewport overlay frame-buffer is sRGB and will expect shaders to output display referred
|
|
|
|
|
* Linear colors. But other frame-buffers (i.e: the area frame-buffers) are not sRGB and require
|
|
|
|
|
* the shader output color to be in sRGB space
|
|
|
|
|
* (assumed display encoded color-space as the time of writing).
|
2020-07-28 20:04:15 +02:00
|
|
|
* For this reason we have a uniform to switch the transform on and off depending on the current
|
2020-07-30 08:31:25 +10:00
|
|
|
* frame-buffer color-space.
|
2020-07-28 20:04:15 +02:00
|
|
|
* \{ */
|
|
|
|
|
|
2025-08-11 09:34:28 +02:00
|
|
|
void Shader::set_srgb_uniform(Context *ctx, blender::gpu::Shader *shader)
|
2020-04-14 20:44:45 +02:00
|
|
|
{
|
2020-08-20 12:26:29 +02:00
|
|
|
int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM);
|
2020-06-04 14:15:25 +02:00
|
|
|
if (loc != -1) {
|
2025-05-07 16:42:01 +02:00
|
|
|
GPU_shader_uniform_int_ex(shader, loc, 1, 1, &ctx->shader_builtin_srgb_transform);
|
2020-04-14 20:44:45 +02:00
|
|
|
}
|
2025-05-07 16:42:01 +02:00
|
|
|
ctx->shader_builtin_srgb_is_dirty = false;
|
2020-04-14 20:44:45 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-16 19:12:16 +02:00
|
|
|
void Shader::set_scene_linear_to_xyz_uniform(blender::gpu::Shader *shader)
|
|
|
|
|
{
|
|
|
|
|
int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SCENE_LINEAR_XFORM);
|
|
|
|
|
if (loc != -1) {
|
|
|
|
|
GPU_shader_uniform_float_ex(
|
|
|
|
|
shader, loc, 9, 1, blender::colorspace::scene_linear_to_rec709.ptr()[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-12 17:40:13 +01:00
|
|
|
void Shader::set_framebuffer_srgb_target(int use_srgb_to_linear)
|
2020-04-14 20:44:45 +02:00
|
|
|
{
|
2025-05-07 16:42:01 +02:00
|
|
|
Context *ctx = Context::get();
|
|
|
|
|
if (ctx->shader_builtin_srgb_transform != use_srgb_to_linear) {
|
|
|
|
|
ctx->shader_builtin_srgb_transform = use_srgb_to_linear;
|
|
|
|
|
ctx->shader_builtin_srgb_is_dirty = true;
|
2021-05-02 00:09:43 +10:00
|
|
|
}
|
2020-04-14 20:44:45 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 20:04:15 +02:00
|
|
|
/** \} */
|
2023-04-19 08:40:23 +10:00
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name ShaderCompiler
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_batch_compilation)
|
|
|
|
|
{
|
2025-06-06 14:39:51 +02:00
|
|
|
using Clock = std::chrono::steady_clock;
|
|
|
|
|
using TimePoint = Clock::time_point;
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
using namespace blender::gpu::shader;
|
|
|
|
|
const_cast<ShaderCreateInfo &>(info).finalize();
|
2025-08-27 20:17:04 +02:00
|
|
|
BLI_assert(info.do_static_compilation_ || info.is_generated_);
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2025-06-06 14:39:51 +02:00
|
|
|
TimePoint start_time;
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
if (Context::get()) {
|
|
|
|
|
/* Context can be null in Vulkan compilation threads. */
|
|
|
|
|
GPU_debug_group_begin(GPU_DEBUG_SHADER_COMPILATION_GROUP);
|
2025-05-20 14:44:23 +02:00
|
|
|
GPU_debug_group_begin(info.name_.c_str());
|
2025-05-08 18:16:47 +02:00
|
|
|
}
|
2025-06-16 11:02:18 +02:00
|
|
|
else if (G.profile_gpu) {
|
2025-06-06 14:39:51 +02:00
|
|
|
start_time = Clock::now();
|
|
|
|
|
}
|
2024-06-05 18:45:57 +02:00
|
|
|
|
|
|
|
|
const std::string error = info.check_error();
|
|
|
|
|
if (!error.empty()) {
|
2024-11-01 20:00:31 +01:00
|
|
|
std::cerr << error << "\n";
|
2024-06-05 18:45:57 +02:00
|
|
|
BLI_assert(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader *shader = GPUBackend::get()->shader_alloc(info.name_.c_str());
|
2025-05-19 17:42:55 +02:00
|
|
|
/* Needs to be called before init as GL uses the default specialization constants state to insert
|
|
|
|
|
* default shader inside a map. */
|
2024-06-05 18:45:57 +02:00
|
|
|
shader->specialization_constants_init(info);
|
2025-05-19 17:42:55 +02:00
|
|
|
shader->init(info, is_batch_compilation);
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2024-12-10 17:13:06 +01:00
|
|
|
shader->fragment_output_bits = 0;
|
|
|
|
|
for (const shader::ShaderCreateInfo::FragOut &frag_out : info.fragment_outputs_) {
|
|
|
|
|
shader->fragment_output_bits |= 1u << frag_out.index;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
std::string defines = shader->defines_declare(info);
|
|
|
|
|
std::string resources = shader->resources_declare(info);
|
|
|
|
|
|
2025-06-10 12:37:20 +02:00
|
|
|
info.resource_guard_defines(defines);
|
|
|
|
|
|
2025-04-04 18:21:38 +02:00
|
|
|
defines += "#define USE_GPU_SHADER_CREATE_INFO\n";
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
Vector<StringRefNull> typedefs;
|
2024-06-05 18:45:57 +02:00
|
|
|
if (!info.typedef_sources_.is_empty() || !info.typedef_source_generated.empty()) {
|
|
|
|
|
typedefs.append(gpu_shader_dependency_get_source("GPU_shader_shared_utils.hh").c_str());
|
|
|
|
|
}
|
|
|
|
|
if (!info.typedef_source_generated.empty()) {
|
2024-11-01 20:00:31 +01:00
|
|
|
typedefs.append(info.typedef_source_generated);
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
for (auto filename : info.typedef_sources_) {
|
2025-09-12 14:09:35 +02:00
|
|
|
typedefs.extend_non_duplicates(
|
2025-09-29 16:31:13 +02:00
|
|
|
gpu_shader_dependency_get_resolved_source(filename, info.generated_sources, info.name_));
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!info.vertex_source_.is_empty()) {
|
2025-09-29 16:31:13 +02:00
|
|
|
Vector<StringRefNull> code = gpu_shader_dependency_get_resolved_source(
|
|
|
|
|
info.vertex_source_, info.generated_sources, info.name_);
|
2024-06-05 18:45:57 +02:00
|
|
|
std::string interface = shader->vertex_interface_declare(info);
|
|
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
Vector<StringRefNull> sources;
|
2024-06-05 18:45:57 +02:00
|
|
|
standard_defines(sources);
|
|
|
|
|
sources.append("#define GPU_VERTEX_SHADER\n");
|
|
|
|
|
if (!info.geometry_source_.is_empty()) {
|
|
|
|
|
sources.append("#define USE_GEOMETRY_SHADER\n");
|
|
|
|
|
}
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(defines);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(typedefs);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(resources);
|
|
|
|
|
sources.append(interface);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(code);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(info.vertex_source_generated);
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2025-06-10 12:37:20 +02:00
|
|
|
if (info.vertex_entry_fn_ != "main") {
|
|
|
|
|
sources.append("void main() { ");
|
|
|
|
|
sources.append(info.vertex_entry_fn_);
|
|
|
|
|
sources.append("(); }\n");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
shader->vertex_shader_from_glsl(sources);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!info.fragment_source_.is_empty()) {
|
2025-09-29 16:31:13 +02:00
|
|
|
Vector<StringRefNull> code = gpu_shader_dependency_get_resolved_source(
|
|
|
|
|
info.fragment_source_, info.generated_sources, info.name_);
|
2024-06-05 18:45:57 +02:00
|
|
|
std::string interface = shader->fragment_interface_declare(info);
|
|
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
Vector<StringRefNull> sources;
|
2024-06-05 18:45:57 +02:00
|
|
|
standard_defines(sources);
|
|
|
|
|
sources.append("#define GPU_FRAGMENT_SHADER\n");
|
|
|
|
|
if (!info.geometry_source_.is_empty()) {
|
|
|
|
|
sources.append("#define USE_GEOMETRY_SHADER\n");
|
|
|
|
|
}
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(defines);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(typedefs);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(resources);
|
|
|
|
|
sources.append(interface);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(code);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(info.fragment_source_generated);
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2025-06-10 12:37:20 +02:00
|
|
|
if (info.fragment_entry_fn_ != "main") {
|
|
|
|
|
sources.append("void main() { ");
|
|
|
|
|
sources.append(info.fragment_entry_fn_);
|
|
|
|
|
sources.append("(); }\n");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
shader->fragment_shader_from_glsl(sources);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!info.geometry_source_.is_empty()) {
|
2025-09-29 16:31:13 +02:00
|
|
|
Vector<StringRefNull> code = gpu_shader_dependency_get_resolved_source(
|
|
|
|
|
info.geometry_source_, info.generated_sources, info.name_);
|
2024-06-05 18:45:57 +02:00
|
|
|
std::string layout = shader->geometry_layout_declare(info);
|
|
|
|
|
std::string interface = shader->geometry_interface_declare(info);
|
|
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
Vector<StringRefNull> sources;
|
2024-06-05 18:45:57 +02:00
|
|
|
standard_defines(sources);
|
|
|
|
|
sources.append("#define GPU_GEOMETRY_SHADER\n");
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(defines);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(typedefs);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(resources);
|
|
|
|
|
sources.append(layout);
|
|
|
|
|
sources.append(interface);
|
|
|
|
|
sources.append(info.geometry_source_generated);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(code);
|
|
|
|
|
|
2025-06-10 12:37:20 +02:00
|
|
|
if (info.geometry_entry_fn_ != "main") {
|
|
|
|
|
sources.append("void main() { ");
|
|
|
|
|
sources.append(info.geometry_entry_fn_);
|
|
|
|
|
sources.append("(); }\n");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
shader->geometry_shader_from_glsl(sources);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!info.compute_source_.is_empty()) {
|
2025-09-29 16:31:13 +02:00
|
|
|
Vector<StringRefNull> code = gpu_shader_dependency_get_resolved_source(
|
|
|
|
|
info.compute_source_, info.generated_sources, info.name_);
|
2024-06-05 18:45:57 +02:00
|
|
|
std::string layout = shader->compute_layout_declare(info);
|
|
|
|
|
|
2024-11-01 20:00:31 +01:00
|
|
|
Vector<StringRefNull> sources;
|
2024-06-05 18:45:57 +02:00
|
|
|
standard_defines(sources);
|
|
|
|
|
sources.append("#define GPU_COMPUTE_SHADER\n");
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(defines);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(typedefs);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(resources);
|
|
|
|
|
sources.append(layout);
|
2024-06-05 18:45:57 +02:00
|
|
|
sources.extend(code);
|
2024-11-01 20:00:31 +01:00
|
|
|
sources.append(info.compute_source_generated);
|
2024-06-05 18:45:57 +02:00
|
|
|
|
2025-06-10 12:37:20 +02:00
|
|
|
if (info.compute_entry_fn_ != "main") {
|
|
|
|
|
sources.append("void main() { ");
|
|
|
|
|
sources.append(info.compute_entry_fn_);
|
|
|
|
|
sources.append("(); }\n");
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
shader->compute_shader_from_glsl(sources);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!shader->finalize(&info)) {
|
|
|
|
|
delete shader;
|
2025-05-08 18:16:47 +02:00
|
|
|
shader = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Context::get()) {
|
|
|
|
|
/* Context can be null in Vulkan compilation threads. */
|
2024-06-05 18:45:57 +02:00
|
|
|
GPU_debug_group_end();
|
2025-05-20 14:44:23 +02:00
|
|
|
GPU_debug_group_end();
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
2025-06-16 11:02:18 +02:00
|
|
|
else if (G.profile_gpu) {
|
2025-06-06 14:39:51 +02:00
|
|
|
TimePoint end_time = Clock::now();
|
|
|
|
|
/* Note: Used by the vulkan backend. Use the same time_since_epoch as process_frame_timings. */
|
|
|
|
|
ProfileReport::get().add_group_cpu(GPU_DEBUG_SHADER_COMPILATION_GROUP,
|
|
|
|
|
start_time.time_since_epoch().count(),
|
|
|
|
|
end_time.time_since_epoch().count());
|
|
|
|
|
ProfileReport::get().add_group_cpu(info.name_.c_str(),
|
|
|
|
|
start_time.time_since_epoch().count(),
|
|
|
|
|
end_time.time_since_epoch().count());
|
|
|
|
|
}
|
2024-06-05 18:45:57 +02:00
|
|
|
|
|
|
|
|
return shader;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
ShaderCompiler::ShaderCompiler(uint32_t threads_count,
|
|
|
|
|
GPUWorker::ContextType context_type,
|
|
|
|
|
bool support_specializations)
|
2025-04-07 15:26:25 +02:00
|
|
|
{
|
2025-05-08 18:16:47 +02:00
|
|
|
support_specializations_ = support_specializations;
|
|
|
|
|
|
2025-04-07 15:26:25 +02:00
|
|
|
if (!GPU_use_main_context_workaround()) {
|
2025-05-08 18:16:47 +02:00
|
|
|
compilation_worker_ = std::make_unique<GPUWorker>(
|
2025-06-10 17:24:18 +02:00
|
|
|
threads_count,
|
|
|
|
|
context_type,
|
|
|
|
|
mutex_,
|
|
|
|
|
[this]() -> void * { return this->pop_work(); },
|
|
|
|
|
[this](void *work) { this->do_work(work); });
|
2025-04-07 15:26:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
ShaderCompiler::~ShaderCompiler()
|
2024-06-05 18:45:57 +02:00
|
|
|
{
|
2025-05-08 18:16:47 +02:00
|
|
|
compilation_worker_.reset();
|
2025-04-07 15:26:25 +02:00
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
/* Ensure all the requested batches have been retrieved. */
|
2025-04-07 15:26:25 +02:00
|
|
|
BLI_assert(batches_.is_empty());
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
Shader *ShaderCompiler::compile_shader(const shader::ShaderCreateInfo &info)
|
|
|
|
|
{
|
|
|
|
|
return compile(info, false);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-29 19:43:02 +02:00
|
|
|
BatchHandle ShaderCompiler::batch_compile(Span<const shader::ShaderCreateInfo *> &infos,
|
|
|
|
|
CompilationPriority priority)
|
2024-06-05 18:45:57 +02:00
|
|
|
{
|
2025-04-07 15:26:25 +02:00
|
|
|
std::unique_lock lock(mutex_);
|
2025-02-27 19:20:33 +01:00
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
Batch *batch = MEM_new<Batch>(__func__);
|
2025-04-07 15:26:25 +02:00
|
|
|
batch->infos = infos;
|
|
|
|
|
batch->shaders.reserve(infos.size());
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
BatchHandle handle = next_batch_handle_++;
|
|
|
|
|
batches_.add(handle, batch);
|
|
|
|
|
|
|
|
|
|
if (compilation_worker_) {
|
|
|
|
|
batch->shaders.resize(infos.size(), nullptr);
|
|
|
|
|
batch->pending_compilations = infos.size();
|
|
|
|
|
for (int i : infos.index_range()) {
|
2025-05-29 19:43:02 +02:00
|
|
|
compilation_queue_.push({batch, i}, priority);
|
2025-05-08 18:16:47 +02:00
|
|
|
compilation_worker_->wake_up();
|
|
|
|
|
}
|
2024-06-05 18:45:57 +02:00
|
|
|
}
|
2025-04-07 15:26:25 +02:00
|
|
|
else {
|
|
|
|
|
for (const shader::ShaderCreateInfo *info : infos) {
|
|
|
|
|
batch->shaders.append(compile(*info, false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
void ShaderCompiler::batch_cancel(BatchHandle &handle)
|
2024-06-05 18:45:57 +02:00
|
|
|
{
|
2025-05-12 19:54:03 +02:00
|
|
|
std::unique_lock lock(mutex_);
|
2025-02-27 19:20:33 +01:00
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
Batch *batch = batches_.pop(handle);
|
2025-05-29 19:43:02 +02:00
|
|
|
compilation_queue_.remove_batch(batch);
|
2025-05-12 19:54:03 +02:00
|
|
|
|
|
|
|
|
if (batch->is_specialization_batch()) {
|
|
|
|
|
/* For specialization batches, we block until ready, since base shader compilation may be
|
|
|
|
|
* cancelled afterwards, leaving the specialization with a deleted base shader. */
|
|
|
|
|
compilation_finished_notification_.wait(lock, [&]() { return batch->is_ready(); });
|
|
|
|
|
}
|
2025-05-08 18:16:47 +02:00
|
|
|
|
|
|
|
|
if (batch->is_ready()) {
|
|
|
|
|
batch->free_shaders();
|
|
|
|
|
MEM_delete(batch);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* If it's currently compiling, the compilation thread makes the cleanup. */
|
|
|
|
|
batch->is_cancelled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ShaderCompiler::batch_is_ready(BatchHandle handle)
|
|
|
|
|
{
|
2025-02-27 19:20:33 +01:00
|
|
|
std::lock_guard lock(mutex_);
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
return batches_.lookup(handle)->is_ready();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector<Shader *> ShaderCompiler::batch_finalize(BatchHandle &handle)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock lock(mutex_);
|
2025-05-22 17:53:22 +02:00
|
|
|
/* TODO: Move to be first on the queue. */
|
2025-05-08 18:16:47 +02:00
|
|
|
compilation_finished_notification_.wait(lock,
|
|
|
|
|
[&]() { return batches_.lookup(handle)->is_ready(); });
|
|
|
|
|
|
|
|
|
|
Batch *batch = batches_.pop(handle);
|
|
|
|
|
Vector<Shader *> shaders = std::move(batch->shaders);
|
|
|
|
|
MEM_delete(batch);
|
2024-06-05 18:45:57 +02:00
|
|
|
handle = 0;
|
2025-05-08 18:16:47 +02:00
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
return shaders;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 18:16:47 +02:00
|
|
|
SpecializationBatchHandle ShaderCompiler::precompile_specializations(
|
2025-05-29 19:43:02 +02:00
|
|
|
Span<ShaderSpecialization> specializations, CompilationPriority priority)
|
2025-05-08 18:16:47 +02:00
|
|
|
{
|
|
|
|
|
if (!compilation_worker_ || !support_specializations_) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::lock_guard lock(mutex_);
|
|
|
|
|
|
|
|
|
|
Batch *batch = MEM_new<Batch>(__func__);
|
|
|
|
|
batch->specializations = specializations;
|
|
|
|
|
|
|
|
|
|
BatchHandle handle = next_batch_handle_++;
|
|
|
|
|
batches_.add(handle, batch);
|
|
|
|
|
|
|
|
|
|
batch->pending_compilations = specializations.size();
|
|
|
|
|
for (int i : specializations.index_range()) {
|
2025-05-29 19:43:02 +02:00
|
|
|
compilation_queue_.push({batch, i}, priority);
|
2025-05-08 18:16:47 +02:00
|
|
|
compilation_worker_->wake_up();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ShaderCompiler::specialization_batch_is_ready(SpecializationBatchHandle &handle)
|
|
|
|
|
{
|
|
|
|
|
if (handle != 0 && batch_is_ready(handle)) {
|
|
|
|
|
std::lock_guard lock(mutex_);
|
|
|
|
|
|
|
|
|
|
Batch *batch = batches_.pop(handle);
|
|
|
|
|
MEM_delete(batch);
|
|
|
|
|
handle = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return handle == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
void *ShaderCompiler::pop_work()
|
2025-04-07 15:26:25 +02:00
|
|
|
{
|
2025-06-10 17:24:18 +02:00
|
|
|
/* NOTE: Already under mutex lock when GPUWorker calls this function. */
|
2025-04-07 15:26:25 +02:00
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
if (compilation_queue_.is_empty()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2025-04-07 15:26:25 +02:00
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
ParallelWork work = compilation_queue_.pop();
|
|
|
|
|
return MEM_new<ParallelWork>(__func__, work);
|
|
|
|
|
}
|
2025-04-07 15:26:25 +02:00
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
void ShaderCompiler::do_work(void *work_payload)
|
|
|
|
|
{
|
|
|
|
|
ParallelWork *work = reinterpret_cast<ParallelWork *>(work_payload);
|
|
|
|
|
Batch *batch = work->batch;
|
|
|
|
|
int shader_index = work->shader_index;
|
|
|
|
|
MEM_delete(work);
|
2025-05-08 18:16:47 +02:00
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
/* Compile */
|
|
|
|
|
if (!batch->is_specialization_batch()) {
|
|
|
|
|
batch->shaders[shader_index] = compile_shader(*batch->infos[shader_index]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
specialize_shader(batch->specializations[shader_index]);
|
|
|
|
|
}
|
2025-05-08 18:16:47 +02:00
|
|
|
|
2025-06-10 17:24:18 +02:00
|
|
|
{
|
|
|
|
|
std::lock_guard lock(mutex_);
|
|
|
|
|
batch->pending_compilations--;
|
|
|
|
|
if (batch->is_ready() && batch->is_cancelled) {
|
|
|
|
|
batch->free_shaders();
|
|
|
|
|
MEM_delete(batch);
|
|
|
|
|
}
|
2025-04-07 15:26:25 +02:00
|
|
|
}
|
2025-06-10 17:24:18 +02:00
|
|
|
|
|
|
|
|
compilation_finished_notification_.notify_all();
|
2025-04-07 15:26:25 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-31 20:06:27 +02:00
|
|
|
bool ShaderCompiler::is_compiling_impl()
|
2025-05-22 17:53:22 +02:00
|
|
|
{
|
2025-09-09 09:07:23 +02:00
|
|
|
/* The mutex should be locked before calling this function. */
|
2025-07-31 20:06:27 +02:00
|
|
|
BLI_assert(!mutex_.try_lock());
|
2025-05-22 17:53:22 +02:00
|
|
|
|
2025-07-31 20:06:27 +02:00
|
|
|
if (!compilation_queue_.is_empty()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (Batch *batch : batches_.values()) {
|
|
|
|
|
if (!batch->is_ready()) {
|
|
|
|
|
return true;
|
2025-05-22 17:53:22 +02:00
|
|
|
}
|
2025-07-31 20:06:27 +02:00
|
|
|
}
|
2025-05-22 17:53:22 +02:00
|
|
|
|
2025-07-31 20:06:27 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ShaderCompiler::is_compiling()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock lock(mutex_);
|
|
|
|
|
return is_compiling_impl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShaderCompiler::wait_for_all()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock lock(mutex_);
|
|
|
|
|
compilation_finished_notification_.wait(lock, [&]() { return !is_compiling_impl(); });
|
2025-05-22 17:53:22 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-05 18:45:57 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-04-19 08:40:23 +10:00
|
|
|
} // namespace blender::gpu
|