X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Funiform_query.cpp;h=3108d348d6fa90f88137c97cae6ef1419a331504;hb=e70d0d22a2dccc1df2c88890a2964491cdafac94;hp=33c959dc1a5583f3b2faf6804cf129286a5b115a;hpb=ef56cf7738ecb25e8c668c509097fc714ca71c96;p=mesa.git diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index 33c959dc1a5..3108d348d6f 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -31,11 +31,11 @@ #include "main/shaderapi.h" #include "main/shaderobj.h" #include "main/uniforms.h" -#include "glsl/ir.h" -#include "glsl/ir_uniform.h" -#include "glsl/glsl_parser_extras.h" -#include "glsl/program.h" -#include "program/hash_table.h" +#include "compiler/glsl/ir.h" +#include "compiler/glsl/ir_uniform.h" +#include "compiler/glsl/glsl_parser_extras.h" +#include "compiler/glsl/program.h" +#include "util/bitscan.h" extern "C" void GLAPIENTRY @@ -179,10 +179,10 @@ validate_uniform_parameters(struct gl_context *ctx, /* Check that the given location is in bounds of uniform remap table. * Unlinked programs will have NumUniformRemapTable == 0, so we can take - * the shProg->LinkStatus check out of the main path. + * the shProg->data->LinkStatus check out of the main path. */ if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) { - if (!shProg->LinkStatus) + if (!shProg->data->LinkStatus) _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller); else @@ -193,7 +193,7 @@ validate_uniform_parameters(struct gl_context *ctx, } if (location == -1) { - if (!shProg->LinkStatus) + if (!shProg->data->LinkStatus) _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller); @@ -318,19 +318,12 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, return; } - if ((uni->type->base_type == GLSL_TYPE_DOUBLE && - returnType != GLSL_TYPE_DOUBLE) || - (uni->type->base_type != GLSL_TYPE_DOUBLE && - returnType == GLSL_TYPE_DOUBLE)) { - _mesa_error( ctx, GL_INVALID_OPERATION, - "glGetnUniform*vARB(incompatible uniform types)"); - return; - } { unsigned elements = (uni->type->is_sampler()) ? 1 : uni->type->components(); - const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1; + const int dmul = uni->type->is_64bit() ? 2 : 1; + const int rmul = glsl_base_type_is_64bit(returnType) ? 2 : 1; /* Calculate the source base address *BEFORE* modifying elements to * account for the size of the user's buffer. @@ -342,7 +335,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE); /* doubles have a different size than the other 3 types */ - unsigned bytes = sizeof(src[0]) * elements * dmul; + unsigned bytes = sizeof(src[0]) * elements * rmul; if (bufSize < 0 || bytes > (unsigned) bufSize) { _mesa_error( ctx, GL_INVALID_OPERATION, "glGetnUniform*vARB(out of bounds: bufSize is %d," @@ -366,32 +359,68 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, } else { union gl_constant_value *const dst = (union gl_constant_value *) paramsOut; - /* This code could be optimized by putting the loop inside the switch * statements. However, this is not expected to be * performance-critical code. */ for (unsigned i = 0; i < elements; i++) { + int sidx = i * dmul; + int didx = i * rmul; + switch (returnType) { case GLSL_TYPE_FLOAT: switch (uni->type->base_type) { case GLSL_TYPE_UINT: - dst[i].f = (float) src[i].u; + dst[didx].f = (float) src[sidx].u; break; case GLSL_TYPE_INT: case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: - dst[i].f = (float) src[i].i; + dst[didx].f = (float) src[sidx].i; break; case GLSL_TYPE_BOOL: - dst[i].f = src[i].i ? 1.0f : 0.0f; + dst[didx].f = src[sidx].i ? 1.0f : 0.0f; + break; + case GLSL_TYPE_DOUBLE: { + double tmp; + memcpy(&tmp, &src[sidx].f, sizeof(tmp)); + dst[didx].f = tmp; break; + } + default: + assert(!"Should not get here."); + break; + } + break; + case GLSL_TYPE_DOUBLE: + switch (uni->type->base_type) { + case GLSL_TYPE_UINT: { + double tmp = src[sidx].u; + memcpy(&dst[didx].f, &tmp, sizeof(tmp)); + break; + } + case GLSL_TYPE_INT: + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: { + double tmp = src[sidx].i; + memcpy(&dst[didx].f, &tmp, sizeof(tmp)); + break; + } + case GLSL_TYPE_BOOL: { + double tmp = src[sidx].i ? 1.0 : 0.0; + memcpy(&dst[didx].f, &tmp, sizeof(tmp)); + break; + } + case GLSL_TYPE_FLOAT: { + double tmp = src[sidx].f; + memcpy(&dst[didx].f, &tmp, sizeof(tmp)); + break; + } default: assert(!"Should not get here."); break; } break; - case GLSL_TYPE_INT: case GLSL_TYPE_UINT: switch (uni->type->base_type) { @@ -413,11 +442,17 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, * a floating-point value is rounded to the * nearest integer..." */ - dst[i].i = IROUND(src[i].f); + dst[didx].i = IROUND(src[sidx].f); break; case GLSL_TYPE_BOOL: - dst[i].i = src[i].i ? 1 : 0; + dst[didx].i = src[sidx].i ? 1 : 0; + break; + case GLSL_TYPE_DOUBLE: { + double tmp; + memcpy(&tmp, &src[sidx].f, sizeof(tmp)); + dst[didx].i = IROUNDD(tmp); break; + } default: assert(!"Should not get here."); break; @@ -464,9 +499,12 @@ log_uniform(const void *values, enum glsl_base_type basicType, case GLSL_TYPE_FLOAT: printf("%g ", v[i].f); break; - case GLSL_TYPE_DOUBLE: - printf("%g ", *(double* )&v[i * 2].f); + case GLSL_TYPE_DOUBLE: { + double tmp; + memcpy(&tmp, &v[i * 2].f, sizeof(tmp)); + printf("%g ", tmp); break; + } default: assert(!"Should not get here."); break; @@ -527,7 +565,7 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni, */ const unsigned components = MAX2(1, uni->type->vector_elements); const unsigned vectors = MAX2(1, uni->type->matrix_columns); - const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1; + const int dmul = uni->type->is_64bit() ? 2 : 1; /* Store the data in the driver's requested type in the driver's storage * areas. @@ -556,14 +594,31 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni, unsigned j; unsigned v; - for (j = 0; j < count; j++) { - for (v = 0; v < vectors; v++) { - memcpy(dst, src, src_vector_byte_stride); - src += src_vector_byte_stride; - dst += store->vector_stride; + if (src_vector_byte_stride == store->vector_stride) { + if (extra_stride) { + for (j = 0; j < count; j++) { + memcpy(dst, src, src_vector_byte_stride * vectors); + src += src_vector_byte_stride * vectors; + dst += store->vector_stride * vectors; + + dst += extra_stride; + } + } else { + /* Unigine Heaven benchmark gets here */ + memcpy(dst, src, src_vector_byte_stride * vectors * count); + src += src_vector_byte_stride * vectors * count; + dst += store->vector_stride * vectors * count; } + } else { + for (j = 0; j < count; j++) { + for (v = 0; v < vectors; v++) { + memcpy(dst, src, src_vector_byte_stride); + src += src_vector_byte_stride; + dst += store->vector_stride; + } - dst += extra_stride; + dst += extra_stride; + } } break; } @@ -647,7 +702,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, unsigned src_components) { unsigned offset; - int size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1; + int size_mul = glsl_base_type_is_64bit(basicType) ? 2 : 1; struct gl_uniform_storage *const uni = validate_uniform_parameters(ctx, shProg, location, count, @@ -737,6 +792,10 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, return; } } + /* We need to reset the validate flag on changes to samplers in case + * two different sampler types are set to the same texture unit. + */ + ctx->_Shader->Validated = GL_FALSE; } if (uni->type->is_image()) { @@ -790,8 +849,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } - uni->initialized = true; - _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); /* If the uniform is a sampler, do the extra magic necessary to propagate @@ -800,15 +857,15 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, if (uni->type->is_sampler()) { bool flushed = false; for (int i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_shader *const sh = shProg->_LinkedShaders[i]; + struct gl_linked_shader *const sh = shProg->_LinkedShaders[i]; /* If the shader stage doesn't use the sampler uniform, skip this. */ - if (sh == NULL || !uni->sampler[i].active) + if (sh == NULL || !uni->opaque[i].active) continue; for (int j = 0; j < count; j++) { - sh->SamplerUnits[uni->sampler[i].index + offset + j] = + sh->SamplerUnits[uni->opaque[i].index + offset + j] = ((unsigned *) values)[j]; } @@ -820,9 +877,10 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, * been modified. */ bool changed = false; - for (unsigned j = 0; j < ARRAY_SIZE(prog->SamplerUnits); j++) { - if ((sh->active_samplers & (1U << j)) != 0 - && (prog->SamplerUnits[j] != sh->SamplerUnits[j])) { + GLbitfield mask = sh->active_samplers; + while (mask) { + const int j = u_bit_scan(&mask); + if (prog->SamplerUnits[j] != sh->SamplerUnits[j]) { changed = true; break; } @@ -834,10 +892,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, flushed = true; } - memcpy(prog->SamplerUnits, - sh->SamplerUnits, - sizeof(sh->SamplerUnits)); - _mesa_update_shader_textures_used(shProg, prog); if (ctx->Driver.SamplerUniformChange) ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog); @@ -850,11 +904,11 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, */ if (uni->type->is_image()) { for (int i = 0; i < MESA_SHADER_STAGES; i++) { - if (uni->image[i].active) { - struct gl_shader *sh = shProg->_LinkedShaders[i]; + if (uni->opaque[i].active) { + struct gl_linked_shader *sh = shProg->_LinkedShaders[i]; for (int j = 0; j < count; j++) - sh->ImageUnits[uni->image[i].index + offset + j] = + sh->ImageUnits[uni->opaque[i].index + offset + j] = ((GLint *) values)[j]; } } @@ -970,7 +1024,7 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, elements = components * vectors; if (!transpose) { - memcpy(&uni->storage[elements * offset], values, + memcpy(&uni->storage[size_mul * elements * offset], values, sizeof(uni->storage[0]) * elements * count * size_mul); } else if (basicType == GLSL_TYPE_FLOAT) { /* Copy and transpose the matrix. @@ -1005,8 +1059,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, } } - uni->initialized = true; - _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); } @@ -1016,7 +1068,7 @@ _mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg, char *errMsg, size_t errMsgLength) { /* Shader does not have samplers. */ - if (shProg->NumUniformStorage == 0) + if (shProg->data->NumUniformStorage == 0) return true; if (!shProg->SamplersValidated) { @@ -1045,58 +1097,51 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline) * - The number of active samplers in the program exceeds the * maximum number of texture image units allowed." */ + + GLbitfield mask; + GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + struct gl_linked_shader *shader; unsigned active_samplers = 0; const struct gl_shader_program **shProg = (const struct gl_shader_program **) pipeline->CurrentProgram; - const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - memset(unit_types, 0, sizeof(unit_types)); + + memset(TexturesUsed, 0, sizeof(TexturesUsed)); for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) { if (!shProg[idx]) continue; - for (unsigned i = 0; i < shProg[idx]->NumUniformStorage; i++) { - const struct gl_uniform_storage *const storage = - &shProg[idx]->UniformStorage[i]; + shader = shProg[idx]->_LinkedShaders[idx]; + if (!shader || !shader->Program) + continue; - if (!storage->type->is_sampler()) + mask = shader->Program->SamplersUsed; + while (mask) { + const int s = u_bit_scan(&mask); + GLuint unit = shader->SamplerUnits[s]; + GLuint tgt = shader->SamplerTargets[s]; + + /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a + * great job of eliminating unused uniforms currently so for now + * don't throw an error if two sampler types both point to 0. + */ + if (unit == 0) continue; - active_samplers++; - - const unsigned count = MAX2(1, storage->array_elements); - for (unsigned j = 0; j < count; j++) { - const unsigned unit = storage->storage[j].i; - - /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a - * great job of eliminating unused uniforms currently so for now - * don't throw an error if two sampler types both point to 0. - */ - if (unit == 0) - continue; - - /* The types of the samplers associated with a particular texture - * unit must be an exact match. Page 74 (page 89 of the PDF) of - * the OpenGL 3.3 core spec says: - * - * "It is not allowed to have variables of different sampler - * types pointing to the same texture image unit within a - * program object." - */ - if (unit_types[unit] == NULL) { - unit_types[unit] = storage->type; - } else if (unit_types[unit] != storage->type) { - pipeline->InfoLog = - ralloc_asprintf(pipeline, - "Texture unit %d is accessed both as %s " - "and %s", - unit, unit_types[unit]->name, - storage->type->name); - return false; - } + if (TexturesUsed[unit] & ~(1 << tgt)) { + pipeline->InfoLog = + ralloc_asprintf(pipeline, + "Program %d: " + "Texture unit %d is accessed with 2 different types", + shProg[idx]->Name, unit); + return false; } + + TexturesUsed[unit] |= (1 << tgt); } + + active_samplers += shader->num_samplers; } if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {