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:
authorClément Foucault <foucault.clem@gmail.com>2020-08-14 16:20:35 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-08-18 22:30:09 +0300
commit216d78687d2b9468b05fb598d1cef0b8424a40d2 (patch)
treeb6d53ddf17e27c2cc0805c46fe76764004109f81 /source/blender/gpu/intern
parentdf28d2c27e2bef54e5b4fc33d663125ac5ec83f7 (diff)
GPUShader: GL backend isolation
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_backend.hh3
-rw-r--r--source/blender/gpu/intern/gpu_batch.cc2
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c1
-rw-r--r--source/blender/gpu/intern/gpu_batch_utils.c1
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc13
-rw-r--r--source/blender/gpu/intern/gpu_matrix.cc18
-rw-r--r--source/blender/gpu/intern/gpu_shader.cc589
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h54
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.hh61
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc4
11 files changed, 225 insertions, 523 deletions
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index 25d165098a7..6ab0e32a754 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -28,6 +28,7 @@
#include "gpu_batch_private.hh"
#include "gpu_context_private.hh"
#include "gpu_drawlist_private.hh"
+#include "gpu_shader_private.hh"
namespace blender {
namespace gpu {
@@ -43,7 +44,7 @@ class GPUBackend {
virtual Batch *batch_alloc(void) = 0;
virtual DrawList *drawlist_alloc(int list_length) = 0;
// virtual FrameBuffer *framebuffer_alloc(void) = 0;
- // virtual Shader *shader_alloc(void) = 0;
+ virtual Shader *shader_alloc(const char *name) = 0;
// virtual Texture *texture_alloc(void) = 0;
};
diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc
index b0a0c142036..6ea82cbc4f1 100644
--- a/source/blender/gpu/intern/gpu_batch.cc
+++ b/source/blender/gpu/intern/gpu_batch.cc
@@ -39,7 +39,7 @@
#include "gpu_batch_private.hh"
#include "gpu_context_private.hh"
#include "gpu_primitive_private.h"
-#include "gpu_shader_private.h"
+#include "gpu_shader_private.hh"
#include "gpu_vertex_format_private.h"
#include <limits.h>
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index 71c971d8656..8adb1ba1ed3 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -35,7 +35,6 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h" /* own include */
#include "GPU_batch_utils.h"
-#include "gpu_shader_private.h"
/* -------------------------------------------------------------------- */
/** \name Local Structures
diff --git a/source/blender/gpu/intern/gpu_batch_utils.c b/source/blender/gpu/intern/gpu_batch_utils.c
index 0660d4a1724..e2d03d27035 100644
--- a/source/blender/gpu/intern/gpu_batch_utils.c
+++ b/source/blender/gpu/intern/gpu_batch_utils.c
@@ -28,7 +28,6 @@
#include "GPU_batch.h"
#include "GPU_batch_utils.h" /* own include */
-#include "gpu_shader_private.h"
/* -------------------------------------------------------------------- */
/** \name Polygon Creation (2D)
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index 2d137c2f21c..ed2950d8ee9 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -35,7 +35,7 @@
#include "gpu_attr_binding_private.h"
#include "gpu_context_private.hh"
#include "gpu_primitive_private.h"
-#include "gpu_shader_private.h"
+#include "gpu_shader_private.hh"
#include "gpu_vertex_format_private.h"
#include <stdlib.h>
@@ -145,10 +145,7 @@ GPUVertFormat *immVertexFormat(void)
void immBindShader(GPUShader *shader)
{
-#if TRUST_NO_ONE
- assert(imm.bound_program == NULL);
- assert(glIsProgram(shader->program));
-#endif
+ BLI_assert(imm.bound_program == NULL);
imm.bound_program = shader;
imm.shader_interface = shader->interface;
@@ -159,8 +156,8 @@ void immBindShader(GPUShader *shader)
GPU_shader_bind(shader);
get_attr_locations(&imm.vertex_format, &imm.attr_binding, imm.shader_interface);
- GPU_matrix_bind(imm.shader_interface);
- GPU_shader_set_srgb_uniform(imm.shader_interface);
+ GPU_matrix_bind(shader);
+ GPU_shader_set_srgb_uniform(shader);
}
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
@@ -375,7 +372,7 @@ static void immDrawSetup(void)
}
if (GPU_matrix_dirty_get()) {
- GPU_matrix_bind(imm.shader_interface);
+ GPU_matrix_bind(imm.bound_program);
}
}
diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc
index 5d8d77bbf1c..c9bb7e9dad9 100644
--- a/source/blender/gpu/intern/gpu_matrix.cc
+++ b/source/blender/gpu/intern/gpu_matrix.cc
@@ -643,13 +643,13 @@ const float (*GPU_matrix_normal_inverse_get(float m[3][3]))[3]
return m;
}
-void GPU_matrix_bind(const GPUShaderInterface *shaderface)
+void GPU_matrix_bind(GPUShader *shader)
{
/* set uniform values to matrix stack values
* 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);
@@ -658,32 +658,30 @@ void GPU_matrix_bind(const GPUShaderInterface *shaderface)
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);
- /* XXX(fclem) this works but this assumes shader is unused inside GPU_shader_uniform_vector. */
- GPUShader *sh = NULL;
if (MV != -1) {
- GPU_shader_uniform_vector(sh, MV, 16, 1, (const float *)GPU_matrix_model_view_get(NULL));
+ GPU_shader_uniform_vector(shader, MV, 16, 1, (const float *)GPU_matrix_model_view_get(NULL));
}
if (P != -1) {
- GPU_shader_uniform_vector(sh, P, 16, 1, (const float *)GPU_matrix_projection_get(NULL));
+ GPU_shader_uniform_vector(shader, P, 16, 1, (const float *)GPU_matrix_projection_get(NULL));
}
if (MVP != -1) {
GPU_shader_uniform_vector(
- sh, MVP, 16, 1, (const float *)GPU_matrix_model_view_projection_get(NULL));
+ shader, MVP, 16, 1, (const float *)GPU_matrix_model_view_projection_get(NULL));
}
if (N != -1) {
- GPU_shader_uniform_vector(sh, N, 9, 1, (const float *)GPU_matrix_normal_get(NULL));
+ GPU_shader_uniform_vector(shader, N, 9, 1, (const float *)GPU_matrix_normal_get(NULL));
}
if (MV_inv != -1) {
Mat4 m;
GPU_matrix_model_view_get(m);
invert_m4(m);
- GPU_shader_uniform_vector(sh, MV_inv, 16, 1, (const float *)m);
+ GPU_shader_uniform_vector(shader, MV_inv, 16, 1, (const float *)m);
}
if (P_inv != -1) {
Mat4 m;
GPU_matrix_projection_get(m);
invert_m4(m);
- GPU_shader_uniform_vector(sh, P_inv, 16, 1, (const float *)m);
+ GPU_shader_uniform_vector(shader, P_inv, 16, 1, (const float *)m);
}
gpu_matrix_state_active_set_dirty(false);
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc
index 7a44efce7fb..52d6ae3956e 100644
--- a/source/blender/gpu/intern/gpu_shader.cc
+++ b/source/blender/gpu/intern/gpu_shader.cc
@@ -29,6 +29,7 @@
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
+#include "BLI_vector.hh"
#include "BKE_appdir.h"
#include "BKE_global.h"
@@ -42,226 +43,98 @@
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
+#include "gpu_backend.hh"
#include "gpu_context_private.hh"
-#include "gpu_shader_private.h"
+#include "gpu_shader_private.hh"
extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[];
-/* Adjust these constants as needed. */
-#define MAX_DEFINE_LENGTH 256
-#define MAX_EXT_DEFINE_LENGTH 512
-
-#ifndef NDEBUG
-static uint g_shaderid = 0;
-#endif
+using namespace blender;
+using namespace blender::gpu;
/* -------------------------------------------------------------------- */
-/** \name Convenience functions
+/** \name Debug functions
* \{ */
-static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
+void Shader::print_errors(Span<const char *> sources, const char *log)
{
- int line = 1;
-
- fprintf(stderr, "GPUShader: %s error:\n", task);
-
- for (int i = 0; i < totcode; i++) {
- const char *c, *pos, *end = code[i] + strlen(code[i]);
+ // int line = 1;
- if (G.debug & G_DEBUG) {
- fprintf(stderr, "===== shader string %d ====\n", i + 1);
+ // for (int i = 0; i < totcode; i++) {
+ // const char *c, *pos, *end = code[i] + strlen(code[i]);
- c = code[i];
- while ((c < end) && (pos = strchr(c, '\n'))) {
- fprintf(stderr, "%2d ", line);
- fwrite(c, (pos + 1) - c, 1, stderr);
- c = pos + 1;
- line++;
- }
+ // if (G.debug & G_DEBUG) {
+ // fprintf(stderr, "===== shader string %d ====\n", i + 1);
- fprintf(stderr, "%s", c);
- }
- }
+ // c = code[i];
+ // while ((c < end) && (pos = strchr(c, '\n'))) {
+ // fprintf(stderr, "%2d ", line);
+ // fwrite(c, (pos + 1) - c, 1, stderr);
+ // c = pos + 1;
+ // line++;
+ // }
+ // fprintf(stderr, "%s", c);
+ // }
+ // }
+ /* TODO display the error lines context. */
fprintf(stderr, "%s\n", log);
+
+ UNUSED_VARS(sources);
}
-static const char *gpu_shader_version(void)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Creation / Destruction
+ * \{ */
+
+Shader::Shader(const char *sh_name)
{
- return "#version 330\n";
+ BLI_strncpy(this->name, sh_name, sizeof(this->name));
}
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
+Shader::~Shader()
{
- /* enable extensions for features that are not part of our base GLSL version
- * don't use an extension for something already available!
- */
-
- if (GLEW_ARB_texture_gather) {
- /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather
- * is reported to be supported but yield a compile error (see T55802). */
- if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) || GLEW_VERSION_4_0) {
- strcat(defines, "#extension GL_ARB_texture_gather: enable\n");
-
- /* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the
- * shader so double check the preprocessor define (see T56544). */
- if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) {
- strcat(defines, "#ifdef GL_ARB_texture_gather\n");
- strcat(defines, "# define GPU_ARB_texture_gather\n");
- strcat(defines, "#endif\n");
- }
- else {
- strcat(defines, "#define GPU_ARB_texture_gather\n");
- }
- }
- }
- if (GLEW_ARB_texture_query_lod) {
- /* a #version 400 feature, but we use #version 330 maximum so use extension */
- strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
- }
- if (GLEW_ARB_shader_draw_parameters) {
- strcat(defines, "#extension GL_ARB_shader_draw_parameters : enable\n");
- strcat(defines, "#define GPU_ARB_shader_draw_parameters\n");
- }
- if (GPU_arb_texture_cube_map_array_is_supported()) {
- strcat(defines, "#extension GL_ARB_texture_cube_map_array : enable\n");
- strcat(defines, "#define GPU_ARB_texture_cube_map_array\n");
+ if (this->interface) {
+ GPU_shaderinterface_discard(this->interface);
}
}
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
+static void standard_defines(Vector<const char *> &sources)
{
+ BLI_assert(sources.size() == 0);
+ /* Version needs to be first. Exact values will be added by implementation. */
+ sources.append("version");
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- strcat(defines, "#define GPU_ATI\n");
- if (GPU_crappy_amd_driver()) {
- strcat(defines, "#define GPU_DEPRECATED_AMD_DRIVER\n");
- }
+ sources.append("#define GPU_ATI\n");
}
else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- strcat(defines, "#define GPU_NVIDIA\n");
+ sources.append("#define GPU_NVIDIA\n");
}
else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- strcat(defines, "#define GPU_INTEL\n");
+ sources.append("#define GPU_INTEL\n");
}
-
/* some useful defines to detect OS type */
if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_WIN, GPU_DRIVER_ANY)) {
- strcat(defines, "#define OS_WIN\n");
+ sources.append("#define OS_WIN\n");
}
else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) {
- strcat(defines, "#define OS_MAC\n");
+ sources.append("#define OS_MAC\n");
}
else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
- strcat(defines, "#define OS_UNIX\n");
- }
-
- float derivatives_factors[2];
- GPU_get_dfdy_factors(derivatives_factors);
- if (derivatives_factors[0] == 1.0f) {
- strcat(defines, "#define DFDX_SIGN 1.0\n");
- }
- else {
- strcat(defines, "#define DFDX_SIGN -1.0\n");
- }
-
- if (derivatives_factors[1] == 1.0f) {
- strcat(defines, "#define DFDY_SIGN 1.0\n");
- }
- else {
- strcat(defines, "#define DFDY_SIGN -1.0\n");
- }
-}
-
-#define DEBUG_SHADER_NONE ""
-#define DEBUG_SHADER_VERTEX "vert"
-#define DEBUG_SHADER_FRAGMENT "frag"
-#define DEBUG_SHADER_GEOMETRY "geom"
-
-/**
- * Dump GLSL shaders to disk
- *
- * This is used for profiling shader performance externally and debug if shader code is correct.
- * If called with no code, it simply bumps the shader index, so different shaders for the same
- * program share the same index.
- */
-static void gpu_dump_shaders(const char **code, const int num_shaders, const char *extension)
-{
- if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) {
- return;
- }
-
- /* We use the same shader index for shaders in the same program.
- * So we call this function once before calling for the individual shaders. */
- static int shader_index = 0;
- if (code == NULL) {
- shader_index++;
- BLI_assert(STREQ(DEBUG_SHADER_NONE, extension));
- return;
+ sources.append("#define OS_UNIX\n");
}
- /* Determine the full path of the new shader. */
- char shader_path[FILE_MAX];
-
- char file_name[512] = {'\0'};
- sprintf(file_name, "%04d.%s", shader_index, extension);
-
- BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name);
-
- /* Write shader to disk. */
- FILE *f = fopen(shader_path, "w");
- if (f == NULL) {
- printf("Error writing to file: %s\n", shader_path);
- }
- for (int j = 0; j < num_shaders; j++) {
- fprintf(f, "%s", code[j]);
- }
- fclose(f);
- printf("Shader file written to disk: %s\n", shader_path);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Creation / Destruction
- * \{ */
-
-GPUShader *GPU_shader_create(const char *vertexcode,
- const char *fragcode,
- const char *geocode,
- const char *libcode,
- const char *defines,
- const char *shname)
-{
- return GPU_shader_create_ex(
- 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);
+ if (GPU_crappy_amd_driver()) {
+ sources.append("#define GPU_DEPRECATED_AMD_DRIVER\n");
}
-
- 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_create_ex(const char *vertexcode,
+GPUShader *GPU_shader_create_ex(const char *vertcode,
const char *fragcode,
- const char *geocode,
+ const char *geomcode,
const char *libcode,
const char *defines,
const eGPUShaderTFBType tf_type,
@@ -269,223 +142,113 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
const int tf_count,
const char *shname)
{
- GLint status;
- GLchar log[5000];
- GLsizei length = 0;
- GPUShader *shader;
- char standard_defines[MAX_DEFINE_LENGTH] = "";
- char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
-
- shader = (GPUShader *)MEM_callocN(sizeof(GPUShader), "GPUShader");
- gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
-
-#ifndef NDEBUG
- BLI_snprintf(shader->name, sizeof(shader->name), "%s_%u", shname, g_shaderid++);
-#else
- UNUSED_VARS(shname);
-#endif
-
/* At least a vertex shader and a fragment shader are required. */
- BLI_assert((fragcode != NULL) && (vertexcode != NULL));
-
- if (vertexcode) {
- shader->vertex = glCreateShader(GL_VERTEX_SHADER);
- }
- if (fragcode) {
- shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
- }
- if (geocode) {
- shader->geometry = glCreateShader(GL_GEOMETRY_SHADER);
- }
-
- shader->program = glCreateProgram();
-
- if (!shader->program || (vertexcode && !shader->vertex) || (fragcode && !shader->fragment) ||
- (geocode && !shader->geometry)) {
- fprintf(stderr, "GPUShader, object creation failed.\n");
- GPU_shader_free(shader);
- return NULL;
- }
-
- gpu_shader_standard_defines(standard_defines);
- gpu_shader_standard_extensions(standard_extensions);
-
- if (vertexcode) {
- const char *source[7];
- /* custom limit, may be too small, beware */
- int num_source = 0;
+ BLI_assert((fragcode != NULL) && (vertcode != NULL));
- source[num_source++] = gpu_shader_version();
- source[num_source++] =
- "#define GPU_VERTEX_SHADER\n"
- "#define IN_OUT out\n";
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
+ Shader *shader = GPUBackend::get()->shader_alloc(shname);
- if (geocode) {
- source[num_source++] = "#define USE_GEOMETRY_SHADER\n";
+ if (vertcode) {
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_VERTEX_SHADER\n");
+ sources.append("#define IN_OUT out\n");
+ if (geomcode) {
+ sources.append("#define USE_GEOMETRY_SHADER\n");
}
if (defines) {
- source[num_source++] = defines;
+ sources.append(defines);
}
- source[num_source++] = vertexcode;
-
- gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX);
-
- glAttachShader(shader->program, shader->vertex);
- glShaderSource(shader->vertex, num_source, source, NULL);
+ sources.append(vertcode);
- glCompileShader(shader->vertex);
- glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
+ shader->vertex_shader_from_glsl(sources);
}
if (fragcode) {
- const char *source[8];
- int num_source = 0;
-
- source[num_source++] = gpu_shader_version();
- source[num_source++] =
- "#define GPU_FRAGMENT_SHADER\n"
- "#define IN_OUT in\n";
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
-
- if (geocode) {
- source[num_source++] = "#define USE_GEOMETRY_SHADER\n";
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_FRAGMENT_SHADER\n");
+ sources.append("#define IN_OUT in\n");
+ if (geomcode) {
+ sources.append("#define USE_GEOMETRY_SHADER\n");
}
if (defines) {
- source[num_source++] = defines;
+ sources.append(defines);
}
if (libcode) {
- source[num_source++] = libcode;
+ sources.append(libcode);
}
- source[num_source++] = fragcode;
-
- gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT);
-
- glAttachShader(shader->program, shader->fragment);
- glShaderSource(shader->fragment, num_source, source, NULL);
+ sources.append(fragcode);
- glCompileShader(shader->fragment);
- glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
+ shader->fragment_shader_from_glsl(sources);
}
- if (geocode) {
- const char *source[6];
- int num_source = 0;
-
- source[num_source++] = gpu_shader_version();
- source[num_source++] = "#define GPU_GEOMETRY_SHADER\n";
- source[num_source++] = standard_extensions;
- source[num_source++] = standard_defines;
-
+ if (geomcode) {
+ Vector<const char *> sources;
+ standard_defines(sources);
+ sources.append("#define GPU_GEOMETRY_SHADER\n");
if (defines) {
- source[num_source++] = defines;
+ sources.append(defines);
}
- source[num_source++] = geocode;
+ sources.append(geomcode);
- gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY);
-
- glAttachShader(shader->program, shader->geometry);
- glShaderSource(shader->geometry, num_source, source, NULL);
-
- glCompileShader(shader->geometry);
- glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status);
-
- if (!status) {
- glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log);
- shader_print_errors("compile", log, source, num_source);
-
- GPU_shader_free(shader);
- return NULL;
- }
+ shader->geometry_shader_from_glsl(sources);
}
- if (tf_names != NULL) {
- glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS);
- /* Primitive type must be setup */
+ if (tf_names != NULL && tf_count > 0) {
BLI_assert(tf_type != GPU_SHADER_TFB_NONE);
- shader->feedback_transform_type = tf_type;
+ shader->transform_feedback_names_set(Span<const char *>(tf_names, tf_count), tf_type);
}
- glLinkProgram(shader->program);
- glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
- if (!status) {
- glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
- /* print attached shaders in pipeline order */
- if (defines) {
- shader_print_errors("linking", log, &defines, 1);
- }
- if (vertexcode) {
- shader_print_errors("linking", log, &vertexcode, 1);
- }
- if (geocode) {
- shader_print_errors("linking", log, &geocode, 1);
- }
- if (libcode) {
- shader_print_errors("linking", log, &libcode, 1);
- }
- if (fragcode) {
- shader_print_errors("linking", log, &fragcode, 1);
- }
-
- GPU_shader_free(shader);
+ if (!shader->finalize()) {
+ delete shader;
return NULL;
- }
+ };
- glUseProgram(shader->program);
- shader->interface = GPU_shaderinterface_create(shader->program);
+ return static_cast<GPUShader *>(shader);
+}
- return shader;
+void GPU_shader_free(GPUShader *shader)
+{
+ delete static_cast<Shader *>(shader);
}
-#undef DEBUG_SHADER_GEOMETRY
-#undef DEBUG_SHADER_FRAGMENT
-#undef DEBUG_SHADER_VERTEX
-#undef DEBUG_SHADER_NONE
+/** \} */
-void GPU_shader_free(GPUShader *shader)
+/* -------------------------------------------------------------------- */
+/** \name Creation utils
+ * \{ */
+
+GPUShader *GPU_shader_create(const char *vertcode,
+ const char *fragcode,
+ const char *geomcode,
+ const char *libcode,
+ const char *defines,
+ const char *shname)
{
-#if 0 /* Would be nice to have, but for now the Deferred compilation \
- * does not have a GPUContext. */
- BLI_assert(GPU_context_active_get() != NULL);
-#endif
- BLI_assert(shader);
+ return GPU_shader_create_ex(
+ vertcode, fragcode, geomcode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, shname);
+}
- if (shader->vertex) {
- glDeleteShader(shader->vertex);
- }
- if (shader->geometry) {
- glDeleteShader(shader->geometry);
- }
- if (shader->fragment) {
- glDeleteShader(shader->fragment);
+GPUShader *GPU_shader_create_from_python(const char *vertcode,
+ const char *fragcode,
+ const char *geomcode,
+ const char *libcode,
+ const char *defines)
+{
+ char *libcodecat = NULL;
+
+ if (libcode == NULL) {
+ libcode = datatoc_gpu_shader_colorspace_lib_glsl;
}
- if (shader->program) {
- glDeleteProgram(shader->program);
+ else {
+ libcode = libcodecat = BLI_strdupcat(libcode, datatoc_gpu_shader_colorspace_lib_glsl);
}
- if (shader->interface) {
- GPU_shaderinterface_discard(shader->interface);
- }
+ GPUShader *sh = GPU_shader_create_ex(
+ vertcode, fragcode, geomcode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, NULL);
- MEM_freeN(shader);
+ MEM_SAFE_FREE(libcodecat);
+ return sh;
}
static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_is_alloc)
@@ -563,21 +326,21 @@ struct GPUShader *GPU_shader_create_from_arrays_impl(
/** \name Binding
* \{ */
-void GPU_shader_bind(GPUShader *shader)
+void GPU_shader_bind(GPUShader *gpu_shader)
{
- BLI_assert(shader && shader->program);
+ Shader *shader = static_cast<Shader *>(gpu_shader);
GPUContext *ctx = GPU_context_active_get();
if (ctx->shader != shader) {
ctx->shader = shader;
- glUseProgram(shader->program);
- GPU_matrix_bind(shader->interface);
- GPU_shader_set_srgb_uniform(shader->interface);
+ shader->bind();
+ GPU_matrix_bind(shader);
+ GPU_shader_set_srgb_uniform(shader);
}
if (GPU_matrix_dirty_get()) {
- GPU_matrix_bind(shader->interface);
+ GPU_matrix_bind(shader);
}
}
@@ -585,8 +348,10 @@ void GPU_shader_unbind(void)
{
#ifndef NDEBUG
GPUContext *ctx = GPU_context_active_get();
+ if (ctx->shader) {
+ static_cast<Shader *>(ctx->shader)->unbind();
+ }
ctx->shader = NULL;
- glUseProgram(0);
#endif
}
@@ -594,34 +359,18 @@ void GPU_shader_unbind(void)
/* -------------------------------------------------------------------- */
/** \name Transform feedback
+ *
+ * TODO(fclem) Should be replaced by compute shaders.
* \{ */
-bool GPU_shader_transform_feedback_enable(GPUShader *shader, uint vbo_id)
+bool GPU_shader_transform_feedback_enable(GPUShader *shader, GPUVertBuf *vertbuf)
{
- if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) {
- return false;
- }
-
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id);
-
- switch (shader->feedback_transform_type) {
- case GPU_SHADER_TFB_POINTS:
- glBeginTransformFeedback(GL_POINTS);
- return true;
- case GPU_SHADER_TFB_LINES:
- glBeginTransformFeedback(GL_LINES);
- return true;
- case GPU_SHADER_TFB_TRIANGLES:
- glBeginTransformFeedback(GL_TRIANGLES);
- return true;
- default:
- return false;
- }
+ return static_cast<Shader *>(shader)->transform_feedback_enable(vertbuf);
}
-void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
+void GPU_shader_transform_feedback_disable(GPUShader *shader)
{
- glEndTransformFeedback();
+ static_cast<Shader *>(shader)->transform_feedback_disable();
}
/** \} */
@@ -632,49 +381,42 @@ void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
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 : -1;
}
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
{
- BLI_assert(shader && shader->program);
return GPU_shaderinterface_uniform_builtin(shader->interface,
static_cast<GPUUniformBuiltin>(builtin));
}
int GPU_shader_get_builtin_block(GPUShader *shader, int builtin)
{
- BLI_assert(shader && shader->program);
return GPU_shaderinterface_block_builtin(shader->interface,
static_cast<GPUUniformBlockBuiltin>(builtin));
}
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
{
- BLI_assert(shader && shader->program);
const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, 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;
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
- BLI_assert(shader && shader->program);
const GPUShaderInput *attr = GPU_shaderinterface_attr(shader->interface, name);
return attr ? attr->location : -1;
}
@@ -686,9 +428,10 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name)
* \{ */
/* Clement : Temp */
-int GPU_shader_get_program(GPUShader *shader)
+int GPU_shader_get_program(GPUShader *UNUSED(shader))
{
- return (int)shader->program;
+ /* TODO fixme */
+ return (int)0;
}
/** \} */
@@ -698,57 +441,15 @@ int GPU_shader_get_program(GPUShader *shader)
* \{ */
void GPU_shader_uniform_vector(
- GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
+ GPUShader *shader, int loc, int len, int arraysize, const float *value)
{
- if (location == -1 || value == NULL) {
- return;
- }
-
- switch (length) {
- case 1:
- glUniform1fv(location, arraysize, value);
- break;
- case 2:
- glUniform2fv(location, arraysize, value);
- break;
- case 3:
- glUniform3fv(location, arraysize, value);
- break;
- case 4:
- glUniform4fv(location, arraysize, value);
- break;
- case 9:
- glUniformMatrix3fv(location, arraysize, 0, value);
- break;
- case 16:
- glUniformMatrix4fv(location, arraysize, 0, value);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ static_cast<Shader *>(shader)->uniform_float(loc, len, arraysize, value);
}
void GPU_shader_uniform_vector_int(
- GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
-{
- switch (length) {
- case 1:
- glUniform1iv(location, arraysize, value);
- break;
- case 2:
- glUniform2iv(location, arraysize, value);
- break;
- case 3:
- glUniform3iv(location, arraysize, value);
- break;
- case 4:
- glUniform4iv(location, arraysize, value);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ GPUShader *shader, int loc, int len, int arraysize, const int *value)
+{
+ static_cast<Shader *>(shader)->uniform_int(loc, len, arraysize, value);
}
void GPU_shader_uniform_int(GPUShader *shader, int location, int value)
@@ -851,11 +552,11 @@ void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, cons
static int g_shader_builtin_srgb_transform = 0;
-void GPU_shader_set_srgb_uniform(const GPUShaderInterface *interface)
+void GPU_shader_set_srgb_uniform(GPUShader *shader)
{
- int32_t loc = GPU_shaderinterface_uniform_builtin(interface, GPU_UNIFORM_SRGB_TRANSFORM);
+ int32_t loc = GPU_shaderinterface_uniform_builtin(shader->interface, GPU_UNIFORM_SRGB_TRANSFORM);
if (loc != -1) {
- glUniform1i(loc, g_shader_builtin_srgb_transform);
+ 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 9c0692b76e2..da5bcaeca17 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -42,8 +42,6 @@
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
-#include "gpu_shader_private.h"
-
/* Adjust these constants as needed. */
#define MAX_DEFINE_LENGTH 256
#define MAX_EXT_DEFINE_LENGTH 512
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
deleted file mode 100644
index 0f89fbda737..00000000000
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup gpu
- */
-
-#pragma once
-
-#include "GPU_shader_interface.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct GPUShader {
- /** Handle for full program (links shader stages below). */
- GLuint program;
-
- /** Handle for vertex shader. */
- GLuint vertex;
- /** Handle for geometry shader. */
- GLuint geometry;
- /** Handle for fragment shader. */
- GLuint fragment;
-
- /** Cached uniform & attribute interface for shader. */
- GPUShaderInterface *interface;
-
- int feedback_transform_type;
-#ifndef NDEBUG
- char name[64];
-#endif
-};
-
-/* XXX do not use it. Special hack to use OCIO with batch API. */
-GPUShader *immGetShader(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh
new file mode 100644
index 00000000000..29e78dcd533
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_private.hh
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "BLI_span.hh"
+
+#include "GPU_shader.h"
+#include "GPU_shader_interface.h"
+#include "GPU_vertex_buffer.h"
+
+namespace blender {
+namespace gpu {
+
+class Shader : public GPUShader {
+ public:
+ Shader(const char *name);
+ virtual ~Shader();
+
+ virtual void vertex_shader_from_glsl(MutableSpan<const char *> sources) = 0;
+ virtual void geometry_shader_from_glsl(MutableSpan<const char *> sources) = 0;
+ virtual void fragment_shader_from_glsl(MutableSpan<const char *> sources) = 0;
+ virtual bool finalize(void) = 0;
+
+ virtual void transform_feedback_names_set(Span<const char *> name_list,
+ const eGPUShaderTFBType geom_type) = 0;
+ virtual bool transform_feedback_enable(GPUVertBuf *) = 0;
+ virtual void transform_feedback_disable(void) = 0;
+
+ virtual void bind(void) = 0;
+ virtual void unbind(void) = 0;
+
+ virtual void uniform_float(int location, int comp_len, int array_size, const float *data) = 0;
+ virtual void uniform_int(int location, int comp_len, int array_size, const int *data) = 0;
+
+ protected:
+ void print_errors(Span<const char *> sources, const char *log);
+};
+
+} // namespace gpu
+} // namespace blender
+
+/* XXX do not use it. Special hack to use OCIO with batch API. */
+GPUShader *immGetShader(void);
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index 2e8017660d0..a25b2b67e2e 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -33,7 +33,6 @@
#include "BLI_utildefines.h"
#include "GPU_shader.h"
-#include "gpu_shader_private.h"
#define PACK_DEBUG 0
@@ -480,6 +479,8 @@ static void get_fetch_mode_and_comp_type(int gl_type,
void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader)
{
+ UNUSED_VARS(format, shader);
+#if 0 /* TODO (fclem) port to GLShader */
GPU_vertformat_clear(format);
GPUVertAttr *attr = &format->attrs[0];
@@ -512,4 +513,5 @@ void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader)
attr->comp_type = comp_type;
attr += 1;
}
+#endif
}