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:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user