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:
-rw-r--r--source/blender/gpu/GPU_extensions.h3
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c95
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c27
3 files changed, 119 insertions, 6 deletions
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 23ac95775d7..1059ba06953 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -41,6 +41,9 @@ extern "C" {
int GPU_max_texture_size(void);
int GPU_max_texture_layers(void);
int GPU_max_textures(void);
+int GPU_max_textures_vert(void);
+int GPU_max_textures_geom(void);
+int GPU_max_textures_frag(void);
float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void);
int GPU_max_cube_map_size(void);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 7c312f5f36b..db893251149 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -185,7 +185,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip a variable/function name */
while (*str) {
- if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r'))
break;
else {
if (token && len < max - 1) {
@@ -203,7 +203,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip the next special characters:
* note the missing ')' */
while (*str) {
- if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r'))
str++;
else
break;
@@ -1764,6 +1764,87 @@ GPUPass *GPU_generate_pass_new(
return pass;
}
+static int count_active_texture_sampler(GPUShader *shader, char *source)
+{
+ char *code = source;
+ int samplers_id[64]; /* Remember this is per stage. */
+ int sampler_len = 0;
+
+ while((code = strstr(code, "uniform "))) {
+ /* Move past "uniform". */
+ code += 7;
+ /* Skip following spaces. */
+ while (*code == ' ') { code++; }
+ /* Skip "i" from potential isamplers. */
+ if (*code == 'i') { code++; }
+ /* Skip following spaces. */
+ if (gpu_str_prefix(code, "sampler")) {
+ /* Move past "uniform". */
+ code += 7;
+ /* Skip sampler type suffix. */
+ while (*code != ' ' && *code != '\0') { code++; }
+ /* Skip following spaces. */
+ while (*code == ' ') { code++; }
+
+ if (*code != '\0') {
+ char sampler_name[64];
+ code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name));
+ int id = GPU_shader_get_uniform(shader, sampler_name);
+
+ if (id == -1) {
+ continue;
+ }
+ /* Catch duplicates. */
+ bool is_duplicate = false;
+ for (int i = 0; i < sampler_len; ++i) {
+ if (samplers_id[i] == id) {
+ is_duplicate = true;
+ }
+ }
+
+ if (!is_duplicate) {
+ samplers_id[sampler_len] = id;
+ sampler_len++;
+ }
+ }
+ }
+ }
+
+ return sampler_len;
+}
+
+static bool gpu_pass_shader_validate(GPUPass *pass)
+{
+ if (pass->shader == NULL) {
+ return false;
+ }
+
+ /* NOTE: The only drawback of this method is that it will count a sampler
+ * used in the fragment shader and only declared (but not used) in the vertex
+ * shader as used by both. But this corner case is not happening for now. */
+ int vert_samplers_len = count_active_texture_sampler(pass->shader, pass->vertexcode);
+ int frag_samplers_len = count_active_texture_sampler(pass->shader, pass->fragmentcode);
+
+ int total_samplers_len = vert_samplers_len + frag_samplers_len;
+
+ /* Validate against opengl limit. */
+ if ((frag_samplers_len > GPU_max_textures_frag()) ||
+ (frag_samplers_len > GPU_max_textures_vert()))
+ {
+ return false;
+ }
+
+ if (pass->geometrycode) {
+ int geom_samplers_len = count_active_texture_sampler(pass->shader, pass->geometrycode);
+ total_samplers_len += geom_samplers_len;
+ if (geom_samplers_len > GPU_max_textures_geom()) {
+ return false;
+ }
+ }
+
+ return (total_samplers_len <= GPU_max_textures());
+}
+
void GPU_pass_compile(GPUPass *pass, const char *shname)
{
if (!pass->compiled) {
@@ -1774,6 +1855,16 @@ void GPU_pass_compile(GPUPass *pass, const char *shname)
NULL,
pass->defines,
shname);
+
+ /* NOTE: Some drivers / gpu allows more active samplers than the opengl limit.
+ * We need to make sure to count active samplers to avoid undefined behaviour. */
+ if (!gpu_pass_shader_validate(pass)) {
+ if (pass->shader != NULL) {
+ fprintf(stderr, "GPUShader: error: too many samplers in shader.\n");
+ GPU_shader_free(pass->shader);
+ }
+ pass->shader = NULL;
+ }
pass->compiled = true;
}
}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 112618de92d..198f986d06e 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -68,6 +68,9 @@ static struct GPUGlobal {
GLint maxtexlayers;
GLint maxcubemapsize;
GLint maxtextures;
+ GLint maxtexturesfrag;
+ GLint maxtexturesgeom;
+ GLint maxtexturesvert;
GLint maxubosize;
GLint maxubobinds;
int colordepth;
@@ -106,6 +109,21 @@ int GPU_max_textures(void)
return GG.maxtextures;
}
+int GPU_max_textures_frag(void)
+{
+ return GG.maxtexturesfrag;
+}
+
+int GPU_max_textures_geom(void)
+{
+ return GG.maxtexturesgeom;
+}
+
+int GPU_max_textures_vert(void)
+{
+ return GG.maxtexturesvert;
+}
+
float GPU_max_texture_anisotropy(void)
{
return GG.max_anisotropy;
@@ -144,7 +162,10 @@ void gpu_extensions_init(void)
*/
BLI_assert(GLEW_VERSION_3_3);
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag);
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert);
+ glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom);
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
@@ -172,9 +193,7 @@ void gpu_extensions_init(void)
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
- if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
- glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
- }
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
const char *vendor = (const char *)glGetString(GL_VENDOR);
const char *renderer = (const char *)glGetString(GL_RENDERER);