Compositor: Support CPU storage in result class

This patch adds support for CPU side buffers for the result class. A new
storage type member was added to identify the type of buffer storage,
and allocation will either allocate a GPU texture or a CPU buffer based
on the context's GPU usage.
This commit is contained in:
Omar Emara
2024-08-13 16:13:22 +03:00
parent 81d78e3416
commit edc4d0d84a
37 changed files with 559 additions and 266 deletions

View File

@@ -17,7 +17,7 @@ namespace blender::realtime_compositor {
class Context;
/* To add a new type, update the format related static methods in the Result class. */
/* Make sure to update the format related static methods in the Result class. */
enum class ResultType : uint8_t {
/* The following types are user facing and can be used as inputs and outputs of operations. They
* either represent the base type of the result texture or a single value result. The color type
@@ -29,19 +29,29 @@ enum class ResultType : uint8_t {
Color,
/* The following types are for internal use only, not user facing, and can't be used as inputs
* and outputs of operations. Furthermore, they can't be single values and thus always need to be
* allocated as textures. It follows that they needn't be handled in implicit operations like
* and outputs of operations. It follows that they needn't be handled in implicit operations like
* type conversion, shader, or single value reduction operations. */
Float2,
Float3,
Int2,
};
/* The precision of the data. CPU data is always stored using full precision at the moment. */
enum class ResultPrecision : uint8_t {
Full,
Half,
};
/* The type of storage used to hold the result data. */
enum class ResultStorageType : uint8_t {
/* Stored as a GPUTexture on the GPU. */
GPU,
/* Stored as a contiguous float buffer the CPU. */
FloatCPU,
/* Stored as a contiguous integer buffer the CPU. */
IntegerCPU,
};
/* ------------------------------------------------------------------------------------------------
* Result
*
@@ -91,10 +101,16 @@ class Result {
ResultPrecision precision_ = ResultPrecision::Half;
/* If true, the result is a single value, otherwise, the result is a texture. */
bool is_single_value_ = false;
/* A GPU texture storing the result data. This will be a 1x1 texture if the result is a single
* value, the value of which will be identical to that of the value member. See class description
* for more information. */
GPUTexture *texture_ = nullptr;
/* The type of storage used to hold the data. Used to correctly interpret the data union. */
ResultStorageType storage_type_ = ResultStorageType::GPU;
/* A texture storing the result pixel data, either stored in a GPU texture or a raw contagious
* array on CPU. This will be a 1x1 texture if the result is a single value, the value of which
* will be identical to that of the value member. See class description for more information. */
union {
GPUTexture *gpu_texture_ = nullptr;
float *float_texture_;
int *integer_texture_;
};
/* The number of operations that currently needs this result. At the time when the result is
* computed, this member will have a value that matches initial_reference_count_. Once each
* operation that needs the result no longer needs it, the release method is called and the
@@ -116,6 +132,9 @@ class Result {
float float_value_;
float4 vector_value_;
float4 color_value_ = float4(0.0f);
float2 float2_value_;
float3 float3_value_;
int2 int2_value_;
};
/* The domain of the result. This only matters if the result was a texture. See the discussion in
* COM_domain.hh for more information. */
@@ -144,20 +163,24 @@ class Result {
/* Construct a result of the given type and precision within the given context. */
Result(Context &context, ResultType type, ResultPrecision precision);
/* Returns the appropriate texture format based on the given result type and precision. */
static eGPUTextureFormat texture_format(ResultType type, ResultPrecision precision);
/* Returns the appropriate GPU texture format based on the given result type and precision. */
static eGPUTextureFormat gpu_texture_format(ResultType type, ResultPrecision precision);
/* Returns the texture format that corresponds to the give one, but with the given precision. */
static eGPUTextureFormat texture_format(eGPUTextureFormat format, ResultPrecision precision);
/* Returns the GPU texture format that corresponds to the give one, but whose precision is the
* given precision. */
static eGPUTextureFormat gpu_texture_format(eGPUTextureFormat format, ResultPrecision precision);
/* Returns the precision of the given format. */
/* Returns the precision of the given GPU texture format. */
static ResultPrecision precision(eGPUTextureFormat format);
/* Returns the type of the given format. */
/* Returns the type of the given GPU texture format. */
static ResultType type(eGPUTextureFormat format);
/* Implicit conversion to the internal GPU texture. */
operator GPUTexture *() const;
/* Returns the appropriate texture format based on the result's type and precision. */
eGPUTextureFormat get_texture_format() const;
eGPUTextureFormat get_gpu_texture_format() const;
/* Declare the result to be a texture result, allocate a texture of an appropriate type with
* the size of the given domain, and set the domain of the result to the given domain.
@@ -168,6 +191,9 @@ class Result {
* be used for most other cases where the result will be allocated then later released in the
* same evaluation.
*
* If the context of the result uses GPU, then GPU allocation will be done, otherwise, CPU
* allocation will be done.
*
* If the result should not be computed, that is, should_compute() returns false, yet this method
* is called, that means the result is only being allocated because the shader that computes it
* also computes another result that is actually needed, and shaders needs to have a texture
@@ -181,7 +207,7 @@ class Result {
void allocate_texture(Domain domain, bool from_pool = true);
/* Declare the result to be a single value result, allocate a texture of an appropriate type with
* size 1x1 from the texture pool, and set the domain to be an identity domain. See class
* size 1x1 from the texture pool, and set the domain to be an identity domain. See class
* description for more information. */
void allocate_single_value();
@@ -189,20 +215,20 @@ class Result {
* value can't be computed and are considered invalid. */
void allocate_invalid();
/* Bind the texture of the result to the texture image unit with the given name in the currently
* bound given shader. This also inserts a memory barrier for texture fetches to ensure any prior
* writes to the texture are reflected before reading from it. */
/* Bind the GPU texture of the result to the texture image unit with the given name in the
* currently bound given shader. This also inserts a memory barrier for texture fetches to ensure
* any prior writes to the texture are reflected before reading from it. */
void bind_as_texture(GPUShader *shader, const char *texture_name) const;
/* Bind the texture of the result to the image unit with the given name in the currently bound
* given shader. If read is true, a memory barrier will be inserted for image reads to ensure any
* prior writes to the images are reflected before reading from it. */
/* Bind the GPU texture of the result to the image unit with the given name in the currently
* bound given shader. If read is true, a memory barrier will be inserted for image reads to
* ensure any prior writes to the images are reflected before reading from it. */
void bind_as_image(GPUShader *shader, const char *image_name, bool read = false) const;
/* Unbind the texture which was previously bound using bind_as_texture. */
/* Unbind the GPU texture which was previously bound using bind_as_texture. */
void unbind_as_texture() const;
/* Unbind the texture which was previously bound using bind_as_image. */
/* Unbind the GPU texture which was previously bound using bind_as_image. */
void unbind_as_image() const;
/* Pass this result through to a target result, in which case, the target result becomes a proxy
@@ -230,13 +256,19 @@ 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. */
/* Set up the result to wrap an external GPU 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);
/* Identical to GPU variant of wrap_external but wraps a float buffer instead. */
void wrap_external(float *texture, int2 size);
/* Identical to GPU variant of wrap_external but wraps an integer buffer instead. */
void wrap_external(int *texture, int2 size);
/* Sets the transformation of the domain of the result to the given transformation. */
void set_transformation(const float3x3 &transformation);
@@ -248,38 +280,31 @@ class Result {
* for more information. */
RealizationOptions &get_realization_options();
/* If the result is a single value result of type float, return its float value. Otherwise, an
* uninitialized value is returned. */
/* Returns the single value of the result. */
float get_float_value() const;
/* If the result is a single value result of type vector, return its vector value. Otherwise, an
* uninitialized value is returned. */
float4 get_vector_value() const;
/* If the result is a single value result of type color, return its color value. Otherwise, an
* uninitialized value is returned. */
float4 get_color_value() const;
float2 get_float2_value() const;
float3 get_float3_value() const;
int2 get_int2_value() const;
/* Same as get_float_value but returns a default value if the result is not a single value. */
/* Returns the single value of the result, but returns a default value if the result is not a
* single value result. */
float get_float_value_default(float default_value) const;
/* Same as get_vector_value but returns a default value if the result is not a single value. */
float4 get_vector_value_default(const float4 &default_value) const;
/* Same as get_color_value but returns a default value if the result is not a single value. */
float4 get_color_value_default(const float4 &default_value) const;
float2 get_float2_value_default(const float2 &default_value) const;
float3 get_float3_value_default(const float3 &default_value) const;
int2 get_int2_value_default(const int2 &default_value) const;
/* If the result is a single value result of type float, set its float value and upload it to the
* texture. Otherwise, an undefined behavior is invoked. */
/* Set the single value of the result to the given value, which also involves setting the single
* pixel in the texture to that value. See the class description for more information. */
void set_float_value(float value);
/* If the result is a single value result of type vector, set its vector value and upload it to
* the texture. Otherwise, an undefined behavior is invoked. */
void set_vector_value(const float4 &value);
/* If the result is a single value result of type color, set its color value and upload it to the
* texture. Otherwise, an undefined behavior is invoked. */
void set_color_value(const float4 &value);
void set_float2_value(const float2 &value);
void set_float3_value(const float3 &value);
void set_int2_value(const int2 &value);
/* Set the value of initial_reference_count_, see that member for more details. This should be
* called after constructing the result to declare the number of operations that needs it. */
@@ -296,10 +321,9 @@ class Result {
* result, the reference count of the master result is incremented instead. */
void increment_reference_count(int count = 1);
/* Decrement the reference count of the result and release the its texture back into the texture
* pool if the reference count reaches zero. This should be called when an operation that used
* this result no longer needs it. If this result have a master result, the master result is
* released instead. */
/* Decrement the reference count of the result and free its texture if the reference count
* reaches zero. This should be called when an operation that used this result no longer needs
* it. If this result have a master result, the master result is released instead. */
void release();
/* Returns true if this result should be computed and false otherwise. The result should be
@@ -316,24 +340,23 @@ class Result {
/* Sets the precision of the result. */
void set_precision(ResultPrecision precision);
/* Returns true if the result is a texture and false of it is a single value. */
bool is_texture() const;
/* Returns true if the result is a single value and false of it is a texture. */
bool is_single_value() const;
/* Returns true if the result is allocated. */
bool is_allocated() const;
/* Returns the allocated GPU texture of the result. */
GPUTexture *texture() const;
/* Returns the reference count of the result. If this result have a master result, then the
* reference count of the master result is returned instead. */
int reference_count() const;
/* Returns a reference to the domain of the result. See the Domain class. */
const Domain &domain() const;
private:
/* Allocates the texture data for the given size, either on the GPU or CPU based on the result's
* context. See the allocate_texture method for information about the from_pool argument. */
void allocate_data(int2 size, bool from_pool);
};
} // namespace blender::realtime_compositor

View File

@@ -87,7 +87,10 @@ float sum_red(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -101,7 +104,10 @@ float sum_green(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -115,7 +121,10 @@ float sum_blue(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -131,7 +140,10 @@ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coef
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -147,7 +159,10 @@ float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -161,7 +176,10 @@ float4 sum_color(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Color, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Color, ResultPrecision::Full));
const float4 sum = float4(reduced_value);
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -182,7 +200,10 @@ float sum_red_squared_difference(Context &context, GPUTexture *texture, float su
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -199,7 +220,10 @@ float sum_green_squared_difference(Context &context, GPUTexture *texture, float
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -216,7 +240,10 @@ float sum_blue_squared_difference(Context &context, GPUTexture *texture, float s
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -237,7 +264,10 @@ float sum_luminance_squared_difference(Context &context,
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -257,7 +287,10 @@ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float maximum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -271,7 +304,10 @@ float maximum_float(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float maximum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -292,7 +328,10 @@ float maximum_float_in_range(Context &context,
GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float maximum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -312,7 +351,10 @@ float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float minimum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -326,7 +368,10 @@ float minimum_float(Context &context, GPUTexture *texture)
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float minimum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
@@ -347,7 +392,10 @@ float minimum_float_in_range(Context &context,
GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
float *reduced_value = parallel_reduction_dispatch(
context, texture, shader, Result::texture_format(ResultType::Float, ResultPrecision::Full));
context,
texture,
shader,
Result::gpu_texture_format(ResultType::Float, ResultPrecision::Full));
const float minimum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();

View File

@@ -104,14 +104,14 @@ void realize_on_domain(Context &context,
* interpolation. */
const bool use_bilinear = ELEM(
realization_options.interpolation, Interpolation::Bilinear, Interpolation::Bicubic);
GPU_texture_filter_mode(input.texture(), use_bilinear);
GPU_texture_filter_mode(input, use_bilinear);
/* If the input wraps, set a repeating wrap mode for out-of-bound texture access. Otherwise,
* make out-of-bound texture access return zero by setting a clamp to border extend mode. */
GPU_texture_extend_mode_x(input.texture(),
GPU_texture_extend_mode_x(input,
realization_options.wrap_x ? GPU_SAMPLER_EXTEND_MODE_REPEAT :
GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_extend_mode_y(input.texture(),
GPU_texture_extend_mode_y(input,
realization_options.wrap_y ? GPU_SAMPLER_EXTEND_MODE_REPEAT :
GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);

View File

@@ -67,7 +67,7 @@ static Result detect_edges(Context &context,
GPU_shader_uniform_1f(
shader, "smaa_local_contrast_adaptation_factor", local_contrast_adaptation_factor);
GPU_texture_filter_mode(input.texture(), true);
GPU_texture_filter_mode(input, true);
input.bind_as_texture(shader, "input_tx");
Result edges = context.create_result(ResultType::Color);
@@ -90,7 +90,7 @@ static Result calculate_blending_weights(Context &context, Result &edges, int co
GPU_shader_uniform_1i(shader, "smaa_corner_rounding", corner_rounding);
GPU_texture_filter_mode(edges.texture(), true);
GPU_texture_filter_mode(edges, true);
edges.bind_as_texture(shader, "edges_tx");
const SMAAPrecomputedTextures &smaa_precomputed_textures =
@@ -140,10 +140,10 @@ static void blend_neighborhood(Context &context, Result &input, Result &weights,
GPUShader *shader = context.get_shader(get_blend_shader_name(input.type()));
GPU_shader_bind(shader);
GPU_texture_filter_mode(input.texture(), true);
GPU_texture_filter_mode(input, true);
input.bind_as_texture(shader, "input_tx");
GPU_texture_filter_mode(weights.texture(), true);
GPU_texture_filter_mode(weights, true);
weights.bind_as_texture(shader, "weights_tx");
output.allocate_texture(input.domain());

View File

@@ -142,7 +142,7 @@ CachedMask::CachedMask(Context &context,
size.x,
size.y,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_SHADER_READ,
evaluated_mask.data());
}

View File

@@ -55,7 +55,7 @@ CachedShader::CachedShader(const char *info_name, ResultPrecision precision)
if (resource.bind_type != ShaderCreateInfo::Resource::BindType::IMAGE) {
continue;
}
resource.image.format = Result::texture_format(resource.image.format, precision);
resource.image.format = Result::gpu_texture_format(resource.image.format, precision);
}
shader_ = GPU_shader_create_from_info(reinterpret_cast<const GPUShaderCreateInfo *>(&info));

View File

@@ -96,7 +96,7 @@ CachedTexture::CachedTexture(Context &context,
size.x,
size.y,
1,
Result::texture_format(ResultType::Color, context.get_precision()),
Result::gpu_texture_format(ResultType::Color, context.get_precision()),
GPU_TEXTURE_USAGE_SHADER_READ,
*color_pixels.data());
@@ -105,7 +105,7 @@ CachedTexture::CachedTexture(Context &context,
size.x,
size.y,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_SHADER_READ,
value_pixels.data());
}

View File

@@ -93,7 +93,7 @@ DistortionGrid::DistortionGrid(
size.x,
size.y,
1,
Result::texture_format(ResultType::Float2, context.get_precision()),
Result::gpu_texture_format(ResultType::Float2, context.get_precision()),
GPU_TEXTURE_USAGE_SHADER_READ,
*distortion_grid.data());
}

View File

@@ -173,7 +173,7 @@ KeyingScreen::KeyingScreen(Context &context,
size.x,
size.y,
1,
Result::texture_format(ResultType::Color, context.get_precision()),
Result::gpu_texture_format(ResultType::Color, context.get_precision()),
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE,
nullptr);
const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");

View File

@@ -96,7 +96,7 @@ void MorphologicalDistanceFeatherWeights::compute_weights(Context &context, int
"Weights",
size,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_GENERAL,
weights.data());
}
@@ -147,7 +147,7 @@ void MorphologicalDistanceFeatherWeights::compute_distance_falloffs(Context &con
"Distance Factors",
size,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_GENERAL,
falloffs.data());
}

View File

@@ -233,7 +233,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
GPUTexture *texture;
const ResultType result_type = (channel == TEXTURE_RGB_CHANNEL) ? ResultType::Float3 :
ResultType::Float;
const eGPUTextureFormat texture_format = Result::texture_format(result_type, precision_);
const eGPUTextureFormat texture_format = Result::gpu_texture_format(result_type, precision_);
/* A height of 1 indicates a 1D texture according to the OCIO API. */
# if OCIO_VERSION_HEX >= 0x02030000
if (dimensions == OCIO::GpuShaderDesc::TEXTURE_1D) {
@@ -276,7 +276,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
size,
size,
1,
Result::texture_format(ResultType::Float3, precision_),
Result::gpu_texture_format(ResultType::Float3, precision_),
GPU_TEXTURE_USAGE_SHADER_READ,
values);
GPU_texture_filter_mode(texture, interpolation != OCIO::INTERP_NEAREST);
@@ -309,7 +309,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
shader_create_info_.local_group_size(16, 16);
shader_create_info_.sampler(0, ImageType::FLOAT_2D, input_sampler_name());
shader_create_info_.image(0,
Result::texture_format(ResultType::Color, precision_),
Result::gpu_texture_format(ResultType::Color, precision_),
Qualifier::WRITE,
ImageType::FLOAT_2D,
output_image_name());

View File

@@ -103,7 +103,7 @@ SymmetricBlurWeights::SymmetricBlurWeights(Context &context, int type, float2 ra
size.x,
size.y,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_GENERAL,
weights.data());
}

View File

@@ -81,7 +81,7 @@ SymmetricSeparableBlurWeights::SymmetricSeparableBlurWeights(Context &context,
"Weights",
size,
1,
Result::texture_format(ResultType::Float, context.get_precision()),
Result::gpu_texture_format(ResultType::Float, context.get_precision()),
GPU_TEXTURE_USAGE_GENERAL,
weights.data());
GPU_texture_filter_mode(texture_, true);

View File

@@ -31,7 +31,7 @@ void ReduceToSingleValueOperation::execute()
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
const Result &input = get_input();
float *pixel = static_cast<float *>(GPU_texture_read(input.texture(), GPU_DATA_FLOAT, 0));
float *pixel = static_cast<float *>(GPU_texture_read(input, GPU_DATA_FLOAT, 0));
Result &result = get_result();
result.allocate_single_value();

View File

@@ -2,8 +2,11 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "MEM_guardedalloc.h"
#include "BLI_assert.h"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "GPU_shader.hh"
@@ -21,7 +24,7 @@ Result::Result(Context &context, ResultType type, ResultPrecision precision)
{
}
eGPUTextureFormat Result::texture_format(ResultType type, ResultPrecision precision)
eGPUTextureFormat Result::gpu_texture_format(ResultType type, ResultPrecision precision)
{
switch (precision) {
case ResultPrecision::Half:
@@ -60,7 +63,7 @@ eGPUTextureFormat Result::texture_format(ResultType type, ResultPrecision precis
return GPU_RGBA32F;
}
eGPUTextureFormat Result::texture_format(eGPUTextureFormat format, ResultPrecision precision)
eGPUTextureFormat Result::gpu_texture_format(eGPUTextureFormat format, ResultPrecision precision)
{
switch (precision) {
case ResultPrecision::Half:
@@ -166,9 +169,15 @@ ResultType Result::type(eGPUTextureFormat format)
return ResultType::Color;
}
eGPUTextureFormat Result::get_texture_format() const
Result::operator GPUTexture *() const
{
return Result::texture_format(type_, precision_);
BLI_assert(storage_type_ == ResultStorageType::GPU);
return gpu_texture_;
}
eGPUTextureFormat Result::get_gpu_texture_format() const
{
return Result::gpu_texture_format(type_, precision_);
}
void Result::allocate_texture(Domain domain, bool from_pool)
@@ -182,39 +191,16 @@ void Result::allocate_texture(Domain domain, bool from_pool)
}
is_single_value_ = false;
if (context_->use_gpu()) {
is_from_pool_ = from_pool;
if (from_pool) {
texture_ = context_->texture_pool().acquire(domain.size, get_texture_format());
}
else {
texture_ = GPU_texture_create_2d("Compositor Texture",
domain.size.x,
domain.size.y,
1,
this->get_texture_format(),
GPU_TEXTURE_USAGE_GENERAL,
nullptr);
}
}
else {
/* TODO: Host side allocation. */
}
this->allocate_data(domain.size, from_pool);
domain_ = domain;
}
void Result::allocate_single_value()
{
/* Single values are stored in 1x1 textures as well as the single value members. Further, they
* are always allocated from the pool. */
is_single_value_ = true;
/* Single values are stored in 1x1 textures as well as the single value members. */
const int2 texture_size{1, 1};
if (context_->use_gpu()) {
is_from_pool_ = true;
texture_ = context_->texture_pool().acquire(texture_size, get_texture_format());
}
else {
/* TODO: Host side allocation. */
}
this->allocate_data(int2(1), true);
domain_ = Domain::identity();
}
@@ -231,41 +217,52 @@ void Result::allocate_invalid()
case ResultType::Color:
set_color_value(float4(0.0f));
break;
default:
/* Other types are internal and do not support single values. */
BLI_assert_unreachable();
case ResultType::Float2:
set_float2_value(float2(0.0f));
break;
case ResultType::Float3:
set_float3_value(float3(0.0f));
break;
case ResultType::Int2:
set_int2_value(int2(0));
break;
}
}
void Result::bind_as_texture(GPUShader *shader, const char *texture_name) const
{
BLI_assert(storage_type_ == ResultStorageType::GPU);
/* Make sure any prior writes to the texture are reflected before reading from it. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name);
GPU_texture_bind(texture_, texture_image_unit);
GPU_texture_bind(gpu_texture_, texture_image_unit);
}
void Result::bind_as_image(GPUShader *shader, const char *image_name, bool read) const
{
BLI_assert(storage_type_ == ResultStorageType::GPU);
/* Make sure any prior writes to the texture are reflected before reading from it. */
if (read) {
GPU_memory_barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
const int image_unit = GPU_shader_get_sampler_binding(shader, image_name);
GPU_texture_image_bind(texture_, image_unit);
GPU_texture_image_bind(gpu_texture_, image_unit);
}
void Result::unbind_as_texture() const
{
GPU_texture_unbind(texture_);
BLI_assert(storage_type_ == ResultStorageType::GPU);
GPU_texture_unbind(gpu_texture_);
}
void Result::unbind_as_image() const
{
GPU_texture_image_unbind(texture_);
BLI_assert(storage_type_ == ResultStorageType::GPU);
GPU_texture_image_unbind(gpu_texture_);
}
void Result::pass_through(Result &target)
@@ -286,46 +283,55 @@ void Result::pass_through(Result &target)
void Result::steal_data(Result &source)
{
BLI_assert(type_ == source.type_);
BLI_assert(!is_allocated() && source.is_allocated());
BLI_assert(precision_ == source.precision_);
BLI_assert(!this->is_allocated() && source.is_allocated());
BLI_assert(master_ == nullptr && source.master_ == nullptr);
is_single_value_ = source.is_single_value_;
is_from_pool_ = source.is_from_pool_;
texture_ = source.texture_;
context_ = source.context_;
domain_ = source.domain_;
/* Overwrite everything except reference counts. */
const int reference_count = reference_count_;
const int initial_reference_count = initial_reference_count_;
*this = source;
reference_count_ = reference_count;
initial_reference_count_ = initial_reference_count;
switch (type_) {
case ResultType::Float:
float_value_ = source.float_value_;
break;
case ResultType::Vector:
vector_value_ = source.vector_value_;
break;
case ResultType::Color:
color_value_ = source.color_value_;
break;
default:
/* Other types are internal and do not support single values. */
break;
}
source.texture_ = nullptr;
source.context_ = nullptr;
source.reset();
}
void Result::wrap_external(GPUTexture *texture)
{
BLI_assert(GPU_texture_format(texture) == get_texture_format());
BLI_assert(!is_allocated());
BLI_assert(GPU_texture_format(texture) == this->get_gpu_texture_format());
BLI_assert(!this->is_allocated());
BLI_assert(!master_);
texture_ = texture;
gpu_texture_ = texture;
storage_type_ = ResultStorageType::GPU;
is_external_ = true;
is_single_value_ = false;
domain_ = Domain(int2(GPU_texture_width(texture), GPU_texture_height(texture)));
}
void Result::wrap_external(float *texture, int2 size)
{
BLI_assert(!this->is_allocated());
BLI_assert(!master_);
float_texture_ = texture;
storage_type_ = ResultStorageType::FloatCPU;
is_external_ = true;
domain_ = Domain(size);
}
void Result::wrap_external(int *texture, int2 size)
{
BLI_assert(!this->is_allocated());
BLI_assert(!master_);
integer_texture_ = texture;
storage_type_ = ResultStorageType::IntegerCPU;
is_external_ = true;
domain_ = Domain(size);
}
void Result::set_transformation(const float3x3 &transformation)
{
domain_.transformation = transformation;
@@ -343,21 +349,49 @@ RealizationOptions &Result::get_realization_options()
float Result::get_float_value() const
{
BLI_assert(type_ == ResultType::Float);
BLI_assert(is_single_value_);
return float_value_;
}
float4 Result::get_vector_value() const
{
BLI_assert(type_ == ResultType::Vector);
BLI_assert(is_single_value_);
return vector_value_;
}
float4 Result::get_color_value() const
{
BLI_assert(type_ == ResultType::Color);
BLI_assert(is_single_value_);
return color_value_;
}
float2 Result::get_float2_value() const
{
BLI_assert(type_ == ResultType::Float2);
BLI_assert(is_single_value_);
return float2_value_;
}
float3 Result::get_float3_value() const
{
BLI_assert(type_ == ResultType::Float3);
BLI_assert(is_single_value_);
return float3_value_;
}
int2 Result::get_int2_value() const
{
BLI_assert(type_ == ResultType::Int2);
BLI_assert(is_single_value_);
return int2_value_;
}
float Result::get_float_value_default(float default_value) const
{
BLI_assert(type_ == ResultType::Float);
if (is_single_value()) {
return get_float_value();
}
@@ -366,6 +400,7 @@ float Result::get_float_value_default(float default_value) const
float4 Result::get_vector_value_default(const float4 &default_value) const
{
BLI_assert(type_ == ResultType::Vector);
if (is_single_value()) {
return get_vector_value();
}
@@ -374,28 +409,158 @@ float4 Result::get_vector_value_default(const float4 &default_value) const
float4 Result::get_color_value_default(const float4 &default_value) const
{
BLI_assert(type_ == ResultType::Color);
if (is_single_value()) {
return get_color_value();
}
return default_value;
}
float2 Result::get_float2_value_default(const float2 &default_value) const
{
BLI_assert(type_ == ResultType::Float2);
if (is_single_value()) {
return get_float2_value();
}
return default_value;
}
float3 Result::get_float3_value_default(const float3 &default_value) const
{
BLI_assert(type_ == ResultType::Float3);
if (is_single_value()) {
return get_float3_value();
}
return default_value;
}
int2 Result::get_int2_value_default(const int2 &default_value) const
{
BLI_assert(type_ == ResultType::Int2);
if (is_single_value()) {
return get_int2_value();
}
return default_value;
}
void Result::set_float_value(float value)
{
BLI_assert(type_ == ResultType::Float);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
float_value_ = value;
GPU_texture_update(texture_, GPU_DATA_FLOAT, &float_value_);
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_FLOAT, &value);
break;
case ResultStorageType::FloatCPU:
*float_texture_ = value;
break;
case ResultStorageType::IntegerCPU:
BLI_assert_unreachable();
break;
}
}
void Result::set_vector_value(const float4 &value)
{
BLI_assert(type_ == ResultType::Vector);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
vector_value_ = value;
GPU_texture_update(texture_, GPU_DATA_FLOAT, vector_value_);
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_FLOAT, value);
break;
case ResultStorageType::FloatCPU:
copy_v4_v4(float_texture_, value);
break;
case ResultStorageType::IntegerCPU:
BLI_assert_unreachable();
break;
}
}
void Result::set_color_value(const float4 &value)
{
BLI_assert(type_ == ResultType::Color);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
color_value_ = value;
GPU_texture_update(texture_, GPU_DATA_FLOAT, color_value_);
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_FLOAT, value);
break;
case ResultStorageType::FloatCPU:
copy_v4_v4(float_texture_, value);
break;
case ResultStorageType::IntegerCPU:
BLI_assert_unreachable();
break;
}
}
void Result::set_float2_value(const float2 &value)
{
BLI_assert(type_ == ResultType::Float2);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
float2_value_ = value;
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_FLOAT, value);
break;
case ResultStorageType::FloatCPU:
copy_v2_v2(float_texture_, value);
break;
case ResultStorageType::IntegerCPU:
BLI_assert_unreachable();
break;
}
}
void Result::set_float3_value(const float3 &value)
{
BLI_assert(type_ == ResultType::Float3);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
float3_value_ = value;
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_FLOAT, value);
break;
case ResultStorageType::FloatCPU:
copy_v3_v3(float_texture_, value);
break;
case ResultStorageType::IntegerCPU:
BLI_assert_unreachable();
break;
}
}
void Result::set_int2_value(const int2 &value)
{
BLI_assert(type_ == ResultType::Int2);
BLI_assert(is_single_value_);
BLI_assert(this->is_allocated());
int2_value_ = value;
switch (storage_type_) {
case ResultStorageType::GPU:
GPU_texture_update(gpu_texture_, GPU_DATA_INT, value);
break;
case ResultStorageType::FloatCPU:
BLI_assert_unreachable();
break;
case ResultStorageType::IntegerCPU:
copy_v2_v2_int(integer_texture_, value);
break;
}
}
void Result::set_initial_reference_count(int count)
@@ -441,13 +606,25 @@ void Result::release()
return;
}
if (is_from_pool_) {
context_->texture_pool().release(texture_);
switch (storage_type_) {
case ResultStorageType::GPU:
if (is_from_pool_) {
context_->texture_pool().release(gpu_texture_);
}
else {
GPU_texture_free(gpu_texture_);
}
gpu_texture_ = nullptr;
break;
case ResultStorageType::FloatCPU:
MEM_freeN(float_texture_);
float_texture_ = nullptr;
break;
case ResultStorageType::IntegerCPU:
MEM_freeN(integer_texture_);
integer_texture_ = nullptr;
break;
}
else {
GPU_texture_free(texture_);
}
texture_ = nullptr;
}
bool Result::should_compute()
@@ -468,15 +645,10 @@ ResultPrecision Result::precision() const
void Result::set_precision(ResultPrecision precision)
{
/* Changing the precision can only be done if it wasn't allocated yet. */
BLI_assert(!is_allocated());
BLI_assert(!this->is_allocated());
precision_ = precision;
}
bool Result::is_texture() const
{
return !is_single_value_;
}
bool Result::is_single_value() const
{
return is_single_value_;
@@ -484,12 +656,14 @@ bool Result::is_single_value() const
bool Result::is_allocated() const
{
return texture_ != nullptr;
}
GPUTexture *Result::texture() const
{
return texture_;
switch (storage_type_) {
case ResultStorageType::GPU:
return gpu_texture_ != nullptr;
case ResultStorageType::FloatCPU:
return float_texture_ != nullptr;
case ResultStorageType::IntegerCPU:
return integer_texture_ != nullptr;
}
}
int Result::reference_count() const
@@ -506,4 +680,57 @@ const Domain &Result::domain() const
return domain_;
}
void Result::allocate_data(int2 size, bool from_pool)
{
if (context_->use_gpu()) {
is_from_pool_ = from_pool;
if (from_pool) {
gpu_texture_ = context_->texture_pool().acquire(size, this->get_gpu_texture_format());
}
else {
gpu_texture_ = GPU_texture_create_2d(__func__,
size.x,
size.y,
1,
this->get_gpu_texture_format(),
GPU_TEXTURE_USAGE_GENERAL,
nullptr);
}
}
else {
switch (type_) {
case ResultType::Float:
float_texture_ = static_cast<float *>(
MEM_malloc_arrayN(size.x * size.y, sizeof(float), __func__));
storage_type_ = ResultStorageType::FloatCPU;
break;
case ResultType::Vector:
case ResultType::Color:
float_texture_ = static_cast<float *>(
MEM_malloc_arrayN(size.x * size.y, sizeof(float4), __func__));
storage_type_ = ResultStorageType::FloatCPU;
break;
case ResultType::Float2:
float_texture_ = static_cast<float *>(
MEM_malloc_arrayN(size.x * size.y, sizeof(float2), __func__));
storage_type_ = ResultStorageType::FloatCPU;
break;
case ResultType::Float3:
float_texture_ = static_cast<float *>(
MEM_malloc_arrayN(size.x * size.y, sizeof(float3), __func__));
storage_type_ = ResultStorageType::FloatCPU;
break;
case ResultType::Int2:
integer_texture_ = static_cast<int *>(
MEM_malloc_arrayN(size.x * size.y, sizeof(int2), __func__));
storage_type_ = ResultStorageType::IntegerCPU;
break;
}
}
}
} // namespace blender::realtime_compositor

View File

@@ -441,7 +441,7 @@ void ShaderOperation::generate_code_for_outputs(ShaderCreateInfo &shader_create_
/* Add a write-only image for this output where its values will be written. */
shader_create_info.image(0,
result.get_texture_format(),
result.get_gpu_texture_format(),
Qualifier::WRITE,
ImageType::FLOAT_2D,
output_identifier,

View File

@@ -212,7 +212,7 @@ void compute_preview_from_result(Context &context, const DNode &node, Result &in
GPU_shader_bind(shader);
if (input_result.type() == ResultType::Float) {
GPU_texture_swizzle_set(input_result.texture(), "rrr1");
GPU_texture_swizzle_set(input_result, "rrr1");
}
input_result.bind_as_texture(shader, "input_tx");
@@ -229,7 +229,7 @@ void compute_preview_from_result(Context &context, const DNode &node, Result &in
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
float *preview_pixels = static_cast<float *>(
GPU_texture_read(preview_result.texture(), GPU_DATA_FLOAT, 0));
GPU_texture_read(preview_result, GPU_DATA_FLOAT, 0));
preview_result.release();
ColormanageProcessor *color_processor = IMB_colormanagement_display_processor_new(
@@ -247,7 +247,7 @@ void compute_preview_from_result(Context &context, const DNode &node, Result &in
/* Restore original swizzle mask set above. */
if (input_result.type() == ResultType::Float) {
GPU_texture_swizzle_set(input_result.texture(), "rgba");
GPU_texture_swizzle_set(input_result, "rgba");
}
IMB_colormanagement_processor_free(color_processor);

View File

@@ -156,7 +156,7 @@ class BokehBlurOperation : public NodeOperation {
int compute_variable_size_search_radius()
{
const Result &input_size = get_input("Size");
const float maximum_size = maximum_float(context(), input_size.texture());
const float maximum_size = maximum_float(context(), input_size);
const float base_size = compute_blur_radius();
return math::clamp(int(maximum_size * base_size), 0, get_max_size());

View File

@@ -76,7 +76,7 @@ class BokehImageOperation : public NodeOperation {
node_storage(bnode()).lensshift);
Result &output = get_result("Image");
output.wrap_external(bokeh_kernel.texture());
output.wrap_external(bokeh_kernel);
}
Domain compute_domain() override

View File

@@ -101,9 +101,9 @@ class CornerPinOperation : public NodeOperation {
GPU_shader_uniform_mat3_as_mat4(shader, "homography_matrix", homography_matrix.ptr());
Result &input_image = get_input("Image");
GPU_texture_mipmap_mode(input_image.texture(), true, true);
GPU_texture_anisotropic_filter(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_EXTEND);
GPU_texture_mipmap_mode(input_image, true, true);
GPU_texture_anisotropic_filter(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_EXTEND);
input_image.bind_as_texture(shader, "input_tx");
plane_mask.bind_as_texture(shader, "mask_tx");

View File

@@ -330,7 +330,7 @@ class BaseCryptoMatteOperation : public NodeOperation {
/* Clear the matte to zero to ready it to accumulate the coverage. */
const float4 zero_color = float4(0.0f);
GPU_texture_clear(output_matte.texture(), GPU_DATA_FLOAT, zero_color);
GPU_texture_clear(output_matte, GPU_DATA_FLOAT, zero_color);
Vector<float> identifiers = get_identifiers();
/* The user haven't selected any entities, return the currently zero matte. */
@@ -832,7 +832,7 @@ class LegacyCryptoMatteOperation : public BaseCryptoMatteOperation {
Vector<GPUTexture *> layers;
/* Add all textures of all inputs except the first input, which is the input image. */
for (const bNodeSocket *socket : bnode().input_sockets().drop_front(1)) {
layers.append(get_input(socket->identifier).texture());
layers.append(get_input(socket->identifier));
}
return layers;
}

View File

@@ -137,7 +137,7 @@ class DefocusOperation : public NodeOperation {
radius.bind_as_texture(shader, "radius_tx");
GPU_texture_filter_mode(bokeh_kernel.texture(), true);
GPU_texture_filter_mode(bokeh_kernel, true);
bokeh_kernel.bind_as_texture(shader, "weights_tx");
const Domain domain = compute_domain();

View File

@@ -113,7 +113,7 @@ class DenoiseOperation : public NodeOperation {
/* Download the input texture and set it as both the input and output of the filter to denoise
* it in-place. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *color = static_cast<float *>(GPU_texture_read(input_image.texture(), data_format, 0));
float *color = static_cast<float *>(GPU_texture_read(input_image, data_format, 0));
oidn::FilterRef filter = device.newFilter("RT");
filter.setImage("color", color, oidn::Format::Float3, width, height, 0, pixel_stride);
filter.setImage("output", color, oidn::Format::Float3, width, height, 0, pixel_stride);
@@ -126,7 +126,7 @@ class DenoiseOperation : public NodeOperation {
float *albedo = nullptr;
Result &input_albedo = get_input("Albedo");
if (!input_albedo.is_single_value()) {
albedo = static_cast<float *>(GPU_texture_read(input_albedo.texture(), data_format, 0));
albedo = static_cast<float *>(GPU_texture_read(input_albedo, data_format, 0));
if (should_denoise_auxiliary_passes()) {
oidn::FilterRef albedoFilter = device.newFilter("RT");
@@ -149,7 +149,7 @@ class DenoiseOperation : public NodeOperation {
float *normal = nullptr;
Result &input_normal = get_input("Normal");
if (albedo && !input_normal.is_single_value()) {
normal = static_cast<float *>(GPU_texture_read(input_normal.texture(), data_format, 0));
normal = static_cast<float *>(GPU_texture_read(input_normal, data_format, 0));
if (should_denoise_auxiliary_passes()) {
oidn::FilterRef normalFilter = device.newFilter("RT");
@@ -169,7 +169,7 @@ class DenoiseOperation : public NodeOperation {
filter.execute();
output_image.allocate_texture(input_image.domain());
GPU_texture_update(output_image.texture(), data_format, color);
GPU_texture_update(output_image, data_format, color);
MEM_freeN(color);
if (albedo) {

View File

@@ -90,8 +90,8 @@ class DirectionalBlurOperation : public NodeOperation {
GPU_shader_uniform_1f(shader, "scale", get_scale());
const Result &input_image = get_input("Image");
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Domain domain = compute_domain();

View File

@@ -61,9 +61,9 @@ class DisplaceOperation : public NodeOperation {
GPU_shader_bind(shader);
const Result &input_image = get_input("Image");
GPU_texture_mipmap_mode(input_image.texture(), true, true);
GPU_texture_anisotropic_filter(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_mipmap_mode(input_image, true, true);
GPU_texture_anisotropic_filter(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Result &input_displacement = get_input("Vector");

View File

@@ -649,7 +649,7 @@ class FileOutputOperation : public NodeOperation {
/* The image buffer in the file output will take ownership of this buffer and freeing it will
* be its responsibility. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *buffer = static_cast<float *>(GPU_texture_read(result.texture(), GPU_DATA_FLOAT, 0));
float *buffer = static_cast<float *>(GPU_texture_read(result, GPU_DATA_FLOAT, 0));
const int2 size = result.domain().size;
switch (result.type()) {
@@ -689,7 +689,7 @@ class FileOutputOperation : public NodeOperation {
/* The image buffer in the file output will take ownership of this buffer and freeing it will
* be its responsibility. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *buffer = static_cast<float *>(GPU_texture_read(result.texture(), GPU_DATA_FLOAT, 0));
float *buffer = static_cast<float *>(GPU_texture_read(result, GPU_DATA_FLOAT, 0));
const int2 size = result.domain().size;
switch (result.type()) {

View File

@@ -183,7 +183,7 @@ class GlareOperation : public NodeOperation {
GPU_shader_uniform_1f(shader, "threshold", node_storage(bnode()).threshold);
const Result &input_image = get_input("Image");
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_filter_mode(input_image, true);
input_image.bind_as_texture(shader, "input_tx");
const int2 glare_size = get_glare_size();
@@ -253,7 +253,7 @@ class GlareOperation : public NodeOperation {
Result horizontal_pass_result = context().create_result(ResultType::Color);
horizontal_pass_result.allocate_texture(glare_size);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
GPU_texture_copy(horizontal_pass_result.texture(), highlights_result.texture());
GPU_texture_copy(horizontal_pass_result, highlights_result);
GPUShader *shader = context().get_shader("compositor_glare_simple_star_horizontal_pass");
GPU_shader_bind(shader);
@@ -310,7 +310,7 @@ class GlareOperation : public NodeOperation {
Result diagonal_pass_result = context().create_result(ResultType::Color);
diagonal_pass_result.allocate_texture(glare_size);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
GPU_texture_copy(diagonal_pass_result.texture(), highlights_result.texture());
GPU_texture_copy(diagonal_pass_result, highlights_result);
GPUShader *shader = context().get_shader("compositor_glare_simple_star_diagonal_pass");
GPU_shader_bind(shader);
@@ -350,7 +350,7 @@ class GlareOperation : public NodeOperation {
const int2 glare_size = get_glare_size();
Result accumulated_streaks_result = context().create_result(ResultType::Color);
accumulated_streaks_result.allocate_texture(glare_size);
GPU_texture_clear(accumulated_streaks_result.texture(), GPU_DATA_FLOAT, zero_color);
GPU_texture_clear(accumulated_streaks_result, GPU_DATA_FLOAT, zero_color);
/* For each streak, compute its direction and apply a streak filter in that direction, then
* accumulate the result into the accumulated streaks result. */
@@ -390,7 +390,7 @@ class GlareOperation : public NodeOperation {
Result input_streak_result = context().create_result(ResultType::Color);
input_streak_result.allocate_texture(glare_size);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
GPU_texture_copy(input_streak_result.texture(), highlights_result.texture());
GPU_texture_copy(input_streak_result, highlights_result);
Result output_streak_result = context().create_result(ResultType::Color);
output_streak_result.allocate_texture(glare_size);
@@ -408,9 +408,8 @@ class GlareOperation : public NodeOperation {
GPU_shader_uniform_3fv(shader, "fade_factors", fade_factors);
GPU_shader_uniform_2fv(shader, "streak_vector", streak_vector);
GPU_texture_filter_mode(input_streak_result.texture(), true);
GPU_texture_extend_mode(input_streak_result.texture(),
GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_streak_result, true);
GPU_texture_extend_mode(input_streak_result, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_streak_result.bind_as_texture(shader, "input_streak_tx");
output_streak_result.bind_as_image(shader, "output_streak_img");
@@ -425,7 +424,7 @@ class GlareOperation : public NodeOperation {
* copying for the last iteration since it is not needed. */
if (iteration != iterations_range.last()) {
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
GPU_texture_copy(input_streak_result.texture(), output_streak_result.texture());
GPU_texture_copy(input_streak_result, output_streak_result);
}
}
@@ -533,7 +532,7 @@ class GlareOperation : public NodeOperation {
const int2 glare_size = get_glare_size();
Result accumulated_ghosts_result = context().create_result(ResultType::Color);
accumulated_ghosts_result.allocate_texture(glare_size);
GPU_texture_clear(accumulated_ghosts_result.texture(), GPU_DATA_FLOAT, zero_color);
GPU_texture_clear(accumulated_ghosts_result, GPU_DATA_FLOAT, zero_color);
/* For the given number of iterations, accumulate four ghosts with different scales and color
* modulators. The result of the previous iteration is used as the input of the current
@@ -558,7 +557,7 @@ class GlareOperation : public NodeOperation {
* copying for the last iteration since it is not needed. */
if (i != iterations_range.last()) {
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
GPU_texture_copy(input_ghost_result.texture(), accumulated_ghosts_result.texture());
GPU_texture_copy(input_ghost_result, accumulated_ghosts_result);
}
}
@@ -596,12 +595,12 @@ class GlareOperation : public NodeOperation {
GPUShader *shader = context().get_shader("compositor_glare_ghost_base");
GPU_shader_bind(shader);
GPU_texture_filter_mode(small_ghost_result.texture(), true);
GPU_texture_extend_mode(small_ghost_result.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(small_ghost_result, true);
GPU_texture_extend_mode(small_ghost_result, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
small_ghost_result.bind_as_texture(shader, "small_ghost_tx");
GPU_texture_filter_mode(big_ghost_result.texture(), true);
GPU_texture_extend_mode(big_ghost_result.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(big_ghost_result, true);
GPU_texture_extend_mode(big_ghost_result, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
big_ghost_result.bind_as_texture(shader, "big_ghost_tx");
const int2 glare_size = get_glare_size();
@@ -747,7 +746,7 @@ class GlareOperation : public NodeOperation {
if (chain_length < 2) {
Result bloom_result = context().create_result(ResultType::Color);
bloom_result.allocate_texture(highlights_result.domain());
GPU_texture_copy(bloom_result.texture(), highlights_result.texture());
GPU_texture_copy(bloom_result, highlights_result);
return bloom_result;
}
@@ -761,7 +760,7 @@ class GlareOperation : public NodeOperation {
for (const int i : upsample_passes_range) {
Result &input = downsample_chain[upsample_passes_range.last() - i + 1];
GPU_texture_filter_mode(input.texture(), true);
GPU_texture_filter_mode(input, true);
input.bind_as_texture(shader, "input_tx");
const Result &output = downsample_chain[upsample_passes_range.last() - i];
@@ -812,7 +811,7 @@ class GlareOperation : public NodeOperation {
}
const Result &input = downsample_chain[i];
GPU_texture_filter_mode(input.texture(), true);
GPU_texture_filter_mode(input, true);
input.bind_as_texture(shader, "input_tx");
Result &output = downsample_chain[i + 1];
@@ -894,7 +893,7 @@ class GlareOperation : public NodeOperation {
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *highlights_buffer = static_cast<float *>(
GPU_texture_read(highlights_result.texture(), GPU_DATA_FLOAT, 0));
GPU_texture_read(highlights_result, GPU_DATA_FLOAT, 0));
/* Zero pad the image to the required spatial domain size, storing each channel in planar
* format for better cache locality, that is, RRRR...GGGG...BBBB. */
@@ -989,9 +988,9 @@ class GlareOperation : public NodeOperation {
fftwf_free(image_spatial_domain);
fftwf_free(image_frequency_domain);
GPU_texture_update(fog_glow_result.texture(), GPU_DATA_FLOAT, output.data());
GPU_texture_update(fog_glow_result, GPU_DATA_FLOAT, output.data());
#else
GPU_texture_copy(fog_glow_result.texture(), highlights_result.texture());
GPU_texture_copy(fog_glow_result, highlights_result.texture());
#endif
return fog_glow_result;
@@ -1020,7 +1019,7 @@ class GlareOperation : public NodeOperation {
const Result &input_image = get_input("Image");
input_image.bind_as_texture(shader, "input_tx");
GPU_texture_filter_mode(glare_result.texture(), true);
GPU_texture_filter_mode(glare_result, true);
glare_result.bind_as_texture(shader, "glare_tx");
const Domain domain = compute_domain();

View File

@@ -95,7 +95,7 @@ class ConvertKuwaharaOperation : public NodeOperation {
* is enabled, since summed area tables are less precise. */
Result &size_input = get_input("Size");
if (!node_storage(bnode()).high_precision &&
(size_input.is_texture() || size_input.get_float_value() > 5.0f))
(!size_input.is_single_value() || size_input.get_float_value() > 5.0f))
{
execute_classic_summed_area_table();
return;

View File

@@ -100,8 +100,8 @@ class LensDistortionOperation : public NodeOperation {
GPU_shader_bind(shader);
const Result &input_image = get_input("Image");
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Domain domain = compute_domain();
@@ -126,8 +126,8 @@ class LensDistortionOperation : public NodeOperation {
GPU_shader_bind(shader);
const Result &input_image = get_input("Image");
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Domain domain = compute_domain();

View File

@@ -129,17 +129,17 @@ class LevelsOperation : public NodeOperation {
const Result &input = get_input("Image");
switch (get_channel()) {
case CMP_NODE_LEVLES_RED:
return sum_red(context(), input.texture());
return sum_red(context(), input);
case CMP_NODE_LEVLES_GREEN:
return sum_green(context(), input.texture());
return sum_green(context(), input);
case CMP_NODE_LEVLES_BLUE:
return sum_blue(context(), input.texture());
return sum_blue(context(), input);
case CMP_NODE_LEVLES_LUMINANCE_BT709:
return sum_luminance(context(), input.texture(), float3(luminance_coefficients_bt709_));
return sum_luminance(context(), input, float3(luminance_coefficients_bt709_));
case CMP_NODE_LEVLES_LUMINANCE: {
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
return sum_luminance(context(), input.texture(), float3(luminance_coefficients));
return sum_luminance(context(), input, float3(luminance_coefficients));
}
default:
BLI_assert_unreachable();
@@ -159,19 +159,19 @@ class LevelsOperation : public NodeOperation {
const Result &input = get_input("Image");
switch (get_channel()) {
case CMP_NODE_LEVLES_RED:
return sum_red_squared_difference(context(), input.texture(), subtrahend);
return sum_red_squared_difference(context(), input, subtrahend);
case CMP_NODE_LEVLES_GREEN:
return sum_green_squared_difference(context(), input.texture(), subtrahend);
return sum_green_squared_difference(context(), input, subtrahend);
case CMP_NODE_LEVLES_BLUE:
return sum_blue_squared_difference(context(), input.texture(), subtrahend);
return sum_blue_squared_difference(context(), input, subtrahend);
case CMP_NODE_LEVLES_LUMINANCE_BT709:
return sum_luminance_squared_difference(
context(), input.texture(), float3(luminance_coefficients_bt709_), subtrahend);
context(), input, float3(luminance_coefficients_bt709_), subtrahend);
case CMP_NODE_LEVLES_LUMINANCE: {
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
return sum_luminance_squared_difference(
context(), input.texture(), float3(luminance_coefficients), subtrahend);
context(), input, float3(luminance_coefficients), subtrahend);
}
default:
BLI_assert_unreachable();

View File

@@ -70,15 +70,15 @@ class MapUVOperation : public NodeOperation {
const Result &input_image = get_input("Image");
if (nearest_neighbour) {
GPU_texture_mipmap_mode(input_image.texture(), false, false);
GPU_texture_anisotropic_filter(input_image.texture(), false);
GPU_texture_mipmap_mode(input_image, false, false);
GPU_texture_anisotropic_filter(input_image, false);
}
else {
GPU_texture_mipmap_mode(input_image.texture(), true, true);
GPU_texture_anisotropic_filter(input_image.texture(), true);
GPU_texture_mipmap_mode(input_image, true, true);
GPU_texture_anisotropic_filter(input_image, true);
}
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Result &input_uv = get_input("UV");

View File

@@ -121,8 +121,8 @@ class MovieDistortionOperation : public NodeOperation {
GPUShader *shader = context().get_shader("compositor_movie_distortion");
GPU_shader_bind(shader);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image, true);
input_image.bind_as_texture(shader, "input_tx");
distortion_grid.bind_as_texture(shader, "distortion_grid_tx");

View File

@@ -49,10 +49,8 @@ class NormalizeOperation : public NodeOperation {
return;
}
const float maximum = maximum_float_in_range(
context(), input_image.texture(), -range_, range_);
const float minimum = minimum_float_in_range(
context(), input_image.texture(), -range_, range_);
const float maximum = maximum_float_in_range(context(), input_image, -range_, range_);
const float minimum = minimum_float_in_range(context(), input_image, -range_, range_);
const float scale = (maximum != minimum) ? (1.0f / (maximum - minimum)) : 0.0f;
GPUShader *shader = context().get_shader("compositor_normalize");

View File

@@ -182,9 +182,9 @@ class PlaneTrackDeformOperation : public NodeOperation {
GPU_uniformbuf_bind(homography_matrices_buffer, ubo_location);
Result &input_image = get_input("Image");
GPU_texture_mipmap_mode(input_image.texture(), true, true);
GPU_texture_anisotropic_filter(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_EXTEND);
GPU_texture_mipmap_mode(input_image, true, true);
GPU_texture_anisotropic_filter(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_EXTEND);
input_image.bind_as_texture(shader, "input_tx");
plane_mask.bind_as_texture(shader, "mask_tx");

View File

@@ -116,8 +116,8 @@ class ScaleOperation : public NodeOperation {
GPU_shader_bind(shader);
Result &input = get_input("Image");
GPU_texture_filter_mode(input.texture(), true);
GPU_texture_extend_mode(input.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input, true);
GPU_texture_extend_mode(input, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input.bind_as_texture(shader, "input_tx");
Result &x_scale = get_input("X");

View File

@@ -74,8 +74,8 @@ class SunBeamsOperation : public NodeOperation {
GPU_shader_uniform_2fv(shader, "source", node_storage(bnode()).source);
GPU_shader_uniform_1i(shader, "max_steps", max_steps);
GPU_texture_filter_mode(input_image.texture(), true);
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_filter_mode(input_image, true);
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
input_image.bind_as_texture(shader, "input_tx");
const Domain domain = compute_domain();

View File

@@ -223,7 +223,7 @@ class ToneMapOperation : public NodeOperation {
}
const Result &input = get_input("Image");
return sum_color(context(), input.texture()) / (input.domain().size.x * input.domain().size.y);
return sum_color(context(), input) / (input.domain().size.x * input.domain().size.y);
}
float compute_average_luminance()
@@ -238,7 +238,7 @@ class ToneMapOperation : public NodeOperation {
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
const Result &input = get_input("Image");
float sum = sum_luminance(context(), input.texture(), luminance_coefficients);
float sum = sum_luminance(context(), input, luminance_coefficients);
return sum / (input.domain().size.x * input.domain().size.y);
}
@@ -278,7 +278,7 @@ class ToneMapOperation : public NodeOperation {
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
const float sum_of_log_luminance = sum_log_luminance(
context(), input_image.texture(), luminance_coefficients);
context(), input_image, luminance_coefficients);
return sum_of_log_luminance / (input_image.domain().size.x * input_image.domain().size.y);
}
@@ -287,8 +287,7 @@ class ToneMapOperation : public NodeOperation {
{
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
const float maximum = maximum_luminance(
context(), get_input("Image").texture(), luminance_coefficients);
const float maximum = maximum_luminance(context(), get_input("Image"), luminance_coefficients);
return std::log(math::max(maximum, 1e-5f));
}
@@ -296,8 +295,7 @@ class ToneMapOperation : public NodeOperation {
{
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
const float minimum = minimum_luminance(
context(), get_input("Image").texture(), luminance_coefficients);
const float minimum = minimum_luminance(context(), get_input("Image"), luminance_coefficients);
return std::log(math::max(minimum, 1e-5f));
}