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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt11
-rw-r--r--source/blender/gpu/GPU_batch_presets.h4
-rw-r--r--source/blender/gpu/GPU_buffers.h11
-rw-r--r--source/blender/gpu/GPU_context.h8
-rw-r--r--source/blender/gpu/GPU_draw.h15
-rw-r--r--source/blender/gpu/GPU_immediate_util.h7
-rw-r--r--source/blender/gpu/GPU_init_exit.h4
-rw-r--r--source/blender/gpu/GPU_material.h14
-rw-r--r--source/blender/gpu/GPU_shader.h73
-rw-r--r--source/blender/gpu/GPU_shader_interface.h58
-rw-r--r--source/blender/gpu/GPU_state.h6
-rw-r--r--source/blender/gpu/GPU_texture.h32
-rw-r--r--source/blender/gpu/GPU_vertex_format.h11
-rw-r--r--source/blender/gpu/intern/gpu_batch.c52
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c150
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.h8
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c347
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c26
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h4
-rw-r--r--source/blender/gpu/intern/gpu_draw.c104
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c10
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c11
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c136
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c26
-rw-r--r--source/blender/gpu/intern/gpu_material.c12
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c44
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c34
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c18
-rw-r--r--source/blender/gpu/intern/gpu_shader.c236
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c486
-rw-r--r--source/blender/gpu/intern/gpu_state.c40
-rw-r--r--source/blender/gpu/intern/gpu_texture.c471
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c6
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.c2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c125
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c209
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl57
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_polyline_frag.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_polyline_geom.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_polyline_vert.glsl28
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl119
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl5
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl52
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl7
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl168
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl64
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl5
59 files changed, 1938 insertions, 1599 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index cf1d449ad3b..1d6a5031d7e 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -146,8 +146,6 @@ data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl SRC)
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_flat_id_frag.glsl SRC)
@@ -165,7 +163,6 @@ 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)
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_smooth_color_dithered_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)
@@ -179,16 +176,15 @@ 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_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_multisample_resolve_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)
data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_polyline_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_polyline_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_polyline_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_3D_normal_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_passthrough_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC)
@@ -321,6 +317,7 @@ data_to_c_simple(shaders/gpu_shader_gpencil_fill_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_gpencil_fill_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_colorspace_lib.glsl SRC)
data_to_c_simple(shaders/gpu_shader_common_obinfos_lib.glsl SRC)
diff --git a/source/blender/gpu/GPU_batch_presets.h b/source/blender/gpu/GPU_batch_presets.h
index ba8ad3c4990..eb803333d98 100644
--- a/source/blender/gpu/GPU_batch_presets.h
+++ b/source/blender/gpu/GPU_batch_presets.h
@@ -39,6 +39,10 @@ extern "C" {
/* Replacement for gluSphere */
struct GPUBatch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
struct GPUBatch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
+struct GPUBatch *GPU_batch_preset_panel_drag_widget(const float pixelsize,
+ const float col_high[4],
+ const float col_dark[4],
+ const float width) ATTR_WARN_UNUSED_RESULT;
void gpu_batch_presets_init(void);
void gpu_batch_presets_register(struct GPUBatch *preset_batch);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 9d91fd79137..ab16bfc43c4 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -42,14 +42,14 @@ struct MPoly;
struct MVert;
struct Mesh;
struct PBVH;
+struct SubdivCCG;
/* Buffers for drawing from PBVH grids. */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
/* Build must be called once before using the other functions, used every time
* mesh topology changes. Threaded. */
-GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
- const struct MPoly *mpoly,
+GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const struct MPoly *mpoly,
const struct MLoop *mloop,
const struct MLoopTri *looptri,
const struct MVert *verts,
@@ -77,14 +77,11 @@ enum {
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const struct MVert *mvert,
- const int *vert_indices,
- int totvert,
const float *vmask,
const struct MLoopCol *vcol,
const int *sculpt_face_sets,
const int face_sets_color_seed,
const int face_sets_color_default,
- const int (*face_vert_indices)[3],
const int update_flags);
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
@@ -95,10 +92,14 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
const int update_flags);
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
+ struct SubdivCCG *subdiv_ccg,
struct CCGElem **grids,
const struct DMFlagMat *grid_flag_mats,
int *grid_indices,
int totgrid,
+ const int *sculpt_face_sets,
+ const int face_sets_color_seed,
+ const int face_sets_color_default,
const struct CCGKey *key,
const int update_flags);
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index dd7611fe2fc..9876aa6998c 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -26,14 +26,14 @@
#ifndef __GPU_CONTEXT_H__
#define __GPU_CONTEXT_H__
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "GPU_batch.h"
#include "GPU_common.h"
#include "GPU_shader_interface.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct GPUContext GPUContext;
GPUContext *GPU_context_create(GLuint default_framebuffer);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index f521fa3c702..ab507d852e8 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -24,6 +24,9 @@
#ifndef __GPU_DRAW_H__
#define __GPU_DRAW_H__
+#include "BLI_utildefines.h"
+#include "DNA_object_enums.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -34,18 +37,8 @@ struct Image;
struct ImageUser;
struct Main;
-#include "BLI_utildefines.h"
-#include "DNA_object_enums.h"
-
/* OpenGL drawing functions related to shading. */
-/* Initialize
- * - sets the default Blender opengl state, if in doubt, check
- * the contents of this function
- * - this is called when starting Blender, for opengl rendering. */
-
-void GPU_state_init(void);
-
/* Mipmap settings
* - these will free textures on changes */
@@ -57,7 +50,7 @@ void GPU_paint_set_mipmap(struct Main *bmain, bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
-void GPU_set_anisotropic(struct Main *bmain, float value);
+void GPU_set_anisotropic(float value);
float GPU_get_anisotropic(void);
/* Image updates and free
diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h
index 1cf6475408f..47b44b59461 100644
--- a/source/blender/gpu/GPU_immediate_util.h
+++ b/source/blender/gpu/GPU_immediate_util.h
@@ -70,6 +70,13 @@ void imm_draw_disk_partial_fill_2d(uint pos,
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2);
void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2);
+void imm_draw_box_checker_2d_ex(float x1,
+ float y1,
+ float x2,
+ float y2,
+ const float color_primary[4],
+ const float color_secondary[4],
+ int checker_size);
void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2);
void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]);
diff --git a/source/blender/gpu/GPU_init_exit.h b/source/blender/gpu/GPU_init_exit.h
index 0046eaa942b..3e30a1ddcf5 100644
--- a/source/blender/gpu/GPU_init_exit.h
+++ b/source/blender/gpu/GPU_init_exit.h
@@ -24,12 +24,12 @@
#ifndef __GPU_INIT_EXIT_H__
#define __GPU_INIT_EXIT_H__
+#include "BLI_utildefines.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-#include "BLI_utildefines.h"
-
void GPU_init(void);
void GPU_exit(void);
bool GPU_is_initialized(void);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 337c0b03308..eeb2d2caef2 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -29,6 +29,8 @@
#include "BLI_sys_types.h" /* for bool */
+#include "GPU_texture.h" /* for eGPUSamplerState */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -138,8 +140,14 @@ typedef enum eGPUMaterialStatus {
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
-GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
@@ -190,6 +198,7 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct GPUShader *GPU_material_get_shader(GPUMaterial *material);
struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
@@ -228,6 +237,7 @@ typedef struct GPUMaterialTexture {
char sampler_name[32]; /* Name of sampler in GLSL. */
char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
int users;
+ int sampler_state; /* eGPUSamplerState */
} GPUMaterialTexture;
typedef struct GPUMaterialVolumeGrid {
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 334e295c636..0ad472113c9 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -29,6 +29,7 @@ extern "C" {
#endif
typedef struct GPUShader GPUShader;
+struct GPUShaderInterface;
struct GPUTexture;
struct GPUUniformBuffer;
@@ -49,6 +50,11 @@ GPUShader *GPU_shader_create(const char *vertexcode,
const char *libcode,
const char *defines,
const char *shader_name);
+GPUShader *GPU_shader_create_from_python(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines);
GPUShader *GPU_shader_create_ex(const char *vertexcode,
const char *fragcode,
const char *geocode,
@@ -83,17 +89,21 @@ int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
+void GPU_shader_set_srgb_uniform(const struct GPUShaderInterface *interface);
+
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
+int GPU_shader_get_builtin_block(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
+
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name);
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name);
+
void GPU_shader_uniform_vector(
GPUShader *shader, int location, int length, int arraysize, const float *value);
void GPU_shader_uniform_vector_int(
GPUShader *shader, int location, int length, int arraysize, const int *value);
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
-void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_float(GPUShader *shader, int location, float value);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
@@ -101,16 +111,14 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name);
char *GPU_shader_get_binary(GPUShader *shader, uint *r_binary_format, int *r_binary_len);
+void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear);
+
/* Builtin/Non-generated shaders */
typedef enum eGPUBuiltinShader {
/* specialized drawing */
GPU_SHADER_TEXT,
GPU_SHADER_KEYFRAME_DIAMOND,
GPU_SHADER_SIMPLE_LIGHTING,
- GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR,
- GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR,
- GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA,
-
/* for simple 2D drawing */
/**
* Take a single color for all the vertices and a 2D position for each vertex.
@@ -133,7 +141,6 @@ typedef enum eGPUBuiltinShader {
* \param pos: in vec2
*/
GPU_SHADER_2D_SMOOTH_COLOR,
- GPU_SHADER_2D_SMOOTH_COLOR_DITHER,
GPU_SHADER_2D_IMAGE,
GPU_SHADER_2D_IMAGE_COLOR,
GPU_SHADER_2D_IMAGE_DESATURATE_COLOR,
@@ -141,14 +148,6 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_2D_IMAGE_ALPHA,
GPU_SHADER_2D_IMAGE_RECT_COLOR,
GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_2,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_4,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_8,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_16,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST,
- GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST,
GPU_SHADER_2D_CHECKER,
GPU_SHADER_2D_DIAG_STRIPES,
/* for simple 3D drawing */
@@ -159,8 +158,7 @@ typedef enum eGPUBuiltinShader {
* \param pos: in vec3
*/
GPU_SHADER_3D_UNIFORM_COLOR,
- /* Sets Z-depth to 1.0 (draw onto background). */
- GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND,
+ GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
/**
* Take a 3D position and color for each vertex without color interpolation.
*
@@ -176,12 +174,37 @@ typedef enum eGPUBuiltinShader {
*/
GPU_SHADER_3D_SMOOTH_COLOR,
/**
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ * Used for drawing wide lines.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR,
+ GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR,
+ /**
+ * Take a 3D position and color for each vertex without color interpolation.
+ * Used for drawing wide lines.
+ *
+ * \param color: in vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POLYLINE_FLAT_COLOR,
+ /**
+ * Take a 3D position and color for each vertex with perspective correct interpolation.
+ * Used for drawing wide lines.
+ *
+ * \param color: in vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR,
+ /**
* Take a 3D position for each vertex and output only depth.
+ * Used for drawing wide lines.
*
* \param pos: in vec3
*/
GPU_SHADER_3D_DEPTH_ONLY,
- GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
/* basic image drawing */
GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE,
GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE,
@@ -196,18 +219,6 @@ typedef enum eGPUBuiltinShader {
* \param pos: in vec3
*/
GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
- /**
- * Draw linearized depth texture relate to near and far distances.
- * Take a 3D position and a 2D texture coordinate for each vertex.
- *
- * \param znear: uniform float
- * \param zfar: uniform float
- * \param image: uniform sampler2D
- * \param texCoord: in vec2
- * \param pos: in vec3
- */
- GPU_SHADER_3D_IMAGE_DEPTH,
- GPU_SHADER_3D_IMAGE_DEPTH_COPY,
/* points */
/**
* Draw round points with a hardcoded size.
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index 8b0d25e51a3..28ee162bdbd 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -33,9 +33,7 @@ extern "C" {
#endif
typedef enum {
- GPU_UNIFORM_NONE = 0, /* uninitialized/unknown */
-
- GPU_UNIFORM_MODEL, /* mat4 ModelMatrix */
+ GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */
GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */
GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */
GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */
@@ -56,48 +54,58 @@ typedef enum {
GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */
GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */
GPU_UNIFORM_RESOURCE_ID, /* int resourceId */
-
- GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */
+ GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */
GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */
} GPUUniformBuiltin;
+typedef enum {
+ GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */
+ GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */
+ GPU_UNIFORM_BLOCK_INFO, /* infoBlock */
+
+ GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */
+} GPUUniformBlockBuiltin;
+
typedef struct GPUShaderInput {
- struct GPUShaderInput *next;
uint32_t name_offset;
- uint name_hash;
- /** Only for uniform inputs. */
- GPUUniformBuiltin builtin_type;
- /** Only for attribute inputs. */
- uint32_t gl_type;
- /** Only for attribute inputs. */
- int32_t size;
+ uint32_t name_hash;
int32_t location;
+ /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */
+ int32_t binding;
} GPUShaderInput;
-#define GPU_NUM_SHADERINTERFACE_BUCKETS 257
#define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16
typedef struct GPUShaderInterface {
- int32_t program;
- uint32_t name_buffer_offset;
- GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS];
+ /** Buffer containing all inputs names separated by '\0'. */
char *name_buffer;
- struct GPUBatch **batches; /* references to batches using this interface */
+ /** Reference to GPUBatches using this interface */
+ struct GPUBatch **batches;
uint batches_len;
+ /** Input counts. */
+ uint attribute_len;
+ uint ubo_len;
+ uint uniform_len;
+ /** Enabled bindpoints that needs to be fed with data. */
+ uint16_t enabled_attr_mask;
+ uint16_t enabled_ubo_mask;
+ uint64_t enabled_tex_mask;
+ /** Opengl Location of builtin uniforms. Fast access, no lookup needed. */
+ int32_t builtins[GPU_NUM_UNIFORMS];
+ int32_t builtin_blocks[GPU_NUM_UNIFORM_BLOCKS];
+ /** Flat array. In this order: Attributes, Ubos, Uniforms. */
+ GPUShaderInput inputs[0];
} GPUShaderInterface;
GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id);
void GPU_shaderinterface_discard(GPUShaderInterface *);
const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name);
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *,
- const char *name);
-const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *,
- GPUUniformBuiltin);
+int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBuiltin builtin);
+int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBlockBuiltin builtin);
const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name);
const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *, const char *name);
diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index 9ce91d31d69..4daf3f8dba5 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -40,6 +40,12 @@ typedef enum eGPUFilterFunction {
GPU_LINEAR,
} eGPUFilterFunction;
+/* Initialize
+ * - sets the default Blender opengl state, if in doubt, check
+ * the contents of this function
+ * - this is called when starting Blender, for opengl rendering. */
+void GPU_state_init(void);
+
void GPU_blend(bool enable);
void GPU_blend_set_func(eGPUBlendFunction sfactor, eGPUBlendFunction dfactor);
void GPU_blend_set_func_separate(eGPUBlendFunction src_rgb,
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 892452a2738..a13f61177e6 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -41,6 +41,31 @@ struct PreviewImage;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
+/* GPU Samplers state
+ * - Specify the sampler state to bind a texture with.
+ * - Internally used by textures.
+ * - All states are created at startup to avoid runtime costs.
+ */
+
+typedef enum eGPUSamplerState {
+ GPU_SAMPLER_FILTER = (1 << 0),
+ GPU_SAMPLER_MIPMAP = (1 << 1),
+ GPU_SAMPLER_REPEAT_S = (1 << 2),
+ GPU_SAMPLER_REPEAT_T = (1 << 3),
+ GPU_SAMPLER_REPEAT_R = (1 << 4),
+ GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
+ GPU_SAMPLER_COMPARE = (1 << 6),
+ GPU_SAMPLER_ANISO = (1 << 7),
+ /* Don't use that. */
+ GPU_SAMPLER_MAX = (1 << 8),
+} eGPUSamplerState;
+
+#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER
+#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R)
+
+void GPU_samplers_init(void);
+void GPU_samplers_free(void);
+
/* GPU Texture
* - always returns unsigned char RGBA textures
* - if texture with non square dimensions is created, depending on the
@@ -236,14 +261,17 @@ void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number);
void GPU_texture_unbind(GPUTexture *tex);
-int GPU_texture_bound_number(GPUTexture *tex);
+void GPU_texture_unbind_all(void);
+
+void GPU_texture_copy(GPUTexture *dst, GPUTexture *src);
void GPU_texture_generate_mipmap(GPUTexture *tex);
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
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);
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp);
void GPU_texture_filters(GPUTexture *tex,
eGPUFilterFunction min_filter,
eGPUFilterFunction mag_filter);
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 7e384d0a692..61b14a4c5c0 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -39,7 +39,7 @@ extern "C" {
#define GPU_VERT_ATTR_NAMES_BUF_LEN 256
#define GPU_VERT_FORMAT_MAX_NAMES 63 /* More than enough, actual max is ~30. */
/* Computed as GPU_VERT_ATTR_NAMES_BUF_LEN / 30 (actual max format name). */
-#define GPU_MAX_SAFE_ATTRIB_NAME 12
+#define GPU_MAX_SAFE_ATTR_NAME 12
typedef enum {
GPU_COMP_I8,
@@ -94,19 +94,18 @@ typedef struct GPUVertFormat {
uint packed : 1;
/** Current offset in names[]. */
uint name_offset : 8;
- /** Store each attrib in one contiguous buffer region. */
+ /** Store each attribute in one contiguous buffer region. */
uint deinterleaved : 1;
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
} GPUVertFormat;
-struct GPUShaderInterface;
+struct GPUShader;
void GPU_vertformat_clear(GPUVertFormat *);
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src);
-void GPU_vertformat_from_interface(GPUVertFormat *format,
- const struct GPUShaderInterface *shaderface);
+void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *shader);
uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
@@ -125,7 +124,7 @@ BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format,
return format->names + attr->names[n_idx];
}
-void GPU_vertformat_safe_attrib_name(const char *attrib_name, char *r_safe_name, uint max_len);
+void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint max_len);
/* format conversion */
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 6bc3cd27130..5f77f13c135 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -42,6 +42,8 @@
#include <stdlib.h>
#include <string.h>
+static GLuint g_default_attr_vbo = 0;
+
static void batch_update_program_bindings(GPUBatch *batch, uint i_first);
void GPU_batch_vao_cache_clear(GPUBatch *batch)
@@ -373,7 +375,7 @@ void GPU_batch_program_set_no_use(GPUBatch *batch,
const GPUShaderInterface *shaderface)
{
#if TRUST_NO_ONE
- assert(glIsProgram(shaderface->program));
+ assert(glIsProgram(program));
assert(batch->program_in_use == 0);
#endif
batch->interface = shaderface;
@@ -414,6 +416,7 @@ void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *i
static void create_bindings(GPUVertBuf *verts,
const GPUShaderInterface *interface,
+ uint16_t *attr_mask,
uint v_first,
const bool use_instancing)
{
@@ -446,6 +449,8 @@ static void create_bindings(GPUVertBuf *verts,
continue;
}
+ *attr_mask &= ~(1 << input->location);
+
if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) {
#if TRUST_NO_ONE
assert(a->fetch_mode == GPU_FETCH_FLOAT);
@@ -487,17 +492,35 @@ static void create_bindings(GPUVertBuf *verts,
static void batch_update_program_bindings(GPUBatch *batch, uint i_first)
{
- /* Reverse order so first vbos have more prevalence (in term of attrib override). */
+ uint16_t attr_mask = batch->interface->enabled_attr_mask;
+
+ /* Reverse order so first VBO'S have more prevalence (in term of attribute override). */
for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) {
if (batch->verts[v] != NULL) {
- create_bindings(batch->verts[v], batch->interface, 0, false);
+ create_bindings(batch->verts[v], batch->interface, &attr_mask, 0, false);
}
}
+
for (int v = GPU_BATCH_INST_VBO_MAX_LEN - 1; v > -1; v--) {
if (batch->inst[v]) {
- create_bindings(batch->inst[v], batch->interface, i_first, true);
+ create_bindings(batch->inst[v], batch->interface, &attr_mask, i_first, true);
+ }
+ }
+
+ if (attr_mask != 0 && GLEW_ARB_vertex_attrib_binding) {
+ for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) {
+ if (attr_mask & mask) {
+ /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style.
+ * Fix issues for some drivers (see T75069). */
+ glBindVertexBuffer(a, g_default_attr_vbo, (intptr_t)0, (intptr_t)0);
+
+ glEnableVertexAttribArray(a);
+ glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0);
+ glVertexAttribBinding(a, a);
+ }
}
}
+
if (batch->elem) {
GPU_indexbuf_use(batch->elem);
}
@@ -528,11 +551,11 @@ void GPU_batch_program_use_end(GPUBatch *batch)
#if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); \
assert(uniform);
#else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name);
#endif
void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value)
@@ -652,6 +675,7 @@ void GPU_batch_draw(GPUBatch *batch)
#endif
GPU_batch_program_use_begin(batch);
GPU_matrix_bind(batch->interface); // external call.
+ GPU_shader_set_srgb_uniform(batch->interface);
GPU_batch_bind(batch);
GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
@@ -689,8 +713,8 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi
}
/* Verify there is enough data do draw. */
- /* TODO(fclem) Nice to have but this is invalid when using procedural drawcalls.
- * The right assert would be to check if there is an enabled attrib from each VBO
+ /* TODO(fclem) Nice to have but this is invalid when using procedural draw-calls.
+ * The right assert would be to check if there is an enabled attribute from each VBO
* and check their length. */
// BLI_assert(i_first + i_count <= (batch->inst ? batch->inst->vertex_len : INT_MAX));
// BLI_assert(v_first + v_count <=
@@ -1002,11 +1026,23 @@ void GPU_batch_program_set_imm_shader(GPUBatch *batch)
void gpu_batch_init(void)
{
+ if (g_default_attr_vbo == 0) {
+ g_default_attr_vbo = GPU_buf_alloc();
+
+ float default_attrib_data[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ glBindBuffer(GL_ARRAY_BUFFER, g_default_attr_vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4, default_attrib_data, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
gpu_batch_presets_init();
}
void gpu_batch_exit(void)
{
+ GPU_buf_free(g_default_attr_vbo);
+ g_default_attr_vbo = 0;
+
gpu_batch_presets_exit();
}
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index e00b6f78c2e..d16edab5ac9 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -27,13 +27,20 @@
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
+#include "DNA_userdef_types.h"
+
#include "UI_interface.h"
+#include "UI_resources.h"
#include "GPU_batch.h"
#include "GPU_batch_presets.h" /* own include */
#include "GPU_batch_utils.h"
#include "gpu_shader_private.h"
+/* -------------------------------------------------------------------- */
+/** \name Local Structures
+ * \{ */
+
/* Struct to store 3D Batches and their format */
static struct {
struct {
@@ -53,8 +60,27 @@ static struct {
ThreadMutex mutex;
} g_presets_3d = {{0}};
+static struct {
+ struct {
+ GPUBatch *panel_drag_widget;
+ } batch;
+
+ float panel_drag_widget_pixelsize;
+ float panel_drag_widget_width;
+ float panel_drag_widget_col_high[4];
+ float panel_drag_widget_col_dark[4];
+
+ GPUVertFormat format;
+
+ struct {
+ uint pos, col;
+ } attr_id;
+} g_presets_2d = {{0}};
+
static ListBase presets_list = {NULL, NULL};
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name 3D Primitives
* \{ */
@@ -71,6 +97,18 @@ static GPUVertFormat *preset_3d_format(void)
return &g_presets_3d.format;
}
+static GPUVertFormat *preset_2d_format(void)
+{
+ if (g_presets_2d.format.attr_len == 0) {
+ GPUVertFormat *format = &g_presets_2d.format;
+ g_presets_2d.attr_id.pos = GPU_vertformat_attr_add(
+ format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_presets_2d.attr_id.col = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+ return &g_presets_2d.format;
+}
+
static void batch_sphere_lat_lon_vert(GPUVertBufRaw *pos_step,
GPUVertBufRaw *nor_step,
float lat,
@@ -193,6 +231,114 @@ static GPUBatch *batch_sphere_wire(int lat_res, int lon_res)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Panel Drag Widget
+ * \{ */
+
+static void gpu_batch_preset_rectf_tris_color_ex(GPUVertBufRaw *pos_step,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ GPUVertBufRaw *col_step,
+ const float color[4])
+{
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y1});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y1});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y2});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y1});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x2, y2});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+
+ copy_v2_v2(GPU_vertbuf_raw_step(pos_step), (const float[2]){x1, y2});
+ copy_v4_v4(GPU_vertbuf_raw_step(col_step), color);
+}
+
+static GPUBatch *gpu_batch_preset_panel_drag_widget(float pixelsize,
+ const float col_high[4],
+ const float col_dark[4],
+ const float width)
+{
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_2d_format());
+ const uint vbo_len = 4 * 2 * (6 * 2);
+ GPU_vertbuf_data_alloc(vbo, vbo_len);
+
+ GPUVertBufRaw pos_step, col_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_2d.attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_presets_2d.attr_id.col, &col_step);
+
+ const int px = (int)pixelsize;
+ const int px_zoom = max_ii(round_fl_to_int(width / 22.0f), 1);
+
+ const int box_margin = max_ii(round_fl_to_int((float)(px_zoom * 2.0f)), px);
+ const int box_size = max_ii(round_fl_to_int((width / 8.0f) - px), px);
+
+ const int y_ofs = max_ii(round_fl_to_int(width / 2.5f), px);
+ const int x_ofs = y_ofs;
+ int i_x, i_y;
+
+ for (i_x = 0; i_x < 4; i_x++) {
+ for (i_y = 0; i_y < 2; i_y++) {
+ const int x_co = (x_ofs) + (i_x * (box_size + box_margin));
+ const int y_co = (y_ofs) + (i_y * (box_size + box_margin));
+
+ gpu_batch_preset_rectf_tris_color_ex(&pos_step,
+ x_co - box_size,
+ y_co - px_zoom,
+ x_co,
+ (y_co + box_size) - px_zoom,
+ &col_step,
+ col_dark);
+ gpu_batch_preset_rectf_tris_color_ex(
+ &pos_step, x_co - box_size, y_co, x_co, y_co + box_size, &col_step, col_high);
+ }
+ }
+ return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+GPUBatch *GPU_batch_preset_panel_drag_widget(const float pixelsize,
+ const float col_high[4],
+ const float col_dark[4],
+ const float width)
+{
+ const bool parameters_changed = (g_presets_2d.panel_drag_widget_pixelsize != pixelsize) ||
+ (g_presets_2d.panel_drag_widget_width != width) ||
+ !equals_v4v4(g_presets_2d.panel_drag_widget_col_high,
+ col_high) ||
+ !equals_v4v4(g_presets_2d.panel_drag_widget_col_dark, col_dark);
+
+ if (g_presets_2d.batch.panel_drag_widget && parameters_changed) {
+ gpu_batch_presets_unregister(g_presets_2d.batch.panel_drag_widget);
+ GPU_batch_discard(g_presets_2d.batch.panel_drag_widget);
+ g_presets_2d.batch.panel_drag_widget = NULL;
+ }
+
+ if (!g_presets_2d.batch.panel_drag_widget) {
+ g_presets_2d.batch.panel_drag_widget = gpu_batch_preset_panel_drag_widget(
+ pixelsize, col_high, col_dark, width);
+ gpu_batch_presets_register(g_presets_2d.batch.panel_drag_widget);
+ g_presets_2d.panel_drag_widget_pixelsize = pixelsize;
+ g_presets_2d.panel_drag_widget_width = width;
+ copy_v4_v4(g_presets_2d.panel_drag_widget_col_high, col_high);
+ copy_v4_v4(g_presets_2d.panel_drag_widget_col_dark, col_dark);
+ }
+ return g_presets_2d.batch.panel_drag_widget;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Preset Registration Management
+ * \{ */
+
void gpu_batch_presets_init(void)
{
BLI_mutex_init(&g_presets_3d.mutex);
@@ -241,7 +387,7 @@ void gpu_batch_presets_reset(void)
BLI_mutex_lock(&g_presets_3d.mutex);
/* Reset vao caches for these every time we switch opengl context.
* This way they will draw correctly for each window. */
- for (LinkData *link = presets_list.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &presets_list) {
GPUBatch *preset = link->data;
GPU_batch_vao_cache_clear(preset);
}
@@ -259,3 +405,5 @@ void gpu_batch_presets_exit(void)
BLI_mutex_end(&g_presets_3d.mutex);
}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h
index 42cfc1e2a5c..58d1810ac7a 100644
--- a/source/blender/gpu/intern/gpu_batch_private.h
+++ b/source/blender/gpu/intern/gpu_batch_private.h
@@ -27,14 +27,14 @@
#ifndef __GPU_BATCH_PRIVATE_H__
#define __GPU_BATCH_PRIVATE_H__
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "GPU_batch.h"
#include "GPU_context.h"
#include "GPU_shader_interface.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface);
#ifdef __cplusplus
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 168a3c83a91..cef90d57ef5 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -43,6 +43,7 @@
#include "BKE_mesh.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
+#include "BKE_subdiv_ccg.h"
#include "GPU_batch.h"
#include "GPU_buffers.h"
@@ -150,7 +151,10 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
/* Initialize vertex buffer (match 'VertexBufferFormat'). */
buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&g_vbo_id.format, GPU_USAGE_STATIC);
}
- GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
+ if (buffers->vert_buf->data == NULL || buffers->vert_buf->vertex_len != vert_len) {
+ /* Allocate buffer if not allocated yet or size changed. */
+ GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len);
+ }
#endif
return buffers->vert_buf->data != NULL;
@@ -218,14 +222,11 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MVert *mvert,
- const int *vert_indices,
- int totvert,
const float *vmask,
const MLoopCol *vcol,
const int *sculpt_face_sets,
const int face_sets_color_seed,
const int face_sets_color_default,
- const int (*face_vert_indices)[3],
const int update_flags)
{
const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
@@ -236,7 +237,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
bool default_face_set = true;
{
- int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
+ const int totelem = buffers->tot_tri * 3;
/* Build VBO */
if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
@@ -254,127 +255,77 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.col, &col_step);
}
- /* 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 int vidx = vert_indices[i];
- const MVert *v = &mvert[vidx];
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
- copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), v->no);
+ /* calculate normal for each polygon only once */
+ uint mpoly_prev = UINT_MAX;
+ short no[3] = {0, 0, 0};
- uchar mask;
- if (show_mask) {
- mask = (uchar)(vmask[vidx] * 255);
- }
- else {
- mask = 0.0f;
- }
- *(uchar *)GPU_vertbuf_raw_step(&msk_step) = mask;
- empty_mask = empty_mask && (mask == 0);
+ for (uint i = 0; i < buffers->face_indices_len; i++) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+ const uint vtri[3] = {
+ buffers->mloop[lt->tri[0]].v,
+ buffers->mloop[lt->tri[1]].v,
+ buffers->mloop[lt->tri[2]].v,
+ };
+
+ if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
+ continue;
}
- /* Face Sets. */
- for (uint i = 0; i < buffers->face_indices_len; i++) {
- uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- if (show_face_sets) {
- const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
- const int fset = abs(sculpt_face_sets[lt->poly]);
-
- /* Skip for the default color Face Set to render it white. */
- if (fset != face_sets_color_default) {
- face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
- default_face_set = false;
- }
- }
- for (int j = 0; j < 3; j++) {
- const int vidx = face_vert_indices[i][j];
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vidx, &face_set_color);
- }
+ /* Face normal and mask */
+ if (lt->poly != mpoly_prev && !buffers->smooth) {
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ float fno[3];
+ BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
+ normal_float_to_short_v3(no, fno);
+ mpoly_prev = lt->poly;
}
- if (show_vcol) {
- for (uint i = 0; i < buffers->face_indices_len; i++) {
- const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
- for (int j = 0; j < 3; j++) {
- const int loop_index = lt->tri[j];
- const int vidx = face_vert_indices[i][j];
- const MLoopCol *mcol = &vcol[loop_index];
- ushort scol[4];
- scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
- scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
- scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
- scol[3] = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, scol);
- }
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+ if (show_face_sets) {
+ const int fset = abs(sculpt_face_sets[lt->poly]);
+ /* Skip for the default color Face Set to render it white. */
+ if (fset != face_sets_color_default) {
+ face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
+ default_face_set = false;
}
}
- }
- else {
- /* calculate normal for each polygon only once */
- uint mpoly_prev = UINT_MAX;
- short no[3] = {0, 0, 0};
-
- for (uint i = 0; i < buffers->face_indices_len; i++) {
- const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
- const uint vtri[3] = {
- buffers->mloop[lt->tri[0]].v,
- buffers->mloop[lt->tri[1]].v,
- buffers->mloop[lt->tri[2]].v,
- };
-
- if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
- continue;
- }
- /* Face normal and mask */
- if (lt->poly != mpoly_prev) {
- const MPoly *mp = &buffers->mpoly[lt->poly];
- float fno[3];
- BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
- normal_float_to_short_v3(no, fno);
- mpoly_prev = lt->poly;
- }
+ float fmask = 0.0f;
+ uchar cmask = 0;
+ if (show_mask && !buffers->smooth) {
+ fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
+ cmask = (uchar)(fmask * 255);
+ }
- uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- if (show_face_sets) {
- const int fset = abs(sculpt_face_sets[lt->poly]);
- /* Skip for the default color Face Set to render it white. */
- if (fset != face_sets_color_default) {
- face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
- default_face_set = false;
- }
- }
+ for (uint j = 0; j < 3; j++) {
+ const MVert *v = &mvert[vtri[j]];
+ copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
- float fmask = 0.0f;
- uchar cmask = 0;
- if (show_mask) {
- fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
- cmask = (uchar)(fmask * 255);
+ if (buffers->smooth) {
+ copy_v3_v3_short(no, v->no);
}
+ copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
- for (uint j = 0; j < 3; j++) {
- const MVert *v = &mvert[vtri[j]];
-
- copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
- copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
- *(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask;
- empty_mask = empty_mask && (cmask == 0);
- /* Face Sets. */
- memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar) * 3);
+ if (show_mask && buffers->smooth) {
+ cmask = (uchar)(vmask[vtri[j]] * 255);
+ }
- if (show_vcol) {
- const uint loop_index = lt->tri[j];
- const MLoopCol *mcol = &vcol[loop_index];
- ushort scol[4];
- scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
- scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
- scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
- scol[3] = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
- memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
- }
+ *(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask;
+ empty_mask = empty_mask && (cmask == 0);
+
+ if (show_vcol) {
+ const uint loop_index = lt->tri[j];
+ const MLoopCol *mcol = &vcol[loop_index];
+ ushort scol[4];
+ scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
+ scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
+ scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
+ scol[3] = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
+ memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
}
+
+ /* Face Sets. */
+ memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar) * 3);
}
}
@@ -392,8 +343,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
}
/* Threaded - do not call any functions that use OpenGL calls! */
-GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
- const MPoly *mpoly,
+GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const MPoly *mpoly,
const MLoop *mloop,
const MLoopTri *looptri,
const MVert *mvert,
@@ -440,70 +390,34 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
return buffers;
}
- /* An element index buffer is used for smooth shading, but flat
- * shading requires separate vertex normals so an index buffer
- * can't be used there. */
- if (buffers->smooth) {
- /* Fill the triangle and line buffers. */
- GPUIndexBufBuilder elb, elb_lines;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, INT_MAX);
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX);
-
- for (i = 0; i < face_indices_len; i++) {
- const MLoopTri *lt = &looptri[face_indices[i]];
-
- /* Skip hidden faces */
- if (!gpu_pbvh_is_looptri_visible(lt, mvert, mloop, sculpt_face_sets)) {
- continue;
- }
+ /* Fill the only the line buffer. */
+ GPUIndexBufBuilder elb_lines;
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX);
+ int vert_idx = 0;
- GPU_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
- int r_edges[3];
- BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
+ for (i = 0; i < face_indices_len; i++) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
- if (r_edges[0] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][0], face_vert_indices[i][1]);
- }
- if (r_edges[1] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][1], face_vert_indices[i][2]);
- }
- if (r_edges[2] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][2], face_vert_indices[i][0]);
- }
+ /* Skip hidden faces */
+ if (!gpu_pbvh_is_looptri_visible(lt, mvert, mloop, sculpt_face_sets)) {
+ continue;
}
- buffers->index_buf = GPU_indexbuf_build(&elb);
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
- }
- else {
- /* Fill the only the line buffer. */
- GPUIndexBufBuilder elb_lines;
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX);
- int vert_idx = 0;
- for (i = 0; i < face_indices_len; i++) {
- const MLoopTri *lt = &looptri[face_indices[i]];
-
- /* Skip hidden faces */
- if (!gpu_pbvh_is_looptri_visible(lt, mvert, mloop, sculpt_face_sets)) {
- continue;
- }
-
- int r_edges[3];
- BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
- if (r_edges[0] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1);
- }
- if (r_edges[1] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2);
- }
- if (r_edges[2] != -1) {
- GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0);
- }
-
- vert_idx++;
+ int r_edges[3];
+ BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
+ if (r_edges[0] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1);
}
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
+ if (r_edges[1] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2);
+ }
+ if (r_edges[2] != -1) {
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0);
+ }
+
+ vert_idx++;
}
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
buffers->tot_tri = tottri;
@@ -523,8 +437,13 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
/** \name Grid PBVH
* \{ */
-static void gpu_pbvh_grid_fill_index_buffers(
- GPU_PBVH_Buffers *buffers, int *grid_indices, uint visible_quad_len, int totgrid, int gridsize)
+static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers,
+ SubdivCCG *UNUSED(subdiv_ccg),
+ const int *UNUSED(face_sets),
+ int *grid_indices,
+ uint visible_quad_len,
+ int totgrid,
+ int gridsize)
{
GPUIndexBufBuilder elb, elb_lines;
GPUIndexBufBuilder elb_fast, elb_lines_fast;
@@ -594,7 +513,6 @@ static void gpu_pbvh_grid_fill_index_buffers(
const uint grid_vert_len = square_uint(gridsize - 1) * 4;
for (int i = 0; i < totgrid; i++, offset += grid_vert_len) {
bool grid_visible = false;
-
BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]];
uint v0, v1, v2, v3;
@@ -673,16 +591,24 @@ void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers,
/* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
+ SubdivCCG *subdiv_ccg,
CCGElem **grids,
- const DMFlagMat *grid_flag_mats,
+ const struct DMFlagMat *grid_flag_mats,
int *grid_indices,
int totgrid,
- const CCGKey *key,
+ const int *sculpt_face_sets,
+ const int face_sets_color_seed,
+ const int face_sets_color_default,
+ const struct CCGKey *key,
const int update_flags)
{
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
+ const bool show_face_sets = sculpt_face_sets &&
+ (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
bool empty_mask = true;
+ bool default_face_set = true;
+
int i, j, k, x, y;
/* Build VBO */
@@ -702,8 +628,13 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
return;
}
- gpu_pbvh_grid_fill_index_buffers(
- buffers, grid_indices, visible_quad_len, totgrid, key->grid_size);
+ gpu_pbvh_grid_fill_index_buffers(buffers,
+ subdiv_ccg,
+ sculpt_face_sets,
+ grid_indices,
+ visible_quad_len,
+ totgrid,
+ key->grid_size);
}
uint vbo_index_offset = 0;
@@ -716,9 +647,23 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
}
for (i = 0; i < totgrid; i++) {
- CCGElem *grid = grids[grid_indices[i]];
+ const int grid_index = grid_indices[i];
+ CCGElem *grid = grids[grid_index];
int vbo_index = vbo_index_offset;
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+
+ if (show_face_sets && subdiv_ccg && sculpt_face_sets) {
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid_index);
+
+ const int fset = abs(sculpt_face_sets[face_index]);
+ /* Skip for the default color Face Set to render it white. */
+ if (fset != face_sets_color_default) {
+ face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
+ default_face_set = false;
+ }
+ }
+
if (buffers->smooth) {
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
@@ -742,8 +687,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, &vcol);
}
- uchar fsets[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index, &fsets);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index, &face_set_color);
vbo_index += 1;
}
@@ -799,11 +743,10 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 2, &vcol);
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 3, &vcol);
- uchar fsets[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 0, &fsets);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 1, &fsets);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 2, &fsets);
- GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 3, &fsets);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 0, &face_set_color);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 1, &face_set_color);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 2, &face_set_color);
+ GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, vbo_index + 3, &face_set_color);
vbo_index += 4;
}
@@ -823,7 +766,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
buffers->totgrid = totgrid;
buffers->grid_flag_mats = grid_flag_mats;
buffers->gridkey = *key;
- buffers->show_overlay = !empty_mask;
+ buffers->show_overlay = !empty_mask || !default_face_set;
}
/* Threaded - do not call any functions that use OpenGL calls! */
@@ -1143,13 +1086,24 @@ short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers)
return buffers->material_index;
}
+static void gpu_pbvh_buffers_clear(GPU_PBVH_Buffers *buffers)
+{
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_BATCH_DISCARD_SAFE(buffers->lines_fast);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+}
+
void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers)
{
/* Free empty bmesh node buffers. */
if (buffers->clear_bmesh_on_flush) {
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
- GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ gpu_pbvh_buffers_clear(buffers);
buffers->clear_bmesh_on_flush = false;
}
@@ -1162,16 +1116,7 @@ void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers)
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
- GPU_BATCH_DISCARD_SAFE(buffers->lines);
- GPU_BATCH_DISCARD_SAFE(buffers->lines_fast);
- GPU_BATCH_DISCARD_SAFE(buffers->triangles);
- GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
- GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
- GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
-
+ gpu_pbvh_buffers_clear(buffers);
MEM_freeN(buffers);
}
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 211ae0b3897..c1e7933d7ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -75,7 +75,7 @@ static uint32_t gpu_pass_hash(const char *frag_gen, const char *defs, ListBase *
BLI_HashMurmur2A hm2a;
BLI_hash_mm2a_init(&hm2a, 0);
BLI_hash_mm2a_add(&hm2a, (uchar *)frag_gen, strlen(frag_gen));
- for (GPUMaterialAttribute *attr = attributes->first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attributes) {
BLI_hash_mm2a_add(&hm2a, (uchar *)attr->name, strlen(attr->name));
}
if (defs) {
@@ -314,12 +314,12 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
ListBase ubo_inputs = {NULL, NULL};
/* Attributes */
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
BLI_dynstr_appendf(ds, "in %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
/* Textures */
- for (GPUMaterialTexture *tex = graph->textures.first; tex; tex = tex->next) {
+ LISTBASE_FOREACH (GPUMaterialTexture *, tex, &graph->textures) {
if (tex->colorband) {
BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->sampler_name);
}
@@ -333,7 +333,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
}
/* Volume Grids */
- for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, grid, &graph->volume_grids) {
BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", grid->sampler_name);
BLI_dynstr_appendf(ds, "uniform mat4 %s = mat4(0.0);\n", grid->transform_name);
}
@@ -381,7 +381,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
/* Inputs are sorted */
BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME);
- for (LinkData *link = ubo_inputs.first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, &ubo_inputs) {
input = link->data;
BLI_dynstr_appendf(ds, "\t%s unf%d;\n", gpu_data_type_to_string(input->type), input->id);
}
@@ -673,7 +673,7 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
"#define DEFINE_ATTR(type, attr) in type attr\n"
"#endif\n");
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
/* XXX FIXME : see notes in mesh_render_data_create() */
/* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
if (attr->type == CD_ORCO) {
@@ -689,8 +689,8 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, attr_prefix_get(attr->type));
}
else {
- char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
- GPU_vertformat_safe_attrib_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
+ char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ GPU_vertformat_safe_attr_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s%s);\n",
gpu_data_type_to_string(attr->gputype),
@@ -787,7 +787,7 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n");
}
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
if (attr->type == CD_TANGENT) {
/* Not supported by hairs */
BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", attr->id, use_geom ? "g" : "");
@@ -820,7 +820,7 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n");
}
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
if (attr->type == CD_TANGENT) { /* silly exception */
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
@@ -903,7 +903,7 @@ static char *code_generate_geometry(GPUNodeGraph *graph,
}
}
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
BLI_dynstr_appendf(ds, "in %s var%dg[];\n", gpu_data_type_to_string(attr->gputype), attr->id);
BLI_dynstr_appendf(ds, "out %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
@@ -1010,7 +1010,7 @@ static char *code_generate_geometry(GPUNodeGraph *graph,
BLI_dynstr_append(ds, "#endif\n");
}
- for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
/* TODO let shader choose what to do depending on what the attribute is. */
BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", attr->id, attr->id);
}
@@ -1160,7 +1160,7 @@ static int count_active_texture_sampler(GPUShader *shader, char *source)
if (*code != '\0') {
char sampler_name[64];
code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name));
- int id = GPU_shader_get_uniform_ensure(shader, sampler_name);
+ int id = GPU_shader_get_uniform(shader, sampler_name);
if (id == -1) {
continue;
diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h
index c9379e5433f..f64cdf439a1 100644
--- a/source/blender/gpu/intern/gpu_context_private.h
+++ b/source/blender/gpu/intern/gpu_context_private.h
@@ -26,12 +26,12 @@
#ifndef __GPU_CONTEXT_PRIVATE_H__
#define __GPU_CONTEXT_PRIVATE_H__
+#include "GPU_context.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-#include "GPU_context.h"
-
struct GPUFrameBuffer;
GLuint GPU_vao_default(void);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 350c616e359..1c346217e9f 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -158,10 +158,10 @@ static GLenum gpu_get_mipmap_filter(bool mag)
}
/* Anisotropic filtering settings */
-void GPU_set_anisotropic(Main *bmain, float value)
+void GPU_set_anisotropic(float value)
{
if (GTS.anisotropic != value) {
- GPU_free_images(bmain);
+ GPU_samplers_free();
/* Clamp value to the maximum value the graphics card supports */
const float max = GPU_max_texture_anisotropy();
@@ -170,6 +170,8 @@ void GPU_set_anisotropic(Main *bmain, float value)
}
GTS.anisotropic = value;
+
+ GPU_samplers_init();
}
}
@@ -449,22 +451,12 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap()) {
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
-
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
@@ -905,7 +897,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
bindcode = gpu_texture_create_tile_array(ima, ibuf_intern);
}
else if (textarget == GL_TEXTURE_1D_ARRAY) {
- bindcode = gpu_texture_create_tile_mapping(ima, iuser->multiview_eye);
+ bindcode = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0);
}
else {
bindcode = gpu_texture_create_from_ibuf(ima, ibuf_intern, textarget);
@@ -1098,18 +1090,12 @@ void GPU_create_gl_tex(uint *bind,
GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
int w = rectw / 3, h = recth / 2;
@@ -1132,22 +1118,13 @@ void GPU_create_gl_tex(uint *bind,
}
}
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
gpu_del_cube_map(cube_map);
}
@@ -1156,10 +1133,6 @@ void GPU_create_gl_tex(uint *bind,
}
}
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
glBindTexture(textarget, 0);
if (ibuf) {
@@ -1211,10 +1184,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); i++) {
if (width == 0) {
@@ -1481,66 +1450,3 @@ void GPU_free_images_old(Main *bmain)
ima = ima->id.next;
}
}
-
-static void gpu_disable_multisample(void)
-{
-#ifdef __linux__
- /* changing multisample from the default (enabled) causes problems on some
- * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */
- bool toggle_ok = true;
-
- if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
- int samples = 0;
- glGetIntegerv(GL_SAMPLES, &samples);
-
- if (samples == 0) {
- toggle_ok = false;
- }
- }
-
- if (toggle_ok) {
- glDisable(GL_MULTISAMPLE);
- }
-#else
- glDisable(GL_MULTISAMPLE);
-#endif
-}
-
-/* Default OpenGL State
- *
- * This is called on startup, for opengl offscreen render.
- * Generally we should always return to this state when
- * temporarily modifying the state for drawing, though that are (undocumented)
- * exceptions that we should try to get rid of. */
-
-void GPU_state_init(void)
-{
- GPU_program_point_size(false);
-
- glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
-
- glDepthFunc(GL_LEQUAL);
-
- glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_COLOR_LOGIC_OP);
- glDisable(GL_STENCIL_TEST);
-
- glDepthRange(0.0, 1.0);
-
- glFrontFace(GL_CCW);
- glCullFace(GL_BACK);
- glDisable(GL_CULL_FACE);
-
- gpu_disable_multisample();
-
- /* This is a bit dangerous since addons could change this. */
- glEnable(GL_PRIMITIVE_RESTART);
- glPrimitiveRestartIndex((GLuint)0xFFFFFFFF);
-
- /* TODO: Should become default. But needs at least GL 4.3 */
- if (GLEW_ARB_ES3_compatibility) {
- /* Takes predecence over GL_PRIMITIVE_RESTART */
- glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
- }
-}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e3632b82778..8dd468b5414 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -304,6 +304,14 @@ void gpu_extensions_init(void)
GG.context_local_shaders_workaround = GLEW_ARB_get_program_binary;
}
+ /* Special fix for theses specific GPUs.
+ * Without this workaround, blender crashes on startup. (see T72098) */
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) &&
+ (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) {
+ GG.mip_render_workaround = true;
+ GG.context_local_shaders_workaround = GLEW_ARB_get_program_binary;
+ }
+
/* df/dy calculation factors, those are dependent on driver */
GG.dfdyfactors[0] = 1.0;
GG.dfdyfactors[1] = 1.0;
@@ -347,11 +355,13 @@ void gpu_extensions_init(void)
}
GPU_invalid_tex_init();
+ GPU_samplers_init();
}
void gpu_extensions_exit(void)
{
GPU_invalid_tex_free();
+ GPU_samplers_free();
}
bool GPU_mem_stats_supported(void)
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 59d0be2cefb..5af9364b92c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -514,6 +514,11 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
if (GPU_framebuffer_active_get() != fb) {
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
glEnable(GL_FRAMEBUFFER_SRGB);
+
+ GPUTexture *first_target = fb->attachments[GPU_FB_COLOR_ATTACHMENT0].tex;
+ const bool is_srgb_target = (first_target &&
+ (GPU_texture_format(first_target) == GPU_SRGB8_A8));
+ GPU_shader_set_framebuffer_srgb_target(is_srgb_target);
}
gpu_framebuffer_current_set(fb);
@@ -536,10 +541,6 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
}
#endif
- if (fb->multisample) {
- glEnable(GL_MULTISAMPLE);
- }
-
glViewport(0, 0, fb->width, fb->height);
}
@@ -549,6 +550,7 @@ void GPU_framebuffer_restore(void)
glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default());
gpu_framebuffer_current_set(NULL);
glDisable(GL_FRAMEBUFFER_SRGB);
+ GPU_shader_set_framebuffer_srgb_target(false);
}
}
@@ -944,6 +946,7 @@ void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
GPU_framebuffer_bind(ofs_fb);
glDisable(GL_FRAMEBUFFER_SRGB);
+ GPU_shader_set_framebuffer_srgb_target(false);
}
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index 4523df8be7c..9ea273f33cf 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -43,6 +43,13 @@
extern void GPU_matrix_bind(const GPUShaderInterface *);
extern bool GPU_matrix_dirty_get(void);
+typedef struct ImmediateDrawBuffer {
+ GLuint vbo_id;
+ GLubyte *buffer_data;
+ uint buffer_offset;
+ uint buffer_size;
+} ImmediateDrawBuffer;
+
typedef struct {
/* TODO: organize this struct by frequency of change (run-time) */
@@ -50,14 +57,14 @@ typedef struct {
GPUContext *context;
/* current draw call */
- GLubyte *buffer_data;
- uint buffer_offset;
- uint buffer_bytes_mapped;
- uint vertex_len;
bool strict_vertex_len;
+ uint vertex_len;
+ uint buffer_bytes_mapped;
+ ImmediateDrawBuffer *active_buffer;
GPUPrimType prim_type;
-
GPUVertFormat vertex_format;
+ ImmediateDrawBuffer draw_buffer;
+ ImmediateDrawBuffer draw_buffer_strict;
/* current vertex */
uint vertex_idx;
@@ -65,7 +72,6 @@ typedef struct {
uint16_t
unassigned_attr_bits; /* which attributes of current vertex have not been given values? */
- GLuint vbo_id;
GLuint vao_id;
GLuint bound_program;
@@ -76,7 +82,6 @@ typedef struct {
/* size of internal buffer */
#define DEFAULT_INTERNAL_BUFFER_SIZE (4 * 1024 * 1024)
-static uint imm_buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
static bool initialized = false;
static Immediate imm;
@@ -88,9 +93,14 @@ void immInit(void)
#endif
memset(&imm, 0, sizeof(Immediate));
- imm.vbo_id = GPU_buf_alloc();
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
- glBufferData(GL_ARRAY_BUFFER, imm_buffer_size, NULL, GL_DYNAMIC_DRAW);
+ imm.draw_buffer.vbo_id = GPU_buf_alloc();
+ imm.draw_buffer.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
+ glBindBuffer(GL_ARRAY_BUFFER, imm.draw_buffer.vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, imm.draw_buffer.buffer_size, NULL, GL_DYNAMIC_DRAW);
+ imm.draw_buffer_strict.vbo_id = GPU_buf_alloc();
+ imm.draw_buffer_strict.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
+ glBindBuffer(GL_ARRAY_BUFFER, imm.draw_buffer_strict.vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, imm.draw_buffer_strict.buffer_size, NULL, GL_DYNAMIC_DRAW);
imm.prim_type = GPU_PRIM_NONE;
imm.strict_vertex_len = true;
@@ -124,7 +134,8 @@ void immDeactivate(void)
void immDestroy(void)
{
- GPU_buf_free(imm.vbo_id);
+ GPU_buf_free(imm.draw_buffer.vbo_id);
+ GPU_buf_free(imm.draw_buffer_strict.vbo_id);
initialized = false;
}
@@ -151,6 +162,7 @@ void immBindProgram(GLuint program, const GPUShaderInterface *shaderface)
glUseProgram(program);
get_attr_locations(&imm.vertex_format, &imm.attr_binding, shaderface);
GPU_matrix_bind(shaderface);
+ GPU_shader_set_srgb_uniform(shaderface);
}
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
@@ -212,6 +224,7 @@ void immBegin(GPUPrimType prim_type, uint vertex_len)
assert(initialized);
assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */
assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
+ assert(imm.active_buffer == NULL);
#endif
imm.prim_type = prim_type;
imm.vertex_len = vertex_len;
@@ -220,54 +233,66 @@ void immBegin(GPUPrimType prim_type, uint vertex_len)
/* how many bytes do we need for this draw call? */
const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len);
+ ImmediateDrawBuffer *active_buffer = imm.strict_vertex_len ? &imm.draw_buffer_strict :
+ &imm.draw_buffer;
+ imm.active_buffer = active_buffer;
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
+ glBindBuffer(GL_ARRAY_BUFFER, active_buffer->vbo_id);
/* does the current buffer have enough room? */
- const uint available_bytes = imm_buffer_size - imm.buffer_offset;
+ const uint available_bytes = active_buffer->buffer_size - active_buffer->buffer_offset;
bool recreate_buffer = false;
- if (bytes_needed > imm_buffer_size) {
+ if (bytes_needed > active_buffer->buffer_size) {
/* expand the internal buffer */
- imm_buffer_size = bytes_needed;
+ active_buffer->buffer_size = bytes_needed;
recreate_buffer = true;
}
else if (bytes_needed < DEFAULT_INTERNAL_BUFFER_SIZE &&
- imm_buffer_size > DEFAULT_INTERNAL_BUFFER_SIZE) {
+ active_buffer->buffer_size > DEFAULT_INTERNAL_BUFFER_SIZE) {
/* shrink the internal buffer */
- imm_buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
+ active_buffer->buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
recreate_buffer = true;
}
/* ensure vertex data is aligned */
/* Might waste a little space, but it's safe. */
- const uint pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride);
+ const uint pre_padding = padding(active_buffer->buffer_offset, imm.vertex_format.stride);
if (!recreate_buffer && ((bytes_needed + pre_padding) <= available_bytes)) {
- imm.buffer_offset += pre_padding;
+ active_buffer->buffer_offset += pre_padding;
}
else {
/* orphan this buffer & start with a fresh one */
/* this method works on all platforms, old & new */
- glBufferData(GL_ARRAY_BUFFER, imm_buffer_size, NULL, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, active_buffer->buffer_size, NULL, GL_DYNAMIC_DRAW);
- imm.buffer_offset = 0;
+ active_buffer->buffer_offset = 0;
}
/* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */
- imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER,
- imm.buffer_offset,
- bytes_needed,
- GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT |
- (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
+#if TRUST_NO_ONE
+ {
+ GLint bufsize;
+ glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufsize);
+ assert(active_buffer->buffer_offset + bytes_needed <= bufsize);
+ }
+#endif
+
+ active_buffer->buffer_data = glMapBufferRange(
+ GL_ARRAY_BUFFER,
+ active_buffer->buffer_offset,
+ bytes_needed,
+ GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT |
+ (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
#if TRUST_NO_ONE
- assert(imm.buffer_data != NULL);
+ assert(active_buffer->buffer_data != NULL);
#endif
imm.buffer_bytes_mapped = bytes_needed;
- imm.vertex_data = imm.buffer_data;
+ imm.vertex_data = active_buffer->buffer_data;
}
void immBeginAtMost(GPUPrimType prim_type, uint vertex_len)
@@ -337,7 +362,7 @@ static void immDrawSetup(void)
for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; a_idx++) {
const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx];
- const uint offset = imm.buffer_offset + a->offset;
+ const uint offset = imm.active_buffer->buffer_offset + a->offset;
const GLvoid *pointer = (const GLubyte *)0 + offset;
const uint loc = read_attr_location(&imm.attr_binding, a_idx);
@@ -364,6 +389,7 @@ void immEnd(void)
{
#if TRUST_NO_ONE
assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
+ assert(imm.active_buffer || imm.batch);
#endif
uint buffer_bytes_used;
@@ -420,12 +446,13 @@ void immEnd(void)
// glBindBuffer(GL_ARRAY_BUFFER, 0);
// glBindVertexArray(0);
/* prep for next immBegin */
- imm.buffer_offset += buffer_bytes_used;
+ imm.active_buffer->buffer_offset += buffer_bytes_used;
}
/* prep for next immBegin */
imm.prim_type = GPU_PRIM_NONE;
imm.strict_vertex_len = true;
+ imm.active_buffer = NULL;
}
static void setAttrValueBit(uint attr_id)
@@ -732,13 +759,11 @@ void immVertex2iv(uint attr_id, const int data[2])
#if 0
# if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
assert(uniform);
# else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name);
# endif
#else
/* NOTE: It is possible to have uniform fully optimized out from the shader.
@@ -746,8 +771,7 @@ void immVertex2iv(uint attr_id, const int data[2])
* TODO(sergey): How can we detect existing-but-optimized-out uniform but still
* catch typos in uniform names passed to immUniform*() functions? */
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
if (uniform == NULL) \
return;
#endif
@@ -785,20 +809,9 @@ void immUniform3fv(const char *name, const float data[3])
/* can increase this limit or move to another file */
#define MAX_UNIFORM_NAME_LEN 60
-void immUniformArray3fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray3fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform3fv(uniform->location, count, data);
}
@@ -815,20 +828,9 @@ void immUniform4fv(const char *name, const float data[4])
glUniform4fv(uniform->location, 1, data);
}
-void immUniformArray4fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray4fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform4fv(uniform->location, count, data);
}
@@ -855,12 +857,10 @@ void immUniform4iv(const char *name, const int data[4])
void immUniformColor4f(float r, float g, float b, float a)
{
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(imm.shader_interface,
- GPU_UNIFORM_COLOR);
-#if TRUST_NO_ONE
- assert(uniform != NULL);
-#endif
- glUniform4f(uniform->location, r, g, b, a);
+ int32_t uniform_loc = GPU_shaderinterface_uniform_builtin(imm.shader_interface,
+ GPU_UNIFORM_COLOR);
+ BLI_assert(uniform_loc != -1);
+ glUniform4f(uniform_loc, r, g, b, a);
}
void immUniformColor4fv(const float rgba[4])
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
index 7266f595447..e834d6afccb 100644
--- a/source/blender/gpu/intern/gpu_immediate_util.c
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -361,25 +361,35 @@ void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2)
/**
* Draw a standard checkerboard to indicate transparent backgrounds.
*/
-void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
+void imm_draw_box_checker_2d_ex(float x1,
+ float y1,
+ float x2,
+ float y2,
+ const float color_primary[4],
+ const float color_secondary[4],
+ int checker_size)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- float checker_primary[4];
- float checker_secondary[4];
- int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE);
immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
- UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary);
- UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary);
- immUniform4fv("color1", checker_primary);
- immUniform4fv("color2", checker_secondary);
+ immUniform4fv("color1", color_primary);
+ immUniform4fv("color2", color_secondary);
immUniform1i("size", checker_size);
immRectf(pos, x1, y1, x2, y2);
immUnbindProgram();
}
+void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
+{
+ float checker_primary[4];
+ float checker_secondary[4];
+ UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary);
+ UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary);
+ int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE);
+ imm_draw_box_checker_2d_ex(x1, y1, x2, y2, checker_primary, checker_secondary, checker_size);
+}
void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
{
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 3e73d156440..d2384b9c065 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -191,7 +191,7 @@ static void gpu_material_free_single(GPUMaterial *material)
void GPU_material_free(ListBase *gpumaterial)
{
- for (LinkData *link = gpumaterial->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, gpumaterial) {
GPUMaterial *material = link->data;
gpu_material_free_single(material);
MEM_freeN(material);
@@ -209,6 +209,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
+GPUShader *GPU_material_get_shader(GPUMaterial *material)
+{
+ return material->pass ? GPU_pass_shader_get(material->pass) : NULL;
+}
+
/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
@@ -628,7 +633,7 @@ GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials,
const void *engine_type,
int options)
{
- for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, gpumaterials) {
GPUMaterial *current_material = (GPUMaterial *)link->data;
if (current_material->engine_type == engine_type && current_material->options == options) {
return current_material;
@@ -662,6 +667,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
/* Caller must re-use materials. */
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
+ /* HACK: Eevee assume this to create Ghash keys. */
+ BLI_assert(sizeof(GPUPass) > 16);
+
/* allocate material */
GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
mat->ma = ma;
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 8260e1496ff..2687f56ad27 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -654,63 +654,59 @@ void GPU_matrix_bind(const GPUShaderInterface *shaderface)
* call glUseProgram before this, as glUniform expects program to be bound
*/
- const GPUShaderInput *MV = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_MODELVIEW);
- const GPUShaderInput *P = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_PROJECTION);
- const GPUShaderInput *MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP);
-
- const GPUShaderInput *N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL);
- const GPUShaderInput *MV_inv = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_MODELVIEW_INV);
- const GPUShaderInput *P_inv = GPU_shaderinterface_uniform_builtin(shaderface,
- GPU_UNIFORM_PROJECTION_INV);
-
- if (MV) {
+ int32_t MV = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW);
+ int32_t P = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION);
+ int32_t MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP);
+
+ int32_t N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL);
+ int32_t MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW_INV);
+ int32_t P_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION_INV);
+
+ if (MV != -1) {
#if DEBUG_MATRIX_BIND
puts("setting MV matrix");
#endif
- glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL));
+ glUniformMatrix4fv(MV, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL));
}
- if (P) {
+ if (P != -1) {
#if DEBUG_MATRIX_BIND
puts("setting P matrix");
#endif
- glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL));
+ glUniformMatrix4fv(P, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL));
}
- if (MVP) {
+ if (MVP != -1) {
#if DEBUG_MATRIX_BIND
puts("setting MVP matrix");
#endif
glUniformMatrix4fv(
- MVP->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL));
+ MVP, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL));
}
- if (N) {
+ if (N != -1) {
#if DEBUG_MATRIX_BIND
puts("setting normal matrix");
#endif
- glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL));
+ glUniformMatrix3fv(N, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL));
}
- if (MV_inv) {
+ if (MV_inv != -1) {
Mat4 m;
GPU_matrix_model_view_get(m);
invert_m4(m);
- glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m);
+ glUniformMatrix4fv(MV_inv, 1, GL_FALSE, (const float *)m);
}
- if (P_inv) {
+ if (P_inv != -1) {
Mat4 m;
GPU_matrix_projection_get(m);
invert_m4(m);
- glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
+ glUniformMatrix4fv(P_inv, 1, GL_FALSE, (const float *)m);
}
gpu_matrix_state_active_set_dirty(false);
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 953b2eb40d8..17d97dc05e2 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -34,6 +34,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_texture.h"
+
#include "gpu_material_library.h"
#include "gpu_node_graph.h"
@@ -298,13 +300,14 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
struct GPUTexture **colorband,
- GPUNodeLinkType link_type)
+ GPUNodeLinkType link_type,
+ eGPUSamplerState sampler_state)
{
/* Find existing texture. */
int num_textures = 0;
GPUMaterialTexture *tex = graph->textures.first;
for (; tex; tex = tex->next) {
- if (tex->ima == ima && tex->colorband == colorband) {
+ if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) {
break;
}
num_textures++;
@@ -316,6 +319,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
tex->ima = ima;
tex->iuser = iuser;
tex->colorband = colorband;
+ tex->sampler_state = sampler_state;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
BLI_snprintf(
@@ -389,21 +393,29 @@ GPUNodeLink *GPU_uniform(const float *num)
return link;
}
-GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
@@ -412,7 +424,8 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX);
return link;
}
@@ -424,7 +437,8 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
- link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX);
return link;
}
@@ -645,7 +659,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
- for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, grid, &graph->volume_grids) {
MEM_SAFE_FREE(grid->name);
}
BLI_freelistN(&graph->volume_grids);
@@ -679,7 +693,7 @@ static void gpu_nodes_tag(GPUNodeLink *link)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
{
- for (GPUNode *node = graph->nodes.first; node; node = node->next) {
+ LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
node->tag = false;
}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 56fe1e40d87..4b38cd333a1 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -314,17 +314,10 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c
glEnable(GL_DEPTH_TEST);
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 {
- glDepthFunc(GL_LEQUAL);
- }
+ /* Always use #GL_LEQUAL even though GPU_SELECT_PICK_ALL always clears the buffer. This is
+ * because individual objects themselves might have sections that overlap and we need these
+ * to have the correct distance information. */
+ glDepthFunc(GL_LEQUAL);
float viewport[4];
glGetFloatv(GL_VIEWPORT, viewport);
@@ -731,8 +724,7 @@ void gpu_select_pick_cache_load_id(void)
#ifdef DEBUG_PRINT
printf("%s (building depth from cache)\n", __func__);
#endif
- for (DepthBufCache *rect_depth = ps->cache.bufs.first; rect_depth;
- rect_depth = rect_depth->next) {
+ LISTBASE_FOREACH (DepthBufCache *, rect_depth, &ps->cache.bufs) {
if (rect_depth->next != NULL) {
/* we know the buffers differ, but this sub-region may not.
* double check before adding an id-pass */
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index c6ffcfa2d86..8c03567b95f 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -54,9 +54,6 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_checker_frag_glsl[];
extern char datatoc_gpu_shader_diag_stripes_frag_glsl[];
extern char datatoc_gpu_shader_simple_lighting_frag_glsl[];
-extern char datatoc_gpu_shader_simple_lighting_flat_color_frag_glsl[];
-extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[];
-extern char datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
extern char datatoc_gpu_shader_flat_id_frag_glsl[];
@@ -67,7 +64,6 @@ extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_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_smooth_color_dithered_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[];
@@ -89,15 +85,13 @@ 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_mask_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_image_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_image_multisample_resolve_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[];
+extern char datatoc_gpu_shader_3D_polyline_frag_glsl[];
+extern char datatoc_gpu_shader_3D_polyline_geom_glsl[];
+extern char datatoc_gpu_shader_3D_polyline_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
-extern char datatoc_gpu_shader_3D_normal_flat_color_vert_glsl[];
-extern char datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[];
extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[];
@@ -143,21 +137,25 @@ extern char datatoc_gpu_shader_gpencil_fill_vert_glsl[];
extern char datatoc_gpu_shader_gpencil_fill_frag_glsl[];
extern char datatoc_gpu_shader_cfg_world_clip_lib_glsl[];
+extern char datatoc_gpu_shader_colorspace_lib_glsl[];
+
const struct GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN] = {
[GPU_SHADER_CFG_DEFAULT] =
{
.lib = "",
- .def = "",
+ .def = "#define blender_srgb_to_framebuffer_space(a) a\n",
},
[GPU_SHADER_CFG_CLIPPED] =
{
.lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl,
- .def = "#define USE_WORLD_CLIP_PLANES\n",
+ .def = "#define USE_WORLD_CLIP_PLANES\n"
+ "#define blender_srgb_to_framebuffer_space(a) a\n",
},
};
/* cache of built-in shaders (each is created on first use) */
static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{NULL}};
+static int g_shader_builtin_srgb_transform = 0;
#ifndef NDEBUG
static uint g_shaderid = 0;
@@ -298,6 +296,28 @@ GPUShader *GPU_shader_create(const char *vertexcode,
vertexcode, fragcode, geocode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, shname);
}
+GPUShader *GPU_shader_create_from_python(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines)
+{
+ char *libcodecat = NULL;
+
+ if (libcode == NULL) {
+ libcode = datatoc_gpu_shader_colorspace_lib_glsl;
+ }
+ else {
+ libcode = libcodecat = BLI_strdupcat(libcode, datatoc_gpu_shader_colorspace_lib_glsl);
+ }
+
+ GPUShader *sh = GPU_shader_create_ex(
+ vertexcode, fragcode, geocode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, NULL);
+
+ MEM_SAFE_FREE(libcodecat);
+ return sh;
+}
+
GPUShader *GPU_shader_load_from_binary(const char *binary,
const int binary_format,
const int binary_len,
@@ -311,6 +331,8 @@ GPUShader *GPU_shader_load_from_binary(const char *binary,
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success) {
+ glUseProgram(program);
+
GPUShader *shader = MEM_callocN(sizeof(*shader), __func__);
shader->interface = GPU_shaderinterface_create(program);
shader->program = program;
@@ -552,6 +574,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
+ glUseProgram(shader->program);
shader->interface = GPU_shaderinterface_create(shader->program);
return shader;
@@ -638,6 +661,7 @@ void GPU_shader_bind(GPUShader *shader)
glUseProgram(shader->program);
GPU_matrix_bind(shader->interface);
+ GPU_shader_set_srgb_uniform(shader->interface);
}
void GPU_shader_unbind(void)
@@ -705,21 +729,19 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
- return uniform ? uniform->location : -2;
+ return uniform ? uniform->location : -1;
}
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name)
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
{
BLI_assert(shader && shader->program);
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name);
- return uniform ? uniform->location : -1;
+ return GPU_shaderinterface_uniform_builtin(shader->interface, builtin);
}
-int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
+int GPU_shader_get_builtin_block(GPUShader *shader, int builtin)
{
BLI_assert(shader && shader->program);
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin);
- return uniform ? uniform->location : -1;
+ return GPU_shaderinterface_block_builtin(shader->interface, builtin);
}
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
@@ -729,6 +751,20 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return ubo ? ubo->location : -1;
}
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
+ return ubo ? ubo->binding : -1;
+}
+
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name);
+ return tex ? tex->binding : -1;
+}
+
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->interface;
@@ -816,32 +852,12 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
glUniform1i(location, value);
}
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
+void GPU_shader_set_srgb_uniform(const GPUShaderInterface *interface)
{
- int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
-
- if (location == -1) {
- return;
+ int32_t loc = GPU_shaderinterface_uniform_builtin(interface, GPU_UNIFORM_SRGB_TRANSFORM);
+ if (loc != -1) {
+ glUniform1i(loc, g_shader_builtin_srgb_transform);
}
-
- glUniformBlockBinding(shader->program, location, bindpoint);
-}
-
-void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
-{
- int number = GPU_texture_bound_number(tex);
-
- if (number == -1) {
- fprintf(stderr, "Texture is not bound.\n");
- BLI_assert(0);
- return;
- }
-
- if (location == -1) {
- return;
- }
-
- glUniform1i(location, number);
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
@@ -868,6 +884,11 @@ char *GPU_shader_get_binary(GPUShader *shader, uint *r_binary_format, int *r_bin
return r_binary;
}
+void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear)
+{
+ g_shader_builtin_srgb_transform = use_srgb_to_linear;
+}
+
static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
[GPU_SHADER_TEXT] =
{
@@ -884,23 +905,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_3D_normal_vert_glsl,
.frag = datatoc_gpu_shader_simple_lighting_frag_glsl,
},
- /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */
- [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] =
- {
- .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl,
- .defs = "#define USE_FLAT_NORMAL\n",
- },
- [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] =
- {
- .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl,
- },
- [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] =
- {
- .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl,
- },
[GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] =
{
@@ -912,69 +916,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_3D_image_vert_glsl,
.frag = datatoc_gpu_shader_image_modulate_alpha_frag_glsl,
},
- [GPU_SHADER_3D_IMAGE_DEPTH] =
- {
- .vert = datatoc_gpu_shader_3D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_depth_linear_frag_glsl,
- },
- [GPU_SHADER_3D_IMAGE_DEPTH_COPY] =
- {
- .vert = datatoc_gpu_shader_3D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_depth_copy_frag_glsl,
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 2\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 4\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 8\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 16\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 2\n"
- "#define USE_DEPTH\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 4\n"
- "#define USE_DEPTH\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 8\n"
- "#define USE_DEPTH\n",
- },
- [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] =
- {
- .vert = datatoc_gpu_shader_2D_vert_glsl,
- .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl,
- .defs = "#define SAMPLES 16\n"
- "#define USE_DEPTH\n",
- },
-
[GPU_SHADER_2D_CHECKER] =
{
.vert = datatoc_gpu_shader_2D_vert_glsl,
@@ -1002,11 +943,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl,
.frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl,
},
- [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] =
- {
- .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl,
- .frag = datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl,
- },
[GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
{
.vert = datatoc_gpu_shader_2D_image_vert_glsl,
@@ -1058,12 +994,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_3D_vert_glsl,
.frag = datatoc_gpu_shader_uniform_color_frag_glsl,
},
- [GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND] =
- {
- .vert = datatoc_gpu_shader_3D_vert_glsl,
- .frag = datatoc_gpu_shader_uniform_color_frag_glsl,
- .defs = "#define USE_BACKGROUND\n",
- },
[GPU_SHADER_3D_FLAT_COLOR] =
{
.vert = datatoc_gpu_shader_3D_flat_color_vert_glsl,
@@ -1085,6 +1015,36 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.frag = datatoc_gpu_shader_uniform_color_frag_glsl,
},
+ [GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR] =
+ {
+ .vert = datatoc_gpu_shader_3D_polyline_vert_glsl,
+ .geom = datatoc_gpu_shader_3D_polyline_geom_glsl,
+ .frag = datatoc_gpu_shader_3D_polyline_frag_glsl,
+ .defs = "#define UNIFORM\n",
+ },
+ [GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR] =
+ {
+ .vert = datatoc_gpu_shader_3D_polyline_vert_glsl,
+ .geom = datatoc_gpu_shader_3D_polyline_geom_glsl,
+ .frag = datatoc_gpu_shader_3D_polyline_frag_glsl,
+ .defs = "#define UNIFORM\n"
+ "#define CLIP\n",
+ },
+ [GPU_SHADER_3D_POLYLINE_FLAT_COLOR] =
+ {
+ .vert = datatoc_gpu_shader_3D_polyline_vert_glsl,
+ .geom = datatoc_gpu_shader_3D_polyline_geom_glsl,
+ .frag = datatoc_gpu_shader_3D_polyline_frag_glsl,
+ .defs = "#define FLAT\n",
+ },
+ [GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR] =
+ {
+ .vert = datatoc_gpu_shader_3D_polyline_vert_glsl,
+ .geom = datatoc_gpu_shader_3D_polyline_geom_glsl,
+ .frag = datatoc_gpu_shader_3D_polyline_frag_glsl,
+ .defs = "#define SMOOTH\n",
+ },
+
[GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] =
{
.vert = datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl,
@@ -1262,8 +1222,12 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
/* common case */
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
- *sh_p = GPU_shader_create(
- stages->vert, stages->frag, stages->geom, NULL, stages->defs, __func__);
+ *sh_p = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){stages->vert, NULL},
+ .geom = (const char *[]){stages->geom, NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
+ .defs = (const char *[]){stages->defs, NULL},
+ });
}
else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
/* Remove eventually, for now ensure support for each shader has been added. */
@@ -1282,7 +1246,7 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
*sh_p = GPU_shader_create_from_arrays({
.vert = (const char *[]){world_clip_lib, stages->vert, NULL},
.geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL},
- .frag = (const char *[]){stages->frag, NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL},
.defs = (const char *[]){world_clip_def, stages->defs, NULL},
});
}
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index f23a0a438d6..9d9f98c6bb0 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -24,6 +24,10 @@
*/
#include "BKE_global.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math_base.h"
+
#include "MEM_guardedalloc.h"
#include "GPU_shader_interface.h"
@@ -36,7 +40,6 @@
#include <string.h>
#define DEBUG_SHADER_INTERFACE 0
-#define DEBUG_SHADER_UNIFORMS 0
#if DEBUG_SHADER_INTERFACE
# include <stdio.h>
@@ -45,8 +48,6 @@
static const char *BuiltinUniform_name(GPUUniformBuiltin u)
{
static const char *names[] = {
- [GPU_UNIFORM_NONE] = NULL,
-
[GPU_UNIFORM_MODEL] = "ModelMatrix",
[GPU_UNIFORM_VIEW] = "ViewMatrix",
[GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix",
@@ -68,14 +69,27 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_BASE_INSTANCE] = "baseInstance",
[GPU_UNIFORM_RESOURCE_CHUNK] = "resourceChunk",
[GPU_UNIFORM_RESOURCE_ID] = "resourceId",
+ [GPU_UNIFORM_SRGB_TRANSFORM] = "srgbTarget",
- [GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,
};
return names[u];
}
+static const char *BuiltinUniformBlock_name(GPUUniformBlockBuiltin u)
+{
+ static const char *names[] = {
+ [GPU_UNIFORM_BLOCK_VIEW] = "viewBlock",
+ [GPU_UNIFORM_BLOCK_MODEL] = "modelBlock",
+ [GPU_UNIFORM_BLOCK_INFO] = "infoBlock",
+
+ [GPU_NUM_UNIFORM_BLOCKS] = NULL,
+ };
+
+ return names[u];
+}
+
GPU_INLINE bool match(const char *a, const char *b)
{
return strcmp(a, b) == 0;
@@ -90,129 +104,136 @@ GPU_INLINE uint hash_string(const char *str)
return i;
}
-GPU_INLINE void set_input_name(GPUShaderInterface *shaderface,
- GPUShaderInput *input,
- const char *name,
- uint32_t name_len)
+GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface,
+ GPUShaderInput *input,
+ char *name,
+ uint32_t name_len)
{
- input->name_offset = shaderface->name_buffer_offset;
- input->name_hash = hash_string(name);
- shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */
-}
+ /* remove "[0]" from array name */
+ if (name[name_len - 1] == ']') {
+ name[name_len - 3] = '\0';
+ name_len -= 3;
+ }
-GPU_INLINE void shader_input_to_bucket(GPUShaderInput *input,
- GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
-{
- const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- input->next = buckets[bucket_index];
- buckets[bucket_index] = input;
+ input->name_offset = (uint32_t)(name - shaderface->name_buffer);
+ input->name_hash = hash_string(name);
+ return name_len + 1; /* include NULL terminator */
}
-GPU_INLINE const GPUShaderInput *buckets_lookup(
- GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS],
- const char *name_buffer,
- const char *name)
+GPU_INLINE const GPUShaderInput *input_lookup(const GPUShaderInterface *shaderface,
+ const GPUShaderInput *const inputs,
+ const uint inputs_len,
+ const char *name)
{
const uint name_hash = hash_string(name);
- const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- const GPUShaderInput *input = buckets[bucket_index];
- if (input == NULL) {
- /* Requested uniform is not found at all. */
- return NULL;
- }
- /* Optimization bit: if there is no hash collision detected when constructing shader interface
- * it means we can only request the single possible uniform. Surely, it's possible we request
- * uniform which causes hash collision, but that will be detected in debug builds. */
- if (input->next == NULL) {
- if (name_hash == input->name_hash) {
-#if TRUST_NO_ONE
- assert(match(name_buffer + input->name_offset, name));
-#endif
- return input;
- }
- return NULL;
- }
- /* Work through possible collisions. */
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
- if (input->name_hash != name_hash) {
- continue;
- }
- if (match(name_buffer + input->name_offset, name)) {
- return input;
+ /* Simple linear search for now. */
+ for (int i = inputs_len - 1; i >= 0; i--) {
+ if (inputs[i].name_hash == name_hash) {
+ if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) {
+ /* Hash colision resolve. */
+ for (; i >= 0 && inputs[i].name_hash == name_hash; i--) {
+ if (match(name, shaderface->name_buffer + inputs[i].name_offset)) {
+ return inputs + i; /* not found */
+ }
+ }
+ return NULL; /* not found */
+ }
+ else {
+ /* This is a bit dangerous since we could have a hash collision.
+ * where the asked uniform that does not exist has the same hash
+ * as a real uniform. */
+ BLI_assert(match(name, shaderface->name_buffer + inputs[i].name_offset));
+ return inputs + i;
+ }
}
}
return NULL; /* not found */
}
-GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
+/* Note that this modify the src array. */
+GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len)
{
- for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; bucket_index++) {
- GPUShaderInput *input = buckets[bucket_index];
- while (input != NULL) {
- GPUShaderInput *input_next = input->next;
- MEM_freeN(input);
- input = input_next;
+ for (uint i = 0; i < input_len; i++) {
+ GPUShaderInput *input_src = &src[0];
+ for (uint j = 1; j < input_len; j++) {
+ if (src[j].name_hash > input_src->name_hash) {
+ input_src = &src[j];
+ }
}
+ dst[i] = *input_src;
+ input_src->name_hash = 0;
}
}
-static bool setup_builtin_uniform(GPUShaderInput *input, const char *name)
+static int block_binding(int32_t program, uint32_t block_index)
{
- /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */
-
- /* detect built-in uniforms (name must match) */
- for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (match(name, builtin_name)) {
- input->builtin_type = u;
- return true;
- }
- }
- input->builtin_type = GPU_UNIFORM_CUSTOM;
- return false;
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ glUniformBlockBinding(program, block_index, block_index);
+ return block_index;
}
-static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name)
+static int sampler_binding(int32_t program,
+ uint32_t uniform_index,
+ int32_t uniform_location,
+ int *sampler_len)
{
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif");
-
- input->location = glGetUniformLocation(shaderface->program, name);
-
- const uint name_len = strlen(name);
- /* Include NULL terminator. */
- shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer,
- shaderface->name_buffer_offset + name_len + 1);
- char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
- strcpy(name_buffer, name);
-
- set_input_name(shaderface, input, name, name_len);
- setup_builtin_uniform(input, name);
-
- shader_input_to_bucket(input, shaderface->uniform_buckets);
- if (input->builtin_type != GPU_UNIFORM_NONE && input->builtin_type != GPU_UNIFORM_CUSTOM) {
- shaderface->builtin_uniforms[input->builtin_type] = input;
+ /* Identify sampler uniforms and asign sampler units to them. */
+ GLint type;
+ glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type);
+
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_1D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_1D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_1D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER: {
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ int binding = *sampler_len;
+ glUniform1i(uniform_location, binding);
+ (*sampler_len)++;
+ return binding;
+ }
+ default:
+ return -1;
}
-#if DEBUG_SHADER_INTERFACE
- printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n",
- shaderface,
- shaderface->program,
- name,
- input->location);
-#endif
- return input;
}
GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
{
- GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface");
- shaderface->program = program;
-
-#if DEBUG_SHADER_INTERFACE
- printf("%s {\n", __func__); /* enter function */
- printf("GPUShaderInterface %p, program %d\n", shaderface, program);
+#ifndef NDEBUG
+ GLint curr_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program);
+ BLI_assert(curr_program == program);
#endif
GLint max_attr_name_len = 0, attr_len = 0;
@@ -223,6 +244,11 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
+ GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len);
+ uniform_len = active_uniform_len;
+
/* Work around driver bug with Intel HD 4600 on Windows 7/8, where
* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */
if (attr_len > 0 && max_attr_name_len == 0) {
@@ -231,78 +257,190 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
if (ubo_len > 0 && max_ubo_name_len == 0) {
max_ubo_name_len = 256;
}
+ if (uniform_len > 0 && max_uniform_name_len == 0) {
+ max_uniform_name_len = 256;
+ }
- const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len;
- shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
-
- /* Attributes */
- for (uint32_t i = 0; i < attr_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
- GLsizei name_len = 0;
+ /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before
+ * allocating the uniform array. */
+ GLint max_ubo_uni_len = 0;
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ max_ubo_uni_len = max_ii(max_ubo_uni_len, ubo_uni_len);
+ uniform_len -= ubo_uni_len;
+ }
+ /* Bit set to true if uniform comes from a uniform block. */
+ BLI_bitmap *uniforms_from_blocks = BLI_BITMAP_NEW(active_uniform_len, __func__);
+ /* Set uniforms from block for exclusion. */
+ GLint *ubo_uni_ids = MEM_mallocN(sizeof(GLint) * max_ubo_uni_len, __func__);
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ubo_uni_ids);
+ for (int u = 0; u < ubo_uni_len; u++) {
+ BLI_BITMAP_ENABLE(uniforms_from_blocks, ubo_uni_ids[u]);
+ }
+ }
+ MEM_freeN(ubo_uni_ids);
- glGetActiveAttrib(
- program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+ uint32_t name_buffer_offset = 0;
+ const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len +
+ uniform_len * max_uniform_name_len;
- /* remove "[0]" from array name */
- if (name[name_len - 1] == ']') {
- name[name_len - 3] = '\0';
- name_len -= 3;
- }
+ int input_tot_len = attr_len + ubo_len + uniform_len;
+ size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len;
- /* TODO: reject DOUBLE gl_types */
+ GPUShaderInterface *shaderface = MEM_callocN(interface_size, "GPUShaderInterface");
+ shaderface->attribute_len = attr_len;
+ shaderface->ubo_len = ubo_len;
+ shaderface->uniform_len = uniform_len;
+ shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
+ GPUShaderInput *inputs = shaderface->inputs;
- input->location = glGetAttribLocation(program, name);
+ /* Temp buffer. */
+ int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len);
+ GPUShaderInput *inputs_tmp = MEM_mallocN(sizeof(GPUShaderInput) * input_tmp_len, "name_buffer");
- set_input_name(shaderface, input, name, name_len);
+ /* Attributes */
+ shaderface->enabled_attr_mask = 0;
+ for (int i = 0, idx = 0; i < attr_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
+ GLenum type;
+ GLint size;
+
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name);
+ GLint location = glGetAttribLocation(program, name);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (location == -1) {
+ shaderface->attribute_len--;
+ continue;
+ }
- shader_input_to_bucket(input, shaderface->attr_buckets);
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = input->binding = location;
-#if DEBUG_SHADER_INTERFACE
- printf("attr[%u] '%s' at location %d\n", i, name, input->location);
-#endif
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_attr_mask |= (1 << input->location);
}
+ sort_input_list(inputs, inputs_tmp, shaderface->attribute_len);
+ inputs += shaderface->attribute_len;
+
/* Uniform Blocks */
- for (uint32_t i = 0; i < ubo_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ for (int i = 0, idx = 0; i < ubo_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
GLsizei name_len = 0;
glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
- input->location = i;
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->binding = input->location = block_binding(program, i);
- set_input_name(shaderface, input, name, name_len);
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_ubo_mask |= (1 << input->binding);
+ }
+ sort_input_list(inputs, inputs_tmp, shaderface->ubo_len);
+ inputs += shaderface->ubo_len;
- shader_input_to_bucket(input, shaderface->ubo_buckets);
+ /* Uniforms */
+ for (int i = 0, idx = 0, sampler = 0; i < active_uniform_len; i++) {
+ if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) {
+ continue;
+ }
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
-#if DEBUG_SHADER_INTERFACE
- printf("ubo '%s' at location %d\n", name, input->location);
-#endif
+ glGetActiveUniformName(program, i, remaining_buffer, &name_len, name);
+
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = glGetUniformLocation(program, name);
+ input->binding = sampler_binding(program, i, input->location, &sampler);
+
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_tex_mask |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
}
+ sort_input_list(inputs, inputs_tmp, shaderface->uniform_len);
+
/* Builtin Uniforms */
- for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (glGetUniformLocation(program, builtin_name) != -1) {
- add_uniform((GPUShaderInterface *)shaderface, builtin_name);
- }
+ for (GPUUniformBuiltin u = 0; u < GPU_NUM_UNIFORMS; u++) {
+ shaderface->builtins[u] = glGetUniformLocation(program, BuiltinUniform_name(u));
}
+
+ /* Builtin Uniforms Blocks */
+ for (GPUUniformBlockBuiltin u = 0; u < GPU_NUM_UNIFORM_BLOCKS; u++) {
+ const GPUShaderInput *block = GPU_shaderinterface_ubo(shaderface, BuiltinUniformBlock_name(u));
+ shaderface->builtin_blocks[u] = (block != NULL) ? block->binding : -1;
+ }
+
/* Batches ref buffer */
shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *),
"GPUShaderInterface batches");
+ MEM_freeN(uniforms_from_blocks);
+ MEM_freeN(inputs_tmp);
+
+ /* Resize name buffer to save some memory. */
+ if (name_buffer_offset < name_buffer_len) {
+ shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, name_buffer_offset);
+ }
+
+#if DEBUG_SHADER_INTERFACE
+ char *name_buf = shaderface->name_buffer;
+ printf("--- GPUShaderInterface %p, program %d ---\n", shaderface, program);
+ if (shaderface->attribute_len > 0) {
+ printf("Attributes {\n");
+ for (int i = 0; i < shaderface->attribute_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + i;
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->ubo_len > 0) {
+ printf("Uniform Buffer Objects {\n");
+ for (int i = 0; i < shaderface->ubo_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + i;
+ printf("\t(binding = %d) %s;\n", input->binding, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->enabled_tex_mask > 0) {
+ printf("Samplers {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding != -1) {
+ printf("\t(location = %d, binding = %d) %s;\n",
+ input->location,
+ input->binding,
+ name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ if (shaderface->uniform_len > 0) {
+ printf("Uniforms {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding == -1) {
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ printf("--- GPUShaderInterface end ---\n\n");
+#endif
+
return shaderface;
}
void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
{
- /* Free memory used by buckets and has entries. */
- buckets_free(shaderface->uniform_buckets);
- buckets_free(shaderface->attr_buckets);
- buckets_free(shaderface->ubo_buckets);
/* Free memory used by name_buffer. */
MEM_freeN(shaderface->name_buffer);
/* Remove this interface from all linked Batches vao cache. */
@@ -316,59 +454,39 @@ void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
MEM_freeN(shaderface);
}
-const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
+ const char *name)
{
- return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
+ uint ofs = 0;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
+ const char *name)
{
- const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name);
- /* If input is not found add it so it's found next time. */
- if (input == NULL) {
- input = add_uniform((GPUShaderInterface *)shaderface, name);
-
- if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) {
- fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name);
- }
- }
-
-#if DEBUG_SHADER_UNIFORMS
- if ((G.debug & G_DEBUG_GPU) && input->builtin_type != GPU_UNIFORM_NONE &&
- input->builtin_type != GPU_UNIFORM_CUSTOM) {
- /* Warn if we find a matching builtin, since these can be looked up much quicker. */
- fprintf(stderr,
- "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as "
- "such!\n",
- name);
- }
-#endif
- return (input->location != -1) ? input : NULL;
+ uint ofs = shaderface->attribute_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
- GPUUniformBuiltin builtin)
+const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
+ const char *name)
{
-#if TRUST_NO_ONE
- assert(builtin != GPU_UNIFORM_NONE);
- assert(builtin != GPU_UNIFORM_CUSTOM);
- assert(builtin != GPU_NUM_UNIFORMS);
-#endif
- return shaderface->builtin_uniforms[builtin];
+ uint ofs = shaderface->attribute_len + shaderface->ubo_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
- const char *name)
+int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBuiltin builtin)
{
- return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS);
+ return shaderface->builtins[builtin];
}
-const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
- const char *name)
+int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface,
+ GPUUniformBlockBuiltin builtin)
{
- return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name);
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS);
+ return shaderface->builtin_blocks[builtin];
}
void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
diff --git a/source/blender/gpu/intern/gpu_state.c b/source/blender/gpu/intern/gpu_state.c
index d6f044a79e3..908f5fa5771 100644
--- a/source/blender/gpu/intern/gpu_state.c
+++ b/source/blender/gpu/intern/gpu_state.c
@@ -370,4 +370,44 @@ void gpuPopAttr(void)
#undef Attr
#undef AttrStack
+/* Default OpenGL State
+ *
+ * This is called on startup, for opengl offscreen render.
+ * Generally we should always return to this state when
+ * temporarily modifying the state for drawing, though that are (undocumented)
+ * exceptions that we should try to get rid of. */
+
+void GPU_state_init(void)
+{
+ GPU_program_point_size(false);
+
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_COLOR_LOGIC_OP);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_DITHER);
+
+ glDepthFunc(GL_LEQUAL);
+ glDepthRange(0.0, 1.0);
+
+ glFrontFace(GL_CCW);
+ glCullFace(GL_BACK);
+ glDisable(GL_CULL_FACE);
+
+ /* Is default but better be explicit. */
+ glEnable(GL_MULTISAMPLE);
+
+ /* This is a bit dangerous since addons could change this. */
+ glEnable(GL_PRIMITIVE_RESTART);
+ glPrimitiveRestartIndex((GLuint)0xFFFFFFFF);
+
+ /* TODO: Should become default. But needs at least GL 4.3 */
+ if (GLEW_ARB_ES3_compatibility) {
+ /* Takes predecence over GL_PRIMITIVE_RESTART */
+ glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+ }
+}
+
/** \} */
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 075a8e8aeb5..ca0d633aa9e 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -50,7 +50,9 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D;
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
-} GG = {NULL, NULL, NULL};
+ /** Sampler objects used to replace internal texture parameters. */
+ GLuint samplers[GPU_SAMPLER_MAX];
+} GG = {NULL};
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 12
@@ -72,7 +74,7 @@ typedef enum eGPUTextureFormatFlag {
struct GPUTexture {
int w, h, d; /* width/height/depth */
int orig_w, orig_h; /* width/height (of source data), optional. */
- int number; /* number for multitexture binding */
+ int number; /* Texture unit to which this texture is bound. */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
GLenum target_base; /* same as target, (but no multisample)
@@ -81,6 +83,7 @@ struct GPUTexture {
eGPUTextureFormat format;
eGPUTextureFormatFlag format_flag;
+ eGPUSamplerState sampler_state; /* Internal Sampler state. */
int mipmaps; /* number of mipmaps */
int components; /* number of color/alpha channels */
@@ -88,9 +91,13 @@ struct GPUTexture {
int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
+ /* Legacy workaround for texture copy. */
+ GLuint copy_fb;
+ GPUContext *copy_fb_ctx;
};
static uint gpu_get_bytesize(eGPUTextureFormat data_type);
+static void gpu_texture_framebuffer_ensure(GPUTexture *tex);
/* ------ Memory Management ------- */
/* Records every texture allocation / free
@@ -165,26 +172,33 @@ static const char *gl_enum_to_str(GLenum e)
ENUM_TO_STRING(TEXTURE_2D_MULTISAMPLE),
ENUM_TO_STRING(RGBA32F),
ENUM_TO_STRING(RGBA16F),
+ ENUM_TO_STRING(RGBA16UI),
+ ENUM_TO_STRING(RGBA16I),
ENUM_TO_STRING(RGBA16),
- ENUM_TO_STRING(RG32F),
+ ENUM_TO_STRING(RGBA8UI),
+ ENUM_TO_STRING(RGBA8I),
+ ENUM_TO_STRING(RGBA8),
ENUM_TO_STRING(RGB16F),
+ ENUM_TO_STRING(RG32F),
ENUM_TO_STRING(RG16F),
+ ENUM_TO_STRING(RG16UI),
ENUM_TO_STRING(RG16I),
ENUM_TO_STRING(RG16),
- ENUM_TO_STRING(RGBA8),
- ENUM_TO_STRING(RGBA8UI),
+ ENUM_TO_STRING(RG8UI),
+ ENUM_TO_STRING(RG8I),
+ ENUM_TO_STRING(RG8),
+ ENUM_TO_STRING(R8UI),
+ ENUM_TO_STRING(R8I),
+ ENUM_TO_STRING(R8),
ENUM_TO_STRING(R32F),
ENUM_TO_STRING(R32UI),
ENUM_TO_STRING(R32I),
ENUM_TO_STRING(R16F),
- ENUM_TO_STRING(R16I),
ENUM_TO_STRING(R16UI),
- ENUM_TO_STRING(RG8),
- ENUM_TO_STRING(RG16UI),
+ ENUM_TO_STRING(R16I),
ENUM_TO_STRING(R16),
- ENUM_TO_STRING(R8),
- ENUM_TO_STRING(R8UI),
ENUM_TO_STRING(R11F_G11F_B10F),
+ ENUM_TO_STRING(SRGB8_ALPHA8),
ENUM_TO_STRING(DEPTH24_STENCIL8),
ENUM_TO_STRING(DEPTH32F_STENCIL8),
ENUM_TO_STRING(DEPTH_COMPONENT32F),
@@ -457,7 +471,7 @@ static GLenum gpu_format_to_gl_internalformat(eGPUTextureFormat format)
case GPU_RG16I:
return GL_RG16I;
case GPU_RG16F:
- return GL_RGBA32F;
+ return GL_RG16F;
case GPU_RG16:
return GL_RG16;
case GPU_R8UI:
@@ -816,12 +830,12 @@ GPUTexture *GPU_texture_create_nD(int w,
tex->h = h;
tex->d = d;
tex->samples = samples;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = 0;
+ tex->number = -1;
if (n == 2) {
if (d == 0) {
@@ -965,26 +979,13 @@ GPUTexture *GPU_texture_create_nD(int w,
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_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
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);
- }
- if (n > 2) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1003,12 +1004,12 @@ GPUTexture *GPU_texture_cube_create(int w,
tex->h = w;
tex->d = d;
tex->samples = 0;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = GPU_FORMAT_CUBE;
+ tex->number = -1;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -1106,22 +1107,13 @@ GPUTexture *GPU_texture_cube_create(int w,
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_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
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);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
-
- 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);
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1132,13 +1124,13 @@ GPUTexture *GPU_texture_cube_create(int w,
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->format_flag = 0;
tex->target_base = tex->target = GL_TEXTURE_BUFFER;
tex->mipmaps = 0;
+ tex->number = -1;
GLenum internalformat = gpu_format_to_gl_internalformat(tex_format);
@@ -1185,11 +1177,15 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->bindcode = bindcode;
- tex->number = -1;
tex->refcount = 1;
tex->target = textarget;
tex->target_base = textarget;
tex->samples = 0;
+ tex->sampler_state = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO;
+ if (GPU_get_mipmap()) {
+ tex->sampler_state |= (GPU_SAMPLER_MIPMAP | GPU_SAMPLER_FILTER);
+ }
+ tex->number = -1;
if (!glIsTexture(tex->bindcode)) {
GPU_print_error_debug("Blender Texture Not Loaded");
@@ -1560,25 +1556,117 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int mipl
void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat gpu_data_format, const void *color)
{
- if (GLEW_ARB_clear_texture) {
- GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag);
+ BLI_assert(color != NULL); /* Do not accept NULL as parameter. */
+ gpu_validate_data_format(tex->format, gpu_data_format);
+
+ if (false && GLEW_ARB_clear_texture) {
GLenum data_type = gpu_get_gl_datatype(gpu_data_format);
+ GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag);
glClearTexImage(tex->bindcode, 0, data_format, data_type, color);
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ }
+ else if (GPU_texture_depth(tex)) {
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT:
+ case GPU_DATA_UNSIGNED_INT:
+ break;
+ default:
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ break;
+ }
+ }
+ else {
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT:
+ case GPU_DATA_UNSIGNED_INT:
+ case GPU_DATA_UNSIGNED_BYTE:
+ break;
+ default:
+ /* TODO(clem) implement in fallback. */
+ BLI_assert(0);
+ break;
+ }
+ }
}
else {
- size_t buffer_len = gpu_texture_memory_footprint_compute(tex);
- unsigned char *pixels = MEM_mallocN(buffer_len, __func__);
- if (color) {
- const size_t bytesize = (size_t)gpu_get_bytesize(tex->format);
- for (size_t byte = 0; byte < buffer_len; byte += bytesize) {
- memcpy(&pixels[byte], color, bytesize);
+ /* Fallback for older GL. */
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
+
+ gpu_texture_framebuffer_ensure(tex);
+ /* This means that this function can only be used in one context for each texture. */
+ BLI_assert(tex->copy_fb_ctx == GPU_context_active_get());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, tex->copy_fb);
+ glViewport(0, 0, tex->w, tex->h);
+
+ /* Watch: Write mask could prevent the clear.
+ * glClearTexImage does not change the state so we don't do it here either. */
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ /* TODO(clem) implement. */
+ BLI_assert(0);
+ }
+ else if (GPU_texture_depth(tex)) {
+ float depth;
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT: {
+ depth = *(float *)color;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_INT: {
+ depth = *(uint *)color / (float)UINT_MAX;
+ break;
+ }
+ default:
+ BLI_assert(!"Unhandled data format");
+ depth = 0.0f;
+ break;
}
+ glClearDepth(depth);
+ glClear(GL_DEPTH_BUFFER_BIT);
}
else {
- memset(pixels, 0, buffer_len);
+ float r, g, b, a;
+ switch (gpu_data_format) {
+ case GPU_DATA_FLOAT: {
+ float *f_color = (float *)color;
+ r = f_color[0];
+ g = (tex->components > 1) ? f_color[1] : 0.0f;
+ b = (tex->components > 2) ? f_color[2] : 0.0f;
+ a = (tex->components > 3) ? f_color[3] : 0.0f;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_INT: {
+ uint *u_color = (uint *)color;
+ r = u_color[0] / (float)UINT_MAX;
+ g = (tex->components > 1) ? u_color[1] / (float)UINT_MAX : 0.0f;
+ b = (tex->components > 2) ? u_color[2] / (float)UINT_MAX : 0.0f;
+ a = (tex->components > 3) ? u_color[3] / (float)UINT_MAX : 0.0f;
+ break;
+ }
+ case GPU_DATA_UNSIGNED_BYTE: {
+ uchar *ub_color = (uchar *)color;
+ r = ub_color[0] / 255.0f;
+ g = (tex->components > 1) ? ub_color[1] / 255.0f : 0.0f;
+ b = (tex->components > 2) ? ub_color[2] / 255.0f : 0.0f;
+ a = (tex->components > 3) ? ub_color[3] / 255.0f : 0.0f;
+ break;
+ }
+ default:
+ BLI_assert(!"Unhandled data format");
+ r = g = b = a = 0.0f;
+ break;
+ }
+ glClearColor(r, g, b, a);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (prev_fb) {
+ GPU_framebuffer_bind(prev_fb);
}
- GPU_texture_update(tex, gpu_data_format, pixels);
- MEM_freeN(pixels);
}
}
@@ -1624,16 +1712,17 @@ void GPU_invalid_tex_free(void)
}
}
-void GPU_texture_bind(GPUTexture *tex, int number)
+/* set_number is to save the the texture unit for setting texture parameters. */
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number)
{
- BLI_assert(number >= 0);
+ BLI_assert(unit >= 0);
- if (number >= GPU_max_textures()) {
+ if (unit >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
- if ((G.debug & G_DEBUG)) {
+ if (G.debug & G_DEBUG) {
for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; i++) {
if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
fprintf(stderr,
@@ -1645,16 +1734,27 @@ void GPU_texture_bind(GPUTexture *tex, int number)
}
}
- glActiveTexture(GL_TEXTURE0 + number);
+ if (set_number) {
+ tex->number = unit;
+ }
+
+ glActiveTexture(GL_TEXTURE0 + unit);
+
+ state = (state < GPU_SAMPLER_MAX) ? state : tex->sampler_state;
if (tex->bindcode != 0) {
glBindTexture(tex->target, tex->bindcode);
+ glBindSampler(unit, GG.samplers[state]);
}
else {
GPU_invalid_tex_bind(tex->target_base);
+ glBindSampler(unit, 0);
}
+}
- tex->number = number;
+void GPU_texture_bind(GPUTexture *tex, int unit)
+{
+ GPU_texture_bind_ex(tex, GPU_SAMPLER_MAX, unit, true);
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -1665,13 +1765,34 @@ void GPU_texture_unbind(GPUTexture *tex)
glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
-
+ glBindSampler(tex->number, 0);
tex->number = -1;
}
-int GPU_texture_bound_number(GPUTexture *tex)
+void GPU_texture_unbind_all(void)
{
- return tex->number;
+ if (GLEW_ARB_multi_bind) {
+ glBindTextures(0, GPU_max_textures(), NULL);
+ glBindSamplers(0, GPU_max_textures(), NULL);
+ return;
+ }
+
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_1D, 0);
+ glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_3D, 0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ if (GPU_arb_texture_cube_map_array_is_supported()) {
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0);
+ }
+ glBindSampler(i, 0);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
}
#define WARN_NOT_BOUND(_tex) \
@@ -1695,8 +1816,8 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
if (GPU_texture_depth(tex)) {
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
- * In this case we just create a complete texture with mipmaps manually without down-sampling.
- * You must initialize the texture levels using other methods like
+ * In this case we just create a complete texture with mipmaps manually without
+ * down-sampling. You must initialize the texture levels using other methods like
* GPU_framebuffer_recursive_downsample(). */
eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format);
for (int i = 1; i < levels; i++) {
@@ -1712,66 +1833,125 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
gpu_texture_memory_footprint_add(tex);
}
-void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
+static GLenum gpu_texture_default_attachment(GPUTexture *tex)
{
- WARN_NOT_BOUND(tex);
+ return !GPU_texture_depth(tex) ?
+ GL_COLOR_ATTACHMENT0 :
+ (GPU_texture_stencil(tex) ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
+}
+
+static void gpu_texture_framebuffer_ensure(GPUTexture *tex)
+{
+ if (tex->copy_fb == 0) {
+ tex->copy_fb = GPU_fbo_alloc();
+ tex->copy_fb_ctx = GPU_context_active_get();
+
+ GLenum attachment = gpu_texture_default_attachment(tex);
+ glBindFramebuffer(GL_FRAMEBUFFER, tex->copy_fb);
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, tex->bindcode, 0);
+ if (!GPU_texture_depth(tex)) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ }
+ BLI_assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+}
+
+/* Copy a texture content to a similar texture. Only Mip 0 is copied. */
+void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
+{
+ BLI_assert(dst->target == src->target);
+ BLI_assert(dst->w == src->w);
+ BLI_assert(dst->h == src->h);
+ BLI_assert(!GPU_texture_cube(src) && !GPU_texture_cube(dst));
+ /* TODO support array / 3D textures. */
+ BLI_assert(dst->d == 0);
+ BLI_assert(dst->format == src->format);
+
+ if (GLEW_ARB_copy_image) {
+ /* Opengl 4.3 */
+ glCopyImageSubData(src->bindcode,
+ src->target,
+ 0,
+ 0,
+ 0,
+ 0,
+ dst->bindcode,
+ dst->target,
+ 0,
+ 0,
+ 0,
+ 0,
+ src->w,
+ src->h,
+ 1);
+ }
+ else {
+ /* Fallback for older GL. */
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
+
+ gpu_texture_framebuffer_ensure(src);
+ gpu_texture_framebuffer_ensure(dst);
+
+ /* This means that this function can only be used in one context for each texture. */
+ BLI_assert(src->copy_fb_ctx == GPU_context_active_get());
+ BLI_assert(dst->copy_fb_ctx == GPU_context_active_get());
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, src->copy_fb);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->copy_fb);
+
+ GLbitfield mask = 0;
+ if (GPU_texture_stencil(src)) {
+ mask |= GL_STENCIL_BUFFER_BIT;
+ }
+ if (GPU_texture_depth(src)) {
+ mask |= GL_DEPTH_BUFFER_BIT;
+ }
+ else {
+ mask |= GL_COLOR_BUFFER_BIT;
+ }
+
+ glBlitFramebuffer(0, 0, src->w, src->h, 0, 0, src->w, src->h, mask, GL_NEAREST);
+
+ if (prev_fb) {
+ GPU_framebuffer_bind(prev_fb);
+ }
+ }
+}
+
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
+{
/* Could become an assertion ? (fclem) */
if (!GPU_texture_depth(tex)) {
return;
}
-
- GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- 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);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
- BLI_assert((!use_filter && !use_mipmap) ||
+ 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);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
-void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
{
- WARN_NOT_BOUND(tex);
-
- 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);
- }
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
+ SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
}
void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
@@ -1785,34 +1965,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
}
-static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
-{
- switch (filter) {
- case GPU_NEAREST:
- return GL_NEAREST;
- case GPU_LINEAR:
- return GL_LINEAR;
- default:
- BLI_assert(!"Unhandled filter mode");
- return GL_NEAREST;
- }
-}
-
-void GPU_texture_filters(GPUTexture *tex,
- eGPUFilterFunction min_filter,
- eGPUFilterFunction mag_filter)
-{
- WARN_NOT_BOUND(tex);
-
- /* Stencil and integer format does not support filtering. */
- BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter));
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -1831,6 +1983,9 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->bindcode) {
GPU_tex_free(tex->bindcode);
}
+ if (tex->copy_fb) {
+ GPU_fbo_free(tex->copy_fb, tex->copy_fb_ctx);
+ }
gpu_texture_memory_footprint_remove(tex);
@@ -1970,3 +2125,55 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
size[2] = max_ii(1, tex->d / div);
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name GPU Sampler Objects
+ *
+ * Simple wrapper around opengl sampler objects.
+ * Override texture sampler state for one sampler unit only.
+ * \{ */
+
+void GPU_samplers_init(void)
+{
+ glGenSamplers(GPU_SAMPLER_MAX, GG.samplers);
+ for (int i = 0; i < GPU_SAMPLER_MAX; i++) {
+ eGPUSamplerState state = i;
+ GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
+ GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type;
+ GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type;
+ GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type;
+ GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST;
+ GLenum min_filter = (state & GPU_SAMPLER_FILTER) ?
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) :
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
+ GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
+ float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ?
+ GPU_get_anisotropic() :
+ 1.0f;
+
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_T, wrap_t);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_R, wrap_r);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MIN_FILTER, min_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MAG_FILTER, mag_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_MODE, compare_mode);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ if (GLEW_EXT_texture_filter_anisotropic) {
+ glSamplerParameterf(GG.samplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter);
+ }
+
+ /** Other states are left to default:
+ * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
+ * - GL_TEXTURE_MIN_LOD is -1000.
+ * - GL_TEXTURE_MAX_LOD is 1000.
+ * - GL_TEXTURE_LOD_BIAS is 0.0f.
+ **/
+ }
+}
+
+void GPU_samplers_free(void)
+{
+ glDeleteSamplers(GPU_SAMPLER_MAX, GG.samplers);
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
index 943793956d1..130e8fe7da1 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.c
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -147,7 +147,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
/* Make sure we comply to the ubo alignment requirements. */
gpu_uniformbuffer_inputs_sort(inputs);
- for (LinkData *link = inputs->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, inputs) {
const eGPUType gputype = get_padded_gpu_type(link);
ubo->buffer.size += gputype * sizeof(float);
}
@@ -160,7 +160,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
/* Now that we know the total ubo size we can start populating it. */
float *offset = ubo->data;
- for (LinkData *link = inputs->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, inputs) {
GPUInput *input = link->data;
memcpy(offset, input->vec, input->type * sizeof(float));
offset += get_padded_gpu_type(link);
@@ -272,7 +272,7 @@ static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL};
eGPUType cur_type = MAX_UBO_GPU_TYPE + 1;
- for (LinkData *link = inputs->first; link; link = link->next) {
+ LISTBASE_FOREACH (LinkData *, link, inputs) {
GPUInput *input = link->data;
if (input->type == GPU_MAT3) {
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c
index 1df7e68e08b..25daabe601d 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.c
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.c
@@ -196,7 +196,7 @@ void GPU_vertbuf_attr_fill(GPUVertBuf *verts, uint a_idx, const void *data)
GPU_vertbuf_attr_fill_stride(verts, a_idx, stride, data);
}
-/** Fills a whole vertex (all attribs). Data must match packed layout. */
+/** Fills a whole vertex (all attributes). Data must match packed layout. */
void GPU_vertbuf_vert_set(GPUVertBuf *verts, uint v_idx, const void *data)
{
const GPUVertFormat *format = &verts->format;
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index 8370bcf4beb..b84a7e0f554 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -23,8 +23,6 @@
* GPU vertex format
*/
-#include "GPU_shader_interface.h"
-
#include "GPU_vertex_format.h"
#include "gpu_vertex_format_private.h"
#include <stddef.h>
@@ -34,6 +32,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_shader.h"
+#include "gpu_shader_private.h"
+
#define PACK_DEBUG 0
#if PACK_DEBUG
@@ -207,15 +208,15 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
}
/**
- * Makes vertex attrib from the next vertices to be accessible in the vertex shader.
- * For an attrib named "attr" you can access the next nth vertex using "attrn".
- * Use this function after specifying all the attribs in the format.
+ * Makes vertex attribute from the next vertices to be accessible in the vertex shader.
+ * For an attribute named "attr" you can access the next nth vertex using "attr{number}".
+ * Use this function after specifying all the attributes in the format.
*
* NOTE: This does NOT work when using indexed rendering.
- * NOTE: Only works for first attrib name. (this limitation can be changed if needed)
+ * NOTE: Only works for first attribute name. (this limitation can be changed if needed)
*
- * WARNING: this function creates a lot of aliases/attribs, make sure to keep the attrib name
- * short to avoid overflowing the namebuffer.
+ * WARNING: this function creates a lot of aliases/attributes, make sure to keep the attribute
+ * name short to avoid overflowing the name-buffer.
* */
void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count)
{
@@ -276,28 +277,26 @@ static void safe_bytes(char out[11], const char data[8])
/* Warning: Always add a prefix to the result of this function as
* the generated string can start with a number and not be a valid attribute name. */
-void GPU_vertformat_safe_attrib_name(const char *attrib_name,
- char *r_safe_name,
- uint UNUSED(max_len))
+void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint UNUSED(max_len))
{
char data[8] = {0};
- uint len = strlen(attrib_name);
+ uint len = strlen(attr_name);
if (len > 8) {
/* Start with the first 4 chars of the name; */
for (int i = 0; i < 4; i++) {
- data[i] = attrib_name[i];
+ data[i] = attr_name[i];
}
/* We use a hash to identify each data layer based on its name.
* NOTE: This is still prone to hash collision but the risks are very low.*/
/* Start hashing after the first 2 chars. */
- *(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attrib_name + 4);
+ *(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attr_name + 4);
}
else {
/* Copy the whole name. Collision is barely possible
* (hash would have to be equal to the last 4 bytes). */
- for (int i = 0; i < 8 && attrib_name[i] != '\0'; i++) {
- data[i] = attrib_name[i];
+ for (int i = 0; i < 8 && attr_name[i] != '\0'; i++) {
+ data[i] = attr_name[i];
}
}
/* Convert to safe bytes characters. */
@@ -305,9 +304,9 @@ void GPU_vertformat_safe_attrib_name(const char *attrib_name,
/* End the string */
r_safe_name[11] = '\0';
- BLI_assert(GPU_MAX_SAFE_ATTRIB_NAME >= 12);
+ BLI_assert(GPU_MAX_SAFE_ATTR_NAME >= 12);
#if 0 /* For debugging */
- printf("%s > %lx > %s\n", attrib_name, *(uint64_t *)data, r_safe_name);
+ printf("%s > %lx > %s\n", attr_name, *(uint64_t *)data, r_safe_name);
#endif
}
@@ -316,13 +315,13 @@ void GPU_vertformat_safe_attrib_name(const char *attrib_name,
* Use direct buffer access to fill the data.
* This is for advanced usage.
*
- * Deinterleaved data means all attrib data for each attrib
- * is stored continuously like this :
+ * De-interleaved data means all attribute data for each attribute
+ * is stored continuously like this:
* 000011112222
* instead of :
* 012012012012
*
- * Note this is per attrib deinterleaving, NOT per component.
+ * Note this is per attribute de-interleaving, NOT per component.
* */
void GPU_vertformat_deinterleave(GPUVertFormat *format)
{
@@ -393,38 +392,37 @@ void VertexFormat_pack(GPUVertFormat *format)
format->packed = true;
}
-static uint calc_input_component_size(const GPUShaderInput *input)
+static uint calc_component_size(const GLenum gl_type)
{
- int size = input->size;
- switch (input->gl_type) {
+ switch (gl_type) {
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_UNSIGNED_INT_VEC2:
- return size * 2;
+ return 2;
case GL_FLOAT_VEC3:
case GL_INT_VEC3:
case GL_UNSIGNED_INT_VEC3:
- return size * 3;
+ return 3;
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_INT_VEC4:
case GL_UNSIGNED_INT_VEC4:
- return size * 4;
+ return 4;
case GL_FLOAT_MAT3:
- return size * 9;
+ return 9;
case GL_FLOAT_MAT4:
- return size * 16;
+ return 16;
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT3x2:
- return size * 6;
+ return 6;
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT4x2:
- return size * 8;
+ return 8;
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4x3:
- return size * 12;
+ return 12;
default:
- return size;
+ return 1;
}
}
@@ -468,42 +466,39 @@ static void get_fetch_mode_and_comp_type(int gl_type,
}
}
-void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface)
+void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader)
{
- const char *name_buffer = shaderface->name_buffer;
-
- for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) {
- const GPUShaderInput *input = shaderface->attr_buckets[i];
- if (input == NULL) {
- continue;
- }
+ GPU_vertformat_clear(format);
+ GPUVertAttr *attr = &format->attrs[0];
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
+ GLint attr_len;
+ glGetProgramiv(shader->program, GL_ACTIVE_ATTRIBUTES, &attr_len);
- /* OpenGL attributes such as `gl_VertexID` have a location of -1. */
- if (input->location < 0) {
- continue;
- }
-
- format->name_len++; /* multiname support */
- format->attr_len++;
-
- GPUVertCompType comp_type;
- GPUVertFetchMode fetch_mode;
- get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode);
+ for (int i = 0; i < attr_len; i++) {
+ char name[256];
+ GLenum gl_type;
+ GLint size;
+ glGetActiveAttrib(shader->program, i, sizeof(name), NULL, &size, &gl_type, name);
- GPUVertAttr *attr = &format->attrs[input->location];
-
- attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset);
- attr->offset = 0; /* offsets & stride are calculated later (during pack) */
- attr->comp_len = calc_input_component_size(input);
- attr->sz = attr->comp_len * 4;
- attr->fetch_mode = fetch_mode;
- attr->comp_type = comp_type;
- attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (glGetAttribLocation(shader->program, name) == -1) {
+ continue;
}
+
+ format->name_len++; /* multiname support */
+ format->attr_len++;
+
+ GPUVertCompType comp_type;
+ GPUVertFetchMode fetch_mode;
+ get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode);
+
+ attr->names[attr->name_len++] = copy_attr_name(format, name);
+ attr->offset = 0; /* offsets & stride are calculated later (during pack) */
+ attr->comp_len = calc_component_size(gl_type) * size;
+ attr->sz = attr->comp_len * 4;
+ attr->fetch_mode = fetch_mode;
+ attr->comp_type = comp_type;
+ attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ attr += 1;
}
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 57efaf99b8b..753da8544ea 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -65,6 +65,24 @@ typedef struct ViewportTempTexture {
GPUTexture *texture;
} ViewportTempTexture;
+/* Struct storing a viewport specific GPUBatch.
+ * The end-goal is to have a single batch shared across viewport and use a model matrix to place
+ * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */
+struct GPUViewportBatch {
+ GPUBatch *batch;
+ struct {
+ rctf rect_pos;
+ rctf rect_uv;
+ } last_used_parameters;
+};
+
+static struct {
+ GPUVertFormat format;
+ struct {
+ uint pos, tex_coord;
+ } attr_id;
+} g_viewport = {{0}};
+
struct GPUViewport {
int size[2];
int flag;
@@ -93,10 +111,12 @@ struct GPUViewport {
/* Color management. */
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
+ CurveMapping *orig_curve_mapping;
float dither;
/* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the
* moment. The end goal would be to let the GPUViewport do the color management. */
bool do_color_management;
+ struct GPUViewportBatch batch;
};
enum {
@@ -197,18 +217,6 @@ static void gpu_viewport_framebuffer_view_set(GPUViewport *viewport, int view)
GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
});
- if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
- GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb,
- {
- GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(dtxl->color),
- GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
- });
- }
- else {
- dfbl->stereo_comp_fb = NULL;
- }
-
viewport->active_view = view;
}
@@ -355,7 +363,7 @@ GPUTexture *GPU_viewport_texture_pool_query(
{
GPUTexture *tex;
- for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) {
if ((GPU_texture_format(tmp_tex->texture) == format) &&
(GPU_texture_width(tmp_tex->texture) == width) &&
(GPU_texture_height(tmp_tex->texture) == height)) {
@@ -374,12 +382,10 @@ GPUTexture *GPU_viewport_texture_pool_query(
}
tex = GPU_texture_create_2d(width, height, 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;
@@ -412,7 +418,7 @@ static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport)
static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
{
- for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) {
GPU_texture_free(tmp_tex->texture);
}
@@ -472,9 +478,6 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport)
ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_only_fb, NULL);
- if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
- ok = ok && GPU_framebuffer_check_valid(dfbl->stereo_comp_fb, NULL);
- }
cleanup:
if (!ok) {
GPU_viewport_free(viewport);
@@ -552,8 +555,43 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
ColorManagedDisplaySettings *display_settings,
float dither)
{
- memcpy(&viewport->view_settings, view_settings, sizeof(*view_settings));
- memcpy(&viewport->display_settings, display_settings, sizeof(*display_settings));
+ /**
+ * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene
+ * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching
+ * (which is based on #CurveMap pointer address) cannot operate correctly and it will create
+ * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy
+ * if needed to avoid unneeded cache invalidation.
+ */
+ if (view_settings->curve_mapping) {
+ if (viewport->view_settings.curve_mapping) {
+ if (view_settings->curve_mapping->changed_timestamp !=
+ viewport->view_settings.curve_mapping->changed_timestamp) {
+ BKE_color_managed_view_settings_free(&viewport->view_settings);
+ }
+ }
+ }
+
+ if (viewport->orig_curve_mapping != view_settings->curve_mapping) {
+ viewport->orig_curve_mapping = view_settings->curve_mapping;
+ BKE_color_managed_view_settings_free(&viewport->view_settings);
+ }
+ /* Don't copy the curve mapping already. */
+ CurveMapping *tmp_curve_mapping = view_settings->curve_mapping;
+ CurveMapping *tmp_curve_mapping_vp = viewport->view_settings.curve_mapping;
+ view_settings->curve_mapping = NULL;
+ viewport->view_settings.curve_mapping = NULL;
+
+ BKE_color_managed_view_settings_copy(&viewport->view_settings, view_settings);
+ /* Restore. */
+ view_settings->curve_mapping = tmp_curve_mapping;
+ viewport->view_settings.curve_mapping = tmp_curve_mapping_vp;
+ /* Only copy curvemapping if needed. Avoid uneeded OCIO cache miss. */
+ if (tmp_curve_mapping && viewport->view_settings.curve_mapping == NULL) {
+ BKE_color_managed_view_settings_free(&viewport->view_settings);
+ viewport->view_settings.curve_mapping = BKE_curvemapping_copy(tmp_curve_mapping);
+ }
+
+ BKE_color_managed_display_settings_copy(&viewport->display_settings, display_settings);
viewport->dither = dither;
viewport->do_color_management = true;
}
@@ -570,6 +608,14 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo
DefaultTextureList *dtxl = viewport->txl;
DefaultFramebufferList *dfbl = viewport->fbl;
+ /* The composite framebuffer object needs to be created in the window context. */
+ GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
+ });
+
GPUVertFormat *vert_format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_framebuffer_bind(dfbl->stereo_comp_fb);
@@ -625,6 +671,76 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo
GPU_framebuffer_restore();
}
+/* -------------------------------------------------------------------- */
+/** \name Viewport Batches
+ * \{ */
+
+static GPUVertFormat *gpu_viewport_batch_format(void)
+{
+ if (g_viewport.format.attr_len == 0) {
+ GPUVertFormat *format = &g_viewport.format;
+ g_viewport.attr_id.pos = GPU_vertformat_attr_add(
+ format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ g_viewport.attr_id.tex_coord = GPU_vertformat_attr_add(
+ format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+ return &g_viewport.format;
+}
+
+static GPUBatch *gpu_viewport_batch_create(const rctf *rect_pos, const rctf *rect_uv)
+{
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(gpu_viewport_batch_format());
+ const uint vbo_len = 4;
+ GPU_vertbuf_data_alloc(vbo, vbo_len);
+
+ GPUVertBufRaw pos_step, tex_coord_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.pos, &pos_step);
+ GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.tex_coord, &tex_coord_step);
+
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymin);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymax);
+ copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymax);
+
+ return GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
+}
+
+static GPUBatch *gpu_viewport_batch_get(GPUViewport *viewport,
+ const rctf *rect_pos,
+ const rctf *rect_uv)
+{
+ const float compare_limit = 0.0001f;
+ const bool parameters_changed =
+ (!BLI_rctf_compare(
+ &viewport->batch.last_used_parameters.rect_pos, rect_pos, compare_limit) ||
+ !BLI_rctf_compare(&viewport->batch.last_used_parameters.rect_uv, rect_uv, compare_limit));
+
+ if (viewport->batch.batch && parameters_changed) {
+ GPU_batch_discard(viewport->batch.batch);
+ viewport->batch.batch = NULL;
+ }
+
+ if (!viewport->batch.batch) {
+ viewport->batch.batch = gpu_viewport_batch_create(rect_pos, rect_uv);
+ viewport->batch.last_used_parameters.rect_pos = *rect_pos;
+ viewport->batch.last_used_parameters.rect_uv = *rect_uv;
+ }
+ return viewport->batch.batch;
+}
+
+static void gpu_viewport_batch_free(GPUViewport *viewport)
+{
+ if (viewport->batch.batch) {
+ GPU_batch_discard(viewport->batch.batch);
+ viewport->batch.batch = NULL;
+ }
+}
+
+/** \} */
static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
const rctf *rect_pos,
@@ -635,13 +751,17 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
GPUTexture *color = dtxl->color;
GPUTexture *color_overlay = dtxl->color_overlay;
- GPUVertFormat *vert_format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
bool use_ocio = false;
if (viewport->do_color_management && display_colorspace) {
+ /* During the binding process the last used VertexFormat is tested and can assert as it is not
+ * valid. By calling the `immVertexFormat` the last used VertexFormat is reset and the assert
+ * does not happen. This solves a chicken and egg problem when using GPUBatches. GPUBatches
+ * contain the correct vertex format, but can only bind after the shader is bound.
+ *
+ * Image/UV editor still uses imm, after that has been changed we could move this fix to the
+ * OCIO. */
+ immVertexFormat();
use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(&viewport->view_settings,
&viewport->display_settings,
NULL,
@@ -650,38 +770,26 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
true);
}
- if (!use_ocio) {
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
- immUniform1i("display_transform", display_colorspace);
- immUniform1i("image_texture", 0);
- immUniform1i("overlays_texture", 1);
+ GPUBatch *batch = gpu_viewport_batch_get(viewport, rect_pos, rect_uv);
+ if (use_ocio) {
+ GPU_batch_program_set_imm_shader(batch);
+ }
+ else {
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
+ GPU_batch_uniform_1i(batch, "display_transform", display_colorspace);
+ GPU_batch_uniform_1i(batch, "image_texture", 0);
+ GPU_batch_uniform_1i(batch, "overlays_texture", 1);
}
GPU_texture_bind(color, 0);
GPU_texture_bind(color_overlay, 1);
-
- immBegin(GPU_PRIM_TRI_STRIP, 4);
-
- immAttr2f(texco, rect_uv->xmin, rect_uv->ymin);
- immVertex2f(pos, rect_pos->xmin, rect_pos->ymin);
- immAttr2f(texco, rect_uv->xmax, rect_uv->ymin);
- immVertex2f(pos, rect_pos->xmax, rect_pos->ymin);
- immAttr2f(texco, rect_uv->xmin, rect_uv->ymax);
- immVertex2f(pos, rect_pos->xmin, rect_pos->ymax);
- immAttr2f(texco, rect_uv->xmax, rect_uv->ymax);
- immVertex2f(pos, rect_pos->xmax, rect_pos->ymax);
-
- immEnd();
-
+ GPU_batch_draw(batch);
GPU_texture_unbind(color);
GPU_texture_unbind(color_overlay);
if (use_ocio) {
IMB_colormanagement_finish_glsl_draw();
}
- else {
- immUnbindProgram();
- }
}
/**
@@ -745,8 +853,8 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
* Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
* color transform to display space.
*
- * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
- * inversed axis coordinates (upside down or sideways).
+ * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done
+ * with inversed axis coordinates (upside down or sideways).
*/
void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
{
@@ -923,5 +1031,8 @@ void GPU_viewport_free(GPUViewport *viewport)
DRW_instance_data_list_free(viewport->idatalist);
MEM_freeN(viewport->idatalist);
+ BKE_color_managed_view_settings_free(&viewport->view_settings);
+ gpu_viewport_batch_free(viewport);
+
MEM_freeN(viewport);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl
deleted file mode 100644
index 181b1bf3fad..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl
+++ /dev/null
@@ -1,18 +0,0 @@
-
-noperspective in vec4 finalColor;
-out vec4 fragColor;
-
-/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
-#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
-const vec4 dither_mat4x4[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)),
- vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
- vec4(P(3.0), P(11.0), P(1.0), P(9.0)),
- vec4(P(15.0), P(7.0), P(13.0), P(5.0)));
-
-void main()
-{
- ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4;
- ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2;
- float dither_noise = dither_mat4x4[tx1.x][tx1.y];
- fragColor = finalColor + dither_noise;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
index 4f275c5b220..1333c00682c 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
@@ -5,4 +5,5 @@ out vec4 fragColor;
void main()
{
fragColor = finalColor;
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
}
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
index 18f58d52f32..bdc87baf924 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
@@ -35,4 +35,6 @@ void main()
if (butCo > 0.0) {
fragColor.a = 1.0;
}
+
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
}
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
index 0b2bc08944e..d7cc851556b 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -12,42 +12,15 @@
/* 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));
+const vec2 cornervec[9] = vec2[9](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));
/* 4bits for jitter id */
#define JIT_OFS 6u
@@ -189,26 +162,26 @@ 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;
+ vec2 v = cornervec[vofs];
/* Scale by corner radius */
v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
-
- /* Position to corner */
+ /* Flip in the right direction and osition to corner */
vec4 rct = (is_inner) ? recti : rect;
if (cflag == BOTTOM_LEFT) {
v += rct.xz;
}
else if (cflag == BOTTOM_RIGHT) {
+ v = vec2(-v.y, v.x);
v += rct.yz;
}
else if (cflag == TOP_RIGHT) {
+ v = -v;
v += rct.yw;
}
else /* (cflag == TOP_LEFT) */ {
+ v = vec2(v.y, -v.x);
v += rct.xw;
}
@@ -238,7 +211,7 @@ vec2 do_widget(void)
}
bool is_emboss = (vflag & EMBOSS_FLAG) != 0u;
- v.y -= (is_emboss) ? 1.0f : 0.0;
+ v.y -= (is_emboss) ? (recti.z - rect.z) : 0.0;
return v;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
deleted file mode 100644
index 7fa571343a2..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
+++ /dev/null
@@ -1,22 +0,0 @@
-
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat3 NormalMatrix;
-
-in vec3 pos;
-in vec3 nor;
-in vec4 color;
-
-#ifdef USE_FLAT_NORMAL
-flat out vec3 normal;
-flat out vec4 finalColor;
-#else
-out vec3 normal;
-out vec4 finalColor;
-#endif
-
-void main()
-{
- normal = normalize(NormalMatrix * nor);
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- finalColor = color;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_polyline_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_polyline_frag.glsl
new file mode 100644
index 00000000000..9c6b109d659
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_polyline_frag.glsl
@@ -0,0 +1,24 @@
+
+uniform float lineWidth;
+
+in vec4 finalColor;
+noperspective in float smoothline;
+#ifdef CLIP
+in float clip;
+#endif
+
+out vec4 fragColor;
+
+#define SMOOTH_WIDTH 1.0
+
+void main()
+{
+#ifdef CLIP
+ if (clip < 0.0) {
+ discard;
+ }
+#endif
+ fragColor = finalColor;
+ fragColor.a *= clamp((lineWidth + SMOOTH_WIDTH) * 0.5 - abs(smoothline), 0.0, 1.0);
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_polyline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_polyline_geom.glsl
new file mode 100644
index 00000000000..b28205b349e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_polyline_geom.glsl
@@ -0,0 +1,68 @@
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+uniform vec4 color;
+uniform vec2 viewportSize;
+uniform float lineWidth;
+
+#if !defined(UNIFORM)
+in vec4 finalColor_g[];
+#endif
+
+#ifdef CLIP
+in float clip_g[];
+out float clip;
+#endif
+
+out vec4 finalColor;
+noperspective out float smoothline;
+
+#define SMOOTH_WIDTH 1.0
+
+void do_vertex(const int i, vec2 ofs)
+{
+#if defined(UNIFORM)
+ finalColor = color;
+
+#elif defined(FLAT)
+ finalColor = finalColor_g[0];
+
+#elif defined(SMOOTH)
+ finalColor = finalColor_g[i];
+#endif
+
+#ifdef CLIP
+ clip = clip_g[i];
+#endif
+
+ smoothline = (lineWidth + SMOOTH_WIDTH) * 0.5;
+ gl_Position = gl_in[i].gl_Position;
+ gl_Position.xy += ofs * gl_Position.w;
+ EmitVertex();
+
+ smoothline = -(lineWidth + SMOOTH_WIDTH) * 0.5;
+ gl_Position = gl_in[i].gl_Position;
+ gl_Position.xy -= ofs * gl_Position.w;
+ EmitVertex();
+}
+
+void main(void)
+{
+ vec2 p0 = gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w;
+ vec2 p1 = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w;
+ vec2 e = normalize((p1 - p0) * viewportSize.xy);
+#if 0 /* Hard turn when line direction changes quadrant. */
+ e = abs(e);
+ vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
+#else /* Use perpendicular direction. */
+ vec2 ofs = vec2(-e.y, e.x);
+#endif
+ ofs /= viewportSize.xy;
+ ofs *= lineWidth + SMOOTH_WIDTH;
+
+ do_vertex(0, ofs);
+ do_vertex(1, ofs);
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert.glsl
new file mode 100644
index 00000000000..28aa2a4ccc6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert.glsl
@@ -0,0 +1,28 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+uniform vec4 ClipPlane;
+
+in vec3 pos;
+
+#if !defined(UNIFORM)
+in vec4 color;
+
+out vec4 finalColor_g;
+#endif
+
+#ifdef CLIP
+out float clip_g;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+#if !defined(UNIFORM)
+ finalColor_g = color;
+#endif
+
+#ifdef CLIP
+ clip_g = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane);
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
index 7bd44ba9b88..3a2d96c9929 100644
--- a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
@@ -5,4 +5,5 @@ out vec4 fragColor;
void main()
{
fragColor = finalColor;
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl
new file mode 100644
index 00000000000..aae659516bb
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl
@@ -0,0 +1,16 @@
+
+/* Undefine the macro that avoids compilation errors. */
+#undef blender_srgb_to_framebuffer_space
+
+uniform bool srgbTarget = false;
+
+vec4 blender_srgb_to_framebuffer_space(vec4 color)
+{
+ if (srgbTarget) {
+ vec3 c = max(color.rgb, vec3(0.0));
+ vec3 c1 = c * (1.0 / 12.92);
+ vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));
+ color.rgb = mix(c1, c2, step(vec3(0.04045), c));
+ }
+ return color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
index 6c214534812..99d8b6ab685 100644
--- a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
@@ -5,4 +5,5 @@ out vec4 fragColor;
void main()
{
fragColor = finalColor;
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
}
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
deleted file mode 100644
index 0f2749362b9..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-
-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_depth_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
deleted file mode 100644
index 017b21076c8..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
+++ /dev/null
@@ -1,16 +0,0 @@
-
-in vec2 texCoord_interp;
-out vec4 fragColor;
-
-uniform float znear;
-uniform float zfar;
-uniform sampler2D image;
-
-void main()
-{
- float depth = texture(image, texCoord_interp).r;
-
- /* normalize */
- fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear))));
- fragColor.a = 1.0f;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
deleted file mode 100644
index ca425374a1b..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
+++ /dev/null
@@ -1,119 +0,0 @@
-
-uniform sampler2DMS depthMulti;
-uniform sampler2DMS colorMulti;
-
-out vec4 fragColor;
-
-#if SAMPLES > 16
-# error "Too many samples"
-#endif
-
-void main()
-{
- ivec2 texel = ivec2(gl_FragCoord.xy);
-
- bvec4 b1, b2, b3, b4;
- vec4 w1, w2, w3, w4;
- vec4 d1, d2, d3, d4;
- vec4 c1, c2, c3, c4, c5, c6, c7, c8;
- vec4 c9, c10, c11, c12, c13, c14, c15, c16;
- d1 = d2 = d3 = d4 = vec4(0.5);
- w1 = w2 = w3 = w4 = vec4(0.0);
- c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0);
- c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0);
-
-#ifdef USE_DEPTH
- /* Depth */
- d1.x = texelFetch(depthMulti, texel, 0).r;
- d1.y = texelFetch(depthMulti, texel, 1).r;
-# if SAMPLES > 2
- d1.z = texelFetch(depthMulti, texel, 2).r;
- d1.w = texelFetch(depthMulti, texel, 3).r;
-# endif
-# if SAMPLES > 4
- d2.x = texelFetch(depthMulti, texel, 4).r;
- d2.y = texelFetch(depthMulti, texel, 5).r;
- d2.z = texelFetch(depthMulti, texel, 6).r;
- d2.w = texelFetch(depthMulti, texel, 7).r;
-# endif
-# if SAMPLES > 8
- d3.x = texelFetch(depthMulti, texel, 8).r;
- d3.y = texelFetch(depthMulti, texel, 9).r;
- d3.z = texelFetch(depthMulti, texel, 10).r;
- d3.w = texelFetch(depthMulti, texel, 11).r;
- d4.x = texelFetch(depthMulti, texel, 12).r;
- d4.y = texelFetch(depthMulti, texel, 13).r;
- d4.z = texelFetch(depthMulti, texel, 14).r;
- d4.w = texelFetch(depthMulti, texel, 15).r;
-# endif
-#endif
-
- /* COLOR */
- b1 = notEqual(d1, vec4(1.0));
- if (any(b1)) {
- c1 = texelFetch(colorMulti, texel, 0);
- c2 = texelFetch(colorMulti, texel, 1);
-#if SAMPLES > 2
- c3 = texelFetch(colorMulti, texel, 2);
- c4 = texelFetch(colorMulti, texel, 3);
-#endif
- w1 = vec4(b1);
- }
-#if SAMPLES > 4
- b2 = notEqual(d2, vec4(1.0));
- if (any(b2)) {
- c5 = texelFetch(colorMulti, texel, 4);
- c6 = texelFetch(colorMulti, texel, 5);
- c7 = texelFetch(colorMulti, texel, 6);
- c8 = texelFetch(colorMulti, texel, 7);
- w2 = vec4(b2);
- }
-#endif
-#if SAMPLES > 8
- b3 = notEqual(d3, vec4(1.0));
- if (any(b3)) {
- c9 = texelFetch(colorMulti, texel, 8);
- c10 = texelFetch(colorMulti, texel, 9);
- c11 = texelFetch(colorMulti, texel, 10);
- c12 = texelFetch(colorMulti, texel, 11);
- w3 = vec4(b3);
- }
- b4 = notEqual(d4, vec4(1.0));
- if (any(b4)) {
- c13 = texelFetch(colorMulti, texel, 12);
- c14 = texelFetch(colorMulti, texel, 13);
- c15 = texelFetch(colorMulti, texel, 14);
- c16 = texelFetch(colorMulti, texel, 15);
- w4 = vec4(b4);
- }
-#endif
-
-#ifdef USE_DEPTH
-# if SAMPLES > 8
- d1 = min(d1, min(d3, d4));
-# endif
-# if SAMPLES > 4
- d1 = min(d1, d2);
- d1 = min(d1, d2);
-# endif
-# if SAMPLES > 2
- d1.xy = min(d1.xy, d1.zw);
-# endif
- gl_FragDepth = min(d1.x, d1.y);
-#endif
-
- c1 = c1 + c2;
-#if SAMPLES > 2
- c1 += c3 + c4;
-#endif
-#if SAMPLES > 4
- c1 += c5 + c6 + c7 + c8;
-#endif
-#if SAMPLES > 8
- c1 += c9 + c10 + c11 + c12 + c13 + c14 + c15 + c16;
-#endif
-
- const float inv_samples = 1.0 / float(SAMPLES);
-
- fragColor = c1 * inv_samples;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
deleted file mode 100644
index 2ed99be2bcf..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-uniform vec3 light;
-uniform float alpha;
-uniform float global;
-
-in vec3 normal;
-in vec4 finalColor;
-out vec4 fragColor;
-
-void main()
-{
- fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light)));
- fragColor.a = alpha;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
deleted file mode 100644
index 738b0d84e51..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
+++ /dev/null
@@ -1,16 +0,0 @@
-
-uniform vec3 light;
-
-#ifdef USE_FLAT_NORMAL
-flat in vec3 normal;
-flat in vec4 finalColor;
-#else
-in vec3 normal;
-in vec4 finalColor;
-#endif
-out vec4 fragColor;
-
-void main()
-{
- fragColor = finalColor * max(0.0, dot(normalize(normal), light));
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
index cfa82572e87..2033401db67 100644
--- a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
@@ -17,8 +17,5 @@ void main()
#else
fragColor = color;
#endif
-
-#if defined(USE_BACKGROUND)
- gl_FragDepth = 1.0;
-#endif
+ fragColor = blender_srgb_to_framebuffer_space(fragColor);
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
index 701b07b4aae..f25691c1a83 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
@@ -1,111 +1,115 @@
/* The fractal_noise functions are all exactly the same except for the input type. */
-float fractal_noise(float p, float octaves)
+float fractal_noise(float p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
+ float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
- amp *= 0.5;
+ maxamp += amp;
+ amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ sum /= maxamp;
+ sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- return sum;
+ return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
-float fractal_noise(vec2 p, float octaves)
+float fractal_noise(vec2 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
+ float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
- amp *= 0.5;
+ maxamp += amp;
+ amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ sum /= maxamp;
+ sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- return sum;
+ return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
-float fractal_noise(vec3 p, float octaves)
+float fractal_noise(vec3 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
+ float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
- amp *= 0.5;
+ maxamp += amp;
+ amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ sum /= maxamp;
+ sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- return sum;
+ return sum / maxamp;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
-float fractal_noise(vec4 p, float octaves)
+float fractal_noise(vec4 p, float octaves, float roughness)
{
float fscale = 1.0;
float amp = 1.0;
+ float maxamp = 0.0;
float sum = 0.0;
octaves = clamp(octaves, 0.0, 16.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
sum += t * amp;
- amp *= 0.5;
+ maxamp += amp;
+ amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float sum2 = sum + t * amp;
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ sum /= maxamp;
+ sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
}
else {
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- return sum;
+ return sum / maxamp;
}
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
index 62f76d46088..4cb00c15b78 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
@@ -1,8 +1,16 @@
-void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
+void node_output_material(
+ Closure surface, Closure volume, vec3 displacement, float alpha_threshold, out Closure result)
{
#ifdef VOLUMETRICS
result = volume;
#else
result = surface;
+# if defined(USE_ALPHA_HASH)
+ /* Alpha clip emulation. */
+ if (alpha_threshold >= 0.0) {
+ float alpha = saturate(1.0 - avg(result.transmittance));
+ result.transmittance = vec3(step(alpha, alpha_threshold));
+ }
+# endif
#endif
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
index 9bd36f8a757..20a65f23c05 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
@@ -15,16 +15,11 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
#endif
}
-void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv)
+void node_tex_environment_equirectangular(vec3 co, out vec3 uv)
{
vec3 nco = normalize(co);
uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
-
- /* Fix pole bleeding */
- float half_height = clamp_size / float(textureSize(ima, 0).y);
- uv.y = clamp(uv.y, half_height, 1.0 - half_height);
- uv.z = 0.0;
}
void node_tex_environment_mirror_ball(vec3 co, out vec3 uv)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
index c39bec8ac64..df949f7358b 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
@@ -54,19 +54,6 @@ void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alp
alpha = color.a;
}
-void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- color = safe_color(textureLod(ima, co.xy, 0.0));
- alpha = color.a;
-}
-
-void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy);
- color = safe_color(texelFetch(ima, pix, 0));
- alpha = color.a;
-}
-
/** \param f: Signed distance to texel center. */
void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
{
@@ -79,8 +66,7 @@ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2
w2 = 1.0 - w0 - w1 - w3;
}
-void node_tex_image_cubic_ex(
- vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha)
+void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
vec2 tex_size = vec2(textureSize(ima, 0).xy);
@@ -101,9 +87,6 @@ void node_tex_image_cubic_ex(
final_co.xy = tc - 1.0 + f0;
final_co.zw = tc + 1.0 + f1;
- if (do_extend == 1.0) {
- final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
- }
final_co /= tex_size.xyxy;
color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y;
@@ -136,22 +119,6 @@ void node_tex_image_cubic_ex(
alpha = color.a;
}
-void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
-void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
-}
-
-void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- /* use cubic for now */
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
void tex_box_sample_linear(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -175,32 +142,6 @@ void tex_box_sample_linear(
color3 = texture(ima, uv);
}
-void tex_box_sample_nearest(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- /* X projection */
- vec2 uv = texco.yz;
- if (N.x < 0.0) {
- uv.x = 1.0 - uv.x;
- }
- ivec2 pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color1 = texelFetch(ima, pix, 0);
- /* Y projection */
- uv = texco.xz;
- if (N.y > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color2 = texelFetch(ima, pix, 0);
- /* Z projection */
- uv = texco.yx;
- if (N.z > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color3 = texelFetch(ima, pix, 0);
-}
-
void tex_box_sample_cubic(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -210,36 +151,23 @@ void tex_box_sample_cubic(
if (N.x < 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color1, alpha);
/* Y projection */
uv = texco.xz;
if (N.y > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color2, alpha);
/* Z projection */
uv = texco.yx;
if (N.z > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color3, alpha);
}
-void tex_box_sample_smart(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- tex_box_sample_cubic(texco, N, ima, color1, color2, color3);
-}
-
-void node_tex_image_box(vec3 texco,
- vec3 N,
- vec4 color1,
- vec4 color2,
- vec4 color3,
- sampler2D ima,
- float blend,
- out vec4 color,
- out float alpha)
+void tex_box_blend(
+ vec3 N, vec4 color1, vec4 color2, vec4 color3, float blend, out vec4 color, out float alpha)
{
/* project from direction vector to barycentric coordinates in triangles */
N = abs(N);
@@ -284,70 +212,6 @@ void node_tex_image_box(vec3 texco,
alpha = color.a;
}
-void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
- vec2 minco = min(co.xy, 1.0 - co.xy);
- minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
- float fac = minco.x * minco.y;
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec4 minco = vec4(co.xy, 1.0 - co.xy);
- color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
- alpha = color.a;
-}
-
-void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
-
- co.xy *= tex_size;
- /* texel center */
- vec2 tc = floor(co.xy - 0.5) + 0.5;
- vec2 w0, w1, w2, w3;
- cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
-
- /* TODO Optimize this part. I'm sure there is a smarter way to do that.
- * Could do that when sampling? */
-#define CLIP_CUBIC_SAMPLE(samp, size) \
- (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
- ivec2 itex_size = textureSize(ima, 0).xy;
- float fac;
- fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y;
-#undef CLIP_CUBIC_SAMPLE
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- tex_clip_cubic(co, ima, icolor, color, alpha);
-}
-
void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
{
color = vec4(0.0);
@@ -389,20 +253,6 @@ void node_tex_tile_linear(
alpha = color.a;
}
-void node_tex_tile_nearest(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- if (node_tex_tile_lookup(co, ima, map)) {
- ivec3 pix = ivec3(fract(co.xy) * textureSize(ima, 0).xy, co.z);
- color = safe_color(texelFetch(ima, pix, 0));
- }
- else {
- color = vec4(1.0, 0.0, 1.0, 1.0);
- }
-
- alpha = color.a;
-}
-
void node_tex_tile_cubic(
vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
{
@@ -437,9 +287,3 @@ void node_tex_tile_cubic(
alpha = color.a;
}
-
-void node_tex_tile_smart(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- node_tex_tile_cubic(co, ima, map, color, alpha);
-}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
index 6aeb23b1f99..d8d9ecdf287 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
@@ -32,23 +32,35 @@ vec4 random_vec4_offset(float seed)
100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0);
}
-void node_noise_texture_1d(
- vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+void node_noise_texture_1d(vec3 co,
+ float w,
+ float scale,
+ float detail,
+ float roughness,
+ float distortion,
+ out float value,
+ out vec4 color)
{
float p = w * scale;
if (distortion != 0.0) {
p += snoise(p + random_float_offset(0.0)) * distortion;
}
- value = fractal_noise(p, detail);
+ value = fractal_noise(p, detail, roughness);
color = vec4(value,
- fractal_noise(p + random_float_offset(1.0), detail),
- fractal_noise(p + random_float_offset(2.0), detail),
+ fractal_noise(p + random_float_offset(1.0), detail, roughness),
+ fractal_noise(p + random_float_offset(2.0), detail, roughness),
1.0);
}
-void node_noise_texture_2d(
- vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+void node_noise_texture_2d(vec3 co,
+ float w,
+ float scale,
+ float detail,
+ float roughness,
+ float distortion,
+ out float value,
+ out vec4 color)
{
vec2 p = co.xy * scale;
if (distortion != 0.0) {
@@ -56,15 +68,21 @@ void node_noise_texture_2d(
snoise(p + random_vec2_offset(1.0)) * distortion);
}
- value = fractal_noise(p, detail);
+ value = fractal_noise(p, detail, roughness);
color = vec4(value,
- fractal_noise(p + random_vec2_offset(2.0), detail),
- fractal_noise(p + random_vec2_offset(3.0), detail),
+ fractal_noise(p + random_vec2_offset(2.0), detail, roughness),
+ fractal_noise(p + random_vec2_offset(3.0), detail, roughness),
1.0);
}
-void node_noise_texture_3d(
- vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+void node_noise_texture_3d(vec3 co,
+ float w,
+ float scale,
+ float detail,
+ float roughness,
+ float distortion,
+ out float value,
+ out vec4 color)
{
vec3 p = co * scale;
if (distortion != 0.0) {
@@ -73,15 +91,21 @@ void node_noise_texture_3d(
snoise(p + random_vec3_offset(2.0)) * distortion);
}
- value = fractal_noise(p, detail);
+ value = fractal_noise(p, detail, roughness);
color = vec4(value,
- fractal_noise(p + random_vec3_offset(3.0), detail),
- fractal_noise(p + random_vec3_offset(4.0), detail),
+ fractal_noise(p + random_vec3_offset(3.0), detail, roughness),
+ fractal_noise(p + random_vec3_offset(4.0), detail, roughness),
1.0);
}
-void node_noise_texture_4d(
- vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+void node_noise_texture_4d(vec3 co,
+ float w,
+ float scale,
+ float detail,
+ float roughness,
+ float distortion,
+ out float value,
+ out vec4 color)
{
vec4 p = vec4(co, w) * scale;
if (distortion != 0.0) {
@@ -91,9 +115,9 @@ void node_noise_texture_4d(
snoise(p + random_vec4_offset(3.0)) * distortion);
}
- value = fractal_noise(p, detail);
+ value = fractal_noise(p, detail, roughness);
color = vec4(value,
- fractal_noise(p + random_vec4_offset(4.0), detail),
- fractal_noise(p + random_vec4_offset(5.0), detail),
+ fractal_noise(p + random_vec4_offset(4.0), detail, roughness),
+ fractal_noise(p + random_vec4_offset(5.0), detail, roughness),
1.0);
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl
index c72f9717af3..070f42a5e30 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl
@@ -2,6 +2,7 @@ float calc_wave(vec3 p,
float distortion,
float detail,
float detail_scale,
+ float detail_roughness,
float phase,
int wave_type,
int bands_dir,
@@ -46,7 +47,7 @@ float calc_wave(vec3 p,
n += phase;
if (distortion != 0.0) {
- n += distortion * (fractal_noise(p * detail_scale, detail) * 2.0 - 1.0);
+ n += distortion * (fractal_noise(p * detail_scale, detail, detail_roughness) * 2.0 - 1.0);
}
if (wave_profile == 0) { /* profile sin */
@@ -67,6 +68,7 @@ void node_tex_wave(vec3 co,
float distortion,
float detail,
float detail_scale,
+ float detail_roughness,
float phase,
float wave_type,
float bands_dir,
@@ -80,6 +82,7 @@ void node_tex_wave(vec3 co,
distortion,
detail,
detail_scale,
+ detail_roughness,
phase,
int(wave_type),
int(bands_dir),