Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-12-04 19:20:20 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-12-04 19:21:37 +0300
commit5bd008f4ddd42d61a0e605fca8136230e7189d82 (patch)
tree98a61c1456b5f8e268e95b3a724f71787d2fbab3 /source/blender/draw
parentc370fffc9bd0900a30e04ac631641d43e0f217a5 (diff)
Eevee: Irradiance Grid: Allocate needed resources instead of a static chunck.
This commit makes the irradiance pool and render target sizes depend on the number of irradiance sample in the whole ViewLayer.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c105
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h2
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl9
3 files changed, 89 insertions, 27 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index a83562e81ce..56bfc2f8f23 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -46,7 +46,23 @@
#include "ED_screen.h"
-#define IRRADIANCE_POOL_SIZE 1024
+/* Rounded to nearest PowerOfTwo */
+#if defined(IRRADIANCE_SH_L2)
+#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
+#define IRRADIANCE_SAMPLE_SIZE_Y 4 /* 3 in reality */
+#elif defined(IRRADIANCE_CUBEMAP)
+#define IRRADIANCE_SAMPLE_SIZE_X 8
+#define IRRADIANCE_SAMPLE_SIZE_Y 8
+#elif defined(IRRADIANCE_HL2)
+#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
+#define IRRADIANCE_SAMPLE_SIZE_Y 2
+#endif
+
+#define IRRADIANCE_MAX_POOL_LAYER 256 /* OpenGL 3.3 core requirement, can be extended but it's already very big */
+#define IRRADIANCE_MAX_POOL_SIZE 1024
+#define MAX_IRRADIANCE_SAMPLES \
+ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \
+ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
#define HAMMERSLEY_SIZE 1024
static struct {
@@ -97,6 +113,21 @@ extern GlobalsUboStorage ts;
/* *********** FUNCTIONS *********** */
+static void irradiance_pool_size_get(int visibility_size, int total_samples, int r_size[3])
+{
+ /* Compute how many irradiance samples we can store per visibility sample. */
+ int irr_per_vis = (visibility_size / IRRADIANCE_SAMPLE_SIZE_X) *
+ (visibility_size / IRRADIANCE_SAMPLE_SIZE_Y);
+
+ /* The irradiance itself take one layer, hence the +1 */
+ int layer_ct = MIN2(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER);
+
+ int texel_ct = (int)ceilf((float)total_samples / (float)(layer_ct - 1));
+ r_size[0] = visibility_size * max_ii(1, min_ii(texel_ct, (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
+ r_size[1] = visibility_size * max_ii(1, (texel_ct / (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
+ r_size[2] = layer_ct;
+}
+
static struct GPUTexture *create_hammersley_sample_texture(int samples)
{
struct GPUTexture *tex;
@@ -357,6 +388,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
pinfo->num_cube = 1; /* at least one for the world */
pinfo->num_grid = 1;
pinfo->num_planar = 0;
+ pinfo->total_irradiance_samples = 1;
memset(pinfo->probes_cube_ref, 0, sizeof(pinfo->probes_cube_ref));
memset(pinfo->probes_grid_ref, 0, sizeof(pinfo->probes_grid_ref));
memset(pinfo->probes_planar_ref, 0, sizeof(pinfo->probes_planar_ref));
@@ -522,6 +554,13 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
ped->num_cell = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z;
+ if ((probe->type == LIGHTPROBE_TYPE_GRID) &&
+ ((pinfo->total_irradiance_samples + ped->num_cell) >= MAX_IRRADIANCE_SAMPLES))
+ {
+ printf("Too much grid samples !!!\n");
+ return;
+ }
+
if (ped->need_full_update) {
ped->need_full_update = false;
@@ -554,6 +593,7 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
else { /* GRID */
pinfo->probes_grid_ref[pinfo->num_grid] = ob;
pinfo->num_grid++;
+ pinfo->total_irradiance_samples += ped->num_cell;
}
}
@@ -828,6 +868,18 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
pinfo->cache_num_planar = pinfo->num_planar;
}
+ int irr_size[3];
+ irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
+
+ if ((irr_size[0] != pinfo->cache_irradiance_size[0]) ||
+ (irr_size[1] != pinfo->cache_irradiance_size[1]) ||
+ (irr_size[2] != pinfo->cache_irradiance_size[2]))
+ {
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
+ copy_v3_v3_int(pinfo->cache_irradiance_size, irr_size);
+ }
+
/* XXX this should be run each frame as it ensure planar_depth is set */
planar_pool_ensure_alloc(vedata, pinfo->num_planar);
@@ -867,14 +919,13 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
int irradiance_format = DRW_TEX_RGBA_8;
#endif
- /* TODO Allocate bigger storage if needed. */
if (!sldata->irradiance_pool || !sldata->irradiance_rt) {
if (!sldata->irradiance_pool) {
- sldata->irradiance_pool = DRW_texture_create_2D_array(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, 2,
+ sldata->irradiance_pool = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
irradiance_format, DRW_TEX_FILTER, NULL);
}
if (!sldata->irradiance_rt) {
- sldata->irradiance_rt = DRW_texture_create_2D_array(IRRADIANCE_POOL_SIZE, IRRADIANCE_POOL_SIZE, 2,
+ sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
irradiance_format, DRW_TEX_FILTER, NULL);
}
pinfo->num_render_grid = 0;
@@ -1000,6 +1051,9 @@ static void diffuse_filter_probe(
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ int pool_size[3];
+ irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
+
/* find cell position on the virtual 3D texture */
/* NOTE : Keep in sync with load_irradiance_cell() */
#if defined(IRRADIANCE_SH_L2)
@@ -1012,7 +1066,7 @@ static void diffuse_filter_probe(
pinfo->samples_ct = 1024.0f;
#endif
- int cell_per_row = IRRADIANCE_POOL_SIZE / size[0];
+ int cell_per_row = pool_size[0] / size[0];
int x = size[0] * (offset % cell_per_row);
int y = size[1] * (offset / cell_per_row);
@@ -1032,30 +1086,35 @@ static void diffuse_filter_probe(
EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
DRW_framebuffer_texture_detach(sldata->probe_pool);
- DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0, 0);
DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
DRW_draw_pass(psl->probe_diffuse_compute);
- /* Compute visibility */
- pinfo->samples_ct = 512.0f; /* TODO refine */
- pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
- pinfo->shres = pinfo->irradiance_vis_size;
- pinfo->visibility_range = vis_range;
- pinfo->visibility_blur = vis_blur;
- pinfo->near_clip = -clipsta;
- pinfo->far_clip = -clipend;
- pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
-
- cell_per_row = IRRADIANCE_POOL_SIZE / pinfo->irradiance_vis_size;
- x = pinfo->irradiance_vis_size * (offset % cell_per_row);
- y = pinfo->irradiance_vis_size * (offset / cell_per_row);
+ /* World irradiance have no visibility */
+ if (offset > 0) {
+ /* Compute visibility */
+ pinfo->samples_ct = 512.0f; /* TODO refine */
+ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
+ pinfo->shres = pinfo->irradiance_vis_size;
+ pinfo->visibility_range = vis_range;
+ pinfo->visibility_blur = vis_blur;
+ pinfo->near_clip = -clipsta;
+ pinfo->far_clip = -clipend;
+ pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
+
+ int cell_per_col = pool_size[1] / pinfo->irradiance_vis_size;
+ cell_per_row = pool_size[0] / pinfo->irradiance_vis_size;
+ x = pinfo->irradiance_vis_size * (offset % cell_per_row);
+ y = pinfo->irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
+ int layer = 1 + ((offset / cell_per_row) / cell_per_col);
- DRW_framebuffer_texture_detach(sldata->irradiance_rt);
- DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 1, 0);
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
- DRW_draw_pass(psl->probe_visibility_compute);
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
+ DRW_draw_pass(psl->probe_visibility_compute);
+ }
/* reattach to have a valid framebuffer. */
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 36a6d3fb1d0..98fc6d6a6e4 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -388,6 +388,8 @@ typedef struct EEVEE_LightProbesInfo {
int num_cube, cache_num_cube;
int num_grid, cache_num_grid;
int num_planar, cache_num_planar;
+ int total_irradiance_samples; /* Total for all grids */
+ int cache_irradiance_size[3];
int update_flag;
int updated_bounce;
int num_bounce;
diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
index 2555d413da9..76d20486d3d 100644
--- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
@@ -82,9 +82,10 @@ float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed
{
/* Keep in sync with diffuse_filter_probe() */
ivec2 cell_co = ivec2(irradianceVisibilitySize);
- int cell_per_row = textureSize(irradianceGrid, 0).x / irradianceVisibilitySize;
- cell_co.x *= (cell) % cell_per_row;
- cell_co.y *= (cell) / cell_per_row;
+ ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / irradianceVisibilitySize;
+ cell_co.x *= (cell % cell_per_row_col.x);
+ cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y;
+ float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y);
vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
vec2 co = vec2(cell_co) * texel_size;
@@ -92,7 +93,7 @@ float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed
vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize)));
uv *= vec2(irradianceVisibilitySize) * texel_size;
- vec4 data = texture(irradianceGrid, vec3(co + uv, 1.0));
+ vec4 data = texture(irradianceGrid, vec3(co + uv, layer));
/* Decoding compressed data */
vec2 moments = visibility_decode(data, range);