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:
authorLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
commit7e1832c8d546ec13e752b7bd42ce13e3fc10ae86 (patch)
tree0fff9d878db69b288f909ff9a0f8aefe31ab8d80 /source/blender/gpu
parentc0c8df3f2cf3ab03cec1f660619b0fe2290caf2a (diff)
parent94959dba1b53640e2a36cf9b5ca46aaf49c5c74a (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt29
-rw-r--r--source/blender/gpu/GPU_batch.h6
-rw-r--r--source/blender/gpu/GPU_compositing.h106
-rw-r--r--source/blender/gpu/GPU_draw.h9
-rw-r--r--source/blender/gpu/GPU_extensions.h1
-rw-r--r--source/blender/gpu/GPU_framebuffer.h147
-rw-r--r--source/blender/gpu/GPU_material.h22
-rw-r--r--source/blender/gpu/GPU_select.h1
-rw-r--r--source/blender/gpu/GPU_shader.h19
-rw-r--r--source/blender/gpu/GPU_texture.h12
-rw-r--r--source/blender/gpu/GPU_viewport.h16
-rw-r--r--source/blender/gpu/intern/gpu_batch.c2
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c74
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c140
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c268
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h25
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c1494
-rw-r--r--source/blender/gpu/intern/gpu_draw.c128
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c10
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c938
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c115
-rw-r--r--source/blender/gpu/intern/gpu_material.c85
-rw-r--r--source/blender/gpu/intern/gpu_select.c12
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c112
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c40
-rw-r--r--source/blender/gpu/intern/gpu_shader.c196
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_texture.c295
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c406
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl48
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl107
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl186
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl64
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl)4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl205
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl61
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_geom.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl19
50 files changed, 2467 insertions, 3177 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 0ac842d90a0..bf0e6ea3368 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -55,7 +55,6 @@ set(SRC
intern/gpu_batch_presets.c
intern/gpu_buffers.c
intern/gpu_codegen.c
- intern/gpu_compositing.c
intern/gpu_debug.c
intern/gpu_draw.c
intern/gpu_extensions.c
@@ -81,7 +80,6 @@ set(SRC
shaders/gpu_shader_fx_dof_hq_frag.glsl
shaders/gpu_shader_fx_dof_hq_vert.glsl
shaders/gpu_shader_fx_dof_hq_geo.glsl
- shaders/gpu_shader_fullscreen_vert.glsl
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -99,7 +97,6 @@ set(SRC
GPU_basic_shader.h
GPU_batch.h
GPU_buffers.h
- GPU_compositing.h
GPU_debug.h
GPU_draw.h
GPU_extensions.h
@@ -135,6 +132,12 @@ data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
@@ -142,14 +145,18 @@ data_to_c_simple(shaders/gpu_shader_2D_line_dashed_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
@@ -174,7 +181,7 @@ data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_instance_mball_helpers_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_mball_handles_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
@@ -202,7 +209,10 @@ data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
@@ -221,15 +231,6 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fullscreen_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index d2f3409dc07..760faeff7b1 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -32,6 +32,7 @@
#define __GPU_BATCH_H__
#include "../../../intern/gawain/gawain/gwn_batch.h"
+#include "../../../intern/gawain/gawain/gwn_batch_private.h"
struct rctf;
@@ -39,6 +40,7 @@ struct rctf;
// #include "gawain/batch.h"
#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
#include "GPU_shader.h"
@@ -58,11 +60,15 @@ void gpu_batch_init(void);
void gpu_batch_exit(void);
/* gpu_batch_presets.c */
+/* Only use by draw manager. Use the presets function instead for interface. */
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT;
/* Replacement for gluSphere */
Gwn_Batch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
void gpu_batch_presets_init(void);
+void gpu_batch_presets_register(Gwn_Batch *preset_batch);
+void gpu_batch_presets_reset(void);
void gpu_batch_presets_exit(void);
#endif /* __GPU_BATCH_H__ */
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
deleted file mode 100644
index d506d91a9aa..00000000000
--- a/source/blender/gpu/GPU_compositing.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file GPU_compositing.h
- * \ingroup gpu
- */
-
-#ifndef __GPU_COMPOSITING_H__
-#define __GPU_COMPOSITING_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
-typedef struct GPUFX GPUFX;
-struct GPUDOFSettings;
-struct GPUSSAOSettings;
-struct GPUOffScreen;
-struct GPUFXSettings;
-struct rcti;
-struct Scene;
-struct GPUShader;
-enum eGPUFXFlags;
-
-/**** Public API *****/
-
-typedef enum GPUFXShaderEffect {
- /* Screen space ambient occlusion shader */
- GPU_SHADER_FX_SSAO = 1,
-
- /* depth of field passes. Yep, quite a complex effect */
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
-
- /* high quality */
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9,
-
- GPU_SHADER_FX_DEPTH_RESOLVE = 10,
-} GPUFXShaderEffect;
-
-/* keep in synch with enum above! */
-#define MAX_FX_SHADERS 11
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void);
-
-/* destroy a text compositor */
-void GPU_fx_compositor_destroy(GPUFX *fx);
-
-/* initialize a framebuffer with size taken from the viewport */
-bool GPU_fx_compositor_initialize_passes(
- GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
- const struct GPUFXSettings *fx_settings);
-
-/* do compositing on the fx passes that have been initialized */
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs);
-
-/* bind new depth buffer for XRay pass */
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray);
-
-/* resolve a final depth buffer by compositing the XRay and normal depth buffers */
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
-
-void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
-void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
-
-
-/* initialize and cache the shader unform interface for effects */
-void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect);
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __GPU_COMPOSITING_H__
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 8d29632fc71..9bbf46b2a1f 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -47,6 +47,8 @@ struct RegionView3D;
struct SmokeModifierData;
struct DupliObject;
+#include "DNA_object_enums.h"
+
/* OpenGL drawing functions related to shading. These are also
* shared with the game engine, where there were previously
* duplicates of some of these functions. */
@@ -73,9 +75,10 @@ void GPU_disable_program_point_size(void);
* GPU_object_material_bind returns 0 if drawing should be skipped
* - after drawing, the material must be disabled again */
-void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct ViewLayer *view_layer,
- struct Object *ob, bool glsl, bool *do_alpha_after);
+void GPU_begin_object_materials(
+ struct View3D *v3d, struct RegionView3D *rv3d,
+ struct Scene *scene, struct ViewLayer *view_layer,
+ struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
bool GPU_object_materials_check(void);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index d860431b04f..d36b0ea15be 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -64,7 +64,6 @@ typedef enum GPUDeviceType {
GPU_DEVICE_INTEL = (1 << 2),
GPU_DEVICE_SOFTWARE = (1 << 3),
GPU_DEVICE_UNKNOWN = (1 << 4),
- GPU_DEVICE_AMD_VEGA = (1 << 5),
GPU_DEVICE_ANY = (0xff)
} GPUDeviceType;
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index c58d98c201e..0ab15a4ea47 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -36,61 +36,158 @@
extern "C" {
#endif
+struct GPUTexture;
+
+typedef struct GPUAttachment {
+ struct GPUTexture *tex;
+ int mip, layer;
+} GPUAttachment;
+
+typedef enum GPUFrameBufferBits{
+ GPU_COLOR_BIT = (1 << 0),
+ GPU_DEPTH_BIT = (1 << 1),
+ GPU_STENCIL_BIT = (1 << 2),
+} GPUFrameBufferBits;
+
typedef struct GPUFrameBuffer GPUFrameBuffer;
typedef struct GPUOffScreen GPUOffScreen;
-struct GPUTexture;
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
* multiple FBO's may be created, to get around limitations on the number
* of attached textures and the dimension requirements.
- * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
- * be called before rendering to the window framebuffer again */
-
-void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
+ * - actual FBO creation & config is deferred until GPU_framebuffer_bind or
+ * GPU_framebuffer_check_valid to allow creation & config while another
+ * opengl context is bound (since FBOs are not shared between ogl contexts).
+ */
GPUFrameBuffer *GPU_framebuffer_create(void);
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
-bool GPU_framebuffer_texture_layer_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
-bool GPU_framebuffer_texture_cubeface_attach(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
-void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
-void GPU_framebuffer_bind(GPUFrameBuffer *fb);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
+void GPU_framebuffer_restore(void);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+/* internal use only */
+unsigned int GPU_framebuffer_current_get(void);
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \
+ if (fb != NULL) { \
+ GPU_framebuffer_free(fb); \
+ fb = NULL; \
+ } \
+} while (0)
-void GPU_framebuffer_restore(void);
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, struct GPUTexture *tex,
- GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
+/* Framebuffer setup : You need to call GPU_framebuffer_bind for theses
+ * to be effective. */
+
+void GPU_framebuffer_texture_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+void GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+void GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, struct GPUTexture *tex);
+void GPU_framebuffer_texture_detach_slot(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int type);
+
+/**
+ * How to use GPU_framebuffer_ensure_config().
+ *
+ * Example :
+ * GPU_framebuffer_ensure_config(&fb, {
+ * GPU_ATTACHMENT_TEXTURE(depth), // must be depth buffer
+ * GPU_ATTACHMENT_TEXTURE(tex1),
+ * GPU_ATTACHMENT_TEXTURE_CUBEFACE(tex2, 0),
+ * GPU_ATTACHMENT_TEXTURE_LAYER_MIP(tex2, 0, 0)
+ * })
+ *
+ * Note : Unspecified attachements (i.e: those beyond the last
+ * GPU_ATTACHMENT_* in GPU_framebuffer_ensure_config list)
+ * are left unchanged.
+ * Note : Make sure that the dimensions of your textures matches
+ * otherwise you will have an invalid framebuffer error.
+ **/
+#define GPU_framebuffer_ensure_config(_fb, ...) do { \
+ if (*(_fb) == NULL) { \
+ *(_fb) = GPU_framebuffer_create(); \
+ } \
+ GPUAttachment config[] = __VA_ARGS__; \
+ GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \
+} while (0)
+
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct);
+
+#define GPU_ATTACHMENT_NONE \
+ {.tex = NULL, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_LEAVE \
+ {.tex = NULL, .layer = -1, .mip = -1}
+#define GPU_ATTACHMENT_TEXTURE(_tex) \
+ {.tex = _tex, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_MIP(_tex, _mip) \
+ {.tex = _tex, .layer = -1, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_LAYER(_tex, _layer) \
+ {.tex = _tex, .layer = _layer, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_tex, _layer, _mip) \
+ {.tex = _tex, .layer = _layer, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_tex, _face) \
+ {.tex = _tex, .layer = _face, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(_tex, _face, _mip) \
+ {.tex = _tex, .layer = _face, .mip = _mip}
+
+/* Framebuffer operations */
+
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h);
+
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil);
+
+#define GPU_framebuffer_clear_color(fb, col) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT, col, 0.0f, 0x00)
+
+#define GPU_framebuffer_clear_depth(fb, depth) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, depth, 0x00)
+
+#define GPU_framebuffer_clear_color_depth(fb, col, depth) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT, col, depth, 0x00)
+
+#define GPU_framebuffer_clear_stencil(fb, stencil) \
+ GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, stencil)
+
+#define GPU_framebuffer_clear_depth_stencil(fb, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, depth, stencil)
+
+#define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil)
+
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data);
void GPU_framebuffer_blit(
GPUFrameBuffer *fb_read, int read_slot,
- GPUFrameBuffer *fb_write, int write_slot, bool use_depth, bool use_stencil);
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers);
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ GPUFrameBuffer *fb, int max_lvl,
void (*callback)(void *userData, int level), void *userData);
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
+ */
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
+ bool depth, bool high_bitdepth, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs);
void GPU_offscreen_viewport_data_get(
GPUOffScreen *ofs,
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 698f3ada2a3..1d2b234e7f3 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -110,7 +110,8 @@ typedef enum GPUBuiltin {
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
GPU_OBJECT_INFO = (1 << 15),
GPU_VOLUME_DENSITY = (1 << 16),
- GPU_VOLUME_FLAME = (1 << 17)
+ GPU_VOLUME_FLAME = (1 << 17),
+ GPU_VOLUME_TEMPERATURE = (1 << 18)
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -135,14 +136,19 @@ typedef enum GPUBlendMode {
typedef struct GPUNodeStack {
GPUType type;
- const char *name;
float vec[4];
struct GPUNodeLink *link;
bool hasinput;
bool hasoutput;
short sockettype;
+ bool end;
} GPUNodeStack;
+typedef enum GPUMaterialStatus {
+ GPU_MAT_FAILED = 0,
+ GPU_MAT_QUEUED,
+ GPU_MAT_SUCCESS,
+} GPUMaterialStatus;
#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
@@ -244,9 +250,11 @@ GPUMaterial *GPU_material_from_nodetree_find(
struct ListBase *gpumaterials, const void *engine_type, int options);
GPUMaterial *GPU_material_from_nodetree(
struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred);
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
@@ -262,6 +270,8 @@ bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat);
struct GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material);
void GPU_material_create_uniform_buffer(GPUMaterial *material, struct ListBase *inputs);
@@ -357,10 +367,9 @@ void GPU_zenith_update_color(float color[3]);
struct GPUParticleInfo
{
float scalprops[4];
- float location[3];
+ float location[4];
float velocity[3];
float angular_velocity[3];
- int random_id;
};
#ifdef WITH_OPENSUBDIV
@@ -369,6 +378,9 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
struct DerivedMesh *dm);
#endif
+void GPU_pass_cache_garbage_collect(void);
+void GPU_pass_cache_free(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 0617d58f3b6..f1342a1f6b8 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -47,6 +47,7 @@ enum {
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits);
bool GPU_select_load_id(unsigned int id);
+void GPU_select_finalize(void);
unsigned int GPU_select_end(void);
bool GPU_select_query_check_active(void);
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index f2119a117e5..b33df9fdb20 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -72,9 +72,6 @@ int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
-void *GPU_fx_shader_get_interface(GPUShader *shader);
-void GPU_fx_shader_set_interface(GPUShader *shader, void *interface);
-
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
@@ -100,6 +97,7 @@ typedef enum GPUBuiltinShader {
/* specialized drawing */
GPU_SHADER_TEXT,
+ GPU_SHADER_TEXT_SIMPLE,
GPU_SHADER_EDGES_FRONT_BACK_PERSP,
GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
GPU_SHADER_EDGES_OVERLAY_SIMPLE,
@@ -113,8 +111,12 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_UNIFORM_COLOR,
GPU_SHADER_2D_FLAT_COLOR,
GPU_SHADER_2D_SMOOTH_COLOR,
+ GPU_SHADER_2D_IMAGE,
GPU_SHADER_2D_IMAGE_COLOR,
GPU_SHADER_2D_IMAGE_ALPHA_COLOR,
+ GPU_SHADER_2D_IMAGE_ALPHA,
+ GPU_SHADER_2D_IMAGE_RECT_COLOR,
+ GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR,
GPU_SHADER_2D_CHECKER,
GPU_SHADER_2D_DIAG_STRIPES,
/* for simple 3D drawing */
@@ -131,8 +133,8 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
- GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA,
GPU_SHADER_3D_IMAGE_DEPTH,
+ GPU_SHADER_3D_IMAGE_DEPTH_COPY,
/* stereo 3d */
GPU_SHADER_2D_IMAGE_INTERLACE,
/* points */
@@ -169,11 +171,17 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
+ /* specialized for UI drawing */
+ GPU_SHADER_2D_WIDGET_BASE,
+ GPU_SHADER_2D_WIDGET_BASE_INST,
+ GPU_SHADER_2D_WIDGET_SHADOW,
+ GPU_SHADER_2D_NODELINK,
+ GPU_SHADER_2D_NODELINK_INST,
GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID,
GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE,
- GPU_SHADER_3D_INSTANCE_MBALL_HELPERS,
+ GPU_SHADER_3D_INSTANCE_MBALL_HANDLES,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
@@ -189,7 +197,6 @@ typedef enum GPUInterlaceShader {
} GPUInterlaceShader;
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
void GPU_shader_free_builtin_shaders(void);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index e74d9a3291d..7c33153ee01 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -70,6 +70,7 @@ typedef enum GPUTextureFormat {
GPU_RG16I,
GPU_R32F,
GPU_R16F,
+ GPU_R16I,
GPU_RG8,
GPU_R8,
#if 0
@@ -88,7 +89,6 @@ typedef enum GPUTextureFormat {
GPU_RG8UI,
GPU_R32I,
GPU_R32UI,
- GPU_R16I,
GPU_R16UI,
GPU_R16,
GPU_R8I,
@@ -189,16 +189,18 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter);
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
-struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-int GPU_texture_framebuffer_attachment(GPUTexture *tex);
-void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb);
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_format(const GPUTexture *tex);
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex);
+int GPU_texture_samples(const GPUTexture *tex);
+bool GPU_texture_cube(const GPUTexture *tex);
bool GPU_texture_depth(const GPUTexture *tex);
bool GPU_texture_stencil(const GPUTexture *tex);
+bool GPU_texture_integer(const GPUTexture *tex);
int GPU_texture_opengl_bindcode(const GPUTexture *tex);
#ifdef __cplusplus
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 580ff64befb..ca7d5ae7ceb 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -46,7 +46,7 @@ typedef struct GPUViewport GPUViewport;
/* Contains memory pools informations */
typedef struct ViewportMemoryPool {
struct BLI_mempool *calls;
- struct BLI_mempool *calls_generate;
+ struct BLI_mempool *states;
struct BLI_mempool *shgroups;
struct BLI_mempool *uniforms;
struct BLI_mempool *passes;
@@ -83,7 +83,6 @@ typedef struct ViewportEngineData {
/* Profiling data */
double init_time;
- double cache_time;
double render_time;
double background_time;
} ViewportEngineData;
@@ -98,6 +97,7 @@ typedef struct ViewportEngineData_Info {
GPUViewport *GPU_viewport_create(void);
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
void GPU_viewport_unbind(GPUViewport *viewport);
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
void GPU_viewport_free(GPUViewport *viewport);
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
@@ -113,6 +113,9 @@ void *GPU_viewport_texture_list_get(GPUViewport *viewport);
void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
+/* Profiling */
+double *GPU_viewport_cache_time_get(GPUViewport *viewport);
+
void GPU_viewport_tag_update(GPUViewport *viewport);
bool GPU_viewport_do_update(GPUViewport *viewport);
@@ -122,13 +125,4 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
void GPU_viewport_cache_release(GPUViewport *viewport);
-/* debug */
-bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
-void GPU_viewport_debug_depth_free(GPUViewport *viewport);
-void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y);
-void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar);
-bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport);
-int GPU_viewport_debug_depth_width(const GPUViewport *viewport);
-int GPU_viewport_debug_depth_height(const GPUViewport *viewport);
-
#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 0400fc1025b..332102aca46 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -34,7 +34,7 @@
#include "BLI_utildefines.h"
#include "BLI_rect.h"
#include "BLI_math.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_sort_utils.h"
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index 9db04832a51..10cbd16490b 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -31,6 +31,11 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
+#include "BLI_listbase.h"
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
#include "GPU_batch.h"
#include "gpu_shader_private.h"
@@ -50,14 +55,24 @@ static struct {
struct {
uint pos, nor;
} attr_id;
-} g_presets_3d = {0};
+} g_presets_3d = {{0}};
-/* We may want 2D presets later. */
+static ListBase presets_list = {NULL, NULL};
/* -------------------------------------------------------------------- */
/** \name 3D Primitives
* \{ */
+static Gwn_VertFormat *preset_3D_format(void)
+{
+ if (g_presets_3d.format.attrib_ct == 0) {
+ Gwn_VertFormat *format = &g_presets_3d.format;
+ g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+ return &g_presets_3d.format;
+}
+
static void batch_sphere_lat_lon_vert(
Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step,
float lat, float lon)
@@ -71,13 +86,13 @@ static void batch_sphere_lat_lon_vert(
}
/* Replacement for gluSphere */
-static Gwn_Batch *batch_sphere(int lat_res, int lon_res)
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res)
{
const float lon_inc = 2 * M_PI / lon_res;
const float lat_inc = M_PI / lat_res;
float lon, lat;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&g_presets_3d.format);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
const uint vbo_len = (lat_res - 1) * lon_res * 6;
GWN_vertbuf_data_alloc(vbo, vbo_len);
@@ -115,7 +130,7 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
const float lat_inc = M_PI / lat_res;
float lon, lat;
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&g_presets_3d.format);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2);
GWN_vertbuf_data_alloc(vbo, vbo_len);
@@ -146,6 +161,7 @@ static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
Gwn_Batch *GPU_batch_preset_sphere(int lod)
{
BLI_assert(lod >= 0 && lod <= 2);
+ BLI_assert(BLI_thread_is_main());
if (lod == 0) {
return g_presets_3d.batch.sphere_low;
@@ -161,6 +177,7 @@ Gwn_Batch *GPU_batch_preset_sphere(int lod)
Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
{
BLI_assert(lod >= 0 && lod <= 1);
+ BLI_assert(BLI_thread_is_main());
if (lod == 0) {
return g_presets_3d.batch.sphere_wire_low;
@@ -175,26 +192,45 @@ Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
void gpu_batch_presets_init(void)
{
- if (g_presets_3d.format.attrib_ct == 0) {
- Gwn_VertFormat *format = &g_presets_3d.format;
- g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- }
-
/* Hard coded resolution */
- g_presets_3d.batch.sphere_low = batch_sphere(8, 16);
- g_presets_3d.batch.sphere_med = batch_sphere(16, 10);
- g_presets_3d.batch.sphere_high = batch_sphere(32, 24);
+ g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_low);
+
+ g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_med);
+
+ g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_high);
g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_low);
+
g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med);
+}
+
+void gpu_batch_presets_register(Gwn_Batch *preset_batch)
+{
+ BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch));
+}
+
+void gpu_batch_presets_reset(void)
+{
+ /* Reset vao caches for these every time we switch opengl context.
+ * This way they will draw correctly for each window. */
+ LinkData *link = presets_list.first;
+ for (link = presets_list.first; link; link = link->next) {
+ Gwn_Batch *preset = link->data;
+ gwn_batch_vao_cache_clear(preset);
+ }
}
void gpu_batch_presets_exit(void)
{
- GWN_batch_discard(g_presets_3d.batch.sphere_low);
- GWN_batch_discard(g_presets_3d.batch.sphere_med);
- GWN_batch_discard(g_presets_3d.batch.sphere_high);
- GWN_batch_discard(g_presets_3d.batch.sphere_wire_low);
- GWN_batch_discard(g_presets_3d.batch.sphere_wire_med);
+ LinkData *link;
+ while ((link = BLI_pophead(&presets_list))) {
+ Gwn_Batch *preset = link->data;
+ GWN_batch_discard(preset);
+ MEM_freeN(link);
+ }
}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index d0efee79ab0..3367a568bc5 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -986,15 +986,37 @@ struct GPU_PBVH_Buffers {
float diffuse_color[4];
};
-typedef struct {
+static struct {
uint pos, nor, col;
-} VertexBufferAttrID;
+} g_vbo_id = {0};
-static void gpu_pbvh_vert_format_init__gwn(Gwn_VertFormat *format, VertexBufferAttrID *vbo_id)
+/* Allocates a non-initialized buffer to be sent to GPU.
+ * Return is false it indicates that the memory map failed. */
+static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int vert_ct)
{
- vbo_id->pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- vbo_id->nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- vbo_id->col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ if (buffers->vert_buf == NULL) {
+ /* Initialize vertex buffer */
+ /* match 'VertexBufferFormat' */
+
+ static Gwn_VertFormat format = {0};
+ if (format.attrib_ct == 0) {
+ g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+#if 0
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+ }
+ else if (vert_ct != buffers->vert_buf->vertex_ct) {
+ GWN_vertbuf_data_resize(buffers->vert_buf, vert_ct);
+ }
+#else
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ }
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+#endif
+ return buffers->vert_buf->data != NULL;
}
static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
@@ -1004,14 +1026,14 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
GWN_vertbuf_use(buffers->vert_buf);
}
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
- buffers->triangles = GWN_batch_create(
- GWN_PRIM_TRIS, buffers->vert_buf,
- /* can be NULL */
- buffers->index_buf);
+ if (buffers->triangles == NULL) {
+ buffers->triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf);
+ }
- GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
- if (buffers->index_buf_fast) {
+ if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) {
buffers->triangles_fast = GWN_batch_create(
GWN_PRIM_TRIS, buffers->vert_buf,
/* can be NULL */
@@ -1085,25 +1107,15 @@ void GPU_pbvh_mesh_buffers_update(
rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
/* Build VBO */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
-
- /* match 'VertexBufferFormat' */
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totelem);
-
- if (buffers->vert_buf->data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
/* Vertex data is shared if smooth-shaded, but separate
* copies are made for flat shading because normals
* shouldn't be shared. */
if (buffers->smooth) {
for (uint i = 0; i < totvert; ++i) {
const MVert *v = &mvert[vert_indices[i]];
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, i, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, i, v->no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
}
for (uint i = 0; i < buffers->face_indices_len; i++) {
@@ -1114,10 +1126,10 @@ void GPU_pbvh_mesh_buffers_update(
int v_index = buffers->mloop[lt->tri[j]].v;
uchar color_ub[3];
gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
}
else {
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, diffuse_color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
}
}
}
@@ -1160,9 +1172,9 @@ void GPU_pbvh_mesh_buffers_update(
for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, v->co);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
vbo_index++;
}
@@ -1171,9 +1183,6 @@ void GPU_pbvh_mesh_buffers_update(
gpu_pbvh_batch_init(buffers);
}
- else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- }
}
buffers->mvert = mvert;
@@ -1293,17 +1302,9 @@ void GPU_pbvh_grid_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- /* Build coord/normal VBO */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totgrid * key->grid_area);
-
uint vbo_index_offset = 0;
- if (buffers->vert_buf->data) {
+ /* Build VBO */
+ if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) {
for (i = 0; i < totgrid; ++i) {
CCGElem *grid = grids[grid_indices[i]];
int vbo_index = vbo_index_offset;
@@ -1311,12 +1312,12 @@ void GPU_pbvh_grid_buffers_update(
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
if (buffers->smooth) {
short no_short[3];
normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -1327,7 +1328,7 @@ void GPU_pbvh_grid_buffers_update(
else {
F3TOCHAR3(diffuse_color, color_ub);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
vbo_index += 1;
@@ -1354,7 +1355,7 @@ void GPU_pbvh_grid_buffers_update(
vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
short no_short[3];
normal_float_to_short_v3(no_short, fno);
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
uchar color_ub[3];
@@ -1370,7 +1371,7 @@ void GPU_pbvh_grid_buffers_update(
else {
F3TOCHAR3(diffuse_color, color_ub);
}
- GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
}
@@ -1381,9 +1382,6 @@ void GPU_pbvh_grid_buffers_update(
gpu_pbvh_batch_init(buffers);
}
- else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- }
}
buffers->grids = grids;
@@ -1562,7 +1560,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
static void gpu_bmesh_vert_to_buffer_copy__gwn(
BMVert *v,
Gwn_VertBuf *vert_buf,
- const VertexBufferAttrID *vbo_id,
int *v_index,
const float fno[3],
const float *fmask,
@@ -1573,12 +1570,12 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
/* Set coord, normal, and mask */
- GWN_vertbuf_attr_set(vert_buf, vbo_id->pos, *v_index, v->co);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
{
short no_short[3];
normal_float_to_short_v3(no_short, fno ? fno : v->no);
- GWN_vertbuf_attr_set(vert_buf, vbo_id->nor, *v_index, no_short);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
}
{
@@ -1596,7 +1593,7 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(
effective_mask,
diffuse_color,
color_ub);
- GWN_vertbuf_attr_set(vert_buf, vbo_id->col, *v_index, color_ub);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
}
/* Assign index for use in the triangle index buffer */
@@ -1694,18 +1691,8 @@ void GPU_pbvh_bmesh_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- /* Initialize vertex buffer */
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
- /* match 'VertexBufferFormat' */
- Gwn_VertFormat format = {0};
- VertexBufferAttrID vbo_id;
- gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
-
- buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(buffers->vert_buf, totvert);
-
/* Fill vertex buffer */
- if (buffers->vert_buf->data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
int v_index = 0;
if (buffers->smooth) {
@@ -1718,7 +1705,7 @@ void GPU_pbvh_bmesh_buffers_update(
GSET_ITER (gs_iter, bm_unique_verts) {
gpu_bmesh_vert_to_buffer_copy__gwn(
BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ buffers->vert_buf, &v_index, NULL, NULL,
cd_vert_mask_offset, diffuse_color,
show_mask);
}
@@ -1726,7 +1713,7 @@ void GPU_pbvh_bmesh_buffers_update(
GSET_ITER (gs_iter, bm_other_verts) {
gpu_bmesh_vert_to_buffer_copy__gwn(
BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ buffers->vert_buf, &v_index, NULL, NULL,
cd_vert_mask_offset, diffuse_color,
show_mask);
}
@@ -1759,7 +1746,7 @@ void GPU_pbvh_bmesh_buffers_update(
for (i = 0; i < 3; i++) {
gpu_bmesh_vert_to_buffer_copy__gwn(
- v[i], buffers->vert_buf, &vbo_id,
+ v[i], buffers->vert_buf,
&v_index, f->no, &fmask,
cd_vert_mask_offset, diffuse_color,
show_mask);
@@ -1774,7 +1761,6 @@ void GPU_pbvh_bmesh_buffers_update(
bm->elem_index_dirty |= BM_VERT;
}
else {
- GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
/* Memory map failed */
return;
}
@@ -1786,9 +1772,6 @@ void GPU_pbvh_bmesh_buffers_update(
GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
/* Initialize triangle index buffer */
- if (buffers->triangles && !buffers->is_index_buf_global) {
- GWN_BATCH_DISCARD_SAFE(buffers->triangles);
- }
buffers->is_index_buf_global = false;
/* Fill triangle index buffer */
@@ -1812,7 +1795,12 @@ void GPU_pbvh_bmesh_buffers_update(
buffers->tot_tri = tottri;
- buffers->index_buf = GWN_indexbuf_build(&elb);
+ if (buffers->index_buf == NULL) {
+ buffers->index_buf = GWN_indexbuf_build(&elb);
+ }
+ else {
+ GWN_indexbuf_build_in_place(&elb, buffers->index_buf);
+ }
}
}
else if (buffers->index_buf) {
@@ -1901,7 +1889,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
}
else if (buffers->use_bmesh) {
/* due to dynamic nature of dyntopo, only get first material */
- if (BLI_gset_size(bm_faces) > 0) {
+ if (BLI_gset_len(bm_faces) > 0) {
GSetIterator gs_iter;
BMFace *f;
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 9e4daa2a036..b245c9a161f 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -39,10 +39,14 @@
#include "DNA_node_types.h"
#include "BLI_blenlib.h"
+#include "BLI_hash_mm2a.h"
+#include "BLI_linklist.h"
#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "PIL_time.h"
+
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_material.h"
@@ -64,6 +68,50 @@ extern char datatoc_gpu_shader_geometry_glsl[];
static char *glsl_material_library = NULL;
+/* -------------------- GPUPass Cache ------------------ */
+/**
+ * Internal shader cache: This prevent the shader recompilation / stall when
+ * using undo/redo AND also allows for GPUPass reuse if the Shader code is the
+ * same for 2 different Materials. Unused GPUPasses are free by Garbage collection.
+ **/
+
+static LinkNode *pass_cache = NULL; /* GPUPass */
+
+static uint32_t gpu_pass_hash(const char *vert, const char *geom, const char *frag, const char *defs)
+{
+ BLI_HashMurmur2A hm2a;
+ BLI_hash_mm2a_init(&hm2a, 0);
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)frag, strlen(frag));
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)vert, strlen(vert));
+ if (defs)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)defs, strlen(defs));
+ if (geom)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)geom, strlen(geom));
+
+ return BLI_hash_mm2a_end(&hm2a);
+}
+
+/* Search by hash then by exact string match. */
+static GPUPass *gpu_pass_cache_lookup(
+ const char *vert, const char *geom, const char *frag, const char *defs, uint32_t hash)
+{
+ for (LinkNode *ln = pass_cache; ln; ln = ln->next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ if (pass->hash == hash) {
+ /* Note: Could be made faster if that becomes a real bottleneck. */
+ if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ }
+ else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ }
+ else if ((strcmp(pass->fragmentcode, frag) == 0) &&
+ (strcmp(pass->vertexcode, vert) == 0))
+ {
+ return pass;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* -------------------- GPU Codegen ------------------ */
/* type definitions and constants */
@@ -427,6 +475,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "sampdensity";
else if (builtin == GPU_VOLUME_FLAME)
return "sampflame";
+ else if (builtin == GPU_VOLUME_TEMPERATURE)
+ return "unftemperature";
else
return "";
}
@@ -1173,15 +1223,13 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
-static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs_new(GPUShader *shader, ListBase *inputs, ListBase *nodes)
{
- GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
- ListBase *inputs = &pass->inputs;
int extract, z;
- memset(inputs, 0, sizeof(*inputs));
+ BLI_listbase_clear(inputs);
if (!shader)
return;
@@ -1234,15 +1282,13 @@ static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
GPU_shader_unbind();
}
-static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes)
{
- GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
- ListBase *inputs = &pass->inputs;
int extract, z;
- memset(inputs, 0, sizeof(*inputs));
+ BLI_listbase_clear(inputs);
if (!shader)
return;
@@ -1320,11 +1366,10 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
GPU_shader_unbind();
}
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1349,11 +1394,10 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
}
}
-void GPU_pass_update_uniforms(GPUPass *pass)
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1374,11 +1418,10 @@ void GPU_pass_update_uniforms(GPUPass *pass)
}
}
-void GPU_pass_unbind(GPUPass *pass)
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1677,7 +1720,7 @@ static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **lin
BLI_addtail(&node->outputs, output);
}
-static void gpu_inputs_free(ListBase *inputs)
+void GPU_inputs_free(ListBase *inputs)
{
GPUInput *input;
@@ -1695,7 +1738,7 @@ static void gpu_node_free(GPUNode *node)
{
GPUOutput *output;
- gpu_inputs_free(&node->inputs);
+ GPU_inputs_free(&node->inputs);
for (output = node->outputs.first; output; output = output->next)
if (output->link) {
@@ -1718,7 +1761,7 @@ static void gpu_nodes_free(ListBase *nodes)
/* vertex attributes */
-static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
{
GPUNode *node;
GPUInput *input;
@@ -1958,16 +2001,20 @@ bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNo
totout = 0;
if (in) {
- for (i = 0; in[i].type != GPU_NONE; i++) {
- gpu_node_input_socket(material, bnode, node, &in[i], i);
- totin++;
+ for (i = 0; !in[i].end; i++) {
+ if (in[i].type != GPU_NONE) {
+ gpu_node_input_socket(material, bnode, node, &in[i], i);
+ totin++;
+ }
}
}
if (out) {
- for (i = 0; out[i].type != GPU_NONE; i++) {
- gpu_node_output(node, out[i].type, &out[i].link);
- totout++;
+ for (i = 0; !out[i].end; i++) {
+ if (out[i].type != GPU_NONE) {
+ gpu_node_output(node, out[i].type, &out[i].link);
+ totout++;
+ }
}
}
@@ -2046,7 +2093,7 @@ static void gpu_nodes_tag(GPUNodeLink *link)
gpu_nodes_tag(input->link);
}
-static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
+void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
{
GPUNode *node, *next;
@@ -2066,79 +2113,83 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
GPUPass *GPU_generate_pass_new(
- struct GPUMaterial *material,
- ListBase *nodes, struct GPUNodeLink *frag_outlink,
- GPUVertexAttribs *attribs,
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
const char *vert_code, const char *geom_code,
const char *frag_lib, const char *defines)
{
+ char *vertexcode, *geometrycode, *fragmentcode;
GPUShader *shader;
GPUPass *pass;
- char *vertexgen, *fragmentgen, *tmp;
- char *vertexcode, *geometrycode, *fragmentcode;
/* prune unused nodes */
- gpu_nodes_prune(nodes, frag_outlink);
+ GPU_nodes_prune(nodes, frag_outlink);
- gpu_nodes_get_vertex_attributes(nodes, attribs);
+ GPU_nodes_get_vertex_attributes(nodes, attribs);
- /* generate code and compile with opengl */
- fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
- vertexgen = code_generate_vertex_new(nodes, vert_code, (geom_code != NULL));
+ /* generate code */
+ char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
+ char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
- tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ vertexcode = code_generate_vertex_new(nodes, vert_code, (geom_code != NULL));
+ geometrycode = (geom_code) ? code_generate_geometry_new(nodes, geom_code) : NULL;
fragmentcode = BLI_strdupcat(tmp, fragmentgen);
- vertexcode = BLI_strdup(vertexgen);
-
- if (geom_code) {
- geometrycode = code_generate_geometry_new(nodes, geom_code);
- }
- else {
- geometrycode = NULL;
- }
-
- shader = GPU_shader_create(vertexcode,
- fragmentcode,
- geometrycode,
- NULL,
- defines);
+ MEM_freeN(fragmentgen);
MEM_freeN(tmp);
- /* failed? */
+ /* Cache lookup: Reuse shaders already compiled */
+ uint32_t hash = gpu_pass_hash(vertexcode, geometrycode, fragmentcode, defines);
+ pass = gpu_pass_cache_lookup(vertexcode, geometrycode, fragmentcode, defines, hash);
+ if (pass) {
+ /* Cache hit. Reuse the same GPUPass and GPUShader. */
+ shader = pass->shader;
+ pass->refcount += 1;
+
+ MEM_SAFE_FREE(vertexcode);
+ MEM_SAFE_FREE(fragmentcode);
+ MEM_SAFE_FREE(geometrycode);
+ }
+ else {
+ /* Cache miss. (Re)compile the shader. */
+ shader = GPU_shader_create(vertexcode,
+ fragmentcode,
+ geometrycode,
+ NULL,
+ defines);
+
+ /* We still create a pass even if shader compilation
+ * fails to avoid trying to compile again and again. */
+ pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+ pass->shader = shader;
+ pass->refcount = 1;
+ pass->hash = hash;
+ pass->vertexcode = vertexcode;
+ pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
+ pass->libcode = glsl_material_library;
+ pass->defines = (defines) ? BLI_strdup(defines) : NULL;
+
+ BLI_linklist_prepend(&pass_cache, pass);
+ }
+
+ /* did compilation failed ? */
if (!shader) {
- if (fragmentcode)
- MEM_freeN(fragmentcode);
- if (vertexcode)
- MEM_freeN(vertexcode);
- if (geometrycode)
- MEM_freeN(geometrycode);
- MEM_freeN(fragmentgen);
- MEM_freeN(vertexgen);
gpu_nodes_free(nodes);
+ /* Pass will not be used. Don't increment refcount. */
+ pass->refcount--;
return NULL;
}
-
- /* create pass */
- pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
- pass->shader = shader;
- pass->fragmentcode = fragmentcode;
- pass->geometrycode = geometrycode;
- pass->vertexcode = vertexcode;
- pass->libcode = glsl_material_library;
-
- /* extract dynamic inputs and throw away nodes */
- gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
- gpu_nodes_free(nodes);
-
- MEM_freeN(fragmentgen);
- MEM_freeN(vertexgen);
-
- return pass;
+ else {
+ gpu_nodes_extract_dynamic_inputs_new(shader, inputs, nodes);
+ return pass;
+ }
}
+/* TODO(fclem) Remove for 2.8 */
GPUPass *GPU_generate_pass(
- ListBase *nodes, GPUNodeLink *outlink,
+ ListBase *nodes, ListBase *inputs, GPUNodeLink *outlink,
GPUVertexAttribs *attribs, int *builtins,
const GPUMatType type, const char *UNUSED(name),
const bool use_opensubdiv,
@@ -2156,9 +2207,9 @@ GPUPass *GPU_generate_pass(
#endif
/* prune unused nodes */
- gpu_nodes_prune(nodes, outlink);
+ GPU_nodes_prune(nodes, outlink);
- gpu_nodes_get_vertex_attributes(nodes, attribs);
+ GPU_nodes_get_vertex_attributes(nodes, attribs);
gpu_nodes_get_builtin_flag(nodes, builtins);
/* generate code and compile with opengl */
@@ -2194,30 +2245,38 @@ GPUPass *GPU_generate_pass(
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
-
+ pass->refcount = 1;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;
pass->vertexcode = vertexcode;
pass->libcode = glsl_material_library;
+ BLI_linklist_prepend(&pass_cache, pass);
+
/* extract dynamic inputs and throw away nodes */
- gpu_nodes_extract_dynamic_inputs(pass, nodes);
+ gpu_nodes_extract_dynamic_inputs(shader, inputs, nodes);
gpu_nodes_free(nodes);
return pass;
}
-void GPU_pass_free(GPUPass *pass)
+void GPU_pass_release(GPUPass *pass)
+{
+ BLI_assert(pass->refcount > 0);
+ pass->refcount--;
+}
+
+static void gpu_pass_free(GPUPass *pass)
{
- GPU_shader_free(pass->shader);
- gpu_inputs_free(&pass->inputs);
- if (pass->fragmentcode)
- MEM_freeN(pass->fragmentcode);
- if (pass->geometrycode)
- MEM_freeN(pass->geometrycode);
- if (pass->vertexcode)
- MEM_freeN(pass->vertexcode);
+ BLI_assert(pass->refcount == 0);
+ if (pass->shader) {
+ GPU_shader_free(pass->shader);
+ }
+ MEM_SAFE_FREE(pass->fragmentcode);
+ MEM_SAFE_FREE(pass->geometrycode);
+ MEM_SAFE_FREE(pass->vertexcode);
+ MEM_SAFE_FREE(pass->defines);
MEM_freeN(pass);
}
@@ -2226,3 +2285,34 @@ void GPU_pass_free_nodes(ListBase *nodes)
gpu_nodes_free(nodes);
}
+void GPU_pass_cache_garbage_collect(void)
+{
+ static int lasttime = 0;
+ const int shadercollectrate = 60; /* hardcoded for now. */
+ int ctime = (int)PIL_check_seconds_timer();
+
+ if (ctime < shadercollectrate + lasttime)
+ return;
+
+ lasttime = ctime;
+
+ LinkNode *next, **prev_ln = &pass_cache;
+ for (LinkNode *ln = pass_cache; ln; ln = next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ next = ln->next;
+ if (pass->refcount == 0) {
+ gpu_pass_free(pass);
+ /* Remove from list */
+ MEM_freeN(ln);
+ *prev_ln = next;
+ }
+ else {
+ prev_ln = &ln->next;
+ }
+ }
+}
+
+void GPU_pass_cache_free(void)
+{
+ BLI_linklist_free(pass_cache, (LinkNodeFreeFP)gpu_pass_free);
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 14e07a6e012..dab0bc3f8b1 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -157,25 +157,27 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- ListBase inputs;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
char *vertexcode;
+ char *defines;
const char *libcode;
+ unsigned int refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */
+ uint32_t hash; /* Identity hash generated from all GLSL code. */
};
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass_new(
- struct GPUMaterial *material,
- ListBase *nodes, struct GPUNodeLink *frag_outlink,
- struct GPUVertexAttribs *attribs,
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
const char *vert_code, const char *geom_code,
const char *frag_lib, const char *defines);
GPUPass *GPU_generate_pass(
- ListBase *nodes, struct GPUNodeLink *outlink,
+ ListBase *nodes, ListBase *inputs, struct GPUNodeLink *outlink,
struct GPUVertexAttribs *attribs, int *builtin,
const GPUMatType type, const char *name,
const bool use_opensubdiv,
@@ -183,13 +185,18 @@ GPUPass *GPU_generate_pass(
struct GPUShader *GPU_pass_shader(GPUPass *pass);
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap);
-void GPU_pass_update_uniforms(GPUPass *pass);
-void GPU_pass_unbind(GPUPass *pass);
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs);
+void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink);
+
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap);
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs);
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs);
-void GPU_pass_free(GPUPass *pass);
+void GPU_pass_release(GPUPass *pass);
void GPU_pass_free_nodes(ListBase *nodes);
+void GPU_inputs_free(ListBase *inputs);
+
void gpu_codegen_init(void);
void gpu_codegen_exit(void);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
deleted file mode 100644
index 3de363cc76e..00000000000
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2006 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/gpu/intern/gpu_compositing.c
- * \ingroup gpu
- *
- * System that manages framebuffer compositing.
- */
-
-#include "BLI_sys_types.h"
-#include "BLI_rect.h"
-#include "BLI_math.h"
-
-#include "BLI_rand.h"
-
-#include "DNA_vec_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_gpu_types.h"
-
-#include "GPU_compositing.h"
-#include "GPU_draw.h"
-#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
-#include "GPU_glew.h"
-#include "GPU_shader.h"
-#include "GPU_texture.h"
-#include "GPU_batch.h"
-
-#include "MEM_guardedalloc.h"
-
-static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
-static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
-
-
-/* shader interfaces (legacy GL 2 style, without uniform buffer objects) */
-
-typedef struct {
- int ssao_uniform;
- int ssao_color_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
- int ssao_sample_params_uniform;
- int ssao_concentric_tex;
- int ssao_jitter_uniform;
-} GPUSSAOShaderInterface;
-
-typedef struct {
- int invrendertargetdim_uniform;
- int color_uniform;
- int dof_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFHQPassOneInterface;
-
-typedef struct {
- int rendertargetdim_uniform;
- int color_uniform;
- int coc_uniform;
- int select_uniform;
- int dof_uniform;
-} GPUDOFHQPassTwoInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int far_uniform;
- int near_uniform;
- int viewvecs_uniform;
- int depth_uniform;
-} GPUDOFHQPassThreeInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassOneInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassTwoInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int near_coc_blurred;
-} GPUDOFPassThreeInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int invrendertargetdim_uniform;
-} GPUDOFPassFourInterface;
-
-typedef struct {
- int medium_blurred_uniform;
- int high_blurred_uniform;
- int dof_uniform;
- int invrendertargetdim_uniform;
- int original_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassFiveInterface;
-
-typedef struct {
- int depth_uniform;
-} GPUDepthResolveInterface;
-
-
-struct GPUFX {
- /* we borrow the term gbuffer from deferred rendering however this is just a regular
- * depth/color framebuffer. Could be extended later though */
- GPUFrameBuffer *gbuffer;
-
- /* dimensions of the gbuffer */
- int gbuffer_dim[2];
-
- /* texture bound to the first color attachment of the gbuffer */
- GPUTexture *color_buffer;
-
- /* second texture used for ping-pong compositing */
- GPUTexture *color_buffer_sec;
- /* texture bound to the depth attachment of the gbuffer */
- GPUTexture *depth_buffer;
- GPUTexture *depth_buffer_xray;
-
- /* texture used for jittering for various effects */
- GPUTexture *jitter_buffer;
-
- /* all those buffers below have to coexist.
- * Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
- int dof_downsampled_w;
- int dof_downsampled_h;
-
- /* texture used for near coc and color blurring calculation */
- GPUTexture *dof_near_coc_buffer;
- /* blurred near coc buffer. */
- GPUTexture *dof_near_coc_blurred_buffer;
- /* final near coc buffer. */
- GPUTexture *dof_near_coc_final_buffer;
-
- /* half size blur buffer */
- GPUTexture *dof_half_downsampled_near;
- GPUTexture *dof_half_downsampled_far;
- /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
- GPUTexture *dof_nearfar_coc;
- GPUTexture *dof_near_blur;
- GPUTexture *dof_far_blur;
-
- /* for high quality we use again a spiral texture with radius adapted */
- bool dof_high_quality;
-
- /* texture used for ssao */
- int ssao_sample_count_cache;
- GPUTexture *ssao_spiral_samples_tex;
-
-
- GPUFXSettings settings;
-
- /* or-ed flags of enabled effects */
- int effects;
-
- /* number of passes, needed to detect if ping pong buffer allocation is needed */
- int num_passes;
-
- /* we have a stencil, restore the previous state */
- bool restore_stencil;
-
- Gwn_Batch *quad_batch;
- Gwn_Batch *point_batch;
-};
-
-#if 0
-/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
- * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
-static GPUTexture * create_concentric_sample_texture(int side)
-{
- GPUTexture *tex;
- float midpoint = 0.5f * (side - 1);
- float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
- int i, j;
-
- for (i = 0; i < side; i++) {
- for (j = 0; j < side; j++) {
- int index = (i * side + j) * 2;
- float a = 1.0f - i / midpoint;
- float b = 1.0f - j / midpoint;
- float phi, r;
- if (a * a > b * b) {
- r = a;
- phi = (M_PI_4) * (b / a);
- }
- else {
- r = b;
- phi = M_PI_2 - (M_PI_4) * (a / b);
- }
- texels[index] = r * cos(phi);
- texels[index + 1] = r * sin(phi);
- }
- }
-
- tex = GPU_texture_create_1D_custom(side * side, 2, GPU_RG16F, (float *)texels, NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_unbind(tex);
-
- MEM_freeN(texels);
- return tex;
-}
-#endif
-
-static GPUTexture *create_spiral_sample_texture(int numsaples)
-{
- GPUTexture *tex;
- float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
- const float numsaples_inv = 1.0f / numsaples;
- int i;
- /* arbitrary number to ensure we don't get conciding samples every circle */
- const float spirals = 7.357;
-
- for (i = 0; i < numsaples; i++) {
- float r = (i + 0.5f) * numsaples_inv;
- float phi = r * spirals * (float)(2.0 * M_PI);
- texels[i][0] = r * cosf(phi);
- texels[i][1] = r * sinf(phi);
- }
-
- tex = GPU_texture_create_1D_custom(numsaples, 2, GPU_RG16F, (float *)texels, NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_unbind(tex);
-
- MEM_freeN(texels);
- return tex;
-}
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void)
-{
- GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
-
- /* Quad buffer */
- static Gwn_VertFormat format = {0};
- static unsigned int pos, uvs;
- if (format.attrib_ct == 0) {
- pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
- Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 4);
- for (int i = 0; i < 4; ++i) {
- GWN_vertbuf_attr_set(vbo, pos, i, fullscreencos[i]);
- GWN_vertbuf_attr_set(vbo, uvs, i, fullscreenuvs[i]);
- }
- fx->quad_batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
-
- /* Point Buffer */
- static Gwn_VertFormat format_point = {0};
- static unsigned int dummy_attrib;
- if (format_point.attrib_ct == 0) {
- dummy_attrib = GWN_vertformat_attr_add(&format_point, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- }
- float dummy[2] = {0.0f, 0.0f};
- Gwn_VertBuf *vbo_point = GWN_vertbuf_create_with_format(&format_point);
- GWN_vertbuf_data_alloc(vbo_point, 1);
- GWN_vertbuf_attr_set(vbo_point, dummy_attrib, 0, &dummy);
- fx->point_batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo_point, NULL, GWN_BATCH_OWNS_VBO);
-
- return fx;
-}
-
-static void cleanup_fx_dof_buffers(GPUFX *fx)
-{
- if (fx->dof_near_coc_blurred_buffer) {
- GPU_texture_free(fx->dof_near_coc_blurred_buffer);
- fx->dof_near_coc_blurred_buffer = NULL;
- }
- if (fx->dof_near_coc_buffer) {
- GPU_texture_free(fx->dof_near_coc_buffer);
- fx->dof_near_coc_buffer = NULL;
- }
- if (fx->dof_near_coc_final_buffer) {
- GPU_texture_free(fx->dof_near_coc_final_buffer);
- fx->dof_near_coc_final_buffer = NULL;
- }
-
- if (fx->dof_half_downsampled_near) {
- GPU_texture_free(fx->dof_half_downsampled_near);
- fx->dof_half_downsampled_near = NULL;
- }
- if (fx->dof_half_downsampled_far) {
- GPU_texture_free(fx->dof_half_downsampled_far);
- fx->dof_half_downsampled_far = NULL;
- }
- if (fx->dof_nearfar_coc) {
- GPU_texture_free(fx->dof_nearfar_coc);
- fx->dof_nearfar_coc = NULL;
- }
- if (fx->dof_near_blur) {
- GPU_texture_free(fx->dof_near_blur);
- fx->dof_near_blur = NULL;
- }
- if (fx->dof_far_blur) {
- GPU_texture_free(fx->dof_far_blur);
- fx->dof_far_blur = NULL;
- }
-}
-
-static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
-{
- if (fx->color_buffer) {
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_texture_free(fx->color_buffer);
- fx->color_buffer = NULL;
- }
-
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
-
- if (fx->depth_buffer) {
- GPU_framebuffer_texture_detach(fx->depth_buffer);
- GPU_texture_free(fx->depth_buffer);
- fx->depth_buffer = NULL;
- }
-
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
-
- cleanup_fx_dof_buffers(fx);
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
-
- if (fx->jitter_buffer && do_fbo) {
- GPU_texture_free(fx->jitter_buffer);
- fx->jitter_buffer = NULL;
- }
-
- if (fx->gbuffer && do_fbo) {
- GPU_framebuffer_free(fx->gbuffer);
- fx->gbuffer = NULL;
- }
-}
-
-/* destroy a text compositor */
-void GPU_fx_compositor_destroy(GPUFX *fx)
-{
- cleanup_fx_gl_data(fx, true);
- GWN_batch_discard(fx->quad_batch);
- GWN_batch_discard(fx->point_batch);
- MEM_freeN(fx);
-}
-
-static GPUTexture * create_jitter_texture(void)
-{
- GPUTexture *tex;
- float jitter[64 * 64][2];
- int i;
-
- for (i = 0; i < 64 * 64; i++) {
- jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
- jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
- normalize_v2(jitter[i]);
- }
-
- tex = GPU_texture_create_2D_custom(64, 64, 2, GPU_RG16F, &jitter[0][0], NULL);
-
- /* Set parameters */
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, false);
- GPU_texture_wrap_mode(tex, true);
- GPU_texture_unbind(tex);
-
- return tex;
-}
-
-
-bool GPU_fx_compositor_initialize_passes(
- GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
- const GPUFXSettings *fx_settings)
-{
- int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
- char err_out[256];
- int num_passes = 0;
- char fx_flag;
-
- fx->effects = 0;
-
- if (!fx_settings) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- fx_flag = fx_settings->fx_flag;
-
- /* disable effects if no options passed for them */
- if (!fx_settings->dof) {
- fx_flag &= ~GPU_FX_FLAG_DOF;
- }
- if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
- fx_flag &= ~GPU_FX_FLAG_SSAO;
- }
-
- if (!fx_flag) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
- * add one to match viewport dimensions */
- if (scissor_rect) {
- w++;
- h++;
- }
-
- fx->num_passes = 0;
- /* dof really needs a ping-pong buffer to work */
- if (fx_flag & GPU_FX_FLAG_DOF)
- num_passes++;
-
- if (fx_flag & GPU_FX_FLAG_SSAO)
- num_passes++;
-
- if (!fx->gbuffer) {
- fx->gbuffer = GPU_framebuffer_create();
-
- if (!fx->gbuffer) {
- return false;
- }
- }
-
- /* try creating the jitter texture */
- if (!fx->jitter_buffer)
- fx->jitter_buffer = create_jitter_texture();
-
- /* check if color buffers need recreation */
- if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
- cleanup_fx_gl_data(fx, false);
-
- if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
-
- if (fx_flag & GPU_FX_FLAG_SSAO) {
- if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
- if (fx_settings->ssao->samples < 1)
- fx_settings->ssao->samples = 1;
-
- fx->ssao_sample_count_cache = fx_settings->ssao->samples;
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- }
-
- fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
- }
- }
- else {
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
- }
-
- /* create textures for dof effect */
- if (fx_flag & GPU_FX_FLAG_DOF) {
- bool dof_high_quality = (fx_settings->dof->high_quality != 0);
-
- /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
- if (dof_high_quality != fx->dof_high_quality)
- cleanup_fx_dof_buffers(fx);
-
- if (dof_high_quality) {
- fx->dof_downsampled_w = w / 2;
- fx->dof_downsampled_h = h / 2;
-
- if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
- !fx->dof_far_blur || !fx->dof_half_downsampled_far)
- {
-
- if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RG16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- GPU_texture_bind(fx->dof_nearfar_coc, 0);
- GPU_texture_filter_mode(fx->dof_nearfar_coc, false);
- GPU_texture_wrap_mode(fx->dof_nearfar_coc, false);
- GPU_texture_unbind(fx->dof_nearfar_coc);
-
- if (!(fx->dof_near_blur = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 4, GPU_RGBA16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->dof_far_blur = GPU_texture_create_2D_custom(
- fx->dof_downsampled_w, fx->dof_downsampled_h, 4, GPU_RGBA16F, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- fx->dof_downsampled_w = w / 4;
- fx->dof_downsampled_h = h / 4;
-
- if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
-
- if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
-
- fx->dof_high_quality = dof_high_quality;
- }
- else {
- /* cleanup unnecessary buffers */
- cleanup_fx_dof_buffers(fx);
- }
-
- /* we need to pass data between shader stages, allocate an extra color buffer */
- if (num_passes > 1) {
- if (!fx->color_buffer_sec) {
- if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
- }
-
- /* bind the buffers */
-
- /* first depth buffer, because system assumes read/write buffers */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, 0);
-
- if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
- printf("%.256s\n", err_out);
-
- GPU_texture_bind_as_framebuffer(fx->color_buffer);
-
- /* enable scissor test. It's needed to ensure sculpting works correctly */
- if (scissor_rect) {
- int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
- int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
- gpuPushAttrib(GPU_SCISSOR_BIT);
- glEnable(GL_SCISSOR_TEST);
- glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
- w_sc, h_sc);
- fx->restore_stencil = true;
- }
- else {
- fx->restore_stencil = false;
- }
-
- fx->effects = fx_flag;
-
- if (fx_settings)
- fx->settings = *fx_settings;
- fx->gbuffer_dim[0] = w;
- fx->gbuffer_dim[1] = h;
-
- fx->num_passes = num_passes;
-
- return true;
-}
-
-static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
-{
- if ((*passes_left)-- == 1) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else
- GPU_framebuffer_restore();
- }
- else {
- /* bind the ping buffer to the color buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, 0);
- }
-}
-
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
-{
- char err_out[256];
-
- if (do_xray) {
- if (!fx->depth_buffer_xray &&
- !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return;
- }
- }
- else {
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
- return;
- }
-
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- /* first depth buffer, because system assumes read/write buffers */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, 0);
-}
-
-
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
-{
- GPUShader *depth_resolve_shader;
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
-
- /* attach regular framebuffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
-
- /* full screen quad where we will always write to depth buffer */
- gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_SCISSOR_BIT);
- glDepthFunc(GL_ALWAYS);
- /* disable scissor from sculpt if any */
- glDisable(GL_SCISSOR_TEST);
- /* disable writing to color buffer, it's depth only pass */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
-
- if (depth_resolve_shader) {
- GPUDepthResolveInterface *interface = GPU_fx_shader_get_interface(depth_resolve_shader);
-
- /* set up quad buffer */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(depth_resolve_shader), GPU_shader_get_interface(depth_resolve_shader));
-
- GPU_texture_bind(fx->depth_buffer_xray, 0);
- GPU_texture_compare_mode(fx->depth_buffer_xray, false);
- GPU_texture_filter_mode(fx->depth_buffer_xray, true);
- GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
-
- /* draw */
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_compare_mode(fx->depth_buffer_xray, true);
- GPU_texture_filter_mode(fx->depth_buffer_xray, false);
- GPU_texture_unbind(fx->depth_buffer_xray);
-
- GPU_shader_unbind();
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- gpuPopAttrib();
-}
-
-
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs)
-{
- GPUTexture *src, *target;
- int numslots = 0;
- float invproj[4][4];
- int i;
- float dfdyfac[2];
- /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
- int passes_left = fx->num_passes;
- /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
-
- if (fx->effects == 0)
- return false;
-
- GPU_get_dfdy_factors(dfdyfac);
- /* first, unbind the render-to-texture framebuffer */
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- if (fx->restore_stencil) {
- gpuPopAttrib();
- }
-
- src = fx->color_buffer;
- target = fx->color_buffer_sec;
-
- /* full screen FX pass */
-
- /* invert the view matrix */
- invert_m4_m4(invproj, projmat);
-
- /* convert the view vectors to view space */
- for (i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
- /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
- if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
- }
-
- /* we need to store the differences */
- viewvecs[1][0] -= viewvecs[0][0];
- viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
-
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
- }
-
- glDisable(GL_DEPTH_TEST);
-
- /* ssao pass */
- if (fx->effects & GPU_FX_FLAG_SSAO) {
- GPUShader *ssao_shader;
- ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
- if (ssao_shader) {
- const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
- /* adjust attenuation to be scale invariant */
- float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max);
- float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f};
- float sample_params[3];
-
- sample_params[0] = fx->ssao_sample_count_cache;
- /* multiplier so we tile the random texture on screen */
- sample_params[1] = fx->gbuffer_dim[0] / 64.0;
- sample_params[2] = fx->gbuffer_dim[1] / 64.0;
-
- ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
-
- GPUSSAOShaderInterface *interface = GPU_fx_shader_get_interface(ssao_shader);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(ssao_shader), GPU_shader_get_interface(ssao_shader));
-
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
- GPU_shader_uniform_vector(ssao_shader, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_sample_params_uniform, 3, 1, sample_params);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->jitter_buffer, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_jitter_uniform, fx->jitter_buffer);
-
- GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_concentric_tex, fx->ssao_spiral_samples_tex);
-
- /* draw */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
- GPU_texture_unbind(fx->jitter_buffer);
- GPU_texture_unbind(fx->ssao_spiral_samples_tex);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- /* swap here, after src/target have been unbound */
- SWAP(GPUTexture *, target, src);
- numslots = 0;
- }
- }
-
- /* second pass, dof */
- if (fx->effects & GPU_FX_FLAG_DOF) {
- const GPUDOFSettings *fx_dof = fx->settings.dof;
- float dof_params[4];
- float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
- /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
- * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
- * because the shader reads coordinates in world space, which is in blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
- float scale_camera = 0.001f / scale;
- /* we want radius here for the aperture number */
- float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
-
- dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length /
- (fx_dof->focus_distance - scale_camera * fx_dof->focal_length));
- dof_params[1] = fx_dof->focus_distance;
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
- dof_params[3] = fx_dof->num_blades;
-
- if (fx->dof_high_quality) {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
-
- /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
-
- GPU_shader_unbind();
- return false;
- }
-
- /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- /* disable filtering for the texture so custom downsample can do the right thing */
- GPU_texture_filter_mode(src, false);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, 0);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, 0);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_framebuffer_slots_bind(fx->gbuffer, 0);
-
- GPU_framebuffer_check_valid(fx->gbuffer, NULL);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_filter_mode(src, true);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
-
- numslots = 0;
- }
-
- /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
- * to circle of confusion */
- {
- int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
- float selection[2] = {0.0f, 1.0f};
-
- GPUDOFHQPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
-
- GWN_batch_program_set(fx->point_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
- GPU_texture_filter_mode(fx->dof_half_downsampled_far, false);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, 0);
- GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
-
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glPointSize(1.0f);
- /* have to clear the buffer unfortunately */
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
-
- GPU_texture_unbind(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_far_blur);
-
- selection[0] = 1.0f;
- selection[1] = 0.0f;
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, 0);
- /* have to clear the buffer unfortunately */
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, 0, NULL, NULL);
- GWN_batch_program_use_end(fx->point_batch);
-
- /* disable bindings */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
-
- GPU_framebuffer_texture_detach(fx->dof_near_blur);
-
- GPU_texture_unbind(fx->dof_half_downsampled_near);
- GPU_texture_unbind(fx->dof_nearfar_coc);
-
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
- numslots = 0;
- }
-
- /* third pass, accumulate the near/far blur fields */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass3, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->dof_near_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
- GPU_texture_filter_mode(fx->dof_near_blur, true);
-
- GPU_texture_bind(fx->dof_far_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
- GPU_texture_filter_mode(fx->dof_far_blur, true);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->color_uniform, src);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_blur);
- GPU_texture_unbind(fx->dof_far_blur);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- numslots = 0;
- }
- }
- else {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
-
- /* DOF effect has many passes but most of them are performed
- * on a texture whose dimensions are 4 times less than the original
- * (16 times lower than original screen resolution).
- * Technique used is not very exact but should be fast enough and is based
- * on "Practical Post-Process Depth of Field"
- * see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
- dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
- dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
-
- GPU_shader_unbind();
- return false;
- }
-
- /* pass first, first level of blur in low res buffer */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
- numslots = 0;
- }
-
- /* second pass, gaussian blur the downsampled image */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
- float tmp = invrendertargetdim[0];
- invrendertargetdim[0] = 0.0f;
-
- GPUDOFPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
-
- dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
-
- /* Blurring vertically */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
-
- /* use final buffer as a temp here */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
-
- /* Drawing quad */
- GWN_batch_draw(fx->quad_batch);
-
- /* Rebind Shader */
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
-
- /* *unbind/detach */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- /* Blurring horizontally */
- invrendertargetdim[0] = tmp;
- invrendertargetdim[1] = 0.0f;
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
-
- /* *unbind/detach */
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
-
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
-
- numslots = 0;
- }
-
- /* third pass, calculate near coc */
- {
- GPUDOFPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- numslots = 0;
- }
-
- /* fourth pass blur final coc once to eliminate discontinuities */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
-
- GPUDOFPassFourInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass4);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass4), GPU_shader_get_interface(dof_shader_pass4));
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
- GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
-
- numslots = 0;
- }
-
- /* final pass, merge blurred layers according to final calculated coc */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassFiveInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass5);
-
- GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass5), GPU_shader_get_interface(dof_shader_pass5));
-
- GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->original_uniform, src);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_compare_mode(fx->depth_buffer, false);
- GPU_texture_filter_mode(fx->depth_buffer, true);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- GWN_batch_draw(fx->quad_batch);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
- GPU_texture_unbind(src);
- GPU_texture_compare_mode(fx->depth_buffer, true);
- GPU_texture_filter_mode(fx->depth_buffer, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* may not be attached, in that case this just returns */
- if (target) {
- GPU_framebuffer_texture_detach(target);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else {
- GPU_framebuffer_restore();
- }
- }
-
- SWAP(GPUTexture *, target, src);
- numslots = 0;
- }
- }
- }
-
- GPU_shader_unbind();
-
- return true;
-}
-
-void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
-{
- fx_dof->fstop = 128.0f;
- fx_dof->focal_length = 1.0f;
- fx_dof->focus_distance = 1.0f;
- fx_dof->sensor = 1.0f;
- fx_dof->num_blades = 6;
- fx_dof->ratio = 1.0f;
-}
-
-void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
-{
- fx_ssao->factor = 1.0f;
- fx_ssao->distance_max = 0.2f;
- fx_ssao->attenuation = 1.0f;
- fx_ssao->samples = 20;
-}
-
-void GPU_fx_shader_init_interface(GPUShader *shader, GPUFXShaderEffect effect)
-{
- if (!shader)
- return;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- {
- GPUSSAOShaderInterface *interface = MEM_mallocN(sizeof(GPUSSAOShaderInterface), "GPUSSAOShaderInterface");
-
- interface->ssao_uniform = GPU_shader_get_uniform(shader, "ssao_params");
- interface->ssao_color_uniform = GPU_shader_get_uniform(shader, "ssao_color");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->ssao_sample_params_uniform = GPU_shader_get_uniform(shader, "ssao_sample_params");
- interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
- interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- {
- GPUDOFHQPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassOneInterface), "GPUDOFHQPassOneInterface");
-
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- {
- GPUDOFHQPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassTwoInterface), "GPUDOFHQPassTwoInterface");
-
- interface->rendertargetdim_uniform = GPU_shader_get_uniform(shader, "rendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->coc_uniform = GPU_shader_get_uniform(shader, "cocbuffer");
- interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- {
- GPUDOFHQPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassThreeInterface), "GPUDOFHQPassThreeInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->far_uniform = GPU_shader_get_uniform(shader, "farbuffer");
- interface->near_uniform = GPU_shader_get_uniform(shader, "nearbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- {
- GPUDOFPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFPassOneInterface), "GPUDOFPassOneInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- {
- GPUDOFPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFPassTwoInterface), "GPUDOFPassTwoInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- {
- GPUDOFPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFPassThreeInterface), "GPUDOFPassThreeInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- {
- GPUDOFPassFourInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFourInterface), "GPUDOFPassFourInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- {
- GPUDOFPassFiveInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFiveInterface), "GPUDOFPassFiveInterface");
-
- interface->medium_blurred_uniform = GPU_shader_get_uniform(shader, "mblurredcolorbuffer");
- interface->high_blurred_uniform = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->original_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- {
- GPUDepthResolveInterface *interface = MEM_mallocN(sizeof(GPUDepthResolveInterface), "GPUDepthResolveInterface");
-
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_fx_shader_set_interface(shader, interface);
- break;
- }
-
- default:
- break;
- }
-}
-
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index f9cf3235ac1..8b344716a9c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -39,11 +39,11 @@
#include <string.h>
#include "BLI_blenlib.h"
+#include "BLI_hash.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_hash.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -398,7 +398,7 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
if (alphablend == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else if (alphablend == GPU_BLEND_ADD) {
glEnable(GL_BLEND);
@@ -1319,9 +1319,9 @@ static LinkNode *image_free_queue = NULL;
static void gpu_queue_image_for_free(Image *ima)
{
- BLI_lock_thread(LOCK_OPENGL);
+ BLI_thread_lock(LOCK_OPENGL);
BLI_linklist_prepend(&image_free_queue, ima);
- BLI_unlock_thread(LOCK_OPENGL);
+ BLI_thread_unlock(LOCK_OPENGL);
}
void GPU_free_unused_buffers(void)
@@ -1329,7 +1329,7 @@ void GPU_free_unused_buffers(void)
if (!BLI_thread_is_main())
return;
- BLI_lock_thread(LOCK_OPENGL);
+ BLI_thread_lock(LOCK_OPENGL);
/* images */
for (LinkNode *node = image_free_queue; node; node = node->next) {
@@ -1346,7 +1346,7 @@ void GPU_free_unused_buffers(void)
/* vbo buffers */
GPU_global_buffer_pool_free_unused();
- BLI_unlock_thread(LOCK_OPENGL);
+ BLI_thread_unlock(LOCK_OPENGL);
}
void GPU_free_image(Image *ima)
@@ -1734,6 +1734,8 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
pi->scalprops[3] = p->size;
copy_v3_v3(pi->location, p->state.co);
+ pi->location[3] = BLI_hash_int_01(ind);
+
copy_v3_v3(pi->velocity, p->state.vel);
copy_v3_v3(pi->angular_velocity, p->state.ave);
return 1;
@@ -2093,7 +2095,7 @@ int GPU_scene_object_lights(ViewLayer *view_layer, float viewmat[4][4], int orth
return count;
}
-static void gpu_multisample(bool enable)
+static void gpu_disable_multisample(void)
{
#ifdef __linux__
/* changing multisample from the default (enabled) causes problems on some
@@ -2109,16 +2111,10 @@ static void gpu_multisample(bool enable)
}
if (toggle_ok) {
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
}
#else
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
#endif
}
@@ -2150,7 +2146,7 @@ void GPU_state_init(void)
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
- gpu_multisample(false);
+ gpu_disable_multisample();
}
void GPU_enable_program_point_size(void)
@@ -2385,7 +2381,7 @@ static GPUAttribStack state = {
};
#define AttribStack state
-#define Gwn_VertAttr state.attrib_stack[state.top]
+#define Attrib state.attrib_stack[state.top]
/**
* Replacement for glPush/PopAttributes
@@ -2395,48 +2391,48 @@ static GPUAttribStack state = {
*/
void gpuPushAttrib(eGPUAttribMask mask)
{
- Gwn_VertAttr.mask = mask;
+ Attrib.mask = mask;
if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- glGetIntegerv(GL_DEPTH_FUNC, &Gwn_VertAttr.depth_func);
- glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Gwn_VertAttr.depth_clear_value);
- glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Gwn_VertAttr.depth_write_mask);
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_FUNC, &Attrib.depth_func);
+ glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attrib.depth_clear_value);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attrib.depth_write_mask);
}
if ((mask & GPU_ENABLE_BIT) != 0) {
- Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
for (int i = 0; i < 6; i++) {
- Gwn_VertAttr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
+ Attrib.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
}
- Gwn_VertAttr.is_cull_face = glIsEnabled(GL_CULL_FACE);
- Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
- Gwn_VertAttr.is_dither = glIsEnabled(GL_DITHER);
- Gwn_VertAttr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
- Gwn_VertAttr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
- Gwn_VertAttr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
- Gwn_VertAttr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
- Gwn_VertAttr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
- Gwn_VertAttr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
- Gwn_VertAttr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
- Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- Gwn_VertAttr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ Attrib.is_cull_face = glIsEnabled(GL_CULL_FACE);
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ Attrib.is_dither = glIsEnabled(GL_DITHER);
+ Attrib.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
+ Attrib.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
+ Attrib.is_multisample = glIsEnabled(GL_MULTISAMPLE);
+ Attrib.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
+ Attrib.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
+ Attrib.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
+ Attrib.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ Attrib.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
}
if ((mask & GPU_SCISSOR_BIT) != 0) {
- Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
- glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Gwn_VertAttr.scissor_box);
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attrib.scissor_box);
}
if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Gwn_VertAttr.near_far);
- glGetIntegerv(GL_VIEWPORT, (GLint *)&Gwn_VertAttr.viewport);
+ glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attrib.near_far);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)&Attrib.viewport);
}
if ((mask & GPU_BLEND_BIT) != 0) {
- Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
}
BLI_assert(AttribStack.top < STATE_STACK_DEPTH);
@@ -2458,52 +2454,52 @@ void gpuPopAttrib(void)
BLI_assert(AttribStack.top > 0);
AttribStack.top--;
- GLint mask = Gwn_VertAttr.mask;
+ GLint mask = Attrib.mask;
if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
- restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
- glDepthFunc(Gwn_VertAttr.depth_func);
- glClearDepth(Gwn_VertAttr.depth_clear_value);
- glDepthMask(Gwn_VertAttr.depth_write_mask);
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ glDepthFunc(Attrib.depth_func);
+ glClearDepth(Attrib.depth_clear_value);
+ glDepthMask(Attrib.depth_write_mask);
}
if ((mask & GPU_ENABLE_BIT) != 0) {
- restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+ restore_mask(GL_BLEND, Attrib.is_blend);
for (int i = 0; i < 6; i++) {
- restore_mask(GL_CLIP_PLANE0 + i, Gwn_VertAttr.is_clip_plane[i]);
+ restore_mask(GL_CLIP_PLANE0 + i, Attrib.is_clip_plane[i]);
}
- restore_mask(GL_CULL_FACE, Gwn_VertAttr.is_cull_face);
- restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
- restore_mask(GL_DITHER, Gwn_VertAttr.is_dither);
- restore_mask(GL_LINE_SMOOTH, Gwn_VertAttr.is_line_smooth);
- restore_mask(GL_COLOR_LOGIC_OP, Gwn_VertAttr.is_color_logic_op);
- restore_mask(GL_MULTISAMPLE, Gwn_VertAttr.is_multisample);
- restore_mask(GL_POLYGON_OFFSET_LINE, Gwn_VertAttr.is_polygon_offset_line);
- restore_mask(GL_POLYGON_OFFSET_FILL, Gwn_VertAttr.is_polygon_offset_fill);
- restore_mask(GL_POLYGON_SMOOTH, Gwn_VertAttr.is_polygon_smooth);
- restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Gwn_VertAttr.is_sample_alpha_to_coverage);
- restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
- restore_mask(GL_STENCIL_TEST, Gwn_VertAttr.is_stencil_test);
+ restore_mask(GL_CULL_FACE, Attrib.is_cull_face);
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ restore_mask(GL_DITHER, Attrib.is_dither);
+ restore_mask(GL_LINE_SMOOTH, Attrib.is_line_smooth);
+ restore_mask(GL_COLOR_LOGIC_OP, Attrib.is_color_logic_op);
+ restore_mask(GL_MULTISAMPLE, Attrib.is_multisample);
+ restore_mask(GL_POLYGON_OFFSET_LINE, Attrib.is_polygon_offset_line);
+ restore_mask(GL_POLYGON_OFFSET_FILL, Attrib.is_polygon_offset_fill);
+ restore_mask(GL_POLYGON_SMOOTH, Attrib.is_polygon_smooth);
+ restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attrib.is_sample_alpha_to_coverage);
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ restore_mask(GL_STENCIL_TEST, Attrib.is_stencil_test);
}
if ((mask & GPU_VIEWPORT_BIT) != 0) {
- glViewport(Gwn_VertAttr.viewport[0], Gwn_VertAttr.viewport[1], Gwn_VertAttr.viewport[2], Gwn_VertAttr.viewport[3]);
- glDepthRange(Gwn_VertAttr.near_far[0], Gwn_VertAttr.near_far[1]);
+ glViewport(Attrib.viewport[0], Attrib.viewport[1], Attrib.viewport[2], Attrib.viewport[3]);
+ glDepthRange(Attrib.near_far[0], Attrib.near_far[1]);
}
if ((mask & GPU_SCISSOR_BIT) != 0) {
- restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
- glScissor(Gwn_VertAttr.scissor_box[0], Gwn_VertAttr.scissor_box[1], Gwn_VertAttr.scissor_box[2], Gwn_VertAttr.scissor_box[3]);
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ glScissor(Attrib.scissor_box[0], Attrib.scissor_box[1], Attrib.scissor_box[2], Attrib.scissor_box[3]);
}
if ((mask & GPU_BLEND_BIT) != 0) {
- restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+ restore_mask(GL_BLEND, Attrib.is_blend);
}
}
-#undef Gwn_VertAttr
+#undef Attrib
#undef AttribStack
/** \} */
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 57df877bf18..73e86c1b391 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -149,7 +149,7 @@ void gpu_extensions_init(void)
else
GG.max_anisotropy = 1.0f;
- glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds);
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
#ifndef NDEBUG
@@ -178,14 +178,6 @@ void gpu_extensions_init(void)
GG.device = GPU_DEVICE_ATI;
GG.driver = GPU_DRIVER_OFFICIAL;
}
- /* XXX : TODO : Remove this once this sampling mipmap problem is gone.
- * https://github.com/dfelinto/opengl-sandbox/blob/downsample/README.md */
- else if (strstr(renderer, "AMD VEGA") &&
- strstr(vendor, "X.Org"))
- {
- GG.device = GPU_DEVICE_AMD_VEGA;
- GG.driver = GPU_DRIVER_OPENSOURCE;
- }
else if (strstr(vendor, "NVIDIA")) {
GG.device = GPU_DEVICE_NVIDIA;
GG.driver = GPU_DRIVER_OFFICIAL;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 09013cd29bd..8d8fb50d9b9 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -28,7 +28,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BKE_global.h"
@@ -40,20 +42,91 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
-static struct GPUFrameBufferGlobal {
- GLuint currentfb;
-} GG = {0};
+static ThreadLocal(GLuint) g_currentfb;
-/* Number of maximum output slots.
- * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 5
+typedef enum {
+ GPU_FB_DEPTH_ATTACHMENT = 0,
+ GPU_FB_DEPTH_STENCIL_ATTACHMENT,
+ GPU_FB_COLOR_ATTACHMENT0,
+ GPU_FB_COLOR_ATTACHMENT1,
+ GPU_FB_COLOR_ATTACHMENT2,
+ GPU_FB_COLOR_ATTACHMENT3,
+ GPU_FB_COLOR_ATTACHMENT4,
+ /* Number of maximum output slots.
+ * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
+ * the maximum number of COLOR attachments specified by glDrawBuffers. */
+ GPU_FB_MAX_ATTACHEMENT
+} GPUAttachmentType;
+
+#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
+
+#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15)
+
+#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0)
+#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
GLuint object;
- GPUTexture *colortex[GPU_FB_MAX_SLOTS];
- GPUTexture *depthtex;
+ GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
+ uint16_t dirty_flag;
+ int width, height;
+ bool multisample;
+ /* TODO Check that we always use the right context when binding
+ * (FBOs are not shared accross ogl contexts). */
+ // void *ctx;
};
+static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
+{
+ static const GLenum table[] = {
+ [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
+ [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
+ [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
+ [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
+ [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
+ [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
+ [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4
+ };
+ return table[type];
+}
+
+static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
+{
+ switch (GPU_texture_format(tex)) {
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ return GPU_FB_DEPTH_ATTACHMENT;
+ case GPU_DEPTH24_STENCIL8:
+ return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ return GPU_FB_COLOR_ATTACHMENT0 + slot;
+ }
+}
+
+static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
+{
+ GLbitfield mask = 0;
+ mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
+ mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
+ mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
+ return mask;
+}
+
+static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
+{
+ if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
+ return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
+ else
+ return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;;
+}
+
+static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
+{
+ return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
+}
+
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
const char *format = "GPUFrameBuffer: framebuffer status %s\n";
@@ -94,296 +167,268 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
GPUFrameBuffer *GPU_framebuffer_create(void)
{
- GPUFrameBuffer *fb;
+ /* We generate the FB object later at first use in order to
+ * create the framebuffer in the right opengl context. */
+ return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");;
+}
- fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+static void gpu_framebuffer_init(GPUFrameBuffer *fb)
+{
glGenFramebuffers(1, &fb->object);
-
- if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
- GPU_framebuffer_free(fb);
- return NULL;
- }
-
- /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glReadBuffer(GL_NONE);
- glDrawBuffer(GL_NONE);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return fb;
}
-bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
- GLenum attachment;
-
- if (slot >= GPU_FB_MAX_SLOTS) {
- fprintf(stderr,
- "Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
+ if (fb->attachments[type].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
}
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
+ /* This restores the framebuffer if it was bound */
+ glDeleteFramebuffers(1, &fb->object);
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (g_currentfb == fb->object) {
+ g_currentfb = 0;
+ }
- return true;
+ MEM_freeN(fb);
}
-static bool gpu_framebuffer_texture_layer_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip, bool cubemap)
-{
- GLenum attachment;
- GLenum facetarget;
+/* ---------- Attach ----------- */
- if (slot >= GPU_FB_MAX_SLOTS) {
+static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return false;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
- }
+ "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
+ return;
}
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0 + slot;
+ GPUAttachmentType type = attachment_type_from_tex(tex, slot);
+ GPUAttachment *attachment = &fb->attachments[type];
- if (cubemap) {
- facetarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, facetarget, GPU_texture_opengl_bindcode(tex), mip);
+ if ((attachment->tex == tex) &&
+ (attachment->mip == mip) &&
+ (attachment->layer == layer))
+ {
+ return; /* Exact same texture already bound here. */
}
- else {
- glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip, layer);
+ else if (attachment->tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, attachment->tex);
}
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
-
- GPU_texture_framebuffer_set(tex, fb, slot);
+ if (attachment->tex == NULL) {
+ GPU_texture_attach_framebuffer(tex, fb, type);
+ }
- return true;
+ attachment->tex = tex;
+ attachment->mip = mip;
+ attachment->layer = layer;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
}
-bool GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, layer, mip, false);
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
}
-bool GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
+void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
{
- BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP);
- return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, face, mip, true);
+ /* NOTE: We could support 1D ARRAY texture. */
+ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY);
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip);
}
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
+void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
{
- GLenum attachment;
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ BLI_assert(GPU_texture_cube(tex));
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
+}
- if (!fb)
- return;
+/* ---------- Detach ----------- */
- if (GG.currentfb != fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
- }
+void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type)
+{
+ GPUAttachment *attachment = &fb->attachments[type];
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- }
- else if (GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT;
- }
- else {
- BLI_assert(fb->colortex[fb_attachment] == tex);
- fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
+ if (attachment->tex != tex) {
+ fprintf(stderr,
+ "Warning, attempting to detach Texture %p from framebuffer %p "
+ "but texture is not attached.\n", tex, fb);
+ return;
}
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ attachment->tex = NULL;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+}
- GPU_texture_framebuffer_set(tex, NULL, -1);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+{
+ GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
+ GPU_framebuffer_texture_detach_slot(fb, tex, type);
}
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+/* ---------- Config (Attach & Detach) ----------- */
+
+/**
+ * First GPUAttachment in *config is always the depth/depth_stencil buffer.
+ * Following GPUAttachments are color buffers.
+ * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
+ * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
+ **/
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct)
{
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ if (config[0].tex) {
+ BLI_assert(GPU_texture_depth(config[0].tex));
+ gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip);
+ }
+ else if (config[0].mip == -1) {
+ /* Leave texture attached */
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex);
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
+ }
- if (!fb) {
- fprintf(stderr, "Error, texture not bound to framebuffer!\n");
- return;
+ int slot = 0;
+ for (int i = 1; i < config_ct; ++i, ++slot) {
+ if (config[i].tex != NULL) {
+ BLI_assert(GPU_texture_depth(config[i].tex) == false);
+ gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip);
+ }
+ else if (config[i].mip != -1) {
+ GPUTexture *tex = framebuffer_get_color_tex(fb, slot);
+ if (tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, tex);
+ }
+ }
}
+}
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
+/* ---------- Bind / Restore ----------- */
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
+{
+ int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
+ if (attach->layer > -1) {
+ if (GPU_texture_cube(attach->tex)) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind, attach->mip);
+ }
+ else {
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
+ }
}
else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
- }
-
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
- glEnable(GL_MULTISAMPLE);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
}
+}
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GG.currentfb = fb->object;
+static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
+{
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
}
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
-
- if (!fb->colortex[slot]) {
- fprintf(stderr, "Error, framebuffer slot empty!\n");
- return;
- }
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int numslots = 0;
+
+ BLI_assert(g_currentfb == fb->object);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ if (fb->attachments[type].tex) {
+ gl_attachments[numslots] = convert_attachment_type_to_gl(type);
+ }
+ else {
+ gl_attachments[numslots] = GL_NONE;
+ }
numslots++;
}
- }
-
- /* push attributes */
- gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
+ continue;
+ }
+ else if (fb->attachments[type].tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
+ fb->width = GPU_texture_width(fb->attachments[type].tex);
+ fb->height = GPU_texture_height(fb->attachments[type].tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
+ }
+ fb->dirty_flag = 0;
- /* set default viewport */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ if (numslots)
+ glDrawBuffers(numslots, gl_attachments);
+ else
+ glDrawBuffer(GL_NONE);
}
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[GPU_FB_MAX_SLOTS];
- GLenum readattachement = 0;
- GPUTexture *tex;
+ if (fb->object == 0)
+ gpu_framebuffer_init(fb);
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
- tex = fb->colortex[i];
+ if (g_currentfb != fb->object)
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- if (!readattachement)
- readattachement = GL_COLOR_ATTACHMENT0 + i;
+ g_currentfb = fb->object;
- numslots++;
- }
- }
-
- /* bind framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (fb->dirty_flag != 0)
+ gpu_framebuffer_update_attachments(fb);
- if (numslots == 0) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- tex = fb->depthtex;
- }
- else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(readattachement);
+ /* TODO manually check for errors? */
+#if 0
+ char err_out[256];
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
+ printf("Invalid %s\n", err_out);
}
+#endif
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+ if (fb->multisample)
glEnable(GL_MULTISAMPLE);
- }
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GG.currentfb = fb->object;
+ glViewport(0, 0, fb->width, fb->height);
}
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+void GPU_framebuffer_restore(void)
{
- /* Restore attributes. */
- gpuPopAttrib();
+ if (g_currentfb != 0) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ g_currentfb = 0;
+ }
}
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
+ return (fb->object == g_currentfb) && (fb->object != 0);
}
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
+unsigned int GPU_framebuffer_current_get(void)
{
- return fb->object == GG.currentfb;
+ return g_currentfb;
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
+ if (!GPU_framebuffer_bound(fb))
+ GPU_framebuffer_bind(fb);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -396,172 +441,140 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
return true;
}
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
-{
- int i;
- if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb->depthtex);
-
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- GPU_framebuffer_texture_detach(fb->colortex[i]);
- }
- }
+/* ---------- Framebuffer Operations ----------- */
- if (fb->object) {
- glDeleteFramebuffers(1, &fb->object);
+#define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
+ BLI_assert(GPU_framebuffer_bound(_fb)); \
+ UNUSED_VARS_NDEBUG(_fb);
- if (GG.currentfb == fb->object) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- GG.currentfb = 0;
- }
- }
+/* Needs to be done after binding. */
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- MEM_freeN(fb);
+ glViewport(x, y, w, h);
}
-void GPU_framebuffer_restore(void)
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil)
{
- if (GG.currentfb != 0) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- GG.currentfb = 0;
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ if (buffers & GPU_COLOR_BIT) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (buffers & GPU_DEPTH_BIT) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
}
+ if (buffers & GPU_STENCIL_BIT) {
+ glStencilMask(clear_stencil);
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(buffers);
+ glClear(mask);
}
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, GPUTexture *tex,
- GPUFrameBuffer *blurfb, GPUTexture *blurtex)
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
{
- const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
- const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
-
- static Gwn_VertFormat format = {0};
- static Gwn_VertBuf vbo = {{0}};
- static Gwn_Batch batch = {{0}};
-
- const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
- const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
-
- GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- if (!blur_shader)
- return;
-
- /* Preparing to draw quad */
- if (format.attrib_ct == 0) {
- unsigned int i = 0;
- /* Vertex format */
- unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- /* Vertices */
- GWN_vertbuf_init_with_format(&vbo, &format);
- GWN_vertbuf_data_alloc(&vbo, 36);
-
- for (int j = 0; j < 3; ++j) {
- GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
- GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
- }
- for (int j = 1; j < 4; ++j) {
- GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
- GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
- }
+ GLenum type = GL_DEPTH_COMPONENT;
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
- GWN_batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type;
+ switch (channels) {
+ case 1: type = GL_RED; break;
+ case 2: type = GL_RG; break;
+ case 3: type = GL_RGB; break;
+ case 4: type = GL_RGBA; break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
}
-
- glDisable(GL_DEPTH_TEST);
-
- /* Blurring horizontally */
- /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
- * pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- /* avoid warnings from texture binding */
- GG.currentfb = blurfb->object;
-
- glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
- GPU_texture_bind(tex, 0);
+/* read_slot and write_slot are only used for color buffers. */
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers)
+{
+ BLI_assert(blit_buffers != 0);
- GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
- GWN_batch_uniform_2f(&batch, "ScaleU", scaleh[0], scaleh[1]);
- GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
- GWN_batch_draw(&batch);
+ GLuint prev_fb = g_currentfb;
- /* Blurring vertically */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
-
- GG.currentfb = fb->object;
-
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ /* Framebuffers must be up to date. This simplify this function. */
+ if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
+ GPU_framebuffer_bind(fb_read);
+ }
+ if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
+ GPU_framebuffer_bind(fb_write);
+ }
- GPU_texture_bind(blurtex, 0);
+ const bool do_color = (blit_buffers & GPU_COLOR_BIT);
+ const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
+ const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
- /* Hack to make the following uniform stick */
- GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
- GWN_batch_uniform_2f(&batch, "ScaleU", scalev[0], scalev[1]);
- GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
- GWN_batch_draw(&batch);
-}
+ GPUTexture *read_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_read)
+ : framebuffer_get_color_tex(fb_read, read_slot);
+ GPUTexture *write_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_write)
+ : framebuffer_get_color_tex(fb_write, read_slot);
-void GPU_framebuffer_blit(
- GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write,
- int write_slot, bool use_depth, bool use_stencil)
-{
- GPUTexture *read_tex = (use_depth || use_stencil) ? fb_read->depthtex : fb_read->colortex[read_slot];
- GPUTexture *write_tex = (use_depth || use_stencil) ? fb_write->depthtex : fb_write->colortex[write_slot];
- int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
- int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
- (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
- GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
- int read_bind = GPU_texture_opengl_bindcode(read_tex);
- int write_bind = GPU_texture_opengl_bindcode(write_tex);
- const int read_w = GPU_texture_width(read_tex);
- const int read_h = GPU_texture_height(read_tex);
- const int write_w = GPU_texture_width(write_tex);
- const int write_h = GPU_texture_height(write_tex);
-
-
- /* Never both! */
- BLI_assert(!(use_depth && use_stencil));
-
- if (use_depth) {
+ if (do_depth) {
BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
- else if (use_stencil) {
+ if (do_stencil) {
BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
}
+ if (GPU_texture_samples(write_tex) != 0 ||
+ GPU_texture_samples(read_tex) != 0)
+ {
+ /* Can only blit multisample textures to another texture of the same size. */
+ BLI_assert((fb_read->width == fb_write->width) &&
+ (fb_read->height == fb_write->height));
+ }
- /* read from multi-sample buffer */
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, read_attach,
- GPU_texture_target(read_tex), read_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-
- /* write into new single-sample buffer */
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, write_attach,
- GPU_texture_target(write_tex), write_bind, 0);
- BLI_assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
- glDrawBuffer((use_depth || use_stencil) ? GL_COLOR_ATTACHMENT0 : read_attach);
- glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h,
- (use_depth) ? GL_DEPTH_BUFFER_BIT :
- (use_stencil) ? GL_STENCIL_BUFFER_BIT :
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ if (do_color) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
+ /* XXX we messed with the glDrawBuffer, this will reset the
+ * glDrawBuffers the next time we bind fb_write. */
+ fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
+
+ glBlitFramebuffer(0, 0, fb_read->width, fb_read->height,
+ 0, 0, fb_write->width, fb_write->height,
+ mask, GL_NEAREST);
/* Restore previous framebuffer */
- glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ if (fb_write->object == prev_fb) {
+ GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
+ }
+ else {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
+ g_currentfb = prev_fb;
+ }
}
/**
@@ -569,77 +582,65 @@ void GPU_framebuffer_blit(
* This function only takes care of the correct texture handling. It execute the callback for each texture level.
**/
void GPU_framebuffer_recursive_downsample(
- GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void (*callback)(void *userData, int level), void *userData)
+ GPUFrameBuffer *fb, int max_lvl,
+ void (*callback)(void *userData, int level), void *userData)
{
- int i;
- int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
- GLenum attachment;
-
- /* Manually setup framebuffer to not use GPU_texture_framebuffer_set() */
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
- if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- else if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT;
- else
- attachment = GL_COLOR_ATTACHMENT0;
-
- /* last bound prevails here, better allow explicit control here too */
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0);
- glReadBuffer(GL_COLOR_ATTACHMENT0);
+ /* Framebuffer must be up to date and bound. This simplify this function. */
+ if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
+ GPU_framebuffer_bind(fb);
}
+ /* HACK: We make the framebuffer appear not bound in order to
+ * not trigger any error in GPU_texture_bind(). */
+ GLuint prev_fb = g_currentfb;
+ g_currentfb = 0;
- for (i = 1; i < num_iter + 1; i++) {
-
+ int i;
+ int current_dim[2] = {fb->width, fb->height};
+ for (i = 1; i < max_lvl + 1; i++) {
/* calculate next viewport size */
- current_dim[0] /= 2;
- current_dim[1] /= 2;
-
- if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
- /* NOTE : here 16 is because of a bug on AMD Vega GPU + non-pro drivers, that prevents us
- * from sampling mipmaps that are smaller or equal to 16px. (9) */
- if (current_dim[0] <= 16 && current_dim[1] <= 16) {
- break;
- }
- }
- else {
- if (current_dim[0] <= 2 && current_dim[1] <= 2) {
- /* Cannot reduce further. */
- break;
+ current_dim[0] = max_ii(current_dim[0] / 2, 1);
+ current_dim[1] = max_ii(current_dim[1] / 2, 1);
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* copy attachment and replace miplevel. */
+ GPUAttachment attachment = fb->attachments[type];
+ attachment.mip = i;
+ gpu_framebuffer_attachment_attach(&attachment, type);
}
}
- /* ensure that the viewport size is always at least 1x1 */
- CLAMP_MIN(current_dim[0], 1);
- CLAMP_MIN(current_dim[1], 1);
+ BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
glViewport(0, 0, current_dim[0], current_dim[1]);
-
- /* bind next level for rendering but first restrict fetches only to previous level */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
-
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), i);
-
callback(userData, i);
- }
- glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+ if (current_dim[0] == 1 && current_dim[1] == 1)
+ break;
+ }
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* reset mipmap level range */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* Reattach original level */
+ /* NOTE: This is not necessary but this makes the FBO config
+ * remain in sync with the GPUFrameBuffer config. */
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+ }
+ }
- /* reset mipmap level range for the depth image */
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
+ g_currentfb = prev_fb;
}
/* GPUOffScreen */
@@ -650,55 +651,29 @@ struct GPUOffScreen {
GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool high_bitdepth, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
{
GPUOffScreen *ofs;
ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->fb = GPU_framebuffer_create();
- if (!ofs->fb) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (samples) {
- if (!GLEW_ARB_texture_multisample ||
- /* This is required when blitting from a multi-sampled buffers,
- * even though we're not scaling. */
- !GLEW_EXT_framebuffer_multisample_blit_scaled)
- {
- samples = 0;
- }
- }
-
- ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
- if (!ofs->depth) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4,
+ (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
- if (high_bitdepth) {
- ofs->color = GPU_texture_create_2D_custom_multisample(width, height, 4, GPU_RGBA16F, NULL, samples, err_out);
- }
- else {
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
- }
- if (!ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
+ if (depth) {
+ ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, 0)) {
+ if (!ofs->depth || !ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
+ GPU_framebuffer_ensure_config(&ofs->fb, {
+ GPU_ATTACHMENT_TEXTURE(ofs->depth),
+ GPU_ATTACHMENT_TEXTURE(ofs->color)
+ });
+
/* check validity at the very end! */
if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
GPU_offscreen_free(ofs);
@@ -724,20 +699,19 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
- glDisable(GL_SCISSOR_TEST);
- if (save)
- GPU_texture_bind_as_framebuffer(ofs->color);
- else {
- GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ if (save) {
+ gpuPushAttrib(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
}
+ glDisable(GL_SCISSOR_TEST);
+ GPU_framebuffer_bind(ofs->fb);
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
{
- if (restore)
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
+ if (restore) {
+ gpuPopAttrib();
+ }
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
@@ -745,46 +719,28 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
+ BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
/* For a multi-sample texture,
* we need to create an intermediate buffer to blit to,
* before its copied using 'glReadPixels' */
-
- /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
GLuint fbo_blit = 0;
GLuint tex_blit = 0;
- GLenum status;
/* create texture for new 'fbo_blit' */
glGenTextures(1, &tex_blit);
- if (!tex_blit) {
- goto finally;
- }
-
glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* read from multi-sample buffer */
- glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
- glFramebufferTexture2D(
- GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
- GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
+ w, h, 0, GL_RGBA, type, 0);
/* write into new single-sample buffer */
glGenFramebuffers(1, &fbo_blit);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
@@ -796,21 +752,13 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
finally:
/* cleanup */
- if (tex_blit) {
- glDeleteTextures(1, &tex_blit);
- }
- if (fbo_blit) {
- glDeleteFramebuffers(1, &fbo_blit);
- }
+ glDeleteTextures(1, &tex_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
@@ -827,9 +775,9 @@ int GPU_offscreen_height(const GPUOffScreen *ofs)
return GPU_texture_height(ofs->color);
}
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
{
- return GPU_texture_opengl_bindcode(ofs->color);
+ return ofs->color;
}
/* only to be used by viewport code! */
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
index 3c49c057b49..8968521060d 100644
--- a/source/blender/gpu/intern/gpu_lamp.c
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -49,6 +49,7 @@
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_batch.h"
#include "gpu_lamp_private.h"
@@ -266,90 +267,35 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
(la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
{
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_texture_bind(lamp->depthtex, 0);
- GPU_texture_compare_mode(lamp->depthtex, true);
- GPU_texture_unbind(lamp->depthtex);
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0);
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
+ lamp->blurfb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0);
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL) ||
+ !GPU_framebuffer_check_valid(lamp->blurfb, NULL))
+ {
gpu_lamp_shadow_free(lamp);
return lamp;
}
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
}
else {
lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
GPU_texture_bind(lamp->tex, 0);
GPU_texture_compare_mode(lamp->tex, true);
+ GPU_texture_filter_mode(lamp->tex, true);
GPU_texture_unbind(lamp->tex);
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
+ lamp->fb = GPU_framebuffer_create();
+ GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0);
if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
gpu_lamp_shadow_free(lamp);
@@ -437,7 +383,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
+ GPU_framebuffer_bind(lamp->fb);
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
@@ -447,14 +393,45 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
*winsize = lamp->size;
}
+static void gpu_lamp_shadow_blur(GPULamp *lamp)
+{
+ const float scaleh[2] = {1.0f / GPU_texture_width(lamp->blurtex), 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(lamp->tex)};
+
+ GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
+
+ if (!blur_shader)
+ return;
+
+ int tex_loc = GPU_shader_get_uniform(blur_shader, "textureSource");
+ int scale_loc = GPU_shader_get_uniform(blur_shader, "ScaleU");
+
+ glDisable(GL_DEPTH_TEST);
+
+ GPU_shader_bind(blur_shader);
+
+ /* Blurring horizontally */
+ GPU_framebuffer_bind(lamp->blurfb);
+ GPU_texture_bind(lamp->tex, 0);
+ GPU_shader_uniform_vector(blur_shader, scale_loc, 2, 1, scaleh);
+ GPU_shader_uniform_texture(blur_shader, tex_loc, lamp->tex);
+ GWN_draw_primitive(GL_TRIANGLES, 3);
+
+ /* Blurring vertically */
+ GPU_framebuffer_bind(lamp->fb);
+ GPU_texture_bind(lamp->blurtex, 0);
+ GPU_shader_uniform_vector(blur_shader, scale_loc, 2, 1, scalev);
+ GPU_shader_uniform_texture(blur_shader, tex_loc, lamp->blurtex);
+ GWN_draw_primitive(GL_TRIANGLES, 3);
+}
+
void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
{
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
+ gpu_lamp_shadow_blur(lamp);
}
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 2e6c1cbf9df..a408a41513a 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -68,6 +68,8 @@
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
+#include "DRW_engine.h"
+
#include "gpu_codegen.h"
#include "gpu_lamp_private.h"
@@ -103,6 +105,7 @@ struct GPUMaterial {
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
int type; /* DEPRECATED */
+ GPUMaterialStatus status;
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
@@ -113,6 +116,7 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
+ ListBase inputs; /* GPUInput */
GPUVertexAttribs attribs;
int builtins;
int alpha, obcolalpha;
@@ -142,7 +146,10 @@ struct GPUMaterial {
*/
int domain;
+ /* Used by 2.8 pipeline */
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
+
+ /* Eevee SSS */
GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
float *sss_radii; /* UBO containing SSS profile. */
@@ -215,12 +222,14 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam
{
if (material->outlink) {
GPUNodeLink *outlink = material->outlink;
- material->pass = GPU_generate_pass(&material->nodes, outlink,
+ material->pass = GPU_generate_pass(&material->nodes, &material->inputs, outlink,
&material->attribs, &material->builtins, material->type,
passname,
material->is_opensubdiv,
GPU_material_use_new_shading_nodes(material));
+ material->status = (material->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
+
if (!material->pass)
return 0;
@@ -270,8 +279,14 @@ void GPU_material_free(ListBase *gpumaterial)
for (LinkData *link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
+ /* Cancel / wait any pending lazy compilation. */
+ DRW_deferred_shader_remove(material);
+
+ GPU_pass_free_nodes(&material->nodes);
+ GPU_inputs_free(&material->inputs);
+
if (material->pass)
- GPU_pass_free(material->pass);
+ GPU_pass_release(material->pass);
if (material->ubo != NULL) {
GPU_uniformbuffer_free(material->ubo);
@@ -343,7 +358,7 @@ void GPU_material_bind(
}
/* note material must be bound before setting uniforms */
- GPU_pass_bind(material->pass, time, mipmap);
+ GPU_pass_bind(material->pass, &material->inputs, time, mipmap);
/* handle per material built-ins */
if (material->builtins & GPU_VIEW_MATRIX) {
@@ -363,7 +378,7 @@ void GPU_material_bind(
}
}
- GPU_pass_update_uniforms(material->pass);
+ GPU_pass_update_uniforms(material->pass, &material->inputs);
material->bound = 1;
}
@@ -417,7 +432,7 @@ void GPU_material_bind_uniforms(
GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
}
if (material->builtins & GPU_PARTICLE_LOCATION) {
- GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
+ GPU_shader_uniform_vector(shader, material->partcoloc, 4, 1, pi->location);
}
if (material->builtins & GPU_PARTICLE_VELOCITY) {
GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
@@ -436,7 +451,7 @@ void GPU_material_unbind(GPUMaterial *material)
{
if (material->pass) {
material->bound = 0;
- GPU_pass_unbind(material->pass);
+ GPU_pass_unbind(material->pass, &material->inputs);
}
}
@@ -460,6 +475,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
+ListBase *GPU_material_get_inputs(GPUMaterial *material)
+{
+ return &material->inputs;
+}
+
GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
{
return material->ubo;
@@ -557,7 +577,9 @@ static float eval_profile(float r, short falloff_type, float sharpness, float pa
{
r = fabsf(r);
- if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
+ {
return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
}
else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
@@ -598,7 +620,9 @@ static void compute_sss_kernel(
/* Christensen-Burley fitting */
float l[3], d[3];
- if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
+ {
mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
const float A = 1.0f;
const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
@@ -825,6 +849,12 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
BLI_addtail(&material->nodes, node);
}
+/* Return true if the material compilation has not yet begin or begin. */
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat)
+{
+ return mat->status;
+}
+
/* Code generation */
bool GPU_material_do_color_management(GPUMaterial *mat)
@@ -2486,10 +2516,8 @@ GPUMaterial *GPU_material_from_nodetree_find(
*/
GPUMaterial *GPU_material_from_nodetree(
Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
- const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, bool deferred)
{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
LinkData *link;
bool has_volume_output, has_surface_output;
@@ -2497,7 +2525,7 @@ GPUMaterial *GPU_material_from_nodetree(
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
/* allocate material */
- mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");;
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
@@ -2512,11 +2540,15 @@ GPUMaterial *GPU_material_from_nodetree(
mat->domain |= GPU_DOMAIN_VOLUME;
}
- /* Let Draw manager finish the construction. */
- if (mat->outlink) {
- outlink = mat->outlink;
- mat->pass = GPU_generate_pass_new(
- mat, &mat->nodes, outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
+ if (!deferred) {
+ GPU_material_generate_pass(mat, vert_code, geom_code, frag_lib, defines);
+ }
+ else if (mat->outlink) {
+ /* Prune the unused nodes and extract attribs before compiling so the
+ * generated VBOs are ready to accept the future shader. */
+ GPU_nodes_prune(&mat->nodes, mat->outlink);
+ GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
+ mat->status = GPU_MAT_QUEUED;
}
/* note that even if building the shader fails in some way, we still keep
@@ -2530,6 +2562,21 @@ GPUMaterial *GPU_material_from_nodetree(
return mat;
}
+/* Calls this function if /a mat was created with deferred compilation. */
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ BLI_assert(mat->pass == NULL); /* Only run once! */
+ if (mat->outlink) {
+ mat->pass = GPU_generate_pass_new(
+ mat, mat->outlink, &mat->attribs, &mat->nodes, &mat->inputs, vert_code, geom_code, frag_lib, defines);
+ mat->status = (mat->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
+ }
+ else {
+ mat->status = GPU_MAT_FAILED;
+ }
+}
+
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{
GPUMaterial *mat;
@@ -2692,7 +2739,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
if (pass && pass->fragmentcode && pass->vertexcode) {
shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
- for (input = pass->inputs.first; input; input = input->next) {
+ for (input = mat->inputs.first; input; input = input->next) {
GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
if (input->ima) {
@@ -2869,7 +2916,7 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
{
GPUPass *pass = gpu_material->pass;
GPUShader *shader = (pass != NULL ? pass->shader : NULL);
- ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
+ ListBase *inputs = (pass != NULL ? &gpu_material->inputs : NULL);
GPUInput *input;
if (shader == NULL) {
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 153cf5f1e97..7023e44d289 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -73,7 +73,7 @@ static GPUSelectState g_select_state = {0};
/**
* initialize and provide buffer for results
*/
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
+void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* In the case hits was '-1', don't start the second pass since it's not going to give useful results.
@@ -108,12 +108,12 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *in
case ALGO_GL_QUERY:
{
g_select_state.use_cache = false;
- gpu_select_query_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode, oldhits);
+ gpu_select_query_begin((uint (*)[4])buffer, bufsize / 4, input, mode, oldhits);
break;
}
default: /* ALGO_GL_PICK */
{
- gpu_select_pick_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode);
+ gpu_select_pick_begin((uint (*)[4])buffer, bufsize / 4, input, mode);
break;
}
}
@@ -126,7 +126,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *in
*
* \warning We rely on the order of object rendering on passes to be the same for this to work.
*/
-bool GPU_select_load_id(unsigned int id)
+bool GPU_select_load_id(uint id)
{
/* if no selection mode active, ignore */
if (!g_select_state.select_is_active)
@@ -154,9 +154,9 @@ bool GPU_select_load_id(unsigned int id)
* Return number of hits and hits in buffer.
* if \a dopass is true, we will do a second pass with occlusion queries to get the closest hit.
*/
-unsigned int GPU_select_end(void)
+uint GPU_select_end(void)
{
- unsigned int hits = 0;
+ uint hits = 0;
switch (g_select_state.algorithm) {
case ALGO_GL_LEGACY:
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index f1d311890e6..4aef80934ad 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -62,14 +62,14 @@
/* For looping over a sub-region of a rect, could be moved into 'rct.c'*/
typedef struct SubRectStride {
- unsigned int start; /* start here */
- unsigned int span; /* read these */
- unsigned int span_len; /* len times (read span 'len' times). */
- unsigned int skip; /* skip those */
+ uint start; /* start here */
+ uint span; /* read these */
+ uint span_len; /* len times (read span 'len' times). */
+ uint skip; /* skip those */
} SubRectStride;
/* we may want to change back to float if uint isn't well supported */
-typedef unsigned int depth_t;
+typedef uint depth_t;
/**
* Calculate values needed for looping over a sub-region (smaller buffer within a larger buffer).
@@ -89,10 +89,10 @@ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRect
src->ymax >= dst->ymax && src->ymax >= dst->ymax);
BLI_assert(x >= 0 && y >= 0);
- r_sub->start = (unsigned int)((src_x * y) + x);
- r_sub->span = (unsigned int)dst_x;
- r_sub->span_len = (unsigned int)dst_y;
- r_sub->skip = (unsigned int)(src_x - dst_x);
+ r_sub->start = (uint)((src_x * y) + x);
+ r_sub->span = (uint)dst_x;
+ r_sub->span_len = (uint)dst_y;
+ r_sub->skip = (uint)(src_x - dst_x);
}
/**
@@ -114,11 +114,11 @@ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
/* store result of glReadPixels */
typedef struct DepthBufCache {
struct DepthBufCache *next, *prev;
- unsigned int id;
+ uint id;
depth_t buf[0];
} DepthBufCache;
-static DepthBufCache *depth_buf_malloc(unsigned int rect_len)
+static DepthBufCache *depth_buf_malloc(uint rect_len)
{
DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__);
rect->id = SELECT_ID_NONE;
@@ -127,10 +127,10 @@ static DepthBufCache *depth_buf_malloc(unsigned int rect_len)
static bool depth_buf_rect_depth_any(
const DepthBufCache *rect_depth,
- unsigned int rect_len)
+ uint rect_len)
{
const depth_t *curr = rect_depth->buf;
- for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ for (uint i = 0; i < rect_len; i++, curr++) {
if (*curr != DEPTH_MAX) {
return true;
}
@@ -143,7 +143,7 @@ static bool depth_buf_subrect_depth_any(
const SubRectStride *sub_rect)
{
const depth_t *curr = rect_depth->buf + sub_rect->start;
- for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ for (uint i = 0; i < sub_rect->span_len; i++) {
const depth_t *curr_end = curr + sub_rect->span;
for (; curr < curr_end; curr++, curr++) {
if (*curr != DEPTH_MAX) {
@@ -157,14 +157,14 @@ static bool depth_buf_subrect_depth_any(
static bool depth_buf_rect_depth_any_filled(
const DepthBufCache *rect_prev, const DepthBufCache *rect_curr,
- unsigned int rect_len)
+ uint rect_len)
{
#if 0
return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0;
#else
const depth_t *prev = rect_prev->buf;
const depth_t *curr = rect_curr->buf;
- for (unsigned int i = 0; i < rect_len; i++, curr++, prev++) {
+ for (uint i = 0; i < rect_len; i++, curr++, prev++) {
if (depth_is_filled(prev, curr)) {
return true;
}
@@ -183,7 +183,7 @@ static bool depth_buf_subrect_depth_any_filled(
/* same as above but different rect sizes */
const depth_t *prev = rect_src->buf + sub_rect->start;
const depth_t *curr = rect_dst->buf + sub_rect->start;
- for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ for (uint i = 0; i < sub_rect->span_len; i++) {
const depth_t *curr_end = curr + sub_rect->span;
for (; curr < curr_end; prev++, curr++) {
if (depth_is_filled(prev, curr)) {
@@ -203,7 +203,7 @@ static bool depth_buf_subrect_depth_any_filled(
*/
typedef struct DepthID {
- unsigned int id;
+ uint id;
depth_t depth;
} DepthID;
@@ -238,10 +238,10 @@ static int depth_cmp(const void *v1, const void *v2)
/* depth sorting */
typedef struct GPUPickState {
/* cache on initialization */
- unsigned int (*buffer)[4];
+ uint (*buffer)[4];
/* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
- unsigned int bufsize;
+ uint bufsize;
/* mode of operation */
char mode;
@@ -257,14 +257,14 @@ typedef struct GPUPickState {
/* Set after first draw */
bool is_init;
- unsigned int prev_id;
+ uint prev_id;
} gl;
/* src: data stored in 'cache' and 'gl',
* dst: use when cached region is smaller (where src -> dst isn't 1:1) */
struct {
rcti clip_rect;
- unsigned int rect_len;
+ uint rect_len;
} src, dst;
/* Store cache between `GPU_select_cache_begin/end` */
@@ -284,13 +284,13 @@ typedef struct GPUPickState {
/* GPU_SELECT_PICK_ALL */
struct {
DepthID *hits;
- unsigned int hits_len;
- unsigned int hits_len_alloc;
+ uint hits_len;
+ uint hits_len_alloc;
} all;
/* GPU_SELECT_PICK_NEAREST */
struct {
- unsigned int *rect_id;
+ uint *rect_id;
} nearest;
};
} GPUPickState;
@@ -299,7 +299,7 @@ typedef struct GPUPickState {
static GPUPickState g_pick_state = {0};
void gpu_select_pick_begin(
- unsigned int (*buffer)[4], unsigned int bufsize,
+ uint (*buffer)[4], uint bufsize,
const rcti *input, char mode)
{
GPUPickState *ps = &g_pick_state;
@@ -312,7 +312,7 @@ void gpu_select_pick_begin(
ps->buffer = buffer;
ps->mode = mode;
- const unsigned int rect_len = (unsigned int)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
+ const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
ps->dst.clip_rect = *input;
ps->dst.rect_len = rect_len;
@@ -327,6 +327,9 @@ void gpu_select_pick_begin(
glDepthMask(GL_TRUE);
if (mode == GPU_SELECT_PICK_ALL) {
+ /* Note that other depth settings (such as #GL_LEQUAL) work too,
+ * since the depth is always cleared.
+ * Noting this for cases when depth picking is used where drawing calls change depth settings. */
glDepthFunc(GL_ALWAYS);
}
else {
@@ -358,7 +361,7 @@ void gpu_select_pick_begin(
#if 0
glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf);
#else
- for (unsigned int i = 0; i < rect_len; i++) {
+ for (uint i = 0; i < rect_len; i++) {
ps->gl.rect_depth->buf[i] = DEPTH_MAX;
}
#endif
@@ -381,8 +384,8 @@ void gpu_select_pick_begin(
}
else {
/* Set to 0xff for SELECT_ID_NONE */
- ps->nearest.rect_id = MEM_mallocN(sizeof(unsigned int) * ps->dst.rect_len, __func__);
- memset(ps->nearest.rect_id, 0xff, sizeof(unsigned int) * ps->dst.rect_len);
+ ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__);
+ memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len);
}
}
@@ -393,7 +396,7 @@ void gpu_select_pick_begin(
static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
{
GPUPickState *ps = &g_pick_state;
- const unsigned int id = rect_curr->id;
+ const uint id = rect_curr->id;
/* find the best depth for this pass and store in 'all.hits' */
depth_t depth_best = DEPTH_MAX;
@@ -405,15 +408,15 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
if (ps->is_cached == false) {
const depth_t *curr = rect_curr->buf;
BLI_assert(ps->src.rect_len == ps->dst.rect_len);
- const unsigned int rect_len = ps->src.rect_len;
- for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ const uint rect_len = ps->src.rect_len;
+ for (uint i = 0; i < rect_len; i++, curr++) {
EVAL_TEST();
}
}
else {
/* same as above but different rect sizes */
const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
- for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
const depth_t *curr_end = curr + ps->cache.sub_rect.span;
for (; curr < curr_end; curr++) {
EVAL_TEST();
@@ -437,10 +440,10 @@ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr)
{
GPUPickState *ps = &g_pick_state;
- const unsigned int id = rect_curr->id;
+ const uint id = rect_curr->id;
/* keep track each pixels ID in 'nearest.rect_id' */
if (id != SELECT_ID_NONE) {
- unsigned int *id_ptr = ps->nearest.rect_id;
+ uint *id_ptr = ps->nearest.rect_id;
/* Check against DEPTH_MAX because XRAY will clear the buffer,
* so previously set values will become unset.
@@ -454,8 +457,8 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
const depth_t *prev = rect_prev->buf;
const depth_t *curr = rect_curr->buf;
BLI_assert(ps->src.rect_len == ps->dst.rect_len);
- const unsigned int rect_len = ps->src.rect_len;
- for (unsigned int i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
+ const uint rect_len = ps->src.rect_len;
+ for (uint i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
EVAL_TEST();
}
}
@@ -463,7 +466,7 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
/* same as above but different rect sizes */
const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start;
const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
- for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) {
const depth_t *curr_end = curr + ps->cache.sub_rect.span;
for (; curr < curr_end; prev++, curr++, id_ptr++) {
EVAL_TEST();
@@ -478,11 +481,11 @@ static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, cons
}
-bool gpu_select_pick_load_id(unsigned int id)
+bool gpu_select_pick_load_id(uint id)
{
GPUPickState *ps = &g_pick_state;
if (ps->gl.is_init) {
- const unsigned int rect_len = ps->src.rect_len;
+ const uint rect_len = ps->src.rect_len;
glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth_test->buf);
/* perform initial check since most cases the array remains unchanged */
@@ -524,7 +527,7 @@ bool gpu_select_pick_load_id(unsigned int id)
return true;
}
-unsigned int gpu_select_pick_end(void)
+uint gpu_select_pick_end(void)
{
GPUPickState *ps = &g_pick_state;
@@ -537,7 +540,6 @@ unsigned int gpu_select_pick_end(void)
/* force finishing last pass */
gpu_select_pick_load_id(ps->gl.prev_id);
}
-
gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
@@ -559,9 +561,9 @@ unsigned int gpu_select_pick_end(void)
rect_depth_final = ps->gl.rect_depth;
}
- unsigned int maxhits = g_pick_state.bufsize;
+ uint maxhits = g_pick_state.bufsize;
DepthID *depth_data;
- unsigned int depth_data_len = 0;
+ uint depth_data_len = 0;
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
depth_data = ps->all.hits;
@@ -575,7 +577,7 @@ unsigned int gpu_select_pick_end(void)
/* GPU_SELECT_PICK_NEAREST */
/* Over alloc (unlikely we have as many depths as pixels) */
- unsigned int depth_data_len_first_pass = 0;
+ uint depth_data_len_first_pass = 0;
depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__);
/* Partially de-duplicating copy,
@@ -584,7 +586,7 @@ unsigned int gpu_select_pick_end(void)
#define EVAL_TEST(i_src, i_dst) \
{ \
- const unsigned int id = ps->nearest.rect_id[i_dst]; \
+ const uint id = ps->nearest.rect_id[i_dst]; \
if (id != SELECT_ID_NONE) { \
const depth_t depth = rect_depth_final->buf[i_src]; \
if (depth_last == NULL || depth_last->id != id) { \
@@ -601,15 +603,15 @@ unsigned int gpu_select_pick_end(void)
{
DepthID *depth_last = NULL;
if (ps->is_cached == false) {
- for (unsigned int i = 0; i < ps->src.rect_len; i++) {
+ for (uint i = 0; i < ps->src.rect_len; i++) {
EVAL_TEST(i, i);
}
}
else {
/* same as above but different rect sizes */
- unsigned int i_src = ps->cache.sub_rect.start, i_dst = 0;
- for (unsigned int j = 0; j < ps->cache.sub_rect.span_len; j++) {
- const unsigned int i_src_end = i_src + ps->cache.sub_rect.span;
+ uint i_src = ps->cache.sub_rect.start, i_dst = 0;
+ for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) {
+ const uint i_src_end = i_src + ps->cache.sub_rect.span;
for (; i_src < i_src_end; i_src++, i_dst++) {
EVAL_TEST(i_src, i_dst);
}
@@ -626,7 +628,7 @@ unsigned int gpu_select_pick_end(void)
depth_data_len = 0;
{
DepthID *depth_last = NULL;
- for (unsigned int i = 0; i < depth_data_len_first_pass; i++) {
+ for (uint i = 0; i < depth_data_len_first_pass; i++) {
if (depth_last == NULL || depth_last->id != depth_data[i].id) {
depth_last = &depth_data[depth_data_len++];
*depth_last = depth_data[i];
@@ -640,16 +642,16 @@ unsigned int gpu_select_pick_end(void)
/* Finally sort each unique (id, depth) pair by depth
* so the final hit-list is sorted by depth (nearest first) */
- unsigned int hits = 0;
+ uint hits = 0;
if (depth_data_len > maxhits) {
- hits = (unsigned int)-1;
+ hits = (uint)-1;
}
else {
/* leave sorting up to the caller */
qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
- for (unsigned int i = 0; i < depth_data_len; i++) {
+ for (uint i = 0; i < depth_data_len; i++) {
#ifdef DEBUG_PRINT
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
#endif
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index e3bd20f3776..12390e5cdb0 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -44,6 +44,8 @@
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "gpu_select_private.h"
@@ -54,20 +56,20 @@ typedef struct GPUQueryState {
/* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
bool query_issued;
/* array holding the OpenGL query identifiers */
- unsigned int *queries;
+ uint *queries;
/* array holding the id corresponding to each query */
- unsigned int *id;
+ uint *id;
/* number of queries in *queries and *id */
- unsigned int num_of_queries;
+ uint num_of_queries;
/* index to the next query to start */
- unsigned int active_query;
+ uint active_query;
/* cache on initialization */
- unsigned int (*buffer)[4];
+ uint (*buffer)[4];
/* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
- unsigned int bufsize;
+ uint bufsize;
/* mode of operation */
char mode;
- unsigned int index;
+ uint index;
int oldhits;
} GPUQueryState;
@@ -75,7 +77,7 @@ static GPUQueryState g_query_state = {0};
void gpu_select_query_begin(
- unsigned int (*buffer)[4], unsigned int bufsize,
+ uint (*buffer)[4], uint bufsize,
const rcti *input, char mode,
int oldhits)
{
@@ -96,7 +98,7 @@ void gpu_select_query_begin(
g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
- gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT | GPU_SCISSOR_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -114,6 +116,7 @@ void gpu_select_query_begin(
glDepthMask(GL_FALSE);
}
else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ glDisable(GL_SCISSOR_TEST); /* allows fast clear */
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
@@ -126,7 +129,7 @@ void gpu_select_query_begin(
}
}
-bool gpu_select_query_load_id(unsigned int id)
+bool gpu_select_query_load_id(uint id)
{
if (g_query_state.query_issued) {
glEndQuery(GL_SAMPLES_PASSED);
@@ -161,19 +164,28 @@ bool gpu_select_query_load_id(unsigned int id)
return true;
}
-unsigned int gpu_select_query_end(void)
+uint gpu_select_query_end(void)
{
int i;
- unsigned int hits = 0;
- const unsigned int maxhits = g_query_state.bufsize;
+ uint hits = 0;
+ const uint maxhits = g_query_state.bufsize;
if (g_query_state.query_issued) {
glEndQuery(GL_SAMPLES_PASSED);
}
for (i = 0; i < g_query_state.active_query; i++) {
- unsigned int result;
+ uint result = 0;
+ /* Wait until the result is available. */
+ while (result == 0) {
+ glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result);
+ if (result == 0) {
+ /* (fclem) Not sure if this is better than calling
+ * glGetQueryObjectuiv() indefinitely. */
+ PIL_sleep_ms(1);
+ }
+ }
glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 598722d372b..e0b11edb197 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -37,7 +37,6 @@
#include "DNA_space_types.h"
-#include "GPU_compositing.h"
#include "GPU_extensions.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
@@ -66,17 +65,27 @@ extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_2D_image_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_frag_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[];
extern char datatoc_gpu_shader_3D_image_vert_glsl[];
+extern char datatoc_gpu_shader_image_frag_glsl[];
extern char datatoc_gpu_shader_image_linear_frag_glsl[];
extern char datatoc_gpu_shader_image_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[];
extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
-extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
+extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
extern char datatoc_gpu_shader_3D_normal_vert_glsl[];
extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
@@ -98,7 +107,7 @@ extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl[];
extern char datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl[];
-extern char datatoc_gpu_shader_instance_mball_helpers_vert_glsl[];
+extern char datatoc_gpu_shader_instance_mball_handles_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
@@ -133,7 +142,10 @@ extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
extern char datatoc_gpu_shader_text_vert_glsl[];
+extern char datatoc_gpu_shader_text_geom_glsl[];
extern char datatoc_gpu_shader_text_frag_glsl[];
+extern char datatoc_gpu_shader_text_simple_vert_glsl[];
+extern char datatoc_gpu_shader_text_simple_geom_glsl[];
extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[];
extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[];
@@ -144,22 +156,10 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
-extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
-extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
-extern char datatoc_gpu_shader_fx_lib_glsl[];
/* cache of built-in shaders (each is created on first use) */
static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
-/* cache for shader fx. Those can exist in combinations so store them here */
-static GPUShader *fx_shaders[MAX_FX_SHADERS * 2] = { NULL };
-
typedef struct {
const char *vert;
const char *frag;
@@ -542,9 +542,6 @@ void GPU_shader_free(GPUShader *shader)
if (shader->program)
glDeleteProgram(shader->program);
- if (shader->uniform_interface)
- MEM_freeN(shader->uniform_interface);
-
if (shader->interface)
GWN_shaderinterface_discard(shader->interface);
@@ -573,11 +570,6 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return ubo ? ubo->location : -1;
}
-void *GPU_fx_shader_get_interface(GPUShader *shader)
-{
- return shader->uniform_interface;
-}
-
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->interface;
@@ -589,11 +581,6 @@ int GPU_shader_get_program(GPUShader *shader)
return (int)shader->program;
}
-void GPU_fx_shader_set_interface(GPUShader *shader, void *interface)
-{
- shader->uniform_interface = interface;
-}
-
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
{
if (location == -1 || value == NULL)
@@ -640,32 +627,17 @@ void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
int number = GPU_texture_bound_number(tex);
- int bindcode = GPU_texture_opengl_bindcode(tex);
- int target = GPU_texture_target(tex);
- if (number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
+ if (number == -1) {
+ fprintf(stderr, "Texture is not bound.\n");
+ BLI_assert(0);
return;
}
-
- if (number == -1)
- return;
if (location == -1)
return;
- if (number != 0)
- glActiveTexture(GL_TEXTURE0 + number);
-
- if (bindcode != 0)
- glBindTexture(target, bindcode);
- else
- GPU_invalid_tex_bind(target);
-
glUniform1i(location, number);
-
- if (number != 0)
- glActiveTexture(GL_TEXTURE0);
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
@@ -687,7 +659,12 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
[GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
- [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, datatoc_gpu_shader_text_frag_glsl },
+ [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_geom_glsl },
+ [GPU_SHADER_TEXT_SIMPLE] = { datatoc_gpu_shader_text_simple_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_simple_geom_glsl },
[GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl,
datatoc_gpu_shader_keyframe_diamond_frag_glsl },
[GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
@@ -710,10 +687,10 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
[GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
- [GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
- datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl },
[GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_depth_linear_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_depth_copy_frag_glsl },
[GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_interlace_frag_glsl },
@@ -728,12 +705,21 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_2D_smooth_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_linear_frag_glsl },
+ [GPU_SHADER_2D_IMAGE] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_frag_glsl },
[GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_alpha_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_ALPHA] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
[GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_shuffle_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl,
+ datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl,
+ datatoc_gpu_shader_image_varying_color_frag_glsl },
+
[GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
@@ -816,12 +802,23 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_flat_color_frag_glsl,
datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
+ [GPU_SHADER_2D_WIDGET_BASE] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_BASE_INST] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_SHADOW] = { datatoc_gpu_shader_2D_widget_shadow_vert_glsl,
+ datatoc_gpu_shader_2D_widget_shadow_frag_glsl },
+ [GPU_SHADER_2D_NODELINK] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+ [GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+
[GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID] = { datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl,
datatoc_gpu_shader_simple_lighting_frag_glsl },
[GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE] = { datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
- [GPU_SHADER_3D_INSTANCE_MBALL_HELPERS] = { datatoc_gpu_shader_instance_mball_helpers_vert_glsl,
+ [GPU_SHADER_3D_INSTANCE_MBALL_HANDLES] = { datatoc_gpu_shader_instance_mball_handles_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
};
@@ -829,25 +826,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
/* just a few special cases */
const char *defines = NULL;
switch (shader) {
+ case GPU_SHADER_2D_WIDGET_BASE_INST:
+ case GPU_SHADER_2D_NODELINK_INST:
+ defines = "#define USE_INSTANCE\n";
+ break;
case GPU_SHADER_SMOKE_COBA:
- defines = "#define USE_COBA;\n";
+ defines = "#define USE_COBA\n";
break;
case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE:
- defines = "#define UNIFORM_SCALE;\n";
+ defines = "#define UNIFORM_SCALE\n";
break;
case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS:
- defines = "#define AXIS_NAME;\n";
+ defines = "#define AXIS_NAME\n";
break;
case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR:
case GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID:
- defines = "#define USE_INSTANCE_COLOR;\n";
+ defines = "#define USE_INSTANCE_COLOR\n";
break;
case GPU_SHADER_3D_FLAT_COLOR_U32:
case GPU_SHADER_3D_UNIFORM_COLOR_U32:
- defines = "#define USE_COLOR_U32;\n";
+ defines = "#define USE_COLOR_U32\n";
break;
case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR:
- defines = "#define USE_FLAT_NORMAL;\n";
+ defines = "#define USE_FLAT_NORMAL\n";
break;
default:
break;
@@ -880,82 +881,6 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
#define MAX_DEFINES 100
-GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
-{
- int offset;
- char defines[MAX_DEFINES] = "";
- /* avoid shaders out of range */
- if (effect >= MAX_FX_SHADERS)
- return NULL;
-
- offset = 2 * effect;
-
- if (persp) {
- offset += 1;
- strcat(defines, "#define PERSP_MATRIX\n");
- }
-
- if (!fx_shaders[offset]) {
- GPUShader *shader = NULL;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- strcat(defines, "#define FOURTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- strcat(defines, "#define FIFTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
- break;
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines);
- break;
- }
-
- fx_shaders[offset] = shader;
- GPU_fx_shader_init_interface(shader, effect);
- }
-
- return fx_shaders[offset];
-}
-
-
void GPU_shader_free_builtin_shaders(void)
{
for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) {
@@ -964,11 +889,4 @@ void GPU_shader_free_builtin_shaders(void)
builtin_shaders[i] = NULL;
}
}
-
- for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
- if (fx_shaders[i]) {
- GPU_shader_free(fx_shaders[i]);
- fx_shaders[i] = NULL;
- }
- }
}
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
index f883773df17..67d8c6e6213 100644
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -35,9 +35,6 @@ struct GPUShader {
GLuint geometry; /* handle for geometry shader */
GLuint fragment; /* handle for fragment shader */
- void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
- /* NOTE: ^-- only FX compositing shaders use this */
-
Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
};
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index d6b641af225..75830f60f03 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -48,6 +48,22 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
+/* Maximum number of FBOs a texture can be attached to. */
+#define GPU_TEX_MAX_FBO_ATTACHED 8
+
+typedef enum GPUTextureFormatFlag{
+ GPU_FORMAT_DEPTH = (1 << 0),
+ GPU_FORMAT_STENCIL = (1 << 1),
+ GPU_FORMAT_INTEGER = (1 << 2),
+ GPU_FORMAT_FLOAT = (1 << 3),
+
+ GPU_FORMAT_1D = (1 << 10),
+ GPU_FORMAT_2D = (1 << 11),
+ GPU_FORMAT_3D = (1 << 12),
+ GPU_FORMAT_CUBE = (1 << 13),
+ GPU_FORMAT_ARRAY = (1 << 14),
+} GPUTextureFormatFlag;
+
/* GPUTexture */
struct GPUTexture {
int w, h, d; /* width/height/depth */
@@ -59,14 +75,15 @@ struct GPUTexture {
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int fb_attachment; /* slot the texture is attached to */
- bool depth; /* is a depth texture? */
- bool stencil; /* is a stencil texture? */
+ GPUTextureFormat format;
+ GPUTextureFormatFlag format_flag;
unsigned int bytesize; /* number of byte for one pixel */
- int format; /* GPUTextureFormat */
int components; /* number of color/alpha channels */
+ int samples; /* number of samples for multisamples textures. 0 if not multisample target */
+
+ int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
+ GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
};
/* ------ Memory Management ------- */
@@ -113,30 +130,26 @@ unsigned int GPU_texture_memory_usage_get(void)
static GLenum gpu_texture_get_format(
int components, GPUTextureFormat data_type,
- GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil, unsigned int *bytesize)
+ GLenum *format, GLenum *data_format, GPUTextureFormatFlag *format_flag, unsigned int *bytesize)
{
if (ELEM(data_type, GPU_DEPTH_COMPONENT24,
GPU_DEPTH_COMPONENT16,
GPU_DEPTH_COMPONENT32F))
{
- *is_depth = true;
- *is_stencil = false;
+ *format_flag |= GPU_FORMAT_DEPTH;
*data_format = GL_FLOAT;
*format = GL_DEPTH_COMPONENT;
}
else if (data_type == GPU_DEPTH24_STENCIL8) {
- *is_depth = true;
- *is_stencil = true;
+ *format_flag |= GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL;
*data_format = GL_UNSIGNED_INT_24_8;
*format = GL_DEPTH_STENCIL;
}
else {
- *is_depth = false;
- *is_stencil = false;
-
/* Integer formats */
- if (ELEM(data_type, GPU_RG16I)) {
+ if (ELEM(data_type, GPU_RG16I, GPU_R16I)) {
*data_format = GL_INT;
+ *format_flag |= GPU_FORMAT_INTEGER;
switch (components) {
case 1: *format = GL_RED_INTEGER; break;
@@ -148,6 +161,7 @@ static GLenum gpu_texture_get_format(
}
else {
*data_format = GL_FLOAT;
+ *format_flag |= GPU_FORMAT_FLOAT;
switch (components) {
case 1: *format = GL_RED; break;
@@ -184,6 +198,7 @@ static GLenum gpu_texture_get_format(
break;
case GPU_DEPTH_COMPONENT16:
case GPU_R16F:
+ case GPU_R16I:
case GPU_RG8:
*bytesize = 2;
break;
@@ -208,6 +223,7 @@ static GLenum gpu_texture_get_format(
case GPU_RGBA8: return GL_RGBA8;
case GPU_R32F: return GL_R32F;
case GPU_R16F: return GL_R16F;
+ case GPU_R16I: return GL_R16I;
case GPU_RG8: return GL_RG8;
case GPU_R8: return GL_R8;
/* Special formats texture & renderbuffer */
@@ -340,11 +356,12 @@ static GPUTexture *GPU_texture_create_nD(
tex->w = w;
tex->h = h;
tex->d = d;
+ tex->samples = samples;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
+ tex->format_flag = 0;
if (n == 2) {
if (d == 0)
@@ -371,7 +388,8 @@ static GPUTexture *GPU_texture_create_nD(
tex->target = GL_TEXTURE_2D_MULTISAMPLE;
GLenum format, internalformat, data_format;
- internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
@@ -387,7 +405,6 @@ static GPUTexture *GPU_texture_create_nD(
return NULL;
}
- tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
/* Check if texture fit in VRAM */
@@ -446,17 +463,23 @@ static GPUTexture *GPU_texture_create_nD(
MEM_freeN(rescaled_fpixels);
/* Texture Parameters */
- if (tex->depth) {
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
if (n > 1) {
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -465,7 +488,7 @@ static GPUTexture *GPU_texture_create_nD(
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, 0);
return tex;
}
@@ -483,11 +506,12 @@ static GPUTexture *GPU_texture_cube_create(
tex->w = w;
tex->h = w;
tex->d = d;
+ tex->samples = 0;
tex->number = -1;
tex->refcount = 1;
- tex->fb_attachment = -1;
tex->format = data_type;
tex->components = components;
+ tex->format_flag = GPU_FORMAT_CUBE;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -497,7 +521,8 @@ static GPUTexture *GPU_texture_cube_create(
// tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
}
- internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
gpu_texture_memory_footprint_add(tex);
@@ -513,7 +538,6 @@ static GPUTexture *GPU_texture_cube_create(
return NULL;
}
- tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
/* Upload Texture */
@@ -525,22 +549,28 @@ static GPUTexture *GPU_texture_cube_create(
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nz);
/* Texture Parameters */
- if (tex->depth) {
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, 0);
return tex;
}
@@ -576,6 +606,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
tex->fromblender = 1;
tex->format = -1;
tex->components = -1;
+ tex->samples = 0;
ima->gputexture[gputt] = tex;
@@ -686,7 +717,8 @@ GPUTexture *GPU_texture_create_2D_custom_multisample(
return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, channels, samples, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_array_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_2D_array_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
return GPU_texture_create_nD(w, h, d, 2, pixels, data_type, channels, 0, false, err_out);
}
@@ -696,11 +728,13 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char
return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_3D_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_cube_custom(int w, int channels, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_cube_custom(
+ int w, int channels, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
{
const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz;
@@ -716,7 +750,8 @@ GPUTexture *GPU_texture_create_cube_custom(int w, int channels, GPUTextureFormat
fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL;
}
- return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz, data_type, channels, err_out);
+ return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz,
+ data_type, channels, err_out);
}
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
@@ -745,7 +780,8 @@ void GPU_texture_update(GPUTexture *tex, const float *pixels)
BLI_assert(tex->components > -1);
GLenum format, data_format;
- gpu_texture_get_format(tex->components, tex->format, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ gpu_texture_get_format(tex->components, tex->format, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
glBindTexture(tex->target, tex->bindcode);
@@ -803,55 +839,44 @@ void GPU_invalid_tex_free(void)
GPU_texture_free(GG.invalid_tex_3D);
}
-
void GPU_texture_bind(GPUTexture *tex, int number)
{
+ BLI_assert(number >= 0);
+
if (number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
if ((G.debug & G_DEBUG)) {
- if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind "
+ "texture attached to current framebuffer!\n");
+ BLI_assert(0); /* Should never happen! */
+ break;
+ }
}
}
- if (number < 0)
- return;
-
- if (number != 0)
- glActiveTexture(GL_TEXTURE0 + number);
+ glActiveTexture(GL_TEXTURE0 + number);
if (tex->bindcode != 0)
glBindTexture(tex->target, tex->bindcode);
else
GPU_invalid_tex_bind(tex->target_base);
- if (number != 0)
- glActiveTexture(GL_TEXTURE0);
-
tex->number = number;
}
void GPU_texture_unbind(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
if (tex->number == -1)
return;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
-
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
-
tex->number = -1;
}
@@ -860,114 +885,79 @@ int GPU_texture_bound_number(GPUTexture *tex)
return tex->number;
}
+#define WARN_NOT_BOUND(_tex) do { \
+ if (_tex->number == -1) { \
+ fprintf(stderr, "Warning : Trying to set parameter on a texture not bound.\n"); \
+ BLI_assert(0); \
+ return; \
+ } \
+} while (0);
+
void GPU_texture_generate_mipmap(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ WARN_NOT_BOUND(tex);
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glGenerateMipmap(tex->target_base);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
+ /* Could become an assertion ? (fclem) */
+ if (!GPU_texture_depth(tex))
return;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
-
- /* TODO viewport: use GL_COMPARE_REF_TO_TEXTURE after we switch to core profile */
- if (tex->depth)
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, use_compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+ GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
- return;
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
- GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
- if (tex->number == -1)
- return;
+ WARN_NOT_BOUND(tex);
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert((!use_filter && !use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
GLenum mipmap = (use_filter)
- ? use_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
- : use_mipmap ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
+ ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
+ : (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
- GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
- return;
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0 + tex->number);
+ GLenum repeat = (use_repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
- GLenum repeat = use_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ glActiveTexture(GL_TEXTURE0 + tex->number);
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
if (tex->target_base != GL_TEXTURE_1D)
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
if (tex->target_base == GL_TEXTURE_3D)
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
-
- if (tex->number != 0)
- glActiveTexture(GL_TEXTURE0);
}
void GPU_texture_free(GPUTexture *tex)
@@ -978,8 +968,12 @@ void GPU_texture_free(GPUTexture *tex)
fprintf(stderr, "GPUTexture: negative refcount\n");
if (tex->refcount == 0) {
- if (tex->fb)
- GPU_framebuffer_texture_detach(tex);
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] != NULL) {
+ GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]);
+ }
+ }
+
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -1009,39 +1003,64 @@ int GPU_texture_height(const GPUTexture *tex)
return tex->h;
}
-int GPU_texture_format(const GPUTexture *tex)
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex)
{
return tex->format;
}
+int GPU_texture_samples(const GPUTexture *tex)
+{
+ return tex->samples;
+}
+
bool GPU_texture_depth(const GPUTexture *tex)
{
- return tex->depth;
+ return (tex->format_flag & GPU_FORMAT_DEPTH) != 0;
}
bool GPU_texture_stencil(const GPUTexture *tex)
{
- return tex->stencil;
+ return (tex->format_flag & GPU_FORMAT_STENCIL) != 0;
}
-int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+bool GPU_texture_integer(const GPUTexture *tex)
{
- return tex->bindcode;
+ return (tex->format_flag & GPU_FORMAT_INTEGER) != 0;
}
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+bool GPU_texture_cube(const GPUTexture *tex)
{
- return tex->fb;
+ return (tex->format_flag & GPU_FORMAT_CUBE) != 0;
}
-int GPU_texture_framebuffer_attachment(GPUTexture *tex)
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
- return tex->fb_attachment;
+ return tex->bindcode;
}
-void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+void GPU_texture_attach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
{
- tex->fb = fb;
- tex->fb_attachment = attachment;
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == NULL) {
+ tex->fb[i] = fb;
+ tex->fb_attachment[i] = attachment;
+ return;
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Not enough Framebuffer slots");
}
+/* Return previous attachment point */
+int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb)
+{
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == fb) {
+ tex->fb[i] = NULL;
+ return tex->fb_attachment[i];
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Framebuffer is not attached");
+ return 0;
+}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 3ef53b3a6c3..5d89bd59277 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -48,6 +48,7 @@
#include "GPU_immediate.h"
#include "GPU_texture.h"
#include "GPU_viewport.h"
+#include "GPU_draw.h"
#include "DRW_engine.h"
@@ -68,12 +69,7 @@ typedef struct ViewportTempTexture {
} ViewportTempTexture;
struct GPUViewport {
- float pad[4];
-
- /* debug */
- GPUTexture *debug_depth;
int size[2];
-
int samples;
int flag;
@@ -87,6 +83,9 @@ struct GPUViewport {
struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */
ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
+
+ /* Profiling data */
+ double cache_time;
};
enum {
@@ -97,6 +96,7 @@ static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, Texture
static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
static void gpu_viewport_passes_free(PassList *psl, int psl_len);
static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
+static void gpu_viewport_default_fb_create(GPUViewport *viewport);
void GPU_viewport_tag_update(GPUViewport *viewport)
{
@@ -125,9 +125,33 @@ GPUViewport *GPU_viewport_create(void)
GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
{
GPUViewport *viewport = GPU_viewport_create();
- GPU_offscreen_viewport_data_get(ofs, &viewport->fbl->default_fb, &viewport->txl->color, &viewport->txl->depth);
+ GPUTexture *color, *depth;
+ GPUFrameBuffer *fb;
viewport->size[0] = GPU_offscreen_width(ofs);
viewport->size[1] = GPU_offscreen_height(ofs);
+
+ GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth);
+
+ if (GPU_texture_samples(color)) {
+ viewport->txl->multisample_color = color;
+ viewport->txl->multisample_depth = depth;
+ viewport->fbl->multisample_fb = fb;
+ gpu_viewport_default_fb_create(viewport);
+ }
+ else {
+ viewport->fbl->default_fb = fb;
+ viewport->txl->color = color;
+ viewport->txl->depth = depth;
+ GPU_framebuffer_ensure_config(&viewport->fbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->color)
+ });
+ GPU_framebuffer_ensure_config(&viewport->fbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+ }
+
return viewport;
}
/**
@@ -135,9 +159,22 @@ GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
*/
void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
{
- viewport->fbl->default_fb = NULL;
- viewport->txl->color = NULL;
- viewport->txl->depth = NULL;
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+
+ if (dfbl->multisample_fb) {
+ /* GPUViewport expect the final result to be in default_fb but
+ * GPUOffscreen wants it in its multisample_fb, so we sync it back. */
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT);
+ dfbl->multisample_fb = NULL;
+ dtxl->multisample_color = NULL;
+ dtxl->multisample_depth = NULL;
+ }
+ else {
+ viewport->fbl->default_fb = NULL;
+ dtxl->color = NULL;
+ dtxl->depth = NULL;
+ }
}
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
@@ -243,6 +280,11 @@ void GPU_viewport_size_set(GPUViewport *viewport, const int size[2])
viewport->size[1] = size[1];
}
+double *GPU_viewport_cache_time_get(GPUViewport *viewport)
+{
+ return &viewport->cache_time;
+}
+
/**
* Try to find a texture coresponding to params into the texture pool.
* If no texture was found, create one and add it to the pool.
@@ -252,9 +294,9 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
GPUTexture *tex;
for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
- if ((GPU_texture_width(tmp_tex->texture) == width) &&
- (GPU_texture_height(tmp_tex->texture) == height) &&
- (GPU_texture_format(tmp_tex->texture) == format))
+ if ((GPU_texture_format(tmp_tex->texture) == format) &&
+ (GPU_texture_width(tmp_tex->texture) == width) &&
+ (GPU_texture_height(tmp_tex->texture) == height))
{
/* Search if the engine is not already using this texture */
for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
@@ -271,11 +313,16 @@ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine,
}
tex = GPU_texture_create_2D_custom(width, height, channels, format, NULL, NULL);
+ GPU_texture_bind(tex, 0);
+ /* Doing filtering for depth does not make sense when not doing shadow mapping,
+ * and enabling texture filtering on integer texture make them unreadable. */
+ bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
+ GPU_texture_filter_mode(tex, do_filter);
+ GPU_texture_unbind(tex);
ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
tmp_tex->texture = tex;
tmp_tex->user[0] = engine;
-
BLI_addtail(&viewport->tex_pool, tmp_tex);
return tex;
@@ -335,16 +382,94 @@ void GPU_viewport_cache_release(GPUViewport *viewport)
}
}
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+static void gpu_viewport_default_fb_create(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ bool ok = true;
+
+ dtxl->color = GPU_texture_create_2D(size[0], size[1], NULL, NULL);
+ dtxl->depth = GPU_texture_create_depth_with_stencil(size[0], size[1], NULL);
+
+ if (!(dtxl->depth && dtxl->color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport)
{
DefaultFramebufferList *dfbl = viewport->fbl;
DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ int samples = viewport->samples;
+ bool ok = true;
+
+ dtxl->multisample_color = GPU_texture_create_2D_multisample(size[0], size[1], NULL, samples, NULL);
+ dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(size[0], size[1], samples, NULL);
+
+ if (!(dtxl->multisample_depth && dtxl->multisample_color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->multisample_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
int fbl_len, txl_len;
/* add one pixel because of scissor test */
int rect_w = BLI_rcti_size_x(rect) + 1;
int rect_h = BLI_rcti_size_y(rect) + 1;
+ DRW_opengl_context_enable();
+
if (dfbl->default_fb) {
if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) {
gpu_viewport_buffers_free(
@@ -361,121 +486,31 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
}
}
+ viewport->size[0] = rect_w;
+ viewport->size[1] = rect_h;
+ viewport->samples = U.ogl_multisamples;
+
gpu_viewport_texture_pool_clear_users(viewport);
/* Multisample Buffer */
- if (U.ogl_multisamples > 0) {
+ if (viewport->samples > 0) {
if (!dfbl->default_fb) {
- bool ok = true;
- viewport->samples = U.ogl_multisamples;
-
- dfbl->multisample_fb = GPU_framebuffer_create();
- if (!dfbl->multisample_fb) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Color */
- dtxl->multisample_color = GPU_texture_create_2D_multisample(rect_w, rect_h, NULL, U.ogl_multisamples, NULL);
- if (!dtxl->multisample_color) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_color, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
-
- /* Depth */
- dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(rect_w, rect_h,
- U.ogl_multisamples, NULL);
-
- if (!dtxl->multisample_depth) {
- ok = false;
- goto cleanup_multisample;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_depth, 0, 0)) {
- ok = false;
- goto cleanup_multisample;
- }
- else if (!GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL)) {
- ok = false;
- goto cleanup_multisample;
- }
-
-cleanup_multisample:
- if (!ok) {
- GPU_viewport_free(viewport);
- MEM_freeN(viewport);
- return;
- }
+ gpu_viewport_default_multisample_fb_create(viewport);
}
}
if (!dfbl->default_fb) {
- bool ok = true;
- viewport->size[0] = rect_w;
- viewport->size[1] = rect_h;
-
- dfbl->default_fb = GPU_framebuffer_create();
- if (!dfbl->default_fb) {
- ok = false;
- goto cleanup;
- }
-
- /* Color */
- dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
- if (!dtxl->color) {
- ok = false;
- goto cleanup;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0, 0)) {
- ok = false;
- goto cleanup;
- }
-
- /* Depth */
- dtxl->depth = GPU_texture_create_depth_with_stencil(rect_w, rect_h, NULL);
-
- if (dtxl->depth) {
- /* Define texture parameters */
- GPU_texture_bind(dtxl->depth, 0);
- GPU_texture_compare_mode(dtxl->depth, false);
- GPU_texture_filter_mode(dtxl->depth, true);
- GPU_texture_unbind(dtxl->depth);
- }
- else {
- ok = false;
- goto cleanup;
- }
-
- if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0)) {
- ok = false;
- goto cleanup;
- }
- else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
- ok = false;
- goto cleanup;
- }
-
-cleanup:
- if (!ok) {
- GPU_viewport_free(viewport);
- MEM_freeN(viewport);
- return;
- }
-
- GPU_framebuffer_restore();
+ gpu_viewport_default_fb_create(viewport);
}
-
- GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
}
-static void draw_ofs_to_screen(GPUViewport *viewport)
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ if (dfbl->default_fb == NULL)
+ return;
+
DefaultTextureList *dtxl = viewport->txl;
GPUTexture *color = dtxl->color;
@@ -483,50 +518,31 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
const float w = (float)GPU_texture_width(color);
const float h = (float)GPU_texture_height(color);
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
- GPU_texture_bind(color, 0);
-
- immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
-
- immBegin(GWN_PRIM_TRI_STRIP, 4);
+ BLI_assert(w == BLI_rcti_size_x(rect) + 1);
+ BLI_assert(h == BLI_rcti_size_y(rect) + 1);
- immAttrib2f(texcoord, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, 0.0f);
+ float x1 = rect->xmin;
+ float x2 = rect->xmin + w;
+ float y1 = rect->ymin;
+ float y2 = rect->ymin + h;
- immAttrib2f(texcoord, 1.0f, 0.0f);
- immVertex2f(pos, w, 0.0f);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
- immAttrib2f(texcoord, 0.0f, 1.0f);
- immVertex2f(pos, 0.0f, h);
-
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
+ GPU_texture_bind(color, 0);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), 0.0f, 0.0f, 1.0f, 1.0f);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
- immEnd();
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
GPU_texture_unbind(color);
-
- immUnbindProgram();
}
-void GPU_viewport_unbind(GPUViewport *viewport)
+void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
{
- DefaultFramebufferList *dfbl = viewport->fbl;
-
- if (dfbl->default_fb) {
- GPU_framebuffer_texture_unbind(NULL, NULL);
- GPU_framebuffer_restore();
-
- glEnable(GL_SCISSOR_TEST);
- glDisable(GL_DEPTH_TEST);
-
- /* This might be bandwidth limiting */
- draw_ofs_to_screen(viewport);
- }
+ DRW_opengl_context_disable();
}
static void gpu_viewport_buffers_free(
@@ -571,6 +587,7 @@ static void gpu_viewport_passes_free(PassList *psl, int psl_len)
}
}
+/* Must be executed inside Drawmanager Opengl Context. */
void GPU_viewport_free(GPUViewport *viewport)
{
gpu_viewport_engines_data_free(viewport);
@@ -587,8 +604,8 @@ void GPU_viewport_free(GPUViewport *viewport)
if (viewport->vmempool.calls != NULL) {
BLI_mempool_destroy(viewport->vmempool.calls);
}
- if (viewport->vmempool.calls_generate != NULL) {
- BLI_mempool_destroy(viewport->vmempool.calls_generate);
+ if (viewport->vmempool.states != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.states);
}
if (viewport->vmempool.shgroups != NULL) {
BLI_mempool_destroy(viewport->vmempool.shgroups);
@@ -603,84 +620,5 @@ void GPU_viewport_free(GPUViewport *viewport)
DRW_instance_data_list_free(viewport->idatalist);
MEM_freeN(viewport->idatalist);
- GPU_viewport_debug_depth_free(viewport);
-}
-
-/****************** debug ********************/
-
-bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
-{
- viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
- return (viewport->debug_depth != NULL);
-}
-
-void GPU_viewport_debug_depth_free(GPUViewport *viewport)
-{
- if (viewport->debug_depth != NULL) {
- MEM_freeN(viewport->debug_depth);
- viewport->debug_depth = NULL;
- }
-}
-
-void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y)
-{
- const int w = GPU_texture_width(viewport->debug_depth);
- const int h = GPU_texture_height(viewport->debug_depth);
-
- GPU_texture_bind(viewport->debug_depth, 0);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, x, y, w, h, 0);
- GPU_texture_unbind(viewport->debug_depth);
-}
-
-void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar)
-{
- const float w = (float)GPU_texture_width(viewport->debug_depth);
- const float h = (float)GPU_texture_height(viewport->debug_depth);
-
- Gwn_VertFormat *format = immVertexFormat();
- unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH);
-
- GPU_texture_bind(viewport->debug_depth, 0);
-
- immUniform1f("znear", znear);
- immUniform1f("zfar", zfar);
- immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
-
- immBegin(GWN_PRIM_TRI_STRIP, 4);
-
- immAttrib2f(texcoord, 0.0f, 0.0f);
- immVertex2f(pos, 0.0f, 0.0f);
-
- immAttrib2f(texcoord, 1.0f, 0.0f);
- immVertex2f(pos, w, 0.0f);
-
- immAttrib2f(texcoord, 0.0f, 1.0f);
- immVertex2f(pos, 0.0f, h);
-
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
-
- immEnd();
-
- GPU_texture_unbind(viewport->debug_depth);
-
- immUnbindProgram();
-}
-
-int GPU_viewport_debug_depth_width(const GPUViewport *viewport)
-{
- return GPU_texture_width(viewport->debug_depth);
-}
-
-int GPU_viewport_debug_depth_height(const GPUViewport *viewport)
-{
- return GPU_texture_height(viewport->debug_depth);
-}
-
-bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport)
-{
- return viewport->debug_depth != NULL;
+ MEM_freeN(viewport);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
new file mode 100644
index 00000000000..9fdf8ececc5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
@@ -0,0 +1,48 @@
+/**
+ * Simple shader that just draw multiple icons at the specified locations
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+/* Same as ICON_DRAW_CACHE_SIZE */
+#define MAX_CALLS 16
+
+uniform vec4 calls_data[MAX_CALLS * 3];
+
+out vec2 texCoord_interp;
+flat out vec4 finalColor;
+
+void main()
+{
+ /* Rendering 2 triangle per icon. */
+ int i = gl_VertexID / 6;
+ int v = gl_VertexID % 6;
+
+ vec4 pos = calls_data[i*3];
+ vec4 tex = calls_data[i*3+1];
+ finalColor = calls_data[i*3+2];
+
+ /* TODO Remove this */
+ if (v == 2) v = 4;
+ else if (v == 3) v = 0;
+ else if (v == 5) v = 2;
+
+ if (v == 0) {
+ pos.xy = pos.xw;
+ tex.xy = tex.xw;
+ }
+ else if (v == 1) {
+ pos.xy = pos.xz;
+ tex.xy = tex.xz;
+ }
+ else if (v == 2) {
+ pos.xy = pos.yw;
+ tex.xy = tex.yw;
+ }
+ else {
+ pos.xy = pos.yz;
+ tex.xy = tex.yz;
+ }
+
+ gl_Position = vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = tex.xy;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
new file mode 100644
index 00000000000..118f4e3b187
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
@@ -0,0 +1,35 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 rect_icon;
+uniform vec4 rect_geom;
+
+out vec2 texCoord_interp;
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
new file mode 100644
index 00000000000..8dda575107a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
@@ -0,0 +1,10 @@
+
+in float colorGradient;
+in vec4 finalColor;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = finalColor;
+ fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient));
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
new file mode 100644
index 00000000000..4c295fcd72a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -0,0 +1,107 @@
+/**
+ * 2D Quadratic Bezier thick line drawing
+ **/
+
+#define MID_VERTEX 57
+
+/* u is position along the curve, defining the tangent space.
+ * v is "signed" distance (compressed to [0..1] range) from the pos in expand direction */
+in vec2 uv;
+in vec2 pos; /* verts position in the curve tangent space */
+in vec2 expand;
+
+#ifdef USE_INSTANCE
+/* Instance attrib */
+in vec2 P0;
+in vec2 P1;
+in vec2 P2;
+in vec2 P3;
+in ivec4 colid_doarrow;
+
+uniform vec4 colors[6];
+
+#define colStart colors[colid_doarrow[0]]
+#define colEnd colors[colid_doarrow[1]]
+#define colShadow colors[colid_doarrow[2]]
+#define doArrow (colid_doarrow[3] != 0)
+
+#else
+/* Single curve drawcall, use uniform. */
+uniform vec2 bezierPts[4];
+
+#define P0 bezierPts[0]
+#define P1 bezierPts[1]
+#define P2 bezierPts[2]
+#define P3 bezierPts[3]
+
+uniform vec4 colors[3];
+uniform bool doArrow;
+
+#define colShadow colors[0]
+#define colStart colors[1]
+#define colEnd colors[2]
+
+#endif
+
+uniform float expandSize;
+uniform float arrowSize;
+uniform mat4 ModelViewProjectionMatrix;
+
+out float colorGradient;
+out vec4 finalColor;
+
+void main(void)
+{
+ float t = uv.x;
+ float t2 = t * t;
+ float t2_3 = 3.0 * t2;
+ float one_minus_t = 1.0 - t;
+ float one_minus_t2 = one_minus_t * one_minus_t;
+ float one_minus_t2_3 = 3.0 * one_minus_t2;
+
+ vec2 point = (P0 * one_minus_t2 * one_minus_t +
+ P1 * one_minus_t2_3 * t +
+ P2 * t2_3 * one_minus_t +
+ P3 * t2 * t);
+
+ vec2 tangent = ((P1 - P0) * one_minus_t2_3 +
+ (P2 - P1) * 6.0 * (t - t2) +
+ (P3 - P2) * t2_3);
+
+ /* tangent space at t */
+ tangent = normalize(tangent);
+ vec2 normal = tangent.yx * vec2(-1.0, 1.0);
+
+ /* Position vertex on the curve tangent space */
+ point += (pos.x * tangent + pos.y * normal) * arrowSize;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(point, 0.0, 1.0);
+
+ vec2 exp_axis = expand.x * tangent + expand.y * normal;
+
+ /* rotate & scale the expand axis */
+ exp_axis = ModelViewProjectionMatrix[0].xy * exp_axis.xx +
+ ModelViewProjectionMatrix[1].xy * exp_axis.yy;
+
+
+ float expand_dist = (uv.y * 2.0 - 1.0);
+ colorGradient = expand_dist;
+
+ if (gl_VertexID < MID_VERTEX) {
+ /* Shadow pass */
+ finalColor = colShadow;
+ }
+ else {
+ /* Second pass */
+ finalColor = mix(colStart, colEnd, uv.x);
+ expand_dist *= 0.5;
+ }
+
+ /* Expand into a line */
+ gl_Position.xy += exp_axis * expandSize * expand_dist;
+
+ /* if arrow */
+ if (expand.y != 1.0 && !doArrow) {
+ gl_Position.xy *= 0.0;
+ }
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
new file mode 100644
index 00000000000..f660cae8d12
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
@@ -0,0 +1,35 @@
+uniform vec3 checkerColorAndSize;
+
+noperspective in vec4 finalColor;
+noperspective in float butCo;
+
+out vec4 fragColor;
+
+vec4 do_checkerboard()
+{
+ float size = checkerColorAndSize.z;
+ vec2 phase = mod(gl_FragCoord.xy, size * 2.0);
+
+ if ((phase.x > size && phase.y < size) ||
+ (phase.x < size && phase.y > size))
+ {
+ return vec4(checkerColorAndSize.xxx, 1.0);
+ }
+ else {
+ return vec4(checkerColorAndSize.yyy, 1.0);
+ }
+}
+
+void main()
+{
+ fragColor = finalColor;
+
+ if (butCo > 0.5) {
+ vec4 checker = do_checkerboard();
+ fragColor = mix(checker, fragColor, fragColor.a);
+ }
+
+ if (butCo > 0.0) {
+ fragColor.a = 1.0;
+ }
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
new file mode 100644
index 00000000000..0c351a3bce4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -0,0 +1,186 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+/* 4bits for jitter id */
+#define JIT_OFS 6u
+#define JIT_RANGE BIT_RANGE(4)
+const vec2 jit[9] = vec2[9](
+ vec2( 0.468813, -0.481430), vec2(-0.155755, -0.352820),
+ vec2( 0.219306, -0.238501), vec2(-0.393286, -0.110949),
+ vec2(-0.024699, 0.013908), vec2( 0.343805, 0.147431),
+ vec2(-0.272855, 0.269918), vec2( 0.095909, 0.388710),
+ vec2( 0.0, 0.0)
+);
+
+/* 2bits for other flags */
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+#define EMBOSS_FLAG uint(1 << 11) /* is emboss vert */
+
+/* 2bits for color */
+#define COLOR_OFS 12u
+#define COLOR_RANGE BIT_RANGE(2)
+#define COLOR_INNER 0u
+#define COLOR_EDGE 1u
+#define COLOR_EMBOSS 2u
+
+/* 2bits for trias type */
+#define TRIA_FLAG uint(1 << 14) /* is tria vert */
+#define TRIA_FIRST INNER_FLAG /* is first tria (reuse INNER_FLAG) */
+
+/* We can reuse the CORNER_* bits for tria */
+#define TRIA_VEC_RANGE BIT_RANGE(6)
+const vec2 triavec[34] = vec2[34](
+ /* horizontal tria */
+ vec2(-0.352077, 0.532607), vec2(-0.352077, -0.549313), vec2( 0.330000, -0.008353),
+ vec2( 0.352077, 0.532607), vec2( 0.352077, -0.549313), vec2(-0.330000, -0.008353),
+ /* circle tria (triangle strip) */
+ vec2(0.000000, 1.000000),
+ vec2(0.382684, 0.923879), vec2(-0.382683, 0.923880),
+ vec2(0.707107, 0.707107), vec2(-0.707107, 0.707107),
+ vec2(0.923879, 0.382684), vec2(-0.923879, 0.382684),
+ vec2(1.000000, 0.000000), vec2(-1.000000, 0.000000),
+ vec2(0.923879, -0.382684), vec2(-0.923879, -0.382684),
+ vec2(0.707107, -0.707107), vec2(-0.707107, -0.707107),
+ vec2(0.382684, -0.923879), vec2(-0.382683, -0.923880),
+ vec2(0.000000, -1.000000),
+ /* menu arrow */
+ vec2(-0.33, 0.16), vec2(0.33, 0.16), vec2(0.0, 0.82),
+ vec2(0.0, -0.82), vec2(-0.33, -0.16), vec2(0.33, -0.16),
+ /* check mark */
+ vec2(-0.578579, 0.253369), vec2(-0.392773, 0.412794), vec2(-0.004241, -0.328551),
+ vec2(-0.003001, 0.034320), vec2(1.055313, 0.864744), vec2(0.866408, 1.026895)
+);
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#ifdef USE_INSTANCE
+#define MAX_INSTANCE 6
+uniform vec4 parameters[11 * MAX_INSTANCE];
+#else
+uniform vec4 parameters[11];
+#endif
+
+/* gl_InstanceID is 0 if not drawing instances. */
+#define recti parameters[gl_InstanceID * 11 + 0]
+#define rect parameters[gl_InstanceID * 11 + 1]
+#define radsi parameters[gl_InstanceID * 11 + 2].x
+#define rads parameters[gl_InstanceID * 11 + 2].y
+#define faci parameters[gl_InstanceID * 11 + 2].zw
+#define roundCorners parameters[gl_InstanceID * 11 + 3]
+#define colorInner1 parameters[gl_InstanceID * 11 + 4]
+#define colorInner2 parameters[gl_InstanceID * 11 + 5]
+#define colorEdge parameters[gl_InstanceID * 11 + 6]
+#define colorEmboss parameters[gl_InstanceID * 11 + 7]
+#define colorTria parameters[gl_InstanceID * 11 + 8]
+#define tria1Center parameters[gl_InstanceID * 11 + 9].xy
+#define tria2Center parameters[gl_InstanceID * 11 + 9].zw
+#define tria1Size parameters[gl_InstanceID * 11 + 10].x
+#define tria2Size parameters[gl_InstanceID * 11 + 10].y
+#define shadeDir parameters[gl_InstanceID * 11 + 10].z
+#define doAlphaCheck parameters[gl_InstanceID * 11 + 10].w
+
+in uint vflag;
+
+noperspective out vec4 finalColor;
+noperspective out float butCo;
+
+vec2 do_widget(void)
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ /* compute uv and color gradient */
+ uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE;
+ if (color_id == COLOR_INNER) {
+ vec2 uv = faci * (v - recti.xz);
+ float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0);
+ if (doAlphaCheck != 0.0) {
+ finalColor = colorInner1;
+ butCo = uv.x;
+ }
+ else {
+ finalColor = mix(colorInner2, colorInner1, fac);
+ butCo = -1.0;
+ }
+ }
+ else if (color_id == COLOR_EDGE) {
+ finalColor = colorEdge;
+ butCo = -1.0;
+ }
+ else /* (color_id == COLOR_EMBOSS) */ {
+ finalColor = colorEmboss;
+ butCo = -1.0;
+ }
+
+ bool is_emboss = (vflag & EMBOSS_FLAG) != 0u;
+ v.y -= (is_emboss) ? 1.0f : 0.0;
+
+ return v;
+}
+
+vec2 do_tria()
+{
+ uint vofs = vflag & TRIA_VEC_RANGE;
+
+ vec2 v = triavec[vofs];
+
+ finalColor = colorTria;
+ butCo = -1.0;
+
+ bool is_tria_first = (vflag & TRIA_FIRST) != 0u;
+
+ if (is_tria_first)
+ v = v * tria1Size + tria1Center;
+ else
+ v = v * tria2Size + tria2Center;
+
+ return v;
+}
+
+void main()
+{
+ bool is_tria = (vflag & TRIA_FLAG) != 0u;
+
+ vec2 v = (is_tria) ? do_tria() : do_widget();
+
+ /* Antialiasing offset */
+ v += jit[(vflag >> JIT_OFS) & JIT_RANGE];
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
new file mode 100644
index 00000000000..7587b2fc18a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
@@ -0,0 +1,13 @@
+
+in float shadowFalloff;
+
+out vec4 fragColor;
+
+uniform float alpha;
+
+void main()
+{
+ fragColor = vec4(0.0);
+ /* Manual curve fit of the falloff curve of previous drawing method. */
+ fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
new file mode 100644
index 00000000000..2f5353a7c86
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
@@ -0,0 +1,64 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 parameters[4];
+/* radi and rad per corner */
+#define recti parameters[0]
+#define rect parameters[1]
+#define radsi parameters[2].x
+#define rads parameters[2].y
+#define roundCorners parameters[3]
+
+in uint vflag;
+
+out float shadowFalloff;
+
+void main()
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ shadowFalloff = (is_inner) ? 1.0 : 0.0;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
deleted file mode 100644
index fc5cc1cdcc3..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
+++ /dev/null
@@ -1,10 +0,0 @@
-
-in vec2 pos;
-in vec2 uvs;
-out vec4 uvcoordsvar;
-
-void main()
-{
- uvcoordsvar = vec4(uvs, 0.0, 0.0);
- gl_Position = vec4(pos, 0.0, 1.0);
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
new file mode 100644
index 00000000000..10f4dfd5a87
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ float depth = texture(image, texCoord_interp).r;
+ fragColor = vec4(depth);
+ gl_FragDepth = depth;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
index 7d9ce9d2003..6eeab8ca7e8 100644
--- a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
@@ -2,11 +2,9 @@
in vec2 texCoord_interp;
out vec4 fragColor;
-uniform float alpha;
-uniform sampler2DRect image;
+uniform sampler2D image;
void main()
{
fragColor = texture(image, texCoord_interp);
- fragColor.a *= alpha;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
index 7f3e7df40ac..d95645f58e5 100644
--- a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
@@ -8,8 +8,8 @@ in vec2 texCoord_interp;
out vec4 fragColor;
uniform int interlace_id;
-uniform sampler2DRect image_a;
-uniform sampler2DRect image_b;
+uniform sampler2D image_a;
+uniform sampler2D image_b;
bool interlace()
{
diff --git a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
new file mode 100644
index 00000000000..37686092700
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp) * finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl
index 819199c26c7..819199c26c7 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_mball_handles_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 780f4f59fb9..d3bc1f0ef8e 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,16 +1,9 @@
-uniform mat4 ModelViewMatrix;
-#ifndef EEVEE_ENGINE
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
-uniform mat4 ViewMatrix;
-#endif
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixInverse;
+uniform mat4 ModelViewMatrix;
uniform mat4 ModelViewMatrixInverse;
-uniform mat4 ProjectionMatrixInverse;
uniform mat3 NormalMatrix;
-uniform vec4 CameraTexCoFactors;
/* Old glsl mode compat. */
@@ -238,16 +231,18 @@ void geom(
}
void particle_info(
- vec4 sprops, vec3 loc, vec3 vel, vec3 avel,
- out float index, out float age, out float life_time, out vec3 location,
+ vec4 sprops, vec4 loc, vec3 vel, vec3 avel,
+ out float index, out float random, out float age,
+ out float life_time, out vec3 location,
out float size, out vec3 velocity, out vec3 angular_velocity)
{
index = sprops.x;
+ random = loc.w;
age = sprops.y;
life_time = sprops.z;
size = sprops.w;
- location = loc;
+ location = loc.xyz;
velocity = vel;
angular_velocity = avel;
}
@@ -2533,8 +2528,7 @@ uint hash(int kx, int ky, int kz)
float bits_to_01(uint bits)
{
- float x = float(bits) * (1.0 / float(0xffffffffu));
- return x;
+ return (float(bits) / 4294967295.0);
}
float cellnoise(vec3 p)
@@ -2696,7 +2690,6 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
{
#ifdef EEVEE_ENGINE
vec3 out_spec, ssr_spec;
- roughness = sqrt(roughness);
eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
@@ -2718,7 +2711,8 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
vec3 light_specular = glLightSource[i].specular.rgb;
/* we mix in some diffuse so low roughness still shows up */
- float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness);
+ float r2 = roughness * roughness;
+ float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2);
bsdf += 0.5 * max(dot(N, light_position), 0.0);
L += light_specular * bsdf;
}
@@ -2738,7 +2732,6 @@ void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_i
{
#ifdef EEVEE_ENGINE
vec3 out_spec, out_refr, ssr_spec;
- roughness = sqrt(roughness);
vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */
eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
out_refr *= refr_color;
@@ -2977,9 +2970,10 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
#ifdef EEVEE_ENGINE
vec3 out_refr;
color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
- roughness = sqrt(roughness);
eevee_closure_refraction(N, roughness, ior, out_refr);
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
result.radiance = out_refr * color.rgb;
result.ssr_id = REFRACT_CLOSURE_FLAG;
#else
@@ -3004,7 +2998,7 @@ void node_ambient_occlusion(vec4 color, out Closure result)
/* emission */
-void node_emission(vec4 color, float strength, vec3 N, out Closure result)
+void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
{
#ifndef VOLUMETRICS
color *= strength;
@@ -3012,7 +3006,7 @@ void node_emission(vec4 color, float strength, vec3 N, out Closure result)
result = CLOSURE_DEFAULT;
result.radiance = color.rgb;
result.opacity = color.a;
- result.ssr_normal = normal_encode(N, viewCameraVec);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
#else
result = Closure(color.rgb, color.a);
#endif
@@ -3072,6 +3066,86 @@ void node_volume_absorption(vec4 color, float density, out Closure result)
#endif
}
+void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color)
+{
+ if(temperature >= 12000.0) {
+ color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0);
+ }
+ else if(temperature < 965.0) {
+ color = vec4(4.70366907, 0.0, 0.0, 1.0);
+ }
+ else {
+ float t = (temperature - 965.0) / (12000.0 - 965.0);
+ color = vec4(texture(spectrummap, vec2(t, 0.0)).rgb, 1.0);
+ }
+}
+
+void node_volume_principled(
+ vec4 color,
+ float density,
+ float anisotropy,
+ vec4 absorption_color,
+ float emission_strength,
+ vec4 emission_color,
+ float blackbody_intensity,
+ vec4 blackbody_tint,
+ float temperature,
+ float density_attribute,
+ vec4 color_attribute,
+ float temperature_attribute,
+ sampler2D spectrummap,
+ out Closure result)
+{
+#ifdef VOLUMETRICS
+ vec3 absorption_coeff = vec3(0.0);
+ vec3 scatter_coeff = vec3(0.0);
+ vec3 emission_coeff = vec3(0.0);
+
+ /* Compute density. */
+ density = max(density, 0.0);
+
+ if(density > 1e-5) {
+ density = max(density * density_attribute, 0.0);
+ }
+
+ if(density > 1e-5) {
+ /* Compute scattering and absorption coefficients. */
+ vec3 scatter_color = color.rgb * color_attribute.rgb;
+
+ scatter_coeff = scatter_color * density;
+ absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0));
+ absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * density;
+ }
+
+ /* Compute emission. */
+ emission_strength = max(emission_strength, 0.0);
+
+ if(emission_strength > 1e-5) {
+ emission_coeff += emission_strength * emission_color.rgb;
+ }
+
+ if(blackbody_intensity > 1e-3) {
+ /* Add temperature from attribute. */
+ float T = max(temperature * max(temperature_attribute, 0.0), 0.0);
+
+ /* Stefan-Boltzman law. */
+ float T4 = (T * T) * (T * T);
+ float sigma = 5.670373e-8 * 1e-6 / M_PI;
+ float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+ if(intensity > 1e-5) {
+ vec4 bb;
+ node_blackbody(T, spectrummap, bb);
+ emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
+ }
+ }
+
+ result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
+
/* closures */
void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
@@ -3150,7 +3224,13 @@ void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec
#else
vec3 cos = vec3(0.0);
#endif
- outvec = texture(tex, cos).rgb;
+
+ vec4 value = texture(tex, cos).rgba;
+ /* Density is premultiplied for interpolation, divide it out here. */
+ if (value.a > 1e-8)
+ value.rgb /= value.a;
+
+ outvec = value.rgb;
outcol = vec4(outvec, 1.0);
outf = dot(vec3(1.0 / 3.0), outvec);
}
@@ -3162,9 +3242,23 @@ void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec
#else
vec3 cos = vec3(0.0);
#endif
- outvec = texture(tex, cos).rrr;
- outcol = vec4(outvec, 1.0);
- outf = dot(vec3(1.0 / 3.0), outvec);
+ outf = texture(tex, cos).r;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
+}
+
+void node_attribute_volume_temperature(sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ float flame = texture(tex, cos).r;
+
+ outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x): 0.0;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
}
void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
@@ -3657,17 +3751,29 @@ float noise_perlin(float x, float y, float z)
float v = noise_fade(fy);
float w = noise_fade(fz);
- float result;
+ float noise_u[2], noise_v[2];
+
+ noise_u[0] = noise_nerp(u,
+ noise_grad(hash(X, Y, Z), fx, fy, fz),
+ noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz));
+
+ noise_u[1] = noise_nerp(u,
+ noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz),
+ noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
+
+ noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]);
- result = noise_nerp(w, noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z), fx, fy, fz),
- noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)),
- noise_nerp(u, noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz),
- noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz))),
- noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0),
- noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)),
- noise_nerp(u, noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
- noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0))));
- return noise_scale3(result);
+ noise_u[0] = noise_nerp(u,
+ noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0),
+ noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
+
+ noise_u[1] = noise_nerp(u,
+ noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
+ noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
+
+ noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]);
+
+ return noise_scale3(noise_nerp(w, noise_v[0], noise_v[1]));
}
float noise(vec3 p)
@@ -4135,9 +4241,38 @@ void node_bevel(float radius, vec3 N, out vec3 result)
result = N;
}
-void node_displacement(float height, float dist, vec3 N, out vec3 result)
+void node_displacement_object(float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result)
+{
+ N = (vec4(N, 0.0) * obmat).xyz;
+ result = (height - midlevel) * scale * normalize(N);
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result)
+{
+ result = (height - midlevel) * scale * normalize(N);
+}
+
+void node_vector_displacement_tangent(vec4 vector, float midlevel, float scale, vec4 tangent, vec3 normal, mat4 obmat, mat4 viewmat, out vec3 result)
+{
+ vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz);
+ vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz);
+ vec3 B_object = tangent.w * normalize(cross(N_object, T_object));
+
+ vec3 offset = (vector.xyz - vec3(midlevel)) * scale;
+ result = offset.x * T_object + offset.y * N_object + offset.z * B_object;
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_vector_displacement_object(vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result)
+{
+ result = (vector.xyz - vec3(midlevel)) * scale;
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result)
{
- result = height * dist * N;
+ result = (vector.xyz - vec3(midlevel)) * scale;
}
/* output */
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 1319e386c65..fca39852c2a 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,12 +1,14 @@
-uniform mat4 ModelViewProjectionMatrix;
-
-in vec2 pos;
-in vec2 uvs;
out vec2 texCoord_interp;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
- texCoord_interp = uvs;
+ const vec4 vert[3] = vec4[3](
+ vec3(-1.0, -1.0, 0.0, 0.0),
+ vec3( 3.0, -1.0, 2.0, 0.0),
+ vec3(-1.0, 3.0, 0.0, 2.0)
+ );
+
+ gl_Position = vec4(vert[gl_VertexID].xy, 0.0, 1.0);
+ texCoord_interp = vert[gl_VertexID].zw;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
index 7ff90ad4f21..fbfa4cfcc9d 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -1,15 +1,74 @@
flat in vec4 color_flat;
+flat in vec4 texCoord_rect;
noperspective in vec2 texCoord_interp;
out vec4 fragColor;
uniform sampler2D glyph;
+const vec2 offsets4[4] = vec2[4](
+ vec2(-0.5, 0.5), vec2( 0.5, 0.5),
+ vec2(-0.5, -0.5), vec2(-0.5, -0.5)
+);
+
+const vec2 offsets16[16] = vec2[16](
+ vec2(-1.5, 1.5), vec2(-0.5, 1.5), vec2( 0.5, 1.5), vec2( 1.5, 1.5),
+ vec2(-1.5, 0.5), vec2(-0.5, 0.5), vec2( 0.5, 0.5), vec2( 1.5, 0.5),
+ vec2(-1.5, -0.5), vec2(-0.5, -0.5), vec2( 0.5, -0.5), vec2( 1.5, -0.5),
+ vec2(-1.5, -1.5), vec2(-0.5, -1.5), vec2( 0.5, -1.5), vec2( 1.5, -1.5)
+);
+
+#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+
void main()
{
// input color replaces texture color
fragColor.rgb = color_flat.rgb;
+ vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
+ vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp);
+
// modulate input alpha & texture alpha
- fragColor.a = color_flat.a * texture(glyph, texCoord_interp).r;
+ if (texCoord_rect.x > 0) {
+ fragColor.a = texture(glyph, texco).r;
+ }
+ else {
+ fragColor.a = 0.0;
+
+ if (texCoord_rect.w > 0) {
+ /* 3x3 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]);
+ fragColor.a *= (1.0 / 4.0);
+ }
+ else {
+ /* 5x5 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 3]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 4]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 5]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 6]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 7]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 8]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 9]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]);
+ fragColor.a *= (1.0 / 20.0);
+ }
+ }
+
+ fragColor.a *= color_flat.a;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
new file mode 100644
index 00000000000..0acd2106f7a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
@@ -0,0 +1,37 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
new file mode 100644
index 00000000000..8903fd1df57
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
@@ -0,0 +1,36 @@
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+ gl_Position.zw = vec2(0.0, 1.0);
+
+ gl_Position.xy = pos_rect[0].xy;
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zy;
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].xw;
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zw;
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
new file mode 100644
index 00000000000..4a2cde71e07
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
@@ -0,0 +1,22 @@
+
+/* Simpler version of gpu_shader_text_vert that supports only 2D translation. */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
+
+void main()
+{
+ /* Manual mat4*vec2 */
+ pos_rect = ModelViewProjectionMatrix[0].xyxy * pos.xxzz;
+ pos_rect += ModelViewProjectionMatrix[1].xyxy * pos.yyww;
+ pos_rect += ModelViewProjectionMatrix[3].xyxy;
+ tex_rect = tex;
+ color = col;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
index 6129f49ce22..338156f5b68 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -1,16 +1,17 @@
uniform mat4 ModelViewProjectionMatrix;
-in vec2 pos;
-in vec2 texCoord;
-in vec4 color;
-flat out vec4 color_flat;
-noperspective out vec2 texCoord_interp;
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
-
- color_flat = color;
- texCoord_interp = texCoord;
+ pos_rect = pos;
+ tex_rect = tex;
+ color = col;
}