Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-Implement GPU particles on master #41711

Merged
merged 2 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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