Refactor: realtime compositer context changes for render compositing

* Provide render data, node tree and color management directly instead
  of going through scene, as these may be modified by the render pipeline.
  Also better for cached texture hits this way.
* Change legacy pass type to pass name.
* Skip file output node when not doing final render.
* Gracefully handle incomplete render results.

Pull Request: https://projects.blender.org/blender/blender/pulls/108629
This commit is contained in:
Brecht Van Lommel
2023-06-05 17:18:38 +02:00
parent 6704881708
commit db43a8fb57
22 changed files with 100 additions and 63 deletions

View File

@@ -75,15 +75,13 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture);
*/
bool BKE_texture_is_image_user(const struct Tex *tex);
void BKE_texture_get_value_ex(const struct Scene *scene,
struct Tex *texture,
void BKE_texture_get_value_ex(struct Tex *texture,
const float *tex_co,
struct TexResult *texres,
struct ImagePool *pool,
bool use_color_management);
void BKE_texture_get_value(const struct Scene *scene,
struct Tex *texture,
void BKE_texture_get_value(struct Tex *texture,
const float *tex_co,
struct TexResult *texres,
bool use_color_management);

View File

@@ -1931,7 +1931,7 @@ static void sample_mesh(FluidFlowSettings *ffs,
tex_co[1] = tex_co[1] * 2.0f - 1.0f;
tex_co[2] = ffs->texture_offset;
}
BKE_texture_get_value(nullptr, ffs->noise_texture, tex_co, &texres, false);
BKE_texture_get_value(ffs->noise_texture, tex_co, &texres, false);
emission_strength *= texres.tin;
}
}

View File

@@ -705,22 +705,15 @@ bool BKE_texture_dependsOnTime(const Tex *texture)
/* ------------------------------------------------------------------------- */
void BKE_texture_get_value_ex(const Scene *scene,
Tex *texture,
void BKE_texture_get_value_ex(Tex *texture,
const float *tex_co,
TexResult *texres,
ImagePool *pool,
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, pool, do_color_manage, false);
const int result_type = multitex_ext_safe(
texture, tex_co, texres, pool, use_color_management, 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.
@@ -734,13 +727,12 @@ void BKE_texture_get_value_ex(const Scene *scene,
}
}
void BKE_texture_get_value(const Scene *scene,
Tex *texture,
void BKE_texture_get_value(Tex *texture,
const float *tex_co,
TexResult *texres,
bool use_color_management)
{
BKE_texture_get_value_ex(scene, texture, tex_co, texres, nullptr, use_color_management);
BKE_texture_get_value_ex(texture, tex_co, texres, nullptr, use_color_management);
}
static void texture_nodes_fetch_images_for_pool(Tex *texture, bNodeTree *ntree, ImagePool *pool)

View File

@@ -305,10 +305,10 @@ extern "C" {
* (true) or editing (false).
* based on this setting the system will work differently:
* - during rendering only Composite & the File output node will be calculated
* \see NodeOperation.is_output_program(int rendering) of the specific operations
* \see NodeOperation.is_output_program(bool rendering) of the specific operations
*
* - during editing all output nodes will be calculated
* \see NodeOperation.is_output_program(int rendering) of the specific operations
* \see NodeOperation.is_output_program(bool rendering) of the specific operations
*
* - another quality setting can be used bNodeTree.
* The quality is determined by the bNodeTree fields.
@@ -329,7 +329,7 @@ extern "C" {
void COM_execute(RenderData *render_data,
Scene *scene,
bNodeTree *node_tree,
int rendering,
bool rendering,
const char *view_name);
/**

View File

@@ -50,7 +50,7 @@ static void compositor_reset_node_tree_status(bNodeTree *node_tree)
void COM_execute(RenderData *render_data,
Scene *scene,
bNodeTree *node_tree,
int rendering,
bool rendering,
const char *view_name)
{
/* Initialize mutex, TODO: this mutex init is actually not thread safe and

View File

@@ -42,8 +42,17 @@ class Context {
public:
Context(TexturePool &texture_pool);
/* Get the active compositing scene. */
virtual const Scene *get_scene() const = 0;
/* Get the node tree used for compositing. */
virtual const bNodeTree &get_node_tree() const = 0;
/* True if compositor should do write file outputs, false if only running for viewing. */
virtual bool use_file_output() const = 0;
/* True if color management should be used for texture evaluation. */
virtual bool use_texture_color_management() const = 0;
/* Get the render settings for compositing. */
virtual const RenderData &get_render_data() const = 0;
/* Get the width and height of the render passes and of the output texture returned by the
* get_input_texture and get_output_texture methods respectively. */
@@ -63,7 +72,7 @@ class Context {
/* Get the texture where the given render pass is stored. This should be called by the Render
* Layer node to populate its outputs. */
virtual GPUTexture *get_input_texture(int view_layer, eScenePassType pass_type) = 0;
virtual GPUTexture *get_input_texture(int view_layer, const char *pass_name) = 0;
/* Get the name of the view currently being rendered. */
virtual StringRef get_view_name() = 0;

View File

@@ -13,7 +13,6 @@
#include "GPU_texture.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "COM_cached_resource.hh"
@@ -49,7 +48,7 @@ class CachedTexture : public CachedResource {
GPUTexture *value_texture_ = nullptr;
public:
CachedTexture(Tex *texture, const Scene *scene, int2 size, float2 offset, float2 scale);
CachedTexture(Tex *texture, bool use_color_management, int2 size, float2 offset, float2 scale);
~CachedTexture();
@@ -74,8 +73,12 @@ class CachedTextureContainer : CachedResourceContainer {
* CachedTexture cached resource with the given parameters in the container, if one exists,
* return it, otherwise, return a newly created one and add it to the container. In both cases,
* tag the cached resource as needed to keep it cached for the next evaluation. */
CachedTexture &get(
Context &context, Tex *texture, const Scene *scene, int2 size, float2 offset, float2 scale);
CachedTexture &get(Context &context,
Tex *texture,
bool use_color_management,
int2 size,
float2 offset,
float2 scale);
};
} // namespace blender::realtime_compositor

View File

@@ -51,7 +51,7 @@ bool operator==(const CachedTextureKey &a, const CachedTextureKey &b)
*/
CachedTexture::CachedTexture(
Tex *texture, const Scene *scene, int2 size, float2 offset, float2 scale)
Tex *texture, bool use_color_management, int2 size, float2 offset, float2 scale)
{
ImagePool *image_pool = BKE_image_pool_new();
BKE_texture_fetch_images_for_pool(texture, image_pool);
@@ -67,7 +67,8 @@ CachedTexture::CachedTexture(
/* Note that it is expected that the offset is scaled by the scale. */
coordinates = (coordinates + offset) * scale;
TexResult texture_result;
BKE_texture_get_value_ex(scene, texture, coordinates, &texture_result, image_pool, true);
BKE_texture_get_value_ex(
texture, coordinates, &texture_result, image_pool, use_color_management);
color_pixels[y * size.x + x] = float4(texture_result.trgba);
value_pixels[y * size.x + x] = texture_result.talpha ? texture_result.trgba[3] :
texture_result.tin;
@@ -131,8 +132,12 @@ void CachedTextureContainer::reset()
}
}
CachedTexture &CachedTextureContainer::get(
Context &context, Tex *texture, const Scene *scene, int2 size, float2 offset, float2 scale)
CachedTexture &CachedTextureContainer::get(Context &context,
Tex *texture,
bool use_color_management,
int2 size,
float2 offset,
float2 scale)
{
const CachedTextureKey key(size, offset, scale);
@@ -143,8 +148,9 @@ CachedTexture &CachedTextureContainer::get(
cached_textures_for_id.clear();
}
auto &cached_texture = *cached_textures_for_id.lookup_or_add_cb(
key, [&]() { return std::make_unique<CachedTexture>(texture, scene, size, offset, scale); });
auto &cached_texture = *cached_textures_for_id.lookup_or_add_cb(key, [&]() {
return std::make_unique<CachedTexture>(texture, use_color_management, size, offset, scale);
});
cached_texture.needed = true;
return cached_texture;

View File

@@ -23,18 +23,19 @@ int2 Context::get_compositing_region_size() const
float Context::get_render_percentage() const
{
return get_scene()->r.size / 100.0f;
return get_render_data().size / 100.0f;
}
int Context::get_frame_number() const
{
return get_scene()->r.cfra;
return get_render_data().cfra;
}
float Context::get_time() const
{
const float frame_number = float(get_frame_number());
const float frame_rate = float(get_scene()->r.frs_sec) / float(get_scene()->r.frs_sec_base);
const float frame_rate = float(get_render_data().frs_sec) /
float(get_render_data().frs_sec_base);
return frame_number / frame_rate;
}

View File

@@ -66,7 +66,7 @@ bool Evaluator::validate_node_tree()
void Evaluator::compile_and_evaluate()
{
derived_node_tree_ = std::make_unique<DerivedNodeTree>(*context_.get_scene()->nodetree);
derived_node_tree_ = std::make_unique<DerivedNodeTree>(context_.get_node_tree());
if (!validate_node_tree()) {
return;

View File

@@ -58,9 +58,24 @@ class Context : public realtime_compositor::Context {
{
}
const Scene *get_scene() const override
const bNodeTree &get_node_tree() const override
{
return DRW_context_state_get()->scene;
return *DRW_context_state_get()->scene->nodetree;
}
bool use_file_output() const override
{
return false;
}
bool use_texture_color_management() const override
{
return BKE_scene_check_color_management_enabled(DRW_context_state_get()->scene);
}
const RenderData &get_render_data() const override
{
return DRW_context_state_get()->scene->r;
}
int2 get_render_size() const override
@@ -130,15 +145,20 @@ class Context : public realtime_compositor::Context {
return DRW_viewport_texture_list_get()->color;
}
GPUTexture *get_input_texture(int /*view_layer*/, eScenePassType /*pass_type*/) override
GPUTexture *get_input_texture(int view_layer, const char *pass_name) override
{
return get_output_texture();
if (view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED)) {
return get_output_texture();
}
else {
return nullptr;
}
}
StringRef get_view_name() override
{
const SceneRenderView *view = static_cast<SceneRenderView *>(
BLI_findlink(&get_scene()->r.views, DRW_context_state_get()->v3d->multiview_eye));
BLI_findlink(&get_render_data().views, DRW_context_state_get()->v3d->multiview_eye));
return view->name;
}

View File

@@ -1086,7 +1086,7 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
/* Fill in image buffer. */
float *rect_float = rv->combined_buffer.data;
float tex_coord[3] = {0.0f, 0.0f, 0.0f};
bool color_manage = true;
bool color_manage = BKE_scene_check_color_management_enabled(sce);
for (int y = 0; y < height; y++) {
/* Tex coords between -1.0f and 1.0f. */
@@ -1097,7 +1097,7 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
/* Evaluate texture at tex_coord. */
TexResult texres = {0};
BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage);
BKE_texture_get_value_ex(tex, tex_coord, &texres, img_pool, color_manage);
copy_v4_fl4(rect_float,
texres.trgba[0],
texres.trgba[1],

View File

@@ -194,8 +194,7 @@ static void displaceModifier_do_task(void *__restrict userdata,
}
if (data->tex_target) {
BKE_texture_get_value_ex(
data->scene, data->tex_target, tex_co[iter], &texres, data->pool, false);
BKE_texture_get_value_ex(data->tex_target, tex_co[iter], &texres, data->pool, false);
delta = texres.tin - dmd->midlevel;
}
else {

View File

@@ -170,8 +170,7 @@ template<typename GridType> struct DisplaceOp {
openvdb::Vec3d evaluate_texture(const openvdb::Vec3f &pos) const
{
TexResult texture_result = {0};
BKE_texture_get_value(
nullptr, this->texture, const_cast<float *>(pos.asV()), &texture_result, false);
BKE_texture_get_value(this->texture, const_cast<float *>(pos.asV()), &texture_result, false);
return {texture_result.trgba[0], texture_result.trgba[1], texture_result.trgba[2]};
}
};

View File

@@ -299,9 +299,8 @@ static void warpModifier_do(WarpModifierData *wmd,
fac *= weight;
if (tex_co) {
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
TexResult texres;
BKE_texture_get_value(scene, tex_target, tex_co[i], &texres, false);
BKE_texture_get_value(tex_target, tex_co[i], &texres, false);
fac *= texres.tin;
}

View File

@@ -258,9 +258,8 @@ static void waveModifier_do(WaveModifierData *md,
/* Apply texture. */
if (tex_co) {
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
TexResult texres;
BKE_texture_get_value(scene, tex_target, tex_co[i], &texres, false);
BKE_texture_get_value(tex_target, tex_co[i], &texres, false);
amplit *= texres.tin;
}

View File

@@ -26,6 +26,7 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BKE_texture.h" /* Texture masking. */
#include "UI_interface.h"
@@ -160,11 +161,10 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
int idx = indices ? indices[i] : i;
TexResult texres;
float hsv[3]; /* For HSV color space. */
bool do_color_manage;
bool do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT &&
BKE_scene_check_color_management_enabled(scene);
do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT;
BKE_texture_get_value(scene, texture, tex_co[idx], &texres, do_color_manage);
BKE_texture_get_value(texture, tex_co[idx], &texres, do_color_manage);
/* Get the good channel value... */
switch (tex_use_channel) {
case MOD_WVG_MASK_TEX_USE_INT:

View File

@@ -30,7 +30,7 @@ void register_node_type_cmp_custom_group(bNodeType *ntype);
void ntreeCompositExecTree(struct Scene *scene,
struct bNodeTree *ntree,
struct RenderData *rd,
int rendering,
bool rendering,
int do_previews,
const char *view_name);

View File

@@ -174,7 +174,7 @@ void register_node_tree_type_cmp()
void ntreeCompositExecTree(Scene *scene,
bNodeTree *ntree,
RenderData *rd,
int rendering,
bool rendering,
int do_preview,
const char *view_name)
{

View File

@@ -825,7 +825,7 @@ class RenderLayerOperation : public NodeOperation {
void execute() override
{
const int view_layer = bnode().custom1;
GPUTexture *pass_texture = context().get_input_texture(view_layer, SCE_PASS_COMBINED);
GPUTexture *pass_texture = context().get_input_texture(view_layer, RE_PASSNAME_COMBINED);
execute_image(pass_texture);
execute_alpha(pass_texture);
@@ -848,6 +848,11 @@ class RenderLayerOperation : public NodeOperation {
if (!image_result.should_compute()) {
return;
}
if (pass_texture == nullptr) {
/* Pass not rendered (yet). */
image_result.allocate_invalid();
return;
}
GPUShader *shader = shader_manager().get("compositor_read_pass");
GPU_shader_bind(shader);
@@ -878,6 +883,11 @@ class RenderLayerOperation : public NodeOperation {
if (!alpha_result.should_compute()) {
return;
}
if (pass_texture == nullptr) {
/* Pass not rendered (yet). */
alpha_result.allocate_invalid();
return;
}
GPUShader *shader = shader_manager().get("compositor_read_pass_alpha");
GPU_shader_bind(shader);

View File

@@ -449,7 +449,9 @@ class OutputFileOperation : public NodeOperation {
void execute() override
{
context().set_info_message("Viewport compositor setup not fully supported");
if (context().use_file_output()) {
context().set_info_message("Viewport compositor setup not fully supported");
}
}
};

View File

@@ -57,7 +57,7 @@ class TextureOperation : public NodeOperation {
CachedTexture &cached_texture = context().cache_manager().cached_textures.get(
context(),
get_texture(),
context().get_scene(),
context().use_texture_color_management(),
domain.size,
get_input("Offset").get_vector_value_default(float4(0.0f)).xy(),
get_input("Scale").get_vector_value_default(float4(0.0f)).xy());