Refactor: Move tile highlight logic outside of Render
Allows to generalize the API a bit more, getting closer to a situation when RenderEngine::re points to a baseclass of the Render.
This commit is contained in:
committed by
Sergey Sharybin
parent
032bcd50f8
commit
76995feea0
@@ -40,6 +40,7 @@ set(SRC
|
||||
intern/texture_margin.cc
|
||||
intern/texture_pointdensity.c
|
||||
intern/texture_procedural.c
|
||||
intern/tile_highlight.cc
|
||||
intern/zbuf.c
|
||||
|
||||
RE_bake.h
|
||||
@@ -54,6 +55,7 @@ set(SRC
|
||||
intern/render_result.h
|
||||
intern/render_types.h
|
||||
intern/texture_common.h
|
||||
intern/tile_highlight.h
|
||||
intern/zbuf.h
|
||||
)
|
||||
|
||||
|
||||
@@ -303,45 +303,6 @@ static void render_result_to_bake(RenderEngine *engine, RenderResult *rr)
|
||||
|
||||
/* Render Results */
|
||||
|
||||
static HighlightedTile highlighted_tile_from_result_get(Render * /*re*/, RenderResult *result)
|
||||
{
|
||||
HighlightedTile tile;
|
||||
tile.rect = result->tilerect;
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
static void engine_tile_highlight_set(RenderEngine *engine,
|
||||
const HighlightedTile *tile,
|
||||
bool highlight)
|
||||
{
|
||||
if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Render *re = engine->re;
|
||||
|
||||
BLI_mutex_lock(&re->highlighted_tiles_mutex);
|
||||
|
||||
if (re->highlighted_tiles == nullptr) {
|
||||
re->highlighted_tiles = BLI_gset_new(
|
||||
BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "highlighted tiles");
|
||||
}
|
||||
|
||||
if (highlight) {
|
||||
HighlightedTile **tile_in_set;
|
||||
if (!BLI_gset_ensure_p_ex(re->highlighted_tiles, tile, (void ***)&tile_in_set)) {
|
||||
*tile_in_set = MEM_cnew<HighlightedTile>(__func__);
|
||||
**tile_in_set = *tile;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_gset_remove(re->highlighted_tiles, tile, MEM_freeN);
|
||||
}
|
||||
|
||||
BLI_mutex_unlock(&re->highlighted_tiles_mutex);
|
||||
}
|
||||
|
||||
RenderResult *RE_engine_begin_result(
|
||||
RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
|
||||
{
|
||||
@@ -457,9 +418,16 @@ void RE_engine_end_result(
|
||||
}
|
||||
|
||||
if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES)) {
|
||||
const HighlightedTile tile = highlighted_tile_from_result_get(re, result);
|
||||
blender::render::TilesHighlight *tile_highlight = re->get_tile_highlight();
|
||||
|
||||
engine_tile_highlight_set(engine, &tile, highlight);
|
||||
if (tile_highlight) {
|
||||
if (highlight) {
|
||||
tile_highlight->highlight_tile_for_result(result);
|
||||
}
|
||||
else {
|
||||
tile_highlight->unhighlight_tile_for_result(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancel || merge_results) {
|
||||
@@ -644,50 +612,18 @@ bool RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
|
||||
|
||||
const rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_free)
|
||||
{
|
||||
static rcti tiles_static[BLENDER_MAX_THREADS];
|
||||
const int allocation_step = BLENDER_MAX_THREADS;
|
||||
int total_tiles = 0;
|
||||
rcti *tiles = tiles_static;
|
||||
int allocation_size = BLENDER_MAX_THREADS;
|
||||
|
||||
BLI_mutex_lock(&re->highlighted_tiles_mutex);
|
||||
|
||||
*r_needs_free = false;
|
||||
|
||||
if (re->highlighted_tiles == nullptr) {
|
||||
blender::render::TilesHighlight *tiles_highlight = re->get_tile_highlight();
|
||||
if (!tiles_highlight) {
|
||||
*r_total_tiles = 0;
|
||||
BLI_mutex_unlock(&re->highlighted_tiles_mutex);
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
GSET_FOREACH_BEGIN (HighlightedTile *, tile, re->highlighted_tiles) {
|
||||
if (total_tiles >= allocation_size) {
|
||||
/* Just in case we're using crazy network rendering with more
|
||||
* workers than BLENDER_MAX_THREADS.
|
||||
*/
|
||||
allocation_size += allocation_step;
|
||||
if (tiles == tiles_static) {
|
||||
/* Can not realloc yet, tiles are pointing to a
|
||||
* stack memory.
|
||||
*/
|
||||
tiles = MEM_cnew_array<rcti>(allocation_size, "current engine tiles");
|
||||
}
|
||||
else {
|
||||
tiles = static_cast<rcti *>(MEM_reallocN(tiles, allocation_size * sizeof(rcti)));
|
||||
}
|
||||
*r_needs_free = true;
|
||||
}
|
||||
tiles[total_tiles] = tile->rect;
|
||||
blender::Span<rcti> highlighted_tiles = tiles_highlight->get_all_highlighted_tiles();
|
||||
|
||||
total_tiles++;
|
||||
}
|
||||
GSET_FOREACH_END();
|
||||
|
||||
BLI_mutex_unlock(&re->highlighted_tiles_mutex);
|
||||
|
||||
*r_total_tiles = total_tiles;
|
||||
|
||||
return tiles;
|
||||
*r_total_tiles = highlighted_tiles.size();
|
||||
return highlighted_tiles.data();
|
||||
}
|
||||
|
||||
RenderData *RE_engine_get_render_data(Render *re)
|
||||
@@ -1262,27 +1198,51 @@ void RE_engine_draw_release(Render *re)
|
||||
void RE_engine_tile_highlight_set(
|
||||
RenderEngine *engine, int x, int y, int width, int height, bool highlight)
|
||||
{
|
||||
HighlightedTile tile;
|
||||
BLI_rcti_init(&tile.rect, x, x + width, y, y + height);
|
||||
if (!engine->re) {
|
||||
/* No render on the engine, so nowhere to store the highlighted tiles information. */
|
||||
return;
|
||||
}
|
||||
if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
|
||||
/* Engine reported it does not support tiles highlight, but attempted to set the highlight.
|
||||
* Technically it is a logic error, but there is no good way to inform an external engine about
|
||||
* it. */
|
||||
return;
|
||||
}
|
||||
|
||||
engine_tile_highlight_set(engine, &tile, highlight);
|
||||
blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
|
||||
if (!tile_highlight) {
|
||||
/* The renderer itself does not support tiles highlight. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (highlight) {
|
||||
tile_highlight->highlight_tile(x, y, width, height);
|
||||
}
|
||||
else {
|
||||
tile_highlight->unhighlight_tile(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
|
||||
{
|
||||
if (!engine->re) {
|
||||
/* No render on the engine, so nowhere to store the highlighted tiles information. */
|
||||
return;
|
||||
}
|
||||
if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
|
||||
/* Engine reported it does not support tiles highlight, but attempted to set the highlight.
|
||||
* Technically it is a logic error, but there is no good way to inform an external engine about
|
||||
* it. */
|
||||
return;
|
||||
}
|
||||
|
||||
Render *re = engine->re;
|
||||
|
||||
BLI_mutex_lock(&re->highlighted_tiles_mutex);
|
||||
|
||||
if (re->highlighted_tiles != nullptr) {
|
||||
BLI_gset_clear(re->highlighted_tiles, MEM_freeN);
|
||||
blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
|
||||
if (!tile_highlight) {
|
||||
/* The renderer itself does not support tiles highlight. */
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_mutex_unlock(&re->highlighted_tiles_mutex);
|
||||
tile_highlight->clear();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -1820,21 +1820,6 @@ static void render_pipeline_free(Render *re)
|
||||
/* Destroy the opengl context in the correct thread. */
|
||||
RE_blender_gpu_context_free(re);
|
||||
RE_system_gpu_context_free(re);
|
||||
|
||||
/* In the case the engine did not mark tiles as finished (un-highlight, which could happen in
|
||||
* the case of cancelled render) ensure the storage is empty. */
|
||||
if (re->highlighted_tiles != nullptr) {
|
||||
BLI_mutex_lock(&re->highlighted_tiles_mutex);
|
||||
|
||||
/* Rendering is supposed to be finished here, so no new tiles are expected to be written.
|
||||
* Only make it so possible read-only access to the highlighted tiles is thread-safe. */
|
||||
BLI_assert(re->highlighted_tiles);
|
||||
|
||||
BLI_gset_free(re->highlighted_tiles, MEM_freeN);
|
||||
re->highlighted_tiles = nullptr;
|
||||
|
||||
BLI_mutex_unlock(&re->highlighted_tiles_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void RE_RenderFrame(Render *re,
|
||||
|
||||
@@ -36,14 +36,9 @@ Render::~Render()
|
||||
RE_blender_gpu_context_free(this);
|
||||
RE_system_gpu_context_free(this);
|
||||
|
||||
BLI_mutex_end(&highlighted_tiles_mutex);
|
||||
BLI_mutex_end(&gpu_compositor_mutex);
|
||||
|
||||
BKE_curvemapping_free_data(&r.mblur_shutter_curve);
|
||||
|
||||
if (highlighted_tiles != nullptr) {
|
||||
BLI_gset_free(highlighted_tiles, MEM_freeN);
|
||||
}
|
||||
|
||||
render_result_free(pushedresult);
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "RE_compositor.hh"
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "tile_highlight.h"
|
||||
|
||||
struct Depsgraph;
|
||||
struct GSet;
|
||||
struct Main;
|
||||
@@ -26,14 +28,15 @@ struct Object;
|
||||
struct RenderEngine;
|
||||
struct ReportList;
|
||||
|
||||
struct HighlightedTile {
|
||||
rcti rect;
|
||||
};
|
||||
|
||||
struct BaseRender {
|
||||
BaseRender() = default;
|
||||
virtual ~BaseRender();
|
||||
|
||||
/* Get class which manages highlight of tiles.
|
||||
* Note that it might not exist: for example, viewport render does not support the tile
|
||||
* highlight. */
|
||||
virtual blender::render::TilesHighlight *get_tile_highlight() = 0;
|
||||
|
||||
/* Result of rendering */
|
||||
RenderResult *result = nullptr;
|
||||
|
||||
@@ -50,6 +53,10 @@ struct BaseRender {
|
||||
};
|
||||
|
||||
struct ViewRender : public BaseRender {
|
||||
blender::render::TilesHighlight *get_tile_highlight() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/* Controls state of render, everything that's read-only during render stage */
|
||||
@@ -59,6 +66,11 @@ struct Render : public BaseRender {
|
||||
Render() = default;
|
||||
virtual ~Render();
|
||||
|
||||
blender::render::TilesHighlight *get_tile_highlight() override
|
||||
{
|
||||
return &tile_highlight;
|
||||
}
|
||||
|
||||
char name[RE_MAXNAME] = "";
|
||||
int slot = 0;
|
||||
|
||||
@@ -97,8 +109,7 @@ struct Render : public BaseRender {
|
||||
char single_view_layer[MAX_NAME] = "";
|
||||
struct Object *camera_override = nullptr;
|
||||
|
||||
ThreadMutex highlighted_tiles_mutex = BLI_MUTEX_INITIALIZER;
|
||||
struct GSet *highlighted_tiles = nullptr;
|
||||
blender::render::TilesHighlight tile_highlight;
|
||||
|
||||
/* NOTE: This is a minimal dependency graph and evaluated scene which is enough to access view
|
||||
* layer visibility and use for postprocessing (compositor and sequencer). */
|
||||
|
||||
102
source/blender/render/intern/tile_highlight.cc
Normal file
102
source/blender/render/intern/tile_highlight.cc
Normal file
@@ -0,0 +1,102 @@
|
||||
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup render
|
||||
*/
|
||||
|
||||
#include "tile_highlight.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash.hh"
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
namespace blender::render {
|
||||
|
||||
TilesHighlight::Tile::Tile(const RenderResult *result) : rect(result->tilerect) {}
|
||||
|
||||
TilesHighlight::Tile::Tile(const int x, const int y, const int width, const int height)
|
||||
{
|
||||
BLI_rcti_init(&rect, x, x + width, y, y + height);
|
||||
}
|
||||
|
||||
uint64_t TilesHighlight::Tile::hash() const
|
||||
{
|
||||
return get_default_hash_4(rect.xmin, rect.xmax, rect.ymin, rect.ymax);
|
||||
}
|
||||
|
||||
void TilesHighlight::highlight_tile_for_result(const RenderResult *result)
|
||||
{
|
||||
const Tile tile(result);
|
||||
highlight_tile(tile);
|
||||
}
|
||||
|
||||
void TilesHighlight::unhighlight_tile_for_result(const RenderResult *result)
|
||||
{
|
||||
const Tile tile(result);
|
||||
unhighlight_tile(tile);
|
||||
}
|
||||
|
||||
void TilesHighlight::highlight_tile(const int x, const int y, const int width, const int height)
|
||||
{
|
||||
const Tile tile(x, y, width, height);
|
||||
highlight_tile(tile);
|
||||
}
|
||||
|
||||
void TilesHighlight::unhighlight_tile(const int x, const int y, const int width, const int height)
|
||||
{
|
||||
const Tile tile(x, y, width, height);
|
||||
unhighlight_tile(tile);
|
||||
}
|
||||
|
||||
void TilesHighlight::highlight_tile(const Tile &tile)
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
highlighted_tiles_set_.add(tile);
|
||||
did_tiles_change_ = true;
|
||||
}
|
||||
|
||||
void TilesHighlight::unhighlight_tile(const Tile &tile)
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
highlighted_tiles_set_.remove(tile);
|
||||
did_tiles_change_ = true;
|
||||
}
|
||||
|
||||
void TilesHighlight::clear()
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
highlighted_tiles_set_.clear();
|
||||
cached_highlighted_tiles_.clear_and_shrink();
|
||||
}
|
||||
|
||||
Span<rcti> TilesHighlight::get_all_highlighted_tiles() const
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
/* Updated cached flat list if needed. */
|
||||
if (did_tiles_change_) {
|
||||
if (highlighted_tiles_set_.is_empty()) {
|
||||
cached_highlighted_tiles_.clear_and_shrink();
|
||||
}
|
||||
else {
|
||||
cached_highlighted_tiles_.reserve(highlighted_tiles_set_.size());
|
||||
for (const Tile &tile : highlighted_tiles_set_) {
|
||||
cached_highlighted_tiles_.append(tile.rect);
|
||||
}
|
||||
}
|
||||
|
||||
did_tiles_change_ = false;
|
||||
}
|
||||
|
||||
return cached_highlighted_tiles_;
|
||||
}
|
||||
|
||||
} // namespace blender::render
|
||||
67
source/blender/render/intern/tile_highlight.h
Normal file
67
source/blender/render/intern/tile_highlight.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup render
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
struct RenderResult;
|
||||
|
||||
namespace blender::render {
|
||||
|
||||
class TilesHighlight {
|
||||
public:
|
||||
TilesHighlight() = default;
|
||||
~TilesHighlight() = default;
|
||||
|
||||
void highlight_tile_for_result(const RenderResult *result);
|
||||
void unhighlight_tile_for_result(const RenderResult *result);
|
||||
|
||||
void highlight_tile(int x, int y, int width, int height);
|
||||
void unhighlight_tile(int x, int y, int width, int height);
|
||||
|
||||
void clear();
|
||||
|
||||
Span<rcti> get_all_highlighted_tiles() const;
|
||||
|
||||
private:
|
||||
struct Tile {
|
||||
Tile() = default;
|
||||
explicit Tile(const RenderResult *result);
|
||||
explicit Tile(int x, int y, int width, int height);
|
||||
|
||||
uint64_t hash() const;
|
||||
|
||||
inline bool operator==(const Tile &other) const
|
||||
{
|
||||
return rect == other.rect;
|
||||
}
|
||||
inline bool operator!=(const Tile &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
rcti rect = {0, 0, 0, 0};
|
||||
};
|
||||
|
||||
void highlight_tile(const Tile &tile);
|
||||
void unhighlight_tile(const Tile &tile);
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
Set<Tile> highlighted_tiles_set_;
|
||||
|
||||
/* Cached flat list of currently highlighted tiles for a fast access via API. */
|
||||
mutable bool did_tiles_change_ = false;
|
||||
mutable Vector<rcti> cached_highlighted_tiles_;
|
||||
};
|
||||
|
||||
} // namespace blender::render
|
||||
Reference in New Issue
Block a user