*/
#include <stdlib.h>
+#include <inttypes.h> /* for PRIx64 macro */
#include "main/core.h"
#include "main/context.h"
#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
}
static struct gl_uniform_storage *
-validate_uniform_parameters(struct gl_context *ctx,
- struct gl_shader_program *shProg,
- GLint location, GLsizei count,
- unsigned *array_index,
- const char *caller)
+validate_uniform_parameters(GLint location, GLsizei count,
+ unsigned *array_index,
+ struct gl_context *ctx,
+ struct gl_shader_program *shProg,
+ const char *caller)
{
if (shProg == NULL) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
/* 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
}
if (location == -1) {
- if (!shProg->LinkStatus)
+ if (!shProg->data->LinkStatus)
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
caller);
unsigned offset;
struct gl_uniform_storage *const uni =
- validate_uniform_parameters(ctx, shProg, location, 1,
- &offset, "glGetUniform");
+ validate_uniform_parameters(location, 1, &offset,
+ ctx, shProg, "glGetUniform");
if (uni == NULL) {
/* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
* spec says:
{
unsigned elements = (uni->type->is_sampler())
? 1 : uni->type->components();
- const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1;
- const int rmul = returnType == 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.
&uni->storage[offset * elements * dmul];
assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
- returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE);
+ returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE ||
+ returnType == GLSL_TYPE_UINT64 || returnType == GLSL_TYPE_INT64);
/* doubles have a different size than the other 3 types */
unsigned bytes = sizeof(src[0]) * elements * rmul;
&&
(uni->type->base_type == GLSL_TYPE_INT
|| uni->type->base_type == GLSL_TYPE_UINT
- || uni->type->base_type == GLSL_TYPE_SAMPLER
- || uni->type->base_type == GLSL_TYPE_IMAGE))) {
+ || uni->type->is_sampler()
+ || uni->type->is_image()))
+ || ((returnType == GLSL_TYPE_UINT64 ||
+ returnType == GLSL_TYPE_INT64 ) &&
+ (uni->type->base_type == GLSL_TYPE_UINT64 ||
+ uni->type->base_type == GLSL_TYPE_INT64))) {
memcpy(paramsOut, src, bytes);
} else {
union gl_constant_value *const dst =
case GLSL_TYPE_BOOL:
dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
break;
- case GLSL_TYPE_DOUBLE:
- dst[didx].f = *(double *)&src[sidx].f;
+ case GLSL_TYPE_DOUBLE: {
+ double tmp;
+ memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+ dst[didx].f = tmp;
break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+ dst[didx].f = tmp;
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].i, 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 *)&dst[didx].f = (double) src[sidx].u;
+ 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 *)&dst[didx].f = (double) src[sidx].i;
+ case GLSL_TYPE_IMAGE: {
+ double tmp = src[sidx].i;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
break;
- case GLSL_TYPE_BOOL:
- *(double *)&dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
+ }
+ 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 *)&dst[didx].f = (double) src[sidx].f;
+ }
+ case GLSL_TYPE_FLOAT: {
+ double tmp = src[sidx].f;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmpu;
+ double tmp;
+ memcpy(&tmpu, &src[sidx].u, sizeof(tmpu));
+ tmp = tmpu;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmpi;
+ double tmp;
+ memcpy(&tmpi, &src[sidx].i, sizeof(tmpi));
+ tmp = tmpi;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
default:
assert(!"Should not get here.");
break;
case GLSL_TYPE_BOOL:
dst[didx].i = src[sidx].i ? 1 : 0;
break;
- case GLSL_TYPE_DOUBLE:
- dst[didx].i = IROUNDD(*(double *)&src[sidx].f);
+ case GLSL_TYPE_DOUBLE: {
+ double tmp;
+ memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+ dst[didx].i = IROUNDD(tmp);
break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+ dst[didx].i = tmp;
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmp;
+ memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+ dst[didx].i = tmp;
+ break;
+ }
default:
assert(!"Should not get here.");
break;
}
break;
-
+ case GLSL_TYPE_INT64:
+ case GLSL_TYPE_UINT64:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_UINT: {
+ uint64_t tmp = src[sidx].u;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE: {
+ int64_t tmp = src[sidx].i;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_BOOL: {
+ int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_FLOAT: {
+ int64_t tmp = src[sidx].f;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
default:
assert(!"Should not get here.");
break;
case GLSL_TYPE_INT:
printf("%d ", v[i].i);
break;
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
+ printf("%" PRIu64 " ", tmp);
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmp;
+ memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
+ printf("%" PRId64 " ", tmp);
+ break;
+ }
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;
*/
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.
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;
}
return "float";
case GLSL_TYPE_DOUBLE:
return "double";
+ case GLSL_TYPE_UINT64:
+ return "uint64";
+ case GLSL_TYPE_INT64:
+ return "int64";
case GLSL_TYPE_BOOL:
return "bool";
case GLSL_TYPE_SAMPLER:
* Called via glUniform*() functions.
*/
extern "C" void
-_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
- GLint location, GLsizei count,
- const GLvoid *values,
- enum glsl_base_type basicType,
- unsigned src_components)
+_mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
+ struct gl_context *ctx, struct gl_shader_program *shProg,
+ enum glsl_base_type basicType, 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,
- &offset, "glUniform");
+ validate_uniform_parameters(location, count, &offset,
+ ctx, shProg, "glUniform");
if (uni == NULL)
return;
}
}
- 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
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->opaque[i].active)
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
continue;
+ bool changed = false;
for (int j = 0; j < count; j++) {
- sh->SamplerUnits[uni->opaque[i].index + offset + j] =
- ((unsigned *) values)[j];
+ unsigned unit = uni->opaque[i].index + offset + j;
+ if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
+ sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
+ changed = true;
+ }
}
- struct gl_program *const prog = sh->Program;
-
- assert(sizeof(prog->SamplerUnits) == sizeof(sh->SamplerUnits));
-
- /* Determine if any of the samplers used by this shader stage have
- * 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])) {
- changed = true;
- break;
- }
- }
-
if (changed) {
if (!flushed) {
FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
flushed = true;
}
- memcpy(prog->SamplerUnits,
- sh->SamplerUnits,
- sizeof(sh->SamplerUnits));
-
+ struct gl_program *const prog = sh->Program;
_mesa_update_shader_textures_used(shProg, prog);
if (ctx->Driver.SamplerUniformChange)
ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
if (uni->type->is_image()) {
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
if (uni->opaque[i].active) {
- struct gl_shader *sh = shProg->_LinkedShaders[i];
+ struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
for (int j = 0; j < count; j++)
- sh->ImageUnits[uni->opaque[i].index + offset + j] =
+ sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
((GLint *) values)[j];
}
}
* Note: cols=2, rows=4 ==> array[2] of vec4
*/
extern "C" void
-_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
- GLuint cols, GLuint rows,
- GLint location, GLsizei count,
- GLboolean transpose,
- const GLvoid *values, enum glsl_base_type basicType)
+_mesa_uniform_matrix(GLint location, GLsizei count,
+ GLboolean transpose, const void *values,
+ struct gl_context *ctx, struct gl_shader_program *shProg,
+ GLuint cols, GLuint rows, enum glsl_base_type basicType)
{
unsigned offset;
- unsigned vectors;
- unsigned components;
- unsigned elements;
- int size_mul;
struct gl_uniform_storage *const uni =
- validate_uniform_parameters(ctx, shProg, location, count,
- &offset, "glUniformMatrix");
+ validate_uniform_parameters(location, count, &offset,
+ ctx, shProg, "glUniformMatrix");
if (uni == NULL)
return;
}
assert(basicType == GLSL_TYPE_FLOAT || basicType == GLSL_TYPE_DOUBLE);
- size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
+ const unsigned size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
assert(!uni->type->is_sampler());
- vectors = uni->type->matrix_columns;
- components = uni->type->vector_elements;
+ const unsigned vectors = uni->type->matrix_columns;
+ const unsigned components = uni->type->vector_elements;
/* Verify that the types are compatible. This is greatly simplified for
* matrices because they can only have a float base type.
/* Store the data in the "actual type" backing storage for the uniform.
*/
- elements = components * vectors;
+ const unsigned 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.
}
}
- uni->initialized = true;
-
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
char *errMsg, size_t errMsgLength)
{
/* Shader does not have samplers. */
- if (shProg->NumUniformStorage == 0)
+ if (shProg->data->NumUniformStorage == 0)
return true;
if (!shProg->SamplersValidated) {
* - 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];
unsigned active_samplers = 0;
- const struct gl_shader_program **shProg =
- (const struct gl_shader_program **) pipeline->CurrentProgram;
+ const struct gl_program **prog =
+ (const struct gl_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])
+ if (!prog[idx])
continue;
- for (unsigned i = 0; i < shProg[idx]->NumUniformStorage; i++) {
- const struct gl_uniform_storage *const storage =
- &shProg[idx]->UniformStorage[i];
-
- if (!storage->type->is_sampler())
+ mask = prog[idx]->SamplersUsed;
+ while (mask) {
+ const int s = u_bit_scan(&mask);
+ GLuint unit = prog[idx]->SamplerUnits[s];
+ GLuint tgt = prog[idx]->sh.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",
+ prog[idx]->Id, unit);
+ return false;
}
+
+ TexturesUsed[unit] |= (1 << tgt);
}
+
+ active_samplers += prog[idx]->info.num_textures;
}
if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {