diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2016-06-02 18:30:33 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2016-06-02 18:30:33 +0300 |
commit | 570bbf680a58b6159792e22d6a1206e4a505bae4 (patch) | |
tree | 120cc39738fbc2ab83cb095b351e900aa3187e80 /source/blender | |
parent | 8fda725b1873af2ca91e3e1999e82c02b9ff1863 (diff) |
Support for image sampling in the LLVM backend.
This reintroduces the "globals" concept for mapping ID datablocks with
a consistent permanent identifier key.
Diffstat (limited to 'source/blender')
22 files changed, 444 insertions, 194 deletions
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index e4c9a6dbcf7..904c130616f 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -39,6 +39,7 @@ extern "C" { struct bNode; struct Brush; +struct BVMEvalGlobals; struct ColorBand; struct EnvMap; struct EvaluationContext; @@ -136,8 +137,9 @@ bool BKE_texture_is_image_user(const struct Tex *tex); void BKE_texture_get_value( const struct Scene *scene, struct Tex *texture, - float *tex_co, struct TexResult *texres, bool use_color_management); -void BKE_texture_get_value_deriv( + const float *tex_co, struct TexResult *texres, bool use_color_management); +void BKE_texture_get_value_ex( + struct BVMEvalGlobals *globals, const struct Scene *scene, struct Tex *texture, const float *tex_co, const float *tex_dx, const float *tex_dy, struct TexResult *texres, struct TexResult *texres_dx, struct TexResult *texres_dy, diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 8e24dd117c9..b6ce24de682 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1660,45 +1660,36 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture) void BKE_texture_get_value( const Scene *scene, Tex *texture, - float *tex_co, TexResult *texres, bool use_color_management) + const float *tex_co, TexResult *texres, + bool use_color_management) { - int result_type; - bool do_color_manage = false; - - if (scene && use_color_management) { - do_color_manage = BKE_scene_check_color_management_enabled(scene); - } - - /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false); - - /* if the texture gave an RGB value, we assume it didn't give a valid - * intensity, since this is in the context of modifiers don't use perceptual color conversion. - * if the texture didn't give an RGB value, copy the intensity across - */ - if (result_type & TEX_RGB) { - texres->tin = (1.0f / 3.0f) * (texres->tr + texres->tg + texres->tb); - } - else { - copy_v3_fl(&texres->tr, texres->tin); - } + BKE_texture_get_value_ex(NULL, scene, texture, + tex_co, NULL, NULL, + texres, NULL, NULL, + use_color_management); } -void BKE_texture_get_value_deriv( +void BKE_texture_get_value_ex( + struct BVMEvalGlobals *globals, const Scene *scene, Tex *texture, const float *tex_co, const float *tex_dx, const float *tex_dy, TexResult *texres, TexResult *texres_dx, TexResult *texres_dy, - bool UNUSED(use_color_management)) + bool use_color_management) { int result_type; + bool do_color_manage = false; + + if (scene && use_color_management) { + do_color_manage = BKE_scene_check_color_management_enabled(scene); + } - /* no node textures for now */ if (texture->use_nodes && texture->nodetree) { struct BVMFunction *fn = BVM_gen_texture_function_llvm(texture->nodetree, true); if (fn) { struct BVMEvalContext *context = BVM_context_create(); - BVM_eval_texture_llvm(context, fn, + BVM_eval_texture_llvm(globals, + context, fn, texres, texres_dx, texres_dy, tex_co, tex_dx, tex_dy, 0, 0, scene->r.cfra, false); @@ -1708,6 +1699,10 @@ void BKE_texture_get_value_deriv( BVM_function_llvm_release(fn); } } + else { + struct ImagePool *image_pool = (globals ? BVM_globals_image_pool(globals) : NULL); + result_type = multitex_ext_safe(texture, (float*)tex_co, texres, image_pool, do_color_manage, false); + } /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. diff --git a/source/blender/blenvm/BVM_api.h b/source/blender/blenvm/BVM_api.h index 45f3af31ea6..467e147de42 100644 --- a/source/blender/blenvm/BVM_api.h +++ b/source/blender/blenvm/BVM_api.h @@ -91,6 +91,7 @@ BVMBufferType BVM_typedesc_buffer_type(struct BVMTypeDesc *typedesc); /* ------------------------------------------------------------------------- */ +struct bNodeTree; struct DepsNodeHandle; void BVM_nodetree_compile_dependencies(struct bNodeTree *ntree, struct DepsNodeHandle *handle); @@ -102,10 +103,12 @@ struct BVMEvalGlobals; struct BVMEvalContext; struct bNodeTree; +struct ImagePool; struct BVMEvalGlobals *BVM_globals_create(void); void BVM_globals_free(struct BVMEvalGlobals *globals); +struct ImagePool *BVM_globals_image_pool(struct BVMEvalGlobals *globals); void BVM_globals_add_object(struct BVMEvalGlobals *globals, int key, struct Object *ob); void BVM_globals_add_nodetree_relations(struct BVMEvalGlobals *globals, struct bNodeTree *ntree); @@ -139,7 +142,7 @@ struct BVMFunction *BVM_gen_forcefield_function_bvm(struct bNodeTree *btree, boo void BVM_debug_forcefield_nodes(struct bNodeTree *btree, FILE *debug_file, const char *label, BVMDebugMode mode); void BVM_eval_forcefield_bvm(struct BVMEvalGlobals *globals, struct BVMEvalContext *context, struct BVMFunction *fn, - struct Object *effob, const struct EffectedPoint *point, float force[3], float impulse[3]); + struct Object *effob, const struct EffectedPoint *point, float force[3], float impulse[3]); /* ------------------------------------------------------------------------- */ @@ -151,11 +154,13 @@ struct BVMFunction *BVM_gen_texture_function_llvm(struct bNodeTree *btree, bool void BVM_debug_texture_nodes(struct bNodeTree *btree, FILE *debug_file, const char *label, BVMDebugMode mode); -void BVM_eval_texture_bvm(struct BVMEvalContext *context, struct BVMFunction *fn, +void BVM_eval_texture_bvm(struct BVMEvalGlobals *globals, struct BVMEvalContext *context, + struct BVMFunction *fn, struct TexResult *target, float coord[3], float dxt[3], float dyt[3], int osatex, short which_output, int cfra, int preview); -void BVM_eval_texture_llvm(struct BVMEvalContext *context, struct BVMFunction *fn, +void BVM_eval_texture_llvm(struct BVMEvalGlobals *globals, struct BVMEvalContext *context, + struct BVMFunction *fn, struct TexResult *value, struct TexResult *value_dx, struct TexResult *value_dy, diff --git a/source/blender/blenvm/CMakeLists.txt b/source/blender/blenvm/CMakeLists.txt index 9b264a516a7..af06863533c 100644 --- a/source/blender/blenvm/CMakeLists.txt +++ b/source/blender/blenvm/CMakeLists.txt @@ -33,6 +33,7 @@ set(INC ../blenkernel ../blenlib ../depsgraph + ../imbuf ../makesdna ../makesrna ../render/extern/include @@ -54,12 +55,15 @@ set(SRC modules/mod_defines.h modules/mod_base.h modules/mod_color.h + modules/mod_image.h modules/mod_math.h modules/mod_texture.h util/util_opcode.h util/util_data_ptr.h util/util_debug.h + util/util_eval_globals.cc + util/util_eval_globals.h util/util_hash.h util/util_map.h util/util_math.h diff --git a/source/blender/blenvm/bvm/CMakeLists.txt b/source/blender/blenvm/bvm/CMakeLists.txt index 14601ef9384..ac668dd8de3 100644 --- a/source/blender/blenvm/bvm/CMakeLists.txt +++ b/source/blender/blenvm/bvm/CMakeLists.txt @@ -26,6 +26,7 @@ set(INC . .. + ../intern ../modules ../util ../../blenkernel diff --git a/source/blender/blenvm/bvm/bvm_eval.cc b/source/blender/blenvm/bvm/bvm_eval.cc index 79da5cb3b85..fd053c7db19 100644 --- a/source/blender/blenvm/bvm/bvm_eval.cc +++ b/source/blender/blenvm/bvm/bvm_eval.cc @@ -59,70 +59,6 @@ extern "C" { namespace blenvm { -EvalGlobals::EvalGlobals() -{ - m_image_pool = BKE_image_pool_new(); -} - -EvalGlobals::~EvalGlobals() -{ - BKE_image_pool_free(m_image_pool); -} - -int EvalGlobals::get_id_key(ID *id) -{ - int hash = BLI_ghashutil_strhash(id->name); - if (id->lib) { - hash = hash_combine(hash, BLI_ghashutil_strhash(id->lib->name)); - } - return hash; -} - -void EvalGlobals::add_object(int key, Object *ob) -{ - m_objects[key] = ob; -} - -PointerRNA EvalGlobals::lookup_object(int key) const -{ - ObjectMap::const_iterator it = m_objects.find(key); - if (it != m_objects.end()) { - PointerRNA ptr; - RNA_id_pointer_create((ID *)it->second, &ptr); - return ptr; - } - else { - return PointerRNA_NULL; - } -} - -void EvalGlobals::add_image(int key, Image *ima) -{ - m_images[key] = ima; -} - -ImBuf *EvalGlobals::lookup_imbuf(int key, ImageUser *iuser) const -{ - ImageMap::const_iterator ima_it = m_images.find(key); - Image *ima = (ima_it != m_images.end()) ? ima_it->second : NULL; - if (!ima) - return NULL; - - /* local changes to the original ImageUser */ -// if (!BKE_image_is_multilayer(ima)) -// iuser->multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); - - ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, iuser, m_image_pool); - if (!ibuf || (!ibuf->rect && !ibuf->rect_float)) { - BKE_image_pool_release_ibuf(ima, ibuf, m_image_pool); - return NULL; - } - - return ibuf; -} - -/* ------------------------------------------------------------------------- */ - int EvalStack::stack_size(size_t datasize) { return int_div_ceil(datasize, sizeof(EvalStack)); diff --git a/source/blender/blenvm/bvm/bvm_eval.h b/source/blender/blenvm/bvm/bvm_eval.h index 68dd80f4c85..c4d4c06ac06 100644 --- a/source/blender/blenvm/bvm/bvm_eval.h +++ b/source/blender/blenvm/bvm/bvm_eval.h @@ -32,24 +32,9 @@ * \ingroup bvm */ -#include <set> -#include <vector> - #include "MEM_guardedalloc.h" -extern "C" { -#include "RNA_access.h" -} - -#include "util_map.h" -#include "util_string.h" - -struct ID; -struct Image; -struct ImagePool; -struct ImageUser; -struct ImBuf; -struct Object; +#include "util_eval_globals.h" namespace blenvm { @@ -57,29 +42,6 @@ struct InstructionList; #define BVM_STACK_SIZE 4095 -struct EvalGlobals { - typedef unordered_map<int, Object *> ObjectMap; - typedef unordered_map<int, Image *> ImageMap; - - EvalGlobals(); - ~EvalGlobals(); - - static int get_id_key(ID *id); - - void add_object(int key, Object *ob); - PointerRNA lookup_object(int key) const; - - void add_image(int key, Image *ima); - ImBuf *lookup_imbuf(int key, ImageUser *iuser) const; - -private: - ObjectMap m_objects; - ImageMap m_images; - ImagePool *m_image_pool; - - MEM_CXX_CLASS_ALLOC_FUNCS("BVM:EvalGlobals") -}; - struct EvalStack { static int stack_size(size_t datasize); diff --git a/source/blender/blenvm/compile/node_graph.cc b/source/blender/blenvm/compile/node_graph.cc index ef0f057be98..17d5aa31cf2 100644 --- a/source/blender/blenvm/compile/node_graph.cc +++ b/source/blender/blenvm/compile/node_graph.cc @@ -74,9 +74,10 @@ NodeOutput::~NodeOutput() /* ------------------------------------------------------------------------- */ -NodeType::NodeType(const string &name, eNodeTypeKind kind) : +NodeType::NodeType(const string &name, eNodeTypeKind kind, bool use_globals) : m_name(name), - m_kind(kind) + m_kind(kind), + m_use_globals(use_globals) { } @@ -1773,6 +1774,7 @@ static void register_opcode_node_types() nt->add_output("duplis", "DUPLIS"); nt = NodeGraph::add_node_type("IMAGE_SAMPLE"); + nt->set_use_globals(true); nt->add_input("image", "INT", 0); nt->add_input("uv", "FLOAT3", float3(0.0f, 0.0f, 0.0f)); nt->add_output("color", "FLOAT4"); diff --git a/source/blender/blenvm/compile/node_graph.h b/source/blender/blenvm/compile/node_graph.h index 57b182bbcb5..47228138993 100644 --- a/source/blender/blenvm/compile/node_graph.h +++ b/source/blender/blenvm/compile/node_graph.h @@ -98,11 +98,14 @@ struct NodeType { typedef std::vector<NodeInput> InputList; typedef std::vector<NodeOutput> OutputList; - NodeType(const string &name, eNodeTypeKind kind = NODE_TYPE_FUNCTION); + NodeType(const string &name, eNodeTypeKind kind = NODE_TYPE_FUNCTION, bool use_globals = false); ~NodeType(); const string &name() const { return m_name; } eNodeTypeKind kind() const { return m_kind; } + bool use_globals() const { return m_use_globals; } + + void set_use_globals(bool use_globals) { m_use_globals = use_globals; } int num_inputs() const { return m_inputs.size(); } int num_outputs() const { return m_outputs.size(); } @@ -139,6 +142,7 @@ private: InputList m_inputs; OutputList m_outputs; eNodeTypeKind m_kind; + bool m_use_globals; MEM_CXX_CLASS_ALLOC_FUNCS("BVM:NodeType") }; diff --git a/source/blender/blenvm/intern/bvm_api.cc b/source/blender/blenvm/intern/bvm_api.cc index ee047e2291f..3a0a46590fa 100644 --- a/source/blender/blenvm/intern/bvm_api.cc +++ b/source/blender/blenvm/intern/bvm_api.cc @@ -77,6 +77,13 @@ extern "C" { namespace blenvm { static mesh_ptr __empty_mesh__; static duplis_ptr __empty_duplilist__ = duplis_ptr(new DupliList()); + +static blenvm::EvalGlobals *eval_globals_default() +{ + static blenvm::EvalGlobals default_globals; + return &default_globals; +} + } void BVM_init(void) @@ -292,6 +299,9 @@ struct BVMEvalGlobals *BVM_globals_create(void) void BVM_globals_free(struct BVMEvalGlobals *globals) { delete _GLOBALS(globals); } +struct ImagePool *BVM_globals_image_pool(struct BVMEvalGlobals *globals) +{ return _GLOBALS(globals)->image_pool(); } + void BVM_globals_add_object(struct BVMEvalGlobals *globals, int key, struct Object *ob) { _GLOBALS(globals)->add_object(key, ob); } @@ -556,7 +566,8 @@ void BVM_eval_forcefield_bvm(struct BVMEvalGlobals *globals, struct BVMEvalConte namespace blenvm { -typedef void (*TexNodesFunc)(Dual2<float4> *r_color, Dual2<float3> *r_normal, +typedef void (*TexNodesFunc)(const struct EvalGlobals *globals, + Dual2<float4> *r_color, Dual2<float3> *r_normal, const Dual2<float3> *co, int cfra, int osatex); static void set_texresult(TexResult *result, const float4 &color, const float3 &normal) @@ -672,37 +683,41 @@ void BVM_debug_texture_nodes(bNodeTree *btree, FILE *debug_file, const char *lab debug_node_graph(graph, debug_file, label, mode); } -void BVM_eval_texture_bvm(struct BVMEvalContext *ctx, struct BVMFunction *fn, +void BVM_eval_texture_bvm(struct BVMEvalGlobals *_globals, struct BVMEvalContext *ctx, struct BVMFunction *fn, struct TexResult *target, float coord[3], float dxt[3], float dyt[3], int osatex, short UNUSED(which_output), int cfra, int UNUSED(preview)) { using namespace blenvm; - EvalGlobals globals; + EvalGlobals *globals = _GLOBALS(_globals); + if (globals == NULL) + globals = eval_globals_default(); float4 color; float3 normal; const void *args[] = { coord, dxt, dyt, &cfra, &osatex }; void *results[] = { &color.x, &normal.x }; - _FUNC_BVM(fn)->eval(_CTX(ctx), &globals, args, results); + _FUNC_BVM(fn)->eval(_CTX(ctx), globals, args, results); set_texresult(target, color, normal); } -void BVM_eval_texture_llvm(struct BVMEvalContext *UNUSED(ctx), struct BVMFunction *fn, +void BVM_eval_texture_llvm(struct BVMEvalGlobals *_globals, struct BVMEvalContext *UNUSED(ctx), struct BVMFunction *fn, struct TexResult *value, struct TexResult *value_dx, struct TexResult *value_dy, const float coord[3], const float dxt[3], const float dyt[3], int osatex, short UNUSED(which_output), int cfra, int UNUSED(preview)) { using namespace blenvm; - EvalGlobals globals; + EvalGlobals *globals = _GLOBALS(_globals); + if (globals == NULL) + globals = eval_globals_default(); + Dual2<float4> r_color; Dual2<float3> r_normal; - UNUSED_VARS(globals); #ifdef WITH_LLVM TexNodesFunc fp = (TexNodesFunc)_FUNC_LLVM(fn)->ptr(); @@ -717,9 +732,9 @@ void BVM_eval_texture_llvm(struct BVMEvalContext *UNUSED(ctx), struct BVMFunctio else coord_v.set_dy(float3(0.0f, 1.0f, 0.0f)); - fp(&r_color, &r_normal, &coord_v, cfra, osatex); + fp(globals, &r_color, &r_normal, &coord_v, cfra, osatex); #else - UNUSED_VARS(fn, coord, dxt, dyt, cfra, osatex); + UNUSED_VARS(fn, globals, coord, dxt, dyt, cfra, osatex); r_color = Dual2<float4>(float4(0.0f, 0.0f, 0.0f, 0.0f)); r_normal = Dual2<float3>(float3(0.0f, 0.0f, 1.0f)); #endif diff --git a/source/blender/blenvm/llvm/CMakeLists.txt b/source/blender/blenvm/llvm/CMakeLists.txt index 442702235d8..2c184427833 100644 --- a/source/blender/blenvm/llvm/CMakeLists.txt +++ b/source/blender/blenvm/llvm/CMakeLists.txt @@ -32,6 +32,7 @@ set(INC ../util ../../blenkernel ../../blenlib + ../../imbuf ../../makesdna ../../makesrna ../../../../intern/guardedalloc diff --git a/source/blender/blenvm/llvm/llvm_compiler.cc b/source/blender/blenvm/llvm/llvm_compiler.cc index 432cb43d2c7..6bbc4fe311a 100644 --- a/source/blender/blenvm/llvm/llvm_compiler.cc +++ b/source/blender/blenvm/llvm/llvm_compiler.cc @@ -49,7 +49,8 @@ namespace blenvm { LLVMCompilerBase::LLVMCompilerBase() : - m_module(NULL) + m_module(NULL), + m_globals_ptr(NULL) { } @@ -115,28 +116,28 @@ llvm::BasicBlock *LLVMCompilerBase::codegen_function_body_expression(const NodeG using namespace llvm; node_graph_begin(); + /* cache function arguments */ + int num_inputs = graph.inputs.size(); + int num_outputs = graph.outputs.size(); + std::vector<Argument*> input_args(num_inputs), output_args(num_outputs); + { + Function::ArgumentListType::iterator arg_it = func->arg_begin(); + m_globals_ptr = arg_it++; /* globals, passed to functions which need it */ + for (int i = 0; i < num_outputs; ++i) + output_args[i] = arg_it++; + for (int i = 0; i < num_inputs; ++i) + input_args[i] = arg_it++; + } IRBuilder<> builder(context()); BasicBlock *block = BasicBlock::Create(context(), "entry", func); builder.SetInsertPoint(block); - int num_inputs = graph.inputs.size(); - int num_outputs = graph.outputs.size(); - - { - Function::ArgumentListType::iterator it = func->arg_begin(); - for (int i = 0; i < num_outputs; ++i) { - /* skip output arguments */ - ++it; - } - for (int i = 0; i < num_inputs; ++i) { - const NodeGraph::Input &input = graph.inputs[i]; - Argument *arg = it++; - - if (input.key) - map_argument(block, input.key, arg); - } + for (int i = 0; i < num_inputs; ++i) { + const NodeGraph::Input &input = graph.inputs[i]; + if (input.key) + map_argument(block, input.key, input_args[i]); } OrderedNodeSet nodes; @@ -149,19 +150,15 @@ llvm::BasicBlock *LLVMCompilerBase::codegen_function_body_expression(const NodeG codegen_node(block, &node); } - { - Function::ArgumentListType::iterator it = func->arg_begin(); - for (int i = 0; i < num_outputs; ++i) { - const NodeGraph::Output &output = graph.outputs[i]; - Argument *arg = it++; - - store_return_value(block, output.key, arg); - } + for (int i = 0; i < num_outputs; ++i) { + const NodeGraph::Output &output = graph.outputs[i]; + store_return_value(block, output.key, output_args[i]); } builder.CreateRetVoid(); node_graph_end(); + m_globals_ptr = NULL; return block; } @@ -182,8 +179,8 @@ llvm::Function *LLVMCompilerBase::codegen_node_function(const string &name, cons output_types.push_back(FunctionParameter(type, output.name)); } - Function *func = declare_function(module(), name, input_types, output_types); - BLI_assert(func->getArgumentList().size() == graph.inputs.size() + graph.outputs.size() && + Function *func = declare_function(module(), name, input_types, output_types, true); + BLI_assert(func->getArgumentList().size() == 1 + graph.inputs.size() + graph.outputs.size() && "Error: Function has wrong number of arguments for node tree\n"); codegen_function_body_expression(graph, func); @@ -278,6 +275,10 @@ void LLVMCompilerBase::expand_function_node(llvm::BasicBlock *block, const NodeI /* function call arguments */ std::vector<Value *> args; + if (node->type->use_globals()) { + args.push_back(m_globals_ptr); + } + for (int i = 0; i < node->num_outputs(); ++i) { ConstOutputKey output = node->output(i); @@ -313,11 +314,18 @@ void LLVMCompilerBase::expand_function_node(llvm::BasicBlock *block, const NodeI llvm::Function *LLVMCompilerBase::declare_function(llvm::Module *mod, const string &name, const FunctionParameterList &input_types, - const FunctionParameterList &output_types) + const FunctionParameterList &output_types, + bool use_globals) { using namespace llvm; std::vector<llvm::Type*> arg_types; + + if (use_globals) { + Type *t_globals = llvm::TypeBuilder<void*, false>::get(context()); + arg_types.push_back(t_globals); + } + for (int i = 0; i < output_types.size(); ++i) { Type *type = output_types[i].type; /* use a pointer to store output values */ @@ -332,11 +340,14 @@ llvm::Function *LLVMCompilerBase::declare_function(llvm::Module *mod, const stri Function *func = Function::Create(functype, Function::ExternalLinkage, name, mod); Function::arg_iterator it = func->arg_begin(); - for (size_t i = 0; i < output_types.size(); ++i, ++it) { - it->setName(output_types[i].name); + if (use_globals) { + (it++)->setName("globals"); + } + for (size_t i = 0; i < output_types.size(); ++i) { + (it++)->setName(output_types[i].name); } - for (size_t i = 0; i < input_types.size(); ++i, ++it) { - it->setName(input_types[i].name); + for (size_t i = 0; i < input_types.size(); ++i) { + (it++)->setName(input_types[i].name); } return func; @@ -356,7 +367,7 @@ llvm::Function *LLVMCompilerBase::declare_node_function(llvm::Module *mod, const append_output_types(output_types, output); } - return declare_function(mod, nodetype->name(), input_types, output_types); + return declare_function(mod, nodetype->name(), input_types, output_types, nodetype->use_globals()); } /* ------------------------------------------------------------------------- */ @@ -374,15 +385,6 @@ FunctionLLVM *LLVMCompilerBase::compile_function(const string &name, const NodeG BLI_assert(opt_level >= 0 && opt_level <= 3 && "Invalid optimization level (must be between 0 and 3)"); optimize_function(func, opt_level); -#if 0 - printf("=== NODE FUNCTION ===\n"); - fflush(stdout); -// func->dump(); - module()->dump(); - printf("=====================\n"); - fflush(stdout); -#endif - verifyFunction(*func, &outs()); verifyModule(*module(), &outs()); diff --git a/source/blender/blenvm/llvm/llvm_compiler.h b/source/blender/blenvm/llvm/llvm_compiler.h index ba01a2b6d76..f48f7813c9c 100644 --- a/source/blender/blenvm/llvm/llvm_compiler.h +++ b/source/blender/blenvm/llvm/llvm_compiler.h @@ -121,13 +121,15 @@ protected: llvm::Function *declare_function(llvm::Module *mod, const string &name, const FunctionParameterList &input_types, - const FunctionParameterList &output_types); + const FunctionParameterList &output_types, + bool use_globals); llvm::Function *declare_node_function(llvm::Module *mod, const NodeType *nodetype); virtual void define_nodes_module() = 0; virtual llvm::Module *get_nodes_module() const = 0; private: llvm::Module *m_module; + llvm::Value *m_globals_ptr; }; struct LLVMTextureCompiler : public LLVMCompilerBase { diff --git a/source/blender/blenvm/llvm/llvm_compiler_dual.cc b/source/blender/blenvm/llvm/llvm_compiler_dual.cc index 97eacec0863..f01cf7197af 100644 --- a/source/blender/blenvm/llvm/llvm_compiler_dual.cc +++ b/source/blender/blenvm/llvm/llvm_compiler_dual.cc @@ -400,7 +400,7 @@ llvm::Function *LLVMTextureCompiler::declare_elementary_node_function( return NULL; } - return declare_function(mod, name, input_types, output_types); + return declare_function(mod, name, input_types, output_types, nodetype->use_globals()); } void LLVMTextureCompiler::define_elementary_functions(llvm::Module *mod, OpCode op, const NodeType *nodetype) @@ -445,6 +445,14 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, std::vector<Value*> call_args_value, call_args_dx, call_args_dy; Function::arg_iterator arg_it = func->arg_begin(); + + if (nodetype->use_globals()) { + Value *globals = arg_it++; + call_args_value.push_back(globals); + call_args_dx.push_back(globals); + call_args_dy.push_back(globals); + } + /* output arguments */ for (int i = 0; i < nodetype->num_outputs(); ++i) { const NodeOutput *output = nodetype->find_output(i); @@ -507,13 +515,14 @@ void LLVMTextureCompiler::define_dual_function_wrapper(llvm::Module *mod, } else { /* zero the derivatives */ - for (int i = 0; i < nodetype->num_outputs(); ++i, ++arg_it) { + for (int i = 0; i < nodetype->num_outputs(); ++i) { const NodeOutput *output = nodetype->find_output(i); const TypeSpec *typespec = output->typedesc.get_typespec(); if (bvm_type_has_dual_value(typespec)) { - bvm_llvm_set_zero(context(), block, call_args_dx[i], typespec); - bvm_llvm_set_zero(context(), block, call_args_dy[i], typespec); + int arg_i = nodetype->use_globals() ? i + 1 : i; + bvm_llvm_set_zero(context(), block, call_args_dx[arg_i], typespec); + bvm_llvm_set_zero(context(), block, call_args_dy[arg_i], typespec); } } } diff --git a/source/blender/blenvm/modules/mod_image.h b/source/blender/blenvm/modules/mod_image.h new file mode 100644 index 00000000000..f5197880950 --- /dev/null +++ b/source/blender/blenvm/modules/mod_image.h @@ -0,0 +1,94 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __MOD_IMAGE_H__ +#define __MOD_IMAGE_H__ + +extern "C" { +#include "BLI_math_color.h" + +#include "DNA_image_types.h" + +#include "BKE_image.h" +#include "BKE_scene.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" +} + +#include "mod_defines.h" + +#include "util_eval_globals.h" +#include "util_math.h" + +BVM_MOD_NAMESPACE_BEGIN + +/* nearest sampling mode */ +inline static void imbuf_sample_nearest(ImBuf *ibuf, const float3 &uv, float4 &color) +{ + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + int x1 = (int)uv.x; + int y1 = (int)uv.y; + + /* sample area entirely outside image? */ + if (x1 < 0 || x1 > ibuf->x - 1 || y1 < 0 || y1 > ibuf->y - 1) { + color.x = color.y = color.z = color.w = 0.0f; + return; + } + + if (ibuf->rect_float) { + const float *data = ibuf->rect_float + ((size_t)ibuf->x * y1 + x1) * 4; + copy_v4_v4(color.data(), data); + } + else { + const unsigned char *data = (unsigned char *)ibuf->rect + ((size_t)ibuf->x * y1 + x1) * 4; + rgba_uchar_to_float(color.data(), data); + } +} + +bvm_extern void V__IMAGE_SAMPLE(const EvalGlobals *globals, + float4 &r_color, + int image, const float3 &uv) +{ + r_color = float4(0.0f, 0.0f, 0.0f, 0.0f); + + /* TODO just a dummy ImageUser for now */ + ImageUser iuser = {0}; + iuser.ok = true; + + ImBuf *ibuf = globals->lookup_imbuf(image, &iuser); + if (ibuf) { + imbuf_sample_nearest(ibuf, uv, r_color); + } +} +BVM_DECL_FUNCTION_VALUE(IMAGE_SAMPLE) + +BVM_MOD_NAMESPACE_END + +#endif /* __MOD_IMAGE_H__ */ diff --git a/source/blender/blenvm/modules/modules.h b/source/blender/blenvm/modules/modules.h index b2ab355855c..f8d6edbaf1b 100644 --- a/source/blender/blenvm/modules/modules.h +++ b/source/blender/blenvm/modules/modules.h @@ -30,6 +30,7 @@ #include "mod_base.h" #include "mod_color.h" +#include "mod_image.h" #include "mod_math.h" #include "mod_texture.h" diff --git a/source/blender/blenvm/util/util_eval_globals.cc b/source/blender/blenvm/util/util_eval_globals.cc new file mode 100644 index 00000000000..5b33ba95107 --- /dev/null +++ b/source/blender/blenvm/util/util_eval_globals.cc @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file util_eval_globals.cc + * \ingroup bvm + */ + +#include <cassert> + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "DNA_ID.h" +#include "DNA_object_types.h" + +#include "BKE_image.h" + +#include "IMB_imbuf_types.h" +} + +#include "util_eval_globals.h" + +#include "util_hash.h" + +namespace blenvm { + +EvalGlobals::EvalGlobals() +{ + m_image_pool = BKE_image_pool_new(); +} + +EvalGlobals::~EvalGlobals() +{ + BKE_image_pool_free(m_image_pool); +} + +int EvalGlobals::get_id_key(ID *id) +{ + int hash = BLI_ghashutil_strhash(id->name); + if (id->lib) { + hash = hash_combine(hash, BLI_ghashutil_strhash(id->lib->name)); + } + return hash; +} + +void EvalGlobals::add_object(int key, Object *ob) +{ + m_objects[key] = ob; +} + +PointerRNA EvalGlobals::lookup_object(int key) const +{ + ObjectMap::const_iterator it = m_objects.find(key); + if (it != m_objects.end()) { + PointerRNA ptr; + RNA_id_pointer_create((ID *)it->second, &ptr); + return ptr; + } + else { + return PointerRNA_NULL; + } +} + +void EvalGlobals::add_image(int key, Image *ima) +{ + m_images[key] = ima; +} + +ImBuf *EvalGlobals::lookup_imbuf(int key, ImageUser *iuser) const +{ + ImageMap::const_iterator ima_it = m_images.find(key); + Image *ima = (ima_it != m_images.end()) ? ima_it->second : NULL; + if (!ima) + return NULL; + + /* local changes to the original ImageUser */ +// if (!BKE_image_is_multilayer(ima)) +// iuser->multi_index = BKE_scene_multiview_view_id_get(this->m_rd, this->m_viewName); + + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, iuser, m_image_pool); + if (!ibuf || (!ibuf->rect && !ibuf->rect_float)) { + BKE_image_pool_release_ibuf(ima, ibuf, m_image_pool); + return NULL; + } + + return ibuf; +} + +} /* namespace blenvm */ diff --git a/source/blender/blenvm/util/util_eval_globals.h b/source/blender/blenvm/util/util_eval_globals.h new file mode 100644 index 00000000000..9d0a0e520a7 --- /dev/null +++ b/source/blender/blenvm/util/util_eval_globals.h @@ -0,0 +1,80 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __UTIL_EVAL_GLOBALS_H__ +#define __UTIL_EVAL_GLOBALS_H__ + +/** \file util_eval_globals.h + * \ingroup bvm + */ + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "RNA_access.h" +} + +#include "util_map.h" +#include "util_string.h" + +struct ID; +struct Image; +struct ImagePool; +struct ImageUser; +struct ImBuf; +struct Object; + +namespace blenvm { + +struct EvalGlobals { + typedef unordered_map<int, Object *> ObjectMap; + typedef unordered_map<int, Image *> ImageMap; + + EvalGlobals(); + ~EvalGlobals(); + + static int get_id_key(ID *id); + + ImagePool *image_pool() const { return m_image_pool; } + + void add_object(int key, Object *ob); + PointerRNA lookup_object(int key) const; + + void add_image(int key, Image *ima); + ImBuf *lookup_imbuf(int key, ImageUser *iuser) const; + +private: + ObjectMap m_objects; + ImageMap m_images; + ImagePool *m_image_pool; + + MEM_CXX_CLASS_ALLOC_FUNCS("BVM:EvalGlobals") +}; + +} /* namespace blenvm */ + +#endif /* __UTIL_EVAL_GLOBALS_H__ */ diff --git a/source/blender/blenvm/util/util_opcode.h b/source/blender/blenvm/util/util_opcode.h index 41742328a24..210f67cf963 100644 --- a/source/blender/blenvm/util/util_opcode.h +++ b/source/blender/blenvm/util/util_opcode.h @@ -208,6 +208,7 @@ namespace blenvm { #define BVM_DEFINE_OPCODES \ BVM_DEFINE_OPCODES_BASE \ BVM_DEFINE_OPCODES_COLOR \ + BVM_DEFINE_OPCODES_IMAGE \ BVM_DEFINE_OPCODES_MATH \ BVM_DEFINE_OPCODES_TEXTURE \ diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 0de7676e8f8..5c17ab46a78 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../blenkernel ../blenlib ../blenfont + ../blenvm ../depsgraph ../makesdna ../makesrna diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 24400b731cb..fbf9b060b52 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -47,6 +47,8 @@ #include "BKE_texture.h" #include "BKE_deform.h" +#include "BVM_api.h" + #include "depsgraph_private.h" #include "MEM_guardedalloc.h" @@ -209,6 +211,7 @@ static void displaceModifier_do( float weight = 1.0f; /* init value unused but some compilers may complain */ const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ float (*vert_clnors)[3] = NULL; + struct BVMEvalGlobals *globals = NULL; if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return; if (dmd->strength == 0.0f) return; @@ -222,6 +225,10 @@ static void displaceModifier_do( get_texture_coords((MappingInfoModifierData *)dmd, ob, dm, vertexCos, tex_co, numVerts); modifier_init_texture(dmd->modifier.scene, dmd->texture); + + globals = BVM_globals_create(); + if (dmd->texture->use_nodes && dmd->texture->nodetree != NULL) + BVM_globals_add_nodetree_relations(globals, dmd->texture->nodetree); } else { tex_co = NULL; @@ -259,7 +266,11 @@ static void displaceModifier_do( if (dmd->texture) { texres.nor = NULL; - BKE_texture_get_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false); + BKE_texture_get_value_ex(globals, + dmd->modifier.scene, dmd->texture, + tex_co[i], NULL, NULL, + &texres, NULL, NULL, + false); delta = texres.tin - dmd->midlevel; } else { @@ -304,6 +315,10 @@ static void displaceModifier_do( if (vert_clnors) { MEM_freeN(vert_clnors); } + + if (globals) { + BVM_globals_free(globals); + } } static void deformVerts(ModifierData *md, Object *ob, diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index b4c5fea1c68..21e5d4e6cf3 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1126,7 +1126,11 @@ static int multitex(Tex *tex, if (fn) { struct BVMEvalContext *context = BVM_context_create(); - BVM_eval_texture_llvm(context, fn, texres, NULL, NULL, texvec, dxt, dyt, osatex, which_output, + BVM_eval_texture_llvm(NULL, + context, fn, + texres, NULL, NULL, + texvec, dxt, dyt, + osatex, which_output, R.r.cfra, texnode_preview); retval = TEX_INT | TEX_RGB | TEX_NOR; |