Blender V4.3
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
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
20#include "gpu_shader_private.hh"
21
22#include <functional>
23
24namespace blender::gpu {
25
36struct GLSource {
37 std::string source;
38 const char *source_ref;
39
40 GLSource() = default;
41 GLSource(const char *other_source);
42};
43class GLSources : public Vector<GLSource> {
44 public:
47 std::string to_string() const;
48};
49
55 std::string comp;
56 std::string vert;
57 std::string geom;
58 std::string frag;
59
60 /* Returns the size (in bytes) required to store the source of all the used stages. */
61 size_t size();
62};
63
67class GLShader : public Shader {
70 friend class GLShaderCompiler;
71
72 private:
73 struct GLProgram {
75 GLuint program_id = 0;
77 GLuint vert_shader = 0;
78 GLuint geom_shader = 0;
79 GLuint frag_shader = 0;
80 GLuint compute_shader = 0;
81
82 GLProgram() {}
83 GLProgram(GLProgram &&other)
84 {
85 program_id = other.program_id;
86 vert_shader = other.vert_shader;
87 geom_shader = other.geom_shader;
88 frag_shader = other.frag_shader;
89 compute_shader = other.compute_shader;
90 other.program_id = 0;
91 other.vert_shader = 0;
92 other.geom_shader = 0;
93 other.frag_shader = 0;
94 other.compute_shader = 0;
95 }
96 ~GLProgram();
97 };
98
99 using GLProgramCacheKey = Vector<shader::SpecializationConstant::Value>;
100 Map<GLProgramCacheKey, GLProgram> program_cache_;
101
106 GLProgram *program_active_ = nullptr;
107
108 /* When true, the shader generates its GLSources but it's not compiled.
109 * (Used for batch compilation) */
110 bool async_compilation_ = false;
111
117 GLSources vertex_sources_;
118 GLSources geometry_sources_;
119 GLSources fragment_sources_;
120 GLSources compute_sources_;
121
122 Vector<const char *> specialization_constant_names_;
123
132 void init_program();
133
134 void update_program_and_sources(GLSources &stage_sources, MutableSpan<const char *> sources);
135
139 void program_link();
140 bool check_link_status();
141
146 GLuint program_get();
147
149 bool compilation_failed_ = false;
150
151 eGPUShaderTFBType transform_feedback_type_ = GPU_SHADER_TFB_NONE;
152
153 std::string debug_source;
154
155 public:
156 GLShader(const char *name);
157 ~GLShader();
158
159 void init(const shader::ShaderCreateInfo &info, bool is_batch_compilation) override;
160
162 void vertex_shader_from_glsl(MutableSpan<const char *> sources) override;
163 void geometry_shader_from_glsl(MutableSpan<const char *> sources) override;
164 void fragment_shader_from_glsl(MutableSpan<const char *> sources) override;
165 void compute_shader_from_glsl(MutableSpan<const char *> sources) override;
166 bool finalize(const shader::ShaderCreateInfo *info = nullptr) override;
167 bool post_finalize(const shader::ShaderCreateInfo *info = nullptr);
168 void warm_cache(int /*limit*/) override{};
169
170 std::string resources_declare(const shader::ShaderCreateInfo &info) const override;
171 std::string constants_declare() const;
172 std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override;
173 std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override;
174 std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override;
175 std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override;
176 std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override;
177
180 eGPUShaderTFBType geom_type) override;
181 bool transform_feedback_enable(VertBuf *buf) override;
182 void transform_feedback_disable() override;
183
184 void bind() override;
185 void unbind() override;
186
187 void uniform_float(int location, int comp_len, int array_size, const float *data) override;
188 void uniform_int(int location, int comp_len, int array_size, const int *data) override;
189
190 /* Unused: SSBO vertex fetch draw parameters. */
191 bool get_uses_ssbo_vertex_fetch() const override
192 {
193 return false;
194 }
196 {
197 return 0;
198 }
199
201 int program_handle_get() const override;
202
203 bool is_compute() const
204 {
205 if (!vertex_sources_.is_empty()) {
206 return false;
207 }
208 if (!compute_sources_.is_empty()) {
209 return true;
210 }
211 return program_active_->compute_shader != 0;
212 }
213
215
216 private:
217 const char *glsl_patch_get(GLenum gl_stage);
218
220 GLuint create_shader_stage(GLenum gl_stage,
222 GLSources &gl_sources);
223
228 std::string workaround_geometry_shader_source_create(const shader::ShaderCreateInfo &info);
229
230 bool do_geometry_shader_injection(const shader::ShaderCreateInfo *info);
231
232 MEM_CXX_CLASS_ALLOC_FUNCS("GLShader");
233};
234
235#if BLI_SUBPROCESS_SUPPORT
236
237class GLCompilerWorker {
238 friend class GLShaderCompiler;
239
240 private:
241 BlenderSubprocess subprocess_;
242 std::unique_ptr<SharedMemory> shared_mem_;
243 std::unique_ptr<SharedSemaphore> start_semaphore_;
244 std::unique_ptr<SharedSemaphore> end_semaphore_;
245 std::unique_ptr<SharedSemaphore> close_semaphore_;
246 enum eState {
247 /* The worker has been acquired and the compilation has been requested. */
248 COMPILATION_REQUESTED,
249 /* The shader binary result is ready to be read. */
250 COMPILATION_READY,
251 /* The binary result has been loaded into a program and the worker can be released. */
252 COMPILATION_FINISHED,
253 /* The worker is not currently in use and can be acquired. */
254 AVAILABLE
255 };
256 eState state_ = AVAILABLE;
257 double compilation_start = 0;
258
259 GLCompilerWorker();
260 ~GLCompilerWorker();
261
262 void compile(const GLSourcesBaked &sources);
263 bool is_ready();
264 bool load_program_binary(GLint program);
265 void release();
266
267 /* Check if the process may have closed/crashed/hanged. */
268 bool is_lost();
269};
270
271class GLShaderCompiler : public ShaderCompiler {
272 private:
273 std::mutex mutex_;
274 Vector<GLCompilerWorker *> workers_;
275
276 struct CompilationWork {
277 const shader::ShaderCreateInfo *info = nullptr;
278 GLShader *shader = nullptr;
279 GLSourcesBaked sources;
280
281 GLCompilerWorker *worker = nullptr;
282 bool do_async_compilation = false;
283 bool is_ready = false;
284 };
285
286 struct Batch {
287 Vector<CompilationWork> items;
288 bool is_ready = false;
289 };
290
291 Map<BatchHandle, Batch> batches;
292
293 struct SpecializationRequest {
294 BatchHandle handle;
295 Vector<ShaderSpecialization> specializations;
296 };
297
298 Vector<SpecializationRequest> specialization_queue;
299
300 struct SpecializationWork {
301 GLShader *shader = nullptr;
302 Vector<shader::SpecializationConstant> constants;
303 GLSourcesBaked sources;
304
305 GLShader::GLProgram *program_get();
306
307 GLCompilerWorker *worker = nullptr;
308 bool do_async_compilation = false;
309 bool is_ready = false;
310 };
311
312 struct SpecializationBatch {
313 SpecializationBatchHandle handle = 0;
314 Vector<SpecializationWork> items;
315 bool is_ready = true;
316 };
317
318 SpecializationBatch current_specialization_batch;
319 void prepare_next_specialization_batch();
320
321 /* Shared across regular and specialization batches,
322 * to prevent the use of a wrong handle type. */
323 int64_t next_batch_handle = 1;
324
325 GLCompilerWorker *get_compiler_worker(const GLSourcesBaked &sources);
326 bool worker_is_lost(GLCompilerWorker *&worker);
327
328 public:
329 virtual ~GLShaderCompiler() override;
330
331 virtual BatchHandle batch_compile(Span<const shader::ShaderCreateInfo *> &infos) override;
332 virtual bool batch_is_ready(BatchHandle handle) override;
333 virtual Vector<Shader *> batch_finalize(BatchHandle &handle) override;
334
336 Span<ShaderSpecialization> specializations) override;
337
338 virtual bool specialization_batch_is_ready(SpecializationBatchHandle &handle) override;
339};
340
341#else
342
344
345#endif
346
347class GLLogParser : public GPULogParser {
348 public:
349 const char *parse_line(const char *source_combined,
350 const char *log_line,
351 GPULogItem &log_item) override;
352
353 protected:
354 const char *skip_severity_prefix(const char *log_line, GPULogItem &log_item);
355 const char *skip_severity_keyword(const char *log_line, GPULogItem &log_item);
356
358};
359
360} // namespace blender::gpu
int64_t BatchHandle
Definition GPU_shader.hh:68
eGPUShaderTFBType
@ GPU_SHADER_TFB_NONE
int64_t SpecializationBatchHandle
Read Guarded memory(de)allocation.
void init()
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")
bool is_compute() const
Definition gl_shader.hh:203
bool get_uses_ssbo_vertex_fetch() const override
Definition gl_shader.hh:191
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:849
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:669
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:879
void fragment_shader_from_glsl(MutableSpan< const char * > sources) override
void unbind() override
void uniform_float(int location, int comp_len, int array_size, const float *data) override
void transform_feedback_names_set(Span< const char * > name_list, eGPUShaderTFBType geom_type) override
bool post_finalize(const shader::ShaderCreateInfo *info=nullptr)
int get_ssbo_vertex_fetch_output_num_verts() const override
Definition gl_shader.hh:195
GLShader(const char *name)
Definition gl_shader.cc:50
void bind() override
GLSourcesBaked get_sources()
void compute_shader_from_glsl(MutableSpan< const char * > sources) override
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:901
std::string constants_declare() const
Definition gl_shader.cc:619
int program_handle_get() const override
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
Definition gl_shader.cc:572
bool transform_feedback_enable(VertBuf *buf) override
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:716
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
void geometry_shader_from_glsl(MutableSpan< const char * > sources) override
void vertex_shader_from_glsl(MutableSpan< const char * > sources) override
void transform_feedback_disable() override
void warm_cache(int) override
Definition gl_shader.hh:168
Vector< const char * > sources_get() const
std::string to_string() const
GLSources & operator=(Span< const char * > other)
virtual bool batch_is_ready(BatchHandle handle) override
virtual BatchHandle batch_compile(Span< const shader::ShaderCreateInfo * > &infos) override
virtual Vector< Shader * > batch_finalize(BatchHandle &handle) override
virtual bool specialization_batch_is_ready(SpecializationBatchHandle &handle)
virtual SpecializationBatchHandle precompile_specializations(Span< ShaderSpecialization >)
__int64 int64_t
Definition stdint.h:89
const char * source_ref
Definition gl_shader.hh:38
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...