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
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
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>;
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
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.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
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")
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
friend class GLShaderCompiler
Definition gl_shader.hh:70
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 >)
Shader(const char *name)
Definition gpu_shader.cc:55
__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...