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>2020-03-11 19:12:01 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-11 19:12:16 +0300
commit7dd0be9554ae7a728ded1a95d4709a93b68301b4 (patch)
tree52a097fd8edd1128def41fcda6bed64e8c6b39b7 /source/blender/gpu
parentc476c36e400883d929a7149def8dcb6ad6157a86 (diff)
EEVEE: Replace octahedron reflection probe by cubemap array
We implement cubemap array support for EEVEE's lightcache reflection probes. This removes stretched texels and bottom hemisphere seams artifacts caused by the octahedral projection previously used. This introduce versioning code for the lightcache which will discard any lightcache version that is not compatible. Differential Revision: https://developer.blender.org/D7066
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_extensions.h1
-rw-r--r--source/blender/gpu/GPU_texture.h10
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c8
-rw-r--r--source/blender/gpu/intern/gpu_shader.c6
-rw-r--r--source/blender/gpu/intern/gpu_texture.c217
5 files changed, 127 insertions, 115 deletions
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 245f7f47510..4ffe4a53a52 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -44,6 +44,7 @@ int GPU_max_ubo_size(void);
float GPU_max_line_width(void);
void GPU_get_dfdy_factors(float fac[2]);
bool GPU_arb_base_instance_is_supported(void);
+bool GPU_arb_texture_cube_map_array_is_supported(void);
bool GPU_mip_render_workaround(void);
bool GPU_depth_blitting_workaround(void);
bool GPU_unused_fb_slot_workaround(void);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index bd15030d135..892452a2738 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -162,6 +162,12 @@ GPUTexture *GPU_texture_create_nD(int w,
int samples,
const bool can_rescale,
char err_out[256]);
+GPUTexture *GPU_texture_cube_create(int w,
+ int d,
+ const void *pixels,
+ eGPUTextureFormat tex_format,
+ eGPUDataFormat gpu_data_format,
+ char err_out[256]);
GPUTexture *GPU_texture_create_1d(int w,
eGPUTextureFormat data_type,
@@ -185,6 +191,9 @@ GPUTexture *GPU_texture_create_cube(int w,
eGPUTextureFormat data_type,
const float *pixels,
char err_out[256]);
+GPUTexture *GPU_texture_create_cube_array(
+ int w, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]);
+
GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert);
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer);
@@ -252,6 +261,7 @@ void GPU_texture_orig_size_set(GPUTexture *tex, int w, int h);
int GPU_texture_layers(const GPUTexture *tex);
eGPUTextureFormat GPU_texture_format(const GPUTexture *tex);
int GPU_texture_samples(const GPUTexture *tex);
+bool GPU_texture_array(const GPUTexture *tex);
bool GPU_texture_cube(const GPUTexture *tex);
bool GPU_texture_depth(const GPUTexture *tex);
bool GPU_texture_stencil(const GPUTexture *tex);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 5a2b74f3407..f497ed22bec 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -78,6 +78,8 @@ static struct GPUGlobal {
/* Some Intel drivers have limited support for `GLEW_ARB_base_instance` so in
* these cases it is best to indicate that it is not supported. See T67951 */
bool glew_arb_base_instance_is_supported;
+ /* Cubemap Array support. */
+ bool glew_arb_texture_cube_map_array_is_supported;
/* Some Intel drivers have issues with using mips as framebuffer targets if
* GL_TEXTURE_MAX_LEVEL is higher than the target mip.
* We need a workaround in this cases. */
@@ -197,6 +199,11 @@ bool GPU_arb_base_instance_is_supported(void)
return GG.glew_arb_base_instance_is_supported;
}
+bool GPU_arb_texture_cube_map_array_is_supported(void)
+{
+ return GG.glew_arb_texture_cube_map_array_is_supported;
+}
+
bool GPU_mip_render_workaround(void)
{
return GG.mip_render_workaround;
@@ -281,6 +288,7 @@ void gpu_extensions_init(void)
}
GG.glew_arb_base_instance_is_supported = GLEW_ARB_base_instance;
+ GG.glew_arb_texture_cube_map_array_is_supported = GLEW_ARB_texture_cube_map_array;
gpu_detect_mip_render_workaround();
if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index c950a1daaa5..0993d69e14d 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -46,7 +46,7 @@
/* Adjust these constants as needed. */
#define MAX_DEFINE_LENGTH 256
-#define MAX_EXT_DEFINE_LENGTH 256
+#define MAX_EXT_DEFINE_LENGTH 512
/* Non-generated shaders */
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
@@ -235,6 +235,10 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
if (GLEW_ARB_shader_draw_parameters) {
strcat(defines, "#extension GL_ARB_shader_draw_parameters : enable\n");
}
+ if (GPU_arb_texture_cube_map_array_is_supported()) {
+ strcat(defines, "#extension GL_ARB_texture_cube_map_array : enable\n");
+ strcat(defines, "#define GPU_ARB_texture_cube_map_array\n");
+ }
}
static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 2fd3e618664..7b51b03096f 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -109,7 +109,7 @@ static uint gpu_texture_memory_footprint_compute(GPUTexture *tex)
return tex->bytesize * tex->w * tex->h * tex->d * samp;
case GL_TEXTURE_CUBE_MAP:
return tex->bytesize * 6 * tex->w * tex->h * samp;
- case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY_ARB:
return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp;
default:
return 0;
@@ -138,6 +138,7 @@ static const char *gl_enum_to_str(GLenum e)
#define ENUM_TO_STRING(e) [GL_##e] = STRINGIFY_ARG(e)
static const char *enum_strings[] = {
ENUM_TO_STRING(TEXTURE_CUBE_MAP),
+ ENUM_TO_STRING(TEXTURE_CUBE_MAP_ARRAY),
ENUM_TO_STRING(TEXTURE_2D),
ENUM_TO_STRING(TEXTURE_2D_ARRAY),
ENUM_TO_STRING(TEXTURE_1D),
@@ -202,6 +203,25 @@ static int gpu_get_component_count(eGPUTextureFormat format)
}
}
+static uint gpu_get_data_format_bytesize(int comp, eGPUDataFormat data_format)
+{
+ switch (data_format) {
+ case GPU_DATA_FLOAT:
+ return sizeof(float) * comp;
+ case GPU_DATA_INT:
+ case GPU_DATA_UNSIGNED_INT:
+ return sizeof(int) * comp;
+ case GPU_DATA_UNSIGNED_INT_24_8:
+ case GPU_DATA_10_11_11_REV:
+ return sizeof(int);
+ case GPU_DATA_UNSIGNED_BYTE:
+ return sizeof(char) * comp;
+ default:
+ BLI_assert(0);
+ return 0;
+ }
+}
+
/* Definitely not complete, edit according to the gl specification. */
static void gpu_validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
{
@@ -679,6 +699,7 @@ GPUTexture *GPU_texture_create_nD(int w,
}
else {
tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY;
+ tex->format_flag |= GPU_FORMAT_ARRAY;
}
}
else if (n == 1) {
@@ -687,6 +708,7 @@ GPUTexture *GPU_texture_create_nD(int w,
}
else {
tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY;
+ tex->format_flag |= GPU_FORMAT_ARRAY;
}
}
else if (n == 3) {
@@ -839,17 +861,12 @@ GPUTexture *GPU_texture_create_nD(int w,
return tex;
}
-static GPUTexture *GPU_texture_cube_create(int w,
- int d,
- const float *fpixels_px,
- const float *fpixels_py,
- const float *fpixels_pz,
- const float *fpixels_nx,
- const float *fpixels_ny,
- const float *fpixels_nz,
- eGPUTextureFormat tex_format,
- eGPUDataFormat gpu_data_format,
- char err_out[256])
+GPUTexture *GPU_texture_cube_create(int w,
+ int d,
+ const void *pixels,
+ eGPUTextureFormat tex_format,
+ eGPUDataFormat gpu_data_format,
+ char err_out[256])
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
@@ -867,8 +884,21 @@ static GPUTexture *GPU_texture_cube_create(int w,
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
}
else {
- BLI_assert(false && "Cubemap array Not implemented yet");
- // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
+ tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY_ARB;
+ tex->format_flag |= GPU_FORMAT_ARRAY;
+
+ if (!GPU_arb_texture_cube_map_array_is_supported()) {
+ fprintf(stderr, "ERROR: Attempt to create a cubemap array without hardware support!\n");
+ BLI_assert(0);
+ GPU_texture_free(tex);
+ return NULL;
+ }
+
+ if (d > GPU_max_texture_layers() / 6) {
+ BLI_assert(0);
+ GPU_texture_free(tex);
+ return NULL;
+ }
}
GLenum internalformat = gpu_get_gl_internalformat(tex_format);
@@ -905,60 +935,42 @@ static GPUTexture *GPU_texture_cube_create(int w,
glBindTexture(tex->target, tex->bindcode);
/* Upload Texture */
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_px);
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_py);
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_pz);
- glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_nx);
- glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_ny);
- glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- 0,
- internalformat,
- tex->w,
- tex->h,
- 0,
- data_format,
- data_type,
- fpixels_nz);
+ if (d == 0) {
+ const char *pixels_px, *pixels_py, *pixels_pz, *pixels_nx, *pixels_ny, *pixels_nz;
+
+ if (pixels) {
+ size_t face_ofs = w * w * gpu_get_data_format_bytesize(tex->components, gpu_data_format);
+ pixels_px = (char *)pixels + 0 * face_ofs;
+ pixels_nx = (char *)pixels + 1 * face_ofs;
+ pixels_py = (char *)pixels + 2 * face_ofs;
+ pixels_ny = (char *)pixels + 3 * face_ofs;
+ pixels_pz = (char *)pixels + 4 * face_ofs;
+ pixels_nz = (char *)pixels + 5 * face_ofs;
+ }
+ else {
+ pixels_px = pixels_py = pixels_pz = pixels_nx = pixels_ny = pixels_nz = NULL;
+ }
+
+ GLuint face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_px);
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_nx);
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_py);
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_ny);
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_pz);
+ glTexImage2D(face++, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pixels_nz);
+ }
+ else {
+ glTexImage3D(tex->target,
+ 0,
+ internalformat,
+ tex->w,
+ tex->h,
+ tex->d * 6,
+ 0,
+ data_format,
+ data_type,
+ pixels);
+ }
/* Texture Parameters */
if (GPU_texture_stencil(tex) || /* Does not support filtering */
@@ -1131,33 +1143,16 @@ GPUTexture *GPU_texture_create_cube(int w,
char err_out[256])
{
BLI_assert(w > 0);
- const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz;
- const int channels = gpu_get_component_count(tex_format);
-
- if (fpixels) {
- int face_ofs = w * w * channels;
- fpixels_px = fpixels + 0 * face_ofs;
- fpixels_nx = fpixels + 1 * face_ofs;
- fpixels_py = fpixels + 2 * face_ofs;
- fpixels_ny = fpixels + 3 * face_ofs;
- fpixels_pz = fpixels + 4 * face_ofs;
- fpixels_nz = fpixels + 5 * face_ofs;
- }
- else {
- fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL;
- }
+ eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format);
+ return GPU_texture_cube_create(w, 0, fpixels, tex_format, data_format, err_out);
+}
- return GPU_texture_cube_create(w,
- 0,
- fpixels_px,
- fpixels_py,
- fpixels_pz,
- fpixels_nx,
- fpixels_ny,
- fpixels_nz,
- tex_format,
- GPU_DATA_FLOAT,
- err_out);
+GPUTexture *GPU_texture_create_cube_array(
+ int w, int d, eGPUTextureFormat tex_format, const float *fpixels, char err_out[256])
+{
+ BLI_assert(w > 0 && d > 0);
+ eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format);
+ return GPU_texture_cube_create(w, d, fpixels, tex_format, data_format, err_out);
}
GPUTexture *GPU_texture_create_from_vertbuf(GPUVertBuf *vert)
@@ -1297,6 +1292,7 @@ void GPU_texture_add_mipmap(GPUTexture *tex,
break;
case GL_TEXTURE_3D:
case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY_ARB:
glTexImage3D(tex->target,
miplvl,
internalformat,
@@ -1385,29 +1381,13 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int mipl
gpu_validate_data_format(tex->format, gpu_data_format);
- size_t buf_size = gpu_texture_memory_footprint_compute(tex);
size_t samples_count = max_ii(1, tex->samples);
-
samples_count *= size[0];
samples_count *= max_ii(1, size[1]);
samples_count *= max_ii(1, size[2]);
- samples_count *= (GPU_texture_cube(tex)) ? 6 : 1;
+ samples_count *= (GPU_texture_cube(tex) && !GPU_texture_array(tex)) ? 6 : 1;
- switch (gpu_data_format) {
- case GPU_DATA_FLOAT:
- buf_size = sizeof(float) * samples_count * tex->components;
- break;
- case GPU_DATA_INT:
- case GPU_DATA_UNSIGNED_INT:
- buf_size = sizeof(int) * samples_count * tex->components;
- break;
- case GPU_DATA_UNSIGNED_INT_24_8:
- case GPU_DATA_10_11_11_REV:
- buf_size = sizeof(int) * samples_count;
- break;
- case GPU_DATA_UNSIGNED_BYTE:
- break;
- }
+ size_t buf_size = samples_count * gpu_get_data_format_bytesize(tex->components, gpu_data_format);
/* AMD Pro driver have a bug that write 8 bytes past buffer size
* if the texture is big. (see T66573) */
@@ -1418,7 +1398,7 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int mipl
glBindTexture(tex->target, tex->bindcode);
- if (GPU_texture_cube(tex)) {
+ if (GPU_texture_cube(tex) && !GPU_texture_array(tex)) {
int cube_face_size = buf_size / 6;
for (int i = 0; i < 6; i++) {
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
@@ -1763,6 +1743,11 @@ int GPU_texture_samples(const GPUTexture *tex)
return tex->samples;
}
+bool GPU_texture_array(const GPUTexture *tex)
+{
+ return (tex->format_flag & GPU_FORMAT_ARRAY) != 0;
+}
+
bool GPU_texture_depth(const GPUTexture *tex)
{
return (tex->format_flag & GPU_FORMAT_DEPTH) != 0;
@@ -1828,8 +1813,12 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
size[1] = max_ii(1, tex->h / div);
}
- if (tex->target == GL_TEXTURE_2D_ARRAY) {
+ if (GPU_texture_array(tex)) {
size[2] = tex->d;
+ /* Return the number of face layers. */
+ if (GPU_texture_cube(tex)) {
+ size[2] *= 6;
+ }
}
else if (tex->d > 0) {
size[2] = max_ii(1, tex->d / div);