Merge branch 'master' into asset-browser-grid-view
This commit is contained in:
commit
d2c4918d77
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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',
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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");
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)")
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ struct LogCursor {
|
|||
|
||||
struct GPULogItem {
|
||||
LogCursor cursor;
|
||||
bool source_base_row = false;
|
||||
Severity severity = Severity::Unknown;
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 smooth–shaded, 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 ¶ms, 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>();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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")`.
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
/**
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue