Blender V5.0
gl_shader.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "MEM_guardedalloc.h"
12
13#include <epoxy/gl.h>
14
15#include "BLI_map.hh"
16#include "BLI_subprocess.hh"
17#include "BLI_utility_mixins.hh"
18
19#include "GPU_capabilities.hh"
21#include "gpu_shader_private.hh"
22
23#include <functional>
24#include <mutex>
25
26namespace blender::gpu {
27
38struct GLSource {
39 std::string source;
40 std::optional<StringRefNull> source_ref;
41
42 GLSource() = default;
43 GLSource(StringRefNull other_source);
44};
45class GLSources : public Vector<GLSource> {
46 public:
49 std::string to_string() const;
50};
51
57 std::string comp;
58 std::string vert;
59 std::string geom;
60 std::string frag;
61
62 /* Returns the size (in bytes) required to store the source of all the used stages. */
63 size_t size();
64};
65
69class GLShader : public Shader {
73 friend class GLShaderCompiler;
74
75 private:
76 struct GLProgram {
78 GLuint program_id = 0;
80 GLuint vert_shader = 0;
81 GLuint geom_shader = 0;
82 GLuint frag_shader = 0;
83 GLuint compute_shader = 0;
84
85 std::mutex compilation_mutex;
86
87 GLProgram() {}
88 ~GLProgram();
89
90 void program_link(StringRefNull shader_name);
91 };
92
93 using GLProgramCacheKey = Vector<shader::SpecializationConstant::Value>;
96
97 std::mutex program_cache_mutex_;
98
100 GLProgram *main_program_ = nullptr;
101
102 /* When true, the shader generates its GLSources but it's not compiled.
103 * (Used for batch compilation) */
104 bool async_compilation_ = false;
105
111 GLSources vertex_sources_;
112 GLSources geometry_sources_;
113 GLSources fragment_sources_;
114 GLSources compute_sources_;
115
116 Vector<const char *> specialization_constant_names_;
117
118 void update_program_and_sources(GLSources &stage_sources, MutableSpan<StringRefNull> sources);
119
124 GLShader::GLProgram &program_get(const shader::SpecializationConstants *constants_state);
125
127 bool compilation_failed_ = false;
128
129 std::string debug_source;
130
131 public:
132 GLShader(const char *name);
133 ~GLShader();
134
135 void init(const shader::ShaderCreateInfo &info, bool is_batch_compilation) override;
136
142 bool finalize(const shader::ShaderCreateInfo *info = nullptr) override;
143 bool post_finalize(const shader::ShaderCreateInfo *info = nullptr);
144 void warm_cache(int /*limit*/) override {};
145
146 std::string resources_declare(const shader::ShaderCreateInfo &info) const override;
147 std::string constants_declare(const shader::SpecializationConstants &constants_state) const;
148 std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override;
149 std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override;
150 std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override;
151 std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override;
152 std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override;
153
154 void bind(const shader::SpecializationConstants *constants_state) override;
155 void unbind() override;
156
157 void uniform_float(int location, int comp_len, int array_size, const float *data) override;
158 void uniform_int(int location, int comp_len, int array_size, const int *data) override;
159
160 bool is_compute() const
161 {
162 if (!vertex_sources_.is_empty()) {
163 return false;
164 }
165 if (!compute_sources_.is_empty()) {
166 return true;
167 }
168 return main_program_->compute_shader != 0;
169 }
170
172
173 private:
174 StringRefNull glsl_patch_get(GLenum gl_stage);
175
176 bool has_specialization_constants() const
177 {
178 return constants->types.is_empty() == false;
179 }
180
182 GLuint create_shader_stage(GLenum gl_stage,
184 GLSources &gl_sources,
185 const shader::SpecializationConstants &constants_state);
186
191 std::string workaround_geometry_shader_source_create(const shader::ShaderCreateInfo &info);
192
193 bool do_geometry_shader_injection(const shader::ShaderCreateInfo *info) const;
194
195 MEM_CXX_CLASS_ALLOC_FUNCS("GLShader");
196};
197
199 public:
201 : ShaderCompiler(GPU_max_parallel_compilations(), GPUWorker::ContextType::PerThread, true) {
202 };
203
204 virtual void specialize_shader(ShaderSpecialization &specialization) override;
205};
206
207#if BLI_SUBPROCESS_SUPPORT
208
209class GLCompilerWorker {
210 friend class GLSubprocessShaderCompiler;
211
212 private:
213 BlenderSubprocess subprocess_;
214 std::unique_ptr<SharedMemory> shared_mem_;
215 std::unique_ptr<SharedSemaphore> start_semaphore_;
216 std::unique_ptr<SharedSemaphore> end_semaphore_;
217 std::unique_ptr<SharedSemaphore> close_semaphore_;
218 enum State {
219 /* The worker has been acquired and the compilation has been requested. */
220 COMPILATION_REQUESTED,
221 /* The shader binary result is ready to be read. */
222 COMPILATION_READY,
223 /* The binary result has been loaded into a program and the worker can be released. */
224 COMPILATION_FINISHED,
225 /* The worker is not currently in use and can be acquired. */
226 AVAILABLE
227 };
228 std::atomic<State> state_ = AVAILABLE;
229 double compilation_start = 0;
230
231 GLCompilerWorker();
232 ~GLCompilerWorker();
233
234 void compile(const GLSourcesBaked &sources);
235 bool block_until_ready();
236 bool load_program_binary(GLint program);
237 void release();
238
239 /* Check if the process may have closed/crashed/hanged. */
240 bool is_lost();
241};
242
244 private:
245 Vector<GLCompilerWorker *> workers_;
246 std::mutex workers_mutex_;
247
248 GLCompilerWorker *get_compiler_worker();
249
250 GLShader::GLProgram *specialization_program_get(ShaderSpecialization &specialization);
251
252 public:
253 GLSubprocessShaderCompiler()
254 : ShaderCompiler(GPU_max_parallel_compilations(), GPUWorker::ContextType::PerThread, true) {
255 };
256 virtual ~GLSubprocessShaderCompiler() override;
257
258 virtual Shader *compile_shader(const shader::ShaderCreateInfo &info) override;
259 virtual void specialize_shader(ShaderSpecialization &specialization) override;
260};
261
262#else
263
265
266#endif
267
268class GLLogParser : public GPULogParser {
269 public:
270 const char *parse_line(const char *source_combined,
271 const char *log_line,
272 GPULogItem &log_item) override;
273
274 protected:
275 const char *skip_severity_prefix(const char *log_line, GPULogItem &log_item);
276 const char *skip_severity_keyword(const char *log_line, GPULogItem &log_item);
277
279};
280
281} // namespace blender::gpu
int GPU_max_parallel_compilations()
Read Guarded memory(de)allocation.
BMesh const char void * data
return true
void init()
NonCopyable(const NonCopyable &other)=delete
const char * parse_line(const char *source_combined, const char *log_line, GPULogItem &log_item) override
const char * skip_severity_prefix(const char *log_line, GPULogItem &log_item)
const char * skip_severity_keyword(const char *log_line, GPULogItem &log_item)
MEM_CXX_CLASS_ALLOC_FUNCS("GLLogParser")
virtual void specialize_shader(ShaderSpecialization &specialization) override
bool is_compute() const
Definition gl_shader.hh:160
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:910
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:719
void fragment_shader_from_glsl(MutableSpan< StringRefNull > sources) override
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:940
void geometry_shader_from_glsl(MutableSpan< StringRefNull > sources) override
void compute_shader_from_glsl(MutableSpan< StringRefNull > sources) override
void unbind() override
void uniform_float(int location, int comp_len, int array_size, const float *data) override
bool post_finalize(const shader::ShaderCreateInfo *info=nullptr)
GLShader(const char *name)
Definition gl_shader.cc:60
GLSourcesBaked get_sources()
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:962
std::string constants_declare(const shader::SpecializationConstants &constants_state) const
Definition gl_shader.cc:668
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:593
friend class GLShaderCompiler
Definition gl_shader.hh:73
friend class GLSubprocessShaderCompiler
Definition gl_shader.hh:72
void uniform_int(int location, int comp_len, int array_size, const int *data) override
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:786
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
void warm_cache(int) override
Definition gl_shader.hh:144
void bind(const shader::SpecializationConstants *constants_state) override
void vertex_shader_from_glsl(MutableSpan< StringRefNull > sources) override
GLSources & operator=(Span< StringRefNull > other)
std::string to_string() const
Vector< StringRefNull > sources_get() const
virtual void specialize_shader(ShaderSpecialization &)
ShaderCompiler(uint32_t threads_count=1, GPUWorker::ContextType context_type=GPUWorker::ContextType::PerThread, bool support_specializations=false)
virtual Shader * compile_shader(const shader::ShaderCreateInfo &info)
std::unique_ptr< const shader::SpecializationConstants > constants
Shader(const char *name)
Definition gpu_shader.cc:57
const char * name
std::optional< StringRefNull > source_ref
Definition gl_shader.hh:40
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...