WIP: Vulkan: Workbench #107886

Closed
Jeroen Bakker wants to merge 88 commits from Jeroen-Bakker:vulkan-draw-manager-workbench into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
126 changed files with 1354 additions and 866 deletions
Showing only changes of commit 6bc2f31be5 - Show all commits

View File

@ -37,7 +37,7 @@ def draw_callback_px(self, context):
# BLF drawing routine
font_id = font_info["font_id"]
blf.position(font_id, 2, 80, 0)
blf.size(font_id, 50)
blf.size(font_id, 50.0)
blf.draw(font_id, "Hello World")

View File

@ -20,7 +20,7 @@ you would pass ``{'active_object': object}`` to :class:`bpy.types.Context.temp_o
# Remove all objects in scene rather than the selected ones.
import bpy
from bpy import context
override = context.copy()
override["selected_objects"] = list(context.scene.objects)
with context.temp_override(**override):
context_override = context.copy()
context_override["selected_objects"] = list(context.scene.objects)
with context.temp_override(**context_override):
bpy.ops.object.delete()

View File

@ -27,17 +27,11 @@ Keywords and Positional Arguments
For calling operators keywords are used for operator properties and
positional arguments are used to define how the operator is called.
There are 3 optional positional arguments (documented in detail below).
There are 2 optional positional arguments (documented in detail below).
.. code-block:: python
bpy.ops.test.operator(override_context, execution_context, undo)
- override_context - ``dict`` type.
.. deprecated:: 3.2
:class:`bpy.types.Context.temp_override` should be used instead of this argument.
bpy.ops.test.operator(execution_context, undo)
- execution_context - ``str`` (enum).
- undo - ``bool`` type.

View File

@ -77,7 +77,7 @@ Typically multiple shaders are linked together into a *Program*.
However, in the Blender Python API the term *Shader* refers to an OpenGL Program.
Every :class:`gpu.types.GPUShader` consists of a vertex shader, a fragment shader and an optional geometry shader.
For common drawing tasks there are some built-in shaders accessible from :class:`gpu.shader.from_builtin`
with an identifier such as `2D_UNIFORM_COLOR` or `3D_FLAT_COLOR`.
with an identifier such as `UNIFORM_COLOR` or `FLAT_COLOR`.
Every shader defines a set of attributes and uniforms that have to be set in order to use the shader.
Attributes are properties that are set using a vertex buffer and can be different for individual vertices.
@ -129,7 +129,7 @@ import gpu
from gpu_extras.batch import batch_for_shader
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
shader = gpu.shader.from_builtin('UNIFORM_COLOR')
batch = batch_for_shader(shader, 'LINES', {"pos": coords})

View File

@ -17,7 +17,7 @@ indices = (
(4, 5), (4, 6), (5, 7), (6, 7),
(0, 4), (1, 5), (2, 6), (3, 7))
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
shader = gpu.shader.from_builtin('UNIFORM_COLOR')
batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)

View File

@ -21,7 +21,7 @@ mesh.loop_triangles.foreach_get(
vertex_colors = [(random(), random(), random(), 1) for _ in range(len(mesh.vertices))]
shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
shader = gpu.shader.from_builtin('SMOOTH_COLOR')
batch = batch_for_shader(
shader, 'TRIS',
{"pos": vertices, "color": vertex_colors},

View File

@ -13,7 +13,7 @@ vertices = (
indices = (
(0, 1, 2), (2, 1, 3))
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
shader = gpu.shader.from_builtin('UNIFORM_COLOR')
batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)

View File

@ -12,7 +12,7 @@ IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('2D_IMAGE')
shader = gpu.shader.from_builtin('IMAGE')
batch = batch_for_shader(
shader, 'TRI_FAN',
{
@ -45,7 +45,7 @@ IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('3D_IMAGE')
shader = gpu.shader.from_builtin('IMAGE')
batch = batch_for_shader(
shader, 'TRIS',
{

View File

@ -1305,9 +1305,7 @@ void PathTrace::set_guiding_params(const GuidingParams &guiding_params, const bo
break;
}
}
# if OPENPGL_VERSION_MINOR >= 4
field_args.deterministic = guiding_params.deterministic;
# endif
reinterpret_cast<PGLKDTreeArguments *>(field_args.spatialSturctureArguments)->maxDepth = 16;
openpgl::cpp::Device *guiding_device = static_cast<openpgl::cpp::Device *>(
device_->get_guiding_device());
@ -1374,12 +1372,7 @@ void PathTrace::guiding_update_structures()
/* we wait until we have at least 1024 samples */
if (num_valid_samples >= 1024) {
# if OPENPGL_VERSION_MINOR < 4
const size_t num_samples = 1;
guiding_field_->Update(*guiding_sample_data_storage_, num_samples);
# else
guiding_field_->Update(*guiding_sample_data_storage_);
# endif
guiding_update_count++;
VLOG_DEBUG << "Path guiding field valid: " << guiding_field_->Validate();

View File

@ -358,12 +358,7 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
# if PATH_GUIDING_LEVEL >= 2
const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights;
# if OPENPGL_VERSION_MINOR >= 5
kg->opgl_path_segment_storage->PrepareSamples(use_mis_weights, use_direct_light, false);
# else
kg->opgl_path_segment_storage->PrepareSamples(
false, nullptr, use_mis_weights, use_direct_light, false);
# endif
# endif
# ifdef WITH_CYCLES_DEBUG

View File

@ -7,10 +7,6 @@
#include "kernel/closure/bsdf.h"
#include "kernel/film/write.h"
#if OPENPGL_VERSION_MINOR >= 5
# define RIS_INCOMING_RADIANCE
#endif
CCL_NAMESPACE_BEGIN
/* Utilities. */
@ -27,11 +23,7 @@ struct GuidingRISSample {
float ris_pdf{0.0f};
float ris_weight{0.0f};
#ifdef RIS_INCOMING_RADIANCE
float incoming_radiance_pdf{0.0f};
#else
float cosine{0.0f};
#endif
BsdfEval bsdf_eval;
float avg_bsdf_eval{0.0f};
Spectrum eval{zero_spectrum()};
@ -45,16 +37,9 @@ ccl_device_forceinline bool calculate_ris_target(ccl_private GuidingRISSample *r
if (ris_sample->avg_bsdf_eval > 0.0f && ris_sample->bsdf_pdf > 1e-10f &&
ris_sample->guide_pdf > 0.0f)
{
# ifdef RIS_INCOMING_RADIANCE
ris_sample->ris_target = (ris_sample->avg_bsdf_eval *
((((1.0f - guiding_sampling_prob) * (1.0f / (pi_factor * M_PI_F))) +
(guiding_sampling_prob * ris_sample->incoming_radiance_pdf))));
# else
ris_sample->ris_target = (ris_sample->avg_bsdf_eval / ris_sample->cosine *
((((1.0f - guiding_sampling_prob) * (1.0f / (pi_factor * M_PI_F))) +
(guiding_sampling_prob * ris_sample->guide_pdf))));
# endif
ris_sample->ris_pdf = (0.5f * (ris_sample->bsdf_pdf + ris_sample->guide_pdf));
ris_sample->ris_weight = ris_sample->ris_target / ris_sample->ris_pdf;
return true;
@ -511,14 +496,8 @@ ccl_device_forceinline bool guiding_bsdf_init(KernelGlobals kg,
ccl_private float &rand)
{
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
# if OPENPGL_VERSION_MINOR >= 5
if (kg->opgl_surface_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
# else
if (kg->opgl_surface_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand, true))
{
# endif
kg->opgl_surface_sampling_distribution->ApplyCosineProduct(guiding_point3f(N));
return true;
}
@ -558,7 +537,7 @@ ccl_device_forceinline float guiding_surface_incoming_radiance_pdf(KernelGlobals
IntegratorState state,
const float3 wo)
{
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4 && OPENPGL_VERSION_MINOR >= 5
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
return kg->opgl_surface_sampling_distribution->IncomingRadiancePDF(guiding_vec3f(wo));
#else
return 0.0f;
@ -580,14 +559,8 @@ ccl_device_forceinline bool guiding_phase_init(KernelGlobals kg,
return false;
}
# if OPENPGL_VERSION_MINOR >= 5
if (kg->opgl_volume_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
# else
if (kg->opgl_volume_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand, true))
{
# endif
kg->opgl_volume_sampling_distribution->ApplySingleLobeHenyeyGreensteinProduct(guiding_vec3f(D),
g);
return true;

View File

@ -620,12 +620,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
const Spectrum emission = volume_emission_integrate(
&coeff, closure_flag, transmittance, dt);
accum_emission += result.indirect_throughput * emission;
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329
if (kernel_data.integrator.max_volume_bounce > 1)
# endif
{
guiding_record_volume_emission(kg, state, emission);
}
guiding_record_volume_emission(kg, state, emission);
}
}
@ -969,13 +964,9 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
const Spectrum phase_weight = bsdf_eval_sum(&phase_eval) / phase_pdf;
/* Add phase function sampling data to the path segment. */
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329
if (kernel_data.integrator.max_volume_bounce > 1)
# endif
{
guiding_record_volume_bounce(
kg, state, sd, phase_weight, phase_pdf, normalize(phase_wo), sampled_roughness);
}
guiding_record_volume_bounce(
kg, state, sd, phase_weight, phase_pdf, normalize(phase_wo), sampled_roughness);
/* Update throughput. */
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
const Spectrum throughput_phase = throughput * phase_weight;
@ -1070,11 +1061,7 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
const float3 direct_P = ray->P + result.direct_t * ray->D;
# ifdef __PATH_GUIDING__
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329
if (kernel_data.integrator.use_guiding && kernel_data.integrator.max_volume_bounce > 1) {
# else
if (kernel_data.integrator.use_guiding) {
# endif
# if PATH_GUIDING_LEVEL >= 1
if (result.direct_sample_method == VOLUME_SAMPLE_DISTANCE) {
/* If the direct scatter event is generated using VOLUME_SAMPLE_DISTANCE the direct event
@ -1147,12 +1134,7 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
# if defined(__PATH_GUIDING__)
# if PATH_GUIDING_LEVEL >= 1
if (!guiding_generated_new_segment) {
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329
if (kernel_data.integrator.max_volume_bounce > 1)
# endif
{
guiding_record_volume_segment(kg, state, sd.P, sd.wi);
}
guiding_record_volume_segment(kg, state, sd.P, sd.wi);
}
# endif
# if PATH_GUIDING_LEVEL >= 4

View File

@ -670,12 +670,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
ris_samples[0].avg_bsdf_eval = average(ris_samples[0].bsdf_eval.sum);
ris_samples[0].guide_pdf = guiding_bsdf_pdf(kg, state, ris_samples[0].wo);
ris_samples[0].guide_pdf *= (1.0f - bssrdf_sampling_prob);
# ifdef RIS_INCOMING_RADIANCE
ris_samples[0].incoming_radiance_pdf = guiding_surface_incoming_radiance_pdf(
kg, state, ris_samples[0].wo);
# else
ris_samples[0].cosine = max(0.01f, fabsf(dot(sd->N, ris_samples[0].wo)));
# endif
ris_samples[0].bsdf_pdf = max(0.0f, ris_samples[0].bsdf_pdf);
}
@ -687,12 +683,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
ris_samples[1].guide_pdf = guiding_bsdf_sample(
kg, state, float3_to_float2(ris_samples[1].rand), &ris_samples[1].wo);
ris_samples[1].guide_pdf *= (1.0f - bssrdf_sampling_prob);
# ifdef RIS_INCOMING_RADIANCE
ris_samples[1].incoming_radiance_pdf = guiding_surface_incoming_radiance_pdf(
kg, state, ris_samples[1].wo);
# else
ris_samples[1].cosine = max(0.01f, fabsf(dot(sd->N, ris_samples[1].wo)));
# endif
ris_samples[1].bsdf_pdf = surface_shader_bsdf_eval_pdfs(
kg, sd, ris_samples[1].wo, &ris_samples[1].bsdf_eval, unguided_bsdf_pdfs, 0);
ris_samples[1].label = ris_samples[0].label;

View File

@ -18,11 +18,9 @@ static int guiding_device_type()
# if defined(__ARM_NEON)
return 8;
# else
# if OPENPGL_VERSION_MINOR >= 4
if (system_cpu_support_avx2()) {
return 8;
}
# endif
if (system_cpu_support_sse41()) {
return 4;
}

View File

@ -40,7 +40,7 @@
* reports of color differences between OpenGL and Vulkan to narrow down if there are other
* configurations we need to support.
*/
#define SELECT_COMPATIBLE_SURFACES false
#define SELECT_COMPATIBLE_SURFACES_ONLY false
using namespace std;
@ -842,7 +842,7 @@ static bool selectSurfaceFormat(const VkPhysicalDevice physical_device,
}
}
#if !SELECT_COMPATIBLE_SURFACES
#if !SELECT_COMPATIBLE_SURFACES_ONLY
r_surfaceFormat = formats[0];
#endif
@ -857,7 +857,7 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
VkPhysicalDevice physical_device = vulkan_device->physical_device;
VkSurfaceFormatKHR format = {};
#if SELECT_COMPATIBLE_SURFACES
#if SELECT_COMPATIBLE_SURFACES_ONLY
if (!selectSurfaceFormat(physical_device, m_surface, format)) {
return GHOST_kFailure;
}

View File

@ -8,10 +8,8 @@
#pragma once
#include "GHOST_Event.hh"
extern "C" {
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
};
/**
* Drag & drop event

View File

@ -7,12 +7,12 @@
#ifndef __MEM_CACHELIMITERC_API_H__
#define __MEM_CACHELIMITERC_API_H__
#include "BLI_utildefines.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "BLI_utildefines.h"
struct MEM_CacheLimiter_s;
struct MEM_CacheLimiterHandle_s;

View File

@ -40,19 +40,13 @@ class _BPyOpsSubModOp:
@staticmethod
def _parse_args(args):
C_dict = None
C_exec = 'EXEC_DEFAULT'
C_undo = False
is_dict = is_exec = is_undo = False
is_exec = is_undo = False
for arg in args:
if is_dict is False and isinstance(arg, dict):
if is_exec is True or is_undo is True:
raise ValueError("dict arg must come first")
C_dict = arg
is_dict = True
elif is_exec is False and isinstance(arg, str):
if is_exec is False and isinstance(arg, str):
if is_undo is True:
raise ValueError("string arg must come before the boolean")
C_exec = arg
@ -61,9 +55,9 @@ class _BPyOpsSubModOp:
C_undo = arg
is_undo = True
else:
raise ValueError("1-3 args execution context is supported")
raise ValueError("1-2 args execution context is supported")
return C_dict, C_exec, C_undo
return C_exec, C_undo
@staticmethod
def _view_layer_update(context):
@ -83,8 +77,8 @@ class _BPyOpsSubModOp:
self._func = func
def poll(self, *args):
C_dict, C_exec, _C_undo = _BPyOpsSubModOp._parse_args(args)
return _op_poll(self.idname_py(), C_dict, C_exec)
C_exec, _C_undo = _BPyOpsSubModOp._parse_args(args)
return _op_poll(self.idname_py(), C_exec)
def idname(self):
# submod.foo -> SUBMOD_OT_foo
@ -107,10 +101,10 @@ class _BPyOpsSubModOp:
_BPyOpsSubModOp._view_layer_update(context)
if args:
C_dict, C_exec, C_undo = _BPyOpsSubModOp._parse_args(args)
ret = _op_call(self.idname_py(), C_dict, kw, C_exec, C_undo)
C_exec, C_undo = _BPyOpsSubModOp._parse_args(args)
ret = _op_call(self.idname_py(), kw, C_exec, C_undo)
else:
ret = _op_call(self.idname_py(), None, kw)
ret = _op_call(self.idname_py(), kw)
if 'FINISHED' in ret and context.window_manager == wm:
_BPyOpsSubModOp._view_layer_update(context)

View File

@ -256,7 +256,7 @@ class QuickExplode(ObjectModeOperator, Operator):
)
def execute(self, context):
fake_context = context.copy()
context_override = context.copy()
obj_act = context.active_object
if obj_act is None or obj_act.type != 'MESH':
@ -288,8 +288,9 @@ class QuickExplode(ObjectModeOperator, Operator):
to_obj = mesh_objects[0]
for obj in mesh_objects:
fake_context["object"] = obj
bpy.ops.object.particle_system_add(fake_context)
context_override["object"] = obj
with context.temp_override(**context_override):
bpy.ops.object.particle_system_add()
settings = obj.particle_systems[-1].settings
settings.count = self.amount
@ -370,9 +371,10 @@ class QuickExplode(ObjectModeOperator, Operator):
psys = obj.particle_systems[-1]
fake_context["particle_system"] = obj.particle_systems[-1]
bpy.ops.particle.new_target(fake_context)
bpy.ops.particle.new_target(fake_context)
context_override["particle_system"] = obj.particle_systems[-1]
with context.temp_override(**context_override):
bpy.ops.particle.new_target()
bpy.ops.particle.new_target()
if obj == from_obj:
psys.targets[1].object = to_obj
@ -436,7 +438,7 @@ class QuickSmoke(ObjectModeOperator, Operator):
self.report({'ERROR'}, "Built without Fluid modifier")
return {'CANCELLED'}
fake_context = context.copy()
context_override = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
min_co = Vector((100000.0, 100000.0, 100000.0))
@ -447,9 +449,10 @@ class QuickSmoke(ObjectModeOperator, Operator):
return {'CANCELLED'}
for obj in mesh_objects:
fake_context["object"] = obj
context_override["object"] = obj
# make each selected object a smoke flow
bpy.ops.object.modifier_add(fake_context, type='FLUID')
with context.temp_override(**context_override):
bpy.ops.object.modifier_add(type='FLUID')
obj.modifiers[-1].fluid_type = 'FLOW'
# set type
@ -541,7 +544,7 @@ class QuickLiquid(Operator):
self.report({'ERROR'}, "Built without Fluid modifier")
return {'CANCELLED'}
fake_context = context.copy()
context_override = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
min_co = Vector((100000.0, 100000.0, 100000.0))
@ -559,9 +562,10 @@ class QuickLiquid(Operator):
space.shading.type = 'WIREFRAME'
for obj in mesh_objects:
fake_context["object"] = obj
context_override["object"] = obj
# make each selected object a liquid flow
bpy.ops.object.modifier_add(fake_context, type='FLUID')
with context.temp_override(**context_override):
bpy.ops.object.modifier_add(type='FLUID')
obj.modifiers[-1].fluid_type = 'FLOW'
# set type

View File

@ -1419,7 +1419,11 @@ class WM_OT_properties_edit(Operator):
return rna_custom_property_subtype_number_items
case 'FLOAT_ARRAY':
return rna_custom_property_subtype_vector_items
return ()
case _:
# Needed so 'NONE' can always be assigned.
return (
rna_custom_property_subtype_none_item,
)
def property_type_update_cb(self, context):
self.subtype = 'NONE'

View File

@ -11,7 +11,7 @@ def draw_callback_px(self, context):
# draw some text
blf.position(font_id, 15, 30, 0)
blf.size(font_id, 20, 72)
blf.size(font_id, 20.0)
blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
# 50% alpha, 2 pixel width line

View File

@ -38,14 +38,16 @@ struct Library;
struct MainLock;
struct UniqueName_Map;
/* Blender thumbnail, as written on file (width, height, and data as char RGBA). */
/* We pack pixel data after that struct. */
/**
* Blender thumbnail, as written to the `.blend` file (width, height, and data as char RGBA).
*/
typedef struct BlendThumbnail {
int width, height;
/** Pixel data, RGBA (repeated): `sizeof(char[4]) * width * height`. */
char rect[0];
} BlendThumbnail;
/* Structs caching relations between data-blocks in a given Main. */
/** Structs caching relations between data-blocks in a given Main. */
typedef struct MainIDRelationsEntryItem {
struct MainIDRelationsEntryItem *next;
@ -123,10 +125,10 @@ typedef struct Main {
/**
* The file-path of this blend file, an empty string indicates an unsaved file.
*
* \note For the current loaded blend file this path should be absolute & normalized
* to prevent redundant leading slashes or current-working-directory relative paths
* from causing problems with absolute/relative patch conversion that relies on this being
* an absolute path. See #BLI_path_canonicalize_native.
* \note For the current loaded blend file this path must be absolute & normalized.
* This prevents redundant leading slashes or current-working-directory relative paths
* from causing problems with absolute/relative conversion which relies on this `filepath`
* being absolute. See #BLI_path_canonicalize_native.
*
* This rule is not strictly enforced as in some cases loading a #Main is performed
* to read data temporarily (preferences & startup) for e.g.
@ -230,10 +232,10 @@ typedef struct Main {
*/
struct MainIDRelations *relations;
/* IDMap of IDs. Currently used when reading (expanding) libraries. */
/** IDMap of IDs. Currently used when reading (expanding) libraries. */
struct IDNameLib_Map *id_map;
/* Used for efficient calculations of unique names. */
/** Used for efficient calculations of unique names. */
struct UniqueName_Map *name_map;
struct MainLock *lock;

View File

@ -103,8 +103,7 @@ int BKE_packedfile_unpack_all_libraries(struct Main *bmain, struct ReportList *r
int BKE_packedfile_write_to_file(struct ReportList *reports,
const char *ref_file_name,
const char *filepath,
struct PackedFile *pf,
bool guimode);
struct PackedFile *pf);
/* Free. */

View File

@ -1402,7 +1402,7 @@ bool BKE_collection_object_add_notest(Main *bmain, Collection *collection, Objec
BKE_main_collection_sync(bmain);
}
DEG_id_tag_update(&collection->id, ID_RECALC_GEOMETRY);
DEG_id_tag_update(&collection->id, ID_RECALC_GEOMETRY | ID_RECALC_HIERARCHY);
return true;
}
@ -1470,7 +1470,7 @@ bool BKE_collection_object_remove(Main *bmain,
BKE_main_collection_sync(bmain);
}
DEG_id_tag_update(&collection->id, ID_RECALC_GEOMETRY);
DEG_id_tag_update(&collection->id, ID_RECALC_GEOMETRY | ID_RECALC_HIERARCHY);
return true;
}

View File

@ -71,7 +71,8 @@ using blender::Vector;
#define CUSTOMDATA_GROW 5
/* ensure typemap size is ok */
BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)nullptr)->typemap) == CD_NUMTYPES, "size mismatch");
BLI_STATIC_ASSERT(BOUNDED_ARRAY_TYPE_SIZE<decltype(CustomData::typemap)>() == CD_NUMTYPES,
"size mismatch");
static CLG_LogRef LOG = {"bke.customdata"};

View File

@ -3989,12 +3989,11 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
if (rpass) {
// printf("load from pass %s\n", rpass->name);
/* since we free render results, we copy the rect */
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
IMB_assign_float_buffer(
ibuf, static_cast<float *>(MEM_dupallocN(rpass->rect)), IB_TAKE_OWNERSHIP);
ibuf->channels = rpass->channels;
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
BKE_imbuf_stamp_info(ima->rr, ibuf);
image_init_after_load(ima, iuser, ibuf);
@ -4301,7 +4300,8 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
image_init_after_load(ima, iuser, ibuf);
IMB_assign_float_buffer(ibuf, rpass->rect, IB_DO_NOT_TAKE_OWNERSHIP);
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
ibuf->channels = rpass->channels;
BKE_imbuf_stamp_info(ima->rr, ibuf);
@ -4320,8 +4320,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
{
Render *re;
RenderView *rv;
float *rectf, *rectz;
uint *rect;
RenderBuffer *combined_buffer, *z_buffer;
RenderByteBuffer *byte_buffer;
float dither;
int channels, layer, pass;
ImBuf *ibuf;
@ -4355,7 +4355,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
rres = *(slot->render);
rres.have_combined = ((RenderView *)rres.views.first)->rectf != nullptr;
rres.have_combined = ((RenderView *)rres.views.first)->combined_buffer.data != nullptr;
}
if (!(rres.rectx > 0 && rres.recty > 0)) {
@ -4380,14 +4380,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
/* this gives active layer, composite or sequence result */
if (rv == nullptr) {
rect = (uint *)rres.rect32;
rectf = rres.rectf;
rectz = rres.rectz;
byte_buffer = &rres.byte_buffer;
combined_buffer = &rres.combined_buffer;
z_buffer = &rres.z_buffer;
}
else {
rect = (uint *)rv->rect32;
rectf = rv->rectf;
rectz = rv->rectz;
byte_buffer = &rv->byte_buffer;
combined_buffer = &rv->combined_buffer;
z_buffer = &rv->z_buffer;
}
dither = iuser->scene->r.dither_intensity;
@ -4396,13 +4396,13 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
if (rres.have_combined && layer == 0) {
/* pass */
}
else if (rect && layer == 0) {
else if (byte_buffer && byte_buffer->data && layer == 0) {
/* rect32 is set when there's a Sequence pass, this pass seems
* to have layer=0 (this is from image_buttons.c)
* in this case we ignore float buffer, because it could have
* hung from previous pass which was float
*/
rectf = nullptr;
combined_buffer = nullptr;
}
else if (rres.layers.first) {
RenderLayer *rl = static_cast<RenderLayer *>(
@ -4410,7 +4410,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
if (rl) {
RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr);
if (rpass) {
rectf = rpass->rect;
combined_buffer = &rpass->buffer;
if (pass != 0) {
channels = rpass->channels;
dither = 0.0f; /* don't dither passes */
@ -4419,7 +4419,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) {
if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) {
rectz = rpass->rect;
z_buffer = &rpass->buffer;
}
}
}
@ -4441,14 +4441,16 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
*
* For other cases we need to be sure it stays to default byte buffer space.
*/
if (ibuf->byte_buffer.data != (uint8_t *)rect) {
if (ibuf->byte_buffer.data != byte_buffer->data) {
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace);
}
/* invalidate color managed buffers if render result changed */
BLI_thread_lock(LOCK_COLORMANAGE);
if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->float_buffer.data != rectf) {
if (combined_buffer && (ibuf->x != rres.rectx || ibuf->y != rres.recty ||
ibuf->float_buffer.data != combined_buffer->data))
{
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
@ -4458,9 +4460,26 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
imb_freerectImBuf(ibuf);
IMB_assign_byte_buffer(ibuf, (uint8_t *)rect, IB_DO_NOT_TAKE_OWNERSHIP);
IMB_assign_float_buffer(ibuf, rectf, IB_DO_NOT_TAKE_OWNERSHIP);
IMB_assign_float_z_buffer(ibuf, rectz, IB_DO_NOT_TAKE_OWNERSHIP);
if (byte_buffer) {
IMB_assign_shared_byte_buffer(ibuf, byte_buffer->data, byte_buffer->sharing_info);
}
else {
IMB_assign_byte_buffer(ibuf, nullptr, IB_DO_NOT_TAKE_OWNERSHIP);
}
if (combined_buffer) {
IMB_assign_shared_float_buffer(ibuf, combined_buffer->data, combined_buffer->sharing_info);
}
else {
IMB_assign_float_buffer(ibuf, nullptr, IB_DO_NOT_TAKE_OWNERSHIP);
}
if (z_buffer) {
IMB_assign_shared_float_z_buffer(ibuf, z_buffer->data, z_buffer->sharing_info);
}
else {
IMB_assign_float_z_buffer(ibuf, nullptr, IB_DO_NOT_TAKE_OWNERSHIP);
}
/* TODO(sergey): Make this faster by either simply referencing the stamp
* or by changing both ImBuf and RenderResult to use same data type to

View File

@ -738,7 +738,7 @@ bool BKE_image_render_write_exr(ReportList *reports,
/* Compositing result. */
if (rr->have_combined) {
LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
if (!rview->rectf) {
if (!rview->combined_buffer.data) {
continue;
}
@ -756,10 +756,11 @@ bool BKE_image_render_write_exr(ReportList *reports,
continue;
}
float *output_rect = (save_as_render) ?
image_exr_from_scene_linear_to_output(
rview->rectf, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
rview->rectf;
float *output_rect =
(save_as_render) ?
image_exr_from_scene_linear_to_output(
rview->combined_buffer.data, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
rview->combined_buffer.data;
for (int a = 0; a < channels; a++) {
char passname[EXR_PASS_MAXNAME];
@ -781,9 +782,10 @@ bool BKE_image_render_write_exr(ReportList *reports,
exrhandle, layname, passname, viewname, 4, 4 * rr->rectx, output_rect + a, half_float);
}
if (write_z && rview->rectz) {
if (write_z && rview->z_buffer.data) {
const char *layname = (multi_layer) ? "Composite" : "";
IMB_exr_add_channel(exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->rectz, false);
IMB_exr_add_channel(
exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->z_buffer.data, false);
}
}
}
@ -825,8 +827,8 @@ bool BKE_image_render_write_exr(ReportList *reports,
float *output_rect =
(save_as_render && pass_RGBA) ?
image_exr_from_scene_linear_to_output(
rp->rect, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
rp->rect;
rp->buffer.data, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
rp->buffer.data;
for (int a = 0; a < std::min(channels, rp->channels); a++) {
/* Save Combined as RGBA or RGB if single layer save. */

View File

@ -1227,7 +1227,7 @@ static IDProperty *object_asset_dimensions_property(Object *ob)
}
IDPropertyTemplate idprop{};
idprop.array.len = ARRAY_SIZE(dimensions);
idprop.array.len = 3;
idprop.array.type = IDP_FLOAT;
IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions");

View File

@ -286,8 +286,7 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
int BKE_packedfile_write_to_file(ReportList *reports,
const char *ref_file_name,
const char *filepath_rel,
PackedFile *pf,
const bool guimode)
PackedFile *pf)
{
int file, number;
int ret_value = RET_OK;
@ -296,9 +295,6 @@ int BKE_packedfile_write_to_file(ReportList *reports,
char filepath_temp[FILE_MAX];
/* void *data; */
if (guimode) {
} // XXX waitcursor(1);
STRNCPY(filepath, filepath_rel);
BLI_path_abs(filepath, ref_file_name);
@ -350,9 +346,6 @@ int BKE_packedfile_write_to_file(ReportList *reports,
}
}
if (guimode) {
} // XXX waitcursor(0);
return ret_value;
}
@ -441,7 +434,7 @@ char *BKE_packedfile_unpack_to_file(ReportList *reports,
ATTR_FALLTHROUGH;
}
case PF_WRITE_LOCAL:
if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf) == RET_OK) {
temp = local_name;
}
break;
@ -461,7 +454,7 @@ char *BKE_packedfile_unpack_to_file(ReportList *reports,
ATTR_FALLTHROUGH;
}
case PF_WRITE_ORIGINAL:
if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf) == RET_OK) {
temp = abs_name;
}
break;

View File

@ -1113,7 +1113,7 @@ bool BKE_unit_replace_string(
/* Apply the default unit on the whole expression, this allows to handle nasty cases like
* '2+2in'. */
if (SNPRINTF(str_tmp, "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) {
strncpy(str, str_tmp, str_maxncpy);
BLI_strncpy(str, str_tmp, str_maxncpy);
}
else {
/* BLI_snprintf would not fit into str_tmp, can't do much in this case.
@ -1190,8 +1190,13 @@ void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int
int len_name = 0;
/* Copy everything before the unit. */
offset = (offset < str_maxncpy ? offset : str_maxncpy);
strncpy(str, orig_str, offset);
if (offset < str_maxncpy) {
memcpy(str, orig_str, offset);
}
else {
BLI_strncpy(str, orig_str, str_maxncpy);
offset = str_maxncpy;
}
str += offset;
orig_str += offset + strlen(unit->name_short);
@ -1213,7 +1218,7 @@ void BKE_unit_name_to_alt(char *str, int str_maxncpy, const char *orig_str, int
}
/* Finally copy the rest of the string. */
strncpy(str, orig_str, str_maxncpy);
BLI_strncpy(str, orig_str, str_maxncpy);
}
double BKE_unit_closest_scalar(double value, int system, int type)

View File

@ -201,12 +201,12 @@ void lift_gamma_gain_to_asc_cdl(const float *lift,
float *slope,
float *power);
#if BLI_MATH_DO_INLINE
# include "intern/math_color_inline.c"
#endif
/** \} */
#ifdef __cplusplus
}
#endif
#if BLI_MATH_DO_INLINE
# include "intern/math_color_inline.c"
#endif

View File

@ -1402,6 +1402,10 @@ float geodesic_distance_propagate_across_triangle(
/** \} */
#ifdef __cplusplus
}
#endif
/* -------------------------------------------------------------------- */
/** \name Inline Definitions
* \{ */
@ -1415,7 +1419,3 @@ float geodesic_distance_propagate_across_triangle(
#endif
/** \} */
#ifdef __cplusplus
}
#endif

View File

@ -551,7 +551,10 @@ int BLI_string_find_split_words(const char *str,
* \note `ARRAY_SIZE` allows pointers on some platforms.
* \{ */
#define STRNCPY(dst, src) BLI_strncpy(dst, src, ARRAY_SIZE(dst))
#ifndef __cplusplus
# define STRNCPY(dst, src) BLI_strncpy(dst, src, ARRAY_SIZE(dst))
#endif
#define STRNCPY_RLEN(dst, src) BLI_strncpy_rlen(dst, src, ARRAY_SIZE(dst))
#define SNPRINTF(dst, format, ...) BLI_snprintf(dst, ARRAY_SIZE(dst), format, __VA_ARGS__)
#define SNPRINTF_RLEN(dst, format, ...) \
@ -635,4 +638,17 @@ void BLI_string_debug_size_after_nil(char *str, size_t str_maxncpy);
/** \} */
#ifdef __cplusplus
}
/**
* Copy source string str into the destination dst of a size known at a compile time.
* Ensures that the destination is not overflown, and that the destination is always
* null-terminated.
*
* Returns the dst.
*/
template<size_t N> inline char *STRNCPY(char (&dst)[N], const char *src)
{
return BLI_strncpy(dst, src, N);
}
#endif

View File

@ -21,6 +21,9 @@
#include "BLI_compiler_typecheck.h"
#ifdef __cplusplus
# include <type_traits>
# include <utility>
extern "C" {
#endif
@ -493,12 +496,15 @@ extern "C" {
((void)0)
/* assuming a static array */
#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && !defined(__INTEL_COMPILER)
# define ARRAY_SIZE(arr) \
((sizeof(struct { int isnt_array : ((const void *)&(arr) == &(arr)[0]); }) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
#else
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
#ifndef __cplusplus
# if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && \
!defined(__INTEL_COMPILER)
# define ARRAY_SIZE(arr) \
((sizeof(struct { int isnt_array : ((const void *)&(arr) == &(arr)[0]); }) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
# else
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
# endif
#endif
/* ARRAY_SET_ITEMS#(v, ...): set indices of array 'v' */
@ -867,6 +873,46 @@ extern bool BLI_memory_is_zero(const void *arr, size_t arr_size);
#ifdef __cplusplus
}
namespace blender::blenlib_internal {
/* A replacement for std::is_bounded_array_v until we go C++20. */
template<class T> struct IsBoundedArray : std::false_type {
};
template<class T, std::size_t N> struct IsBoundedArray<T[N]> : std::true_type {
};
} // namespace blender::blenlib_internal
/**
* Size of a bounded array provided as an arg.
*
* The arg must be a bounded array, such as int[7] or MyType[11].
* Returns the number of elements in the array, known at the compile time.
*/
template<class T, size_t N> constexpr size_t ARRAY_SIZE(const T (&arg)[N]) noexcept
{
(void)arg;
return N;
}
/**
* Number of elements in a type which defines a bounded array.
*
* For example,
* struct MyType {
* int array[12];
* };
*
* `BOUNDED_ARRAY_TYPE_SIZE<decltype(MyType::array)>` returns 12.
*/
template<class T>
constexpr std::enable_if_t<blender::blenlib_internal::IsBoundedArray<T>::value, size_t>
BOUNDED_ARRAY_TYPE_SIZE() noexcept
{
return sizeof(std::declval<T>()) / sizeof(std::declval<T>()[0]);
}
#endif
#endif /* __BLI_UTILDEFINES_H__ */

View File

@ -546,6 +546,7 @@ if(WITH_GTESTS)
tests/BLI_task_graph_test.cc
tests/BLI_task_test.cc
tests/BLI_tempfile_test.cc
tests/BLI_utildefines_test.cc
tests/BLI_uuid_test.cc
tests/BLI_vector_set_test.cc
tests/BLI_vector_test.cc

View File

@ -11,6 +11,10 @@
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __MATH_COLOR_INLINE_C__
# define __MATH_COLOR_INLINE_C__
@ -379,3 +383,7 @@ MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float c
}
#endif /* __MATH_COLOR_INLINE_C__ */
#ifdef __cplusplus
}
#endif

View File

@ -160,8 +160,7 @@ bool BLI_windows_register_blend_extension(const bool background)
BLI_windows_get_executable_dir(InstallDir);
GetSystemDirectory(SysDir, FILE_MAXDIR);
const char *ThumbHandlerDLL = "BlendThumb.dll";
snprintf(
RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
SNPRINTF(RegCmd, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
system(RegCmd);
}
# endif

View File

@ -4,11 +4,9 @@
#include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_math.h"
#include "BLI_rand.h"
#include "PIL_time.h"
}
#include <fstream>
#include <iostream>

View File

@ -1332,3 +1332,18 @@ TEST_F(StringEscape, Control)
}
/** \} */
TEST(BLI_string, bounded_strcpy)
{
{
char str[8];
STRNCPY(str, "Hello");
EXPECT_STREQ(str, "Hello");
}
{
char str[8];
STRNCPY(str, "Hello, World!");
EXPECT_STREQ(str, "Hello, ");
}
}

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "BLI_utildefines.h"
#include "testing/testing.h"
namespace blender::tests {
TEST(BLI_utildefines, ARRAY_SIZE)
{
{
int bounded_char[5];
static_assert(ARRAY_SIZE(bounded_char) == 5);
}
{
int *bounded_char[5];
static_assert(ARRAY_SIZE(bounded_char) == 5);
}
}
TEST(BLI_utildefines, BOUNDED_ARRAY_TYPE_SIZE)
{
{
int bounded_char[5];
static_assert(BOUNDED_ARRAY_TYPE_SIZE<decltype(bounded_char)>() == 5);
}
{
int *bounded_char[5];
static_assert(BOUNDED_ARRAY_TYPE_SIZE<decltype(bounded_char)>() == 5);
}
{
struct MyType {
int array[12];
};
static_assert(BOUNDED_ARRAY_TYPE_SIZE<decltype(MyType::array)>() == 12);
}
}
} // namespace blender::tests

View File

@ -67,14 +67,9 @@ void CompositorOperation::deinit_execution()
if (rr) {
RenderView *rv = RE_RenderViewGetByName(rr, view_name_);
if (rv->rectf != nullptr) {
MEM_freeN(rv->rectf);
}
rv->rectf = output_buffer_;
if (rv->rectz != nullptr) {
MEM_freeN(rv->rectz);
}
rv->rectz = depth_buffer_;
RE_RenderBuffer_assign_data(&rv->combined_buffer, output_buffer_);
RE_RenderBuffer_assign_data(&rv->z_buffer, depth_buffer_);
rr->have_combined = true;
}
else {

View File

@ -86,7 +86,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
}
/* This is ignored since we query using our own GPU capabilities system. */
void setTextureMaxWidth(unsigned max_width) override {}
void setTextureMaxWidth(unsigned /*max_width*/) override {}
unsigned getTextureMaxWidth() const noexcept override
{
@ -255,7 +255,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
/* This gets called before the finalize() method to construct the shader code. We just
* concatenate the code except for the declarations section. That's because the ShaderCreateInfo
* will add the declaration itself. */
void createShaderText(const char *declarations,
void createShaderText(const char * /*declarations*/,
const char *helper_methods,
const char *function_header,
const char *function_body,

View File

@ -131,7 +131,6 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain,
scene_(nullptr),
view_layer_(nullptr),
view_layer_index_(-1),
collection_(nullptr),
is_parent_collection_visible_(true)
{
}
@ -324,6 +323,13 @@ bool DepsgraphNodeBuilder::has_operation_node(ID *id,
return find_operation_node(id, comp_type, comp_name, opcode, name, name_tag) != nullptr;
}
bool DepsgraphNodeBuilder::has_operation_node(ID *id,
const NodeType comp_type,
const OperationCode opcode)
{
return find_operation_node(id, comp_type, opcode) != nullptr;
}
OperationNode *DepsgraphNodeBuilder::find_operation_node(const ID *id,
NodeType comp_type,
const char *comp_name,
@ -702,7 +708,10 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti
id_node = add_id_node(&collection->id);
id_node->is_visible_on_build = is_collection_visible;
add_operation_node(&collection->id, NodeType::HIERARCHY, OperationCode::HIERARCHY);
build_idproperties(collection->id.properties);
build_parameters(&collection->id);
add_operation_node(&collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
}
if (from_layer_collection != nullptr) {
@ -711,10 +720,8 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti
return;
}
/* Backup state. */
Collection *current_state_collection = collection_;
const bool is_current_parent_collection_visible = is_parent_collection_visible_;
/* Modify state as we've entered new collection/ */
collection_ = collection;
is_parent_collection_visible_ = is_collection_visible;
/* Build collection objects. */
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
@ -725,7 +732,6 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti
build_collection(nullptr, child->collection);
}
/* Restore state. */
collection_ = current_state_collection;
is_parent_collection_visible_ = is_current_parent_collection_visible;
id_node->is_collection_fully_expanded = true;
}
@ -772,6 +778,9 @@ void DepsgraphNodeBuilder::build_object(int base_index,
id_node->is_visible_on_build = is_visible;
}
id_node->has_base |= (base_index != -1);
add_operation_node(&object->id, NodeType::HIERARCHY, OperationCode::HIERARCHY);
/* Various flags, flushing from bases/collections. */
build_object_from_layer(base_index, object, linked_state);
/* Transform. */
@ -822,6 +831,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
{
build_texture(object->pd->tex);
}
/* Object dupligroup. */
if (object->instance_collection != nullptr) {
build_object_instance_collection(object, is_visible);
@ -829,6 +839,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
&object->id, NodeType::DUPLI, OperationCode::DUPLI);
op_node->flag |= OperationFlag::DEPSOP_FLAG_PINNED;
}
/* Synchronization back to original object. */
add_operation_node(&object->id,
NodeType::SYNCHRONIZATION,

View File

@ -139,6 +139,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
OperationCode opcode,
const char *name = "",
int name_tag = -1);
bool has_operation_node(ID *id, NodeType comp_type, OperationCode opcode);
OperationNode *find_operation_node(const ID *id,
NodeType comp_type,
@ -193,6 +194,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_object_transform(Object *object);
virtual void build_object_constraints(Object *object);
virtual void build_object_pointcache(Object *object);
virtual void build_pose_constraints(Object *object, bPoseChannel *pchan, int pchan_index);
virtual void build_rigidbody(Scene *scene);
virtual void build_particle_systems(Object *object, bool is_object_visible);
@ -307,7 +309,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
int view_layer_index_;
/* NOTE: Collection are possibly built recursively, so be careful when
* setting the current state. */
Collection *collection_;
/* Accumulated flag over the hierarchy of currently building collections.
* Denotes whether all the hierarchy from parent of `collection_` to the
* very root is visible (aka not restricted.). */

View File

@ -78,6 +78,9 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
/* Scene ID block. */
IDNode *id_node = add_id_node(&scene->id);
id_node->linked_state = linked_state;
add_operation_node(&scene->id, NodeType::HIERARCHY, OperationCode::HIERARCHY);
/* Time source. */
add_time_source();
/* Setup currently building context. */

View File

@ -282,6 +282,15 @@ Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key)
return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
}
ComponentNode *DepsgraphRelationBuilder::find_node(const ComponentKey &key) const
{
IDNode *id_node = graph_->find_id_node(key.id);
if (!id_node) {
return nullptr;
}
return id_node->find_component(key.type, key.name);
}
OperationNode *DepsgraphRelationBuilder::find_node(const OperationKey &key) const
{
IDNode *id_node = graph_->find_id_node(key.id);
@ -300,6 +309,11 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
return find_node(key) != nullptr;
}
bool DepsgraphRelationBuilder::has_node(const ComponentKey &key) const
{
return find_node(key) != nullptr;
}
void DepsgraphRelationBuilder::add_depends_on_transform_relation(const DepsNodeHandle *handle,
const char *description)
{
@ -504,7 +518,7 @@ void DepsgraphRelationBuilder::build_id(ID *id)
build_camera((Camera *)id);
break;
case ID_GR:
build_collection(nullptr, nullptr, (Collection *)id);
build_collection(nullptr, (Collection *)id);
break;
case ID_OB:
build_object((Object *)id);
@ -615,76 +629,85 @@ void DepsgraphRelationBuilder::build_idproperties(IDProperty *id_property)
}
void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection,
Object *object,
Collection *collection)
{
const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
if (from_layer_collection != nullptr) {
/* If we came from layer collection we don't go deeper, view layer
* builder takes care of going deeper.
/* If we came from layer collection we don't go deeper, view layer builder takes care of going
* deeper.
*
* NOTE: Do early output before tagging build as done, so possible
* subsequent builds from outside of the layer collection properly
* recurses into all the nested objects and collections. */
* NOTE: Do early output before tagging build as done, so possible subsequent builds from
* outside of the layer collection properly recurses into all the nested objects and
* collections. */
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
Object *object = cob->ob;
/* Ensure that the hierarchy relations always exists, even for the layer collection.
*
* Note that the view layer builder can skip bases if they are constantly excluded from the
* collections. In order to avoid noisy output check that the target node exists before
* adding the relation. */
const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
if (has_node(object_hierarchy_key)) {
add_relation(collection_hierarchy_key,
object_hierarchy_key,
"Collection -> Object hierarchy",
RELATION_CHECK_BEFORE_ADD);
}
}
return;
}
if (built_map_.checkIsBuiltAndTag(collection)) {
return;
}
build_idproperties(collection->id.properties);
build_parameters(&collection->id);
const BuilderStack::ScopedEntry stack_entry = stack_.trace(collection->id);
const bool group_done = built_map_.checkIsBuiltAndTag(collection);
OperationKey object_transform_final_key(object != nullptr ? &object->id : nullptr,
NodeType::TRANSFORM,
OperationCode::TRANSFORM_FINAL);
ComponentKey duplicator_key(object != nullptr ? &object->id : nullptr, NodeType::DUPLI);
if (!group_done) {
build_idproperties(collection->id.properties);
OperationKey collection_geometry_key{
&collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
build_object(cob->ob);
const OperationKey collection_geometry_key{
&collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
/* The geometry of a collection depends on the positions of the elements in it. */
OperationKey object_transform_key{
&cob->ob->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL};
add_relation(object_transform_key, collection_geometry_key, "Collection Geometry");
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
Object *object = cob->ob;
/* Only create geometry relations to child objects, if they have a geometry component. */
OperationKey object_geometry_key{
&cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL};
if (find_node(object_geometry_key) != nullptr) {
add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry");
}
build_object(object);
/* An instance is part of the geometry of the collection. */
if (cob->ob->type == OB_EMPTY) {
Collection *collection_instance = cob->ob->instance_collection;
if (collection_instance != nullptr) {
OperationKey collection_instance_key{
&collection_instance->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry");
}
}
const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
add_relation(collection_hierarchy_key, object_hierarchy_key, "Collection -> Object hierarchy");
/* The geometry of a collection depends on the positions of the elements in it. */
const OperationKey object_transform_key{
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL};
add_relation(object_transform_key, collection_geometry_key, "Collection Geometry");
/* Only create geometry relations to child objects, if they have a geometry component. */
const OperationKey object_geometry_key{
&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL};
if (find_node(object_geometry_key) != nullptr) {
add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry");
}
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
build_collection(nullptr, nullptr, child->collection);
OperationKey child_collection_geometry_key{
&child->collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry");
/* An instance is part of the geometry of the collection. */
if (object->type == OB_EMPTY) {
Collection *collection_instance = cob->ob->instance_collection;
if (collection_instance != nullptr) {
const OperationKey collection_instance_key{
&collection_instance->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry");
}
}
}
if (object != nullptr) {
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, ob, graph_->mode) {
ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
/* Hook to special component, to ensure proper visibility/evaluation
* optimizations. */
add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
const NodeType dupli_geometry_component_type = geometry_tag_to_component(&ob->id);
if (dupli_geometry_component_type != NodeType::UNDEFINED) {
ComponentKey dupli_geometry_component_key(&ob->id, dupli_geometry_component_type);
add_relation(dupli_geometry_component_key, duplicator_key, "Dupligroup");
}
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
build_collection(nullptr, child->collection);
const OperationKey child_collection_geometry_key{
&child->collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry");
}
}
@ -796,12 +819,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_texture(object->pd->tex);
}
/* Object dupligroup. */
if (object->instance_collection != nullptr) {
build_collection(nullptr, object, object->instance_collection);
}
/* Point caches. */
build_object_instance_collection(object);
build_object_pointcache(object);
/* Synchronization back to original object. */
@ -1210,6 +1228,35 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
BLI_freelistN(&ptcache_id_list);
}
void DepsgraphRelationBuilder::build_object_instance_collection(Object *object)
{
if (object->instance_collection == nullptr) {
return;
}
Collection *instance_collection = object->instance_collection;
build_collection(nullptr, instance_collection);
const OperationKey object_transform_final_key(
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
const ComponentKey duplicator_key(&object->id, NodeType::DUPLI);
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (instance_collection, ob, graph_->mode) {
const ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
/* Hook to special component, to ensure proper visibility/evaluation optimizations. */
add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
const NodeType dupli_geometry_component_type = geometry_tag_to_component(&ob->id);
if (dupli_geometry_component_type != NodeType::UNDEFINED) {
ComponentKey dupli_geometry_component_key(&ob->id, dupli_geometry_component_type);
add_relation(dupli_geometry_component_key, duplicator_key, "Dupligroup");
}
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
}
void DepsgraphRelationBuilder::build_constraints(ID *id,
NodeType component_type,
const char *component_subdata,
@ -2012,7 +2059,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
}
/* Objects. */
if (rbw->group != nullptr) {
build_collection(nullptr, nullptr, rbw->group);
build_collection(nullptr, rbw->group);
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
if (object->type != OB_MESH) {
continue;
@ -2168,7 +2215,7 @@ void DepsgraphRelationBuilder::build_particle_systems(Object *object)
break;
case PART_DRAW_GR:
if (part->instance_collection != nullptr) {
build_collection(nullptr, nullptr, part->instance_collection);
build_collection(nullptr, part->instance_collection);
LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
build_particle_system_visualization_object(object, psys, go->ob);
}
@ -2632,7 +2679,7 @@ void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket)
else if (socket->type == SOCK_COLLECTION) {
Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
if (collection != nullptr) {
build_collection(nullptr, nullptr, collection);
build_collection(nullptr, collection);
}
}
else if (socket->type == SOCK_TEXTURE) {
@ -3248,6 +3295,11 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
if (ELEM(comp_node->type, NodeType::PARAMETERS, NodeType::LAYER_COLLECTIONS)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}
/* Compatibility with the legacy tagging: groups are only tagged for Copy-on-Write when their
* hierarchy changes, and it needs to be flushed downstream. */
if (id_type == ID_GR && comp_node->type == NodeType::HIERARCHY) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}
/* All entry operations of each component should wait for a proper
* copy of ID. */
OperationNode *op_entry = comp_node->get_entry_operation();

View File

@ -129,13 +129,13 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_scene_parameters(Scene *scene);
virtual void build_scene_compositor(Scene *scene);
virtual void build_layer_collections(ListBase *lb);
virtual bool build_layer_collection(LayerCollection *layer_collection);
virtual void build_view_layer_collections(ViewLayer *view_layer);
virtual void build_view_layer(Scene *scene,
ViewLayer *view_layer,
eDepsNode_LinkedState_Type linked_state);
virtual void build_collection(LayerCollection *from_layer_collection,
Object *object,
Collection *collection);
virtual void build_collection(LayerCollection *from_layer_collection, Collection *collection);
virtual void build_object(Object *object);
virtual void build_object_from_view_layer_base(Object *object);
virtual void build_object_layer_component_relations(Object *object);
@ -149,6 +149,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_object_data_speaker(Object *object);
virtual void build_object_parent(Object *object);
virtual void build_object_pointcache(Object *object);
virtual void build_object_instance_collection(Object *object);
virtual void build_constraints(ID *id,
NodeType component_type,
const char *component_subdata,
@ -263,6 +265,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
Node *get_node(const RNAPathKey &key);
OperationNode *find_node(const OperationKey &key) const;
ComponentNode *find_node(const ComponentKey &key) const;
bool has_node(const ComponentKey &key) const;
bool has_node(const OperationKey &key) const;
Relation *add_time_relation(TimeSourceNode *timesrc,

View File

@ -43,26 +43,55 @@
namespace blender::deg {
void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
bool DepsgraphRelationBuilder::build_layer_collection(LayerCollection *layer_collection)
{
const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT :
COLLECTION_HIDE_RENDER;
const int hide_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT :
COLLECTION_HIDE_RENDER;
for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
if (lc->collection->flag & visibility_flag) {
continue;
Collection *collection = layer_collection->collection;
const bool is_collection_hidden = collection->flag & hide_flag;
const bool is_layer_collection_excluded = layer_collection->flag & LAYER_COLLECTION_EXCLUDE;
if (is_collection_hidden || is_layer_collection_excluded) {
return false;
}
build_collection(layer_collection, collection);
const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
LISTBASE_FOREACH (
LayerCollection *, child_layer_collection, &layer_collection->layer_collections) {
if (build_layer_collection(child_layer_collection)) {
Collection *child_collection = child_layer_collection->collection;
const ComponentKey child_collection_hierarchy_key{&child_collection->id,
NodeType::HIERARCHY};
add_relation(
collection_hierarchy_key, child_collection_hierarchy_key, "Collection hierarchy");
}
if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
build_collection(lc, nullptr, lc->collection);
}
return true;
}
void DepsgraphRelationBuilder::build_view_layer_collections(ViewLayer *view_layer)
{
const ComponentKey scene_hierarchy_key{&scene_->id, NodeType::HIERARCHY};
LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
if (build_layer_collection(layer_collection)) {
Collection *collection = layer_collection->collection;
const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
add_relation(scene_hierarchy_key, collection_hierarchy_key, "Scene -> Collection hierarchy");
}
build_layer_collections(&lc->layer_collections);
}
}
void DepsgraphRelationBuilder::build_freestyle_lineset(FreestyleLineSet *fls)
{
if (fls->group != nullptr) {
build_collection(nullptr, nullptr, fls->group);
build_collection(nullptr, fls->group);
}
if (fls->linestyle != nullptr) {
build_freestyle_linestyle(fls->linestyle);
@ -86,7 +115,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene,
}
}
build_layer_collections(&view_layer->layer_collections);
build_view_layer_collections(view_layer);
if (scene->camera != nullptr) {
build_object(scene->camera);

View File

@ -400,6 +400,7 @@ static void deg_debug_graphviz_node(DotExportContext &ctx,
case NodeType::PARTICLE_SETTINGS:
case NodeType::COPY_ON_WRITE:
case NodeType::OBJECT_FROM_LAYER:
case NodeType::HIERARCHY:
case NodeType::BATCH_CACHE:
case NodeType::DUPLI:
case NodeType::SYNCHRONIZATION:

View File

@ -217,7 +217,11 @@ void depsgraph_tag_to_component_opcode(const ID *id,
*operation_code = OperationCode::NTREE_OUTPUT;
break;
case ID_RECALC_PROVISION_26:
case ID_RECALC_HIERARCHY:
*component_type = NodeType::HIERARCHY;
*operation_code = OperationCode::HIERARCHY;
break;
case ID_RECALC_PROVISION_27:
case ID_RECALC_PROVISION_28:
case ID_RECALC_PROVISION_29:
@ -749,7 +753,9 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
case ID_RECALC_NTREE_OUTPUT:
return "ID_RECALC_NTREE_OUTPUT";
case ID_RECALC_PROVISION_26:
case ID_RECALC_HIERARCHY:
return "ID_RECALC_HIERARCHY";
case ID_RECALC_PROVISION_27:
case ID_RECALC_PROVISION_28:
case ID_RECALC_PROVISION_29:

View File

@ -124,6 +124,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
object->base_flag = base_flag;
object->base_local_view_bits = base_local_view_bits;
/* Restore modifier's runtime data.
* NOTE: Data of unused modifiers will be freed there. */
restore_modifier_runtime_data(object);

View File

@ -65,6 +65,8 @@ const char *nodeTypeAsString(NodeType type)
return "COPY_ON_WRITE";
case NodeType::OBJECT_FROM_LAYER:
return "OBJECT_FROM_LAYER";
case NodeType::HIERARCHY:
return "HIERARCHY";
/* **** Evaluation-Related Outer Types (with Subdata) **** */
case NodeType::EVAL_POSE:
return "EVAL_POSE";
@ -140,6 +142,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
case NodeType::LAYER_COLLECTIONS:
case NodeType::COPY_ON_WRITE:
case NodeType::OBJECT_FROM_LAYER:
case NodeType::HIERARCHY:
case NodeType::AUDIO:
case NodeType::ARMATURE:
case NodeType::GENERIC_DATABLOCK:
@ -223,6 +226,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
case NodeType::LAYER_COLLECTIONS:
case NodeType::COPY_ON_WRITE:
case NodeType::OBJECT_FROM_LAYER:
case NodeType::HIERARCHY:
case NodeType::AUDIO:
case NodeType::ARMATURE:
case NodeType::GENERIC_DATABLOCK:

View File

@ -77,6 +77,8 @@ enum class NodeType {
/* Used by all operations which are updating object when something is
* changed in view layer. */
OBJECT_FROM_LAYER,
/* Hierarchy of objects and collections */
HIERARCHY,
/* Audio-related evaluation. */
AUDIO,
ARMATURE,

View File

@ -331,6 +331,7 @@ DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
DEG_COMPONENT_NODE_DEFINE(Hierarchy, HIERARCHY, 0);
DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0);
@ -366,6 +367,7 @@ void deg_register_component_depsnodes()
register_node_typeinfo(&DNTI_SHADING);
register_node_typeinfo(&DNTI_TRANSFORM);
register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
register_node_typeinfo(&DNTI_HIERARCHY);
register_node_typeinfo(&DNTI_DUPLI);
register_node_typeinfo(&DNTI_SYNCHRONIZATION);
register_node_typeinfo(&DNTI_AUDIO);

View File

@ -200,6 +200,7 @@ DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Shading);
DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Hierarchy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);

View File

@ -152,6 +152,7 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name)
ComponentNode *comp_node = find_component(type, name);
if (!comp_node) {
DepsNodeFactory *factory = type_get_factory(type);
BLI_assert(factory);
comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
/* Register. */

View File

@ -34,6 +34,9 @@ const char *operationCodeAsString(OperationCode opcode)
return "PARAMETERS_EXIT";
case OperationCode::VISIBILITY:
return "VISIBILITY";
/* Hierarchy. */
case OperationCode::HIERARCHY:
return "HIERARCHY";
/* Animation, Drivers, etc. */
case OperationCode::ANIMATION_ENTRY:
return "ANIMATION_ENTRY";

View File

@ -28,13 +28,16 @@ enum class OperationCode {
/* Placeholder for operations which don't need special mention */
OPERATION = 0,
/* Generic parameters evaluation. */
/* Generic parameters evaluation. --------------------------------------- */
ID_PROPERTY,
PARAMETERS_ENTRY,
PARAMETERS_EVAL,
PARAMETERS_EXIT,
VISIBILITY,
/* Hierarchy. ----------------------------------------------------------- */
HIERARCHY,
/* Animation, Drivers, etc. --------------------------------------------- */
/* NLA + Action */
ANIMATION_ENTRY,

View File

@ -582,6 +582,7 @@ static void eevee_cryptomatte_extract_render_passes(
const int pass_offset = pass * 2;
SNPRINTF_RLEN(cryptomatte_pass_name, render_pass_name_format, pass);
RenderPass *rp_object = RE_pass_find_by_name(rl, cryptomatte_pass_name, viewname);
float *rp_buffer_data = rp_object->buffer.data;
for (int y = 0; y < rect_height; y++) {
for (int x = 0; x < rect_width; x++) {
const int accum_buffer_offset = (rect_offset_x + x +
@ -589,15 +590,15 @@ static void eevee_cryptomatte_extract_render_passes(
accum_pixel_stride +
layer_index * layer_stride + pass_offset;
const int render_pass_offset = (y * rect_width + x) * 4;
rp_object->rect[render_pass_offset] = accum_buffer[accum_buffer_offset].hash;
rp_object->rect[render_pass_offset + 1] = accum_buffer[accum_buffer_offset].weight;
rp_buffer_data[render_pass_offset] = accum_buffer[accum_buffer_offset].hash;
rp_buffer_data[render_pass_offset + 1] = accum_buffer[accum_buffer_offset].weight;
if (levels_done + 1 < num_cryptomatte_levels) {
rp_object->rect[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash;
rp_object->rect[render_pass_offset + 3] = accum_buffer[accum_buffer_offset + 1].weight;
rp_buffer_data[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash;
rp_buffer_data[render_pass_offset + 3] = accum_buffer[accum_buffer_offset + 1].weight;
}
else {
rp_object->rect[render_pass_offset + 2] = 0.0f;
rp_object->rect[render_pass_offset + 3] = 0.0f;
rp_buffer_data[render_pass_offset + 2] = 0.0f;
rp_buffer_data[render_pass_offset + 3] = 0.0f;
}
}
}

View File

@ -271,7 +271,7 @@ static void eevee_render_color_result(RenderLayer *rl,
num_channels,
0,
GPU_DATA_FLOAT,
rp->rect);
rp->buffer.data);
}
static void eevee_render_result_combined(RenderLayer *rl,

View File

@ -276,8 +276,7 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
* However, on some implementation, we need a buffer with a few extra bytes for the read to
* happen correctly (see GLTexture::read()). So we need a custom memory allocation. */
/* Avoid memcpy(), replace the pointer directly. */
MEM_SAFE_FREE(rp->rect);
rp->rect = result;
RE_pass_set_buffer_data(rp, result);
BLI_mutex_unlock(&render->update_render_passes_mutex);
}
}
@ -291,7 +290,7 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
RenderPass *vector_rp = RE_pass_find_by_name(
render_layer, vector_pass_name.c_str(), view_name);
if (vector_rp) {
memset(vector_rp->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
memset(vector_rp->buffer.data, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
}
}
}

View File

@ -355,7 +355,7 @@ enum eVelocityStep : uint32_t {
struct VelocityObjectIndex {
/** Offset inside #VelocityObjectBuf for each timestep. Indexed using eVelocityStep. */
int3 ofs;
packed_int3 ofs;
/** Temporary index to copy this to the #VelocityIndexBuf. */
uint resource_id;
@ -367,11 +367,11 @@ BLI_STATIC_ASSERT_ALIGN(VelocityObjectIndex, 16)
struct VelocityGeometryIndex {
/** Offset inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
int3 ofs;
packed_int3 ofs;
/** If true, compute deformation motion blur. */
bool1 do_deform;
/** Length of data inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
int3 len;
packed_int3 len;
int _pad0;

View File

@ -49,8 +49,8 @@ void GPENCIL_render_init(GPENCIL_Data *vedata,
RenderPass *rpass_z_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
RenderPass *rpass_col_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
float *pix_z = (rpass_z_src) ? rpass_z_src->rect : NULL;
float *pix_col = (rpass_col_src) ? rpass_col_src->rect : NULL;
float *pix_z = (rpass_z_src) ? rpass_z_src->buffer.data : NULL;
float *pix_col = (rpass_col_src) ? rpass_col_src->buffer.data : NULL;
if (!pix_z || !pix_col) {
RE_engine_set_error_message(engine,
@ -160,6 +160,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
float *ro_buffer_data = rp->buffer.data;
GPU_framebuffer_read_depth(vedata->fbl->render_fb,
rect->xmin,
@ -167,7 +168,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
GPU_DATA_FLOAT,
rp->rect);
ro_buffer_data);
float winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
@ -177,12 +178,12 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
/* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
if (ro_buffer_data[i] == 1.0f) {
ro_buffer_data[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
ro_buffer_data[i] = ro_buffer_data[i] * 2.0f - 1.0f;
ro_buffer_data[i] = winmat[3][2] / (ro_buffer_data[i] + winmat[2][2]);
}
}
}
@ -193,11 +194,11 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
float range = fabsf(far - near);
for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
if (ro_buffer_data[i] == 1.0f) {
ro_buffer_data[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = rp->rect[i] * range - near;
ro_buffer_data[i] = ro_buffer_data[i] * range - near;
}
}
}
@ -221,7 +222,7 @@ static void GPENCIL_render_result_combined(struct RenderLayer *rl,
4,
0,
GPU_DATA_FLOAT,
rp->rect);
rp->buffer.data);
}
void GPENCIL_render_to_image(void *ved,

View File

@ -552,7 +552,7 @@ static void write_render_color_output(struct RenderLayer *layer,
4,
0,
GPU_DATA_FLOAT,
rp->rect);
rp->buffer.data);
}
}
@ -571,13 +571,13 @@ static void write_render_z_output(struct RenderLayer *layer,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
GPU_DATA_FLOAT,
rp->rect);
rp->buffer.data);
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(nullptr)) {
for (float &z : MutableSpan(rp->rect, pix_num)) {
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
if (z == 1.0f) {
z = 1e10f; /* Background */
}
@ -593,7 +593,7 @@ static void write_render_z_output(struct RenderLayer *layer,
float far = DRW_view_far_distance_get(nullptr);
float range = fabsf(far - near);
for (float &z : MutableSpan(rp->rect, pix_num)) {
for (float &z : MutableSpan(rp->buffer.data, pix_num)) {
if (z == 1.0f) {
z = 1e10f; /* Background */
}

View File

@ -105,6 +105,7 @@ static void workbench_render_result_z(struct RenderLayer *rl,
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
float *rp_buffer_data = rp->buffer.data;
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_read_depth(dfbl->default_fb,
@ -113,7 +114,7 @@ static void workbench_render_result_z(struct RenderLayer *rl,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
GPU_DATA_FLOAT,
rp->rect);
rp_buffer_data);
float winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
@ -123,12 +124,12 @@ static void workbench_render_result_z(struct RenderLayer *rl,
/* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
if (rp_buffer_data[i] == 1.0f) {
rp_buffer_data[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
rp_buffer_data[i] = rp_buffer_data[i] * 2.0f - 1.0f;
rp_buffer_data[i] = winmat[3][2] / (rp_buffer_data[i] + winmat[2][2]);
}
}
}
@ -139,11 +140,11 @@ static void workbench_render_result_z(struct RenderLayer *rl,
float range = fabsf(far - near);
for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
if (rp_buffer_data[i] == 1.0f) {
rp_buffer_data[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = rp->rect[i] * range - near;
rp_buffer_data[i] = rp_buffer_data[i] * range - near;
}
}
}
@ -208,7 +209,7 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer
4,
0,
GPU_DATA_FLOAT,
rp->rect);
rp->buffer.data);
workbench_render_result_z(render_layer, viewname, rect);
}

View File

@ -691,7 +691,7 @@ class Texture : NonCopyable {
eGPUTextureFormat format = GPU_texture_format(tx_);
for (auto i : IndexRange(mip_len)) {
mip_views_.append(
GPU_texture_create_view(name_, tx_, format, i, 1, 0, 9999, cube_as_array));
GPU_texture_create_view(name_, tx_, format, i, 1, 0, 9999, cube_as_array, false));
}
return true;
}
@ -726,7 +726,7 @@ class Texture : NonCopyable {
eGPUTextureFormat format = GPU_texture_format(tx_);
for (auto i : IndexRange(layer_len)) {
layer_views_.append(
GPU_texture_create_view(name_, tx_, format, 0, 9999, i, 1, cube_as_array));
GPU_texture_create_view(name_, tx_, format, 0, 9999, i, 1, cube_as_array, false));
}
return true;
}
@ -742,8 +742,8 @@ class Texture : NonCopyable {
{
if (stencil_view_ == nullptr) {
eGPUTextureFormat format = GPU_texture_format(tx_);
stencil_view_ = GPU_texture_create_view(name_, tx_, format, 0, 9999, 0, 9999, cube_as_array);
GPU_texture_stencil_texture_mode_set(stencil_view_, true);
stencil_view_ = GPU_texture_create_view(
name_, tx_, format, 0, 9999, 0, 9999, cube_as_array, true);
}
return stencil_view_;
}

View File

@ -51,7 +51,7 @@ void View::frustum_boundbox_calc(int view_id)
#endif
MutableSpan<float4> corners = {culling_[view_id].frustum_corners.corners,
ARRAY_SIZE(culling_[view_id].frustum_corners.corners)};
int64_t(ARRAY_SIZE(culling_[view_id].frustum_corners.corners))};
float left, right, bottom, top, near, far;
bool is_persp = data_[view_id].winmat[3][3] == 0.0f;
@ -107,7 +107,7 @@ void View::frustum_culling_sphere_calc(int view_id)
{
BoundSphere &bsphere = *reinterpret_cast<BoundSphere *>(&culling_[view_id].bound_sphere);
Span<float4> corners = {culling_[view_id].frustum_corners.corners,
ARRAY_SIZE(culling_[view_id].frustum_corners.corners)};
int64_t(ARRAY_SIZE(culling_[view_id].frustum_corners.corners))};
/* Extract Bounding Sphere */
if (data_[view_id].winmat[3][3] != 0.0f) {

View File

@ -6,12 +6,12 @@
#pragma once
#include "ED_file_indexer.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "ED_file_indexer.h"
/**
* File Indexer Service for indexing asset files.
*

View File

@ -66,7 +66,7 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
return;
}
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX_LIBEXTRA);
}
bool ED_asset_handle_get_use_relative_path(const AssetHandle *asset)

View File

@ -153,7 +153,7 @@ void AssetList::setup()
const bool use_asset_indexer = !USER_EXPERIMENTAL_TEST(&U, no_asset_indexing);
filelist_setindexer(files, use_asset_indexer ? &file_indexer_asset : &file_indexer_noop);
char path[FILE_MAXDIR] = "";
char path[FILE_MAX_LIBEXTRA] = "";
if (!asset_lib_path.empty()) {
STRNCPY(path, asset_lib_path.c_str());
}

View File

@ -142,8 +142,15 @@ struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm,
bool use_seams,
bool do_islands);
void BM_uv_element_map_free(struct UvElementMap *element_map);
/**
* Return the #UvElement associated with a given #BMLoop, or NULL if no association exists.
*
* \param element_map: The #UvElementMap to look in.
* \param l: The loop to search for.
* \return The #UvElement associated with #l, or NULL if not found. (e.g. the vertex is hidden.)
*/
struct UvElement *BM_uv_element_get(const struct UvElementMap *element_map,
const struct BMFace *efa,
const struct BMLoop *l);
struct UvElement *BM_uv_element_get_head(struct UvElementMap *element_map,
struct UvElement *child);

View File

@ -181,7 +181,7 @@ static bool eyedropper_cryptomatte_sample_renderlayer_fl(RenderLayer *render_lay
const int y = int(fpos[1] * render_pass->recty);
const int offset = 4 * (y * render_pass->rectx + x);
zero_v3(r_col);
r_col[0] = render_pass->rect[offset];
r_col[0] = render_pass->buffer.data[offset];
return true;
}
}

View File

@ -285,7 +285,7 @@ void UI_list_panel_unique_str(Panel *panel, char *r_name)
{
/* The panel sort-order will be unique for a specific panel type because the instanced
* panel list is regenerated for every change in the data order / length. */
snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder);
BLI_snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder);
}
/**

View File

@ -686,8 +686,8 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
/* Scan forwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l, offsets)) {
UvElement *next = BM_uv_element_get(element_map, element->l->next->f, element->l->next);
if (next->island == INVALID_ISLAND) {
UvElement *next = BM_uv_element_get(element_map, element->l->next);
if (next && next->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[next - element_map->storage];
stack_uv[stacksize_uv++] = tail;
while (tail) {
@ -702,8 +702,8 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
/* Scan backwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, offsets)) {
UvElement *prev = BM_uv_element_get(element_map, element->l->prev->f, element->l->prev);
if (prev->island == INVALID_ISLAND) {
UvElement *prev = BM_uv_element_get(element_map, element->l->prev);
if (prev && prev->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[prev - element_map->storage];
stack_uv[stacksize_uv++] = tail;
while (tail) {
@ -1186,11 +1186,11 @@ void BM_uv_element_map_free(UvElementMap *element_map)
}
}
UvElement *BM_uv_element_get(const UvElementMap *element_map, const BMFace *efa, const BMLoop *l)
UvElement *BM_uv_element_get(const UvElementMap *element_map, const BMLoop *l)
{
UvElement *element = element_map->vertex[BM_elem_index_get(l->v)];
while (element) {
if (element->l->f == efa) {
if (element->l == l) {
return element;
}
element = element->next;

View File

@ -207,11 +207,11 @@ static void image_buffer_rect_update(RenderJob *rj,
rv = RE_RenderViewGetById(rr, view_id);
/* find current float rect for display, first case is after composite... still weak */
if (rv->rectf) {
rectf = rv->rectf;
if (rv->combined_buffer.data) {
rectf = rv->combined_buffer.data;
}
else {
if (rv->rect32) {
if (rv->byte_buffer.data) {
/* special case, currently only happens with sequencer rendering,
* which updates the whole frame, so we can only mark display buffer
* as invalid here (sergey)

View File

@ -193,17 +193,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
RenderView *rv_del = rv->next;
BLI_remlink(&rr->views, rv_del);
if (rv_del->rectf) {
MEM_freeN(rv_del->rectf);
}
if (rv_del->rectz) {
MEM_freeN(rv_del->rectz);
}
if (rv_del->rect32) {
MEM_freeN(rv_del->rect32);
}
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
RE_RenderBuffer_data_free(&rv_del->z_buffer);
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
MEM_freeN(rv_del);
}
@ -227,17 +219,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
BLI_remlink(&rr->views, rv_del);
if (rv_del->rectf) {
MEM_freeN(rv_del->rectf);
}
if (rv_del->rectz) {
MEM_freeN(rv_del->rectz);
}
if (rv_del->rect32) {
MEM_freeN(rv_del->rect32);
}
RE_RenderBuffer_data_free(&rv_del->combined_buffer);
RE_RenderBuffer_data_free(&rv_del->z_buffer);
RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
MEM_freeN(rv_del);
}

View File

@ -666,7 +666,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect
rv = nullptr;
}
if (rv && rv->rectf) {
if (rv && rv->combined_buffer.data) {
if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) {
@ -1073,8 +1073,9 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
/* Create buffer in empty RenderView created in the init step. */
RenderResult *rr = RE_AcquireResultWrite(re);
RenderView *rv = (RenderView *)rr->views.first;
rv->rectf = static_cast<float *>(
MEM_callocN(sizeof(float[4]) * width * height, "texture render result"));
RE_RenderBuffer_assign_data(&rv->combined_buffer,
static_cast<float *>(MEM_callocN(sizeof(float[4]) * width * height,
"texture render result")));
RE_ReleaseResult(re);
/* Get texture image pool (if any) */
@ -1082,7 +1083,7 @@ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Rend
BKE_texture_fetch_images_for_pool(tex, img_pool);
/* Fill in image buffer. */
float *rect_float = rv->rectf;
float *rect_float = rv->combined_buffer.data;
float tex_coord[3] = {0.0f, 0.0f, 0.0f};
bool color_manage = true;

View File

@ -11,6 +11,7 @@
#include <cmath>
#include <cstdio>
#include <cstring>
#include <utility>
#include "MEM_guardedalloc.h"
@ -190,6 +191,8 @@ BLI_INLINE uchar f_to_char(const float val)
/* to avoid locking in tile initialization */
#define TILE_PENDING POINTER_FROM_INT(-1)
struct ProjPaintState;
/**
* This is mainly a convenience struct used so we can keep an array of images we use -
* their #ImBuf's, etc, in 1 array, When using threads this array is copied for each thread
@ -217,7 +220,8 @@ struct ProjStrokeHandle {
/* Support for painting from multiple views at once,
* currently used to implement symmetry painting,
* we can assume at least the first is set while painting. */
struct ProjPaintState *ps_views[8];
ProjPaintState *ps_views[8];
int ps_views_tot;
int symmetry_flags;
@ -5985,9 +5989,9 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
ProjStrokeHandle *ps_handle;
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
char symmetry_flag_views[BOUNDED_ARRAY_TYPE_SIZE<decltype(ps_handle->ps_views)>()] = {0};
ps_handle = MEM_cnew<ProjStrokeHandle>("ProjStrokeHandle");
ps_handle = MEM_new<ProjStrokeHandle>("ProjStrokeHandle");
ps_handle->scene = scene;
ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);

View File

@ -379,9 +379,8 @@ static void relaxation_iteration_uv(UvSculptData *sculptdata,
const UvElement *storage = sculptdata->elementMap->storage;
for (int j = 0; j < total_uvs; j++) {
const UvElement *ele_curr = storage + j;
const BMFace *efa = ele_curr->l->f;
const UvElement *ele_next = BM_uv_element_get(sculptdata->elementMap, efa, ele_curr->l->next);
const UvElement *ele_prev = BM_uv_element_get(sculptdata->elementMap, efa, ele_curr->l->prev);
const UvElement *ele_next = BM_uv_element_get(sculptdata->elementMap, ele_curr->l->next);
const UvElement *ele_prev = BM_uv_element_get(sculptdata->elementMap, ele_curr->l->prev);
const float *v_curr_co = ele_curr->l->v->co;
const float *v_prev_co = ele_prev->l->v->co;
@ -598,11 +597,13 @@ static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op)
op->customdata = nullptr;
}
static int uv_element_offset_from_face_get(
UvElementMap *map, BMFace *efa, BMLoop *l, int island_index, const bool doIslands)
static int uv_element_offset_from_face_get(UvElementMap *map,
BMLoop *l,
int island_index,
const bool do_islands)
{
UvElement *element = BM_uv_element_get(map, efa, l);
if (!element || (doIslands && element->island != island_index)) {
UvElement *element = BM_uv_element_get(map, l);
if (!element || (do_islands && element->island != island_index)) {
return -1;
}
return element - map->storage;
@ -686,14 +687,15 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
/* Mouse coordinates, useful for some functions like grab and sculpt all islands */
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
/* we need to find the active island here */
/* We need to find the active island here. */
if (do_island_optimization) {
UvElement *element;
UvNearestHit hit = uv_nearest_hit_init_max(&region->v2d);
uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
island_index = element->island;
UvElement *element = BM_uv_element_get(data->elementMap, hit.l);
if (element) {
island_index = element->island;
}
}
/* Count 'unique' UVs */
@ -759,18 +761,18 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
counter = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
int offset1, itmp1 = uv_element_offset_from_face_get(
data->elementMap, efa, l, island_index, do_island_optimization);
int offset2, itmp2 = uv_element_offset_from_face_get(
data->elementMap, efa, l->next, island_index, do_island_optimization);
int itmp1 = uv_element_offset_from_face_get(
data->elementMap, l, island_index, do_island_optimization);
int itmp2 = uv_element_offset_from_face_get(
data->elementMap, l->next, island_index, do_island_optimization);
/* Skip edge if not found(unlikely) or not on valid island */
if (itmp1 == -1 || itmp2 == -1) {
continue;
}
offset1 = uniqueUv[itmp1];
offset2 = uniqueUv[itmp2];
int offset1 = uniqueUv[itmp1];
int offset2 = uniqueUv[itmp2];
/* Using an order policy, sort UVs according to address space.
* This avoids having two different UvEdges with the same UVs on different positions. */

View File

@ -251,20 +251,24 @@ struct FileList {
BlendHandle *libfiledata;
/* Set given path as root directory,
* if last bool is true may change given string in place to a valid value.
* Returns True if valid dir. */
bool (*check_dir_fn)(FileList *, char *, const bool);
/**
* Set given path as root directory.
*
* \param do_change: When true, the callback may change given string in place to a valid value.
* \return True when `dirpath` is valid.
*/
bool (*check_dir_fn)(FileList *filelist, char dirpath[FILE_MAX_LIBEXTRA], const bool do_change);
/* Fill filelist (to be called by read job). */
void (*read_job_fn)(FileListReadJob *, bool *, bool *, float *);
/** Fill `filelist` (to be called by read job). */
void (*read_job_fn)(FileListReadJob *job_params, bool *stop, bool *do_update, float *progress);
/* Filter an entry of current filelist. */
bool (*filter_fn)(FileListInternEntry *, const char *, FileListFilter *);
/* Executed before filtering individual items, to set up additional filter data. */
void (*prepare_filter_fn)(const FileList *, FileListFilter *);
/** Filter an entry of current `filelist`. */
bool (*filter_fn)(FileListInternEntry *file, const char *root, FileListFilter *filter);
/** Executed before filtering individual items, to set up additional filter data. */
void (*prepare_filter_fn)(const FileList *filelist, FileListFilter *filter);
short tags; /* FileListTags */
/** #FileListTags. */
short tags;
};
/** #FileList.flags */
@ -1139,7 +1143,9 @@ void filelist_free_icons(void)
}
}
void filelist_file_get_full_path(const FileList *filelist, const FileDirEntry *file, char *r_path)
void filelist_file_get_full_path(const FileList *filelist,
const FileDirEntry *file,
char r_path[/*FILE_MAX_LIBEXTRA*/])
{
if (file->asset) {
const std::string asset_path = AS_asset_representation_full_path_get(file->asset);
@ -1343,40 +1349,46 @@ static void parent_dir_until_exists_or_default_root(char *dir)
}
}
static bool filelist_checkdir_dir(FileList * /*filelist*/, char *r_dir, const bool do_change)
static bool filelist_checkdir_dir(FileList * /*filelist*/,
char dirpath[FILE_MAX_LIBEXTRA],
const bool do_change)
{
if (do_change) {
parent_dir_until_exists_or_default_root(r_dir);
parent_dir_until_exists_or_default_root(dirpath);
return true;
}
return BLI_is_dir(r_dir);
return BLI_is_dir(dirpath);
}
static bool filelist_checkdir_lib(FileList * /*filelist*/, char *r_dir, const bool do_change)
static bool filelist_checkdir_lib(FileList * /*filelist*/,
char dirpath[FILE_MAX_LIBEXTRA],
const bool do_change)
{
char tdir[FILE_MAX_LIBEXTRA];
char *name;
const bool is_valid = (BLI_is_dir(r_dir) ||
(BKE_blendfile_library_path_explode(r_dir, tdir, nullptr, &name) &&
const bool is_valid = (BLI_is_dir(dirpath) ||
(BKE_blendfile_library_path_explode(dirpath, tdir, nullptr, &name) &&
BLI_is_file(tdir) && !name));
if (do_change && !is_valid) {
/* if not a valid library, we need it to be a valid directory! */
parent_dir_until_exists_or_default_root(r_dir);
parent_dir_until_exists_or_default_root(dirpath);
return true;
}
return is_valid;
}
static bool filelist_checkdir_main(FileList *filelist, char *r_dir, const bool do_change)
static bool filelist_checkdir_main(FileList *filelist,
char dirpath[FILE_MAX_LIBEXTRA],
const bool do_change)
{
/* TODO */
return filelist_checkdir_lib(filelist, r_dir, do_change);
return filelist_checkdir_lib(filelist, dirpath, do_change);
}
static bool filelist_checkdir_return_always_valid(struct FileList * /*filelist*/,
char * /*r_dir*/,
char /*dirpath*/[FILE_MAX_LIBEXTRA],
const bool /*do_change*/)
{
return true;
@ -1990,19 +2002,19 @@ bool filelist_is_dir(FileList *filelist, const char *path)
return filelist->check_dir_fn(filelist, (char *)path, false);
}
void filelist_setdir(FileList *filelist, char *r_dir)
void filelist_setdir(FileList *filelist, char dirpath[FILE_MAX_LIBEXTRA])
{
const bool allow_invalid = filelist->asset_library_ref != nullptr;
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
BLI_assert(strlen(dirpath) < FILE_MAX_LIBEXTRA);
BLI_path_abs(r_dir, BKE_main_blendfile_path_from_global());
BLI_path_normalize_dir(r_dir, FILE_MAX_LIBEXTRA);
const bool is_valid_path = filelist->check_dir_fn(filelist, r_dir, !allow_invalid);
BLI_path_abs(dirpath, BKE_main_blendfile_path_from_global());
BLI_path_normalize_dir(dirpath, FILE_MAX_LIBEXTRA);
const bool is_valid_path = filelist->check_dir_fn(filelist, dirpath, !allow_invalid);
BLI_assert(is_valid_path || allow_invalid);
UNUSED_VARS_NDEBUG(is_valid_path);
if (!STREQ(filelist->filelist.root, r_dir)) {
STRNCPY(filelist->filelist.root, r_dir);
if (!STREQ(filelist->filelist.root, dirpath)) {
STRNCPY(filelist->filelist.root, dirpath);
filelist->flags |= FL_FORCE_RESET;
}
}

View File

@ -101,9 +101,9 @@ void filelist_free(struct FileList *filelist);
const char *filelist_dir(const struct FileList *filelist);
bool filelist_is_dir(struct FileList *filelist, const char *path);
/**
* May modify in place given r_dir, which is expected to be FILE_MAX_LIBEXTRA length.
* May modify in place given `dirpath`, which is expected to be #FILE_MAX_LIBEXTRA length.
*/
void filelist_setdir(struct FileList *filelist, char *r_dir);
void filelist_setdir(struct FileList *filelist, char dirpath[1090 /*FILE_MAX_LIBEXTRA*/]);
/**
* Limited version of full update done by space_file's file_refresh(),

View File

@ -127,10 +127,10 @@ static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
{
RenderView *rv = RE_RenderViewGetById(rr, 0);
if (rv->rectf) {
if (rv->combined_buffer.data) {
return IFACE_("Composite");
}
if (rv->rect32) {
if (rv->byte_buffer.data) {
return IFACE_("Sequence");
}
return NULL;

View File

@ -73,7 +73,9 @@ static int unpack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
WM_cursor_wait(true);
BKE_packedfile_unpack_all_libraries(bmain, op->reports);
WM_cursor_wait(false);
return OPERATOR_FINISHED;
}
@ -225,7 +227,9 @@ static int unpack_all_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
if (method != PF_KEEP) {
WM_cursor_wait(true);
BKE_packedfile_unpack_all(bmain, op->reports, method); /* XXX PF_ASK can't work here */
WM_cursor_wait(false);
}
G.fileflags &= ~G_FILE_AUTOPACK;
@ -329,7 +333,9 @@ static int unpack_item_exec(bContext *C, wmOperator *op)
}
if (method != PF_KEEP) {
WM_cursor_wait(true);
BKE_packedfile_id_unpack(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
WM_cursor_wait(false);
}
G.fileflags &= ~G_FILE_AUTOPACK;

View File

@ -571,7 +571,6 @@ static void nla_fmodifier_panel_id(void *fcm_link, char *r_name)
{
FModifier *fcm = (FModifier *)fcm_link;
eFModifier_Types type = fcm->type;
snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_", NLA_FMODIFIER_PANEL_PREFIX);
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
BLI_snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_%s", NLA_FMODIFIER_PANEL_PREFIX, fmi->name);
}

View File

@ -395,14 +395,14 @@ static void unlink_collection_fn(bContext *C,
if (GS(tsep->id->name) == ID_OB) {
Object *ob = (Object *)tsep->id;
ob->instance_collection = nullptr;
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
}
else if (GS(tsep->id->name) == ID_GR) {
Collection *parent = (Collection *)tsep->id;
id_fake_user_set(&collection->id);
BKE_collection_child_remove(bmain, parent, collection);
DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
}
else if (GS(tsep->id->name) == ID_SCE) {
@ -410,7 +410,7 @@ static void unlink_collection_fn(bContext *C,
Collection *parent = scene->master_collection;
id_fake_user_set(&collection->id);
BKE_collection_child_remove(bmain, parent, collection);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
}
}
@ -457,14 +457,15 @@ static void unlink_object_fn(bContext *C,
if (GS(tsep->id->name) == ID_GR) {
Collection *parent = (Collection *)tsep->id;
BKE_collection_object_remove(bmain, parent, ob, true);
DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_HIERARCHY);
DEG_id_tag_update(&ob->id, ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
}
else if (GS(tsep->id->name) == ID_SCE) {
Scene *scene = (Scene *)tsep->id;
Collection *parent = scene->master_collection;
BKE_collection_object_remove(bmain, parent, ob, true);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
}
}
@ -2557,7 +2558,7 @@ static int outliner_delete_exec(bContext *C, wmOperator *op)
* cleanup tree here to prevent such cases. */
outliner_cleanup_tree(space_outliner);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_HIERARCHY);
DEG_relations_tag_update(bmain);
BKE_view_layer_synced_ensure(scene, view_layer);

View File

@ -296,9 +296,9 @@ static void createTransUVs(bContext *C, TransInfo *t)
countsel++;
if (island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
UvElement *element = BM_uv_element_get(elementmap, l);
if (element->flag == false) {
if (element && !element->flag) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
add_v2_v2(island_center[element->island].co, luv);
island_center[element->island].co_num++;
@ -370,7 +370,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
}
if (is_island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
UvElement *element = BM_uv_element_get(elementmap, l);
if (element) {
center = island_center[element->island].co;
}

View File

@ -86,7 +86,7 @@ static int iso_index_for_loop(const BMLoop *loop,
UvElementMap *element_map,
const int island_index)
{
UvElement *element = BM_uv_element_get(element_map, loop->f, loop);
UvElement *element = BM_uv_element_get(element_map, loop);
if (!element) {
return -1; /* Either unselected, or a different island. */
}

View File

@ -5451,8 +5451,10 @@ static void uv_isolate_selected_islands(const Scene *scene,
BM_elem_flag_enable(efa, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!uvedit_edge_select_test(scene, l, offsets)) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
is_island_not_selected[element->island] = true;
UvElement *element = BM_uv_element_get(elementmap, l);
if (element) {
is_island_not_selected[element->island] = true;
}
}
}
}
@ -5463,9 +5465,9 @@ static void uv_isolate_selected_islands(const Scene *scene,
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
UvElement *element = BM_uv_element_get(elementmap, l);
/* Deselect all elements of islands which are not completely selected. */
if (is_island_not_selected[element->island] == true) {
if (element && is_island_not_selected[element->island]) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
}

View File

@ -677,10 +677,10 @@ static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *
/* check to see if other vertex of edge belongs to same vertex as */
if (BM_elem_index_get(iter1->l->next->v) == elemindex2) {
iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->next);
iter2 = BM_uv_element_get(element_map, iter1->l->next);
}
else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2) {
iter2 = BM_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
iter2 = BM_uv_element_get(element_map, iter1->l->prev);
}
if (iter2) {
@ -1163,7 +1163,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
/* just to test if face was added for processing.
* uvs of unselected vertices will return NULL */
UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
UvElement *element = BM_uv_element_get(state->element_map, BM_FACE_FIRST_LOOP(efa));
if (element) {
int numoftris = efa->len - 2;
@ -1795,8 +1795,12 @@ static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
{
UvEdge tmp_edge;
UvElement *element1 = BM_uv_element_get(state->element_map, l->f, l);
UvElement *element2 = BM_uv_element_get(state->element_map, l->f, l->next);
UvElement *element1 = BM_uv_element_get(state->element_map, l);
UvElement *element2 = BM_uv_element_get(state->element_map, l->next);
if (!element1 || !element2) {
return NULL;
}
int uv1 = state->map[element1 - state->element_map->storage];
int uv2 = state->map[element2 - state->element_map->storage];
@ -1906,10 +1910,9 @@ static StitchState *stitch_init(bContext *C,
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
UvElement *element = BM_uv_element_get(state->element_map, efa, l);
UvElement *element = BM_uv_element_get(state->element_map, l);
int itmp1 = element - state->element_map->storage;
int itmp2 = BM_uv_element_get(state->element_map, efa, l->next) -
state->element_map->storage;
int itmp2 = BM_uv_element_get(state->element_map, l->next) - state->element_map->storage;
UvEdge *edge;
int offset1 = map[itmp1];
@ -2015,8 +2018,8 @@ static StitchState *stitch_init(bContext *C,
faceIndex = state_init->to_select[selected_count].faceIndex;
elementIndex = state_init->to_select[selected_count].elementIndex;
efa = BM_face_at_index(em->bm, faceIndex);
element = BM_uv_element_get(
state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
element = BM_uv_element_get(state->element_map,
BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
stitch_select_uv(element, state, 1);
}
}
@ -2031,13 +2034,12 @@ static StitchState *stitch_init(bContext *C,
faceIndex = state_init->to_select[selected_count].faceIndex;
elementIndex = state_init->to_select[selected_count].elementIndex;
efa = BM_face_at_index(em->bm, faceIndex);
element = BM_uv_element_get(
state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
element = BM_uv_element_get(state->element_map,
BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
uv1 = map[element - state->element_map->storage];
element = BM_uv_element_get(
state->element_map,
efa,
BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
uv2 = map[element - state->element_map->storage];
@ -2070,7 +2072,7 @@ static StitchState *stitch_init(bContext *C,
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (uvedit_uv_select_test(scene, l, offsets)) {
UvElement *element = BM_uv_element_get(state->element_map, efa, l);
UvElement *element = BM_uv_element_get(state->element_map, l);
if (element) {
stitch_select_uv(element, state, 1);
}
@ -2111,7 +2113,7 @@ static StitchState *stitch_init(bContext *C,
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
UvElement *element = BM_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
UvElement *element = BM_uv_element_get(state->element_map, BM_FACE_FIRST_LOOP(efa));
if (element) {
state->tris_per_island[element->island] += (efa->len > 2) ? efa->len - 2 : 0;
@ -2484,8 +2486,10 @@ static StitchState *stitch_select(bContext *C,
}
/* This works due to setting of tmp in find nearest uv vert */
UvElement *element = BM_uv_element_get(state->element_map, hit.efa, hit.l);
stitch_select_uv(element, state, false);
UvElement *element = BM_uv_element_get(state->element_map, hit.l);
if (element) {
stitch_select_uv(element, state, false);
}
return state;
}

View File

@ -445,12 +445,13 @@ static void prepare(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph)
RenderLayer *rl = RE_GetRenderLayer(re->result, view_layer->name);
bool diffuse = false, z = false;
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
float *rpass_buffer_data = rpass->buffer.data;
if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE_COLOR)) {
controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
controller->setPassDiffuse(rpass_buffer_data, rpass->rectx, rpass->recty);
diffuse = true;
}
if (STREQ(rpass->name, RE_PASSNAME_Z)) {
controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
controller->setPassZ(rpass_buffer_data, rpass->rectx, rpass->recty);
z = true;
}
}

View File

@ -102,7 +102,7 @@ static float get_aspect_scaled_extent(const rctf &extent, const UVPackIsland_Par
}
/**
* \return true iff `b` is a preferred layout over `a`, given the packing parameters supplied.
* \return true if `b` is a preferred layout over `a`, given the packing parameters supplied.
*/
static bool is_larger(const rctf &a, const rctf &b, const UVPackIsland_Params &params)
{

View File

@ -60,6 +60,7 @@
# define bool3 bvec3
# define bool4 bvec4
# define packed_float3 vec3
# define packed_int3 int3
# endif
#else /* C / C++ */
@ -85,6 +86,7 @@ using bool2 = blender::int2;
using bool3 = blender::int3;
using bool4 = blender::int4;
using packed_float3 = blender::float3;
using packed_int3 = blender::int3;
# else /* C */
typedef float float2[2];
@ -102,6 +104,7 @@ typedef int bool2[2];
typedef int bool3[2];
typedef int bool4[4];
typedef float3 packed_float3;
typedef int3 packed_int3;
# endif
#endif

View File

@ -700,6 +700,13 @@ void GPU_texture_free(GPUTexture *texture);
* \note If \a cube_as_array is true, then the created view will be a 2D array texture instead of a
* cube-map texture or cube-map-array texture.
*
* For Depth-Stencil texture view formats:
* \note If \a use_stencil is true, the texture is expected to be bound to a UINT sampler and will
* return the stencil value (in a range of [0..255]) as the first component.
* \note If \a use_stencil is false (default), the texture is expected to be bound to a DEPTH
* sampler and will return the normalized depth value (in a range of [0..1]) as the first
* component.
*
* TODO(fclem): Target conversion (ex: Texture 2D as Texture 2D Array) is not implemented yet.
*/
GPUTexture *GPU_texture_create_view(const char *name,
@ -709,7 +716,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
int mip_len,
int layer_start,
int layer_len,
bool cube_as_array);
bool cube_as_array,
bool use_stencil);
/** \} */
@ -908,16 +916,6 @@ void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mo
*/
void GPU_texture_swizzle_set(GPUTexture *texture, const char swizzle[4]);
/**
* Set a depth-stencil texture read mode.
*
* If \a use_stencil is true, the texture is expected to be bound to a UINT sampler and will return
* the stencil value (in a range of [0..255]) as the first component.
* If \a use_stencil is false, the texture is expected to be bound to a DEPTH sampler and will
* return the normalized depth value (in a range of [0..1]) as the first component.
*/
void GPU_texture_stencil_texture_mode_set(GPUTexture *texture, bool use_stencil);
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -139,7 +139,8 @@ bool Texture::init_view(GPUTexture *src_,
int mip_len,
int layer_start,
int layer_len,
bool cube_as_array)
bool cube_as_array,
bool use_stencil)
{
const Texture *src = unwrap(src_);
w_ = src->w_;
@ -172,7 +173,7 @@ bool Texture::init_view(GPUTexture *src_,
type_ = (type_ & ~GPU_TEXTURE_CUBE) | GPU_TEXTURE_2D_ARRAY;
}
sampler_state = src->sampler_state;
return this->init_internal(src_, mip_start, layer_start);
return this->init_internal(src_, mip_start, layer_start, use_stencil);
}
void Texture::usage_set(eGPUTextureUsage usage_flags)
@ -457,7 +458,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
int mip_len,
int layer_start,
int layer_len,
bool cube_as_array)
bool cube_as_array,
bool use_stencil)
{
BLI_assert(mip_len > 0);
BLI_assert(layer_len > 0);
@ -472,7 +474,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
mip_len,
layer_start,
layer_len,
cube_as_array);
cube_as_array,
use_stencil);
return wrap(view);
}
@ -668,12 +671,6 @@ void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4])
reinterpret_cast<Texture *>(tex)->swizzle_set(swizzle);
}
void GPU_texture_stencil_texture_mode_set(GPUTexture *tex, bool use_stencil)
{
BLI_assert(GPU_texture_has_stencil_format(tex) || !use_stencil);
reinterpret_cast<Texture *>(tex)->stencil_texture_mode_set(use_stencil);
}
void GPU_texture_free(GPUTexture *tex_)
{
Texture *tex = reinterpret_cast<Texture *>(tex_);

View File

@ -139,13 +139,13 @@ class Texture {
int mip_len,
int layer_start,
int layer_len,
bool cube_as_array);
bool cube_as_array,
bool use_stencil);
virtual void generate_mipmap() = 0;
virtual void copy_to(Texture *tex) = 0;
virtual void clear(eGPUDataFormat format, const void *data) = 0;
virtual void swizzle_set(const char swizzle_mask[4]) = 0;
virtual void stencil_texture_mode_set(bool use_stencil) = 0;
virtual void mip_range_set(int min, int max) = 0;
virtual void *read(int mip, eGPUDataFormat format) = 0;
@ -313,7 +313,10 @@ class Texture {
protected:
virtual bool init_internal() = 0;
virtual bool init_internal(GPUVertBuf *vbo) = 0;
virtual bool init_internal(GPUTexture *src, int mip_offset, int layer_offset) = 0;
virtual bool init_internal(GPUTexture *src,
int mip_offset,
int layer_offset,
bool use_stencil) = 0;
};
/* Syntactic sugar. */

View File

@ -219,6 +219,7 @@ class MTLTexture : public Texture {
MTLTextureSwizzleChannels mtl_swizzle_mask_;
bool mip_range_dirty_ = false;
bool texture_view_stencil_ = false;
int mip_texture_base_level_ = 0;
int mip_texture_max_level_ = 1000;
int mip_texture_base_layer_ = 0;
@ -256,9 +257,6 @@ class MTLTexture : public Texture {
void copy_to(Texture *dst) override;
void clear(eGPUDataFormat format, const void *data) override;
void swizzle_set(const char swizzle_mask[4]) override;
void stencil_texture_mode_set(bool use_stencil) override{
/* TODO(Metal): implement. */
};
void mip_range_set(int min, int max) override;
void *read(int mip, eGPUDataFormat type) override;
@ -285,7 +283,8 @@ class MTLTexture : public Texture {
bool init_internal(GPUVertBuf *vbo) override;
bool init_internal(GPUTexture *src,
int mip_offset,
int layer_offset) override; /* Texture View */
int layer_offset,
bool use_stencil) override; /* Texture View */
private:
/* Common Constructor, default initialization. */
@ -516,6 +515,32 @@ inline std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat t
return "";
}
/* Fetch Metal texture type from GPU texture type. */
inline MTLTextureType to_metal_type(eGPUTextureType type)
{
switch (type) {
case GPU_TEXTURE_1D:
return MTLTextureType1D;
case GPU_TEXTURE_2D:
return MTLTextureType2D;
case GPU_TEXTURE_3D:
return MTLTextureType3D;
case GPU_TEXTURE_CUBE:
return MTLTextureTypeCube;
case GPU_TEXTURE_BUFFER:
return MTLTextureTypeTextureBuffer;
case GPU_TEXTURE_1D_ARRAY:
return MTLTextureType1DArray;
case GPU_TEXTURE_2D_ARRAY:
return MTLTextureType2DArray;
case GPU_TEXTURE_CUBE_ARRAY:
return MTLTextureTypeCubeArray;
default:
BLI_assert_unreachable();
}
return MTLTextureType2D;
}
/* Determine whether format is writable or not. Use mtl_format_get_writeable_view_format(..) for
* these. */
inline bool mtl_format_is_writable(MTLPixelFormat format)

View File

@ -159,14 +159,35 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
break;
}
/* Determine texture view format. If texture view is used as a stencil view, we instead provide
* the equivalent format for performing stencil reads/samples. */
MTLPixelFormat texture_view_pixel_format = texture_.pixelFormat;
if (texture_view_stencil_) {
switch (texture_view_pixel_format) {
case MTLPixelFormatDepth24Unorm_Stencil8:
texture_view_pixel_format = MTLPixelFormatX24_Stencil8;
break;
case MTLPixelFormatDepth32Float_Stencil8:
texture_view_pixel_format = MTLPixelFormatX32_Stencil8;
break;
default:
BLI_assert_msg(false, "Texture format does not support stencil views.");
break;
}
}
/* Note: Texture type for cube maps can be overridden as a 2D array. This is done
* via modifying this textures type flags. */
MTLTextureType texture_view_texture_type = to_metal_type(type_);
int range_len = min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
texture_.mipmapLevelCount - mip_texture_base_level_);
BLI_assert(range_len > 0);
BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
BLI_assert(mip_texture_base_layer_ < num_slices);
mip_swizzle_view_ = [texture_
newTextureViewWithPixelFormat:texture_.pixelFormat
textureType:texture_.textureType
newTextureViewWithPixelFormat:texture_view_pixel_format
textureType:texture_view_texture_type
levels:NSMakeRange(mip_texture_base_level_, range_len)
slices:NSMakeRange(mip_texture_base_layer_, num_slices)
swizzle:mtl_swizzle_mask_];
@ -1810,7 +1831,10 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
return true;
}
bool gpu::MTLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
bool gpu::MTLTexture::init_internal(GPUTexture *src,
int mip_offset,
int layer_offset,
bool use_stencil)
{
BLI_assert(src);
@ -1841,6 +1865,13 @@ bool gpu::MTLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_o
is_baked_ = true;
is_dirty_ = false;
/* Stencil view support. */
texture_view_stencil_ = false;
if (use_stencil) {
BLI_assert(ELEM(format_, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8));
texture_view_stencil_ = true;
}
/* Bake mip swizzle view. */
bake_mip_swizzle_view();
return true;

View File

@ -178,7 +178,7 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
return true;
}
bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil)
{
BLI_assert(GLContext::texture_storage_support);
@ -197,6 +197,11 @@ bool GLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_offset)
debug::object_label(GL_TEXTURE, tex_id_, name_);
/* Stencil view support. */
if (ELEM(format_, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8)) {
stencil_texture_mode_set(use_stencil);
}
return true;
}

View File

@ -76,7 +76,6 @@ class GLTexture : public Texture {
void copy_to(Texture *dst) override;
void clear(eGPUDataFormat format, const void *data) override;
void swizzle_set(const char swizzle_mask[4]) override;
void stencil_texture_mode_set(bool use_stencil) override;
void mip_range_set(int min, int max) override;
void *read(int mip, eGPUDataFormat type) override;
@ -117,10 +116,11 @@ class GLTexture : public Texture {
/** Return true on success. */
bool init_internal(GPUVertBuf *vbo) override;
/** Return true on success. */
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset) override;
bool init_internal(GPUTexture *src, int mip_offset, int layer_offset, bool use_stencil) override;
private:
bool proxy_check(int mip);
void stencil_texture_mode_set(bool use_stencil);
void update_sub_direct_state_access(
int mip, int offset[3], int extent[3], GLenum gl_format, GLenum gl_type, const void *data);
GPUFrameBuffer *framebuffer_get();

View File

@ -97,11 +97,6 @@ void VKTexture::swizzle_set(const char /*swizzle_mask*/[4])
NOT_YET_IMPLEMENTED;
}
void VKTexture::stencil_texture_mode_set(bool /*use_stencil*/)
{
NOT_YET_IMPLEMENTED;
}
void VKTexture::mip_range_set(int /*min*/, int /*max*/)
{
NOT_YET_IMPLEMENTED;
@ -252,7 +247,10 @@ bool VKTexture::init_internal(GPUVertBuf *vbo)
return true;
}
bool VKTexture::init_internal(GPUTexture * /*src*/, int /*mip_offset*/, int /*layer_offset*/)
bool VKTexture::init_internal(GPUTexture * /*src*/,
int /*mip_offset*/,
int /*layer_offset*/,
bool /*use_stencil*/)
{
NOT_YET_IMPLEMENTED;
return false;

Some files were not shown because too many files have changed in this diff Show More