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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_attr_binding.cc13
-rw-r--r--source/blender/gpu/intern/gpu_attr_binding_private.h6
-rw-r--r--source/blender/gpu/intern/gpu_backend.hh11
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.hh5
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c2
-rw-r--r--source/blender/gpu/intern/gpu_context_private.hh3
-rw-r--r--source/blender/gpu/intern/gpu_drawlist_private.hh4
-rw-r--r--source/blender/gpu/intern/gpu_extensions.cc21
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc36
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc84
-rw-r--r--source/blender/gpu/intern/gpu_material.c37
-rw-r--r--source/blender/gpu/intern/gpu_matrix.cc17
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c8
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c19
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c39
-rw-r--r--source/blender/gpu/intern/gpu_shader.cc97
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.cc532
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.hh229
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.hh16
-rw-r--r--source/blender/gpu/intern/gpu_state.cc65
-rw-r--r--source/blender/gpu/intern/gpu_state_private.hh25
-rw-r--r--source/blender/gpu/intern/gpu_texture.cc11
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer.cc (renamed from source/blender/gpu/intern/gpu_uniformbuffer.cc)192
-rw-r--r--source/blender/gpu/intern/gpu_uniform_buffer_private.hh69
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc2
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c6
27 files changed, 712 insertions, 839 deletions
diff --git a/source/blender/gpu/intern/gpu_attr_binding.cc b/source/blender/gpu/intern/gpu_attr_binding.cc
index 6cb60884620..2a48107e190 100644
--- a/source/blender/gpu/intern/gpu_attr_binding.cc
+++ b/source/blender/gpu/intern/gpu_attr_binding.cc
@@ -61,9 +61,7 @@ static void write_attr_location(GPUAttrBinding *binding, uint a_idx, uint locati
binding->enabled_bits |= 1 << a_idx;
}
-void get_attr_locations(const GPUVertFormat *format,
- GPUAttrBinding *binding,
- const GPUShaderInterface *shaderface)
+void get_attr_locations(const GPUVertFormat *format, GPUAttrBinding *binding, GPUShader *shader)
{
AttrBinding_clear(binding);
@@ -71,13 +69,12 @@ void get_attr_locations(const GPUVertFormat *format,
const GPUVertAttr *a = &format->attrs[a_idx];
for (uint n_idx = 0; n_idx < a->name_len; n_idx++) {
const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
- const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, name);
-#if TRUST_NO_ONE
- assert(input != NULL);
+ int loc = GPU_shader_get_attribute(shader, name);
/* TODO: make this a recoverable runtime error?
* indicates mismatch between vertex format and program. */
-#endif
- write_attr_location(binding, a_idx, input->location);
+ BLI_assert(loc != -1);
+
+ write_attr_location(binding, a_idx, loc);
}
}
}
diff --git a/source/blender/gpu/intern/gpu_attr_binding_private.h b/source/blender/gpu/intern/gpu_attr_binding_private.h
index 4d359343c38..cd67a51a822 100644
--- a/source/blender/gpu/intern/gpu_attr_binding_private.h
+++ b/source/blender/gpu/intern/gpu_attr_binding_private.h
@@ -25,8 +25,8 @@
#pragma once
-#include "GPU_shader_interface.h"
#include "GPU_vertex_format.h"
+#include "gpu_shader_interface.hh"
#ifdef __cplusplus
extern "C" {
@@ -35,9 +35,7 @@ extern "C" {
/* TODO(fclem) remove, use shaderface directly. */
void AttrBinding_clear(GPUAttrBinding *binding);
-void get_attr_locations(const GPUVertFormat *format,
- GPUAttrBinding *binding,
- const GPUShaderInterface *shaderface);
+void get_attr_locations(const GPUVertFormat *format, GPUAttrBinding *binding, GPUShader *shader);
uint read_attr_location(const GPUAttrBinding *binding, uint a_idx);
#ifdef __cplusplus
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index 6ab0e32a754..f63f3cead2b 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -25,14 +25,16 @@
#pragma once
-#include "gpu_batch_private.hh"
-#include "gpu_context_private.hh"
-#include "gpu_drawlist_private.hh"
-#include "gpu_shader_private.hh"
+struct GPUContext;
namespace blender {
namespace gpu {
+class Batch;
+class DrawList;
+class Shader;
+class UniformBuf;
+
class GPUBackend {
public:
virtual ~GPUBackend(){};
@@ -46,6 +48,7 @@ class GPUBackend {
// virtual FrameBuffer *framebuffer_alloc(void) = 0;
virtual Shader *shader_alloc(const char *name) = 0;
// virtual Texture *texture_alloc(void) = 0;
+ virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
};
} // namespace gpu
diff --git a/source/blender/gpu/intern/gpu_batch_private.hh b/source/blender/gpu/intern/gpu_batch_private.hh
index 3a8044efc1d..c0444647fe1 100644
--- a/source/blender/gpu/intern/gpu_batch_private.hh
+++ b/source/blender/gpu/intern/gpu_batch_private.hh
@@ -28,11 +28,14 @@
#include "GPU_batch.h"
#include "GPU_context.h"
-#include "GPU_shader_interface.h"
namespace blender {
namespace gpu {
+/**
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ * NOTE: Extends GPUBatch as we still needs to expose some of the internals to the outside C code.
+ **/
class Batch : public GPUBatch {
public:
Batch(){};
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index b051d4fe59a..1629584e841 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -43,7 +43,7 @@
#include "GPU_extensions.h"
#include "GPU_material.h"
#include "GPU_shader.h"
-#include "GPU_uniformbuffer.h"
+#include "GPU_uniform_buffer.h"
#include "GPU_vertex_format.h"
#include "BLI_sys_types.h" /* for intptr_t support */
diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh
index b774d6b0995..e8c9c976e9a 100644
--- a/source/blender/gpu/intern/gpu_context_private.hh
+++ b/source/blender/gpu/intern/gpu_context_private.hh
@@ -29,6 +29,7 @@
#include "GPU_context.h"
+#include "gpu_shader_private.hh"
#include "gpu_state_private.hh"
#include <mutex>
@@ -43,7 +44,7 @@ struct GPUMatrixState;
struct GPUContext {
public:
/** State managment */
- GPUShader *shader = NULL;
+ blender::gpu::Shader *shader = NULL;
GPUFrameBuffer *current_fbo = NULL;
GPUMatrixState *matrix_state = NULL;
blender::gpu::GPUStateManager *state_manager = NULL;
diff --git a/source/blender/gpu/intern/gpu_drawlist_private.hh b/source/blender/gpu/intern/gpu_drawlist_private.hh
index 04cc18a5ffd..ddb09fb0c89 100644
--- a/source/blender/gpu/intern/gpu_drawlist_private.hh
+++ b/source/blender/gpu/intern/gpu_drawlist_private.hh
@@ -28,6 +28,10 @@
namespace blender {
namespace gpu {
+/**
+ * Implementation of Multi Draw Indirect.
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ **/
class DrawList {
public:
virtual ~DrawList(){};
diff --git a/source/blender/gpu/intern/gpu_extensions.cc b/source/blender/gpu/intern/gpu_extensions.cc
index 8074e4b64f0..1d607d79b01 100644
--- a/source/blender/gpu/intern/gpu_extensions.cc
+++ b/source/blender/gpu/intern/gpu_extensions.cc
@@ -71,12 +71,10 @@ static struct GPUGlobal {
GLint maxubosize;
GLint maxubobinds;
int samples_color_texture_max;
- float line_width_range[2];
/* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
* calculate dfdy in shader differently when drawing to an off-screen buffer. First
* number is factor on screen and second is off-screen */
float dfdyfactors[2];
- float max_anisotropy;
/* Some Intel drivers have limited support for `GLEW_ARB_base_instance` so in
* these cases it is best to indicate that it is not supported. See T67951 */
bool glew_arb_base_instance_is_supported;
@@ -164,11 +162,6 @@ int GPU_max_textures_vert(void)
return GG.maxtexturesvert;
}
-float GPU_max_texture_anisotropy(void)
-{
- return GG.max_anisotropy;
-}
-
int GPU_max_color_texture_samples(void)
{
return GG.samples_color_texture_max;
@@ -189,11 +182,6 @@ int GPU_max_ubo_size(void)
return GG.maxubosize;
}
-float GPU_max_line_width(void)
-{
- return GG.line_width_range[1];
-}
-
void GPU_get_dfdy_factors(float fac[2])
{
copy_v2_v2(fac, GG.dfdyfactors);
@@ -264,18 +252,9 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
- if (GLEW_EXT_texture_filter_anisotropic) {
- glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);
- }
- else {
- GG.max_anisotropy = 1.0f;
- }
-
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
- glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, GG.line_width_range);
-
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
const char *vendor = (const char *)glGetString(GL_VENDOR);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index da8ab80b347..88013640bfc 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -622,23 +622,37 @@ void GPU_framebuffer_clear(GPUFrameBuffer *fb,
{
CHECK_FRAMEBUFFER_IS_BOUND(fb);
- GPU_context_active_get()->state_manager->apply_state();
+ /* Save and restore the state. */
+ eGPUWriteMask write_mask = GPU_write_mask_get();
+ uint stencil_mask = GPU_stencil_mask_get();
+ eGPUStencilTest stencil_test = GPU_stencil_test_get();
if (buffers & GPU_COLOR_BIT) {
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ GPU_color_mask(true, true, true, true);
glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
}
if (buffers & GPU_DEPTH_BIT) {
- glDepthMask(GL_TRUE);
+ GPU_depth_mask(true);
glClearDepth(clear_depth);
}
if (buffers & GPU_STENCIL_BIT) {
- glStencilMask(0xFF);
+ GPU_stencil_write_mask_set(0xFFu);
+ GPU_stencil_test(GPU_STENCIL_ALWAYS);
glClearStencil(clear_stencil);
}
+ GPU_context_active_get()->state_manager->apply_state();
+
GLbitfield mask = convert_buffer_bits_to_gl(buffers);
glClear(mask);
+
+ if (buffers & (GPU_COLOR_BIT | GPU_DEPTH_BIT)) {
+ GPU_write_mask(write_mask);
+ }
+ if (buffers & GPU_STENCIL_BIT) {
+ GPU_stencil_write_mask_set(stencil_mask);
+ GPU_stencil_test(stencil_test);
+ }
}
/* Clear all textures bound to this framebuffer with a different color. */
@@ -1103,18 +1117,22 @@ void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs,
void GPU_clear_color(float red, float green, float blue, float alpha)
{
+ BLI_assert((GPU_write_mask_get() & GPU_WRITE_COLOR) != 0);
+
+ GPU_context_active_get()->state_manager->apply_state();
+
glClearColor(red, green, blue, alpha);
+ glClear(GL_COLOR_BUFFER_BIT);
}
void GPU_clear_depth(float depth)
{
- glClearDepth(depth);
-}
+ BLI_assert((GPU_write_mask_get() & GPU_WRITE_DEPTH) != 0);
-void GPU_clear(eGPUFrameBufferBits flags)
-{
GPU_context_active_get()->state_manager->apply_state();
- glClear(convert_buffer_bits_to_gl(flags));
+
+ glClearDepth(depth);
+ glClear(GL_DEPTH_BUFFER_BIT);
}
void GPU_frontbuffer_read_pixels(
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index dd05689d69a..431dbe848f7 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -73,7 +73,6 @@ typedef struct {
GLuint vao_id;
GPUShader *bound_program;
- const GPUShaderInterface *shader_interface;
GPUAttrBinding attr_binding;
uint16_t prev_enabled_attr_bits; /* <-- only affects this VAO, so we're ok */
} Immediate;
@@ -148,14 +147,13 @@ void immBindShader(GPUShader *shader)
BLI_assert(imm.bound_program == NULL);
imm.bound_program = shader;
- imm.shader_interface = shader->interface;
if (!imm.vertex_format.packed) {
VertexFormat_pack(&imm.vertex_format);
}
GPU_shader_bind(shader);
- get_attr_locations(&imm.vertex_format, &imm.attr_binding, imm.shader_interface);
+ get_attr_locations(&imm.vertex_format, &imm.attr_binding, shader);
GPU_matrix_bind(shader);
GPU_shader_set_srgb_uniform(shader);
}
@@ -749,123 +747,77 @@ void immVertex2iv(uint attr_id, const int data[2])
/* --- generic uniform functions --- */
-#if 0
-# if TRUST_NO_ONE
-# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
- assert(uniform);
-# else
-# define GET_UNIFORM \
- 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.
- * In this case we can't assert failure or allow NULL-pointer dereference.
- * 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(imm.shader_interface, name); \
- if (uniform == NULL) \
- return;
-#endif
-
void immUniform1f(const char *name, float x)
{
- GET_UNIFORM
- glUniform1f(uniform->location, x);
+ GPU_shader_uniform_1f(imm.bound_program, name, x);
}
void immUniform2f(const char *name, float x, float y)
{
- GET_UNIFORM
- glUniform2f(uniform->location, x, y);
+ GPU_shader_uniform_2f(imm.bound_program, name, x, y);
}
void immUniform2fv(const char *name, const float data[2])
{
- GET_UNIFORM
- glUniform2fv(uniform->location, 1, data);
+ GPU_shader_uniform_2fv(imm.bound_program, name, data);
}
void immUniform3f(const char *name, float x, float y, float z)
{
- GET_UNIFORM
- glUniform3f(uniform->location, x, y, z);
+ GPU_shader_uniform_3f(imm.bound_program, name, x, y, z);
}
void immUniform3fv(const char *name, const float data[3])
{
- GET_UNIFORM
- glUniform3fv(uniform->location, 1, data);
-}
-
-/* can increase this limit or move to another file */
-#define MAX_UNIFORM_NAME_LEN 60
-
-/* Note array index is not supported for name (i.e: "array[0]"). */
-void immUniformArray3fv(const char *name, const float *data, int count)
-{
- GET_UNIFORM
- glUniform3fv(uniform->location, count, data);
+ GPU_shader_uniform_3fv(imm.bound_program, name, data);
}
void immUniform4f(const char *name, float x, float y, float z, float w)
{
- GET_UNIFORM
- glUniform4f(uniform->location, x, y, z, w);
+ GPU_shader_uniform_4f(imm.bound_program, name, x, y, z, w);
}
void immUniform4fv(const char *name, const float data[4])
{
- GET_UNIFORM
- glUniform4fv(uniform->location, 1, data);
+ GPU_shader_uniform_4fv(imm.bound_program, name, data);
}
/* Note array index is not supported for name (i.e: "array[0]"). */
void immUniformArray4fv(const char *name, const float *data, int count)
{
- GET_UNIFORM
- glUniform4fv(uniform->location, count, data);
+ GPU_shader_uniform_4fv_array(imm.bound_program, name, count, (float(*)[4])data);
}
void immUniformMatrix4fv(const char *name, const float data[4][4])
{
- GET_UNIFORM
- glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data);
+ GPU_shader_uniform_mat4(imm.bound_program, name, data);
}
void immUniform1i(const char *name, int x)
{
- GET_UNIFORM
- glUniform1i(uniform->location, x);
-}
-
-void immUniform4iv(const char *name, const int data[4])
-{
- GET_UNIFORM
- glUniform4iv(uniform->location, 1, data);
+ GPU_shader_uniform_1i(imm.bound_program, name, x);
}
void immBindTexture(const char *name, GPUTexture *tex)
{
- GET_UNIFORM
- GPU_texture_bind(tex, uniform->binding);
+ int binding = GPU_shader_get_texture_binding(imm.bound_program, name);
+ GPU_texture_bind(tex, binding);
}
void immBindTextureSampler(const char *name, GPUTexture *tex, eGPUSamplerState state)
{
- GET_UNIFORM
- GPU_texture_bind_ex(tex, state, uniform->binding, true);
+ int binding = GPU_shader_get_texture_binding(imm.bound_program, name);
+ GPU_texture_bind_ex(tex, state, binding, true);
}
/* --- convenience functions for setting "uniform vec4 color" --- */
void immUniformColor4f(float r, float g, float b, float a)
{
- int32_t uniform_loc = GPU_shaderinterface_uniform_builtin(imm.shader_interface,
- GPU_UNIFORM_COLOR);
+ int32_t uniform_loc = GPU_shader_get_builtin_uniform(imm.bound_program, GPU_UNIFORM_COLOR);
BLI_assert(uniform_loc != -1);
- glUniform4f(uniform_loc, r, g, b, a);
+ float data[4] = {r, g, b, a};
+ GPU_shader_uniform_vector(imm.bound_program, uniform_loc, 4, 1, data);
}
void immUniformColor4fv(const float rgba[4])
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 8df1f94238a..1016e766140 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -47,7 +47,7 @@
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "GPU_uniformbuffer.h"
+#include "GPU_uniform_buffer.h"
#include "DRW_engine.h"
@@ -88,11 +88,11 @@ struct GPUMaterial {
eGPUMatFlag flag;
/* Used by 2.8 pipeline */
- GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
+ GPUUniformBuf *ubo; /* UBOs for shader uniforms. */
/* Eevee SSS */
- GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
- GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
+ GPUUniformBuf *sss_profile; /* UBO containing SSS profile. */
+ GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
float sss_enabled;
float sss_radii[3];
int sss_samples;
@@ -174,13 +174,13 @@ static void gpu_material_free_single(GPUMaterial *material)
GPU_pass_release(material->pass);
}
if (material->ubo != NULL) {
- GPU_uniformbuffer_free(material->ubo);
+ GPU_uniformbuf_free(material->ubo);
}
if (material->sss_tex_profile != NULL) {
GPU_texture_free(material->sss_tex_profile);
}
if (material->sss_profile != NULL) {
- GPU_uniformbuffer_free(material->sss_profile);
+ GPU_uniformbuf_free(material->sss_profile);
}
if (material->coba_tex != NULL) {
GPU_texture_free(material->coba_tex);
@@ -220,7 +220,7 @@ Material *GPU_material_get_material(GPUMaterial *material)
return material->ma;
}
-GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material)
+GPUUniformBuf *GPU_material_uniform_buffer_get(GPUMaterial *material)
{
return material->ubo;
}
@@ -232,7 +232,12 @@ GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material)
*/
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs)
{
- material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL);
+#ifndef NDEBUG
+ const char *name = material->name;
+#else
+ const char *name = "Material";
+#endif
+ material->ubo = GPU_uniformbuf_create_from_list(inputs, name);
}
/* Eevee Subsurface scattering. */
@@ -507,13 +512,13 @@ void GPU_material_sss_profile_create(GPUMaterial *material,
/* Update / Create UBO */
if (material->sss_profile == NULL) {
- material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL);
+ material->sss_profile = GPU_uniformbuf_create(sizeof(GPUSssKernelData));
}
}
-struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material,
- int sample_len,
- GPUTexture **tex_profile)
+struct GPUUniformBuf *GPU_material_sss_profile_get(GPUMaterial *material,
+ int sample_len,
+ GPUTexture **tex_profile)
{
if (!material->sss_enabled) {
return NULL;
@@ -530,7 +535,7 @@ struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material,
compute_sss_kernel(&kd, material->sss_radii, sample_len, material->sss_falloff, sharpness);
/* Update / Create UBO */
- GPU_uniformbuffer_update(material->sss_profile, &kd);
+ GPU_uniformbuf_update(material->sss_profile, &kd);
/* Update / Create Tex */
float *translucence_profile;
@@ -555,9 +560,9 @@ struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material,
return material->sss_profile;
}
-struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void)
+struct GPUUniformBuf *GPU_material_create_sss_profile_ubo(void)
{
- return GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL);
+ return GPU_uniformbuf_create(sizeof(GPUSssKernelData));
}
#undef SSS_EXPONENT
@@ -735,7 +740,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
gpu_node_graph_free(&mat->graph);
}
- /* Only free after GPU_pass_shader_get where GPUUniformBuffer
+ /* Only free after GPU_pass_shader_get where GPUUniformBuf
* read data from the local tree. */
ntreeFreeLocalTree(localtree);
MEM_freeN(localtree);
diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc
index 951652b9393..cdb6d303588 100644
--- a/source/blender/gpu/intern/gpu_matrix.cc
+++ b/source/blender/gpu/intern/gpu_matrix.cc
@@ -21,8 +21,6 @@
* \ingroup gpu
*/
-#include "GPU_shader_interface.h"
-
#include "gpu_context_private.hh"
#include "gpu_matrix_private.h"
@@ -649,14 +647,13 @@ void GPU_matrix_bind(GPUShader *shader)
* call this before a draw call if desired matrices are dirty
* call glUseProgram before this, as glUniform expects program to be bound
*/
- const GPUShaderInterface *shaderface = shader->interface;
- 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);
+ int32_t MV = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW);
+ int32_t P = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION);
+ int32_t MVP = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
+
+ int32_t N = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL);
+ int32_t MV_inv = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV);
+ int32_t P_inv = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV);
if (MV != -1) {
GPU_shader_uniform_vector(shader, MV, 16, 1, (const float *)GPU_matrix_model_view_get(NULL));
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 81cf2d69f4d..1b8a5e20240 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -592,10 +592,10 @@ bool GPU_stack_link(GPUMaterial *material,
return true;
}
-GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat,
- bNode *node,
- GPUNodeStack *stack,
- const int index)
+GPUNodeLink *GPU_uniformbuf_link_out(GPUMaterial *mat,
+ bNode *node,
+ GPUNodeStack *stack,
+ const int index)
{
return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 29e2615345c..c3ccb68a998 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_immediate.h"
#include "GPU_select.h"
@@ -287,7 +288,7 @@ typedef struct GPUPickState {
int viewport[4];
int scissor[4];
eGPUWriteMask write_mask;
- bool depth_test;
+ eGPUDepthTest depth_test;
} GPUPickState;
static GPUPickState g_pick_state = {0};
@@ -311,18 +312,17 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c
/* Restrict OpenGL operations for when we don't have cache */
if (ps->is_cached == false) {
ps->write_mask = GPU_write_mask_get();
- ps->depth_test = GPU_depth_test_enabled();
+ ps->depth_test = GPU_depth_test_get();
GPU_scissor_get(ps->scissor);
/* disable writing to the framebuffer */
GPU_color_mask(false, false, false, false);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
+ GPU_depth_mask(true);
/* 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);
+ GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
float viewport[4];
GPU_viewport_size_get_f(viewport);
@@ -339,7 +339,7 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, c
/* It's possible we don't want to clear depth buffer,
* so existing elements are masked by current z-buffer. */
- glClear(GL_DEPTH_BUFFER_BIT);
+ GPU_clear_depth(1.0f);
/* scratch buffer (read new values here) */
ps->gl.rect_depth_test = depth_buf_malloc(rect_len);
@@ -518,8 +518,13 @@ bool gpu_select_pick_load_id(uint id, bool end)
SWAP(DepthBufCache *, ps->gl.rect_depth, ps->gl.rect_depth_test);
if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ /* (fclem) This is to be on the safe side. I don't know if this is required. */
+ bool prev_depth_mask = GPU_depth_mask_get();
/* we want new depths every time */
- glClear(GL_DEPTH_BUFFER_BIT);
+ GPU_depth_mask(true);
+ GPU_clear_depth(1.0f);
+
+ GPU_depth_mask(prev_depth_mask);
}
}
}
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 62414febb44..45d52b22664 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
+#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_select.h"
#include "GPU_state.h"
@@ -65,7 +66,7 @@ typedef struct GPUQueryState {
int viewport[4];
int scissor[4];
eGPUWriteMask write_mask;
- bool depth_test;
+ eGPUDepthTest depth_test;
} GPUQueryState;
static GPUQueryState g_query_state = {0};
@@ -91,41 +92,41 @@ void gpu_select_query_begin(
glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
g_query_state.write_mask = GPU_write_mask_get();
- g_query_state.depth_test = GPU_depth_test_enabled();
+ g_query_state.depth_test = GPU_depth_test_get();
GPU_scissor_get(g_query_state.scissor);
+ GPU_viewport_size_get_i(g_query_state.viewport);
- /* disable writing to the framebuffer */
- GPU_color_mask(false, false, false, false);
+ /* Write to color buffer. Seems to fix issues with selecting alpha blended geom (see T7997). */
+ GPU_color_mask(true, true, true, true);
/* In order to save some fill rate we minimize the viewport using rect.
* We need to get the region of the viewport so that our geometry doesn't
* get rejected before the depth test. Should probably cull rect against
* the viewport but this is a rare case I think */
- GPU_viewport_size_get_i(g_query_state.viewport);
- GPU_viewport(g_query_state.viewport[0],
- g_query_state.viewport[1],
- BLI_rcti_size_x(input),
- BLI_rcti_size_y(input));
+
+ int viewport[4] = {
+ UNPACK2(g_query_state.viewport), BLI_rcti_size_x(input), BLI_rcti_size_y(input)};
+
+ GPU_viewport(UNPACK4(viewport));
+ GPU_scissor(UNPACK4(viewport));
+ GPU_scissor_test(false);
/* occlusion queries operates on fragments that pass tests and since we are interested on all
* objects in the view frustum independently of their order, we need to disable the depth test */
if (mode == GPU_SELECT_ALL) {
/* glQueries on Windows+Intel drivers only works with depth testing turned on.
* See T62947 for details */
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glDepthMask(GL_TRUE);
+ GPU_depth_test(GPU_DEPTH_ALWAYS);
+ GPU_depth_mask(true);
}
else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
- glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
- glDepthFunc(GL_LEQUAL);
+ GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
+ GPU_depth_mask(true);
+ GPU_clear_depth(1.0f);
}
else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
- glDepthFunc(GL_EQUAL);
+ GPU_depth_test(GPU_DEPTH_EQUAL);
+ GPU_depth_mask(false);
}
}
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc
index 536396ad3c6..b1772bed6e8 100644
--- a/source/blender/gpu/intern/gpu_shader.cc
+++ b/source/blender/gpu/intern/gpu_shader.cc
@@ -41,7 +41,7 @@
#include "GPU_platform.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "GPU_uniformbuffer.h"
+#include "GPU_uniform_buffer.h"
#include "gpu_backend.hh"
#include "gpu_context_private.hh"
@@ -52,6 +52,11 @@ extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
using namespace blender;
using namespace blender::gpu;
+/** Opaque type hidding blender::gpu::Shader */
+struct GPUShader {
+ char _pad[1];
+};
+
/* -------------------------------------------------------------------- */
/** \name Debug functions
* \{ */
@@ -196,9 +201,7 @@ Shader::Shader(const char *sh_name)
Shader::~Shader()
{
- if (this->interface) {
- GPU_shaderinterface_discard(this->interface);
- }
+ delete interface;
}
static void standard_defines(Vector<const char *> &sources)
@@ -304,12 +307,12 @@ GPUShader *GPU_shader_create_ex(const char *vertcode,
return NULL;
};
- return static_cast<GPUShader *>(shader);
+ return reinterpret_cast<GPUShader *>(shader);
}
void GPU_shader_free(GPUShader *shader)
{
- delete static_cast<Shader *>(shader);
+ delete reinterpret_cast<Shader *>(shader);
}
/** \} */
@@ -345,7 +348,7 @@ GPUShader *GPU_shader_create_from_python(const char *vertcode,
}
GPUShader *sh = GPU_shader_create_ex(
- vertcode, fragcode, geomcode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, NULL);
+ vertcode, fragcode, geomcode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, "pyGPUShader");
MEM_SAFE_FREE(libcodecat);
return sh;
@@ -431,19 +434,19 @@ struct GPUShader *GPU_shader_create_from_arrays_impl(
void GPU_shader_bind(GPUShader *gpu_shader)
{
- Shader *shader = static_cast<Shader *>(gpu_shader);
+ Shader *shader = reinterpret_cast<Shader *>(gpu_shader);
GPUContext *ctx = GPU_context_active_get();
if (ctx->shader != shader) {
ctx->shader = shader;
shader->bind();
- GPU_matrix_bind(shader);
- GPU_shader_set_srgb_uniform(shader);
+ GPU_matrix_bind(gpu_shader);
+ GPU_shader_set_srgb_uniform(gpu_shader);
}
if (GPU_matrix_dirty_get()) {
- GPU_matrix_bind(shader);
+ GPU_matrix_bind(gpu_shader);
}
}
@@ -452,7 +455,7 @@ void GPU_shader_unbind(void)
#ifndef NDEBUG
GPUContext *ctx = GPU_context_active_get();
if (ctx->shader) {
- static_cast<Shader *>(ctx->shader)->unbind();
+ reinterpret_cast<Shader *>(ctx->shader)->unbind();
}
ctx->shader = NULL;
#endif
@@ -468,12 +471,12 @@ void GPU_shader_unbind(void)
bool GPU_shader_transform_feedback_enable(GPUShader *shader, GPUVertBuf *vertbuf)
{
- return static_cast<Shader *>(shader)->transform_feedback_enable(vertbuf);
+ return reinterpret_cast<Shader *>(shader)->transform_feedback_enable(vertbuf);
}
void GPU_shader_transform_feedback_disable(GPUShader *shader)
{
- static_cast<Shader *>(shader)->transform_feedback_disable();
+ reinterpret_cast<Shader *>(shader)->transform_feedback_disable();
}
/** \} */
@@ -484,43 +487,49 @@ void GPU_shader_transform_feedback_disable(GPUShader *shader)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ const ShaderInput *uniform = interface->uniform_get(name);
return uniform ? uniform->location : -1;
}
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
{
- return GPU_shaderinterface_uniform_builtin(shader->interface,
- static_cast<GPUUniformBuiltin>(builtin));
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ return interface->uniform_builtin((GPUUniformBuiltin)builtin);
}
int GPU_shader_get_builtin_block(GPUShader *shader, int builtin)
{
- return GPU_shaderinterface_block_builtin(shader->interface,
- static_cast<GPUUniformBlockBuiltin>(builtin));
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ return interface->ubo_builtin((GPUUniformBlockBuiltin)builtin);
}
+/* DEPRECATED. */
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
{
- const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ const ShaderInput *ubo = interface->ubo_get(name);
return ubo ? ubo->location : -1;
}
int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name)
{
- const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ const ShaderInput *ubo = interface->ubo_get(name);
return ubo ? ubo->binding : -1;
}
int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
{
- const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name);
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ const ShaderInput *tex = interface->uniform_get(name);
return tex ? tex->binding : -1;
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
- const GPUShaderInput *attr = GPU_shaderinterface_attr(shader->interface, name);
+ ShaderInterface *interface = reinterpret_cast<Shader *>(shader)->interface;
+ const ShaderInput *attr = interface->attr_get(name);
return attr ? attr->location : -1;
}
@@ -546,13 +555,13 @@ int GPU_shader_get_program(GPUShader *UNUSED(shader))
void GPU_shader_uniform_vector(
GPUShader *shader, int loc, int len, int arraysize, const float *value)
{
- static_cast<Shader *>(shader)->uniform_float(loc, len, arraysize, value);
+ reinterpret_cast<Shader *>(shader)->uniform_float(loc, len, arraysize, value);
}
void GPU_shader_uniform_vector_int(
GPUShader *shader, int loc, int len, int arraysize, const int *value)
{
- static_cast<Shader *>(shader)->uniform_int(loc, len, arraysize, value);
+ reinterpret_cast<Shader *>(shader)->uniform_int(loc, len, arraysize, value);
}
void GPU_shader_uniform_int(GPUShader *shader, int location, int value)
@@ -565,14 +574,10 @@ void GPU_shader_uniform_float(GPUShader *shader, int location, float value)
GPU_shader_uniform_vector(shader, location, 1, 1, &value);
}
-#define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform(sh->interface, name); \
- BLI_assert(uniform);
-
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
{
- GET_UNIFORM
- GPU_shader_uniform_int(sh, uniform->location, value);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_int(sh, loc, value);
}
void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value)
@@ -600,44 +605,44 @@ void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, fl
void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float x)
{
- GET_UNIFORM
- GPU_shader_uniform_float(sh, uniform->location, x);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_float(sh, loc, x);
}
void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 2, 1, data);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 2, 1, data);
}
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 3, 1, data);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 3, 1, data);
}
void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 4, 1, data);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 4, 1, data);
}
void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 16, 1, (const float *)data);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 16, 1, (const float *)data);
}
void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 2, len, (const float *)val);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 2, len, (const float *)val);
}
void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4])
{
- GET_UNIFORM
- GPU_shader_uniform_vector(sh, uniform->location, 4, len, (const float *)val);
+ const int loc = GPU_shader_get_uniform(sh, name);
+ GPU_shader_uniform_vector(sh, loc, 4, len, (const float *)val);
}
/** \} */
@@ -657,7 +662,7 @@ static int g_shader_builtin_srgb_transform = 0;
void GPU_shader_set_srgb_uniform(GPUShader *shader)
{
- int32_t loc = GPU_shaderinterface_uniform_builtin(shader->interface, GPU_UNIFORM_SRGB_TRANSFORM);
+ int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM);
if (loc != -1) {
GPU_shader_uniform_vector_int(shader, loc, 1, 1, &g_shader_builtin_srgb_transform);
}
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index da5bcaeca17..ed95a236da5 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -40,7 +40,7 @@
#include "GPU_platform.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "GPU_uniformbuffer.h"
+#include "GPU_uniform_buffer.h"
/* Adjust these constants as needed. */
#define MAX_DEFINE_LENGTH 256
diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc
index ef90dde1877..dc59dca9f78 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.cc
+++ b/source/blender/gpu/intern/gpu_shader_interface.cc
@@ -23,161 +23,41 @@
* GPU shader interface (C --> GLSL)
*/
-#include "BKE_global.h"
-
-#include "BLI_bitmap.h"
-#include "BLI_math_base.h"
-
#include "MEM_guardedalloc.h"
-#include "GPU_shader_interface.h"
-
-#include "gpu_batch_private.hh"
-#include "gpu_context_private.hh"
-
-#include "gl_batch.hh"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define DEBUG_SHADER_INTERFACE 0
-
-#if DEBUG_SHADER_INTERFACE
-# include <stdio.h>
-#endif
-
-using namespace blender::gpu;
-
-static const char *BuiltinUniform_name(GPUUniformBuiltin u)
-{
- switch (u) {
- case GPU_UNIFORM_MODEL:
- return "ModelMatrix";
- case GPU_UNIFORM_VIEW:
- return "ViewMatrix";
- case GPU_UNIFORM_MODELVIEW:
- return "ModelViewMatrix";
- case GPU_UNIFORM_PROJECTION:
- return "ProjectionMatrix";
- case GPU_UNIFORM_VIEWPROJECTION:
- return "ViewProjectionMatrix";
- case GPU_UNIFORM_MVP:
- return "ModelViewProjectionMatrix";
-
- case GPU_UNIFORM_MODEL_INV:
- return "ModelMatrixInverse";
- case GPU_UNIFORM_VIEW_INV:
- return "ViewMatrixInverse";
- case GPU_UNIFORM_MODELVIEW_INV:
- return "ModelViewMatrixInverse";
- case GPU_UNIFORM_PROJECTION_INV:
- return "ProjectionMatrixInverse";
- case GPU_UNIFORM_VIEWPROJECTION_INV:
- return "ViewProjectionMatrixInverse";
-
- case GPU_UNIFORM_NORMAL:
- return "NormalMatrix";
- case GPU_UNIFORM_ORCO:
- return "OrcoTexCoFactors";
- case GPU_UNIFORM_CLIPPLANES:
- return "WorldClipPlanes";
-
- case GPU_UNIFORM_COLOR:
- return "color";
- case GPU_UNIFORM_BASE_INSTANCE:
- return "baseInstance";
- case GPU_UNIFORM_RESOURCE_CHUNK:
- return "resourceChunk";
- case GPU_UNIFORM_RESOURCE_ID:
- return "resourceId";
- case GPU_UNIFORM_SRGB_TRANSFORM:
- return "srgbTarget";
+#include "BLI_span.hh"
+#include "BLI_vector.hh"
- default:
- return NULL;
- }
-}
+#include "gpu_shader_interface.hh"
-static const char *BuiltinUniformBlock_name(GPUUniformBlockBuiltin u)
-{
- switch (u) {
- case GPU_UNIFORM_BLOCK_VIEW:
- return "viewBlock";
- case GPU_UNIFORM_BLOCK_MODEL:
- return "modelBlock";
- case GPU_UNIFORM_BLOCK_INFO:
- return "infoBlock";
- default:
- return NULL;
- }
-}
+namespace blender::gpu {
-GPU_INLINE bool match(const char *a, const char *b)
+ShaderInterface::ShaderInterface(void)
{
- return STREQ(a, b);
+ /* TODO(fclem) add unique ID for debugging. */
}
-GPU_INLINE uint hash_string(const char *str)
+ShaderInterface::~ShaderInterface(void)
{
- uint i = 0, c;
- while ((c = *str++)) {
- i = i * 37 + c;
- }
- return i;
+ /* Free memory used by name_buffer. */
+ MEM_freeN(name_buffer_);
+ MEM_freeN(inputs_);
}
-GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface,
- GPUShaderInput *input,
- char *name,
- uint32_t name_len)
+static void sort_input_list(MutableSpan<ShaderInput> dst)
{
- /* remove "[0]" from array name */
- if (name[name_len - 1] == ']') {
- name[name_len - 3] = '\0';
- name_len -= 3;
+ if (dst.size() == 0) {
+ return;
}
- 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 *input_lookup(const GPUShaderInterface *shaderface,
- const GPUShaderInput *const inputs,
- const uint inputs_len,
- const char *name)
-{
- const uint name_hash = hash_string(name);
- /* 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 */
- }
-
- /* 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 */
-}
+ Vector<ShaderInput> inputs_vec = Vector<ShaderInput>(dst.size());
+ MutableSpan<ShaderInput> src = inputs_vec.as_mutable_span();
+ src.copy_from(dst);
-/* Note that this modify the src array. */
-GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len)
-{
- for (uint i = 0; i < input_len; i++) {
- GPUShaderInput *input_src = &src[0];
- for (uint j = 1; j < input_len; j++) {
+ /* Simple sorting by going through the array and selecting the biggest element each time. */
+ for (uint i = 0; i < dst.size(); i++) {
+ ShaderInput *input_src = &src[0];
+ for (uint j = 1; j < src.size(); j++) {
if (src[j].name_hash > input_src->name_hash) {
input_src = &src[j];
}
@@ -187,360 +67,60 @@ GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const
}
}
-static int block_binding(int32_t program, uint32_t block_index)
+/* Sorts all inputs inside their respective array.
+ * This is to allow fast hash collision detection.
+ * See ShaderInterface::input_lookup for more details. */
+void ShaderInterface::sort_inputs(void)
{
- /* 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;
+ sort_input_list(MutableSpan<ShaderInput>(inputs_, attr_len_));
+ sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_, ubo_len_));
+ sort_input_list(MutableSpan<ShaderInput>(inputs_ + attr_len_ + ubo_len_, uniform_len_));
}
-static int sampler_binding(int32_t program,
- uint32_t uniform_index,
- int32_t uniform_location,
- int *sampler_len)
+void ShaderInterface::debug_print(void)
{
- /* 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;
- }
-}
+ Span<ShaderInput> attrs = Span<ShaderInput>(inputs_, attr_len_);
+ Span<ShaderInput> ubos = Span<ShaderInput>(inputs_ + attr_len_, ubo_len_);
+ Span<ShaderInput> uniforms = Span<ShaderInput>(inputs_ + attr_len_ + ubo_len_, uniform_len_);
+ char *name_buf = name_buffer_;
+ const char format[] = " | %.8x : %4d : %s\n";
-GPUShaderInterface *GPU_shaderinterface_create(int32_t 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;
- glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len);
- glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len);
-
- GLint max_ubo_name_len = 0, ubo_len = 0;
- 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) {
- max_attr_name_len = 256;
- }
- if (ubo_len > 0 && max_ubo_name_len == 0) {
- max_ubo_name_len = 256;
+ printf(" \033[1mGPUShaderInterface : \033[0m\n");
+ if (attrs.size() > 0) {
+ printf("\n Attributes :\n");
}
- if (uniform_len > 0 && max_uniform_name_len == 0) {
- max_uniform_name_len = 256;
+ for (const ShaderInput &attr : attrs) {
+ printf(format, attr.name_hash, attr.location, name_buf + attr.name_offset);
}
- /* 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;
+ if (uniforms.size() > 0) {
+ printf("\n Uniforms :\n");
}
- /* 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 = (GLint *)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]);
+ for (const ShaderInput &uni : uniforms) {
+ /* Bypass samplers. */
+ if (uni.binding == -1) {
+ printf(format, uni.name_hash, uni.location, name_buf + uni.name_offset);
}
}
- MEM_freeN(ubo_uni_ids);
- 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;
-
- int input_tot_len = attr_len + ubo_len + uniform_len;
- size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len;
-
- GPUShaderInterface *shaderface = (GPUShaderInterface *)MEM_callocN(interface_size,
- "GPUShaderInterface");
- shaderface->attribute_len = attr_len;
- shaderface->ubo_len = ubo_len;
- shaderface->uniform_len = uniform_len;
- shaderface->name_buffer = (char *)MEM_mallocN(name_buffer_len, "name_buffer");
- GPUShaderInput *inputs = shaderface->inputs;
-
- /* Temp buffer. */
- int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len);
- GPUShaderInput *inputs_tmp = (GPUShaderInput *)MEM_mallocN(
- sizeof(GPUShaderInput) * input_tmp_len, "name_buffer");
-
- /* 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;
- }
-
- GPUShaderInput *input = &inputs_tmp[idx++];
- input->location = input->binding = location;
-
- name_buffer_offset += set_input_name(shaderface, input, name, name_len);
- shaderface->enabled_attr_mask |= (1 << input->location);
+ if (ubos.size() > 0) {
+ printf("\n Uniform Buffer Objects :\n");
}
- sort_input_list(inputs, inputs_tmp, shaderface->attribute_len);
- inputs += shaderface->attribute_len;
-
- /* Uniform Blocks */
- 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);
-
- GPUShaderInput *input = &inputs_tmp[idx++];
- input->binding = input->location = block_binding(program, i);
-
- name_buffer_offset += set_input_name(shaderface, input, name, name_len);
- shaderface->enabled_ubo_mask |= (1 << input->binding);
+ for (const ShaderInput &ubo : ubos) {
+ printf(format, ubo.name_hash, ubo.binding, name_buf + ubo.name_offset);
}
- sort_input_list(inputs, inputs_tmp, shaderface->ubo_len);
- inputs += shaderface->ubo_len;
- /* 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;
-
- 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 (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) {
- GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int);
- shaderface->builtins[u] = glGetUniformLocation(program, BuiltinUniform_name(u));
- }
-
- /* Builtin Uniforms Blocks */
- for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORM_BLOCKS; u_int++) {
- GPUUniformBlockBuiltin u = static_cast<GPUUniformBlockBuiltin>(u_int);
- 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 = (void **)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 = (char *)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 (enabled_tex_mask_ > 0) {
+ printf("\n Samplers :\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);
- }
+ for (const ShaderInput &samp : uniforms) {
+ /* Bypass uniforms. */
+ if (samp.binding != -1) {
+ printf(format, samp.name_hash, samp.binding, name_buf + samp.name_offset);
}
- printf("};\n");
}
- printf("--- GPUShaderInterface end ---\n\n");
-#endif
- return shaderface;
-}
-
-void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
-{
- /* Free memory used by name_buffer. */
- MEM_freeN(shaderface->name_buffer);
- /* Remove this interface from all linked Batches vao cache. */
- for (int i = 0; i < shaderface->batches_len; i++) {
- if (shaderface->batches[i] != NULL) {
- /* XXX GL specific. to be removed during refactor. */
- reinterpret_cast<GLVaoCache *>(shaderface->batches[i])->remove(shaderface);
- }
- }
- MEM_freeN(shaderface->batches);
- /* Free memory used by shader interface by its self. */
- MEM_freeN(shaderface);
+ printf("\n");
}
-const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
- const char *name)
-{
- uint ofs = 0;
- return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name);
-}
-
-const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
- const char *name)
-{
- uint ofs = shaderface->attribute_len;
- return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name);
-}
-
-const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
- const char *name)
-{
- uint ofs = shaderface->attribute_len + shaderface->ubo_len;
- return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name);
-}
-
-int32_t GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
- GPUUniformBuiltin builtin)
-{
- BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS);
- return shaderface->builtins[builtin];
-}
-
-int32_t GPU_shaderinterface_block_builtin(const GPUShaderInterface *shaderface,
- GPUUniformBlockBuiltin builtin)
-{
- BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS);
- return shaderface->builtin_blocks[builtin];
-}
-
-void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, void *batch)
-{
- int i; /* find first unused slot */
- for (i = 0; i < shaderface->batches_len; i++) {
- if (shaderface->batches[i] == NULL) {
- break;
- }
- }
- if (i == shaderface->batches_len) {
- /* Not enough place, realloc the array. */
- i = shaderface->batches_len;
- shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
- shaderface->batches = (void **)MEM_recallocN(shaderface->batches,
- sizeof(void *) * shaderface->batches_len);
- }
- /** XXX todo cleanup. */
- shaderface->batches[i] = reinterpret_cast<void *>(batch);
-}
-
-void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *shaderface, void *batch)
-{
- for (int i = 0; i < shaderface->batches_len; i++) {
- if (shaderface->batches[i] == batch) {
- shaderface->batches[i] = NULL;
- break; /* cannot have duplicates */
- }
- }
-}
+} // namespace blender::gpu
diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh
new file mode 100644
index 00000000000..6e1cb342c68
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_interface.hh
@@ -0,0 +1,229 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ *
+ * Structure detailing needed vertex inputs and resources for a specific shader.
+ * A shader interface can be shared between two similar shaders.
+ */
+
+#pragma once
+
+#include <cstring> /* required for STREQ later on. */
+
+#include "BLI_hash.h"
+#include "BLI_utildefines.h"
+
+#include "GPU_shader.h"
+
+namespace blender::gpu {
+
+typedef struct ShaderInput {
+ uint32_t name_offset;
+ uint32_t name_hash;
+ int32_t location;
+ /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */
+ int32_t binding;
+} ShaderInput;
+
+/**
+ * Implementation of Shader interface.
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ **/
+class ShaderInterface {
+ /* TODO(fclem) should be protected. */
+ public:
+ /** Flat array. In this order: Attributes, Ubos, Uniforms. */
+ ShaderInput *inputs_ = NULL;
+ /** Buffer containing all inputs names separated by '\0'. */
+ char *name_buffer_ = NULL;
+ /** Input counts inside input array. */
+ uint attr_len_ = 0;
+ uint ubo_len_ = 0;
+ uint uniform_len_ = 0;
+ /** Enabled bindpoints that needs to be fed with data. */
+ uint16_t enabled_attr_mask_ = 0;
+ uint16_t enabled_ubo_mask_ = 0;
+ uint64_t enabled_tex_mask_ = 0;
+ /** Location of builtin uniforms. Fast access, no lookup needed. */
+ int32_t builtins_[GPU_NUM_UNIFORMS];
+ int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS];
+
+ public:
+ ShaderInterface();
+ virtual ~ShaderInterface();
+
+ void debug_print(void);
+
+ inline const ShaderInput *attr_get(const char *name) const
+ {
+ return input_lookup(inputs_, attr_len_, name);
+ }
+
+ inline const ShaderInput *ubo_get(const char *name) const
+ {
+ return input_lookup(inputs_ + attr_len_, ubo_len_, name);
+ }
+
+ inline const ShaderInput *uniform_get(const char *name) const
+ {
+ return input_lookup(inputs_ + attr_len_ + ubo_len_, uniform_len_, name);
+ }
+
+ /* Returns uniform location. */
+ inline int32_t uniform_builtin(const GPUUniformBuiltin builtin) const
+ {
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORMS);
+ return builtins_[builtin];
+ }
+
+ /* Returns binding position. */
+ inline int32_t ubo_builtin(const GPUUniformBlockBuiltin builtin) const
+ {
+ BLI_assert(builtin >= 0 && builtin < GPU_NUM_UNIFORM_BLOCKS);
+ return builtin_blocks_[builtin];
+ }
+
+ protected:
+ static inline const char *builtin_uniform_name(GPUUniformBuiltin u);
+ static inline const char *builtin_uniform_block_name(GPUUniformBlockBuiltin u);
+
+ inline uint32_t set_input_name(ShaderInput *input, char *name, uint32_t name_len) const;
+
+ /* Finalize interface construction by sorting the ShaderInputs for faster lookups. */
+ void sort_inputs(void);
+
+ private:
+ inline const ShaderInput *input_lookup(const ShaderInput *const inputs,
+ const uint inputs_len,
+ const char *name) const;
+};
+
+inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u)
+{
+ switch (u) {
+ case GPU_UNIFORM_MODEL:
+ return "ModelMatrix";
+ case GPU_UNIFORM_VIEW:
+ return "ViewMatrix";
+ case GPU_UNIFORM_MODELVIEW:
+ return "ModelViewMatrix";
+ case GPU_UNIFORM_PROJECTION:
+ return "ProjectionMatrix";
+ case GPU_UNIFORM_VIEWPROJECTION:
+ return "ViewProjectionMatrix";
+ case GPU_UNIFORM_MVP:
+ return "ModelViewProjectionMatrix";
+
+ case GPU_UNIFORM_MODEL_INV:
+ return "ModelMatrixInverse";
+ case GPU_UNIFORM_VIEW_INV:
+ return "ViewMatrixInverse";
+ case GPU_UNIFORM_MODELVIEW_INV:
+ return "ModelViewMatrixInverse";
+ case GPU_UNIFORM_PROJECTION_INV:
+ return "ProjectionMatrixInverse";
+ case GPU_UNIFORM_VIEWPROJECTION_INV:
+ return "ViewProjectionMatrixInverse";
+
+ case GPU_UNIFORM_NORMAL:
+ return "NormalMatrix";
+ case GPU_UNIFORM_ORCO:
+ return "OrcoTexCoFactors";
+ case GPU_UNIFORM_CLIPPLANES:
+ return "WorldClipPlanes";
+
+ case GPU_UNIFORM_COLOR:
+ return "color";
+ case GPU_UNIFORM_BASE_INSTANCE:
+ return "baseInstance";
+ case GPU_UNIFORM_RESOURCE_CHUNK:
+ return "resourceChunk";
+ case GPU_UNIFORM_RESOURCE_ID:
+ return "resourceId";
+ case GPU_UNIFORM_SRGB_TRANSFORM:
+ return "srgbTarget";
+
+ default:
+ return NULL;
+ }
+}
+
+inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBuiltin u)
+{
+ switch (u) {
+ case GPU_UNIFORM_BLOCK_VIEW:
+ return "viewBlock";
+ case GPU_UNIFORM_BLOCK_MODEL:
+ return "modelBlock";
+ case GPU_UNIFORM_BLOCK_INFO:
+ return "infoBlock";
+ default:
+ return NULL;
+ }
+}
+
+/* Returns string length including '\0' terminator. */
+inline uint32_t ShaderInterface::set_input_name(ShaderInput *input,
+ char *name,
+ uint32_t name_len) const
+{
+ /* remove "[0]" from array name */
+ if (name[name_len - 1] == ']') {
+ name[name_len - 3] = '\0';
+ name_len -= 3;
+ }
+
+ input->name_offset = (uint32_t)(name - name_buffer_);
+ input->name_hash = BLI_hash_string(name);
+ return name_len + 1; /* include NULL terminator */
+}
+
+inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const inputs,
+ const uint inputs_len,
+ const char *name) const
+{
+ const uint name_hash = BLI_hash_string(name);
+ /* 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 (STREQ(name, name_buffer_ + inputs[i].name_offset)) {
+ return inputs + i; /* not found */
+ }
+ }
+ return NULL; /* not found */
+ }
+
+ /* 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(STREQ(name, name_buffer_ + inputs[i].name_offset));
+ return inputs + i;
+ }
+ }
+ return NULL; /* not found */
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh
index 1f667fb4cf9..d56a7b2500b 100644
--- a/source/blender/gpu/intern/gpu_shader_private.hh
+++ b/source/blender/gpu/intern/gpu_shader_private.hh
@@ -23,13 +23,25 @@
#include "BLI_span.hh"
#include "GPU_shader.h"
-#include "GPU_shader_interface.h"
#include "GPU_vertex_buffer.h"
+#include "gpu_shader_interface.hh"
namespace blender {
namespace gpu {
-class Shader : public GPUShader {
+/**
+ * Implementation of shader compilation and uniforms handling.
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ **/
+class Shader {
+ public:
+ /** Uniform & attribute locations for shader. */
+ ShaderInterface *interface = nullptr;
+
+ protected:
+ /** For debugging purpose. */
+ char name[64];
+
public:
Shader(const char *name);
virtual ~Shader();
diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc
index f02ec9c5cd4..fcbaa500e2d 100644
--- a/source/blender/gpu/intern/gpu_state.cc
+++ b/source/blender/gpu/intern/gpu_state.cc
@@ -44,7 +44,7 @@ using namespace blender::gpu;
do { \
GPUStateManager *stack = GPU_context_active_get()->state_manager; \
auto &state_object = stack->_prefix##state; \
- state_object._state = _value; \
+ state_object._state = (_value); \
} while (0)
#define SET_IMMUTABLE_STATE(_state, _value) SET_STATE(, _state, _value)
@@ -74,10 +74,14 @@ void GPU_provoking_vertex(eGPUProvokingVertex vert)
SET_IMMUTABLE_STATE(provoking_vert, vert);
}
-/* TODO explicit depth test. */
-void GPU_depth_test(bool enable)
+void GPU_depth_test(eGPUDepthTest test)
{
- SET_IMMUTABLE_STATE(depth_test, (enable) ? GPU_DEPTH_LESS_EQUAL : GPU_DEPTH_NONE);
+ SET_IMMUTABLE_STATE(depth_test, test);
+}
+
+void GPU_stencil_test(eGPUStencilTest test)
+{
+ SET_IMMUTABLE_STATE(stencil_test, test);
}
void GPU_line_smooth(bool enable)
@@ -104,11 +108,11 @@ void GPU_color_mask(bool r, bool g, bool b, bool a)
{
GPUStateManager *stack = GPU_context_active_get()->state_manager;
auto &state = stack->state;
- eGPUWriteMask write_mask = state.write_mask;
- SET_FLAG_FROM_TEST(write_mask, r, GPU_WRITE_RED);
- SET_FLAG_FROM_TEST(write_mask, g, GPU_WRITE_GREEN);
- SET_FLAG_FROM_TEST(write_mask, b, GPU_WRITE_BLUE);
- SET_FLAG_FROM_TEST(write_mask, a, GPU_WRITE_ALPHA);
+ uint32_t write_mask = state.write_mask;
+ SET_FLAG_FROM_TEST(write_mask, r, (uint32_t)GPU_WRITE_RED);
+ SET_FLAG_FROM_TEST(write_mask, g, (uint32_t)GPU_WRITE_GREEN);
+ SET_FLAG_FROM_TEST(write_mask, b, (uint32_t)GPU_WRITE_BLUE);
+ SET_FLAG_FROM_TEST(write_mask, a, (uint32_t)GPU_WRITE_ALPHA);
state.write_mask = write_mask;
}
@@ -116,8 +120,8 @@ void GPU_depth_mask(bool depth)
{
GPUStateManager *stack = GPU_context_active_get()->state_manager;
auto &state = stack->state;
- eGPUWriteMask write_mask = state.write_mask;
- SET_FLAG_FROM_TEST(write_mask, depth, GPU_WRITE_DEPTH);
+ uint32_t write_mask = state.write_mask;
+ SET_FLAG_FROM_TEST(write_mask, depth, (uint32_t)GPU_WRITE_DEPTH);
state.write_mask = write_mask;
}
@@ -141,13 +145,13 @@ void GPU_state_set(eGPUWriteMask write_mask,
{
GPUStateManager *stack = GPU_context_active_get()->state_manager;
auto &state = stack->state;
- state.write_mask = write_mask;
- state.blend = blend;
- state.culling_test = culling_test;
- state.depth_test = depth_test;
- state.stencil_test = stencil_test;
- state.stencil_op = stencil_op;
- state.provoking_vert = provoking_vert;
+ state.write_mask = (uint32_t)write_mask;
+ state.blend = (uint32_t)blend;
+ state.culling_test = (uint32_t)culling_test;
+ state.depth_test = (uint32_t)depth_test;
+ state.stencil_test = (uint32_t)stencil_test;
+ state.stencil_op = (uint32_t)stencil_op;
+ state.provoking_vert = (uint32_t)provoking_vert;
}
/** \} */
@@ -197,7 +201,8 @@ void GPU_scissor(int x, int y, int width, int height)
{
GPUStateManager *stack = GPU_context_active_get()->state_manager;
auto &state = stack->mutable_state;
- int scissor_rect[4] = {x, y, width, height};
+ bool enabled = state.scissor_rect[2] > 0;
+ int scissor_rect[4] = {x, y, enabled ? width : -width, height};
copy_v4_v4_int(state.scissor_rect, scissor_rect);
}
@@ -213,10 +218,12 @@ void GPU_stencil_reference_set(uint reference)
{
SET_MUTABLE_STATE(stencil_reference, (uint8_t)reference);
}
+
void GPU_stencil_write_mask_set(uint write_mask)
{
SET_MUTABLE_STATE(stencil_write_mask, (uint8_t)write_mask);
}
+
void GPU_stencil_compare_mask_set(uint compare_mask)
{
SET_MUTABLE_STATE(stencil_compare_mask, (uint8_t)compare_mask);
@@ -231,19 +238,31 @@ void GPU_stencil_compare_mask_set(uint compare_mask)
eGPUBlend GPU_blend_get()
{
GPUState &state = GPU_context_active_get()->state_manager->state;
- return state.blend;
+ return (eGPUBlend)state.blend;
}
eGPUWriteMask GPU_write_mask_get()
{
GPUState &state = GPU_context_active_get()->state_manager->state;
- return state.write_mask;
+ return (eGPUWriteMask)state.write_mask;
+}
+
+uint GPU_stencil_mask_get()
+{
+ GPUStateMutable &state = GPU_context_active_get()->state_manager->mutable_state;
+ return state.stencil_write_mask;
+}
+
+eGPUDepthTest GPU_depth_test_get()
+{
+ GPUState &state = GPU_context_active_get()->state_manager->state;
+ return (eGPUDepthTest)state.depth_test;
}
-bool GPU_depth_test_enabled()
+eGPUStencilTest GPU_stencil_test_get()
{
GPUState &state = GPU_context_active_get()->state_manager->state;
- return state.depth_test != GPU_DEPTH_NONE;
+ return (eGPUStencilTest)state.stencil_test;
}
void GPU_scissor_get(int coords[4])
diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh
index 1ba79c7c048..a1bfefbaff5 100644
--- a/source/blender/gpu/intern/gpu_state_private.hh
+++ b/source/blender/gpu/intern/gpu_state_private.hh
@@ -35,13 +35,20 @@ namespace gpu {
* Try to keep small to reduce validation time. */
union GPUState {
struct {
- eGPUWriteMask write_mask : 13;
- eGPUBlend blend : 4;
- eGPUFaceCullTest culling_test : 2;
- eGPUDepthTest depth_test : 3;
- eGPUStencilTest stencil_test : 3;
- eGPUStencilOp stencil_op : 3;
- eGPUProvokingVertex provoking_vert : 1;
+ /** eGPUWriteMask */
+ uint32_t write_mask : 13;
+ /** eGPUBlend */
+ uint32_t blend : 4;
+ /** eGPUFaceCullTest */
+ uint32_t culling_test : 2;
+ /** eGPUDepthTest */
+ uint32_t depth_test : 3;
+ /** eGPUStencilTest */
+ uint32_t stencil_test : 3;
+ /** eGPUStencilOp */
+ uint32_t stencil_op : 3;
+ /** eGPUProvokingVertex */
+ uint32_t provoking_vert : 1;
/** Enable bits. */
uint32_t logic_op_xor : 1;
uint32_t invert_facing : 1;
@@ -144,6 +151,10 @@ inline GPUStateMutable operator~(const GPUStateMutable &a)
return r;
}
+/**
+ * State manager keeping track of the draw state and applying it before drawing.
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ **/
class GPUStateManager {
public:
GPUState state;
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 91990dac83f..e70eeece104 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -1158,9 +1158,9 @@ static GLenum convert_target_to_gl(int dimension, bool is_array)
{
switch (dimension) {
case 1:
- return is_array ? GL_TEXTURE_1D : GL_TEXTURE_1D_ARRAY;
+ return is_array ? GL_TEXTURE_1D_ARRAY : GL_TEXTURE_1D;
case 2:
- return is_array ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY;
+ return is_array ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
case 3:
return GL_TEXTURE_3D;
default:
@@ -2179,6 +2179,11 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
void GPU_samplers_init(void)
{
+ float max_anisotropy = 1.0f;
+ if (GLEW_EXT_texture_filter_anisotropic) {
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
+ }
+
glGenSamplers(GPU_SAMPLER_MAX, GG.samplers);
for (int i = 0; i < GPU_SAMPLER_MAX; i++) {
eGPUSamplerState state = static_cast<eGPUSamplerState>(i);
@@ -2193,7 +2198,7 @@ void GPU_samplers_init(void)
GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
/* TODO(fclem) Anisotropic level should be a render engine parameter. */
float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ?
- U.anisotropic_filter :
+ max_ff(max_anisotropy, U.anisotropic_filter) :
1.0f;
glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s);
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc
index e203ffd848f..94aa6bd76ab 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.cc
+++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc
@@ -13,7 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
* All rights reserved.
*/
@@ -27,58 +27,46 @@
#include "BLI_blenlib.h"
#include "BLI_math_base.h"
-#include "gpu_context_private.hh"
+#include "gpu_backend.hh"
#include "gpu_node_graph.h"
-#include "GPU_extensions.h"
-#include "GPU_glew.h"
#include "GPU_material.h"
-#include "GPU_uniformbuffer.h"
-
-typedef struct GPUUniformBuffer {
- /** Data size in bytes. */
- int size;
- /** GL handle for UBO. */
- GLuint bindcode;
- /** Current binding point. */
- int bindpoint;
- /** Continuous memory block to copy to GPU. Is own by the GPUUniformBuffer. */
- void *data;
-} GPUUniformBuffer;
-
-GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
+
+#include "GPU_extensions.h"
+
+#include "GPU_uniform_buffer.h"
+#include "gpu_uniform_buffer_private.hh"
+
+/* -------------------------------------------------------------------- */
+/** \name Creation & Deletion
+ * \{ */
+
+namespace blender::gpu {
+
+UniformBuf::UniformBuf(size_t size, const char *name)
{
/* Make sure that UBO is padded to size of vec4 */
BLI_assert((size % 16) == 0);
+ BLI_assert(size <= GPU_max_ubo_size());
- if (size > GPU_max_ubo_size()) {
- if (err_out) {
- BLI_strncpy(err_out, "GPUUniformBuffer: UBO too big", 256);
- }
- return NULL;
- }
-
- GPUUniformBuffer *ubo = (GPUUniformBuffer *)MEM_mallocN(sizeof(GPUUniformBuffer), __func__);
- ubo->size = size;
- ubo->data = NULL;
- ubo->bindcode = 0;
- ubo->bindpoint = -1;
-
- /* Direct init. */
- if (data != NULL) {
- GPU_uniformbuffer_update(ubo, data);
- }
+ size_in_bytes_ = size;
- return ubo;
+ BLI_strncpy(name_, name, sizeof(name_));
}
-void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
+UniformBuf::~UniformBuf()
{
- MEM_SAFE_FREE(ubo->data);
- GPU_buf_free(ubo->bindcode);
- MEM_freeN(ubo);
+ MEM_SAFE_FREE(data_);
}
+} // namespace blender::gpu
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Uniform buffer from GPUInput list
+ * \{ */
+
/**
* We need to pad some data types (vec3) on the C side
* To match the GPU expected memory block alignment.
@@ -111,10 +99,10 @@ static int inputs_cmp(const void *a, const void *b)
* Make sure we respect the expected alignment of UBOs.
* mat4, vec4, pad vec3 as vec4, then vec2, then floats.
*/
-static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
+static void buffer_from_list_inputs_sort(ListBase *inputs)
{
-/* Only support up to this type, if you want to extend it, make sure the
- * padding logic is correct for the new types. */
+/* Only support up to this type, if you want to extend it, make sure static void
+ * inputs_sobuffer_size_compute *inputs) padding logic is correct for the new types. */
#define MAX_UBO_GPU_TYPE GPU_MAT4
/* Order them as mat4, vec4, vec3, vec2, float. */
@@ -173,23 +161,9 @@ static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
#undef MAX_UBO_GPU_TYPE
}
-/**
- * Create dynamic UBO from parameters
- * Return NULL if failed to create or if \param inputs: is empty.
- *
- * \param inputs: ListBase of #BLI_genericNodeN(#GPUInput).
- */
-GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_out[256])
+static inline size_t buffer_size_from_list(ListBase *inputs)
{
- /* There is no point on creating an UBO if there is no arguments. */
- if (BLI_listbase_is_empty(inputs)) {
- return NULL;
- }
- /* Make sure we comply to the ubo alignment requirements. */
- gpu_uniformbuffer_inputs_sort(inputs);
-
size_t buffer_size = 0;
-
LISTBASE_FOREACH (LinkData *, link, inputs) {
const eGPUType gputype = get_padded_gpu_type(link);
buffer_size += gputype * sizeof(float);
@@ -197,8 +171,12 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
/* Round up to size of vec4. (Opengl Requirement) */
size_t alignment = sizeof(float[4]);
buffer_size = divide_ceil_u(buffer_size, alignment) * alignment;
- void *data = MEM_mallocN(buffer_size, __func__);
+ return buffer_size;
+}
+
+static inline void buffer_fill_from_list(void *data, ListBase *inputs)
+{
/* Now that we know the total ubo size we can start populating it. */
float *offset = (float *)data;
LISTBASE_FOREACH (LinkData *, link, inputs) {
@@ -206,71 +184,73 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
memcpy(offset, input->vec, input->type * sizeof(float));
offset += get_padded_gpu_type(link);
}
-
- /* Pass data as NULL for late init. */
- GPUUniformBuffer *ubo = GPU_uniformbuffer_create(buffer_size, NULL, err_out);
- /* Data will be update just before binding. */
- ubo->data = data;
- return ubo;
}
-static void gpu_uniformbuffer_init(GPUUniformBuffer *ubo)
-{
- BLI_assert(ubo->bindcode == 0);
- ubo->bindcode = GPU_buf_alloc();
+/** \} */
- if (ubo->bindcode == 0) {
- fprintf(stderr, "GPUUniformBuffer: UBO create failed");
- BLI_assert(0);
- return;
- }
+/* -------------------------------------------------------------------- */
+/** \name C-API
+ * \{ */
- glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
- glBufferData(GL_UNIFORM_BUFFER, ubo->size, NULL, GL_DYNAMIC_DRAW);
-}
+using namespace blender::gpu;
-void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+GPUUniformBuf *GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
{
- if (ubo->bindcode == 0) {
- gpu_uniformbuffer_init(ubo);
+ UniformBuf *ubo = GPUBackend::get()->uniformbuf_alloc(size, name);
+ /* Direct init. */
+ if (data != NULL) {
+ ubo->update(data);
}
-
- glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ return reinterpret_cast<GPUUniformBuf *>(ubo);
}
-void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
+/**
+ * Create UBO from inputs list.
+ * Return NULL if failed to create or if \param inputs: is empty.
+ *
+ * \param inputs: ListBase of #BLI_genericNodeN(#GPUInput).
+ */
+GPUUniformBuf *GPU_uniformbuf_create_from_list(ListBase *inputs, const char *name)
{
- if (number >= GPU_max_ubo_binds()) {
- fprintf(stderr, "Not enough UBO slots.\n");
- return;
+ /* There is no point on creating an UBO if there is no arguments. */
+ if (BLI_listbase_is_empty(inputs)) {
+ return NULL;
}
- if (ubo->bindcode == 0) {
- gpu_uniformbuffer_init(ubo);
- }
+ buffer_from_list_inputs_sort(inputs);
+ size_t buffer_size = buffer_size_from_list(inputs);
+ void *data = MEM_mallocN(buffer_size, __func__);
+ buffer_fill_from_list(data, inputs);
- if (ubo->data != NULL) {
- GPU_uniformbuffer_update(ubo, ubo->data);
- MEM_SAFE_FREE(ubo->data);
- }
+ UniformBuf *ubo = GPUBackend::get()->uniformbuf_alloc(buffer_size, name);
+ /* Defer data upload. */
+ ubo->attach_data(data);
+ return reinterpret_cast<GPUUniformBuf *>(ubo);
+}
- glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
- ubo->bindpoint = number;
+void GPU_uniformbuf_free(GPUUniformBuf *ubo)
+{
+ delete reinterpret_cast<UniformBuf *>(ubo);
}
-void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo)
+void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
{
-#ifndef NDEBUG
- glBindBufferBase(GL_UNIFORM_BUFFER, ubo->bindpoint, 0);
-#endif
- ubo->bindpoint = 0;
+ reinterpret_cast<UniformBuf *>(ubo)->update(data);
}
-void GPU_uniformbuffer_unbind_all(void)
+void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
{
- for (int i = 0; i < GPU_max_ubo_binds(); i++) {
- glBindBufferBase(GL_UNIFORM_BUFFER, i, 0);
- }
+ reinterpret_cast<UniformBuf *>(ubo)->bind(slot);
}
+
+void GPU_uniformbuf_unbind(GPUUniformBuf *ubo)
+{
+ reinterpret_cast<UniformBuf *>(ubo)->unbind();
+}
+
+void GPU_uniformbuf_unbind_all(void)
+{
+ /* FIXME */
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh
new file mode 100644
index 00000000000..288cbae526e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "BLI_sys_types.h"
+
+namespace blender {
+namespace gpu {
+
+#ifdef DEBUG
+# define DEBUG_NAME_LEN 8
+#else
+# define DEBUG_NAME_LEN 64
+#endif
+
+/**
+ * Implementation of Uniform Buffers.
+ * Base class which is then specialized for each implementation (GL, VK, ...).
+ **/
+class UniformBuf {
+ protected:
+ /** Data size in bytes. */
+ size_t size_in_bytes_;
+ /** Continuous memory block to copy to GPU. This data is owned by the UniformBuf. */
+ void *data_ = NULL;
+ /** Debugging name */
+ char name_[DEBUG_NAME_LEN];
+
+ public:
+ UniformBuf(size_t size, const char *name);
+ virtual ~UniformBuf();
+
+ virtual void update(const void *data) = 0;
+ virtual void bind(int slot) = 0;
+ virtual void unbind(void) = 0;
+
+ /** Used to defer data upload at drawing time.
+ * This is useful if the thread has no context bound.
+ * This transfers ownership to this UniformBuf. */
+ void attach_data(void *data)
+ {
+ data_ = data;
+ }
+};
+
+#undef DEBUG_NAME_LEN
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index 2b16f4482b4..ed317b3a0df 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -407,6 +407,6 @@ void VertexFormat_pack(GPUVertFormat *format)
void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *gpushader)
{
- const Shader *shader = static_cast<const Shader *>(gpushader);
+ const Shader *shader = reinterpret_cast<const Shader *>(gpushader);
shader->vertformat_from_shader(format);
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index ba938349761..fd1265dc2a6 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -41,7 +41,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_texture.h"
-#include "GPU_uniformbuffer.h"
+#include "GPU_uniform_buffer.h"
#include "GPU_viewport.h"
#include "DRW_engine.h"
@@ -1020,8 +1020,8 @@ void GPU_viewport_free(GPUViewport *viewport)
}
for (int i = 0; i < viewport->vmempool.ubo_len; i++) {
- GPU_uniformbuffer_free(viewport->vmempool.matrices_ubo[i]);
- GPU_uniformbuffer_free(viewport->vmempool.obinfos_ubo[i]);
+ GPU_uniformbuf_free(viewport->vmempool.matrices_ubo[i]);
+ GPU_uniformbuf_free(viewport->vmempool.obinfos_ubo[i]);
}
MEM_SAFE_FREE(viewport->vmempool.matrices_ubo);
MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo);