137 if (pass->hash ==
hash && pass->engine == engine) {
150 if (node !=
nullptr) {
152 pass->next = node->next;
164 GPUShaderCreateInfo *info,
169 for (; pass && (pass->hash ==
hash); pass = pass->next) {
172 pass->engine == engine)
185 return (pass->compiled ==
false || pass->shader !=
nullptr);
195# define SRC_NAME(io, link, list, type) \
196 link->node->name << "_" << io << BLI_findindex(&link->node->list, (const void *)link) << "_" \
199# define SRC_NAME(io, list, link, type) type
204 switch (input->source) {
207 return stream <<
SRC_NAME(
"in", input, inputs,
"tmp") << input->id;
209 return stream <<
SRC_NAME(
"in", input, inputs,
"cons") << input->id;
211 return stream <<
"node_tree.u" << input->id;
213 return stream <<
"var_attrs.v" << input->attr->id;
215 return stream <<
"UNI_ATTR(unf_attrs[resource_id].attr" << input->uniform_attr->id <<
")";
217 return stream <<
"attr_load_layer(" << input->layer_attr->hash_code <<
")";
219 return stream <<
"strct" << input->id;
221 return stream << input->texture->sampler_name;
223 return stream << input->texture->tiled_mapping_name;
232 return stream <<
SRC_NAME(
"out", output, outputs,
"tmp") << output->id;
241 stream << input->
type <<
"(";
242 for (
int i = 0; i < input->type; i++) {
243 char formatted_float[32];
247 SNPRINTF(formatted_float,
"uintBitsToFloat(%uu)", uint_vec[i]);
248 stream << formatted_float;
249 if (i < input->type - 1) {
273 ListBase ubo_inputs_ = {
nullptr,
nullptr};
274 GPUInput *cryptomatte_input_ =
nullptr;
277 uint nodes_total_ = 0;
278 uint textures_total_ = 0;
279 uint uniforms_total_ = 0;
287 output.create_info =
reinterpret_cast<GPUShaderCreateInfo *
>(
316 bool do_optimize = (nodes_total_ >= 60 || textures_total_ >= 4 || uniforms_total_ >= 64) &&
317 (textures_total_ >= 1 && uniforms_total_ >= 8 && nodes_total_ >= 4);
322 void set_unique_ids();
324 void node_serialize(std::stringstream &eval_ss,
const GPUNode *node);
327 const char *output_default =
nullptr);
334 output.attr_load.clear();
345 std::stringstream load_ss;
361 load_ss <<
"var_attrs." << var_name;
362 if (attr->is_hair_length) {
364 load_ss <<
" = attr_load_" << input_type <<
"(" << attr_name <<
");\n";
367 switch (attr->type) {
372 load_ss <<
" = attr_load_orco(" << attr_name <<
");\n";
376 load_ss <<
" = attr_load_tangent(" << attr_name <<
");\n";
380 load_ss <<
" = attr_load_" << input_type <<
"(" << attr_name <<
");\n";
389 output.attr_load = load_ss.str();
396 std::stringstream ss;
401 if (
tex->colorband) {
403 info.
sampler(slot++, ImageType::FLOAT_1D_ARRAY, name, Frequency::BATCH);
407 info.
sampler(0, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH);
409 else if (
tex->tiled_mapping_name[0] !=
'\0') {
411 info.
sampler(slot++, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH);
414 info.
sampler(slot++, ImageType::FLOAT_1D_ARRAY, name_mapping, Frequency::BATCH);
418 info.
sampler(slot++, ImageType::FLOAT_2D, name, Frequency::BATCH);
423 textures_total_ = slot;
427 ss <<
"struct NodeTree {\n";
431 ss << input->
type <<
" crypto_hash;\n";
434 ss << input->type <<
" u" << input->id <<
";\n";
443 ss <<
"struct UniformAttrs {\n";
445 ss <<
"vec4 attr" << attr->id <<
";\n";
476 source_files.
append((
const char *)value);
481 std::sort(source_files.
begin(), source_files.
end());
482 for (
auto &key : source_files) {
488void GPUCodegen::node_serialize(std::stringstream &eval_ss,
const GPUNode *node)
492 switch (input->source) {
494 eval_ss << input->type <<
" " << input <<
"; " << input->function_call << input <<
");\n";
497 eval_ss << input->type <<
" " << input <<
" = CLOSURE_DEFAULT;\n";
500 eval_ss << input->type <<
" " << input <<
" = " << (
GPUConstant *)input <<
";\n";
508 eval_ss << output->type <<
" " << output <<
";\n";
512 eval_ss << node->name <<
"(";
515 switch (input->source) {
521 input->link->output->type;
524 eval_ss << to <<
"_from_" << from <<
"(";
531 eval_ss << input->link->output;
558std::string GPUCodegen::graph_serialize(
eGPUNodeTag tree_tag,
560 const char *output_default)
562 if (output_link ==
nullptr && output_default ==
nullptr) {
566 std::stringstream eval_ss;
567 bool has_nodes =
false;
571 if ((node->tag & tree_tag) == 0) {
574 node_serialize(eval_ss, node);
583 eval_ss <<
"return " << output_link->
output <<
";\n";
587 eval_ss <<
"return " << output_default <<
";\n";
590 std::string
str = eval_ss.str();
595std::string GPUCodegen::graph_serialize(
eGPUNodeTag tree_tag)
597 std::stringstream eval_ss;
599 if (node->tag & tree_tag) {
600 node_serialize(eval_ss, node);
603 std::string
str = eval_ss.str();
614 float material_hash = 0.0f;
619 material_hash =
hash.float_encoded();
621 cryptomatte_input_->
vec[0] = material_hash;
645void GPUCodegen::set_unique_ids()
662 output.surface = graph_serialize(
664 output.volume = graph_serialize(
GPU_NODE_TAG_VOLUME, graph.outlink_volume,
"CLOSURE_DEFAULT");
665 output.displacement = graph_serialize(
673 std::stringstream eval_ss;
674 eval_ss <<
"\n/* Generated Functions */\n\n";
678 node->tag &= ~GPU_NODE_TAG_FUNCTION;
683 eval_ss <<
"float " << func_link->name <<
"() {\n" << fn <<
"}\n\n";
685 output.material_functions = eval_ss.str();
716 if (optimize_graph) {
730 if (!optimize_graph) {
763 finalize_source_cb(thunk, material, &codegen.
output);
786 pass->shader =
nullptr;
791 pass->engine = engine;
793 pass->compiled =
false;
794 pass->compilation_requested =
false;
795 pass->cached =
false;
800 pass->async_compilation_handle = -1;
809 if (!optimize_graph) {
833 int num_samplers = 0;
836 if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
848 if (shader ==
nullptr) {
864 if (pass->create_info->geometry_source_.is_empty() ==
false) {
875 if (!pass->compilation_requested) {
876 pass->compilation_requested =
true;
877 pass->create_info->name_ = shname;
878 GPUShaderCreateInfo *info =
reinterpret_cast<GPUShaderCreateInfo *
>(
888 if (!pass->compiled) {
893 if (shader !=
nullptr) {
894 fprintf(stderr,
"GPUShader: error: too many samplers in shader.\n");
899 pass->shader = shader;
900 pass->compiled =
true;
909 if (pass->async_compilation_handle == -1) {
916 pass->async_compilation_handle = 0;
927 BLI_assert(pass->async_compilation_handle != -1);
928 if (pass->async_compilation_handle) {
937 return pass->async_compilation_handle == 0;
945 if (pass->async_compilation_handle > 0) {
972 delete pass->create_info;
990 if (pass->refcount == 0 && !pass->cached) {
998 const int shadercollectrate = 60;
1005 if (pass->refcount > 0) {
1008 else if (pass->gc_timestamp + shadercollectrate < ctime) {
1014 prev_pass = &pass->
next;
General operations, lookup, etc. for materials.
void BKE_material_defaults_free_gpu(void)
#define BLI_assert_msg(a, msg)
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
void BLI_ghashIterator_step(GHashIterator *ghi)
void BLI_ghashIterator_free(GHashIterator *ghi)
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed)
void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len)
void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data)
uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2)
Single link-list utility macros. (header only api).
#define BLI_LINKS_PREPEND(list, link)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
struct LinkData * BLI_genericNodeN(void *data)
#define STRNCPY(dst, src)
#define SNPRINTF(dst, format,...)
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
pthread_spinlock_t SpinLock
void BLI_mutex_end(ThreadMutex *mutex)
void BLI_mutex_init(ThreadMutex *mutex)
void BLI_mutex_lock(ThreadMutex *mutex)
void BLI_mutex_unlock(ThreadMutex *mutex)
void BLI_spin_init(SpinLock *spin)
void BLI_spin_unlock(SpinLock *spin)
void BLI_spin_lock(SpinLock *spin)
pthread_mutex_t ThreadMutex
void BLI_spin_end(SpinLock *spin)
Platform independent time functions.
double BLI_time_now_seconds(void)
int GPU_max_textures_geom()
int GPU_max_textures_frag()
bool GPU_shader_draw_parameters_support()
int GPU_max_textures_vert()
eGPUBackendType GPU_backend_get_type()
uint64_t GPU_material_uuid_get(GPUMaterial *mat)
void(*)(void *thunk, GPUMaterial *mat, GPUCodegenOutput *codegen) GPUCodegenCallbackFn
Material * GPU_material_get_material(GPUMaterial *material)
eGPUMaterialFlag GPU_material_flag(const GPUMaterial *mat)
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
blender::Vector< GPUShader * > GPU_shader_batch_finalize(BatchHandle &handle)
bool GPU_shader_batch_is_ready(BatchHandle handle)
GPUShader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
BatchHandle GPU_shader_batch_create_from_infos(blender::Span< const GPUShaderCreateInfo * > infos)
void GPU_shader_free(GPUShader *shader)
void GPU_shader_free_builtin_shaders()
Read Guarded memory(de)allocation.
struct GPUShader GPUShader
GPUCodegenCreateInfo * create_info
bool should_optimize_heuristic() const
uint32_t hash_get() const
void generate_cryptomatte()
void generate_resources()
GPUCodegen(GPUMaterial *mat_, GPUNodeGraph *graph_)
void generate_uniform_buffer()
void append(const T &value)
void extend_non_duplicates(Span< T > array)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static GPUPass * gpu_pass_cache_resolve_collision(GPUPass *pass, GPUShaderCreateInfo *info, uint32_t hash)
static SpinLock pass_cache_spin
void GPU_pass_cache_garbage_collect()
static bool gpu_pass_is_valid(const GPUPass *pass)
static int count_active_texture_sampler(GPUPass *pass, GPUShader *shader)
static std::ostream & operator<<(std::ostream &stream, const GPUInput *input)
GPUPass * GPU_generate_pass(GPUMaterial *material, GPUNodeGraph *graph, eGPUMaterialEngine engine, GPUCodegenCallbackFn finalize_source_cb, void *thunk, bool optimize_graph)
static void gpu_pass_free(GPUPass *pass)
static GPUPass * pass_cache
GPUShaderCreateInfo * GPU_pass_begin_compilation(GPUPass *pass, const char *shname)
void GPU_pass_cache_init()
static GPUPass * gpu_pass_cache_lookup(eGPUMaterialEngine engine, uint32_t hash)
void GPU_pass_release(GPUPass *pass)
void GPU_pass_acquire(GPUPass *pass)
void GPU_pass_begin_async_compilation(GPUPass *pass, const char *shname)
bool GPU_pass_compile(GPUPass *pass, const char *shname)
static void gpu_pass_cache_insert_after(GPUPass *node, GPUPass *pass)
bool GPU_pass_async_compilation_try_finalize(GPUPass *pass)
static bool gpu_pass_shader_validate(GPUPass *pass, GPUShader *shader)
#define SRC_NAME(io, list, link, type)
bool GPU_pass_should_optimize(GPUPass *pass)
bool GPU_pass_finalize_compilation(GPUPass *pass, GPUShader *shader)
void GPU_pass_cache_free()
GPUShader * GPU_pass_shader_get(GPUPass *pass)
void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag)
void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph)
void gpu_node_graph_optimize(GPUNodeGraph *graph)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
@ GPU_NODE_TAG_DISPLACEMENT
@ GPU_NODE_TAG_COMPOSITOR
@ GPU_SOURCE_FUNCTION_CALL
@ GPU_SOURCE_TEX_TILED_MAPPING
@ GPU_SOURCE_UNIFORM_ATTR
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
static Type to_type(const eGPUType type)
Vector< const char * > gpu_shader_dependency_get_resolved_source(const StringRefNull source_name)
char attr_names[16][GPU_MAX_SAFE_ATTR_NAME+1]
const char * append_sampler_name(const char name[32])
std::array< char, 32 > NameEntry
blender::Vector< std::unique_ptr< NameEntry >, 16 > sampler_names
StageInterfaceInfo * interface_generated
GPUCodegenCreateInfo(const char *name)
GPUShaderCreateInfo * create_info
eGPUMaterialEngine engine
BatchHandle async_compilation_handle
ThreadMutex shader_creation_mutex
GPUCodegenCreateInfo * create_info
bool compilation_requested
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Self & vertex_in(int slot, Type type, StringRefNull name)
void finalize(const bool recursive=false)
Self & additional_info(StringRefNull info_name)
Self & vertex_out(StageInterfaceInfo &interface)
std::string typedef_source_generated
Vector< const char *, 0 > dependencies_generated
Self & sampler(int slot, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS, GPUSamplerState sampler=GPUSamplerState::internal_sampler())
Self & uniform_buf(int slot, StringRefNull type_name, StringRefNull name, Frequency freq=Frequency::PASS)
Self & smooth(Type type, StringRefNull _name)