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:
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c24
-rw-r--r--source/blender/gpu/intern/gpu_draw.c185
-rw-r--r--source/blender/gpu/intern/gpu_draw_smoke.c112
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c12
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c8
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c4
-rw-r--r--source/blender/gpu/intern/gpu_material.c34
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c69
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h8
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c1
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c7
-rw-r--r--source/blender/gpu/intern/gpu_shader.c6
-rw-r--r--source/blender/gpu/intern/gpu_state.c185
-rw-r--r--source/blender/gpu/intern/gpu_texture.c228
14 files changed, 506 insertions, 377 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 553ecb65529..bcaa95c2f59 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -269,15 +269,6 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_OBJECT_INFO) {
return "unfobjectinfo";
}
- else if (builtin == GPU_VOLUME_DENSITY) {
- return "sampdensity";
- }
- else if (builtin == GPU_VOLUME_FLAME) {
- return "sampflame";
- }
- else if (builtin == GPU_VOLUME_TEMPERATURE) {
- return "unftemperature";
- }
else if (builtin == GPU_BARYCENTRIC_TEXCO) {
return "unfbarycentrictex";
}
@@ -341,6 +332,11 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
}
}
+ /* Volume Grids */
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", grid->sampler_name);
+ }
+
/* Print other uniforms */
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -350,12 +346,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
builtins |= input->builtin;
name = gpu_builtin_name(input->builtin);
- if (BLI_str_startswith(name, "samp")) {
- if ((input->builtin == GPU_VOLUME_DENSITY) || (input->builtin == GPU_VOLUME_FLAME)) {
- BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
- }
- }
- else if (BLI_str_startswith(name, "unf")) {
+ if (BLI_str_startswith(name, "unf")) {
BLI_dynstr_appendf(ds, "uniform %s %s;\n", gpu_data_type_to_string(input->type), name);
}
else {
@@ -438,6 +429,9 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f
else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) {
BLI_dynstr_append(ds, input->texture->tiled_mapping_name);
}
+ else if (input->source == GPU_SOURCE_VOLUME_GRID) {
+ BLI_dynstr_append(ds, input->volume_grid->sampler_name);
+ }
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
ds, input->link->output->type, input->type, "tmp", input->link->output->id);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index d674f8600c2..33bc3ced5b2 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -861,6 +861,7 @@ static void gpu_texture_update_from_ibuf(
* available. It is also required when requesting the GPUTexture for a render result. */
GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, int textarget)
{
+#ifndef GPU_STANDALONE
if (ima == NULL) {
return NULL;
}
@@ -919,10 +920,13 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
GPU_texture_orig_size_set(*tex, ibuf_intern->x, ibuf_intern->y);
return *tex;
+#endif
+ return NULL;
}
GPUTexture *GPU_texture_from_movieclip(MovieClip *clip, MovieClipUser *cuser, int textarget)
{
+#ifndef GPU_STANDALONE
if (clip == NULL) {
return NULL;
}
@@ -945,6 +949,9 @@ GPUTexture *GPU_texture_from_movieclip(MovieClip *clip, MovieClipUser *cuser, in
*tex = GPU_texture_from_bindcode(textarget, bindcode);
return *tex;
+#else
+ return NULL;
+#endif
}
void GPU_free_texture_movieclip(struct MovieClip *clip)
@@ -1270,6 +1277,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima,
* re-uploaded to OpenGL */
void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
{
+#ifndef GPU_STANDALONE
if (!GTS.domipmap) {
return;
}
@@ -1321,10 +1329,12 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
}
}
}
+#endif /* GPU_STANDALONE */
}
void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
+#ifndef GPU_STANDALONE
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
@@ -1346,6 +1356,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
}
BKE_image_release_ibuf(ima, ibuf, NULL);
+#endif
}
static LinkNode *image_free_queue = NULL;
@@ -1526,177 +1537,3 @@ void GPU_state_init(void)
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
}
-
-/** \name Framebuffer color depth, for selection codes
- * \{ */
-
-#define STATE_STACK_DEPTH 16
-
-typedef struct {
- eGPUAttrMask mask;
-
- /* GL_ENABLE_BIT */
- uint is_blend : 1;
- uint is_cull_face : 1;
- uint is_depth_test : 1;
- uint is_dither : 1;
- uint is_lighting : 1;
- uint is_line_smooth : 1;
- uint is_color_logic_op : 1;
- uint is_multisample : 1;
- uint is_polygon_offset_line : 1;
- uint is_polygon_offset_fill : 1;
- uint is_polygon_smooth : 1;
- uint is_sample_alpha_to_coverage : 1;
- uint is_scissor_test : 1;
- uint is_stencil_test : 1;
-
- bool is_clip_plane[6];
-
- /* GL_DEPTH_BUFFER_BIT */
- /* uint is_depth_test : 1; */
- int depth_func;
- double depth_clear_value;
- bool depth_write_mask;
-
- /* GL_SCISSOR_BIT */
- int scissor_box[4];
- /* uint is_scissor_test : 1; */
-
- /* GL_VIEWPORT_BIT */
- int viewport[4];
- double near_far[2];
-} GPUAttrValues;
-
-typedef struct {
- GPUAttrValues attr_stack[STATE_STACK_DEPTH];
- uint top;
-} GPUAttrStack;
-
-static GPUAttrStack state = {
- .top = 0,
-};
-
-#define AttrStack state
-#define Attr state.attr_stack[state.top]
-
-/**
- * Replacement for glPush/PopAttributes
- *
- * We don't need to cover all the options of legacy OpenGL
- * but simply the ones used by Blender.
- */
-void gpuPushAttr(eGPUAttrMask mask)
-{
- Attr.mask = mask;
-
- if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- glGetIntegerv(GL_DEPTH_FUNC, &Attr.depth_func);
- glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attr.depth_clear_value);
- glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attr.depth_write_mask);
- }
-
- if ((mask & GPU_ENABLE_BIT) != 0) {
- Attr.is_blend = glIsEnabled(GL_BLEND);
-
- for (int i = 0; i < 6; i++) {
- Attr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
- }
-
- Attr.is_cull_face = glIsEnabled(GL_CULL_FACE);
- Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- Attr.is_dither = glIsEnabled(GL_DITHER);
- Attr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
- Attr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
- Attr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
- Attr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
- Attr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
- Attr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
- Attr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
- Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- Attr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
- }
-
- if ((mask & GPU_SCISSOR_BIT) != 0) {
- Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attr.scissor_box);
- }
-
- if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far);
- glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport);
- }
-
- if ((mask & GPU_BLEND_BIT) != 0) {
- Attr.is_blend = glIsEnabled(GL_BLEND);
- }
-
- BLI_assert(AttrStack.top < STATE_STACK_DEPTH);
- AttrStack.top++;
-}
-
-static void restore_mask(GLenum cap, const bool value)
-{
- if (value) {
- glEnable(cap);
- }
- else {
- glDisable(cap);
- }
-}
-
-void gpuPopAttr(void)
-{
- BLI_assert(AttrStack.top > 0);
- AttrStack.top--;
-
- GLint mask = Attr.mask;
-
- if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
- glDepthFunc(Attr.depth_func);
- glClearDepth(Attr.depth_clear_value);
- glDepthMask(Attr.depth_write_mask);
- }
-
- if ((mask & GPU_ENABLE_BIT) != 0) {
- restore_mask(GL_BLEND, Attr.is_blend);
-
- for (int i = 0; i < 6; i++) {
- restore_mask(GL_CLIP_PLANE0 + i, Attr.is_clip_plane[i]);
- }
-
- restore_mask(GL_CULL_FACE, Attr.is_cull_face);
- restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
- restore_mask(GL_DITHER, Attr.is_dither);
- restore_mask(GL_LINE_SMOOTH, Attr.is_line_smooth);
- restore_mask(GL_COLOR_LOGIC_OP, Attr.is_color_logic_op);
- restore_mask(GL_MULTISAMPLE, Attr.is_multisample);
- restore_mask(GL_POLYGON_OFFSET_LINE, Attr.is_polygon_offset_line);
- restore_mask(GL_POLYGON_OFFSET_FILL, Attr.is_polygon_offset_fill);
- restore_mask(GL_POLYGON_SMOOTH, Attr.is_polygon_smooth);
- restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attr.is_sample_alpha_to_coverage);
- restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
- restore_mask(GL_STENCIL_TEST, Attr.is_stencil_test);
- }
-
- if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]);
- glDepthRange(Attr.near_far[0], Attr.near_far[1]);
- }
-
- if ((mask & GPU_SCISSOR_BIT) != 0) {
- restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
- glScissor(Attr.scissor_box[0], Attr.scissor_box[1], Attr.scissor_box[2], Attr.scissor_box[3]);
- }
-
- if ((mask & GPU_BLEND_BIT) != 0) {
- restore_mask(GL_BLEND, Attr.is_blend);
- }
-}
-
-#undef Attr
-#undef AttrStack
-
-/** \} */
diff --git a/source/blender/gpu/intern/gpu_draw_smoke.c b/source/blender/gpu/intern/gpu_draw_smoke.c
index 5cca472148a..546faadbda4 100644
--- a/source/blender/gpu/intern/gpu_draw_smoke.c
+++ b/source/blender/gpu/intern/gpu_draw_smoke.c
@@ -122,13 +122,12 @@ static GPUTexture *create_transfer_function(int type, const struct ColorBand *co
return tex;
}
-static void swizzle_texture_channel_rrrr(GPUTexture *tex)
+static void swizzle_texture_channel_single(GPUTexture *tex)
{
+ /* Swizzle texture channels so that we get useful RGBA values when sampling
+ * a texture with fewer channels, e.g. when using density as color. */
GPU_texture_bind(tex, 0);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_swizzle_channel_auto(tex, 1);
GPU_texture_unbind(tex);
}
@@ -186,60 +185,59 @@ static GPUTexture *create_field_texture(FluidDomainSettings *mds)
GPUTexture *tex = GPU_texture_create_nD(
mds->res[0], mds->res[1], mds->res[2], 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
- swizzle_texture_channel_rrrr(tex);
+ swizzle_texture_channel_single(tex);
return tex;
}
static GPUTexture *create_density_texture(FluidDomainSettings *mds, int highres)
{
- float *data = NULL, *source;
- int cell_count = (highres) ? manta_smoke_turbulence_get_cells(mds->fluid) : mds->total_cells;
+ int *dim = (highres) ? mds->res_noise : mds->res;
+
+ float *data;
+ if (highres) {
+ data = manta_smoke_turbulence_get_density(mds->fluid);
+ }
+ else {
+ data = manta_smoke_get_density(mds->fluid);
+ }
+
+ GPUTexture *tex = GPU_texture_create_nD(
+ dim[0], dim[1], dim[2], 3, data, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
+
+ swizzle_texture_channel_single(tex);
+
+ return tex;
+}
+
+static GPUTexture *create_color_texture(FluidDomainSettings *mds, int highres)
+{
const bool has_color = (highres) ? manta_smoke_turbulence_has_colors(mds->fluid) :
manta_smoke_has_colors(mds->fluid);
+
+ if (!has_color) {
+ return NULL;
+ }
+
+ int cell_count = (highres) ? manta_smoke_turbulence_get_cells(mds->fluid) : mds->total_cells;
int *dim = (highres) ? mds->res_noise : mds->res;
- eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8;
+ float *data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
- if (has_color) {
- data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
+ if (data == NULL) {
+ return NULL;
}
if (highres) {
- if (has_color) {
- manta_smoke_turbulence_get_rgba(mds->fluid, data, 0);
- }
- else {
- source = manta_smoke_turbulence_get_density(mds->fluid);
- }
+ manta_smoke_turbulence_get_rgba(mds->fluid, data, 0);
}
else {
- if (has_color) {
- manta_smoke_get_rgba(mds->fluid, data, 0);
- }
- else {
- source = manta_smoke_get_density(mds->fluid);
- }
+ manta_smoke_get_rgba(mds->fluid, data, 0);
}
- GPUTexture *tex = GPU_texture_create_nD(dim[0],
- dim[1],
- dim[2],
- 3,
- (has_color) ? data : source,
- format,
- GPU_DATA_FLOAT,
- 0,
- true,
- NULL);
- if (data) {
- MEM_freeN(data);
- }
+ GPUTexture *tex = GPU_texture_create_nD(
+ dim[0], dim[1], dim[2], 3, data, GPU_RGBA8, GPU_DATA_FLOAT, 0, true, NULL);
+
+ MEM_freeN(data);
- if (format == GPU_R8) {
- /* Swizzle the RGBA components to read the Red channel so
- * that the shader stay the same for colored and non color
- * density textures. */
- swizzle_texture_channel_rrrr(tex);
- }
return tex;
}
@@ -264,7 +262,7 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *mds, int highres)
GPUTexture *tex = GPU_texture_create_nD(
dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
- swizzle_texture_channel_rrrr(tex);
+ swizzle_texture_channel_single(tex);
return tex;
}
@@ -280,35 +278,40 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *mds, int highres)
void GPU_free_smoke(FluidModifierData *mmd)
{
if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
- if (mmd->domain->tex) {
- GPU_texture_free(mmd->domain->tex);
+ if (mmd->domain->tex_density) {
+ GPU_texture_free(mmd->domain->tex_density);
+ mmd->domain->tex_density = NULL;
+ }
+
+ if (mmd->domain->tex_color) {
+ GPU_texture_free(mmd->domain->tex_color);
+ mmd->domain->tex_color = NULL;
}
- mmd->domain->tex = NULL;
if (mmd->domain->tex_shadow) {
GPU_texture_free(mmd->domain->tex_shadow);
+ mmd->domain->tex_shadow = NULL;
}
- mmd->domain->tex_shadow = NULL;
if (mmd->domain->tex_flame) {
GPU_texture_free(mmd->domain->tex_flame);
+ mmd->domain->tex_flame = NULL;
}
- mmd->domain->tex_flame = NULL;
if (mmd->domain->tex_flame_coba) {
GPU_texture_free(mmd->domain->tex_flame_coba);
+ mmd->domain->tex_flame_coba = NULL;
}
- mmd->domain->tex_flame_coba = NULL;
if (mmd->domain->tex_coba) {
GPU_texture_free(mmd->domain->tex_coba);
+ mmd->domain->tex_coba = NULL;
}
- mmd->domain->tex_coba = NULL;
if (mmd->domain->tex_field) {
GPU_texture_free(mmd->domain->tex_field);
+ mmd->domain->tex_field = NULL;
}
- mmd->domain->tex_field = NULL;
}
}
@@ -338,8 +341,11 @@ void GPU_create_smoke(FluidModifierData *mmd, int highres)
if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
FluidDomainSettings *mds = mmd->domain;
- if (!mds->tex) {
- mds->tex = create_density_texture(mds, highres);
+ if (!mds->tex_density) {
+ mds->tex_density = create_density_texture(mds, highres);
+ }
+ if (!mds->tex_color) {
+ mds->tex_color = create_color_texture(mds, highres);
}
if (!mds->tex_flame) {
mds->tex_flame = create_flame_texture(mds, highres);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 4676cc3b244..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) {
@@ -348,7 +356,11 @@ void gpu_extensions_exit(void)
bool GPU_mem_stats_supported(void)
{
+#ifndef GPU_STANDALONE
return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
+#else
+ return false;
+#endif
}
void GPU_mem_stats_get(int *totalmem, int *freemem)
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index bd3de96d636..671335ca702 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -23,7 +23,9 @@
* GPU immediate mode work-alike
*/
-#include "UI_resources.h"
+#ifndef GPU_STANDALONE
+# include "UI_resources.h"
+#endif
#include "GPU_attr_binding.h"
#include "GPU_immediate.h"
@@ -910,6 +912,8 @@ void immUniformColor4ubv(const uchar rgba[4])
immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]);
}
+#ifndef GPU_STANDALONE
+
void immUniformThemeColor(int color_id)
{
float color[4];
@@ -958,3 +962,5 @@ void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col);
immUniformColor4ub(col[0], col[1], col[2], col[3]);
}
+
+#endif /* GPU_STANDALONE */
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index c99b7fc8a67..96dc437e10b 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -64,12 +64,16 @@ void GPU_init(void)
immInit();
}
+#ifndef GPU_STANDALONE
gpu_pbvh_init();
+#endif
}
void GPU_exit(void)
{
+#ifndef GPU_STANDALONE
gpu_pbvh_exit();
+#endif
if (!G.background) {
immDestroy();
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index b2658839d67..8a4a88d0663 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -70,6 +70,7 @@ struct GPUMaterial {
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
+ bool is_volume_shader; /* is volumetric shader */
/* Nodes */
GPUNodeGraph graph;
@@ -80,7 +81,8 @@ struct GPUMaterial {
/* XXX: Should be in Material. But it depends on the output node
* used and since the output selection is different for GPUMaterial...
*/
- int domain;
+ bool has_volume_output;
+ bool has_surface_output;
/* Only used by Eevee to know which bsdf are used. */
int flag;
@@ -109,8 +111,8 @@ struct GPUMaterial {
};
enum {
- GPU_DOMAIN_SURFACE = (1 << 0),
- GPU_DOMAIN_VOLUME = (1 << 1),
+ GPU_USE_SURFACE_OUTPUT = (1 << 0),
+ GPU_USE_VOLUME_OUTPUT = (1 << 1),
};
/* Functions */
@@ -567,6 +569,11 @@ ListBase GPU_material_textures(GPUMaterial *material)
return material->graph.textures;
}
+ListBase GPU_material_volume_grids(GPUMaterial *material)
+{
+ return material->graph.volume_grids;
+}
+
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
if (!material->graph.outlink) {
@@ -592,14 +599,19 @@ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
/* Code generation */
-bool GPU_material_use_domain_surface(GPUMaterial *mat)
+bool GPU_material_has_surface_output(GPUMaterial *mat)
+{
+ return mat->has_surface_output;
+}
+
+bool GPU_material_has_volume_output(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_SURFACE);
+ return mat->has_volume_output;
}
-bool GPU_material_use_domain_volume(GPUMaterial *mat)
+bool GPU_material_is_volume_shader(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_VOLUME);
+ return mat->is_volume_shader;
}
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag)
@@ -636,7 +648,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
struct bNodeTree *ntree,
ListBase *gpumaterials,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -655,6 +668,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
+ mat->is_volume_shader = is_volume_shader;
#ifndef NDEBUG
BLI_snprintf(mat->name, sizeof(mat->name), "%s", name);
#else
@@ -670,8 +684,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
gpu_material_ramp_texture_build(mat);
- SET_FLAG_FROM_TEST(mat->domain, has_surface_output, GPU_DOMAIN_SURFACE);
- SET_FLAG_FROM_TEST(mat->domain, has_volume_output, GPU_DOMAIN_VOLUME);
+ mat->has_surface_output = has_surface_output;
+ mat->has_volume_output = has_volume_output;
if (mat->graph.outlink) {
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index de35b43109f..0d5cc46c0b9 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -119,6 +119,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_TEX_TILED_MAPPING;
input->texture = link->texture;
break;
+ case GPU_NODE_LINK_VOLUME_GRID:
+ input->source = GPU_SOURCE_VOLUME_GRID;
+ input->volume_grid = link->volume_grid;
+ break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
input->attr = link->attr;
@@ -321,6 +325,31 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
return tex;
}
+static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
+{
+ /* Find existing volume grid. */
+ int num_grids = 0;
+ GPUMaterialVolumeGrid *grid = graph->volume_grids.first;
+ for (; grid; grid = grid->next) {
+ if (STREQ(grid->name, name)) {
+ break;
+ }
+ num_grids++;
+ }
+
+ /* Add new requested volume grid. */
+ if (grid == NULL) {
+ grid = MEM_callocN(sizeof(*grid), __func__);
+ grid->name = BLI_strdup(name);
+ BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
+ BLI_addtail(&graph->volume_grids, grid);
+ }
+
+ grid->users++;
+
+ return grid;
+}
+
/* Creating Inputs */
GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name)
@@ -394,6 +423,30 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
return link;
}
+GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
+{
+ /* NOTE: this could be optimized by automatically merging duplicate
+ * lookups of the same attribute. */
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_VOLUME_GRID;
+ link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
+
+ /* Two special cases, where we adjust the output values of smoke grids to
+ * bring the into standard range without having to modify the grid values. */
+ if (strcmp(name, "color") == 0) {
+ GPU_link(mat, "node_attribute_volume_color", link, &link);
+ }
+ else if (strcmp(name, "temperature") == 0) {
+ GPU_link(mat, "node_attribute_volume_temperature", link, &link);
+ }
+ else {
+ GPU_link(mat, "node_attribute_volume", link, &link);
+ }
+
+ return link;
+}
+
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
{
GPUNodeLink *link = gpu_node_link_create();
@@ -537,6 +590,9 @@ static void gpu_inputs_free(ListBase *inputs)
else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
input->texture->users--;
}
+ else if (ELEM(input->source, GPU_SOURCE_VOLUME_GRID)) {
+ input->volume_grid->users--;
+ }
if (input->link) {
gpu_node_link_free(input->link);
@@ -579,6 +635,11 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
+
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ MEM_SAFE_FREE(grid->name);
+ }
+ BLI_freelistN(&graph->volume_grids);
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
}
@@ -637,4 +698,12 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
BLI_freelinkN(&graph->textures, tex);
}
}
+
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first, *next = NULL; grid; grid = next) {
+ next = grid->next;
+ if (grid->users == 0) {
+ MEM_SAFE_FREE(grid->name);
+ BLI_freelinkN(&graph->volume_grids, grid);
+ }
+ }
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 9214bd7f1ba..ceaeea2bfa8 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -48,6 +48,8 @@ typedef enum eGPUDataSource {
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
GPU_SOURCE_TEX_TILED_MAPPING,
+ GPU_SOURCE_VOLUME_GRID,
+ GPU_SOURCE_VOLUME_GRID_TRANSFORM,
} eGPUDataSource;
typedef enum {
@@ -59,6 +61,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE,
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
+ GPU_NODE_LINK_VOLUME_GRID,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@@ -88,6 +91,8 @@ struct GPUNodeLink {
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
struct GPUTexture **colorband;
+ /* GPU_NODE_LINK_VOLUME_GRID */
+ struct GPUMaterialVolumeGrid *volume_grid;
/* GPU_NODE_LINK_OUTPUT */
struct GPUOutput *output;
/* GPU_NODE_LINK_ATTR */
@@ -126,6 +131,8 @@ typedef struct GPUInput {
struct GPUMaterialTexture *texture;
/* GPU_SOURCE_ATTR */
struct GPUMaterialAttribute *attr;
+ /* GPU_SOURCE_VOLUME_GRID */
+ struct GPUMaterialVolumeGrid *volume_grid;
};
} GPUInput;
@@ -139,6 +146,7 @@ typedef struct GPUNodeGraph {
/* Requested attributes and textures. */
ListBase attributes;
ListBase textures;
+ ListBase volume_grids;
} GPUNodeGraph;
/* Node Graph */
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 1fb83b628e1..498de13e10f 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -30,6 +30,7 @@
#include "GPU_immediate.h"
#include "GPU_draw.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 6e8b062cff0..578546f3af9 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -26,9 +26,8 @@
#include <stdlib.h>
-#include "GPU_immediate.h"
-#include "GPU_draw.h"
#include "GPU_select.h"
+#include "GPU_state.h"
#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
@@ -37,10 +36,6 @@
#include "BLI_utildefines.h"
-#include "PIL_time.h"
-
-#include "BKE_global.h"
-
#include "gpu_select_private.h"
/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
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_state.c b/source/blender/gpu/intern/gpu_state.c
index caf97a620ab..9ff518aec1b 100644
--- a/source/blender/gpu/intern/gpu_state.c
+++ b/source/blender/gpu/intern/gpu_state.c
@@ -18,7 +18,12 @@
* \ingroup gpu
*/
-#include "DNA_userdef_types.h"
+#ifndef GPU_STANDALONE
+# include "DNA_userdef_types.h"
+# define PIXELSIZE (U.pixelsize)
+#else
+# define PIXELSIZE (1.0f)
+#endif
#include "BLI_utildefines.h"
@@ -107,7 +112,7 @@ void GPU_line_smooth(bool enable)
void GPU_line_width(float width)
{
float max_size = GPU_max_line_width();
- float final_size = width * U.pixelsize;
+ float final_size = width * PIXELSIZE;
/* Fix opengl errors on certain platform / drivers. */
CLAMP(final_size, 1.0f, max_size);
glLineWidth(final_size);
@@ -115,7 +120,7 @@ void GPU_line_width(float width)
void GPU_point_size(float size)
{
- glPointSize(size * U.pixelsize);
+ glPointSize(size * PIXELSIZE);
}
void GPU_polygon_smooth(bool enable)
@@ -189,3 +194,177 @@ void GPU_logic_op_invert_set(bool enable)
glEnable(GL_DITHER);
}
}
+
+/** \name GPU Push/Pop State
+ * \{ */
+
+#define STATE_STACK_DEPTH 16
+
+typedef struct {
+ eGPUAttrMask mask;
+
+ /* GL_ENABLE_BIT */
+ uint is_blend : 1;
+ uint is_cull_face : 1;
+ uint is_depth_test : 1;
+ uint is_dither : 1;
+ uint is_lighting : 1;
+ uint is_line_smooth : 1;
+ uint is_color_logic_op : 1;
+ uint is_multisample : 1;
+ uint is_polygon_offset_line : 1;
+ uint is_polygon_offset_fill : 1;
+ uint is_polygon_smooth : 1;
+ uint is_sample_alpha_to_coverage : 1;
+ uint is_scissor_test : 1;
+ uint is_stencil_test : 1;
+
+ bool is_clip_plane[6];
+
+ /* GL_DEPTH_BUFFER_BIT */
+ /* uint is_depth_test : 1; */
+ int depth_func;
+ double depth_clear_value;
+ bool depth_write_mask;
+
+ /* GL_SCISSOR_BIT */
+ int scissor_box[4];
+ /* uint is_scissor_test : 1; */
+
+ /* GL_VIEWPORT_BIT */
+ int viewport[4];
+ double near_far[2];
+} GPUAttrValues;
+
+typedef struct {
+ GPUAttrValues attr_stack[STATE_STACK_DEPTH];
+ uint top;
+} GPUAttrStack;
+
+static GPUAttrStack state = {
+ .top = 0,
+};
+
+#define AttrStack state
+#define Attr state.attr_stack[state.top]
+
+/**
+ * Replacement for glPush/PopAttributes
+ *
+ * We don't need to cover all the options of legacy OpenGL
+ * but simply the ones used by Blender.
+ */
+void gpuPushAttr(eGPUAttrMask mask)
+{
+ Attr.mask = mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_FUNC, &Attr.depth_func);
+ glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attr.depth_clear_value);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attr.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ Attr.is_blend = glIsEnabled(GL_BLEND);
+
+ for (int i = 0; i < 6; i++) {
+ Attr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
+ }
+
+ Attr.is_cull_face = glIsEnabled(GL_CULL_FACE);
+ Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ Attr.is_dither = glIsEnabled(GL_DITHER);
+ Attr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
+ Attr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
+ Attr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
+ Attr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
+ Attr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
+ Attr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
+ Attr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ Attr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attr.scissor_box);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ Attr.is_blend = glIsEnabled(GL_BLEND);
+ }
+
+ BLI_assert(AttrStack.top < STATE_STACK_DEPTH);
+ AttrStack.top++;
+}
+
+static void restore_mask(GLenum cap, const bool value)
+{
+ if (value) {
+ glEnable(cap);
+ }
+ else {
+ glDisable(cap);
+ }
+}
+
+void gpuPopAttr(void)
+{
+ BLI_assert(AttrStack.top > 0);
+ AttrStack.top--;
+
+ GLint mask = Attr.mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
+ glDepthFunc(Attr.depth_func);
+ glClearDepth(Attr.depth_clear_value);
+ glDepthMask(Attr.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ restore_mask(GL_BLEND, Attr.is_blend);
+
+ for (int i = 0; i < 6; i++) {
+ restore_mask(GL_CLIP_PLANE0 + i, Attr.is_clip_plane[i]);
+ }
+
+ restore_mask(GL_CULL_FACE, Attr.is_cull_face);
+ restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
+ restore_mask(GL_DITHER, Attr.is_dither);
+ restore_mask(GL_LINE_SMOOTH, Attr.is_line_smooth);
+ restore_mask(GL_COLOR_LOGIC_OP, Attr.is_color_logic_op);
+ restore_mask(GL_MULTISAMPLE, Attr.is_multisample);
+ restore_mask(GL_POLYGON_OFFSET_LINE, Attr.is_polygon_offset_line);
+ restore_mask(GL_POLYGON_OFFSET_FILL, Attr.is_polygon_offset_fill);
+ restore_mask(GL_POLYGON_SMOOTH, Attr.is_polygon_smooth);
+ restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attr.is_sample_alpha_to_coverage);
+ restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
+ restore_mask(GL_STENCIL_TEST, Attr.is_stencil_test);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]);
+ glDepthRange(Attr.near_far[0], Attr.near_far[1]);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
+ glScissor(Attr.scissor_box[0], Attr.scissor_box[1], Attr.scissor_box[2], Attr.scissor_box[3]);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ restore_mask(GL_BLEND, Attr.is_blend);
+ }
+}
+
+#undef Attr
+#undef AttrStack
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 9ef42592b55..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,
@@ -1648,6 +1628,17 @@ void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
}
}
+void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
+{
+ WARN_NOT_BOUND(tex);
+
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, (channels >= 2) ? GL_GREEN : GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, (channels >= 3) ? GL_BLUE : GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
+}
+
static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
{
switch (filter) {
@@ -1752,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;
@@ -1817,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);