Realtime Compositor: Implement zero cost external images #115574

Merged
Omar Emara merged 1 commits from OmarEmaraDev/blender:compositor-result-wrao into main 2023-11-30 09:10:53 +01:00
5 changed files with 36 additions and 11 deletions
Showing only changes of commit fa96497999 - Show all commits

View File

@ -72,7 +72,11 @@ enum class ResultPrecision : uint8_t {
* the results of identity operations, that is, operations that do nothing to their inputs in
* certain configurations. In which case, the proxy result is left as is with no extra
* transformation on its domain whatsoever. Proxy results can be created by calling the
* pass_through method, see that method for more details. */
* pass_through method, see that method for more details.
*
* A result can wrap an external texture that is not allocated nor managed by the result. This is
* set up by a call to the wrap_external method. In that case, when the reference count eventually
* reach zero, the texture will not be freed. */
class Result {
private:
/* The base type of the result's texture or single value. */
@ -120,6 +124,10 @@ class Result {
* calling the pass_through method, which sets this result to be the master of a target result.
* See that method for more information. */
Result *master_ = nullptr;
/* If true, then the result wraps an external texture that is not allocated nor managed by the
* result. This is set up by a call to the wrap_external method. In that case, when the reference
* count eventually reach zero, the texture will not be freed. */
bool is_external_ = false;
public:
/* Construct a result of the given type and precision with the given texture pool that will be
@ -203,6 +211,13 @@ class Result {
* a practical example of use. */
void steal_data(Result &source);
/* Set up the result to wrap an external texture that is not allocated nor managed by the result.
* The is_external_ member will be set to true, the domain will be set to have the same size as
* the texture, and the texture will be set to the given texture. See the is_external_ member for
* more information. The given texture should have the same format as the result and is assumed
* to have a lifetime that covers the evaluation of the compositor. */
void wrap_external(GPUTexture *texture);
/* Sets the transformation of the domain of the result to the given transformation. */
void set_transformation(const float3x3 &transformation);

View File

@ -192,6 +192,19 @@ void Result::steal_data(Result &source)
source.texture_pool_ = nullptr;
}
void Result::wrap_external(GPUTexture *texture)
{
const eGPUTextureFormat texture_format = GPU_texture_format(texture);
BLI_assert(texture_format == get_texture_format());
BLI_assert(!is_allocated());
BLI_assert(!master_);
texture_ = texture;
is_external_ = true;
is_single_value_ = false;
domain_ = Domain(int2(GPU_texture_width(texture), GPU_texture_height(texture)));
}
void Result::set_transformation(const float3x3 &transformation)
{
domain_.transformation = transformation;
@ -298,7 +311,9 @@ void Result::release()
* texture pool. */
reference_count_--;
if (reference_count_ == 0) {
texture_pool_->release(texture_);
if (!is_external_) {
texture_pool_->release(texture_);
}
texture_ = nullptr;
}
}

View File

@ -108,9 +108,7 @@ class KeyingScreenOperation : public NodeOperation {
KeyingScreen &cached_keying_screen = context().cache_manager().keying_screens.get(
context(), get_movie_clip(), movie_tracking_object, get_smoothness());
const Domain domain = compute_domain();
keying_screen.allocate_texture(domain);
GPU_texture_copy(keying_screen.texture(), cached_keying_screen.texture());
keying_screen.wrap_external(cached_keying_screen.texture());
}
Domain compute_domain() override

View File

@ -101,8 +101,7 @@ class MaskOperation : public NodeOperation {
get_motion_blur_samples(),
get_motion_blur_shutter());
output_mask.allocate_texture(domain);
GPU_texture_copy(output_mask.texture(), cached_mask.texture());
output_mask.wrap_external(cached_mask.texture());
}
Domain compute_domain() override

View File

@ -63,13 +63,11 @@ class TextureOperation : public NodeOperation {
get_input("Scale").get_vector_value_default(float4(0.0f)).xy());
if (color_result.should_compute()) {
color_result.allocate_texture(domain);
GPU_texture_copy(color_result.texture(), cached_texture.color_texture());
color_result.wrap_external(cached_texture.color_texture());
}
if (value_result.should_compute()) {
value_result.allocate_texture(domain);
GPU_texture_copy(value_result.texture(), cached_texture.value_texture());
value_result.wrap_external(cached_texture.value_texture());
}
}