Skip to content

Commit

Permalink
Re-Implement GPU particles on master.
Browse files Browse the repository at this point in the history
-No new features yet
-Unlike godot 3.x, sorting happens using GPU
  • Loading branch information
reduz committed Sep 2, 2020
1 parent c591999 commit aa5b5a5
Show file tree
Hide file tree
Showing 16 changed files with 1,764 additions and 105 deletions.
2 changes: 1 addition & 1 deletion scene/resources/particles_material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ void ParticlesMaterial::_update_shader() {
code += "}\n";
code += "\n";

code += "void vertex() {\n";
code += "void compute() {\n";
code += " uint base_number = NUMBER / uint(trail_divisor);\n";
code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n";
code += " float angle_rand = rand_from_seed(alt_seed);\n";
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ class RasterizerStorage {
virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;

virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0;

/* GLOBAL VARIABLES */

virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
Expand Down
85 changes: 85 additions & 0 deletions servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,76 @@ void RasterizerEffectsRD::filter_shadow(RID p_shadow, RID p_backing_shadow, cons
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_source_rect.size.width, p_source_rect.size.height, 1, 8, 8, 1);
}
}

void RasterizerEffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
Sort::PushConstant push_constant;
push_constant.total_elements = p_size;

bool done = true;

int numThreadGroups = ((p_size - 1) >> 9) + 1;

if (numThreadGroups > 1) {
done = false;
}

RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();

RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_BLOCK]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_uniform_set, 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);

int presorted = 512;

while (!done) {
RD::get_singleton()->compute_list_add_barrier(compute_list);

done = true;
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_STEP]);

numThreadGroups = 0;

if (p_size > presorted) {
if (p_size > presorted * 2) {
done = false;
}

int pow2 = presorted;
while (pow2 < p_size) {
pow2 *= 2;
}
numThreadGroups = pow2 >> 9;
}

unsigned int nMergeSize = presorted * 2;

for (unsigned int nMergeSubSize = nMergeSize >> 1; nMergeSubSize > 256; nMergeSubSize = nMergeSubSize >> 1) {
push_constant.job_params[0] = nMergeSubSize;
if (nMergeSubSize == nMergeSize >> 1) {
push_constant.job_params[1] = (2 * nMergeSubSize - 1);
push_constant.job_params[2] = -1;
} else {
push_constant.job_params[1] = nMergeSubSize;
push_constant.job_params[2] = 1;
}
push_constant.job_params[3] = 0;

RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
}

RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_INNER]);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);

presorted *= 2;
}

RD::get_singleton()->compute_list_end();
}

RasterizerEffectsRD::RasterizerEffectsRD() {
{ // Initialize copy
Vector<String> copy_modes;
Expand Down Expand Up @@ -1618,6 +1688,21 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
}
}

{
Vector<String> sort_modes;
sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
sort_modes.push_back("\n#define MODE_SORT_STEP\n");
sort_modes.push_back("\n#define MODE_SORT_INNER\n");

sort.shader.initialize(sort_modes);

sort.shader_version = sort.shader.version_create();

for (int i = 0; i < SORT_MODE_MAX; i++) {
sort.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sort.shader.version_get_shader(sort.shader_version, i));
}
}

RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
Expand Down
24 changes: 23 additions & 1 deletion servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/shadow_reduce.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/sort.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/specular_merge.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
Expand Down Expand Up @@ -545,9 +546,28 @@ class RasterizerEffectsRD {
struct ShadowReduce {
ShadowReduceShaderRD shader;
RID shader_version;
RID pipelines[2];
RID pipelines[SHADOW_REDUCE_MAX];
} shadow_reduce;

enum SortMode {
SORT_MODE_BLOCK,
SORT_MODE_STEP,
SORT_MODE_INNER,
SORT_MODE_MAX
};

struct Sort {
struct PushConstant {
uint32_t total_elements;
uint32_t pad[3];
int32_t job_params[4];
};

SortShaderRD shader;
RID shader_version;
RID pipelines[SORT_MODE_MAX];
} sort;

RID default_sampler;
RID default_mipmap_sampler;
RID index_buffer;
Expand Down Expand Up @@ -650,6 +670,8 @@ class RasterizerEffectsRD {
void reduce_shadow(RID p_source_shadow, RID p_dest_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, int p_shrink_limit, RenderingDevice::ComputeListID compute_list);
void filter_shadow(RID p_shadow, RID p_backing_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, RS::EnvVolumetricFogShadowFilter p_filter, RenderingDevice::ComputeListID compute_list, bool p_vertical = true, bool p_horizontal = true);

void sort_buffer(RID p_uniform_set, int p_size);

RasterizerEffectsRD();
~RasterizerEffectsRD();
};
Expand Down
76 changes: 57 additions & 19 deletions servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,8 +782,7 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
for (int i = 0; i < p_element_count; i++) {
const RenderList::Element *e = p_elements[i];
InstanceData &id = scene_state.instances[i];
RasterizerStorageRD::store_transform(e->instance->transform, id.transform);
RasterizerStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
bool store_transform = true;
id.flags = 0;
id.mask = e->instance->layer_mask;
id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
Expand All @@ -807,12 +806,42 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
}

id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
} else if (e->instance->base_type == RS::INSTANCE_PARTICLES) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
uint32_t stride;
if (false) { // 2D particles
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
stride = 2;
} else {
stride = 3;
}

id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
stride += 1;

id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
stride += 1;

id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);

if (!storage->particles_is_using_local_coords(e->instance->base)) {
store_transform = false;
}

} else if (e->instance->base_type == RS::INSTANCE_MESH) {
if (e->instance->skeleton.is_valid()) {
id.flags |= INSTANCE_DATA_FLAG_SKELETON;
}
}

if (store_transform) {
RasterizerStorageRD::store_transform(e->instance->transform, id.transform);
RasterizerStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
} else {
RasterizerStorageRD::store_transform(Transform(), id.transform);
RasterizerStorageRD::store_transform(Transform(), id.normal_transform);
}

if (p_for_depth) {
id.gi_offset = 0xFFFFFFFF;
continue;
Expand Down Expand Up @@ -967,7 +996,12 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
ERR_CONTINUE(true); //should be a bug
} break;
case RS::INSTANCE_PARTICLES: {
ERR_CONTINUE(true); //should be a bug
RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index & 0xFFFF);

xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);

} break;
default: {
ERR_CONTINUE(true); //should be a bug
Expand Down Expand Up @@ -1036,7 +1070,9 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
ERR_CONTINUE(true); //should be a bug
} break;
case RS::INSTANCE_PARTICLES: {
ERR_CONTINUE(true); //should be a bug
RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
ERR_CONTINUE(!mesh.is_valid()); //should be a bug
storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index & 0xFFFF, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format);
} break;
default: {
ERR_CONTINUE(true); //should be a bug
Expand Down Expand Up @@ -1092,6 +1128,8 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
case RS::INSTANCE_IMMEDIATE: {
} break;
case RS::INSTANCE_PARTICLES: {
uint32_t instances = storage->particles_get_amount(e->instance->base);
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
} break;
default: {
ERR_CONTINUE(true); //should be a bug
Expand Down Expand Up @@ -1524,31 +1562,31 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
_add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);

} break;
#endif
case RS::INSTANCE_PARTICLES: {
int draw_passes = storage->particles_get_draw_passes(inst->base);

RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base);
ERR_CONTINUE(!particles);

for (int j = 0; j < particles->draw_passes.size(); j++) {

RID pmesh = particles->draw_passes[j];
if (!pmesh.is_valid())
for (int j = 0; j < draw_passes; j++) {
RID mesh = storage->particles_get_draw_pass_mesh(inst->base, j);
if (!mesh.is_valid())
continue;
RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh);
if (!mesh)
continue; //mesh not assigned

int ssize = mesh->surfaces.size();
const RID *materials = nullptr;
uint32_t surface_count;

for (int k = 0; k < ssize; k++) {
materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (!materials) {
continue; //nothing to do
}

RasterizerStorageGLES3::Surface *s = mesh->surfaces[k];
_add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass);
for (uint32_t k = 0; k < surface_count; k++) {
uint32_t surface_index = storage->mesh_surface_get_particles_render_pass_index(mesh, j, render_pass, &geometry_index);
_add_geometry(inst, (j << 16) | k, materials[j], p_pass_mode, surface_index, p_using_sdfgi);
}
}

} break;
#endif

default: {
}
}
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ class RasterizerSceneRD : public RasterizerScene {

mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;

/* REFLECTION PROBE INSTANCE */
/* DECAL INSTANCE */

struct DecalInstance {
RID decal;
Expand Down
Loading

0 comments on commit aa5b5a5

Please sign in to comment.