WIP: Geometry Nodes: Shperical Ico Sphere #116982

Draft
Iliya Katushenock wants to merge 48 commits from mod_moder/blender:new_ico_sphere_alg into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
24 changed files with 64 additions and 52 deletions
Showing only changes of commit a6da887487 - Show all commits

View File

@ -4,8 +4,6 @@
#pragma once
#include <functional>
#include "BLI_math_vector.hh"
#include "BLI_rect.h"
#include "BLI_vector.hh"

View File

@ -11,8 +11,8 @@
/* The boolean functions in Blenlib use exact arithmetic, so require GMP. */
#ifdef WITH_GMP
# include "BLI_function_ref.hh"
# include "BLI_mesh_intersect.hh"
# include <functional>
namespace blender::meshintersect {
@ -46,7 +46,7 @@ enum class BoolOpType {
IMesh boolean_mesh(IMesh &imesh,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMesh *imesh_triangulated,
@ -60,7 +60,7 @@ IMesh boolean_mesh(IMesh &imesh,
IMesh boolean_trimesh(IMesh &tm_in,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMeshArena *arena);

View File

@ -16,6 +16,7 @@
# include <iosfwd>
# include "BLI_array.hh"
# include "BLI_function_ref.hh"
# include "BLI_index_range.hh"
# include "BLI_map.hh"
# include "BLI_math_mpq.hh"
@ -403,7 +404,7 @@ IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena);
IMesh trimesh_nary_intersect(const IMesh &tm_in,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
bool use_self,
IMeshArena *arena);

View File

@ -2198,7 +2198,7 @@ static void propagate_windings_and_in_output_volume(PatchesInfo &pinfo,
int c_ambient,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn)
FunctionRef<int(int)> shape_fn)
{
int dbg_level = 0;
if (dbg_level > 0) {
@ -2514,12 +2514,12 @@ static double3 calc_point_inside_tri_db(const Face &tri)
class InsideShapeTestData {
public:
const IMesh &tm;
std::function<int(int)> shape_fn;
FunctionRef<int(int)> shape_fn;
int nshapes;
/* A per-shape vector of parity of hits of that shape. */
Array<int> hit_parity;
InsideShapeTestData(const IMesh &tm, std::function<int(int)> shape_fn, int nshapes)
InsideShapeTestData(const IMesh &tm, FunctionRef<int(int)> shape_fn, int nshapes)
: tm(tm), shape_fn(shape_fn), nshapes(nshapes)
{
}
@ -2578,7 +2578,7 @@ static void inside_shape_callback(void *userdata,
* \param tree: Contains all the triangles of \a tm and can be used for fast ray-casting.
*/
static void test_tri_inside_shapes(const IMesh &tm,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
int nshapes,
int test_t_index,
BVHTree *tree,
@ -2726,11 +2726,8 @@ static void raycast_add_flipped(Vector<Face *> &out_faces, Face &tri, IMeshArena
* when the input is not PWN, some patches can be both inside and outside
* some shapes (e.g., a plane cutting through Suzanne's open eyes).
*/
static IMesh raycast_tris_boolean(const IMesh &tm,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
IMeshArena *arena)
static IMesh raycast_tris_boolean(
const IMesh &tm, BoolOpType op, int nshapes, FunctionRef<int(int)> shape_fn, IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@ -2804,7 +2801,7 @@ static IMesh raycast_tris_boolean(const IMesh &tm,
static IMesh raycast_patches_boolean(const IMesh &tm,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
const PatchesInfo &pinfo,
IMeshArena *arena)
{
@ -3543,7 +3540,7 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
IMesh boolean_trimesh(IMesh &tm_in,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMeshArena *arena)
@ -3691,7 +3688,7 @@ static void dump_test_spec(IMesh &imesh)
IMesh boolean_mesh(IMesh &imesh,
BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMesh *imesh_triangulated,

View File

@ -2935,7 +2935,7 @@ IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena)
IMesh trimesh_nary_intersect(const IMesh &tm_in,
int nshapes,
std::function<int(int)> shape_fn,
const FunctionRef<int(int)> shape_fn,
bool use_self,
IMeshArena *arena)
{

View File

@ -8,6 +8,8 @@
* Main functions for boolean on a #BMesh (used by the tool and modifier)
*/
#include <functional>
#include "BLI_array.hh"
#include "BLI_math_mpq.hh"
#include "BLI_mesh_boolean.hh"

View File

@ -20,7 +20,7 @@ shared uint shared_max_slight_focus_abs_coc;
*/
float dof_slight_focus_coc_tile_get(vec2 frag_coord)
{
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
shared_max_slight_focus_abs_coc = floatBitsToUint(0.0);
}
barrier();

View File

@ -33,7 +33,7 @@ uint dof_tile_large_coc_uint = floatBitsToUint(dof_tile_large_coc);
void main()
{
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
/* NOTE: Min/Max flipped because of inverted fg_coc sign. */
fg_min_coc = floatBitsToUint(0.0);
fg_max_coc = dof_tile_large_coc_uint;
@ -61,7 +61,7 @@ void main()
barrier();
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
if (fg_max_intersectable_coc == dof_tile_large_coc_uint) {
fg_max_intersectable_coc = floatBitsToUint(0.0);
}

View File

@ -37,7 +37,7 @@ uvec2 unpack_payload(uint payload)
void main()
{
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
payload_prev = 0u;
payload_next = 0u;
}
@ -99,7 +99,7 @@ void main()
}
barrier();
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
ivec2 tile_co = ivec2(gl_WorkGroupID.xy);
imageStore(out_tiles_img, tile_co, vec4(max_motion_prev, max_motion_next));
}

View File

@ -23,7 +23,7 @@ float ray_roughness_factor(RayTraceData raytrace, float roughness)
void main()
{
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
/* Init shared variables. */
for (int i = 0; i < 3; i++) {
tile_contains_ray_tracing[i] = 0;
@ -73,7 +73,7 @@ void main()
barrier();
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
ivec2 denoise_tile_co = ivec2(gl_WorkGroupID.xy);
ivec2 tracing_tile_co = denoise_tile_co / uniform_buf.raytrace.resolution_scale;

View File

@ -56,7 +56,7 @@ void main()
cooefs[store_index][3] = cooef.L1.Mp1;
barrier();
if (gl_LocalInvocationID.x == 0) {
if (gl_LocalInvocationIndex == 0u) {
/* Join results */
vec4 result[4];
result[0] = vec4(0.0);

View File

@ -52,7 +52,7 @@ void main()
local_max = max(local_max, z);
}
if (gl_LocalInvocationID.x == 0) {
if (gl_LocalInvocationIndex == 0u) {
global_min = floatBitsToOrderedInt(FLT_MAX);
global_max = floatBitsToOrderedInt(-FLT_MAX);
}
@ -69,7 +69,7 @@ void main()
barrier();
if (gl_LocalInvocationID.x == 0) {
if (gl_LocalInvocationIndex == 0u) {
/* Final result. Min/Max of the whole dispatch. */
atomicMin(light_buf[l_idx].clip_near, global_min);
atomicMax(light_buf[l_idx].clip_far, global_max);

View File

@ -68,7 +68,7 @@ void main()
ShadowTileData tile = shadow_tile_unpack(tiles_buf[tile_index]);
/* Compute update area. */
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
rect_min_x = SHADOW_TILEMAP_RES;
rect_min_y = SHADOW_TILEMAP_RES;
rect_max_x = 0;
@ -96,7 +96,7 @@ void main()
ivec2 viewport_size = viewport_size_get(viewport_index);
/* Issue one view if there is an update in the LOD. */
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
bool lod_has_update = rect_min.x < rect_max.x;
if (lod_has_update) {
view_index = atomicAdd(statistics_buf.view_needed_count, 1);

View File

@ -34,7 +34,7 @@ void main()
barrier();
if (all(equal(gl_LocalInvocationID, uvec3(0)))) {
if (gl_LocalInvocationIndex == 0u) {
/* Reset shift to not tag for update more than once per sync cycle. */
tilemaps_buf[tilemap_index].grid_shift = ivec2(0);

View File

@ -17,7 +17,7 @@ void main(void)
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
has_visible_sss = 0u;
}
@ -53,7 +53,7 @@ void main(void)
barrier();
if (all(equal(gl_LocalInvocationID.xy, uvec2(0)))) {
if (gl_LocalInvocationIndex == 0u) {
if (has_visible_sss > 0u) {
uint tile_id = atomicAdd(convolve_dispatch_buf.num_groups_x, 1u);
convolve_tile_buf[tile_id] = packUvec2x16(gl_WorkGroupID.xy);

View File

@ -87,6 +87,7 @@ GPU_SHADER_CREATE_INFO(eevee_surfel_light)
GPU_SHADER_CREATE_INFO(eevee_surfel_cluster_build)
.local_group_size(SURFEL_GROUP_SIZE)
.builtins(BuiltinBits::TEXTURE_ATOMIC)
.additional_info("eevee_shared", "eevee_surfel_common", "draw_view")
.image(0, GPU_R32I, Qualifier::READ_WRITE, ImageType::INT_3D_ATOMIC, "cluster_list_img")
.compute_source("eevee_surfel_cluster_build_comp.glsl")

View File

@ -8,6 +8,8 @@
#pragma once
#include "BLI_function_ref.hh"
#include "DRW_gpu_wrapper.hh"
#include "DRW_render.h"
#include "UI_resources.hh"
@ -129,7 +131,7 @@ class ShaderModule {
}
ShaderPtr selectable_shader(const char *create_info_name);
ShaderPtr selectable_shader(const char *create_info_name,
std::function<void(gpu::shader::ShaderCreateInfo &info)> patch);
FunctionRef<void(gpu::shader::ShaderCreateInfo &info)> patch);
};
struct Resources : public select::SelectMap {

View File

@ -34,7 +34,8 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(const char *create_info_
}
ShaderModule::ShaderPtr ShaderModule::selectable_shader(
const char *create_info_name, std::function<void(gpu::shader::ShaderCreateInfo &info)> patch)
const char *create_info_name,
const FunctionRef<void(gpu::shader::ShaderCreateInfo &info)> patch)
{
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
GPU_shader_create_info_get(create_info_name));

View File

@ -157,11 +157,14 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
/* Vertex/instance buffers provided have attribute data for attributes which are not needed
* by this particular shader. This shader only needs binding information for the attributes
* has in the shader interface. */
MTL_LOG_WARNING(
"MTLBatch: Could not find attribute with name '%s' (defined in active vertex format) "
"in the shader interface for shader '%s'",
name,
interface->get_name());
if (StringRefNull(name) != "dummy") {
MTL_LOG_WARNING(
"MTLBatch: Could not find attribute with name '%s' (defined in active vertex "
"format) "
"in the shader interface for shader '%s'",
name,
interface->get_name());
}
continue;
}

View File

@ -50,6 +50,8 @@ char *MSLGeneratorInterface::msl_patch_default = nullptr;
#define FRAGMENT_OUT_STRUCT_NAME "FragmentOut"
#define FRAGMENT_TILE_IN_STRUCT_NAME "FragmentTileIn"
#define ATOMIC_DEFINE_STR "#define MTL_SUPPORTS_TEXTURE_ATOMICS 1\n"
/* -------------------------------------------------------------------- */
/** \name Shader Translation utility functions.
* \{ */
@ -1060,6 +1062,13 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
std::stringstream ss_vertex;
std::stringstream ss_fragment;
if (bool(info->builtins_ & BuiltinBits::TEXTURE_ATOMIC) &&
MTLBackend::get_capabilities().supports_texture_atomics)
{
ss_vertex << ATOMIC_DEFINE_STR;
ss_fragment << ATOMIC_DEFINE_STR;
}
/* Generate specialization constants. */
generate_specialization_constant_declarations(info, ss_vertex);
generate_specialization_constant_declarations(info, ss_fragment);
@ -1521,6 +1530,11 @@ bool MTLShader::generate_msl_from_glsl_compute(const shader::ShaderCreateInfo *i
ss_compute << "#define GPU_ARB_texture_cube_map_array 1\n"
"#define GPU_ARB_shader_draw_parameters 1\n";
if (bool(info->builtins_ & BuiltinBits::TEXTURE_ATOMIC) &&
MTLBackend::get_capabilities().supports_texture_atomics)
{
ss_compute << ATOMIC_DEFINE_STR;
}
generate_specialization_constant_declarations(info, ss_compute);
@ -4027,7 +4041,7 @@ std::string MSLTextureResource::get_msl_wrapper_type_str() const
case ImageType::INT_2D_ARRAY_ATOMIC:
case ImageType::UINT_2D_ARRAY_ATOMIC: {
if (supports_native_atomics) {
return "_mtl_combined_image_sampler_2d";
return "_mtl_combined_image_sampler_2d_array";
}
else {
return "_mtl_combined_image_sampler_2d_array_atomic_fallback";

View File

@ -13,13 +13,6 @@
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wcomment"
/** Feature support. */
/* Native texture atomics supported in Metal 3.1+. Without these, we will use a fallback
* implementation based on SSBOS.*/
#if __METAL_VERSION__ >= 310
# define MTL_SUPPORTS_TEXTURE_ATOMICS 1
#endif
/* Base instance with offsets. */
#define gpu_BaseInstance gl_BaseInstanceARB
#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)

View File

@ -336,7 +336,7 @@ static int get_smooth_group(const OBJMesh &mesh, const OBJExportParams &params,
void OBJWriter::write_poly_elements(FormatHandler &fh,
const IndexOffsets &offsets,
const OBJMesh &obj_mesh_data,
std::function<const char *(int)> matname_fn)
FunctionRef<const char *(int)> matname_fn)
{
const func_vert_uv_normal_indices poly_element_writer = get_poly_element_writer(
obj_mesh_data.tot_uv_vertices());

View File

@ -99,7 +99,7 @@ class OBJWriter : NonMovable, NonCopyable {
void write_poly_elements(FormatHandler &fh,
const IndexOffsets &offsets,
const OBJMesh &obj_mesh_data,
std::function<const char *(int)> matname_fn);
FunctionRef<const char *(int)> matname_fn);
/**
* Write loose edges of a mesh as "l v1 v2".
*/

View File

@ -213,7 +213,7 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me
/* This function takes a 0-indexed slot index for the obj_mesh object and
* returns the material name that we are using in the .obj file for it. */
const auto *obj_mtlindices = mtlindices.is_empty() ? nullptr : &mtlindices[i];
std::function<const char *(int)> matname_fn = [&](int s) -> const char * {
auto matname_fn = [&](int s) -> const char * {
if (!obj_mtlindices || s < 0 || s >= obj_mtlindices->size()) {
return nullptr;
}