Merge branch 'master' into asset-browser-grid-view

This commit is contained in:
Julian Eisel 2022-02-07 11:13:31 +01:00
commit d2c4918d77
115 changed files with 1686 additions and 649 deletions

View File

@ -19,13 +19,10 @@
set(FREETYPE_EXTRA_ARGS
-DCMAKE_RELEASE_POSTFIX:STRING=2ST
-DCMAKE_DEBUG_POSTFIX:STRING=2ST_d
-DWITH_BZip2=OFF
-DWITH_HarfBuzz=OFF
-DFT_WITH_HARFBUZZ=OFF
-DFT_WITH_BZIP2=OFF
-DFT_WITH_BROTLI=ON
-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE
-DFT_DISABLE_BZIP2=ON
-DFT_DISABLE_HARFBUZZ=ON
-DFT_DISABLE_PNG=ON
-DFT_REQUIRE_BROTLI=ON
-DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include
-DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib
)

View File

@ -83,9 +83,9 @@ else()
set(OPENEXR_VERSION_POSTFIX)
endif()
set(FREETYPE_VERSION 2.11.0)
set(FREETYPE_VERSION 2.11.1)
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
set(FREETYPE_HASH cf09172322f6b50cf8f568bf8fe14bde)
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
set(FREETYPE_HASH_TYPE MD5)
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)

View File

@ -74,7 +74,7 @@ enum_panorama_types = (
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked."),
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked"),
)
enum_curve_shape = (
@ -901,27 +901,27 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
fisheye_polynomial_k0: FloatProperty(
name="Fisheye Polynomial K0",
description="Coefficient K0 of the lens polinomial",
description="Coefficient K0 of the lens polynomial",
default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE',
)
fisheye_polynomial_k1: FloatProperty(
name="Fisheye Polynomial K1",
description="Coefficient K1 of the lens polinomial",
description="Coefficient K1 of the lens polynomial",
default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE',
)
fisheye_polynomial_k2: FloatProperty(
name="Fisheye Polynomial K2",
description="Coefficient K2 of the lens polinomial",
description="Coefficient K2 of the lens polynomial",
default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE',
)
fisheye_polynomial_k3: FloatProperty(
name="Fisheye Polynomial K3",
description="Coefficient K3 of the lens polinomial",
description="Coefficient K3 of the lens polynomial",
default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE',
)
fisheye_polynomial_k4: FloatProperty(
name="Fisheye Polynomial K4",
description="Coefficient K4 of the lens polinomial",
description="Coefficient K4 of the lens polynomial",
default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE',
)

View File

@ -142,6 +142,7 @@ class BVHParams {
top_level = false;
bvh_layout = BVH_LAYOUT_BVH2;
use_compact_structure = true;
use_unaligned_nodes = false;
num_motion_curve_steps = 0;

View File

@ -193,17 +193,24 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
shadow_flag |= (shadow_flag & PATH_RAY_ANY_PASS) ? 0 : PATH_RAY_SURFACE_PASS;
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
const packed_float3 pass_diffuse_weight =
(bounce == 0) ? packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval)) :
INTEGRATOR_STATE(state, path, pass_diffuse_weight);
const packed_float3 pass_glossy_weight = (bounce == 0) ?
packed_float3(
bsdf_eval_pass_glossy_weight(&bsdf_eval)) :
INTEGRATOR_STATE(state, path, pass_glossy_weight);
packed_float3 pass_diffuse_weight;
packed_float3 pass_glossy_weight;
if (shadow_flag & PATH_RAY_ANY_PASS) {
/* Indirect bounce, use weights from earlier surface or volume bounce. */
pass_diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
pass_glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
}
else {
/* Direct light, use BSDFs at this bounce. */
shadow_flag |= PATH_RAY_SURFACE_PASS;
pass_diffuse_weight = packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval));
pass_glossy_weight = packed_float3(bsdf_eval_pass_glossy_weight(&bsdf_eval));
}
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = pass_glossy_weight;
}

View File

@ -801,16 +801,26 @@ ccl_device_forceinline void integrate_volume_direct_light(
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
shadow_flag |= (shadow_flag & PATH_RAY_ANY_PASS) ? 0 : PATH_RAY_VOLUME_PASS;
const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval);
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
const packed_float3 pass_diffuse_weight = (bounce == 0) ?
packed_float3(one_float3()) :
INTEGRATOR_STATE(
state, path, pass_diffuse_weight);
packed_float3 pass_diffuse_weight;
packed_float3 pass_glossy_weight;
if (shadow_flag & PATH_RAY_ANY_PASS) {
/* Indirect bounce, use weights from earlier surface or volume bounce. */
pass_diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
pass_glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
}
else {
/* Direct light, no diffuse/glossy distinction needed for volumes. */
shadow_flag |= PATH_RAY_VOLUME_PASS;
pass_diffuse_weight = packed_float3(one_float3());
pass_glossy_weight = packed_float3(zero_float3());
}
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = zero_float3();
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = pass_glossy_weight;
}
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE(

View File

@ -356,6 +356,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"y",
"y = (Ax + B)",
# Sub-strings.
"and AMD Radeon Pro 21.Q4 driver or newer",
"available with",
"brown fox",
"can't save image while rendering",
@ -378,6 +379,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"image path can't be written to",
"in memory to enable editing!",
"insufficient content",
"into",
"jumps over",
"left",
"local",
@ -387,6 +389,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"performance impact!",
"right",
"the lazy dog",
"to the top level of the tree",
"unable to load movie clip",
"unable to load text",
"unable to open the file",

View File

@ -76,10 +76,12 @@ class SpellChecker:
"tangency",
"vertices",
"wasn", # wasn't
"zig", "zag",
# Brands etc.
"htc",
"huawei",
"radeon",
"vive",
"xbox",
@ -136,6 +138,7 @@ class SpellChecker:
"filename", "filenames",
"filepath", "filepaths",
"forcefield", "forcefields",
"framerange",
"fulldome", "fulldomes",
"fullscreen",
"gamepad",
@ -498,6 +501,7 @@ class SpellChecker:
"framerate",
"gimbal",
"grayscale",
"icosahedron",
"icosphere",
"inpaint",
"kerning",
@ -556,6 +560,7 @@ class SpellChecker:
"bspline",
"bweight",
"colorband",
"crazyspace",
"datablock", "datablocks",
"despeckle",
"depsgraph",
@ -730,6 +735,7 @@ class SpellChecker:
"precisa",
"px",
"qmc",
"rdna",
"rdp",
"rgb", "rgba",
"rhs",

View File

@ -2027,6 +2027,9 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
layout.use_property_split = True
layout.active = not strip.mute
col = layout.column(align=True)
col.prop(strip.transform, "filter", text="Filter")
col = layout.column(align=True)
col.prop(strip.transform, "offset_x", text="Position X")
col.prop(strip.transform, "offset_y", text="Y")

View File

@ -309,7 +309,7 @@ void BLF_thumb_preview(const char *filename,
/* blf_default.c */
void BLF_default_dpi(int dpi);
void BLF_default_size(int size);
void BLF_default_size(float size);
void BLF_default_set(int fontid);
/**
* Get default font ID so we can pass it to other functions.

View File

@ -37,15 +37,15 @@
/* Default size and dpi, for BLF_draw_default. */
static int global_font_default = -1;
static int global_font_dpi = 72;
/* Keep in sync with `UI_style_get()->widgetlabel.points` */
static int global_font_size = 11;
/* Keep in sync with `UI_DEFAULT_TEXT_POINTS` */
static float global_font_size = 11.0f;
void BLF_default_dpi(int dpi)
{
global_font_dpi = dpi;
}
void BLF_default_size(int size)
void BLF_default_size(float size)
{
global_font_size = size;
}

View File

@ -34,7 +34,6 @@
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_ADVANCES_H /* For FT_Get_Advance */
#include "MEM_guardedalloc.h"
@ -826,7 +825,10 @@ float blf_font_height(FontBLF *font,
float blf_font_fixed_width(FontBLF *font)
{
return (float)font->fixed_width;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
float width = (gc) ? (float)gc->fixed_width : font->size / 2.0f;
blf_glyph_cache_release(font);
return width;
}
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
@ -1318,12 +1320,7 @@ FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int m
void blf_font_free(FontBLF *font)
{
BLI_spin_lock(&blf_glyph_cache_mutex);
GlyphCacheBLF *gc;
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
blf_glyph_cache_clear(font);
if (font->kerning_cache) {
MEM_freeN(font->kerning_cache);
@ -1337,8 +1334,6 @@ void blf_font_free(FontBLF *font)
MEM_freeN(font->name);
}
MEM_freeN(font);
BLI_spin_unlock(&blf_glyph_cache_mutex);
}
/** \} */
@ -1347,51 +1342,25 @@ void blf_font_free(FontBLF *font)
/** \name Font Configure
* \{ */
void blf_font_size(FontBLF *font, float size, unsigned int dpi)
bool blf_font_size(FontBLF *font, float size, unsigned int dpi)
{
blf_glyph_cache_acquire(font);
/* FreeType uses fixed-point integers in 64ths. */
FT_F26Dot6 ft_size = lroundf(size * 64.0f);
/* Adjust our size to be on even 64ths. */
/* Adjust our new size to be on even 64ths. */
size = (float)ft_size / 64.0f;
GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
if (gc && (font->size == size && font->dpi == dpi)) {
/* Optimization: do not call FT_Set_Char_Size if size did not change. */
}
else {
const FT_Error err = FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi);
if (err) {
/* FIXME: here we can go through the fixed size and choice a close one */
printf("The current font don't support the size, %f and dpi, %u\n", size, dpi);
}
else {
if (font->size != size || font->dpi != dpi) {
if (FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi) == 0) {
font->size = size;
font->dpi = dpi;
if (gc == NULL) {
blf_glyph_cache_new(font);
}
}
else {
printf("The current font does not support the size, %f and dpi, %u\n", size, dpi);
return false;
}
}
blf_glyph_cache_release(font);
/* Set fixed-width size for monospaced output. */
FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
if (gindex) {
FT_Fixed advance = 0;
FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
/* Use CSS 'ch unit' width, advance of zero character. */
font->fixed_width = (int)(advance >> 16);
}
else {
/* Font does not contain "0" so use CSS fallback of 1/2 of em. */
font->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
}
if (font->fixed_width < 1) {
font->fixed_width = 1;
}
return true;
}
/** \} */

View File

@ -34,6 +34,7 @@
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_BITMAP_H
#include FT_ADVANCES_H /* For FT_Get_Advance. */
#include "MEM_guardedalloc.h"
@ -73,7 +74,7 @@ static FT_Fixed to_16dot16(double val)
/** \name Glyph Cache
* \{ */
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
static GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
while (gc) {
@ -86,7 +87,7 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
return NULL;
}
GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
@ -100,6 +101,22 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
/* Determine ideal fixed-width size for monospaced output. */
FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
if (gindex) {
FT_Fixed advance = 0;
FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
/* Use CSS 'ch unit' width, advance of zero character. */
gc->fixed_width = (int)(advance >> 16);
}
else {
/* Font does not contain "0" so use CSS fallback of 1/2 of em. */
gc->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
}
if (gc->fixed_width < 1) {
gc->fixed_width = 1;
}
BLI_addhead(&font->cache, gc);
return gc;
}
@ -122,20 +139,7 @@ void blf_glyph_cache_release(FontBLF *font)
BLI_spin_unlock(font->glyph_cache_mutex);
}
void blf_glyph_cache_clear(FontBLF *font)
{
GlyphCacheBLF *gc;
BLI_spin_lock(font->glyph_cache_mutex);
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
BLI_spin_unlock(font->glyph_cache_mutex);
}
void blf_glyph_cache_free(GlyphCacheBLF *gc)
static void blf_glyph_cache_free(GlyphCacheBLF *gc)
{
GlyphBLF *g;
for (uint i = 0; i < ARRAY_SIZE(gc->bucket); i++) {
@ -152,6 +156,19 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
MEM_freeN(gc);
}
void blf_glyph_cache_clear(FontBLF *font)
{
GlyphCacheBLF *gc;
BLI_spin_lock(font->glyph_cache_mutex);
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
BLI_spin_unlock(font->glyph_cache_mutex);
}
/**
* Try to find a glyph in cache.
*

View File

@ -56,7 +56,11 @@ struct FontBLF *blf_font_new(const char *name, const char *filename);
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
/**
* Change font's output size. Returns true if successful in changing the size.
*/
bool blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
void blf_font_draw(struct FontBLF *font,
const char *str,
size_t str_len,
@ -65,10 +69,7 @@ void blf_font_draw__wrap(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
void blf_font_draw_ascii(struct FontBLF *font,
const char *str,
size_t str_len,
struct ResultBLF *r_info);
/**
* Use fixed column width, but an utf8 character may occupy multiple columns.
*/
@ -137,18 +138,9 @@ int blf_font_count_missing_chars(struct FontBLF *font,
void blf_font_free(struct FontBLF *font);
/**
* Find a glyph cache that matches a size, DPI & styles.
*/
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, float size, unsigned int dpi);
/**
* Create a new glyph cache for the current size, DPI & styles.
*/
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
void blf_glyph_cache_release(struct FontBLF *font);
void blf_glyph_cache_clear(struct FontBLF *font);
void blf_glyph_cache_free(struct GlyphCacheBLF *gc);
/**
* Create (or load from cache) a fully-rendered bitmap glyph.

View File

@ -73,6 +73,9 @@ typedef struct GlyphCacheBLF {
bool bold;
bool italic;
/* Column width when printing monospaced. */
int fixed_width;
/* and the glyphs. */
ListBase bucket[257];
@ -207,9 +210,6 @@ typedef struct FontBLF {
/* font size. */
float size;
/* Column width when printing monospaced. */
int fixed_width;
/* max texture size. */
int tex_size_max;

View File

@ -61,7 +61,6 @@ void BLF_thumb_preview(const char *filename,
int font_shrink = 4;
FontBLF *font;
GlyphCacheBLF *gc;
/* Create a new blender font obj and fill it with default values */
font = blf_font_new("thumb_font", filename);
@ -90,10 +89,8 @@ void BLF_thumb_preview(const char *filename,
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
int draw_str_i18n_nbr = 0;
blf_font_size(font, (float)MAX2(font_size_min, font_size_curr), dpi);
gc = blf_glyph_cache_find(font, font->size, font->dpi);
/* There will be no matching glyph cache if blf_font_size() failed to set font size. */
if (!gc) {
CLAMP_MIN(font_size_curr, font_size_min);
if (!blf_font_size(font, (float)font_size_curr, dpi)) {
break;
}

View File

@ -50,6 +50,9 @@ inline void convert_to_static_type(const CustomDataType data_type, const Func &f
case CD_PROP_BOOL:
func(bool());
break;
case CD_PROP_INT8:
func(int8_t());
break;
case CD_PROP_COLOR:
func(ColorGeometry4f());
break;
@ -77,6 +80,9 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
else if (cpp_type.is<bool>()) {
func(bool());
}
else if (cpp_type.is<int8_t>()) {
func(int8_t());
}
else if (cpp_type.is<ColorGeometry4f>()) {
func(ColorGeometry4f());
}
@ -93,6 +99,12 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
template<>
inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
{
return static_cast<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
}
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
{
return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
@ -147,6 +159,11 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b)
return ((1.0f - factor) * a + factor * b) >= 0.5f;
}
template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
{
return static_cast<int8_t>((1.0f - factor) * a + factor * b);
}
template<> inline int mix2(const float factor, const int &a, const int &b)
{
return static_cast<int>((1.0f - factor) * a + factor * b);
@ -364,6 +381,15 @@ template<> struct DefaultMixerStruct<bool> {
using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>;
};
template<> struct DefaultMixerStruct<int8_t> {
static int8_t float_to_int8_t(const float &value)
{
return static_cast<int8_t>(value);
}
/* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
};
template<typename T> struct DefaultPropatationMixerStruct {
/* Use void by default. This can be checked for in `if constexpr` statements. */
using type = typename DefaultMixerStruct<T>::type;

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 1
#define BLENDER_FILE_SUBVERSION 2
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -1585,13 +1585,6 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(nullptr, mesh_orco);
}
/* Ensure normals calculation below is correct (normal settings have transferred properly).
* However, nodes modifiers might create meshes from scratch or transfer meshes from other
* objects with different settings, and in general it doesn't make sense to guarantee that
* the settings are the same as the original mesh. If necessary, this could become a modifier
* type flag. */
BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh);
/* Compute normals. */
editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask);
if (mesh_cage && (mesh_cage != mesh_final)) {

View File

@ -83,6 +83,8 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty
return &CPPType::get<ColorGeometry4f>();
case CD_PROP_BOOL:
return &CPPType::get<bool>();
case CD_PROP_INT8:
return &CPPType::get<int8_t>();
default:
return nullptr;
}
@ -109,6 +111,9 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
if (type.is<bool>()) {
return CD_PROP_BOOL;
}
if (type.is<int8_t>()) {
return CD_PROP_INT8;
}
return static_cast<CustomDataType>(-1);
}
@ -117,16 +122,18 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
switch (data_type) {
case CD_PROP_BOOL:
return 0;
case CD_PROP_INT32:
case CD_PROP_INT8:
return 1;
case CD_PROP_FLOAT:
case CD_PROP_INT32:
return 2;
case CD_PROP_FLOAT2:
case CD_PROP_FLOAT:
return 3;
case CD_PROP_FLOAT3:
case CD_PROP_FLOAT2:
return 4;
case CD_PROP_COLOR:
case CD_PROP_FLOAT3:
return 5;
case CD_PROP_COLOR:
return 6;
#if 0 /* These attribute types are not supported yet. */
case CD_MLOOPCOL:
return 3;

View File

@ -140,7 +140,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
private:
static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 |
CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 |
CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL;
CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL |
CD_MASK_PROP_INT8;
const AttributeDomain domain_;
const CustomDataAccessInfo custom_data_access_;

View File

@ -1793,8 +1793,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 45: CD_HAIRCURVE */ /* UNUSED */
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 45: CD_PROP_INT8 */
{sizeof(int8_t), "MInt8Property", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 46: CD_HAIRMAPPING */ /* UNUSED */
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */
@ -1914,7 +1914,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDCustomLoopNormal",
"CDSculptFaceGroups",
/* 43-46 */ "CDHairPoint",
"CDHairCurve",
"CDPropInt8",
"CDHairMapping",
"CDPoint",
"CDPropCol",

View File

@ -685,6 +685,17 @@ static int customdata_compare(
}
break;
}
case CD_PROP_INT8: {
const int8_t *l1_data = (int8_t *)l1->data;
const int8_t *l2_data = (int8_t *)l2->data;
for (int i = 0; i < total_length; i++) {
if (l1_data[i] != l2_data[i]) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
break;
}
case CD_PROP_BOOL: {
const bool *l1_data = (bool *)l1->data;
const bool *l2_data = (bool *)l2->data;

View File

@ -648,7 +648,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
bNodeTree *ntree = (bNodeTree *)id;
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@ -677,7 +676,6 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
{
/* NOTE: writing and reading goes in sync, for speed. */
ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@ -1145,8 +1143,6 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
}
else {
ntree->typeinfo = &NodeTreeTypeUndefined;
ntree->init &= ~NTREE_TYPE_INIT;
}
/* Deprecated integer type. */
@ -1177,8 +1173,6 @@ static void node_set_typeinfo(const struct bContext *C,
}
else {
node->typeinfo = &NodeTypeUndefined;
ntree->init &= ~NTREE_TYPE_INIT;
}
}
@ -1199,8 +1193,6 @@ static void node_socket_set_typeinfo(bNodeTree *ntree,
}
else {
sock->typeinfo = &NodeSocketTypeUndefined;
ntree->init &= ~NTREE_TYPE_INIT;
}
BKE_ntree_update_tag_socket_type(ntree, sock);
}
@ -1218,8 +1210,6 @@ static void update_typeinfo(Main *bmain,
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
ntree->init |= NTREE_TYPE_INIT;
if (treetype && STREQ(ntree->idname, treetype->idname)) {
ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
}
@ -1260,8 +1250,6 @@ static void update_typeinfo(Main *bmain,
void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
{
ntree->init |= NTREE_TYPE_INIT;
ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@ -2674,11 +2662,6 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
ntree->id.flag |= LIB_EMBEDDED_DATA;
}
/* Types are fully initialized at this point,
* if an undefined node is added later this will be reset.
*/
ntree->init |= NTREE_TYPE_INIT;
BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
ntree_set_typeinfo(ntree, ntreeTypeFind(idname));

View File

@ -62,6 +62,11 @@ static bool float_to_bool(const float &a)
{
return a > 0.0f;
}
static int8_t float_to_int8(const float &a)
{
return std::clamp(
a, float(std::numeric_limits<int8_t>::min()), float(std::numeric_limits<int8_t>::max()));
}
static ColorGeometry4f float_to_color(const float &a)
{
return ColorGeometry4f(a, a, a, 1.0f);
@ -83,6 +88,10 @@ static bool float2_to_bool(const float2 &a)
{
return !is_zero_v2(a);
}
static int8_t float2_to_int8(const float2 &a)
{
return float_to_int8((a.x + a.y) / 2.0f);
}
static ColorGeometry4f float2_to_color(const float2 &a)
{
return ColorGeometry4f(a.x, a.y, 0.0f, 1.0f);
@ -92,6 +101,10 @@ static bool float3_to_bool(const float3 &a)
{
return !is_zero_v3(a);
}
static int8_t float3_to_int8(const float3 &a)
{
return float_to_int8((a.x + a.y + a.z) / 3.0f);
}
static float float3_to_float(const float3 &a)
{
return (a.x + a.y + a.z) / 3.0f;
@ -113,6 +126,11 @@ static bool int_to_bool(const int32_t &a)
{
return a > 0;
}
static int8_t int_to_int8(const int32_t &a)
{
return std::clamp(
a, int(std::numeric_limits<int8_t>::min()), int(std::numeric_limits<int8_t>::max()));
}
static float int_to_float(const int32_t &a)
{
return (float)a;
@ -130,10 +148,39 @@ static ColorGeometry4f int_to_color(const int32_t &a)
return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
}
static bool int8_to_bool(const int8_t &a)
{
return a > 0;
}
static int int8_to_int(const int8_t &a)
{
return static_cast<int>(a);
}
static float int8_to_float(const int8_t &a)
{
return (float)a;
}
static float2 int8_to_float2(const int8_t &a)
{
return float2((float)a);
}
static float3 int8_to_float3(const int8_t &a)
{
return float3((float)a);
}
static ColorGeometry4f int8_to_color(const int8_t &a)
{
return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
}
static float bool_to_float(const bool &a)
{
return (bool)a;
}
static int8_t bool_to_int8(const bool &a)
{
return static_cast<int8_t>(a);
}
static int32_t bool_to_int(const bool &a)
{
return (int32_t)a;
@ -163,6 +210,10 @@ static int32_t color_to_int(const ColorGeometry4f &a)
{
return (int)rgb_to_grayscale(a);
}
static int8_t color_to_int8(const ColorGeometry4f &a)
{
return int_to_int8(color_to_int(a));
}
static float2 color_to_float2(const ColorGeometry4f &a)
{
return float2(a.r, a.g);
@ -180,33 +231,46 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float, float3, float_to_float3>(conversions);
add_implicit_conversion<float, int32_t, float_to_int>(conversions);
add_implicit_conversion<float, bool, float_to_bool>(conversions);
add_implicit_conversion<float, int8_t, float_to_int8>(conversions);
add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
add_implicit_conversion<float2, float, float2_to_float>(conversions);
add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
add_implicit_conversion<float2, int8_t, float2_to_int8>(conversions);
add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
add_implicit_conversion<float3, bool, float3_to_bool>(conversions);
add_implicit_conversion<float3, int8_t, float3_to_int8>(conversions);
add_implicit_conversion<float3, float, float3_to_float>(conversions);
add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
add_implicit_conversion<int32_t, int8_t, int_to_int8>(conversions);
add_implicit_conversion<int32_t, float, int_to_float>(conversions);
add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
add_implicit_conversion<int8_t, bool, int8_to_bool>(conversions);
add_implicit_conversion<int8_t, int32_t, int8_to_int>(conversions);
add_implicit_conversion<int8_t, float, int8_to_float>(conversions);
add_implicit_conversion<int8_t, float2, int8_to_float2>(conversions);
add_implicit_conversion<int8_t, float3, int8_to_float3>(conversions);
add_implicit_conversion<int8_t, ColorGeometry4f, int8_to_color>(conversions);
add_implicit_conversion<bool, float, bool_to_float>(conversions);
add_implicit_conversion<bool, int8_t, bool_to_int8>(conversions);
add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
add_implicit_conversion<ColorGeometry4f, bool, color_to_bool>(conversions);
add_implicit_conversion<ColorGeometry4f, int8_t, color_to_int8>(conversions);
add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);

View File

@ -28,10 +28,12 @@
namespace blender::threading {
#ifndef WITH_TBB
namespace enumerable_thread_specific_utils {
inline std::atomic<int> next_id = 0;
inline thread_local int thread_id = next_id.fetch_add(1, std::memory_order_relaxed);
} // namespace enumerable_thread_specific_utils
#endif
/**
* This is mainly a wrapper for `tbb::enumerable_thread_specific`. The wrapper is needed because we

View File

@ -373,8 +373,7 @@ constexpr int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) cons
constexpr int64_t StringRefBase::find_last_of(char c, int64_t pos) const
{
BLI_assert(pos >= 0);
return index_or_npos_to_int64(
std::string_view(*this).find_last_of(c, static_cast<size_t>(pos)));
return index_or_npos_to_int64(std::string_view(*this).find_last_of(c, static_cast<size_t>(pos)));
}
constexpr int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const

View File

@ -1107,6 +1107,15 @@ static bool seq_transform_origin_set(Sequence *seq, void *UNUSED(user_data))
return true;
}
static bool seq_transform_filter_set(Sequence *seq, void *UNUSED(user_data))
{
StripTransform *transform = seq->strip->transform;
if (seq->strip->transform != NULL) {
transform->filter = SEQ_TRANSFORM_FILTER_BILINEAR;
}
return true;
}
static void do_version_subsurface_methods(bNode *node)
{
if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
@ -2549,6 +2558,14 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 302, 2)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (scene->ed != NULL) {
SEQ_for_each_callback(&scene->ed->seqbase, seq_transform_filter_set, NULL);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -451,6 +451,16 @@ static bool nearly_parallel_normalized(const float d1[3], const float d2[3])
return compare_ff(fabsf(direction_dot), 1.0f, BEVEL_EPSILON_ANG_DOT);
}
/**
* calculate the determinant of a matrix formed by three vectors
* \return dot(a, cross(b, c)) = determinant(a, b, c)
*/
static float determinant_v3v3v3(const float a[3], const float b[3], const float c[3])
{
return a[0] * b[1] * c[2] + a[1] * b[2] * c[0] + a[2] * b[0] * c[1] - a[0] * b[2] * c[1] -
a[1] * b[0] * c[2] - a[2] * b[1] * c[0];
}
/* Make a new BoundVert of the given kind, inserting it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@ -4118,44 +4128,114 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
VMesh *vm_out = new_adj_vmesh(bp->mem_arena, n_boundary, ns_out, vm_in->boundstart);
/* First we adjust the boundary vertices of the input mesh, storing in output mesh. */
BoundVert *bndv = vm_in->boundstart;
for (int i = 0; i < n_boundary; i++) {
float co1[3], co2[3], acc[3];
EdgeHalf *e = bndv->elast;
/* Generate tangents. This is hacked together and would ideally be done elsewhere and then only
* used here. */
float tangent[3], tangent2[3], normal[3];
bool convex = true;
bool orthogonal = false;
float stretch = 0.0f;
if (e) {
/* Projection direction is direction of the edge. */
sub_v3_v3v3(tangent, e->e->v1->co, e->e->v2->co);
if (e->is_rev) {
negate_v3(tangent);
}
normalize_v3(tangent);
if (bndv->is_arc_start || bndv->is_patch_start) {
BMFace *face = e->fnext;
if (face) {
copy_v3_v3(normal, face->no);
}
else {
zero_v3(normal);
}
madd_v3_v3v3fl(co2, bndv->profile.middle, normal, 0.1f);
}
if (bndv->is_arc_start || bp->affect_type == BEVEL_AFFECT_VERTICES) {
EdgeHalf *e1 = bndv->next->elast;
BLI_assert(e1);
sub_v3_v3v3(tangent2, e1->e->v1->co, e1->e->v2->co);
if (e1->is_rev) {
negate_v3(tangent2);
}
normalize_v3(tangent2);
convex = determinant_v3v3v3(tangent2, tangent, normal) < 0;
add_v3_v3(tangent2, tangent);
normalize_v3(tangent2);
copy_v3_v3(tangent, tangent2);
}
/* Calculate a factor which determines how much the interpolated mesh is
* going to be stretched out into the direction of the tangent.
* It is currently using the difference along the tangent of the
* central point on the profile and the current center vertex position. */
get_profile_point(bp, &bndv->profile, ns_in2, ns_in, co);
stretch = dot_v3v3(tangent, mesh_vert(vm_in, i, ns_in2, ns_in2)->co) - dot_v3v3(tangent, co);
stretch = fabsf(stretch);
/* Scale the tangent by stretch. The divide by ns_in2 comes from the Levin Paper. */
mul_v3_fl(tangent, stretch / ns_in2);
orthogonal = bndv->is_patch_start;
}
else if (bndv->prev->is_patch_start) {
/* If this is the second edge of a patch and therefore #e is NULL,
* then e->fprev has to be used/not NULL. */
BLI_assert(bndv->prev->elast);
BMFace *face = bndv->prev->elast->fnext;
if (face) {
copy_v3_v3(normal, face->no);
}
else {
zero_v3(normal);
}
orthogonal = true;
}
else {
/** Should only come here from make_cube_corner_adj_vmesh. */
sub_v3_v3v3(co1, mesh_vert(vm_in, i, 0, 0)->co, mesh_vert(vm_in, i, 0, 1)->co);
sub_v3_v3v3(co2, mesh_vert(vm_in, i, 0, 1)->co, mesh_vert(vm_in, i, 0, 2)->co);
cross_v3_v3v3(tangent, co1, co2);
/** The following constant is chosen to best match the old results. */
normalize_v3_length(tangent, 1.5f / ns_out);
}
/** Copy corner vertex. */
copy_v3_v3(mesh_vert(vm_out, i, 0, 0)->co, mesh_vert(vm_in, i, 0, 0)->co);
/** Copy the rest of the boundary vertices. */
for (int k = 1; k < ns_in; k++) {
copy_v3_v3(co, mesh_vert(vm_in, i, 0, k)->co);
/* Smooth boundary rule. Custom profiles shouldn't be smoothed. */
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
float co1[3], co2[3], acc[3];
copy_v3_v3(co1, mesh_vert(vm_in, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert(vm_in, i, 0, k + 1)->co);
copy_v3_v3(co1, mesh_vert(vm_in, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert(vm_in, i, 0, k + 1)->co);
add_v3_v3v3(acc, co1, co2);
madd_v3_v3fl(acc, co, -2.0f);
madd_v3_v3fl(co, acc, -1.0f / 6.0f);
add_v3_v3v3(acc, co1, co2);
if (bndv->is_arc_start) {
sub_v3_v3(co1, co);
sub_v3_v3(co2, co);
normalize_v3(co1);
normalize_v3(co2);
add_v3_v3v3(tangent, co1, co2);
/* This is an empirical formula to make the result look good. */
normalize_v3(tangent);
float dot = convex ? fminf(0, dot_v3v3(tangent2, tangent)) : 1.0f;
mul_v3_fl(tangent, stretch / ns_in * dot);
}
else if (orthogonal) {
sub_v3_v3(co1, co);
cross_v3_v3v3(tangent, normal, co1);
/* This is an empirical formula to make the result look good. */
normalize_v3_length(tangent, -bp->offset * 0.7071f / ns_in);
}
mul_v3_fl(co, 2.0f);
madd_v3_v3fl(co, acc, -0.25f);
madd_v3_v3fl(co, mesh_vert(vm_in, i, 1, k)->co, -0.5f);
add_v3_v3(co, tangent);
copy_v3_v3(mesh_vert_canon(vm_out, i, 0, 2 * k)->co, co);
}
}
/* Now adjust odd boundary vertices in output mesh, based on even ones. */
BoundVert *bndv = vm_out->boundstart;
for (int i = 0; i < n_boundary; i++) {
for (int k = 1; k < ns_out; k += 2) {
get_profile_point(bp, &bndv->profile, k, ns_out, co);
/* Smooth if using a non-custom profile. */
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
float co1[3], co2[3], acc[3];
copy_v3_v3(co1, mesh_vert_canon(vm_out, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert_canon(vm_out, i, 0, k + 1)->co);
add_v3_v3v3(acc, co1, co2);
madd_v3_v3fl(acc, co, -2.0f);
madd_v3_v3fl(co, acc, -1.0f / 6.0f);
}
copy_v3_v3(mesh_vert_canon(vm_out, i, 0, k)->co, co);
}
bndv = bndv->next;
}
vmesh_copy_equiv_verts(vm_out);
@ -4163,7 +4243,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
/* Copy adjusted verts back into vm_in. */
for (int i = 0; i < n_boundary; i++) {
for (int k = 0; k < ns_in; k++) {
copy_v3_v3(mesh_vert(vm_in, i, 0, k)->co, mesh_vert(vm_out, i, 0, 2 * k)->co);
copy_v3_v3(mesh_vert_canon(vm_in, i, 0, k)->co, mesh_vert_canon(vm_out, i, 0, 2 * k)->co);
}
}
@ -4248,7 +4328,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
vmesh_copy_equiv_verts(vm_out);
/* The center vertex is special. */
gamma = sabin_gamma(n_boundary);
gamma = sabin_gamma(n_boundary) * 0.5f;
beta = -gamma;
/* Accumulate edge verts in co1, face verts in co2. */
float co1[3], co2[3];

View File

@ -1992,7 +1992,7 @@ void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
"Particle Texture -> Particle Reset",
RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
add_relation(texture_key, particle_settings_eval_key, "Particle Texture -> Particle Eval");
/* TODO(sergey): Consider moving texture space handling to an own
/* TODO(sergey): Consider moving texture space handling to its own
* function. */
if (mtex->texco == TEXCO_OBJECT && mtex->object != nullptr) {
ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);

View File

@ -646,8 +646,8 @@ void set_particle_system_modifiers_loaded(Object *object_cow)
void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
{
/* Inactive (and render) dependency graphs are living in own little bubble, should not care about
* edit mode at all. */
/* Inactive (and render) dependency graphs are living in their own little bubble, should not care
* about edit mode at all. */
if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
return;
}

View File

@ -393,7 +393,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
*
* Returns true when a float buffer was created. Somehow the VSE cache increases the ref
* counter, but might use a different mechanism for destructing the image, that doesn't free the
* rect_float as the refcounter isn't 0. To work around this we destruct any created local
* rect_float as the reference-counter isn't 0. To work around this we destruct any created local
* buffers ourself.
*/
bool ensure_float_buffer(ImBuf &image_buffer) const

View File

@ -191,20 +191,17 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.4f);
cb->transp.point_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.custom_fill = grp;
cb->solid.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@ -213,7 +210,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_disable(grp, DRW_STATE_WRITE_DEPTH);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", wire_alpha * 0.6f);
cb->transp.custom_fill = grp;
cb->transp.box_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@ -335,7 +331,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", false);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->solid.envelope_fill = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@ -371,7 +366,6 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_transp_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);

View File

@ -43,7 +43,6 @@ void OVERLAY_fade_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_uniform_color();
pd->fade_grp[i] = DRW_shgroup_create(sh, psl->fade_ps[i]);
DRW_shgroup_uniform_block(pd->fade_grp[i], "globalsBlock", G_draw.block_ubo);
const DRWContextState *draw_ctx = DRW_context_state_get();
float color[4];

View File

@ -37,7 +37,6 @@ void OVERLAY_volume_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_depth_only();
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->volume_ps);
pd->volume_selection_surface_grp = grp;
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
else {
psl->volume_ps = NULL;

View File

@ -40,7 +40,7 @@ void main()
}
else if (lineStyle == OVERLAY_UV_LINE_STYLE_DASH) {
if (fract(line_distance / dashLength) < 0.5) {
inner_color = mix(vec4(1.0), colorEdgeSelect, selectionFac_f);
inner_color = mix(vec4(vec3(0.35), 1.0), colorEdgeSelect, selectionFac_f);
}
}
else if (lineStyle == OVERLAY_UV_LINE_STYLE_BLACK) {

View File

@ -13,7 +13,7 @@ GPU_SHADER_CREATE_INFO(workbench_composite)
.fragment_out(0, Type::VEC4, "fragColor")
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_composite_frag.glsl")
.additional_info("draw_fullscreen");
.additional_info("draw_fullscreen", "draw_view");
/** \} */

View File

@ -272,8 +272,8 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
{
eV3DShadingColorType color_type = wpd->shading.color_type;
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
const CustomData *ldata = workbench_mesh_get_loop_custom_data(me);
const CustomData *vdata = workbench_mesh_get_vert_custom_data(me);
const CustomData *ldata = (me == NULL) ? NULL : workbench_mesh_get_loop_custom_data(me);
const CustomData *vdata = (me == NULL) ? NULL : workbench_mesh_get_vert_custom_data(me);
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_active = (ob == draw_ctx->obact);

View File

@ -1,6 +1,6 @@
#ifndef GPU_SHADER
# include "gpu_shader_shared_utils.h"
# include "GPU_shader_shared_utils.h"
#endif
#define WORKBENCH_SHADER_SHARED_H

View File

@ -295,6 +295,10 @@ class UniformArrayBuffer : public detail::UniformCommon<T, len, false> {
/* TODO(@fclem): We should map memory instead. */
this->data_ = (T *)MEM_mallocN_aligned(len * sizeof(T), 16, this->name_);
}
~UniformArrayBuffer()
{
MEM_freeN(this->data_);
}
};
template<
@ -674,14 +678,6 @@ class Texture : NonCopyable {
if (h == 0) {
return GPU_texture_create_1d(name_, w, mips, format, data);
}
else if (d == 0) {
if (layered) {
return GPU_texture_create_1d_array(name_, w, h, mips, format, data);
}
else {
return GPU_texture_create_2d(name_, w, h, mips, format, data);
}
}
else if (cubemap) {
if (layered) {
return GPU_texture_create_cube_array(name_, w, d, mips, format, data);
@ -690,6 +686,14 @@ class Texture : NonCopyable {
return GPU_texture_create_cube(name_, w, mips, format, data);
}
}
else if (d == 0) {
if (layered) {
return GPU_texture_create_1d_array(name_, w, h, mips, format, data);
}
else {
return GPU_texture_create_2d(name_, w, h, mips, format, data);
}
}
else {
if (layered) {
return GPU_texture_create_2d_array(name_, w, h, d, mips, format, data);

View File

@ -66,6 +66,15 @@
extern "C" {
#endif
/* Uncomment to track unused resource bindings. */
// #define DRW_UNUSED_RESOURCE_TRACKING
#ifdef DRW_UNUSED_RESOURCE_TRACKING
# define DRW_DEBUG_FILE_LINE_ARGS , const char *file, int line
#else
# define DRW_DEBUG_FILE_LINE_ARGS
#endif
struct GPUBatch;
struct GPUMaterial;
struct GPUShader;
@ -468,6 +477,10 @@ void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
int groups_x_len,
int groups_y_len,
int groups_z_len);
/**
* \warning this keeps the ref to groups_ref until it actually dispatch.
*/
void DRW_shgroup_call_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3]);
void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_count);
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_count);
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, Object *ob, uint tri_count);
@ -533,6 +546,11 @@ void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
*/
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
/**
* Issue a barrier command.
*/
void DRW_shgroup_barrier(DRWShadingGroup *shgroup, eGPUBarrier type);
/**
* Issue a clear command.
*/
@ -559,12 +577,12 @@ void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup,
const char *name,
struct GPUTexture **tex);
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
const char *name,
const struct GPUUniformBuf *ubo);
void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
const char *name,
struct GPUUniformBuf **ubo);
void DRW_shgroup_uniform_block_ex(DRWShadingGroup *shgroup,
const char *name,
const struct GPUUniformBuf *ubo DRW_DEBUG_FILE_LINE_ARGS);
void DRW_shgroup_uniform_block_ref_ex(DRWShadingGroup *shgroup,
const char *name,
struct GPUUniformBuf **ubo DRW_DEBUG_FILE_LINE_ARGS);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
const char *name,
const float *value,
@ -624,9 +642,32 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
const char *name,
const float (*value)[4],
int arraysize);
void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
const char *name,
struct GPUVertBuf *vertex_buffer);
void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup,
const char *name,
struct GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS);
void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup,
const char *name,
struct GPUVertBuf **vertex_buffer DRW_DEBUG_FILE_LINE_ARGS);
#ifdef DRW_UNUSED_RESOURCE_TRACKING
# define DRW_shgroup_vertex_buffer(shgroup, name, vert) \
DRW_shgroup_vertex_buffer_ex(shgroup, name, vert, __FILE__, __LINE__)
# define DRW_shgroup_vertex_buffer_ref(shgroup, name, vert) \
DRW_shgroup_vertex_buffer_ref_ex(shgroup, name, vert, __FILE__, __LINE__)
# define DRW_shgroup_uniform_block(shgroup, name, ubo) \
DRW_shgroup_uniform_block_ex(shgroup, name, ubo, __FILE__, __LINE__)
# define DRW_shgroup_uniform_block_ref(shgroup, name, ubo) \
DRW_shgroup_uniform_block_ref_ex(shgroup, name, ubo, __FILE__, __LINE__)
#else
# define DRW_shgroup_vertex_buffer(shgroup, name, vert) \
DRW_shgroup_vertex_buffer_ex(shgroup, name, vert)
# define DRW_shgroup_vertex_buffer_ref(shgroup, name, vert) \
DRW_shgroup_vertex_buffer_ref_ex(shgroup, name, vert)
# define DRW_shgroup_uniform_block(shgroup, name, ubo) \
DRW_shgroup_uniform_block_ex(shgroup, name, ubo)
# define DRW_shgroup_uniform_block_ref(shgroup, name, ubo) \
DRW_shgroup_uniform_block_ref_ex(shgroup, name, ubo)
#endif
bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);

View File

@ -505,8 +505,9 @@ static bool custom_data_match_attribute(const CustomData *custom_data,
int *r_layer_index,
int *r_type)
{
const int possible_attribute_types[6] = {
const int possible_attribute_types[7] = {
CD_PROP_BOOL,
CD_PROP_INT8,
CD_PROP_INT32,
CD_PROP_FLOAT,
CD_PROP_FLOAT2,
@ -655,6 +656,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
break;
}
case CD_PROP_BOOL:
case CD_PROP_INT8:
case CD_PROP_INT32:
case CD_PROP_FLOAT:
case CD_PROP_FLOAT2:

View File

@ -205,8 +205,10 @@ typedef enum {
/* Compute Commands. */
DRW_CMD_COMPUTE = 8,
DRW_CMD_COMPUTE_REF = 9,
/* Other Commands */
DRW_CMD_BARRIER = 11,
DRW_CMD_CLEAR = 12,
DRW_CMD_DRWSTATE = 13,
DRW_CMD_STENCIL = 14,
@ -249,6 +251,14 @@ typedef struct DRWCommandCompute {
int groups_z_len;
} DRWCommandCompute;
typedef struct DRWCommandComputeRef {
int *groups_ref;
} DRWCommandComputeRef;
typedef struct DRWCommandBarrier {
eGPUBarrier type;
} DRWCommandBarrier;
typedef struct DRWCommandDrawProcedural {
GPUBatch *batch;
DRWResourceHandle handle;
@ -286,6 +296,8 @@ typedef union DRWCommand {
DRWCommandDrawInstanceRange instance_range;
DRWCommandDrawProcedural procedural;
DRWCommandCompute compute;
DRWCommandComputeRef compute_ref;
DRWCommandBarrier barrier;
DRWCommandSetMutableState state;
DRWCommandSetStencil stencil;
DRWCommandSetSelectID select_id;
@ -314,6 +326,7 @@ typedef enum {
DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE,
DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
@ -345,6 +358,11 @@ struct DRWUniform {
GPUUniformBuf *block;
GPUUniformBuf **block_ref;
};
/* DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE */
union {
GPUVertBuf *vertbuf;
GPUVertBuf **vertbuf_ref;
};
/* DRW_UNIFORM_FLOAT_COPY */
float fvalue[4];
/* DRW_UNIFORM_INT_COPY */

View File

@ -283,19 +283,45 @@ void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, G
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE_REF, tex, 0, 0, 1);
}
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
const char *name,
const GPUUniformBuf *ubo)
void DRW_shgroup_uniform_block_ex(DRWShadingGroup *shgroup,
const char *name,
const GPUUniformBuf *ubo DRW_DEBUG_FILE_LINE_ARGS)
{
BLI_assert(ubo != NULL);
int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
if (loc == -1) {
#ifdef DRW_UNUSED_RESOURCE_TRACKING
printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n",
file,
line,
name);
#else
/* TODO(@fclem): Would be good to have, but eevee has too much of this for the moment. */
// BLI_assert_msg(0, "Unable to locate binding of shader uniform buffer objects.");
#endif
return;
}
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
}
void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup, const char *name, GPUUniformBuf **ubo)
void DRW_shgroup_uniform_block_ref_ex(DRWShadingGroup *shgroup,
const char *name,
GPUUniformBuf **ubo DRW_DEBUG_FILE_LINE_ARGS)
{
BLI_assert(ubo != NULL);
int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
if (loc == -1) {
#ifdef DRW_UNUSED_RESOURCE_TRACKING
printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n",
file,
line,
name);
#else
/* TODO(@fclem): Would be good to have, but eevee has too much of this for the moment. */
// BLI_assert_msg(0, "Unable to locate binding of shader uniform buffer objects.");
#endif
return;
}
drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
}
@ -447,19 +473,46 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
}
}
void DRW_shgroup_vertex_buffer(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf *vertex_buffer)
void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS)
{
int location = GPU_shader_get_ssbo(shgroup->shader, name);
if (location == -1) {
#ifdef DRW_UNUSED_RESOURCE_TRACKING
printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n",
file,
line,
name);
#else
BLI_assert_msg(0, "Unable to locate binding of shader storage buffer objects.");
#endif
return;
}
drw_shgroup_uniform_create_ex(
shgroup, location, DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE, vertex_buffer, 0, 0, 1);
}
void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf **vertex_buffer DRW_DEBUG_FILE_LINE_ARGS)
{
int location = GPU_shader_get_ssbo(shgroup->shader, name);
if (location == -1) {
#ifdef DRW_UNUSED_RESOURCE_TRACKING
printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n",
file,
line,
name);
#else
BLI_assert_msg(0, "Unable to locate binding of shader storage buffer objects.");
#endif
return;
}
drw_shgroup_uniform_create_ex(
shgroup, location, DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF, vertex_buffer, 0, 0, 1);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -730,6 +783,18 @@ static void drw_command_compute(DRWShadingGroup *shgroup,
cmd->groups_z_len = groups_z_len;
}
static void drw_command_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3])
{
DRWCommandComputeRef *cmd = drw_command_create(shgroup, DRW_CMD_COMPUTE_REF);
cmd->groups_ref = groups_ref;
}
static void drw_command_barrier(DRWShadingGroup *shgroup, eGPUBarrier type)
{
DRWCommandBarrier *cmd = drw_command_create(shgroup, DRW_CMD_BARRIER);
cmd->type = type;
}
static void drw_command_draw_procedural(DRWShadingGroup *shgroup,
GPUBatch *batch,
DRWResourceHandle handle,
@ -855,6 +920,20 @@ void DRW_shgroup_call_compute(DRWShadingGroup *shgroup,
drw_command_compute(shgroup, groups_x_len, groups_y_len, groups_z_len);
}
void DRW_shgroup_call_compute_ref(DRWShadingGroup *shgroup, int groups_ref[3])
{
BLI_assert(GPU_compute_shader_support());
drw_command_compute_ref(shgroup, groups_ref);
}
void DRW_shgroup_barrier(DRWShadingGroup *shgroup, eGPUBarrier type)
{
BLI_assert(GPU_compute_shader_support());
drw_command_barrier(shgroup, type);
}
static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
GPUBatch *geom,
Object *ob,

View File

@ -662,8 +662,11 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
*use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
((GPUVertBuf *)uni->pvalue));
break;
case DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE_REF:
GPU_vertbuf_bind_as_ssbo(*uni->vertbuf_ref, uni->location);
break;
case DRW_UNIFORM_VERTEX_BUFFER_AS_STORAGE:
GPU_vertbuf_bind_as_ssbo((GPUVertBuf *)uni->pvalue, uni->location);
GPU_vertbuf_bind_as_ssbo(uni->vertbuf, uni->location);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
@ -1049,6 +1052,15 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
cmd->compute.groups_y_len,
cmd->compute.groups_z_len);
break;
case DRW_CMD_COMPUTE_REF:
GPU_compute_dispatch(shgroup->shader,
cmd->compute_ref.groups_ref[0],
cmd->compute_ref.groups_ref[1],
cmd->compute_ref.groups_ref[2]);
break;
case DRW_CMD_BARRIER:
GPU_memory_barrier(cmd->barrier.type);
break;
}
}

View File

@ -1,6 +1,6 @@
#ifndef GPU_SHADER
# include "gpu_shader_shared_utils.h"
# include "GPU_shader_shared_utils.h"
#endif
#define DRW_SHADER_SHARED_H

View File

@ -99,6 +99,7 @@ static uint gpu_component_size_for_attribute_type(CustomDataType type)
{
switch (type) {
case CD_PROP_BOOL:
case CD_PROP_INT8:
case CD_PROP_INT32:
case CD_PROP_FLOAT: {
/* TODO(@kevindietrich): should be 1 when scalar attributes conversion is handled by us. See
@ -326,6 +327,10 @@ static void extract_attr_init(const MeshRenderData *mr,
extract_attr_generic<bool, float3>(mr, vbo, request);
break;
}
case CD_PROP_INT8: {
extract_attr_generic<int8_t, float3>(mr, vbo, request);
break;
}
case CD_PROP_INT32: {
extract_attr_generic<int32_t, float3>(mr, vbo, request);
break;
@ -378,6 +383,10 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache,
extract_attr_generic<bool, float3>(mr, src_data, request);
break;
}
case CD_PROP_INT8: {
extract_attr_generic<int8_t, float3>(mr, src_data, request);
break;
}
case CD_PROP_INT32: {
extract_attr_generic<int32_t, float3>(mr, src_data, request);
break;

View File

@ -1,5 +1,5 @@
/* Temporary until we fully make the switch. */
#ifndef DRW_SHADER_SHARED_H
#ifndef USE_GPU_SHADER_CREATE_INFO
# define DRW_RESOURCE_CHUNK_LEN 512
@ -24,7 +24,13 @@ layout(std140) uniform viewBlock
vec4 CameraTexCoFactors;
};
#endif /* DRW_SHADER_SHARED_H */
#endif /* USE_GPU_SHADER_CREATE_INFO */
#ifdef USE_GPU_SHADER_CREATE_INFO
# ifndef DRW_RESOURCE_CHUNK_LEN
# error "Missing draw_view additional create info on shader create info"
# endif
#endif
#define ViewNear (ViewVecs[0].w)
#define ViewFar (ViewVecs[1].w)

View File

@ -30,7 +30,7 @@ GPU_SHADER_CREATE_INFO(draw_resource_id_uniform)
/**
* Declare a resource handle that identify a unique object.
* Requires draw_resource_id[_constant].
* Requires draw_resource_id[_uniform].
*/
GPU_SHADER_CREATE_INFO(draw_resource_handle)
.define("resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id)")

View File

@ -2073,8 +2073,9 @@ static void UI_OT_tree_view_drop(wmOperatorType *ot)
/** \name UI Tree-View Item Rename Operator
*
* General purpose renaming operator for tree-views. Thanks to this, to add a rename button to
* context menus for example, tree-view API users don't have to implement own renaming operators
* with the same logic as they already have for their #ui::AbstractTreeViewItem::rename() override.
* context menus for example, tree-view API users don't have to implement their own renaming
* operators with the same logic as they already have for their #ui::AbstractTreeViewItem::rename()
* override.
*
* \{ */

View File

@ -453,15 +453,6 @@ void uiStyleInit(void)
printf("%s: error, no fonts available\n", __func__);
}
}
else {
/* ? just for speed to initialize?
* Yes, this build the glyph cache and create
* the texture.
*/
BLF_size(font->blf_id, 11.0f * U.pixelsize, U.dpi);
BLF_size(font->blf_id, 12.0f * U.pixelsize, U.dpi);
BLF_size(font->blf_id, 14.0f * U.pixelsize, U.dpi);
}
}
if (style == NULL) {
@ -485,8 +476,6 @@ void uiStyleInit(void)
blf_mono_font = BLF_load_mono_default(unique);
}
BLF_size(blf_mono_font, 12.0f * U.pixelsize, 72);
/* Set default flags based on UI preferences (not render fonts) */
{
const int flag_disable = (BLF_MONOCHROME | BLF_HINTING_NONE | BLF_HINTING_SLIGHT |
@ -529,8 +518,6 @@ void uiStyleInit(void)
const bool unique = true;
blf_mono_font_render = BLF_load_mono_default(unique);
}
BLF_size(blf_mono_font_render, 12.0f * U.pixelsize, 72);
}
void UI_fontstyle_set(const uiFontStyle *fs)

View File

@ -90,7 +90,7 @@ struct RenderJob {
Scene *scene;
ViewLayer *single_layer;
Scene *current_scene;
/* TODO(sergey): Should not be needed once engine will have own
/* TODO(sergey): Should not be needed once engine will have its own
* depsgraph and copy-on-write will be implemented.
*/
Depsgraph *depsgraph;
@ -981,7 +981,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->scene = scene;
rj->current_scene = rj->scene;
rj->single_layer = single_layer;
/* TODO(sergey): Render engine should be using own depsgraph.
/* TODO(sergey): Render engine should be using its own depsgraph.
*
* NOTE: Currently is only used by ED_update_for_newframe() at the end of the render, so no
* need to ensure evaluation here. */

View File

@ -767,7 +767,7 @@ struct ObjectPreviewData {
/* The main for the preview, not of the current file. */
Main *pr_main;
/* Copy of the object to create the preview for. The copy is for thread safety (and to insert
* it into an own main). */
* it into its own main). */
Object *object;
/* Current frame. */
int cfra;

View File

@ -483,7 +483,7 @@ static char *decimate_desc(bContext *UNUSED(C), wmOperatorType *UNUSED(op), Poin
if (RNA_enum_get(ptr, "mode") == DECIM_ERROR) {
return BLI_strdup(
TIP_("Decimate F-Curves by specifying how much it can deviate from the original curve"));
TIP_("Decimate F-Curves by specifying how much they can deviate from the original curve"));
}
/* Use default description. */

View File

@ -127,6 +127,28 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
}
if (data.type().is<int8_t>()) {
const int8_t value = data.get<int8_t>(real_index);
const std::string value_str = std::to_string(value);
uiBut *but = uiDefIconTextBut(params.block,
UI_BTYPE_LABEL,
0,
ICON_NONE,
value_str.c_str(),
params.xmin,
params.ymin,
params.width,
params.height,
nullptr,
0,
0,
0,
0,
nullptr);
/* Right-align Integers. */
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
}
else if (data.type().is<float>()) {
const float value = data.get<float>(real_index);
std::stringstream ss;

View File

@ -243,7 +243,7 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, filter_ptr, "value_string", 0, IFACE_("Value"), ICON_NONE);
break;
case SPREADSHEET_VALUE_TYPE_UNKNOWN:
uiItemL(layout, IFACE_("Unkown column type"), ICON_ERROR);
uiItemL(layout, IFACE_("Unknown column type"), ICON_ERROR);
break;
}
}

View File

@ -244,7 +244,6 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area)
for (region = area->regionbase.first; region; region = region->next) {
if ((region->regiontype == RGN_TYPE_WINDOW) && region->regiondata) {
ED_view3d_stop_render_preview(wm, region);
break;
}
}
}

View File

@ -143,21 +143,6 @@ void calctrackballvec(const rcti *rect, const int event_xy[2], float r_dir[3])
}
}
void viewops_data_alloc(bContext *C, wmOperator *op)
{
ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data");
/* store data */
op->customdata = vod;
vod->bmain = CTX_data_main(C);
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
vod->scene = CTX_data_scene(C);
vod->area = CTX_wm_area(C);
vod->region = CTX_wm_region(C);
vod->v3d = vod->area->spacedata.first;
vod->rv3d = vod->region->regiondata;
}
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
const float ofs_old[3],
const float viewquat_old[4],
@ -289,13 +274,20 @@ enum eViewOpsFlag viewops_flag_from_prefs(void)
(U.uiflag & USER_DEPTH_NAVIGATE) != 0);
}
void viewops_data_create(bContext *C,
wmOperator *op,
const wmEvent *event,
enum eViewOpsFlag viewops_flag)
ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewOpsData *vod = op->customdata;
ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), __func__);
/* Store data. */
vod->bmain = CTX_data_main(C);
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
vod->scene = CTX_data_scene(C);
vod->area = CTX_wm_area(C);
vod->region = CTX_wm_region(C);
vod->v3d = vod->area->spacedata.first;
vod->rv3d = vod->region->regiondata;
Depsgraph *depsgraph = vod->depsgraph;
RegionView3D *rv3d = vod->rv3d;
/* Could do this more nicely. */
@ -427,13 +419,14 @@ void viewops_data_create(bContext *C,
}
rv3d->rflag |= RV3D_NAVIGATING;
return vod;
}
void viewops_data_free(bContext *C, wmOperator *op)
void viewops_data_free(bContext *C, ViewOpsData *vod)
{
ARegion *region;
if (op->customdata) {
ViewOpsData *vod = op->customdata;
if (vod) {
region = vod->region;
vod->rv3d->rflag &= ~RV3D_NAVIGATING;
@ -446,7 +439,6 @@ void viewops_data_free(bContext *C, wmOperator *op)
}
MEM_freeN(vod);
op->customdata = NULL;
}
else {
region = CTX_wm_region(C);
@ -1569,13 +1561,12 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
y = 25;
}
viewops_data_alloc(C, op);
viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
ViewOpsData *vod = op->customdata;
ViewOpsData *vod = viewops_data_create(
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT));
viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
viewops_data_free(C, op);
viewops_data_free(C, vod);
return OPERATOR_FINISHED;
}

View File

@ -82,7 +82,7 @@ enum eViewOpsFlag {
/** Generic View Operator Custom-Data */
typedef struct ViewOpsData {
/** Context pointers (assigned by #viewops_data_alloc). */
/** Context pointers (assigned by #viewops_data_create). */
struct Main *bmain;
struct Scene *scene;
struct ScrArea *area;
@ -169,16 +169,14 @@ void view3d_operator_properties_common(struct wmOperatorType *ot, const enum eV3
/**
* Allocate and fill in context pointers for #ViewOpsData
*/
void viewops_data_alloc(struct bContext *C, struct wmOperator *op);
void viewops_data_free(struct bContext *C, struct wmOperator *op);
void viewops_data_free(struct bContext *C, ViewOpsData *vod);
/**
* Calculate the values for #ViewOpsData
* Allocate, fill in context pointers and calculate the values for #ViewOpsData
*/
void viewops_data_create(struct bContext *C,
struct wmOperator *op,
const struct wmEvent *event,
enum eViewOpsFlag viewops_flag);
ViewOpsData *viewops_data_create(struct bContext *C,
const struct wmEvent *event,
enum eViewOpsFlag viewops_flag);
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
void VIEW3D_OT_view_selected(struct wmOperatorType *ot);

View File

@ -174,7 +174,8 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret & OPERATOR_FINISHED) {
viewops_data_free(C, op);
viewops_data_free(C, vod);
op->customdata = NULL;
}
return ret;
@ -225,7 +226,8 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
ED_region_tag_redraw(region);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -239,9 +241,13 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
/* makes op->customdata */
viewops_data_alloc(C, op);
vod = op->customdata;
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
vod = op->customdata = viewops_data_create(
C,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
@ -259,14 +265,6 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->region);
}
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
viewops_data_create(C,
op,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
/* if one or the other zoom position aren't set, set from event */
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
RNA_int_set(op->ptr, "mx", event->xy[0]);
@ -296,7 +294,8 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
viewdolly_apply(vod, event->prev_xy, (U.uiflag & USER_ZOOM_INVERT) == 0);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -309,7 +308,8 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void viewdolly_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
void VIEW3D_OT_dolly(wmOperatorType *ot)

View File

@ -1103,9 +1103,9 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else
#endif /* WITH_INPUT_NDOF */
if (event->type == TIMER && event->customdata == fly->timer) {
flyApply(C, fly, false);
}
if (event->type == TIMER && event->customdata == fly->timer) {
flyApply(C, fly, false);
}
do_draw |= fly->redraw;

View File

@ -119,7 +119,8 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret & OPERATOR_FINISHED) {
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
return ret;
@ -131,13 +132,11 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
/* makes op->customdata */
viewops_data_alloc(C, op);
viewops_data_create(C,
op,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata = viewops_data_create(
C,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
@ -147,7 +146,8 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewmove_apply(
vod, 2 * event->xy[0] - event->prev_xy[0], 2 * event->xy[1] - event->prev_xy[1]);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -160,7 +160,8 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void viewmove_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
void VIEW3D_OT_move(wmOperatorType *ot)

View File

@ -378,9 +378,8 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
vod = op->customdata;
vod = op->customdata = viewops_data_create(
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
@ -418,7 +417,8 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->region);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -458,10 +458,8 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
vod = op->customdata;
vod = op->customdata = viewops_data_create(
C, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_DEPTH_NAVIGATE));
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
@ -533,7 +531,8 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_region_tag_redraw(vod->region);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}

View File

@ -107,7 +107,8 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Note this does not remove auto-keys on locked cameras. */
copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_CANCELLED;
}
else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
@ -130,7 +131,8 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret & OPERATOR_FINISHED) {
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
return ret;
@ -201,11 +203,13 @@ static int viewroll_exec(bContext *C, wmOperator *op)
.dyn_ofs = dyn_ofs_pt,
});
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_CANCELLED;
}
@ -220,9 +224,7 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* makes op->customdata */
viewops_data_alloc(C, op);
viewops_data_create(C, op, event, viewops_flag_from_prefs());
vod = op->customdata;
vod = op->customdata = viewops_data_create(C, event, viewops_flag_from_prefs());
vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
BLI_rcti_cent_y(&vod->region->winrct)},
FLT_EPSILON);
@ -237,7 +239,8 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
viewroll_apply(vod, event->prev_xy[0], event->prev_xy[1]);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -250,7 +253,8 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void viewroll_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
void VIEW3D_OT_view_roll(wmOperatorType *ot)

View File

@ -370,7 +370,8 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret & OPERATOR_FINISHED) {
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
return ret;
@ -383,17 +384,14 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
/* makes op->customdata */
viewops_data_alloc(C, op);
vod = op->customdata;
vod = op->customdata = viewops_data_create(
C,
event,
viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
viewops_data_create(C,
op,
event,
viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
int event_xy[2];
@ -414,7 +412,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewrotate_apply(vod, event_xy);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -427,7 +426,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void viewrotate_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
void VIEW3D_OT_rotate(wmOperatorType *ot)

View File

@ -1487,9 +1487,9 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else
#endif /* WITH_INPUT_NDOF */
if (event->type == TIMER && event->customdata == walk->timer) {
walkApply(C, walk, false);
}
if (event->type == TIMER && event->customdata == walk->timer) {
walkApply(C, walk, false);
}
do_draw |= walk->redraw;

View File

@ -418,7 +418,8 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret & OPERATOR_FINISHED) {
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
return ret;
@ -499,7 +500,8 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_region_tag_redraw(region);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -511,14 +513,11 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
/* makes op->customdata */
viewops_data_alloc(C, op);
viewops_data_create(C,
op,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
vod = op->customdata = viewops_data_create(
C,
event,
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
@ -549,7 +548,8 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
@ -569,7 +569,8 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void viewzoom_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}
void VIEW3D_OT_zoom(wmOperatorType *ot)

View File

@ -87,8 +87,7 @@ class FieldNode {
public:
FieldNode(FieldNodeType node_type);
virtual ~FieldNode() = default;
virtual ~FieldNode();
virtual const CPPType &output_cpp_type(int output_index) const = 0;
@ -230,6 +229,7 @@ class FieldOperation : public FieldNode {
public:
FieldOperation(std::shared_ptr<const MultiFunction> function, Vector<GField> inputs = {});
FieldOperation(const MultiFunction &function, Vector<GField> inputs = {});
~FieldOperation();
Span<GField> inputs() const;
const MultiFunction &multi_function() const;
@ -259,6 +259,7 @@ class FieldInput : public FieldNode {
public:
FieldInput(const CPPType &type, std::string debug_name = "");
~FieldInput();
/**
* Get the value of this specific input based on the given context. The returned virtual array,

View File

@ -31,6 +31,7 @@ MAKE_CPP_TYPE(float3, blender::float3, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(float4x4, blender::float4x4, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(int32, int32_t, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(int8, int8_t, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(uint32, uint32_t, CPPTypeFlags::BasicType)
MAKE_CPP_TYPE(uint8, uint8_t, CPPTypeFlags::BasicType)
@ -44,6 +45,7 @@ MAKE_FIELD_CPP_TYPE(Float2Field, float2);
MAKE_FIELD_CPP_TYPE(Float3Field, float3);
MAKE_FIELD_CPP_TYPE(ColorGeometry4fField, blender::ColorGeometry4f);
MAKE_FIELD_CPP_TYPE(BoolField, bool);
MAKE_FIELD_CPP_TYPE(Int8Field, int8_t);
MAKE_FIELD_CPP_TYPE(Int32Field, int32_t);
MAKE_FIELD_CPP_TYPE(StringField, std::string);

View File

@ -570,6 +570,13 @@ bool IndexFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IndexFieldInput *>(&other) != nullptr;
}
/* --------------------------------------------------------------------
* FieldNode.
*/
/* Avoid generating the destructor in every translation unit. */
FieldNode::~FieldNode() = default;
/* --------------------------------------------------------------------
* FieldOperation.
*/
@ -581,6 +588,9 @@ FieldOperation::FieldOperation(std::shared_ptr<const MultiFunction> function,
owned_function_ = std::move(function);
}
/* Avoid generating the destructor in every translation unit. */
FieldOperation::~FieldOperation() = default;
/**
* Returns the field inputs used by all the provided fields.
* This tries to reuse an existing #FieldInputs whenever possible to avoid copying it.
@ -655,6 +665,9 @@ FieldInput::FieldInput(const CPPType &type, std::string debug_name)
field_inputs_ = std::move(field_inputs);
}
/* Avoid generating the destructor in every translation unit. */
FieldInput::~FieldInput() = default;
/* --------------------------------------------------------------------
* FieldConstant.
*/

View File

@ -375,7 +375,7 @@ set(GLSL_SRC
shaders/gpu_shader_common_obinfos_lib.glsl
intern/gpu_shader_shared_utils.h
GPU_shader_shared_utils.h
)
set(GLSL_C)

View File

@ -31,6 +31,8 @@
extern "C" {
#endif
#define GPU_DEBUG_SHADER_COMPILATION_GROUP "Shader Compilation"
void GPU_debug_group_begin(const char *name);
void GPU_debug_group_end(void);
/**

View File

@ -22,7 +22,7 @@
*/
#ifndef USE_GPU_SHADER_CREATE_INFO
# include "intern/gpu_shader_shared_utils.h"
# include "GPU_shader_shared_utils.h"
#endif
struct NodeLinkData {

View File

@ -37,11 +37,14 @@ ENUM_OPERATORS(eGPUWriteMask, GPU_WRITE_COLOR)
typedef enum eGPUBarrier {
GPU_BARRIER_NONE = 0,
GPU_BARRIER_SHADER_IMAGE_ACCESS = (1 << 0),
GPU_BARRIER_TEXTURE_FETCH = (1 << 1),
GPU_BARRIER_SHADER_STORAGE = (1 << 2),
GPU_BARRIER_VERTEX_ATTRIB_ARRAY = (1 << 3),
GPU_BARRIER_ELEMENT_ARRAY = (1 << 4),
GPU_BARRIER_COMMAND = (1 << 0),
GPU_BARRIER_FRAMEBUFFER = (1 << 1),
GPU_BARRIER_SHADER_IMAGE_ACCESS = (1 << 2),
GPU_BARRIER_SHADER_STORAGE = (1 << 3),
GPU_BARRIER_TEXTURE_FETCH = (1 << 4),
GPU_BARRIER_TEXTURE_UPDATE = (1 << 5),
GPU_BARRIER_VERTEX_ATTRIB_ARRAY = (1 << 6),
GPU_BARRIER_ELEMENT_ARRAY = (1 << 7),
} eGPUBarrier;
ENUM_OPERATORS(eGPUBarrier, GPU_BARRIER_ELEMENT_ARRAY)

View File

@ -43,8 +43,9 @@ typedef enum GPUAttachmentType : int {
GPU_FB_COLOR_ATTACHMENT3,
GPU_FB_COLOR_ATTACHMENT4,
GPU_FB_COLOR_ATTACHMENT5,
/* Number of maximum output slots.
* We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */
GPU_FB_COLOR_ATTACHMENT6,
GPU_FB_COLOR_ATTACHMENT7,
/* Number of maximum output slots. */
/* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
* the maximum number of COLOR attachments specified by glDrawBuffers. */
GPU_FB_MAX_ATTACHMENT,

View File

@ -26,6 +26,7 @@
#include "BLI_string_utils.h"
#include "GPU_capabilities.h"
#include "GPU_debug.h"
#include "GPU_matrix.h"
#include "GPU_platform.h"
@ -273,6 +274,8 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
const_cast<ShaderCreateInfo &>(info).finalize();
GPU_debug_group_begin(GPU_DEBUG_SHADER_COMPILATION_GROUP);
/* At least a vertex shader and a fragment shader are required, or only a compute shader. */
if (info.compute_source_.is_empty()) {
if (info.vertex_source_.is_empty()) {
@ -301,20 +304,22 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
std::string defines = shader->defines_declare(info);
std::string resources = shader->resources_declare(info);
char *shader_shared_utils = nullptr;
defines += "#define USE_GPU_SHADER_CREATE_INFO\n";
Vector<char *> typedefs;
for (auto filename : info.typedef_sources_) {
typedefs.append(gpu_shader_dependency_get_source(filename.c_str()));
Vector<const char *> typedefs;
if (!info.typedef_sources_.is_empty() || !info.typedef_source_generated.empty()) {
typedefs.append(gpu_shader_dependency_get_source("GPU_shader_shared_utils.h").c_str());
}
if (!typedefs.is_empty()) {
shader_shared_utils = gpu_shader_dependency_get_source("gpu_shader_shared_utils.h");
if (!info.typedef_source_generated.empty()) {
typedefs.append(info.typedef_source_generated.c_str());
}
for (auto filename : info.typedef_sources_) {
typedefs.append(gpu_shader_dependency_get_source(filename).c_str());
}
if (!info.vertex_source_.is_empty()) {
char *code = gpu_shader_dependency_get_resolved_source(info.vertex_source_.c_str());
auto code = gpu_shader_dependency_get_resolved_source(info.vertex_source_);
std::string interface = shader->vertex_interface_declare(info);
Vector<const char *> sources;
@ -324,23 +329,18 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
sources.append("#define USE_GEOMETRY_SHADER\n");
}
sources.append(defines.c_str());
if (!typedefs.is_empty()) {
sources.append(shader_shared_utils);
}
for (auto *types : typedefs) {
sources.append(types);
}
sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(interface.c_str());
sources.append(code);
sources.extend(code);
sources.extend(info.dependencies_generated);
sources.append(info.vertex_source_generated.c_str());
shader->vertex_shader_from_glsl(sources);
free(code);
}
if (!info.fragment_source_.is_empty()) {
char *code = gpu_shader_dependency_get_resolved_source(info.fragment_source_.c_str());
auto code = gpu_shader_dependency_get_resolved_source(info.fragment_source_);
std::string interface = shader->fragment_interface_declare(info);
Vector<const char *> sources;
@ -350,23 +350,18 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
sources.append("#define USE_GEOMETRY_SHADER\n");
}
sources.append(defines.c_str());
if (!typedefs.is_empty()) {
sources.append(shader_shared_utils);
}
for (auto *types : typedefs) {
sources.append(types);
}
sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(interface.c_str());
sources.append(code);
sources.extend(code);
sources.extend(info.dependencies_generated);
sources.append(info.fragment_source_generated.c_str());
shader->fragment_shader_from_glsl(sources);
free(code);
}
if (!info.geometry_source_.is_empty()) {
char *code = gpu_shader_dependency_get_resolved_source(info.geometry_source_.c_str());
auto code = gpu_shader_dependency_get_resolved_source(info.geometry_source_);
std::string layout = shader->geometry_layout_declare(info);
std::string interface = shader->geometry_interface_declare(info);
@ -374,58 +369,38 @@ GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
standard_defines(sources);
sources.append("#define GPU_GEOMETRY_SHADER\n");
sources.append(defines.c_str());
if (!typedefs.is_empty()) {
sources.append(shader_shared_utils);
}
for (auto *types : typedefs) {
sources.append(types);
}
sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(layout.c_str());
sources.append(interface.c_str());
sources.append(code);
sources.extend(code);
shader->geometry_shader_from_glsl(sources);
free(code);
}
if (!info.compute_source_.is_empty()) {
char *code = gpu_shader_dependency_get_resolved_source(info.compute_source_.c_str());
auto code = gpu_shader_dependency_get_resolved_source(info.compute_source_);
std::string layout = shader->compute_layout_declare(info);
Vector<const char *> sources;
standard_defines(sources);
sources.append("#define GPU_COMPUTE_SHADER\n");
sources.append(defines.c_str());
if (!typedefs.is_empty()) {
sources.append(shader_shared_utils);
}
for (auto *types : typedefs) {
sources.append(types);
}
sources.extend(typedefs);
sources.append(resources.c_str());
sources.append(layout.c_str());
sources.append(code);
sources.extend(code);
shader->compute_shader_from_glsl(sources);
free(code);
}
for (auto *types : typedefs) {
free(types);
}
if (shader_shared_utils) {
free(shader_shared_utils);
}
if (!shader->finalize(&info)) {
delete shader;
GPU_debug_group_end();
return nullptr;
}
GPU_debug_group_end();
return wrap(shader);
}

View File

@ -55,6 +55,8 @@ void ShaderCreateInfo::finalize()
}
finalized_ = true;
Set<StringRefNull> deps_merged;
for (auto &info_name : additional_infos_) {
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(
gpu_shader_create_info_get(info_name.c_str()));
@ -62,11 +64,6 @@ void ShaderCreateInfo::finalize()
/* Recursive. */
const_cast<ShaderCreateInfo &>(info).finalize();
#if 0 /* Enabled for debugging merging. TODO(fclem) exception handling and error reporting in \
console. */
std::cout << "Merging : " << info_name << " > " << name_ << std::endl;
#endif
interface_names_size_ += info.interface_names_size_;
vertex_inputs_.extend(info.vertex_inputs_);
@ -83,37 +80,76 @@ void ShaderCreateInfo::finalize()
validate(info);
auto assert_no_overlap = [&](const bool test, const StringRefNull error) {
if (!test) {
std::cout << name_ << ": Validation failed while merging " << info.name_ << " : ";
std::cout << error << std::endl;
BLI_assert(0);
}
};
if (!deps_merged.add(info.name_)) {
assert_no_overlap(false, "additional info already merged via another info");
}
if (info.compute_layout_.local_size_x != -1) {
compute_layout_.local_size_x = info.compute_layout_.local_size_x;
compute_layout_.local_size_y = info.compute_layout_.local_size_y;
compute_layout_.local_size_z = info.compute_layout_.local_size_z;
assert_no_overlap(compute_layout_.local_size_x == -1, "Compute layout already defined");
compute_layout_ = info.compute_layout_;
}
if (!info.vertex_source_.is_empty()) {
BLI_assert(vertex_source_.is_empty());
assert_no_overlap(vertex_source_.is_empty(), "Vertex source already existing");
vertex_source_ = info.vertex_source_;
}
if (!info.geometry_source_.is_empty()) {
BLI_assert(geometry_source_.is_empty());
assert_no_overlap(geometry_source_.is_empty(), "Geometry source already existing");
geometry_source_ = info.geometry_source_;
geometry_layout_ = info.geometry_layout_;
}
if (!info.fragment_source_.is_empty()) {
BLI_assert(fragment_source_.is_empty());
assert_no_overlap(fragment_source_.is_empty(), "Fragment source already existing");
fragment_source_ = info.fragment_source_;
}
if (!info.compute_source_.is_empty()) {
BLI_assert(compute_source_.is_empty());
assert_no_overlap(compute_source_.is_empty(), "Compute source already existing");
compute_source_ = info.compute_source_;
}
do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_;
}
if (auto_resource_location_) {
int images = 0, samplers = 0, ubos = 0, ssbos = 0;
auto set_resource_slot = [&](Resource &res) {
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
res.slot = ubos++;
break;
case Resource::BindType::STORAGE_BUFFER:
res.slot = ssbos++;
break;
case Resource::BindType::SAMPLER:
res.slot = samplers++;
break;
case Resource::BindType::IMAGE:
res.slot = images++;
break;
}
};
for (auto &res : batch_resources_) {
set_resource_slot(res);
}
for (auto &res : pass_resources_) {
set_resource_slot(res);
}
}
}
void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
{
{
if (!auto_resource_location_) {
/* Check same bind-points usage in OGL. */
Set<int> images, samplers, ubos, ssbos;
@ -133,26 +169,26 @@ void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
};
auto print_error_msg = [&](const Resource &res) {
std::cerr << name_ << ": Validation failed : Overlapping ";
std::cout << name_ << ": Validation failed : Overlapping ";
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
std::cerr << "Uniform Buffer " << res.uniformbuf.name;
std::cout << "Uniform Buffer " << res.uniformbuf.name;
break;
case Resource::BindType::STORAGE_BUFFER:
std::cerr << "Storage Buffer " << res.storagebuf.name;
std::cout << "Storage Buffer " << res.storagebuf.name;
break;
case Resource::BindType::SAMPLER:
std::cerr << "Sampler " << res.sampler.name;
std::cout << "Sampler " << res.sampler.name;
break;
case Resource::BindType::IMAGE:
std::cerr << "Image " << res.image.name;
std::cout << "Image " << res.image.name;
break;
default:
std::cerr << "Unknown Type";
std::cout << "Unknown Type";
break;
}
std::cerr << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
std::cout << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
};
for (auto &res : batch_resources_) {
@ -212,14 +248,10 @@ void gpu_shader_create_info_init()
for (ShaderCreateInfo *info : g_create_infos->values()) {
if (info->do_static_compilation_) {
info->builtins_ |= static_cast<BuiltinBits>(
gpu_shader_dependency_get_builtins(info->vertex_source_.c_str()));
info->builtins_ |= static_cast<BuiltinBits>(
gpu_shader_dependency_get_builtins(info->fragment_source_.c_str()));
info->builtins_ |= static_cast<BuiltinBits>(
gpu_shader_dependency_get_builtins(info->geometry_source_.c_str()));
info->builtins_ |= static_cast<BuiltinBits>(
gpu_shader_dependency_get_builtins(info->compute_source_.c_str()));
info->builtins_ |= gpu_shader_dependency_get_builtins(info->vertex_source_);
info->builtins_ |= gpu_shader_dependency_get_builtins(info->fragment_source_);
info->builtins_ |= gpu_shader_dependency_get_builtins(info->geometry_source_);
info->builtins_ |= gpu_shader_dependency_get_builtins(info->compute_source_);
}
}

View File

@ -30,8 +30,11 @@
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "GPU_material.h"
#include "GPU_texture.h"
#include <iostream>
namespace blender::gpu::shader {
#ifndef GPU_SHADER_CREATE_INFO
@ -62,6 +65,59 @@ enum class Type {
BOOL,
};
/* All of these functions is a bit out of place */
static inline Type to_type(const eGPUType type)
{
switch (type) {
case GPU_FLOAT:
return Type::FLOAT;
case GPU_VEC2:
return Type::VEC2;
case GPU_VEC3:
return Type::VEC3;
case GPU_VEC4:
return Type::VEC4;
case GPU_MAT3:
return Type::MAT3;
case GPU_MAT4:
return Type::MAT4;
default:
BLI_assert_msg(0, "Error: Cannot convert eGPUType to shader::Type.");
return Type::FLOAT;
}
}
static inline std::ostream &operator<<(std::ostream &stream, const Type type)
{
switch (type) {
case Type::FLOAT:
return stream << "float";
case Type::VEC2:
return stream << "vec2";
case Type::VEC3:
return stream << "vec3";
case Type::VEC4:
return stream << "vec4";
case Type::MAT3:
return stream << "mat3";
case Type::MAT4:
return stream << "mat4";
default:
BLI_assert(0);
return stream;
}
}
static inline std::ostream &operator<<(std::ostream &stream, const eGPUType type)
{
switch (type) {
case GPU_CLOSURE:
return stream << "Closure";
default:
return stream << to_type(type);
}
}
enum class BuiltinBits {
NONE = 0,
/**
@ -74,7 +130,7 @@ enum class BuiltinBits {
GLOBAL_INVOCATION_ID = (1 << 5),
INSTANCE_ID = (1 << 6),
/**
* Allow setting the target layer when the output is a layered framebuffer.
* Allow setting the target layer when the output is a layered frame-buffer.
* \note Emulated through geometry shader on older hardware.
*/
LAYER = (1 << 7),
@ -229,6 +285,8 @@ struct ShaderCreateInfo {
bool do_static_compilation_ = false;
/** If true, all additionally linked create info will be merged into this one. */
bool finalized_ = false;
/** If true, all resources will have an automatic location assigned. */
bool auto_resource_location_ = false;
/**
* Maximum length of all the resource names including each null terminator.
* Only for names used by gpu::ShaderInterface.
@ -236,11 +294,36 @@ struct ShaderCreateInfo {
size_t interface_names_size_ = 0;
/** Manually set builtins. */
BuiltinBits builtins_ = BuiltinBits::NONE;
/** Manually set generated code. */
std::string vertex_source_generated = "";
std::string fragment_source_generated = "";
std::string typedef_source_generated = "";
/** Manually set generated dependencies. */
Vector<const char *, 0> dependencies_generated;
#define TEST_EQUAL(a, b, _member) \
if (!((a)._member == (b)._member)) { \
return false; \
}
#define TEST_VECTOR_EQUAL(a, b, _vector) \
TEST_EQUAL(a, b, _vector.size()); \
for (auto i : _vector.index_range()) { \
TEST_EQUAL(a, b, _vector[i]); \
}
struct VertIn {
int index;
Type type;
StringRefNull name;
bool operator==(const VertIn &b)
{
TEST_EQUAL(*this, b, index);
TEST_EQUAL(*this, b, type);
TEST_EQUAL(*this, b, name);
return true;
}
};
Vector<VertIn> vertex_inputs_;
@ -250,6 +333,15 @@ struct ShaderCreateInfo {
PrimitiveOut primitive_out;
/** Set to -1 by default to check if used. */
int max_vertices = -1;
bool operator==(const GeometryStageLayout &b)
{
TEST_EQUAL(*this, b, primitive_in);
TEST_EQUAL(*this, b, invocations);
TEST_EQUAL(*this, b, primitive_out);
TEST_EQUAL(*this, b, max_vertices);
return true;
}
};
GeometryStageLayout geometry_layout_;
@ -257,8 +349,15 @@ struct ShaderCreateInfo {
int local_size_x = -1;
int local_size_y = -1;
int local_size_z = -1;
};
bool operator==(const ComputeStageLayout &b)
{
TEST_EQUAL(*this, b, local_size_x);
TEST_EQUAL(*this, b, local_size_y);
TEST_EQUAL(*this, b, local_size_z);
return true;
}
};
ComputeStageLayout compute_layout_;
struct FragOut {
@ -266,6 +365,15 @@ struct ShaderCreateInfo {
Type type;
DualBlend blend;
StringRefNull name;
bool operator==(const FragOut &b)
{
TEST_EQUAL(*this, b, index);
TEST_EQUAL(*this, b, type);
TEST_EQUAL(*this, b, blend);
TEST_EQUAL(*this, b, name);
return true;
}
};
Vector<FragOut> fragment_outputs_;
@ -311,6 +419,35 @@ struct ShaderCreateInfo {
};
Resource(BindType type, int _slot) : bind_type(type), slot(_slot){};
bool operator==(const Resource &b)
{
TEST_EQUAL(*this, b, bind_type);
TEST_EQUAL(*this, b, slot);
switch (bind_type) {
case UNIFORM_BUFFER:
TEST_EQUAL(*this, b, uniformbuf.type_name);
TEST_EQUAL(*this, b, uniformbuf.name);
break;
case STORAGE_BUFFER:
TEST_EQUAL(*this, b, storagebuf.qualifiers);
TEST_EQUAL(*this, b, storagebuf.type_name);
TEST_EQUAL(*this, b, storagebuf.name);
break;
case SAMPLER:
TEST_EQUAL(*this, b, sampler.type);
TEST_EQUAL(*this, b, sampler.sampler);
TEST_EQUAL(*this, b, sampler.name);
break;
case IMAGE:
TEST_EQUAL(*this, b, image.format);
TEST_EQUAL(*this, b, image.type);
TEST_EQUAL(*this, b, image.qualifiers);
TEST_EQUAL(*this, b, image.name);
break;
}
return true;
}
};
/**
* Resources are grouped by frequency of change.
@ -327,6 +464,14 @@ struct ShaderCreateInfo {
Type type;
StringRefNull name;
int array_size;
bool operator==(const PushConst &b)
{
TEST_EQUAL(*this, b, type);
TEST_EQUAL(*this, b, name);
TEST_EQUAL(*this, b, array_size);
return true;
}
};
Vector<PushConst> push_constants_;
@ -554,6 +699,12 @@ struct ShaderCreateInfo {
return *(Self *)this;
}
Self &auto_resource_location(bool value)
{
auto_resource_location_ = value;
return *(Self *)this;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -624,6 +775,77 @@ struct ShaderCreateInfo {
void validate(const ShaderCreateInfo &other_info);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators.
*
* \{ */
/* Comparison operator for GPUPass cache. We only compare if it will create the same shader code.
* So we do not compare name and some other internal stuff. */
bool operator==(const ShaderCreateInfo &b)
{
TEST_EQUAL(*this, b, builtins_);
TEST_EQUAL(*this, b, vertex_source_generated);
TEST_EQUAL(*this, b, fragment_source_generated);
TEST_EQUAL(*this, b, typedef_source_generated);
TEST_VECTOR_EQUAL(*this, b, vertex_inputs_);
TEST_EQUAL(*this, b, geometry_layout_);
TEST_EQUAL(*this, b, compute_layout_);
TEST_VECTOR_EQUAL(*this, b, fragment_outputs_);
TEST_VECTOR_EQUAL(*this, b, pass_resources_);
TEST_VECTOR_EQUAL(*this, b, batch_resources_);
TEST_VECTOR_EQUAL(*this, b, vertex_out_interfaces_);
TEST_VECTOR_EQUAL(*this, b, geometry_out_interfaces_);
TEST_VECTOR_EQUAL(*this, b, push_constants_);
TEST_VECTOR_EQUAL(*this, b, typedef_sources_);
TEST_EQUAL(*this, b, vertex_source_);
TEST_EQUAL(*this, b, geometry_source_);
TEST_EQUAL(*this, b, fragment_source_);
TEST_EQUAL(*this, b, compute_source_);
TEST_VECTOR_EQUAL(*this, b, additional_infos_);
TEST_VECTOR_EQUAL(*this, b, defines_);
return true;
}
/** Debug print */
friend std::ostream &operator<<(std::ostream &stream, const ShaderCreateInfo &info)
{
/* TODO(@fclem): Complete print. */
auto print_resource = [&](const Resource &res) {
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
stream << "UNIFORM_BUFFER(" << res.slot << ", " << res.uniformbuf.name << ")"
<< std::endl;
break;
case Resource::BindType::STORAGE_BUFFER:
stream << "STORAGE_BUFFER(" << res.slot << ", " << res.storagebuf.name << ")"
<< std::endl;
break;
case Resource::BindType::SAMPLER:
stream << "SAMPLER(" << res.slot << ", " << res.sampler.name << ")" << std::endl;
break;
case Resource::BindType::IMAGE:
stream << "IMAGE(" << res.slot << ", " << res.image.name << ")" << std::endl;
break;
}
};
/* TODO(@fclem): Order the resources. */
for (auto &res : info.batch_resources_) {
print_resource(res);
}
for (auto &res : info.pass_resources_) {
print_resource(res);
}
return stream;
}
/** \} */
#undef TEST_EQUAL
#undef TEST_VECTOR_EQUAL
};
} // namespace blender::gpu::shader

View File

@ -332,14 +332,12 @@ struct GPUSource {
}
/* Returns the final string with all includes done. */
std::string build() const
void build(Vector<const char *> &result) const
{
std::string str;
for (auto *dep : dependencies) {
str += dep->source;
result.append(dep->source.c_str());
}
str += source;
return str;
result.append(source.c_str());
}
shader::BuiltinBits builtins_get() const
@ -383,23 +381,47 @@ void gpu_shader_dependency_exit()
delete g_sources;
}
uint32_t gpu_shader_dependency_get_builtins(const char *shader_source_name)
namespace blender::gpu::shader {
BuiltinBits gpu_shader_dependency_get_builtins(const StringRefNull shader_source_name)
{
if (shader_source_name[0] == '\0') {
return 0;
if (shader_source_name.is_empty()) {
return shader::BuiltinBits::NONE;
}
if (g_sources->contains(shader_source_name) == false) {
std::cout << "Error: Could not find \"" << shader_source_name
<< "\" in the list of registered source.\n";
BLI_assert(0);
return shader::BuiltinBits::NONE;
}
GPUSource *source = g_sources->lookup(shader_source_name);
return static_cast<uint32_t>(source->builtins_get());
return source->builtins_get();
}
char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name)
Vector<const char *> gpu_shader_dependency_get_resolved_source(
const StringRefNull shader_source_name)
{
Vector<const char *> result;
GPUSource *source = g_sources->lookup(shader_source_name);
return strdup(source->build().c_str());
source->build(result);
return result;
}
char *gpu_shader_dependency_get_source(const char *shader_source_name)
StringRefNull gpu_shader_dependency_get_source(const StringRefNull shader_source_name)
{
GPUSource *src = g_sources->lookup(shader_source_name);
return strdup(src->source.c_str());
return src->source;
}
StringRefNull gpu_shader_dependency_get_filename_from_source_string(
const StringRefNull source_string)
{
for (auto &source : g_sources->values()) {
if (source->source.c_str() == source_string.c_str()) {
return source->filename;
}
}
return "";
}
} // namespace blender::gpu::shader

View File

@ -34,12 +34,32 @@ void gpu_shader_dependency_init(void);
void gpu_shader_dependency_exit(void);
/* User must free the resulting string using free. */
char *gpu_shader_dependency_get_resolved_source(const char *shader_source_name);
char *gpu_shader_dependency_get_source(const char *shader_source_name);
uint32_t gpu_shader_dependency_get_builtins(const char *shader_source_name);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
# include "BLI_string_ref.hh"
# include "BLI_vector.hh"
# include "gpu_shader_create_info.hh"
namespace blender::gpu::shader {
BuiltinBits gpu_shader_dependency_get_builtins(const StringRefNull source_name);
Vector<const char *> gpu_shader_dependency_get_resolved_source(const StringRefNull source_name);
StringRefNull gpu_shader_dependency_get_source(const StringRefNull source_name);
/**
* \brief Find the name of the file from which the given string was generated.
* \return Return filename or empty string.
* \note source_string needs to be identical to the one given by gpu_shader_dependency_get_source()
*/
StringRefNull gpu_shader_dependency_get_filename_from_source_string(
const StringRefNull source_string);
} // namespace blender::gpu::shader
#endif

View File

@ -68,6 +68,7 @@ class ShaderInterface {
uint16_t enabled_ubo_mask_ = 0;
uint8_t enabled_ima_mask_ = 0;
uint64_t enabled_tex_mask_ = 0;
uint16_t enabled_ssbo_mask_ = 0;
/** Location of builtin uniforms. Fast access, no lookup needed. */
int32_t builtins_[GPU_NUM_UNIFORMS];
int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS];

View File

@ -26,7 +26,9 @@
#include "BLI_dynstr.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_vector.hh"
#include "gpu_shader_dependency_private.h"
#include "gpu_shader_private.hh"
#include "GPU_platform.h"
@ -41,6 +43,14 @@ namespace blender::gpu {
/** \name Debug functions
* \{ */
/* Number of lines before and after the error line to print for compilation errors. */
#define DEBUG_CONTEXT_LINES 0
/**
* Print dependencies sources list before the shader report.
* Useful to debug include order or missing dependencies.
*/
#define DEBUG_DEPENDENCIES 0
void Shader::print_log(Span<const char *> sources,
char *log,
const char *stage,
@ -61,6 +71,30 @@ void Shader::print_log(Span<const char *> sources,
BLI_dynstr_appendf(dynstr, "\n");
#if DEBUG_DEPENDENCIES
BLI_dynstr_appendf(
dynstr, "%s%sIncluded files (in order):%s\n", info_col, line_prefix, reset_col);
#endif
Vector<int64_t> sources_end_line;
for (StringRefNull src : sources) {
int64_t cursor = 0, line_count = 0;
while ((cursor = src.find('\n', cursor) + 1)) {
line_count++;
}
if (sources_end_line.is_empty() == false) {
line_count += sources_end_line.last();
}
sources_end_line.append(line_count);
#if DEBUG_DEPENDENCIES
StringRefNull filename = shader::gpu_shader_dependency_get_filename_from_source_string(src);
if (!filename.is_empty()) {
BLI_dynstr_appendf(
dynstr, "%s%s %s%s\n", info_col, line_prefix, filename.c_str(), reset_col);
}
#endif
}
char *log_line = log, *line_end;
LogCursor previous_location;
@ -73,12 +107,32 @@ void Shader::print_log(Span<const char *> sources,
continue;
}
/* Silence not useful lines. */
StringRef logref = StringRefNull(log_line).substr(0, (size_t)line_end - (size_t)log_line);
if (logref.endswith(" shader failed to compile with the following errors:") ||
logref.endswith(" No code generated")) {
log_line += (size_t)line_end - (size_t)log_line;
continue;
}
GPULogItem log_item;
log_line = parser->parse_line(log_line, log_item);
/* Sanitize output. Really bad values can happen when the error line is buggy. */
if (log_item.cursor.source >= sources.size()) {
log_item.cursor.source = -1;
}
if (log_item.cursor.row >= sources_end_line.last()) {
log_item.cursor.source = -1;
log_item.cursor.row = -1;
}
if (log_item.cursor.row == -1) {
found_line_id = false;
}
else if (log_item.source_base_row && log_item.cursor.source > 0) {
log_item.cursor.row += sources_end_line[log_item.cursor.source - 1];
}
const char *src_line = sources_combined;
@ -98,15 +152,14 @@ void Shader::print_log(Span<const char *> sources,
/* error_line is 1 based in this case. */
int src_line_index = 1;
while ((src_line_end = strchr(src_line, '\n'))) {
if (src_line_index == log_item.cursor.row) {
if (src_line_index >= log_item.cursor.row) {
found_line_id = true;
break;
}
/* TODO(@fclem): Make this an option to display N lines before error. */
#if 0 /* Uncomment to print shader file up to the error line to have more context. */
BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
#endif
if (src_line_index >= log_item.cursor.row - DEBUG_CONTEXT_LINES) {
BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
}
/* Continue to next line. */
src_line = src_line_end + 1;
src_line_index++;
@ -129,10 +182,53 @@ void Shader::print_log(Span<const char *> sources,
BLI_dynstr_appendf(dynstr, "^");
}
BLI_dynstr_appendf(dynstr, "\n");
/* Skip the error line. */
src_line = src_line_end + 1;
src_line_index++;
while ((src_line_end = strchr(src_line, '\n'))) {
if (src_line_index > log_item.cursor.row + DEBUG_CONTEXT_LINES) {
break;
}
BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index);
BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line);
/* Continue to next line. */
src_line = src_line_end + 1;
src_line_index++;
}
}
}
BLI_dynstr_appendf(dynstr, line_prefix);
/* Search the correct source index. */
int row_in_file = log_item.cursor.row;
int source_index = log_item.cursor.source;
if (source_index <= 0) {
for (auto i : sources_end_line.index_range()) {
if (log_item.cursor.row <= sources_end_line[i]) {
source_index = i;
break;
}
}
}
if (source_index > 0) {
row_in_file -= sources_end_line[source_index - 1];
}
/* Print the filename the error line is coming from. */
if (source_index > 0) {
StringRefNull filename = shader::gpu_shader_dependency_get_filename_from_source_string(
sources[source_index]);
if (!filename.is_empty()) {
BLI_dynstr_appendf(dynstr,
"%s%s:%d:%d: %s",
info_col,
filename.c_str(),
row_in_file,
log_item.cursor.column + 1,
reset_col);
}
}
if (log_item.severity == Severity::Error) {
BLI_dynstr_appendf(dynstr, "%s%s%s: ", err_col, "Error", info_col);
}

View File

@ -120,6 +120,7 @@ struct LogCursor {
struct GPULogItem {
LogCursor cursor;
bool source_base_row = false;
Severity severity = Severity::Unknown;
};

View File

@ -451,7 +451,6 @@ inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat da
}
}
/* Definitely not complete, edit according to the gl specification. */
inline eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
{
switch (tex_format) {
@ -462,16 +461,27 @@ inline eGPUDataFormat to_data_format(eGPUTextureFormat tex_format)
case GPU_DEPTH24_STENCIL8:
case GPU_DEPTH32F_STENCIL8:
return GPU_DATA_UINT_24_8;
case GPU_R8UI:
case GPU_R16UI:
case GPU_RG16UI:
case GPU_R32UI:
case GPU_RG16UI:
case GPU_RG32UI:
case GPU_RGBA16UI:
case GPU_RGBA32UI:
return GPU_DATA_UINT;
case GPU_RG16I:
case GPU_R16I:
case GPU_R32I:
case GPU_R8I:
case GPU_RG16I:
case GPU_RG32I:
case GPU_RG8I:
case GPU_RGBA16I:
case GPU_RGBA32I:
case GPU_RGBA8I:
return GPU_DATA_INT;
case GPU_R8:
case GPU_R8UI:
case GPU_RG8:
case GPU_RG8UI:
case GPU_RGBA8:
case GPU_RGBA8UI:
case GPU_SRGB8_A8:

View File

@ -28,8 +28,8 @@ namespace blender::gpu {
void GLCompute::dispatch(int group_x_len, int group_y_len, int group_z_len)
{
GL_CHECK_RESOURCES("Compute");
glDispatchCompute(group_x_len, group_y_len, group_z_len);
debug::check_gl_error("Dispatch Compute");
}
} // namespace blender::gpu

View File

@ -108,6 +108,11 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
GPU_debug_get_groups_names(sizeof(debug_groups), debug_groups);
CLG_Severity clog_severity;
if (GPU_debug_group_match(GPU_DEBUG_SHADER_COMPILATION_GROUP)) {
/** Do not duplicate shader compilation error/warnings. */
return;
}
switch (type) {
case GL_DEBUG_TYPE_ERROR:
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
@ -191,6 +196,9 @@ void init_gl_callbacks()
void check_gl_error(const char *info)
{
if (!(G.debug & G_DEBUG_GPU)) {
return;
}
GLenum error = glGetError();
#define ERROR_CASE(err) \
@ -339,7 +347,7 @@ void object_label(GLenum type, GLuint object, const char *name)
char label[64];
SNPRINTF(label, "%s%s%s", to_str_prefix(type), name, to_str_suffix(type));
/* Small convenience for caller. */
if (ELEM(type, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_VERTEX_SHADER)) {
if (ELEM(type, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_VERTEX_SHADER, GL_COMPUTE_SHADER)) {
type = GL_SHADER;
}
if (ELEM(type, GL_UNIFORM_BUFFER)) {

View File

@ -82,6 +82,8 @@ DEBUG_FUNC_DECLARE(PFNGLDRAWBUFFERSPROC, void, glDrawBuffers, GLsizei, n, const
DEBUG_FUNC_DECLARE(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC, void, glDrawElementsInstancedBaseVertexBaseInstance, GLenum, mode, GLsizei, count, GLenum, type, const void *, indices, GLsizei, primcount, GLint, basevertex, GLuint, baseinstance);
DEBUG_FUNC_DECLARE(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC, void, glDrawElementsInstancedBaseVertex, GLenum, mode, GLsizei, count, GLenum, type, const void *, indices, GLsizei, instancecount, GLint, basevertex);
DEBUG_FUNC_DECLARE(PFNGLENDQUERYPROC, void, glEndQuery, GLenum, target);
DEBUG_FUNC_DECLARE(PFNGLDISPATCHCOMPUTEPROC, void, glDispatchCompute, GLuint, num_groups_x, GLuint, num_groups_y, GLuint, num_groups_z);
DEBUG_FUNC_DECLARE(PFNGLDISPATCHCOMPUTEINDIRECTPROC, void, glDispatchComputeIndirect, GLintptr, indirect);
DEBUG_FUNC_DECLARE(PFNGLENDTRANSFORMFEEDBACKPROC, void, glEndTransformFeedback, void);
DEBUG_FUNC_DECLARE(PFNGLFRAMEBUFFERTEXTURE2DPROC, void, glFramebufferTexture2D, GLenum, target, GLenum, attachment, GLenum, textarget, GLuint, texture, GLint, level);
DEBUG_FUNC_DECLARE(PFNGLFRAMEBUFFERTEXTURELAYERPROC, void, glFramebufferTextureLayer, GLenum, target, GLenum, attachment, GLuint, texture, GLint, level, GLint, layer);
@ -130,6 +132,8 @@ void init_debug_layer()
DEBUG_WRAP(glDeleteSamplers);
DEBUG_WRAP(glDeleteShader);
DEBUG_WRAP(glDeleteVertexArrays);
DEBUG_WRAP(glDispatchCompute);
DEBUG_WRAP(glDispatchComputeIndirect);
DEBUG_WRAP(glDrawArraysInstanced);
DEBUG_WRAP(glDrawArraysInstancedBaseInstance);
DEBUG_WRAP(glDrawBuffers);

View File

@ -141,6 +141,8 @@ static inline GLenum to_gl(const GPUAttachmentType type)
ATTACHMENT(COLOR_ATTACHMENT3);
ATTACHMENT(COLOR_ATTACHMENT4);
ATTACHMENT(COLOR_ATTACHMENT5);
ATTACHMENT(COLOR_ATTACHMENT6);
ATTACHMENT(COLOR_ATTACHMENT7);
default:
BLI_assert(0);
return GL_COLOR_ATTACHMENT0;

View File

@ -85,7 +85,7 @@ static const char *to_string(const Interpolation &interp)
case Interpolation::NO_PERSPECTIVE:
return "noperspective";
default:
return "unkown";
return "unknown";
}
}
@ -122,6 +122,74 @@ static const char *to_string(const Type &type)
return "ivec4";
case Type::BOOL:
return "bool";
default:
return "unknown";
}
}
static const char *to_string(const eGPUTextureFormat &type)
{
switch (type) {
case GPU_RGBA8UI:
return "rgba8ui";
case GPU_RGBA8I:
return "rgba8i";
case GPU_RGBA8:
return "rgba8";
case GPU_RGBA32UI:
return "rgba32ui";
case GPU_RGBA32I:
return "rgba32i";
case GPU_RGBA32F:
return "rgba32f";
case GPU_RGBA16UI:
return "rgba16ui";
case GPU_RGBA16I:
return "rgba16i";
case GPU_RGBA16F:
return "rgba16f";
case GPU_RGBA16:
return "rgba16";
case GPU_RG8UI:
return "rg8ui";
case GPU_RG8I:
return "rg8i";
case GPU_RG8:
return "rg8";
case GPU_RG32UI:
return "rg32ui";
case GPU_RG32I:
return "rg32i";
case GPU_RG32F:
return "rg32f";
case GPU_RG16UI:
return "rg16ui";
case GPU_RG16I:
return "rg16i";
case GPU_RG16F:
return "rg16f";
case GPU_RG16:
return "rg16";
case GPU_R8UI:
return "r8ui";
case GPU_R8I:
return "r8i";
case GPU_R8:
return "r8";
case GPU_R32UI:
return "r32ui";
case GPU_R32I:
return "r32i";
case GPU_R32F:
return "r32f";
case GPU_R16UI:
return "r16ui";
case GPU_R16I:
return "r16i";
case GPU_R16F:
return "r16f";
case GPU_R16:
return "r16";
default:
return "unkown";
}
@ -294,7 +362,7 @@ static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &r
if (GLContext::explicit_location_support) {
os << "layout(binding = " << res.slot;
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
os << ", " << res.image.format;
os << ", " << to_string(res.image.format);
}
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
os << ", std140";
@ -451,7 +519,9 @@ std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) con
ss << "\n/* Inputs. */\n";
for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
if (GLContext::explicit_location_support) {
if (GLContext::explicit_location_support &&
/* Fix issue with AMDGPU-PRO + workbench_prepass_mesh_vert.glsl being quantized. */
GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) == false) {
ss << "layout(location = " << attr.index << ") ";
}
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
@ -736,7 +806,7 @@ static char *glsl_patch_default_get()
STR_CONCAT(patch, slen, "#extension GL_ARB_texture_cube_map_array : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
}
if (GLEW_ARB_conservative_depth) {
if (!GLEW_VERSION_4_2 && GLEW_ARB_conservative_depth) {
STR_CONCAT(patch, slen, "#extension GL_ARB_conservative_depth : enable\n");
}
if (GPU_shader_image_load_store_support()) {
@ -759,6 +829,9 @@ static char *glsl_patch_default_get()
/* Vulkan GLSL compat. */
STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)\n");
/* Array compat. */
STR_CONCAT(patch, slen, "#define array(_type) _type[]\n");
/* Derivative sign can change depending on implementation. */
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]);
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]);

View File

@ -117,7 +117,28 @@ static inline int image_binding(int32_t program,
switch (type) {
case GL_IMAGE_1D:
case GL_IMAGE_2D:
case GL_IMAGE_3D: {
case GL_IMAGE_3D:
case GL_IMAGE_CUBE:
case GL_IMAGE_BUFFER:
case GL_IMAGE_1D_ARRAY:
case GL_IMAGE_2D_ARRAY:
case GL_IMAGE_CUBE_MAP_ARRAY:
case GL_INT_IMAGE_1D:
case GL_INT_IMAGE_2D:
case GL_INT_IMAGE_3D:
case GL_INT_IMAGE_CUBE:
case GL_INT_IMAGE_BUFFER:
case GL_INT_IMAGE_1D_ARRAY:
case GL_INT_IMAGE_2D_ARRAY:
case GL_INT_IMAGE_CUBE_MAP_ARRAY:
case GL_UNSIGNED_INT_IMAGE_1D:
case GL_UNSIGNED_INT_IMAGE_2D:
case GL_UNSIGNED_INT_IMAGE_3D:
case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_BUFFER:
case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: {
/* For now just assign a consecutive index. In the future, we should set it in
* the shader using layout(binding = i) and query its value. */
int binding = *image_len;
@ -298,6 +319,7 @@ GLShaderInterface::GLShaderInterface(GLuint program)
input->binding = input->location = binding;
name_buffer_offset += this->set_input_name(input, name, name_len);
enabled_ssbo_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
}
/* Builtin Uniforms */
@ -455,7 +477,7 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset);
input->location = input->binding = res.slot;
enabled_ubo_mask_ |= (1 << input->binding);
enabled_ssbo_mask_ |= (1 << input->binding);
input++;
}
}

View File

@ -60,6 +60,15 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item)
log_item.cursor.row = log_item.cursor.column;
log_item.cursor.column = -1;
}
else if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL) &&
/* WORKAROUND(@fclem): Both Mesa and AMDGPU-PRO are reported as official. */
StringRefNull(GPU_platform_version()).find(" Mesa ") == -1) {
/* source:row */
log_item.cursor.source = log_item.cursor.row;
log_item.cursor.row = log_item.cursor.column;
log_item.cursor.column = -1;
log_item.source_base_row = true;
}
else {
/* line:char */
}

View File

@ -124,11 +124,20 @@ static inline GLbitfield to_gl(eGPUBarrier barrier_bits)
if (barrier_bits & GPU_BARRIER_SHADER_IMAGE_ACCESS) {
barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) {
barrier |= GL_SHADER_STORAGE_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_TEXTURE_FETCH) {
barrier |= GL_TEXTURE_FETCH_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) {
barrier |= GL_SHADER_STORAGE_BARRIER_BIT;
if (barrier_bits & GPU_BARRIER_TEXTURE_UPDATE) {
barrier |= GL_TEXTURE_UPDATE_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_COMMAND) {
barrier |= GL_COMMAND_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_FRAMEBUFFER) {
barrier |= GL_FRAMEBUFFER_BARRIER_BIT;
}
if (barrier_bits & GPU_BARRIER_VERTEX_ATTRIB_ARRAY) {
barrier |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;

View File

@ -24,6 +24,7 @@
#include "BKE_blender_version.h"
#include "BLI_path_util.h"
#include "BLI_task.hh"
#include "obj_export_mesh.hh"
#include "obj_export_mtl.hh"
@ -167,108 +168,85 @@ void OBJWriter::write_object_name(FormatHandler<eFileType::OBJ> &fh,
fh.write<eOBJSyntaxElement::object_name>(object_name);
}
/* Split up large meshes into multi-threaded jobs; each job processes
* this amount of items. */
static const int chunk_size = 32768;
static int calc_chunk_count(int count)
{
return (count + chunk_size - 1) / chunk_size;
}
/* Write /tot_count/ items to OBJ file output. Each item is written
* by a /function/ that should be independent from other items.
* If the amount of items is large enough (> chunk_size), then writing
* will be done in parallel, into temporary FormatHandler buffers that
* will be written into the final /fh/ buffer at the end.
*/
template<typename Function>
void obj_parallel_chunked_output(FormatHandler<eFileType::OBJ> &fh,
int tot_count,
const Function &function)
{
if (tot_count <= 0) {
return;
}
/* If we have just one chunk, process it directly into the output
* buffer - avoids all the job scheduling and temporary vector allocation
* overhead. */
const int chunk_count = calc_chunk_count(tot_count);
if (chunk_count == 1) {
for (int i = 0; i < tot_count; i++) {
function(fh, i);
}
return;
}
/* Give each chunk its own temporary output buffer, and process them in parallel. */
std::vector<FormatHandler<eFileType::OBJ>> buffers(chunk_count);
blender::threading::parallel_for(IndexRange(chunk_count), 1, [&](IndexRange range) {
for (const int r : range) {
int i_start = r * chunk_size;
int i_end = std::min(i_start + chunk_size, tot_count);
auto &buf = buffers[r];
for (int i = i_start; i < i_end; i++) {
function(buf, i);
}
}
});
/* Emit all temporary output buffers into the destination buffer. */
for (auto &buf : buffers) {
fh.append_from(buf);
}
}
void OBJWriter::write_vertex_coords(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data) const
{
const int tot_vertices = obj_mesh_data.tot_vertices();
for (int i = 0; i < tot_vertices; i++) {
const int tot_count = obj_mesh_data.tot_vertices();
obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) {
float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor);
fh.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]);
}
buf.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]);
});
}
void OBJWriter::write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &r_obj_mesh_data) const
{
for (const float2 &uv_vertex : r_obj_mesh_data.get_uv_coords()) {
fh.write<eOBJSyntaxElement::uv_vertex_coords>(uv_vertex[0], uv_vertex[1]);
}
const Vector<float2> &uv_coords = r_obj_mesh_data.get_uv_coords();
const int tot_count = uv_coords.size();
obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) {
const float2 &uv_vertex = uv_coords[i];
buf.write<eOBJSyntaxElement::uv_vertex_coords>(uv_vertex[0], uv_vertex[1]);
});
}
void OBJWriter::write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data)
{
/* Poly normals should be calculated earlier via store_normal_coords_and_indices. */
for (const float3 &normal : obj_mesh_data.get_normal_coords()) {
fh.write<eOBJSyntaxElement::normal>(normal[0], normal[1], normal[2]);
}
}
int OBJWriter::write_smooth_group(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
const int poly_index,
const int last_poly_smooth_group) const
{
int current_group = SMOOTH_GROUP_DISABLED;
if (!export_params_.export_smooth_groups && obj_mesh_data.is_ith_poly_smooth(poly_index)) {
/* Smooth group calculation is disabled, but polygon is smooth-shaded. */
current_group = SMOOTH_GROUP_DEFAULT;
}
else if (obj_mesh_data.is_ith_poly_smooth(poly_index)) {
/* Smooth group calc is enabled and polygon is smoothshaded, so find the group. */
current_group = obj_mesh_data.ith_smooth_group(poly_index);
}
if (current_group == last_poly_smooth_group) {
/* Group has already been written, even if it is "s 0". */
return current_group;
}
fh.write<eOBJSyntaxElement::smooth_group>(current_group);
return current_group;
}
int16_t OBJWriter::write_poly_material(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
const int poly_index,
const int16_t last_poly_mat_nr,
std::function<const char *(int)> matname_fn) const
{
if (!export_params_.export_materials || obj_mesh_data.tot_materials() <= 0) {
return last_poly_mat_nr;
}
const int16_t current_mat_nr = obj_mesh_data.ith_poly_matnr(poly_index);
/* Whenever a polygon with a new material is encountered, write its material
* and/or group, otherwise pass. */
if (last_poly_mat_nr == current_mat_nr) {
return current_mat_nr;
}
if (current_mat_nr == NOT_FOUND) {
fh.write<eOBJSyntaxElement::poly_usemtl>(MATERIAL_GROUP_DISABLED);
return current_mat_nr;
}
if (export_params_.export_object_groups) {
write_object_group(fh, obj_mesh_data);
}
const char *mat_name = matname_fn(current_mat_nr);
if (!mat_name) {
mat_name = MATERIAL_GROUP_DISABLED;
}
fh.write<eOBJSyntaxElement::poly_usemtl>(mat_name);
return current_mat_nr;
}
int16_t OBJWriter::write_vertex_group(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
const int poly_index,
const int16_t last_poly_vertex_group) const
{
if (!export_params_.export_vertex_groups) {
return last_poly_vertex_group;
}
const int16_t current_group = obj_mesh_data.get_poly_deform_group_index(poly_index);
if (current_group == last_poly_vertex_group) {
/* No vertex group found in this polygon, just like in the last iteration. */
return current_group;
}
if (current_group == NOT_FOUND) {
fh.write<eOBJSyntaxElement::object_group>(DEFORM_GROUP_DISABLED);
}
else {
fh.write<eOBJSyntaxElement::object_group>(
obj_mesh_data.get_poly_deform_group_name(current_group));
}
return current_group;
const Vector<float3> &normal_coords = obj_mesh_data.get_normal_coords();
const int tot_count = normal_coords.size();
obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) {
const float3 &normal = normal_coords[i];
buf.write<eOBJSyntaxElement::normal>(normal[0], normal[1], normal[2]);
});
}
OBJWriter::func_vert_uv_normal_indices OBJWriter::get_poly_element_writer(
@ -290,30 +268,78 @@ OBJWriter::func_vert_uv_normal_indices OBJWriter::get_poly_element_writer(
return &OBJWriter::write_vert_indices;
}
static int get_smooth_group(const OBJMesh &mesh, const OBJExportParams &params, int poly_idx)
{
if (poly_idx < 0) {
return NEGATIVE_INIT;
}
int group = SMOOTH_GROUP_DISABLED;
if (mesh.is_ith_poly_smooth(poly_idx)) {
group = !params.export_smooth_groups ? SMOOTH_GROUP_DEFAULT : mesh.ith_smooth_group(poly_idx);
}
return group;
}
void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh,
const IndexOffsets &offsets,
const OBJMesh &obj_mesh_data,
std::function<const char *(int)> matname_fn)
{
int last_poly_smooth_group = NEGATIVE_INIT;
int16_t last_poly_vertex_group = NEGATIVE_INIT;
int16_t last_poly_mat_nr = NEGATIVE_INIT;
const func_vert_uv_normal_indices poly_element_writer = get_poly_element_writer(
obj_mesh_data.tot_uv_vertices());
const int tot_polygons = obj_mesh_data.tot_polygons();
for (int i = 0; i < tot_polygons; i++) {
obj_parallel_chunked_output(fh, tot_polygons, [&](FormatHandler<eFileType::OBJ> &buf, int i) {
Vector<int> poly_vertex_indices = obj_mesh_data.calc_poly_vertex_indices(i);
Span<int> poly_uv_indices = obj_mesh_data.calc_poly_uv_indices(i);
Vector<int> poly_normal_indices = obj_mesh_data.calc_poly_normal_indices(i);
last_poly_smooth_group = write_smooth_group(fh, obj_mesh_data, i, last_poly_smooth_group);
last_poly_vertex_group = write_vertex_group(fh, obj_mesh_data, i, last_poly_vertex_group);
last_poly_mat_nr = write_poly_material(fh, obj_mesh_data, i, last_poly_mat_nr, matname_fn);
/* Write smoothing group if different from previous. */
{
const int prev_group = get_smooth_group(obj_mesh_data, export_params_, i - 1);
const int group = get_smooth_group(obj_mesh_data, export_params_, i);
if (group != prev_group) {
buf.write<eOBJSyntaxElement::smooth_group>(group);
}
}
/* Write vertex group if different from previous. */
if (export_params_.export_vertex_groups) {
const int16_t prev_group = i == 0 ? NEGATIVE_INIT :
obj_mesh_data.get_poly_deform_group_index(i - 1);
const int16_t group = obj_mesh_data.get_poly_deform_group_index(i);
if (group != prev_group) {
buf.write<eOBJSyntaxElement::object_group>(
group == NOT_FOUND ? DEFORM_GROUP_DISABLED :
obj_mesh_data.get_poly_deform_group_name(group));
}
}
/* Write material name and material group if different from previous. */
if (export_params_.export_materials && obj_mesh_data.tot_materials() > 0) {
const int16_t prev_mat = i == 0 ? NEGATIVE_INIT : obj_mesh_data.ith_poly_matnr(i - 1);
const int16_t mat = obj_mesh_data.ith_poly_matnr(i);
if (mat != prev_mat) {
if (mat == NOT_FOUND) {
buf.write<eOBJSyntaxElement::poly_usemtl>(MATERIAL_GROUP_DISABLED);
}
else {
if (export_params_.export_object_groups) {
write_object_group(buf, obj_mesh_data);
}
const char *mat_name = matname_fn(mat);
if (!mat_name) {
mat_name = MATERIAL_GROUP_DISABLED;
}
buf.write<eOBJSyntaxElement::poly_usemtl>(mat_name);
}
}
}
/* Write polygon elements. */
(this->*poly_element_writer)(
fh, offsets, poly_vertex_indices, poly_uv_indices, poly_normal_indices);
}
buf, offsets, poly_vertex_indices, poly_uv_indices, poly_normal_indices);
});
}
void OBJWriter::write_edges_indices(FormatHandler<eFileType::OBJ> &fh,
@ -369,11 +395,25 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh,
/**
* In `parm u 0 0.1 ..` line:, (total control points + 2) equidistant numbers in the
* parameter range are inserted.
* parameter range are inserted. However for curves with endpoint flag,
* first degree+1 numbers are zeroes, and last degree+1 numbers are ones
*/
const short flagsu = obj_nurbs_data.get_nurbs_flagu(spline_idx);
const bool cyclic = flagsu & CU_NURB_CYCLIC;
const bool endpoint = !cyclic && (flagsu & CU_NURB_ENDPOINT);
fh.write<eOBJSyntaxElement::nurbs_parameter_begin>();
for (int i = 1; i <= total_control_points + 2; i++) {
fh.write<eOBJSyntaxElement::nurbs_parameters>(1.0f * i / (total_control_points + 2 + 1));
float parm = 1.0f * i / (total_control_points + 2 + 1);
if (endpoint) {
if (i <= nurbs_degree) {
parm = 0;
}
else if (i > total_control_points + 2 - nurbs_degree) {
parm = 1;
}
}
fh.write<eOBJSyntaxElement::nurbs_parameters>(parm);
}
fh.write<eOBJSyntaxElement::nurbs_parameter_end>();

View File

@ -102,30 +102,6 @@ class OBJWriter : NonMovable, NonCopyable {
* \note Normal indices ares stored here, but written with polygons later.
*/
void write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data);
/**
* Write smooth group if polygon at the given index is shaded smooth else "s 0"
*/
int write_smooth_group(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
int poly_index,
int last_poly_smooth_group) const;
/**
* Write material name and material group of a polygon in the .OBJ file.
* \return #mat_nr of the polygon at the given index.
* \note It doesn't write to the material library.
*/
int16_t write_poly_material(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
int poly_index,
int16_t last_poly_mat_nr,
std::function<const char *(int)> matname_fn) const;
/**
* Write the name of the deform group of a polygon.
*/
int16_t write_vertex_group(FormatHandler<eFileType::OBJ> &fh,
const OBJMesh &obj_mesh_data,
int poly_index,
int16_t last_poly_vertex_group) const;
/**
* Write polygon elements with at least vertex indices, and conditionally with UV vertex
* indices and polygon normal indices. Also write groups: smooth, vertex, material.

View File

@ -177,7 +177,7 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key
return {"curv 0.0 1.0", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::nurbs_parameter_begin: {
return {"parm 0.0", 0, is_type_string_related<T...>};
return {"parm u 0.0", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::nurbs_parameters: {
return {" %f", 1, is_type_float<T...>};
@ -313,6 +313,14 @@ class FormatHandler : NonCopyable, NonMovable {
return blocks_.size();
}
void append_from(FormatHandler<filetype, buffer_chunk_size, write_local_buffer_size> &v)
{
blocks_.insert(blocks_.end(),
std::make_move_iterator(v.blocks_.begin()),
std::make_move_iterator(v.blocks_.end()));
v.blocks_.clear();
}
/**
* Example invocation: `writer->write<eMTLSyntaxElement::newmtl>("foo")`.
*

View File

@ -193,8 +193,8 @@ static void store_bsdf_properties(const nodes::NodeRef *bsdf_node,
copy_property_from_node(SOCK_FLOAT, bnode, "Roughness", {&roughness, 1});
}
/* Empirical approximation. Importer should use the inverse of this method. */
float spec_exponent = (1.0f - roughness) * 30;
spec_exponent *= spec_exponent;
float spec_exponent = (1.0f - roughness);
spec_exponent *= spec_exponent * 1000.0f;
float specular = material->spec;
if (bnode) {

View File

@ -102,4 +102,10 @@ int OBJCurve::get_nurbs_degree(const int spline_index) const
return nurb->orderu - 1;
}
short OBJCurve::get_nurbs_flagu(const int spline_index) const
{
const Nurb *const nurb = static_cast<Nurb *>(BLI_findlink(&export_curve_->nurb, spline_index));
return nurb->flagu;
}
} // namespace blender::io::obj

View File

@ -61,6 +61,10 @@ class OBJCurve : NonCopyable {
* Get the degree of the NURBS spline at the given index.
*/
int get_nurbs_degree(int spline_index) const;
/**
* Get the U flags (CU_NURB_*) of the NURBS spline at the given index.
*/
short get_nurbs_flagu(int spline_index) const;
private:
/**

View File

@ -265,7 +265,7 @@ o abcdef
o 012345678901234567890123456789abcd
o 123
curv 0.0 1.0
parm 0.0
parm u 0.0
)";
ASSERT_EQ(got_string, expected);
}
@ -345,8 +345,14 @@ class obj_exporter_regression_test : public obj_exporter_test {
std::string output_mtl_str = read_temp_file_in_string(out_mtl_file_path);
std::string golden_mtl_file_path = blender::tests::flags_test_asset_dir() + "/" + golden_mtl;
std::string golden_mtl_str = read_temp_file_in_string(golden_mtl_file_path);
ASSERT_TRUE(strings_equal_after_first_lines(output_mtl_str, golden_mtl_str));
BLI_delete(out_mtl_file_path.c_str(), false, false);
are_equal = strings_equal_after_first_lines(output_mtl_str, golden_mtl_str);
if (save_failing_test_output && !are_equal) {
printf("failing test output in %s\n", out_mtl_file_path.c_str());
}
ASSERT_TRUE(are_equal);
if (!save_failing_test_output || are_equal) {
BLI_delete(out_mtl_file_path.c_str(), false, false);
}
}
}
};
@ -410,6 +416,19 @@ TEST_F(obj_exporter_regression_test, nurbs_as_nurbs)
"io_tests/blend_geometry/nurbs.blend", "io_tests/obj/nurbs.obj", "", _export.params);
}
TEST_F(obj_exporter_regression_test, nurbs_curves_as_nurbs)
{
OBJExportParamsDefault _export;
_export.params.forward_axis = OBJ_AXIS_Y_FORWARD;
_export.params.up_axis = OBJ_AXIS_Z_UP;
_export.params.export_materials = false;
_export.params.export_curves_as_nurbs = true;
compare_obj_export_to_golden("io_tests/blend_geometry/nurbs_curves.blend",
"io_tests/obj/nurbs_curves.obj",
"",
_export.params);
}
TEST_F(obj_exporter_regression_test, nurbs_as_mesh)
{
OBJExportParamsDefault _export;

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