diff options
author | Julian Eisel <julian@blender.org> | 2020-03-16 20:15:33 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-03-16 20:15:33 +0300 |
commit | 5c1ac85ba5b8bd8ea1694a84f7c724da3a887814 (patch) | |
tree | 96edf1331740fb3abbeba5f7a0e993ea5a9fdaa4 /source/blender/gpu/intern | |
parent | d16897eb2ec0764e409bfbe96dfbf843c2e698b2 (diff) | |
parent | a75a79272e4e24f97bdd279ab281028dbfc395a1 (diff) |
Merge branch 'soc-2019-openxr' into vr_scene_inspection
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 10 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 24 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 256 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw_smoke.c | 112 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_extensions.c | 12 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_immediate.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_init_exit.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 34 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_node_graph.c | 69 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_node_graph.h | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_pick.c | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_sample_query.c | 7 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_state.c | 185 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 228 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 2 |
16 files changed, 552 insertions, 414 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 5eae86e50f0..f21cd990a41 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -189,15 +189,17 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) * \{ */ /* Returns the Face Set random color for rendering in the overlay given its ID and a color seed. */ +#define GOLDEN_RATIO_CONJUGATE 0.618033988749895f static void face_set_overlay_color_get(const int face_set, const int seed, uchar *r_color) { float rgba[4]; - const float random_mod_hue = BLI_hash_int_01(abs(face_set) + seed); + float random_mod_hue = GOLDEN_RATIO_CONJUGATE * (abs(face_set) + (seed % 10)); + random_mod_hue = random_mod_hue - floorf(random_mod_hue); const float random_mod_sat = BLI_hash_int_01(abs(face_set) + seed + 1); const float random_mod_val = BLI_hash_int_01(abs(face_set) + seed + 2); hsv_to_rgb(random_mod_hue, - 0.45f + (random_mod_sat * 0.35f), - 1.0f - (random_mod_val * 0.45f), + 0.6f + (random_mod_sat * 0.25f), + 1.0f - (random_mod_val * 0.35f), &rgba[0], &rgba[1], &rgba[2]); @@ -264,8 +266,8 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, } /* Face Sets. */ - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; for (uint i = 0; i < buffers->face_indices_len; i++) { + uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; if (show_face_sets) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; const int fset = abs(sculpt_face_sets[lt->poly]); 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..348b9dddba9 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -180,27 +180,28 @@ float GPU_get_anisotropic(void) /* Set OpenGL state for an MTFace */ -static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) +static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget, const int multiview_eye) { if (textarget == GL_TEXTURE_2D) { - return &ima->gputexture[TEXTARGET_TEXTURE_2D]; + return &(ima->gputexture[TEXTARGET_TEXTURE_2D][multiview_eye]); } else if (textarget == GL_TEXTURE_CUBE_MAP) { - return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; + return &(ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP][multiview_eye]); } else if (textarget == GL_TEXTURE_2D_ARRAY) { - return &ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY]; + return &(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][multiview_eye]); } else if (textarget == GL_TEXTURE_1D_ARRAY) { - return &ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING]; + return &(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][multiview_eye]); } return NULL; } -static uint gpu_texture_create_tile_mapping(Image *ima) +static uint gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye) { - GPUTexture *tilearray = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY]; + GPUTexture *tilearray = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][multiview_eye]; + if (tilearray == NULL) { return 0; } @@ -861,6 +862,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; } @@ -875,7 +877,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, BKE_image_tag_time(ima); /* Test if we already have a texture. */ - GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); + GPUTexture **tex = gpu_get_image_gputexture(ima, textarget, iuser->multiview_eye); if (*tex) { return *tex; } @@ -903,7 +905,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, bindcode = gpu_texture_create_tile_array(ima, ibuf_intern); } else if (textarget == GL_TEXTURE_1D_ARRAY) { - bindcode = gpu_texture_create_tile_mapping(ima); + bindcode = gpu_texture_create_tile_mapping(ima, iuser->multiview_eye); } else { bindcode = gpu_texture_create_from_ibuf(ima, ibuf_intern, textarget); @@ -919,10 +921,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 +950,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 +1278,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; } @@ -1280,14 +1289,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { if (BKE_image_has_opengl_texture(ima)) { if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) { - for (int a = 0; a < TEXTARGET_COUNT; a++) { - if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) { - GPUTexture *tex = ima->gputexture[a]; - if (tex != NULL) { - GPU_texture_bind(tex, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - GPU_texture_unbind(tex); + for (int eye = 0; eye < 2; eye++) { + for (int a = 0; a < TEXTARGET_COUNT; a++) { + if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) { + GPUTexture *tex = ima->gputexture[a][eye]; + if (tex != NULL) { + GPU_texture_bind(tex, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(tex); + } } } } @@ -1304,14 +1315,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) else { for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { if (BKE_image_has_opengl_texture(ima)) { - for (int a = 0; a < TEXTARGET_COUNT; a++) { - if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) { - GPUTexture *tex = ima->gputexture[a]; - if (tex != NULL) { - GPU_texture_bind(tex, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - GPU_texture_unbind(tex); + for (int eye = 0; eye < 2; eye++) { + for (int a = 0; a < TEXTARGET_COUNT; a++) { + if (ELEM(a, TEXTARGET_TEXTURE_2D, TEXTARGET_TEXTURE_2D_ARRAY)) { + GPUTexture *tex = ima->gputexture[a][eye]; + if (tex != NULL) { + GPU_texture_bind(tex, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(tex); + } } } } @@ -1321,10 +1334,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); @@ -1333,19 +1348,20 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i GPU_free_image(ima); } - GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D]; + GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D][0]; /* Check if we need to update the main gputexture. */ if (tex != NULL && tile == ima->tiles.first) { gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h); } /* Check if we need to update the array gputexture. */ - tex = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY]; + tex = ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][0]; if (tex != NULL) { gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h); } BKE_image_release_ibuf(ima, ibuf, NULL); +#endif } static LinkNode *image_free_queue = NULL; @@ -1384,11 +1400,13 @@ void GPU_free_unused_buffers(Main *bmain) static void gpu_free_image_immediate(Image *ima) { - for (int i = 0; i < TEXTARGET_COUNT; i++) { - /* free glsl image binding */ - if (ima->gputexture[i] != NULL) { - GPU_texture_free(ima->gputexture[i]); - ima->gputexture[i] = NULL; + for (int eye = 0; eye < 2; eye++) { + for (int i = 0; i < TEXTARGET_COUNT; i++) { + /* free glsl image binding */ + if (ima->gputexture[i][eye] != NULL) { + GPU_texture_free(ima->gputexture[i][eye]); + ima->gputexture[i][eye] = NULL; + } } } @@ -1526,177 +1544,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); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 5b753416f24..e4fd5d3f122 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -688,7 +688,7 @@ static void gpu_viewport_storage_free(StorageList *stl, int stl_len) static void gpu_viewport_passes_free(PassList *psl, int psl_len) { - memset(psl, 0, sizeof(struct DRWPass *) * psl_len); + memset(psl->passes, 0, sizeof(*psl->passes) * psl_len); } /* Must be executed inside Drawmanager Opengl Context. */ |