Blender V4.5
cached_texture.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstdint>
6#include <memory>
7
8#include "BLI_array.hh"
9#include "BLI_hash.hh"
10#include "BLI_index_range.hh"
11#include "BLI_math_vector.h"
13#include "BLI_task.hh"
14
15#include "GPU_texture.hh"
16
17#include "BKE_image.hh"
18#include "BKE_texture.h"
19
20#include "DNA_ID.h"
21#include "DNA_texture_types.h"
22
23#include "RE_texture.h"
24
25#include "COM_cached_texture.hh"
26#include "COM_context.hh"
27#include "COM_result.hh"
28
29namespace blender::compositor {
30
31/* --------------------------------------------------------------------
32 * Cached Texture Key.
33 */
34
39
44
46{
47 return a.size == b.size && a.offset == b.offset && a.scale == b.scale;
48}
49
50/* --------------------------------------------------------------------
51 * Cached Texture.
52 */
53
55 Tex *texture,
56 bool use_color_management,
57 int2 size,
58 float3 offset,
59 float3 scale)
60 : color_result(context.create_result(ResultType::Color)),
61 value_result(context.create_result(ResultType::Float))
62{
63 ImagePool *image_pool = BKE_image_pool_new();
65
66 color_pixels_ = Array<float4>(size.x * size.y);
67 value_pixels_ = Array<float>(size.x * size.y);
68 threading::parallel_for(IndexRange(size.y), 1, [&](const IndexRange sub_y_range) {
69 for (const int64_t y : sub_y_range) {
70 for (const int64_t x : IndexRange(size.x)) {
71 /* Compute the coordinates in the [-1, 1] range and add 0.5 to evaluate the texture at the
72 * center of pixels in case it was interpolated. */
73 const float2 pixel_coordinates = ((float2(x, y) + 0.5f) / float2(size)) * 2.0f - 1.0f;
74 /* Note that it is expected that the offset is scaled by the scale. */
75 const float3 coordinates = (float3(pixel_coordinates, 0.0f) + offset) * scale;
76
77 TexResult texture_result;
78 const int result_type = multitex_ext_safe(
79 texture, coordinates, &texture_result, image_pool, use_color_management, false);
80
81 float4 color = float4(texture_result.trgba);
82 color.w = texture_result.talpha ? color.w : texture_result.tin;
83 if (!(result_type & TEX_RGB)) {
84 copy_v3_fl(color, color.w);
85 }
86
87 color_pixels_[y * size.x + x] = color;
88 value_pixels_[y * size.x + x] = color.w;
89 }
90 }
91 });
92
93 BKE_image_pool_free(image_pool);
94
95 if (context.use_gpu()) {
96 this->color_result.allocate_texture(Domain(size), false);
97 this->value_result.allocate_texture(Domain(size), false);
98 GPU_texture_update(this->color_result, GPU_DATA_FLOAT, color_pixels_.data());
99 GPU_texture_update(this->value_result, GPU_DATA_FLOAT, value_pixels_.data());
100
101 /* CPU-side data no longer needed, so free it. */
102 color_pixels_ = Array<float4>();
103 value_pixels_ = Array<float>();
104 }
105 else {
106 this->color_result.wrap_external(&color_pixels_.data()[0].x, size);
107 this->value_result.wrap_external(value_pixels_.data(), size);
108 }
109}
110
112{
113 this->color_result.release();
114 this->value_result.release();
115}
116
117/* --------------------------------------------------------------------
118 * Cached Texture Container.
119 */
120
122{
123 /* First, delete all cached textures that are no longer needed. */
124 for (auto &cached_textures_for_id : map_.values()) {
125 cached_textures_for_id.remove_if([](auto item) { return !item.value->needed; });
126 }
127 map_.remove_if([](auto item) { return item.value.is_empty(); });
128 update_counts_.remove_if([&](auto item) { return !map_.contains(item.key); });
129
130 /* Second, reset the needed status of the remaining cached textures to false to ready them to
131 * track their needed status for the next evaluation. */
132 for (auto &cached_textures_for_id : map_.values()) {
133 for (auto &value : cached_textures_for_id.values()) {
134 value->needed = false;
135 }
136 }
137}
138
140 Tex *texture,
141 bool use_color_management,
142 int2 size,
143 float3 offset,
144 float3 scale)
145{
146 const CachedTextureKey key(size, offset, scale);
147
148 const std::string library_key = texture->id.lib ? texture->id.lib->id.name : "";
149 const std::string id_key = std::string(texture->id.name) + library_key;
150 auto &cached_textures_for_id = map_.lookup_or_add_default(id_key);
151
152 /* Invalidate the cache for that texture if it was changed since it was cached. */
153 if (!cached_textures_for_id.is_empty() &&
154 texture->runtime.last_update != update_counts_.lookup(id_key))
155 {
156 cached_textures_for_id.clear();
157 }
158
159 auto &cached_texture = *cached_textures_for_id.lookup_or_add_cb(key, [&]() {
160 return std::make_unique<CachedTexture>(
161 context, texture, use_color_management, size, offset, scale);
162 });
163
164 /* Store the current update count to later compare to and check if the texture changed. */
165 update_counts_.add_overwrite(id_key, texture->runtime.last_update);
166
167 cached_texture.needed = true;
168 return cached_texture;
169}
170
171} // namespace blender::compositor
void BKE_image_pool_free(ImagePool *pool)
ImagePool * BKE_image_pool_new()
void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool)
Definition texture.cc:735
float[4] Color
ID and Library types, which are fundamental for SDNA.
@ GPU_DATA_FLOAT
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
CachedTexture & get(Context &context, Tex *texture, bool use_color_management, int2 size, float3 offset, float3 scale)
CachedTextureKey(int2 size, float3 offset, float3 scale)
CachedTexture(Context &context, Tex *texture, bool use_color_management, int2 size, float3 offset, float3 scale)
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3