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 # BLF drawing routine
font_id = font_info["font_id"] font_id = font_info["font_id"]
blf.position(font_id, 2, 80, 0) blf.position(font_id, 2, 80, 0)
blf.size(font_id, 50) blf.size(font_id, 50.0)
blf.draw(font_id, "Hello World") 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. # Remove all objects in scene rather than the selected ones.
import bpy import bpy
from bpy import context from bpy import context
override = context.copy() context_override = context.copy()
override["selected_objects"] = list(context.scene.objects) context_override["selected_objects"] = list(context.scene.objects)
with context.temp_override(**override): with context.temp_override(**context_override):
bpy.ops.object.delete() bpy.ops.object.delete()

View File

@ -27,17 +27,11 @@ Keywords and Positional Arguments
For calling operators keywords are used for operator properties and For calling operators keywords are used for operator properties and
positional arguments are used to define how the operator is called. 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 .. code-block:: python
bpy.ops.test.operator(override_context, execution_context, undo) bpy.ops.test.operator(execution_context, undo)
- override_context - ``dict`` type.
.. deprecated:: 3.2
:class:`bpy.types.Context.temp_override` should be used instead of this argument.
- execution_context - ``str`` (enum). - execution_context - ``str`` (enum).
- undo - ``bool`` type. - 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. 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. 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` 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. 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. 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 from gpu_extras.batch import batch_for_shader
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)] 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}) batch = batch_for_shader(shader, 'LINES', {"pos": coords})

View File

@ -17,7 +17,7 @@ indices = (
(4, 5), (4, 6), (5, 7), (6, 7), (4, 5), (4, 6), (5, 7), (6, 7),
(0, 4), (1, 5), (2, 6), (3, 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) 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))] 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( batch = batch_for_shader(
shader, 'TRIS', shader, 'TRIS',
{"pos": vertices, "color": vertex_colors}, {"pos": vertices, "color": vertex_colors},

View File

@ -13,7 +13,7 @@ vertices = (
indices = ( indices = (
(0, 1, 2), (2, 1, 3)) (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) 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] image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image) texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('2D_IMAGE') shader = gpu.shader.from_builtin('IMAGE')
batch = batch_for_shader( batch = batch_for_shader(
shader, 'TRI_FAN', shader, 'TRI_FAN',
{ {
@ -45,7 +45,7 @@ IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME] image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image) texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('3D_IMAGE') shader = gpu.shader.from_builtin('IMAGE')
batch = batch_for_shader( batch = batch_for_shader(
shader, 'TRIS', shader, 'TRIS',
{ {

View File

@ -1305,9 +1305,7 @@ void PathTrace::set_guiding_params(const GuidingParams &guiding_params, const bo
break; break;
} }
} }
# if OPENPGL_VERSION_MINOR >= 4
field_args.deterministic = guiding_params.deterministic; field_args.deterministic = guiding_params.deterministic;
# endif
reinterpret_cast<PGLKDTreeArguments *>(field_args.spatialSturctureArguments)->maxDepth = 16; reinterpret_cast<PGLKDTreeArguments *>(field_args.spatialSturctureArguments)->maxDepth = 16;
openpgl::cpp::Device *guiding_device = static_cast<openpgl::cpp::Device *>( openpgl::cpp::Device *guiding_device = static_cast<openpgl::cpp::Device *>(
device_->get_guiding_device()); device_->get_guiding_device());
@ -1374,12 +1372,7 @@ void PathTrace::guiding_update_structures()
/* we wait until we have at least 1024 samples */ /* we wait until we have at least 1024 samples */
if (num_valid_samples >= 1024) { 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_); guiding_field_->Update(*guiding_sample_data_storage_);
# endif
guiding_update_count++; guiding_update_count++;
VLOG_DEBUG << "Path guiding field valid: " << guiding_field_->Validate(); 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 # if PATH_GUIDING_LEVEL >= 2
const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light; const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights; 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); 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 # endif
# ifdef WITH_CYCLES_DEBUG # ifdef WITH_CYCLES_DEBUG

View File

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

View File

@ -620,12 +620,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
const Spectrum emission = volume_emission_integrate( const Spectrum emission = volume_emission_integrate(
&coeff, closure_flag, transmittance, dt); &coeff, closure_flag, transmittance, dt);
accum_emission += result.indirect_throughput * emission; accum_emission += result.indirect_throughput * emission;
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329 guiding_record_volume_emission(kg, state, emission);
if (kernel_data.integrator.max_volume_bounce > 1)
# endif
{
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; const Spectrum phase_weight = bsdf_eval_sum(&phase_eval) / phase_pdf;
/* Add phase function sampling data to the path segment. */ /* Add phase function sampling data to the path segment. */
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329 guiding_record_volume_bounce(
if (kernel_data.integrator.max_volume_bounce > 1) kg, state, sd, phase_weight, phase_pdf, normalize(phase_wo), sampled_roughness);
# endif
{
guiding_record_volume_bounce(
kg, state, sd, phase_weight, phase_pdf, normalize(phase_wo), sampled_roughness);
}
/* Update throughput. */ /* Update throughput. */
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
const Spectrum throughput_phase = throughput * phase_weight; 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; const float3 direct_P = ray->P + result.direct_t * ray->D;
# ifdef __PATH_GUIDING__ # 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) { if (kernel_data.integrator.use_guiding) {
# endif
# if PATH_GUIDING_LEVEL >= 1 # if PATH_GUIDING_LEVEL >= 1
if (result.direct_sample_method == VOLUME_SAMPLE_DISTANCE) { if (result.direct_sample_method == VOLUME_SAMPLE_DISTANCE) {
/* If the direct scatter event is generated using VOLUME_SAMPLE_DISTANCE the direct event /* 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 defined(__PATH_GUIDING__)
# if PATH_GUIDING_LEVEL >= 1 # if PATH_GUIDING_LEVEL >= 1
if (!guiding_generated_new_segment) { if (!guiding_generated_new_segment) {
# if OPENPGL_VERSION_MINOR < 5 // WORKAROUND #104329 guiding_record_volume_segment(kg, state, sd.P, sd.wi);
if (kernel_data.integrator.max_volume_bounce > 1)
# endif
{
guiding_record_volume_segment(kg, state, sd.P, sd.wi);
}
} }
# endif # endif
# if PATH_GUIDING_LEVEL >= 4 # 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].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 = guiding_bsdf_pdf(kg, state, ris_samples[0].wo);
ris_samples[0].guide_pdf *= (1.0f - bssrdf_sampling_prob); 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( ris_samples[0].incoming_radiance_pdf = guiding_surface_incoming_radiance_pdf(
kg, state, ris_samples[0].wo); 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); 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( ris_samples[1].guide_pdf = guiding_bsdf_sample(
kg, state, float3_to_float2(ris_samples[1].rand), &ris_samples[1].wo); kg, state, float3_to_float2(ris_samples[1].rand), &ris_samples[1].wo);
ris_samples[1].guide_pdf *= (1.0f - bssrdf_sampling_prob); 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( ris_samples[1].incoming_radiance_pdf = guiding_surface_incoming_radiance_pdf(
kg, state, ris_samples[1].wo); 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( 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); kg, sd, ris_samples[1].wo, &ris_samples[1].bsdf_eval, unguided_bsdf_pdfs, 0);
ris_samples[1].label = ris_samples[0].label; ris_samples[1].label = ris_samples[0].label;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1419,7 +1419,11 @@ class WM_OT_properties_edit(Operator):
return rna_custom_property_subtype_number_items return rna_custom_property_subtype_number_items
case 'FLOAT_ARRAY': case 'FLOAT_ARRAY':
return rna_custom_property_subtype_vector_items 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): def property_type_update_cb(self, context):
self.subtype = 'NONE' self.subtype = 'NONE'

View File

@ -11,7 +11,7 @@ def draw_callback_px(self, context):
# draw some text # draw some text
blf.position(font_id, 15, 30, 0) 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))) blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
# 50% alpha, 2 pixel width line # 50% alpha, 2 pixel width line

View File

@ -38,14 +38,16 @@ struct Library;
struct MainLock; struct MainLock;
struct UniqueName_Map; 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 { typedef struct BlendThumbnail {
int width, height; int width, height;
/** Pixel data, RGBA (repeated): `sizeof(char[4]) * width * height`. */
char rect[0]; char rect[0];
} BlendThumbnail; } BlendThumbnail;
/* Structs caching relations between data-blocks in a given Main. */ /** Structs caching relations between data-blocks in a given Main. */
typedef struct MainIDRelationsEntryItem { typedef struct MainIDRelationsEntryItem {
struct MainIDRelationsEntryItem *next; struct MainIDRelationsEntryItem *next;
@ -123,10 +125,10 @@ typedef struct Main {
/** /**
* The file-path of this blend file, an empty string indicates an unsaved file. * 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 * \note For the current loaded blend file this path must be absolute & normalized.
* to prevent redundant leading slashes or current-working-directory relative paths * This prevents redundant leading slashes or current-working-directory relative paths
* from causing problems with absolute/relative patch conversion that relies on this being * from causing problems with absolute/relative conversion which relies on this `filepath`
* an absolute path. See #BLI_path_canonicalize_native. * being absolute. See #BLI_path_canonicalize_native.
* *
* This rule is not strictly enforced as in some cases loading a #Main is performed * This rule is not strictly enforced as in some cases loading a #Main is performed
* to read data temporarily (preferences & startup) for e.g. * to read data temporarily (preferences & startup) for e.g.
@ -230,10 +232,10 @@ typedef struct Main {
*/ */
struct MainIDRelations *relations; 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; 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 UniqueName_Map *name_map;
struct MainLock *lock; 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, int BKE_packedfile_write_to_file(struct ReportList *reports,
const char *ref_file_name, const char *ref_file_name,
const char *filepath, const char *filepath,
struct PackedFile *pf, struct PackedFile *pf);
bool guimode);
/* Free. */ /* Free. */

View File

@ -1402,7 +1402,7 @@ bool BKE_collection_object_add_notest(Main *bmain, Collection *collection, Objec
BKE_main_collection_sync(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; return true;
} }
@ -1470,7 +1470,7 @@ bool BKE_collection_object_remove(Main *bmain,
BKE_main_collection_sync(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; return true;
} }

View File

@ -71,7 +71,8 @@ using blender::Vector;
#define CUSTOMDATA_GROW 5 #define CUSTOMDATA_GROW 5
/* ensure typemap size is ok */ /* 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"}; 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) { if (rpass) {
// printf("load from pass %s\n", rpass->name); // 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); 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; ibuf->channels = rpass->channels;
IMB_assign_shared_float_buffer(ibuf, rpass->buffer.data, rpass->buffer.sharing_info);
BKE_imbuf_stamp_info(ima->rr, ibuf); BKE_imbuf_stamp_info(ima->rr, ibuf);
image_init_after_load(ima, iuser, 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); 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; ibuf->channels = rpass->channels;
BKE_imbuf_stamp_info(ima->rr, ibuf); 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; Render *re;
RenderView *rv; RenderView *rv;
float *rectf, *rectz; RenderBuffer *combined_buffer, *z_buffer;
uint *rect; RenderByteBuffer *byte_buffer;
float dither; float dither;
int channels, layer, pass; int channels, layer, pass;
ImBuf *ibuf; 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) { else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
rres = *(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)) { 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 */ /* this gives active layer, composite or sequence result */
if (rv == nullptr) { if (rv == nullptr) {
rect = (uint *)rres.rect32; byte_buffer = &rres.byte_buffer;
rectf = rres.rectf; combined_buffer = &rres.combined_buffer;
rectz = rres.rectz; z_buffer = &rres.z_buffer;
} }
else { else {
rect = (uint *)rv->rect32; byte_buffer = &rv->byte_buffer;
rectf = rv->rectf; combined_buffer = &rv->combined_buffer;
rectz = rv->rectz; z_buffer = &rv->z_buffer;
} }
dither = iuser->scene->r.dither_intensity; 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) { if (rres.have_combined && layer == 0) {
/* pass */ /* 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 /* rect32 is set when there's a Sequence pass, this pass seems
* to have layer=0 (this is from image_buttons.c) * to have layer=0 (this is from image_buttons.c)
* in this case we ignore float buffer, because it could have * in this case we ignore float buffer, because it could have
* hung from previous pass which was float * hung from previous pass which was float
*/ */
rectf = nullptr; combined_buffer = nullptr;
} }
else if (rres.layers.first) { else if (rres.layers.first) {
RenderLayer *rl = static_cast<RenderLayer *>( RenderLayer *rl = static_cast<RenderLayer *>(
@ -4410,7 +4410,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
if (rl) { if (rl) {
RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr); RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr);
if (rpass) { if (rpass) {
rectf = rpass->rect; combined_buffer = &rpass->buffer;
if (pass != 0) { if (pass != 0) {
channels = rpass->channels; channels = rpass->channels;
dither = 0.0f; /* don't dither passes */ 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) { for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) {
if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) { 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. * 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); const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace); IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace);
} }
/* invalidate color managed buffers if render result changed */ /* invalidate color managed buffers if render result changed */
BLI_thread_lock(LOCK_COLORMANAGE); 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; 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_freerectImBuf(ibuf);
IMB_assign_byte_buffer(ibuf, (uint8_t *)rect, IB_DO_NOT_TAKE_OWNERSHIP); if (byte_buffer) {
IMB_assign_float_buffer(ibuf, rectf, IB_DO_NOT_TAKE_OWNERSHIP); IMB_assign_shared_byte_buffer(ibuf, byte_buffer->data, byte_buffer->sharing_info);
IMB_assign_float_z_buffer(ibuf, rectz, IB_DO_NOT_TAKE_OWNERSHIP); }
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 /* TODO(sergey): Make this faster by either simply referencing the stamp
* or by changing both ImBuf and RenderResult to use same data type to * 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. */ /* Compositing result. */
if (rr->have_combined) { if (rr->have_combined) {
LISTBASE_FOREACH (RenderView *, rview, &rr->views) { LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
if (!rview->rectf) { if (!rview->combined_buffer.data) {
continue; continue;
} }
@ -756,10 +756,11 @@ bool BKE_image_render_write_exr(ReportList *reports,
continue; continue;
} }
float *output_rect = (save_as_render) ? float *output_rect =
image_exr_from_scene_linear_to_output( (save_as_render) ?
rview->rectf, rr->rectx, rr->recty, 4, imf, tmp_output_rects) : image_exr_from_scene_linear_to_output(
rview->rectf; rview->combined_buffer.data, rr->rectx, rr->recty, 4, imf, tmp_output_rects) :
rview->combined_buffer.data;
for (int a = 0; a < channels; a++) { for (int a = 0; a < channels; a++) {
char passname[EXR_PASS_MAXNAME]; 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); 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" : ""; 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 = float *output_rect =
(save_as_render && pass_RGBA) ? (save_as_render && pass_RGBA) ?
image_exr_from_scene_linear_to_output( image_exr_from_scene_linear_to_output(
rp->rect, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) : rp->buffer.data, rr->rectx, rr->recty, rp->channels, imf, tmp_output_rects) :
rp->rect; rp->buffer.data;
for (int a = 0; a < std::min(channels, rp->channels); a++) { for (int a = 0; a < std::min(channels, rp->channels); a++) {
/* Save Combined as RGBA or RGB if single layer save. */ /* 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{}; IDPropertyTemplate idprop{};
idprop.array.len = ARRAY_SIZE(dimensions); idprop.array.len = 3;
idprop.array.type = IDP_FLOAT; idprop.array.type = IDP_FLOAT;
IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions"); 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, int BKE_packedfile_write_to_file(ReportList *reports,
const char *ref_file_name, const char *ref_file_name,
const char *filepath_rel, const char *filepath_rel,
PackedFile *pf, PackedFile *pf)
const bool guimode)
{ {
int file, number; int file, number;
int ret_value = RET_OK; int ret_value = RET_OK;
@ -296,9 +295,6 @@ int BKE_packedfile_write_to_file(ReportList *reports,
char filepath_temp[FILE_MAX]; char filepath_temp[FILE_MAX];
/* void *data; */ /* void *data; */
if (guimode) {
} // XXX waitcursor(1);
STRNCPY(filepath, filepath_rel); STRNCPY(filepath, filepath_rel);
BLI_path_abs(filepath, ref_file_name); 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; return ret_value;
} }
@ -441,7 +434,7 @@ char *BKE_packedfile_unpack_to_file(ReportList *reports,
ATTR_FALLTHROUGH; ATTR_FALLTHROUGH;
} }
case PF_WRITE_LOCAL: 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; temp = local_name;
} }
break; break;
@ -461,7 +454,7 @@ char *BKE_packedfile_unpack_to_file(ReportList *reports,
ATTR_FALLTHROUGH; ATTR_FALLTHROUGH;
} }
case PF_WRITE_ORIGINAL: 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; temp = abs_name;
} }
break; 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 /* Apply the default unit on the whole expression, this allows to handle nasty cases like
* '2+2in'. */ * '2+2in'. */
if (SNPRINTF(str_tmp, "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) { 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 { else {
/* BLI_snprintf would not fit into str_tmp, can't do much in this case. /* 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; int len_name = 0;
/* Copy everything before the unit. */ /* Copy everything before the unit. */
offset = (offset < str_maxncpy ? offset : str_maxncpy); if (offset < str_maxncpy) {
strncpy(str, orig_str, offset); memcpy(str, orig_str, offset);
}
else {
BLI_strncpy(str, orig_str, str_maxncpy);
offset = str_maxncpy;
}
str += offset; str += offset;
orig_str += offset + strlen(unit->name_short); 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. */ /* 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) 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 *slope,
float *power); float *power);
#if BLI_MATH_DO_INLINE
# include "intern/math_color_inline.c"
#endif
/** \} */ /** \} */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #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 /** \name Inline Definitions
* \{ */ * \{ */
@ -1415,7 +1419,3 @@ float geodesic_distance_propagate_across_triangle(
#endif #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. * \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 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(dst, format, ...) BLI_snprintf(dst, ARRAY_SIZE(dst), format, __VA_ARGS__)
#define SNPRINTF_RLEN(dst, format, ...) \ #define SNPRINTF_RLEN(dst, format, ...) \
@ -635,4 +638,17 @@ void BLI_string_debug_size_after_nil(char *str, size_t str_maxncpy);
/** \} */ /** \} */
#ifdef __cplusplus #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 #endif

View File

@ -21,6 +21,9 @@
#include "BLI_compiler_typecheck.h" #include "BLI_compiler_typecheck.h"
#ifdef __cplusplus #ifdef __cplusplus
# include <type_traits>
# include <utility>
extern "C" { extern "C" {
#endif #endif
@ -493,12 +496,15 @@ extern "C" {
((void)0) ((void)0)
/* assuming a static array */ /* assuming a static array */
#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && !defined(__INTEL_COMPILER) #ifndef __cplusplus
# define ARRAY_SIZE(arr) \ # if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) && \
((sizeof(struct { int isnt_array : ((const void *)&(arr) == &(arr)[0]); }) * 0) + \ !defined(__INTEL_COMPILER)
(sizeof(arr) / sizeof(*(arr)))) # define ARRAY_SIZE(arr) \
#else ((sizeof(struct { int isnt_array : ((const void *)&(arr) == &(arr)[0]); }) * 0) + \
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr))) (sizeof(arr) / sizeof(*(arr))))
# else
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
# endif
#endif #endif
/* ARRAY_SET_ITEMS#(v, ...): set indices of array 'v' */ /* 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 #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
#endif /* __BLI_UTILDEFINES_H__ */ #endif /* __BLI_UTILDEFINES_H__ */

View File

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

View File

@ -11,6 +11,10 @@
#include <math.h> #include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __MATH_COLOR_INLINE_C__ #ifndef __MATH_COLOR_INLINE_C__
# define __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__ */ #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); BLI_windows_get_executable_dir(InstallDir);
GetSystemDirectory(SysDir, FILE_MAXDIR); GetSystemDirectory(SysDir, FILE_MAXDIR);
const char *ThumbHandlerDLL = "BlendThumb.dll"; const char *ThumbHandlerDLL = "BlendThumb.dll";
snprintf( SNPRINTF(RegCmd, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
system(RegCmd); system(RegCmd);
} }
# endif # endif

View File

@ -4,11 +4,9 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_rand.h" #include "BLI_rand.h"
#include "PIL_time.h" #include "PIL_time.h"
}
#include <fstream> #include <fstream>
#include <iostream> #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) { if (rr) {
RenderView *rv = RE_RenderViewGetByName(rr, view_name_); RenderView *rv = RE_RenderViewGetByName(rr, view_name_);
if (rv->rectf != nullptr) { RE_RenderBuffer_assign_data(&rv->combined_buffer, output_buffer_);
MEM_freeN(rv->rectf); RE_RenderBuffer_assign_data(&rv->z_buffer, depth_buffer_);
}
rv->rectf = output_buffer_;
if (rv->rectz != nullptr) {
MEM_freeN(rv->rectz);
}
rv->rectz = depth_buffer_;
rr->have_combined = true; rr->have_combined = true;
} }
else { else {

View File

@ -86,7 +86,7 @@ class GPUShaderCreator : public OCIO::GpuShaderCreator {
} }
/* This is ignored since we query using our own GPU capabilities system. */ /* 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 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 /* 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 * concatenate the code except for the declarations section. That's because the ShaderCreateInfo
* will add the declaration itself. */ * will add the declaration itself. */
void createShaderText(const char *declarations, void createShaderText(const char * /*declarations*/,
const char *helper_methods, const char *helper_methods,
const char *function_header, const char *function_header,
const char *function_body, const char *function_body,

View File

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

View File

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

View File

@ -78,6 +78,9 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
/* Scene ID block. */ /* Scene ID block. */
IDNode *id_node = add_id_node(&scene->id); IDNode *id_node = add_id_node(&scene->id);
id_node->linked_state = linked_state; id_node->linked_state = linked_state;
add_operation_node(&scene->id, NodeType::HIERARCHY, OperationCode::HIERARCHY);
/* Time source. */ /* Time source. */
add_time_source(); add_time_source();
/* Setup currently building context. */ /* 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); 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 OperationNode *DepsgraphRelationBuilder::find_node(const OperationKey &key) const
{ {
IDNode *id_node = graph_->find_id_node(key.id); 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; 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, void DepsgraphRelationBuilder::add_depends_on_transform_relation(const DepsNodeHandle *handle,
const char *description) const char *description)
{ {
@ -504,7 +518,7 @@ void DepsgraphRelationBuilder::build_id(ID *id)
build_camera((Camera *)id); build_camera((Camera *)id);
break; break;
case ID_GR: case ID_GR:
build_collection(nullptr, nullptr, (Collection *)id); build_collection(nullptr, (Collection *)id);
break; break;
case ID_OB: case ID_OB:
build_object((Object *)id); build_object((Object *)id);
@ -615,76 +629,85 @@ void DepsgraphRelationBuilder::build_idproperties(IDProperty *id_property)
} }
void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection, void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection,
Object *object,
Collection *collection) Collection *collection)
{ {
const ComponentKey collection_hierarchy_key{&collection->id, NodeType::HIERARCHY};
if (from_layer_collection != nullptr) { if (from_layer_collection != nullptr) {
/* If we came from layer collection we don't go deeper, view layer /* If we came from layer collection we don't go deeper, view layer builder takes care of going
* builder takes care of going deeper. * deeper.
* *
* NOTE: Do early output before tagging build as done, so possible * NOTE: Do early output before tagging build as done, so possible subsequent builds from
* subsequent builds from outside of the layer collection properly * outside of the layer collection properly recurses into all the nested objects and
* recurses into all the nested objects and collections. */ * 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; 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 BuilderStack::ScopedEntry stack_entry = stack_.trace(collection->id);
const bool group_done = built_map_.checkIsBuiltAndTag(collection); const OperationKey collection_geometry_key{
OperationKey object_transform_final_key(object != nullptr ? &object->id : nullptr, &collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
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);
/* The geometry of a collection depends on the positions of the elements in it. */ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
OperationKey object_transform_key{ Object *object = cob->ob;
&cob->ob->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. */ build_object(object);
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");
}
/* An instance is part of the geometry of the collection. */ const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
if (cob->ob->type == OB_EMPTY) { add_relation(collection_hierarchy_key, object_hierarchy_key, "Collection -> Object hierarchy");
Collection *collection_instance = cob->ob->instance_collection;
if (collection_instance != nullptr) { /* The geometry of a collection depends on the positions of the elements in it. */
OperationKey collection_instance_key{ const OperationKey object_transform_key{
&collection_instance->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE}; &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL};
add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry"); 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); /* An instance is part of the geometry of the collection. */
OperationKey child_collection_geometry_key{ if (object->type == OB_EMPTY) {
&child->collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE}; Collection *collection_instance = cob->ob->instance_collection;
add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry"); 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) { LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM); build_collection(nullptr, child->collection);
add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup"); const OperationKey child_collection_geometry_key{
/* Hook to special component, to ensure proper visibility/evaluation &child->collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE};
* optimizations. */ add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry");
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;
} }
} }
@ -796,12 +819,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_texture(object->pd->tex); build_texture(object->pd->tex);
} }
/* Object dupligroup. */ build_object_instance_collection(object);
if (object->instance_collection != nullptr) {
build_collection(nullptr, object, object->instance_collection);
}
/* Point caches. */
build_object_pointcache(object); build_object_pointcache(object);
/* Synchronization back to original object. */ /* Synchronization back to original object. */
@ -1210,6 +1228,35 @@ void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
BLI_freelistN(&ptcache_id_list); 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, void DepsgraphRelationBuilder::build_constraints(ID *id,
NodeType component_type, NodeType component_type,
const char *component_subdata, const char *component_subdata,
@ -2012,7 +2059,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
} }
/* Objects. */ /* Objects. */
if (rbw->group != nullptr) { if (rbw->group != nullptr) {
build_collection(nullptr, nullptr, rbw->group); build_collection(nullptr, rbw->group);
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) { FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
if (object->type != OB_MESH) { if (object->type != OB_MESH) {
continue; continue;
@ -2168,7 +2215,7 @@ void DepsgraphRelationBuilder::build_particle_systems(Object *object)
break; break;
case PART_DRAW_GR: case PART_DRAW_GR:
if (part->instance_collection != nullptr) { 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) { LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
build_particle_system_visualization_object(object, psys, go->ob); 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) { else if (socket->type == SOCK_COLLECTION) {
Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value; Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value;
if (collection != nullptr) { if (collection != nullptr) {
build_collection(nullptr, nullptr, collection); build_collection(nullptr, collection);
} }
} }
else if (socket->type == SOCK_TEXTURE) { 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)) { if (ELEM(comp_node->type, NodeType::PARAMETERS, NodeType::LAYER_COLLECTIONS)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH; 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 /* All entry operations of each component should wait for a proper
* copy of ID. */ * copy of ID. */
OperationNode *op_entry = comp_node->get_entry_operation(); 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_parameters(Scene *scene);
virtual void build_scene_compositor(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, virtual void build_view_layer(Scene *scene,
ViewLayer *view_layer, ViewLayer *view_layer,
eDepsNode_LinkedState_Type linked_state); eDepsNode_LinkedState_Type linked_state);
virtual void build_collection(LayerCollection *from_layer_collection, virtual void build_collection(LayerCollection *from_layer_collection, Collection *collection);
Object *object,
Collection *collection);
virtual void build_object(Object *object); virtual void build_object(Object *object);
virtual void build_object_from_view_layer_base(Object *object); virtual void build_object_from_view_layer_base(Object *object);
virtual void build_object_layer_component_relations(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_data_speaker(Object *object);
virtual void build_object_parent(Object *object); virtual void build_object_parent(Object *object);
virtual void build_object_pointcache(Object *object); virtual void build_object_pointcache(Object *object);
virtual void build_object_instance_collection(Object *object);
virtual void build_constraints(ID *id, virtual void build_constraints(ID *id,
NodeType component_type, NodeType component_type,
const char *component_subdata, const char *component_subdata,
@ -263,6 +265,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
Node *get_node(const RNAPathKey &key); Node *get_node(const RNAPathKey &key);
OperationNode *find_node(const OperationKey &key) const; 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; bool has_node(const OperationKey &key) const;
Relation *add_time_relation(TimeSourceNode *timesrc, Relation *add_time_relation(TimeSourceNode *timesrc,

View File

@ -43,26 +43,55 @@
namespace blender::deg { 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 : const int hide_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT :
COLLECTION_HIDE_RENDER; COLLECTION_HIDE_RENDER;
for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { Collection *collection = layer_collection->collection;
if (lc->collection->flag & visibility_flag) {
continue; 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) void DepsgraphRelationBuilder::build_freestyle_lineset(FreestyleLineSet *fls)
{ {
if (fls->group != nullptr) { if (fls->group != nullptr) {
build_collection(nullptr, nullptr, fls->group); build_collection(nullptr, fls->group);
} }
if (fls->linestyle != nullptr) { if (fls->linestyle != nullptr) {
build_freestyle_linestyle(fls->linestyle); 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) { if (scene->camera != nullptr) {
build_object(scene->camera); build_object(scene->camera);

View File

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

View File

@ -217,7 +217,11 @@ void depsgraph_tag_to_component_opcode(const ID *id,
*operation_code = OperationCode::NTREE_OUTPUT; *operation_code = OperationCode::NTREE_OUTPUT;
break; 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_27:
case ID_RECALC_PROVISION_28: case ID_RECALC_PROVISION_28:
case ID_RECALC_PROVISION_29: case ID_RECALC_PROVISION_29:
@ -749,7 +753,9 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
case ID_RECALC_NTREE_OUTPUT: case ID_RECALC_NTREE_OUTPUT:
return "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_27:
case ID_RECALC_PROVISION_28: case ID_RECALC_PROVISION_28:
case ID_RECALC_PROVISION_29: 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_flag = base_flag;
object->base_local_view_bits = base_local_view_bits; object->base_local_view_bits = base_local_view_bits;
/* Restore modifier's runtime data. /* Restore modifier's runtime data.
* NOTE: Data of unused modifiers will be freed there. */ * NOTE: Data of unused modifiers will be freed there. */
restore_modifier_runtime_data(object); restore_modifier_runtime_data(object);

View File

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

View File

@ -77,6 +77,8 @@ enum class NodeType {
/* Used by all operations which are updating object when something is /* Used by all operations which are updating object when something is
* changed in view layer. */ * changed in view layer. */
OBJECT_FROM_LAYER, OBJECT_FROM_LAYER,
/* Hierarchy of objects and collections */
HIERARCHY,
/* Audio-related evaluation. */ /* Audio-related evaluation. */
AUDIO, AUDIO,
ARMATURE, 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(Shading, SHADING, ID_RECALC_SHADING);
DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM); DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0); 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(Dupli, DUPLI, 0);
DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0); DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 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_SHADING);
register_node_typeinfo(&DNTI_TRANSFORM); register_node_typeinfo(&DNTI_TRANSFORM);
register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER); register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
register_node_typeinfo(&DNTI_HIERARCHY);
register_node_typeinfo(&DNTI_DUPLI); register_node_typeinfo(&DNTI_DUPLI);
register_node_typeinfo(&DNTI_SYNCHRONIZATION); register_node_typeinfo(&DNTI_SYNCHRONIZATION);
register_node_typeinfo(&DNTI_AUDIO); 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(ShadingParameters);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform); 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(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Hierarchy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli); DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization); DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio); 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); ComponentNode *comp_node = find_component(type, name);
if (!comp_node) { if (!comp_node) {
DepsNodeFactory *factory = type_get_factory(type); DepsNodeFactory *factory = type_get_factory(type);
BLI_assert(factory);
comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name); comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
/* Register. */ /* Register. */

View File

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

View File

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

View File

@ -582,6 +582,7 @@ static void eevee_cryptomatte_extract_render_passes(
const int pass_offset = pass * 2; const int pass_offset = pass * 2;
SNPRINTF_RLEN(cryptomatte_pass_name, render_pass_name_format, pass); SNPRINTF_RLEN(cryptomatte_pass_name, render_pass_name_format, pass);
RenderPass *rp_object = RE_pass_find_by_name(rl, cryptomatte_pass_name, viewname); 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 y = 0; y < rect_height; y++) {
for (int x = 0; x < rect_width; x++) { for (int x = 0; x < rect_width; x++) {
const int accum_buffer_offset = (rect_offset_x + x + const int accum_buffer_offset = (rect_offset_x + x +
@ -589,15 +590,15 @@ static void eevee_cryptomatte_extract_render_passes(
accum_pixel_stride + accum_pixel_stride +
layer_index * layer_stride + pass_offset; layer_index * layer_stride + pass_offset;
const int render_pass_offset = (y * rect_width + x) * 4; const int render_pass_offset = (y * rect_width + x) * 4;
rp_object->rect[render_pass_offset] = accum_buffer[accum_buffer_offset].hash; rp_buffer_data[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 + 1] = accum_buffer[accum_buffer_offset].weight;
if (levels_done + 1 < num_cryptomatte_levels) { if (levels_done + 1 < num_cryptomatte_levels) {
rp_object->rect[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash; rp_buffer_data[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 + 3] = accum_buffer[accum_buffer_offset + 1].weight;
} }
else { else {
rp_object->rect[render_pass_offset + 2] = 0.0f; rp_buffer_data[render_pass_offset + 2] = 0.0f;
rp_object->rect[render_pass_offset + 3] = 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, num_channels,
0, 0,
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); rp->buffer.data);
} }
static void eevee_render_result_combined(RenderLayer *rl, 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 * 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. */ * happen correctly (see GLTexture::read()). So we need a custom memory allocation. */
/* Avoid memcpy(), replace the pointer directly. */ /* Avoid memcpy(), replace the pointer directly. */
MEM_SAFE_FREE(rp->rect); RE_pass_set_buffer_data(rp, result);
rp->rect = result;
BLI_mutex_unlock(&render->update_render_passes_mutex); 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( RenderPass *vector_rp = RE_pass_find_by_name(
render_layer, vector_pass_name.c_str(), view_name); render_layer, vector_pass_name.c_str(), view_name);
if (vector_rp) { 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 { struct VelocityObjectIndex {
/** Offset inside #VelocityObjectBuf for each timestep. Indexed using eVelocityStep. */ /** Offset inside #VelocityObjectBuf for each timestep. Indexed using eVelocityStep. */
int3 ofs; packed_int3 ofs;
/** Temporary index to copy this to the #VelocityIndexBuf. */ /** Temporary index to copy this to the #VelocityIndexBuf. */
uint resource_id; uint resource_id;
@ -367,11 +367,11 @@ BLI_STATIC_ASSERT_ALIGN(VelocityObjectIndex, 16)
struct VelocityGeometryIndex { struct VelocityGeometryIndex {
/** Offset inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */ /** Offset inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
int3 ofs; packed_int3 ofs;
/** If true, compute deformation motion blur. */ /** If true, compute deformation motion blur. */
bool1 do_deform; bool1 do_deform;
/** Length of data inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */ /** Length of data inside #VelocityGeometryBuf for each timestep. Indexed using eVelocityStep. */
int3 len; packed_int3 len;
int _pad0; 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_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); 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_z = (rpass_z_src) ? rpass_z_src->buffer.data : NULL;
float *pix_col = (rpass_col_src) ? rpass_col_src->rect : NULL; float *pix_col = (rpass_col_src) ? rpass_col_src->buffer.data : NULL;
if (!pix_z || !pix_col) { if (!pix_z || !pix_col) {
RE_engine_set_error_message(engine, 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) { if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); 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, GPU_framebuffer_read_depth(vedata->fbl->render_fb,
rect->xmin, rect->xmin,
@ -167,7 +168,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
BLI_rcti_size_x(rect), BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect), BLI_rcti_size_y(rect),
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); ro_buffer_data);
float winmat[4][4]; float winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false); 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] */ /* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) { if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_num; i++) { for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) { if (ro_buffer_data[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */ ro_buffer_data[i] = 1e10f; /* Background */
} }
else { else {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; ro_buffer_data[i] = ro_buffer_data[i] * 2.0f - 1.0f;
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); 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); float range = fabsf(far - near);
for (int i = 0; i < pix_num; i++) { for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) { if (ro_buffer_data[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */ ro_buffer_data[i] = 1e10f; /* Background */
} }
else { 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, 4,
0, 0,
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); rp->buffer.data);
} }
void GPENCIL_render_to_image(void *ved, void GPENCIL_render_to_image(void *ved,

View File

@ -552,7 +552,7 @@ static void write_render_color_output(struct RenderLayer *layer,
4, 4,
0, 0,
GPU_DATA_FLOAT, 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_x(rect),
BLI_rcti_size_y(rect), BLI_rcti_size_y(rect),
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); rp->buffer.data);
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert GPU depth [0..1] to view Z [near..far] */ /* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(nullptr)) { 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) { if (z == 1.0f) {
z = 1e10f; /* Background */ 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 far = DRW_view_far_distance_get(nullptr);
float range = fabsf(far - near); 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) { if (z == 1.0f) {
z = 1e10f; /* Background */ 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) { if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); 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_bind(dfbl->default_fb);
GPU_framebuffer_read_depth(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_x(rect),
BLI_rcti_size_y(rect), BLI_rcti_size_y(rect),
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); rp_buffer_data);
float winmat[4][4]; float winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false); 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] */ /* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) { if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_num; i++) { for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) { if (rp_buffer_data[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */ rp_buffer_data[i] = 1e10f; /* Background */
} }
else { else {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; rp_buffer_data[i] = rp_buffer_data[i] * 2.0f - 1.0f;
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); 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); float range = fabsf(far - near);
for (int i = 0; i < pix_num; i++) { for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) { if (rp_buffer_data[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */ rp_buffer_data[i] = 1e10f; /* Background */
} }
else { 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, 4,
0, 0,
GPU_DATA_FLOAT, GPU_DATA_FLOAT,
rp->rect); rp->buffer.data);
workbench_render_result_z(render_layer, viewname, rect); workbench_render_result_z(render_layer, viewname, rect);
} }

View File

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

View File

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

View File

@ -6,12 +6,12 @@
#pragma once #pragma once
#include "ED_file_indexer.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "ED_file_indexer.h"
/** /**
* File Indexer Service for indexing asset files. * 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; 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) 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); const bool use_asset_indexer = !USER_EXPERIMENTAL_TEST(&U, no_asset_indexing);
filelist_setindexer(files, use_asset_indexer ? &file_indexer_asset : &file_indexer_noop); 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()) { if (!asset_lib_path.empty()) {
STRNCPY(path, asset_lib_path.c_str()); 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 use_seams,
bool do_islands); bool do_islands);
void BM_uv_element_map_free(struct UvElementMap *element_map); 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, struct UvElement *BM_uv_element_get(const struct UvElementMap *element_map,
const struct BMFace *efa,
const struct BMLoop *l); const struct BMLoop *l);
struct UvElement *BM_uv_element_get_head(struct UvElementMap *element_map, struct UvElement *BM_uv_element_get_head(struct UvElementMap *element_map,
struct UvElement *child); 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 y = int(fpos[1] * render_pass->recty);
const int offset = 4 * (y * render_pass->rectx + x); const int offset = 4 * (y * render_pass->rectx + x);
zero_v3(r_col); zero_v3(r_col);
r_col[0] = render_pass->rect[offset]; r_col[0] = render_pass->buffer.data[offset];
return true; 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 /* 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. */ * 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. */ /* Scan forwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l, offsets)) { 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); UvElement *next = BM_uv_element_get(element_map, element->l->next);
if (next->island == INVALID_ISLAND) { if (next && next->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[next - element_map->storage]; UvElement *tail = element_map->head_table[next - element_map->storage];
stack_uv[stacksize_uv++] = tail; stack_uv[stacksize_uv++] = tail;
while (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. */ /* Scan backwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, offsets)) { 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); UvElement *prev = BM_uv_element_get(element_map, element->l->prev);
if (prev->island == INVALID_ISLAND) { if (prev && prev->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[prev - element_map->storage]; UvElement *tail = element_map->head_table[prev - element_map->storage];
stack_uv[stacksize_uv++] = tail; stack_uv[stacksize_uv++] = tail;
while (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)]; UvElement *element = element_map->vertex[BM_elem_index_get(l->v)];
while (element) { while (element) {
if (element->l->f == efa) { if (element->l == l) {
return element; return element;
} }
element = element->next; element = element->next;

View File

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

View File

@ -193,17 +193,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
RenderView *rv_del = rv->next; RenderView *rv_del = rv->next;
BLI_remlink(&rr->views, rv_del); BLI_remlink(&rr->views, rv_del);
if (rv_del->rectf) { RE_RenderBuffer_data_free(&rv_del->combined_buffer);
MEM_freeN(rv_del->rectf); RE_RenderBuffer_data_free(&rv_del->z_buffer);
} RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
if (rv_del->rectz) {
MEM_freeN(rv_del->rectz);
}
if (rv_del->rect32) {
MEM_freeN(rv_del->rect32);
}
MEM_freeN(rv_del); MEM_freeN(rv_del);
} }
@ -227,17 +219,9 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
BLI_remlink(&rr->views, rv_del); BLI_remlink(&rr->views, rv_del);
if (rv_del->rectf) { RE_RenderBuffer_data_free(&rv_del->combined_buffer);
MEM_freeN(rv_del->rectf); RE_RenderBuffer_data_free(&rv_del->z_buffer);
} RE_RenderByteBuffer_data_free(&rv_del->byte_buffer);
if (rv_del->rectz) {
MEM_freeN(rv_del->rectz);
}
if (rv_del->rect32) {
MEM_freeN(rv_del->rect32);
}
MEM_freeN(rv_del); 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; rv = nullptr;
} }
if (rv && rv->rectf) { if (rv && rv->combined_buffer.data) {
if (abs(rres.rectx - newx) < 2 && abs(rres.recty - newy) < 2) { 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. */ /* Create buffer in empty RenderView created in the init step. */
RenderResult *rr = RE_AcquireResultWrite(re); RenderResult *rr = RE_AcquireResultWrite(re);
RenderView *rv = (RenderView *)rr->views.first; RenderView *rv = (RenderView *)rr->views.first;
rv->rectf = static_cast<float *>( RE_RenderBuffer_assign_data(&rv->combined_buffer,
MEM_callocN(sizeof(float[4]) * width * height, "texture render result")); static_cast<float *>(MEM_callocN(sizeof(float[4]) * width * height,
"texture render result")));
RE_ReleaseResult(re); RE_ReleaseResult(re);
/* Get texture image pool (if any) */ /* 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); BKE_texture_fetch_images_for_pool(tex, img_pool);
/* Fill in image buffer. */ /* 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}; float tex_coord[3] = {0.0f, 0.0f, 0.0f};
bool color_manage = true; bool color_manage = true;

View File

@ -11,6 +11,7 @@
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <utility>
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
@ -190,6 +191,8 @@ BLI_INLINE uchar f_to_char(const float val)
/* to avoid locking in tile initialization */ /* to avoid locking in tile initialization */
#define TILE_PENDING POINTER_FROM_INT(-1) #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 - * 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 * 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, /* Support for painting from multiple views at once,
* currently used to implement symmetry painting, * currently used to implement symmetry painting,
* we can assume at least the first is set while 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 ps_views_tot;
int symmetry_flags; 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; ProjStrokeHandle *ps_handle;
Scene *scene = CTX_data_scene(C); Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings; 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->scene = scene;
ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint); 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; const UvElement *storage = sculptdata->elementMap->storage;
for (int j = 0; j < total_uvs; j++) { for (int j = 0; j < total_uvs; j++) {
const UvElement *ele_curr = storage + j; const UvElement *ele_curr = storage + j;
const BMFace *efa = ele_curr->l->f; const UvElement *ele_next = BM_uv_element_get(sculptdata->elementMap, ele_curr->l->next);
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, ele_curr->l->prev);
const UvElement *ele_prev = BM_uv_element_get(sculptdata->elementMap, efa, ele_curr->l->prev);
const float *v_curr_co = ele_curr->l->v->co; const float *v_curr_co = ele_curr->l->v->co;
const float *v_prev_co = ele_prev->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; op->customdata = nullptr;
} }
static int uv_element_offset_from_face_get( static int uv_element_offset_from_face_get(UvElementMap *map,
UvElementMap *map, BMFace *efa, BMLoop *l, int island_index, const bool doIslands) BMLoop *l,
int island_index,
const bool do_islands)
{ {
UvElement *element = BM_uv_element_get(map, efa, l); UvElement *element = BM_uv_element_get(map, l);
if (!element || (doIslands && element->island != island_index)) { if (!element || (do_islands && element->island != island_index)) {
return -1; return -1;
} }
return element - map->storage; 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 */ /* 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]); 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) { if (do_island_optimization) {
UvElement *element;
UvNearestHit hit = uv_nearest_hit_init_max(&region->v2d); UvNearestHit hit = uv_nearest_hit_init_max(&region->v2d);
uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit); uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l); UvElement *element = BM_uv_element_get(data->elementMap, hit.l);
island_index = element->island; if (element) {
island_index = element->island;
}
} }
/* Count 'unique' UVs */ /* Count 'unique' UVs */
@ -759,18 +761,18 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
counter = 0; counter = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
int offset1, itmp1 = uv_element_offset_from_face_get( int itmp1 = uv_element_offset_from_face_get(
data->elementMap, efa, l, island_index, do_island_optimization); data->elementMap, l, island_index, do_island_optimization);
int offset2, itmp2 = uv_element_offset_from_face_get( int itmp2 = uv_element_offset_from_face_get(
data->elementMap, efa, l->next, island_index, do_island_optimization); data->elementMap, l->next, island_index, do_island_optimization);
/* Skip edge if not found(unlikely) or not on valid island */ /* Skip edge if not found(unlikely) or not on valid island */
if (itmp1 == -1 || itmp2 == -1) { if (itmp1 == -1 || itmp2 == -1) {
continue; continue;
} }
offset1 = uniqueUv[itmp1]; int offset1 = uniqueUv[itmp1];
offset2 = uniqueUv[itmp2]; int offset2 = uniqueUv[itmp2];
/* Using an order policy, sort UVs according to address space. /* Using an order policy, sort UVs according to address space.
* This avoids having two different UvEdges with the same UVs on different positions. */ * This avoids having two different UvEdges with the same UVs on different positions. */

View File

@ -251,20 +251,24 @@ struct FileList {
BlendHandle *libfiledata; BlendHandle *libfiledata;
/* Set given path as root directory, /**
* if last bool is true may change given string in place to a valid value. * Set given path as root directory.
* Returns True if valid dir. */ *
bool (*check_dir_fn)(FileList *, char *, const bool); * \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). */ /** Fill `filelist` (to be called by read job). */
void (*read_job_fn)(FileListReadJob *, bool *, bool *, float *); void (*read_job_fn)(FileListReadJob *job_params, bool *stop, bool *do_update, float *progress);
/* Filter an entry of current filelist. */ /** Filter an entry of current `filelist`. */
bool (*filter_fn)(FileListInternEntry *, const char *, FileListFilter *); bool (*filter_fn)(FileListInternEntry *file, const char *root, FileListFilter *filter);
/* Executed before filtering individual items, to set up additional filter data. */ /** Executed before filtering individual items, to set up additional filter data. */
void (*prepare_filter_fn)(const FileList *, FileListFilter *); void (*prepare_filter_fn)(const FileList *filelist, FileListFilter *filter);
short tags; /* FileListTags */ /** #FileListTags. */
short tags;
}; };
/** #FileList.flags */ /** #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) { if (file->asset) {
const std::string asset_path = AS_asset_representation_full_path_get(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) { if (do_change) {
parent_dir_until_exists_or_default_root(r_dir); parent_dir_until_exists_or_default_root(dirpath);
return true; 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 tdir[FILE_MAX_LIBEXTRA];
char *name; char *name;
const bool is_valid = (BLI_is_dir(r_dir) || const bool is_valid = (BLI_is_dir(dirpath) ||
(BKE_blendfile_library_path_explode(r_dir, tdir, nullptr, &name) && (BKE_blendfile_library_path_explode(dirpath, tdir, nullptr, &name) &&
BLI_is_file(tdir) && !name)); BLI_is_file(tdir) && !name));
if (do_change && !is_valid) { if (do_change && !is_valid) {
/* if not a valid library, we need it to be a valid directory! */ /* 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 true;
} }
return is_valid; 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 */ /* 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*/, static bool filelist_checkdir_return_always_valid(struct FileList * /*filelist*/,
char * /*r_dir*/, char /*dirpath*/[FILE_MAX_LIBEXTRA],
const bool /*do_change*/) const bool /*do_change*/)
{ {
return true; return true;
@ -1990,19 +2002,19 @@ bool filelist_is_dir(FileList *filelist, const char *path)
return filelist->check_dir_fn(filelist, (char *)path, false); 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; 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_abs(dirpath, BKE_main_blendfile_path_from_global());
BLI_path_normalize_dir(r_dir, FILE_MAX_LIBEXTRA); BLI_path_normalize_dir(dirpath, FILE_MAX_LIBEXTRA);
const bool is_valid_path = filelist->check_dir_fn(filelist, r_dir, !allow_invalid); const bool is_valid_path = filelist->check_dir_fn(filelist, dirpath, !allow_invalid);
BLI_assert(is_valid_path || allow_invalid); BLI_assert(is_valid_path || allow_invalid);
UNUSED_VARS_NDEBUG(is_valid_path); UNUSED_VARS_NDEBUG(is_valid_path);
if (!STREQ(filelist->filelist.root, r_dir)) { if (!STREQ(filelist->filelist.root, dirpath)) {
STRNCPY(filelist->filelist.root, r_dir); STRNCPY(filelist->filelist.root, dirpath);
filelist->flags |= FL_FORCE_RESET; 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); const char *filelist_dir(const struct FileList *filelist);
bool filelist_is_dir(struct FileList *filelist, const char *path); 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(), * 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) static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
{ {
RenderView *rv = RE_RenderViewGetById(rr, 0); RenderView *rv = RE_RenderViewGetById(rr, 0);
if (rv->rectf) { if (rv->combined_buffer.data) {
return IFACE_("Composite"); return IFACE_("Composite");
} }
if (rv->rect32) { if (rv->byte_buffer.data) {
return IFACE_("Sequence"); return IFACE_("Sequence");
} }
return NULL; return NULL;

View File

@ -73,7 +73,9 @@ static int unpack_libraries_exec(bContext *C, wmOperator *op)
{ {
Main *bmain = CTX_data_main(C); Main *bmain = CTX_data_main(C);
WM_cursor_wait(true);
BKE_packedfile_unpack_all_libraries(bmain, op->reports); BKE_packedfile_unpack_all_libraries(bmain, op->reports);
WM_cursor_wait(false);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -225,7 +227,9 @@ static int unpack_all_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method"); int method = RNA_enum_get(op->ptr, "method");
if (method != PF_KEEP) { if (method != PF_KEEP) {
WM_cursor_wait(true);
BKE_packedfile_unpack_all(bmain, op->reports, method); /* XXX PF_ASK can't work here */ BKE_packedfile_unpack_all(bmain, op->reports, method); /* XXX PF_ASK can't work here */
WM_cursor_wait(false);
} }
G.fileflags &= ~G_FILE_AUTOPACK; G.fileflags &= ~G_FILE_AUTOPACK;
@ -329,7 +333,9 @@ static int unpack_item_exec(bContext *C, wmOperator *op)
} }
if (method != PF_KEEP) { if (method != PF_KEEP) {
WM_cursor_wait(true);
BKE_packedfile_id_unpack(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */ 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; 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; FModifier *fcm = (FModifier *)fcm_link;
eFModifier_Types type = fcm->type; eFModifier_Types type = fcm->type;
snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_", NLA_FMODIFIER_PANEL_PREFIX);
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type); const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
BLI_snprintf(r_name, BKE_ST_MAXNAME, "%s_PT_%s", NLA_FMODIFIER_PANEL_PREFIX, fmi->name); 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) { if (GS(tsep->id->name) == ID_OB) {
Object *ob = (Object *)tsep->id; Object *ob = (Object *)tsep->id;
ob->instance_collection = nullptr; 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); DEG_relations_tag_update(bmain);
} }
else if (GS(tsep->id->name) == ID_GR) { else if (GS(tsep->id->name) == ID_GR) {
Collection *parent = (Collection *)tsep->id; Collection *parent = (Collection *)tsep->id;
id_fake_user_set(&collection->id); id_fake_user_set(&collection->id);
BKE_collection_child_remove(bmain, parent, collection); 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); DEG_relations_tag_update(bmain);
} }
else if (GS(tsep->id->name) == ID_SCE) { else if (GS(tsep->id->name) == ID_SCE) {
@ -410,7 +410,7 @@ static void unlink_collection_fn(bContext *C,
Collection *parent = scene->master_collection; Collection *parent = scene->master_collection;
id_fake_user_set(&collection->id); id_fake_user_set(&collection->id);
BKE_collection_child_remove(bmain, parent, collection); 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); DEG_relations_tag_update(bmain);
} }
} }
@ -457,14 +457,15 @@ static void unlink_object_fn(bContext *C,
if (GS(tsep->id->name) == ID_GR) { if (GS(tsep->id->name) == ID_GR) {
Collection *parent = (Collection *)tsep->id; Collection *parent = (Collection *)tsep->id;
BKE_collection_object_remove(bmain, parent, ob, true); 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); DEG_relations_tag_update(bmain);
} }
else if (GS(tsep->id->name) == ID_SCE) { else if (GS(tsep->id->name) == ID_SCE) {
Scene *scene = (Scene *)tsep->id; Scene *scene = (Scene *)tsep->id;
Collection *parent = scene->master_collection; Collection *parent = scene->master_collection;
BKE_collection_object_remove(bmain, parent, ob, true); 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); 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. */ * cleanup tree here to prevent such cases. */
outliner_cleanup_tree(space_outliner); 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); DEG_relations_tag_update(bmain);
BKE_view_layer_synced_ensure(scene, view_layer); BKE_view_layer_synced_ensure(scene, view_layer);

View File

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

View File

@ -86,7 +86,7 @@ static int iso_index_for_loop(const BMLoop *loop,
UvElementMap *element_map, UvElementMap *element_map,
const int island_index) 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) { if (!element) {
return -1; /* Either unselected, or a different island. */ 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_elem_flag_enable(efa, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!uvedit_edge_select_test(scene, l, offsets)) { if (!uvedit_edge_select_test(scene, l, offsets)) {
UvElement *element = BM_uv_element_get(elementmap, efa, l); UvElement *element = BM_uv_element_get(elementmap, l);
is_island_not_selected[element->island] = true; if (element) {
is_island_not_selected[element->island] = true;
}
} }
} }
} }
@ -5463,9 +5465,9 @@ static void uv_isolate_selected_islands(const Scene *scene,
continue; continue;
} }
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { 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. */ /* 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_vert, false);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, 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 */ /* check to see if other vertex of edge belongs to same vertex as */
if (BM_elem_index_get(iter1->l->next->v) == elemindex2) { 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) { 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) { if (iter2) {
@ -1163,7 +1163,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
/* just to test if face was added for processing. /* just to test if face was added for processing.
* uvs of unselected vertices will return NULL */ * 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) { if (element) {
int numoftris = efa->len - 2; int numoftris = efa->len - 2;
@ -1795,8 +1795,12 @@ static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
{ {
UvEdge tmp_edge; UvEdge tmp_edge;
UvElement *element1 = BM_uv_element_get(state->element_map, l->f, l); UvElement *element1 = BM_uv_element_get(state->element_map, l);
UvElement *element2 = BM_uv_element_get(state->element_map, l->f, l->next); 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 uv1 = state->map[element1 - state->element_map->storage];
int uv2 = state->map[element2 - 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) { 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 itmp1 = element - state->element_map->storage;
int itmp2 = BM_uv_element_get(state->element_map, efa, l->next) - int itmp2 = BM_uv_element_get(state->element_map, l->next) - state->element_map->storage;
state->element_map->storage;
UvEdge *edge; UvEdge *edge;
int offset1 = map[itmp1]; int offset1 = map[itmp1];
@ -2015,8 +2018,8 @@ static StitchState *stitch_init(bContext *C,
faceIndex = state_init->to_select[selected_count].faceIndex; faceIndex = state_init->to_select[selected_count].faceIndex;
elementIndex = state_init->to_select[selected_count].elementIndex; elementIndex = state_init->to_select[selected_count].elementIndex;
efa = BM_face_at_index(em->bm, faceIndex); efa = BM_face_at_index(em->bm, faceIndex);
element = BM_uv_element_get( element = BM_uv_element_get(state->element_map,
state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex)); BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
stitch_select_uv(element, state, 1); stitch_select_uv(element, state, 1);
} }
} }
@ -2031,13 +2034,12 @@ static StitchState *stitch_init(bContext *C,
faceIndex = state_init->to_select[selected_count].faceIndex; faceIndex = state_init->to_select[selected_count].faceIndex;
elementIndex = state_init->to_select[selected_count].elementIndex; elementIndex = state_init->to_select[selected_count].elementIndex;
efa = BM_face_at_index(em->bm, faceIndex); efa = BM_face_at_index(em->bm, faceIndex);
element = BM_uv_element_get( element = BM_uv_element_get(state->element_map,
state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex)); BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
uv1 = map[element - state->element_map->storage]; uv1 = map[element - state->element_map->storage];
element = BM_uv_element_get( element = BM_uv_element_get(
state->element_map, state->element_map,
efa,
BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len)); BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
uv2 = map[element - state->element_map->storage]; 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_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (uvedit_uv_select_test(scene, l, offsets)) { 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) { if (element) {
stitch_select_uv(element, state, 1); 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) { 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) { if (element) {
state->tris_per_island[element->island] += (efa->len > 2) ? efa->len - 2 : 0; 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 */ /* 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); UvElement *element = BM_uv_element_get(state->element_map, hit.l);
stitch_select_uv(element, state, false); if (element) {
stitch_select_uv(element, state, false);
}
return state; 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); RenderLayer *rl = RE_GetRenderLayer(re->result, view_layer->name);
bool diffuse = false, z = false; bool diffuse = false, z = false;
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { 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)) { 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; diffuse = true;
} }
if (STREQ(rpass->name, RE_PASSNAME_Z)) { 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; 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) static bool is_larger(const rctf &a, const rctf &b, const UVPackIsland_Params &params)
{ {

View File

@ -60,6 +60,7 @@
# define bool3 bvec3 # define bool3 bvec3
# define bool4 bvec4 # define bool4 bvec4
# define packed_float3 vec3 # define packed_float3 vec3
# define packed_int3 int3
# endif # endif
#else /* C / C++ */ #else /* C / C++ */
@ -85,6 +86,7 @@ using bool2 = blender::int2;
using bool3 = blender::int3; using bool3 = blender::int3;
using bool4 = blender::int4; using bool4 = blender::int4;
using packed_float3 = blender::float3; using packed_float3 = blender::float3;
using packed_int3 = blender::int3;
# else /* C */ # else /* C */
typedef float float2[2]; typedef float float2[2];
@ -102,6 +104,7 @@ typedef int bool2[2];
typedef int bool3[2]; typedef int bool3[2];
typedef int bool4[4]; typedef int bool4[4];
typedef float3 packed_float3; typedef float3 packed_float3;
typedef int3 packed_int3;
# endif # endif
#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 * \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. * 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. * TODO(fclem): Target conversion (ex: Texture 2D as Texture 2D Array) is not implemented yet.
*/ */
GPUTexture *GPU_texture_create_view(const char *name, GPUTexture *GPU_texture_create_view(const char *name,
@ -709,7 +716,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
int mip_len, int mip_len,
int layer_start, int layer_start,
int layer_len, 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]); 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 mip_len,
int layer_start, int layer_start,
int layer_len, int layer_len,
bool cube_as_array) bool cube_as_array,
bool use_stencil)
{ {
const Texture *src = unwrap(src_); const Texture *src = unwrap(src_);
w_ = src->w_; w_ = src->w_;
@ -172,7 +173,7 @@ bool Texture::init_view(GPUTexture *src_,
type_ = (type_ & ~GPU_TEXTURE_CUBE) | GPU_TEXTURE_2D_ARRAY; type_ = (type_ & ~GPU_TEXTURE_CUBE) | GPU_TEXTURE_2D_ARRAY;
} }
sampler_state = src->sampler_state; 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) void Texture::usage_set(eGPUTextureUsage usage_flags)
@ -457,7 +458,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
int mip_len, int mip_len,
int layer_start, int layer_start,
int layer_len, int layer_len,
bool cube_as_array) bool cube_as_array,
bool use_stencil)
{ {
BLI_assert(mip_len > 0); BLI_assert(mip_len > 0);
BLI_assert(layer_len > 0); BLI_assert(layer_len > 0);
@ -472,7 +474,8 @@ GPUTexture *GPU_texture_create_view(const char *name,
mip_len, mip_len,
layer_start, layer_start,
layer_len, layer_len,
cube_as_array); cube_as_array,
use_stencil);
return wrap(view); 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); 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_) void GPU_texture_free(GPUTexture *tex_)
{ {
Texture *tex = reinterpret_cast<Texture *>(tex_); Texture *tex = reinterpret_cast<Texture *>(tex_);

View File

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

View File

@ -219,6 +219,7 @@ class MTLTexture : public Texture {
MTLTextureSwizzleChannels mtl_swizzle_mask_; MTLTextureSwizzleChannels mtl_swizzle_mask_;
bool mip_range_dirty_ = false; bool mip_range_dirty_ = false;
bool texture_view_stencil_ = false;
int mip_texture_base_level_ = 0; int mip_texture_base_level_ = 0;
int mip_texture_max_level_ = 1000; int mip_texture_max_level_ = 1000;
int mip_texture_base_layer_ = 0; int mip_texture_base_layer_ = 0;
@ -256,9 +257,6 @@ class MTLTexture : public Texture {
void copy_to(Texture *dst) override; void copy_to(Texture *dst) override;
void clear(eGPUDataFormat format, const void *data) override; void clear(eGPUDataFormat format, const void *data) override;
void swizzle_set(const char swizzle_mask[4]) 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 mip_range_set(int min, int max) override;
void *read(int mip, eGPUDataFormat type) 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(GPUVertBuf *vbo) override;
bool init_internal(GPUTexture *src, bool init_internal(GPUTexture *src,
int mip_offset, int mip_offset,
int layer_offset) override; /* Texture View */ int layer_offset,
bool use_stencil) override; /* Texture View */
private: private:
/* Common Constructor, default initialization. */ /* Common Constructor, default initialization. */
@ -516,6 +515,32 @@ inline std::string tex_data_format_to_msl_texture_template_type(eGPUDataFormat t
return ""; 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 /* Determine whether format is writable or not. Use mtl_format_get_writeable_view_format(..) for
* these. */ * these. */
inline bool mtl_format_is_writable(MTLPixelFormat format) inline bool mtl_format_is_writable(MTLPixelFormat format)

View File

@ -159,14 +159,35 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
break; 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, int range_len = min_ii((mip_texture_max_level_ - mip_texture_base_level_) + 1,
texture_.mipmapLevelCount - mip_texture_base_level_); texture_.mipmapLevelCount - mip_texture_base_level_);
BLI_assert(range_len > 0); BLI_assert(range_len > 0);
BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount); BLI_assert(mip_texture_base_level_ < texture_.mipmapLevelCount);
BLI_assert(mip_texture_base_layer_ < num_slices); BLI_assert(mip_texture_base_layer_ < num_slices);
mip_swizzle_view_ = [texture_ mip_swizzle_view_ = [texture_
newTextureViewWithPixelFormat:texture_.pixelFormat newTextureViewWithPixelFormat:texture_view_pixel_format
textureType:texture_.textureType textureType:texture_view_texture_type
levels:NSMakeRange(mip_texture_base_level_, range_len) levels:NSMakeRange(mip_texture_base_level_, range_len)
slices:NSMakeRange(mip_texture_base_layer_, num_slices) slices:NSMakeRange(mip_texture_base_layer_, num_slices)
swizzle:mtl_swizzle_mask_]; swizzle:mtl_swizzle_mask_];
@ -1810,7 +1831,10 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
return true; 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); BLI_assert(src);
@ -1841,6 +1865,13 @@ bool gpu::MTLTexture::init_internal(GPUTexture *src, int mip_offset, int layer_o
is_baked_ = true; is_baked_ = true;
is_dirty_ = false; 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. */
bake_mip_swizzle_view(); bake_mip_swizzle_view();
return true; return true;

View File

@ -178,7 +178,7 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
return true; 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); 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_); 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; return true;
} }

View File

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

View File

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

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