1243
1294
ir->operands[1]->type->is_vector()) {
1244
1295
src_reg temp = get_temp(glsl_type::vec4_type);
1245
1296
emit(ir, OPCODE_SNE, dst_reg(temp), op[0], op[1]);
1246
emit_dp(ir, result_dst, temp, temp, vector_elements);
1247
emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
1298
/* After the dot-product, the value will be an integer on the
1299
* range [0,4]. Zero stays zero, and positive values become 1.0.
1301
ir_to_mesa_instruction *const dp =
1302
emit_dp(ir, result_dst, temp, temp, vector_elements);
1303
if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
1304
/* The clamping to [0,1] can be done for free in the fragment
1305
* shader with a saturate.
1307
dp->saturate = true;
1309
/* Negating the result of the dot-product gives values on the range
1310
* [-4, 0]. Zero stays zero, and negative values become 1.0. This
1311
* achieved using SLT.
1313
src_reg slt_src = result_src;
1314
slt_src.negate = ~slt_src.negate;
1315
emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0));
1249
1318
emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
1254
1323
assert(ir->operands[0]->type->is_vector());
1255
emit_dp(ir, result_dst, op[0], op[0],
1256
ir->operands[0]->type->vector_elements);
1257
emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
1325
/* After the dot-product, the value will be an integer on the
1326
* range [0,4]. Zero stays zero, and positive values become 1.0.
1328
ir_to_mesa_instruction *const dp =
1329
emit_dp(ir, result_dst, op[0], op[0],
1330
ir->operands[0]->type->vector_elements);
1331
if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
1332
/* The clamping to [0,1] can be done for free in the fragment
1333
* shader with a saturate.
1335
dp->saturate = true;
1337
/* Negating the result of the dot-product gives values on the range
1338
* [-4, 0]. Zero stays zero, and negative values become 1.0. This
1339
* is achieved using SLT.
1341
src_reg slt_src = result_src;
1342
slt_src.negate = ~slt_src.negate;
1343
emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0));
1260
1348
case ir_binop_logic_xor:
1261
1349
emit(ir, OPCODE_SNE, result_dst, op[0], op[1]);
1264
case ir_binop_logic_or:
1265
/* This could be a saturated add and skip the SNE. */
1266
emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
1267
emit(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0));
1352
case ir_binop_logic_or: {
1353
/* After the addition, the value will be an integer on the
1354
* range [0,2]. Zero stays zero, and positive values become 1.0.
1356
ir_to_mesa_instruction *add =
1357
emit(ir, OPCODE_ADD, result_dst, op[0], op[1]);
1358
if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
1359
/* The clamping to [0,1] can be done for free in the fragment
1360
* shader with a saturate.
1362
add->saturate = true;
1364
/* Negating the result of the addition gives values on the range
1365
* [-2, 0]. Zero stays zero, and negative values become 1.0. This
1366
* is achieved using SLT.
1368
src_reg slt_src = result_src;
1369
slt_src.negate = ~slt_src.negate;
1370
emit(ir, OPCODE_SLT, result_dst, slt_src, src_reg_for_float(0.0));
1270
1375
case ir_binop_logic_and:
1271
1376
/* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
2371
* Count resources used by the given gpu program (number of texture
2375
count_resources(struct gl_program *prog)
2493
class add_uniform_to_shader : public uniform_field_visitor {
2495
add_uniform_to_shader(struct gl_shader_program *shader_program,
2496
struct gl_program_parameter_list *params)
2497
: shader_program(shader_program), params(params)
2502
void process(ir_variable *var)
2505
this->uniform_field_visitor::process(var);
2507
var->location = this->idx;
2511
virtual void visit_field(const glsl_type *type, const char *name);
2513
struct gl_shader_program *shader_program;
2514
struct gl_program_parameter_list *params;
2519
add_uniform_to_shader::visit_field(const glsl_type *type, const char *name)
2379
prog->SamplersUsed = 0;
2381
for (i = 0; i < prog->NumInstructions; i++) {
2382
struct prog_instruction *inst = &prog->Instructions[i];
2384
if (_mesa_is_tex_instruction(inst->Opcode)) {
2385
prog->SamplerTargets[inst->TexSrcUnit] =
2386
(gl_texture_index)inst->TexSrcTarget;
2387
prog->SamplersUsed |= 1 << inst->TexSrcUnit;
2388
if (inst->TexShadow) {
2389
prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
2523
if (type->is_vector() || type->is_scalar()) {
2524
size = type->vector_elements;
2526
size = type_size(type) * 4;
2529
gl_register_file file;
2530
if (type->is_sampler() ||
2531
(type->is_array() && type->fields.array->is_sampler())) {
2532
file = PROGRAM_SAMPLER;
2534
file = PROGRAM_UNIFORM;
2537
int index = _mesa_lookup_parameter_index(params, -1, name);
2539
index = _mesa_add_parameter(params, file, name, size, type->gl_type,
2542
/* Sampler uniform values are stored in prog->SamplerUnits,
2543
* and the entry in that array is selected by this index we
2544
* store in ParameterValues[].
2546
if (file == PROGRAM_SAMPLER) {
2549
this->shader_program->UniformHash->get(location,
2550
params->Parameters[index].Name);
2556
struct gl_uniform_storage *storage =
2557
&this->shader_program->UniformStorage[location];
2559
for (unsigned int j = 0; j < size / 4; j++)
2560
params->ParameterValues[index + j][0].f = storage->sampler + j;
2394
_mesa_update_shader_textures_used(prog);
2564
/* The first part of the uniform that's processed determines the base
2565
* location of the whole uniform (for structures).
2399
* Check if the given vertex/fragment/shader program is within the
2400
* resource limits of the context (number of texture units, etc).
2401
* If any of those checks fail, record a linker error.
2572
* Generate the program parameters list for the user uniforms in a shader
2403
* XXX more checks are needed...
2406
check_resources(const struct gl_context *ctx,
2407
struct gl_shader_program *shader_program,
2408
struct gl_program *prog)
2410
switch (prog->Target) {
2411
case GL_VERTEX_PROGRAM_ARB:
2412
if (_mesa_bitcount(prog->SamplersUsed) >
2413
ctx->Const.MaxVertexTextureImageUnits) {
2414
fail_link(shader_program, "Too many vertex shader texture samplers");
2416
if (prog->Parameters->NumParameters > MAX_UNIFORMS) {
2417
fail_link(shader_program, "Too many vertex shader constants");
2420
case MESA_GEOMETRY_PROGRAM:
2421
if (_mesa_bitcount(prog->SamplersUsed) >
2422
ctx->Const.MaxGeometryTextureImageUnits) {
2423
fail_link(shader_program, "Too many geometry shader texture samplers");
2425
if (prog->Parameters->NumParameters >
2426
MAX_GEOMETRY_UNIFORM_COMPONENTS / 4) {
2427
fail_link(shader_program, "Too many geometry shader constants");
2430
case GL_FRAGMENT_PROGRAM_ARB:
2431
if (_mesa_bitcount(prog->SamplersUsed) >
2432
ctx->Const.MaxTextureImageUnits) {
2433
fail_link(shader_program, "Too many fragment shader texture samplers");
2435
if (prog->Parameters->NumParameters > MAX_UNIFORMS) {
2436
fail_link(shader_program, "Too many fragment shader constants");
2440
_mesa_problem(ctx, "unexpected program type in check_resources()");
2446
struct uniform_sort {
2447
struct gl_uniform *u;
2451
/* The shader_program->Uniforms list is almost sorted in increasing
2452
* uniform->{Frag,Vert}Pos locations, but not quite when there are
2453
* uniforms shared between targets. We need to add parameters in
2454
* increasing order for the targets.
2457
sort_uniforms(const void *a, const void *b)
2459
struct uniform_sort *u1 = (struct uniform_sort *)a;
2460
struct uniform_sort *u2 = (struct uniform_sort *)b;
2462
return u1->pos - u2->pos;
2465
/* Add the uniforms to the parameters. The linker chose locations
2466
* in our parameters lists (which weren't created yet), which the
2467
* uniforms code will use to poke values into our parameters list
2468
* when uniforms are updated.
2471
add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
2472
struct gl_shader *shader,
2473
struct gl_program *prog)
2476
unsigned int next_sampler = 0, num_uniforms = 0;
2477
struct uniform_sort *sorted_uniforms;
2479
sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
2480
shader_program->Uniforms->NumUniforms);
2482
for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
2483
struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
2484
int parameter_index = -1;
2486
switch (shader->Type) {
2487
case GL_VERTEX_SHADER:
2488
parameter_index = uniform->VertPos;
2490
case GL_FRAGMENT_SHADER:
2491
parameter_index = uniform->FragPos;
2493
case GL_GEOMETRY_SHADER:
2494
parameter_index = uniform->GeomPos;
2498
/* Only add uniforms used in our target. */
2499
if (parameter_index != -1) {
2500
sorted_uniforms[num_uniforms].pos = parameter_index;
2501
sorted_uniforms[num_uniforms].u = uniform;
2506
qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
2509
for (i = 0; i < num_uniforms; i++) {
2510
struct gl_uniform *uniform = sorted_uniforms[i].u;
2511
int parameter_index = sorted_uniforms[i].pos;
2512
const glsl_type *type = uniform->Type;
2515
if (type->is_vector() ||
2516
type->is_scalar()) {
2517
size = type->vector_elements;
2519
size = type_size(type) * 4;
2522
gl_register_file file;
2523
if (type->is_sampler() ||
2524
(type->is_array() && type->fields.array->is_sampler())) {
2525
file = PROGRAM_SAMPLER;
2527
file = PROGRAM_UNIFORM;
2530
GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
2534
index = _mesa_add_parameter(prog->Parameters, file,
2535
uniform->Name, size, type->gl_type,
2538
/* Sampler uniform values are stored in prog->SamplerUnits,
2539
* and the entry in that array is selected by this index we
2540
* store in ParameterValues[].
2542
if (file == PROGRAM_SAMPLER) {
2543
for (unsigned int j = 0; j < size / 4; j++)
2544
prog->Parameters->ParameterValues[index + j][0] = next_sampler++;
2547
/* The location chosen in the Parameters list here (returned
2548
* from _mesa_add_uniform) has to match what the linker chose.
2550
if (index != parameter_index) {
2551
fail_link(shader_program, "Allocation of uniform `%s' to target "
2552
"failed (%d vs %d)\n",
2553
uniform->Name, index, parameter_index);
2558
ralloc_free(sorted_uniforms);
2574
* \param shader_program Linked shader program. This is only used to
2575
* emit possible link errors to the info log.
2576
* \param sh Shader whose uniforms are to be processed.
2577
* \param params Parameter list to be filled in.
2580
_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
2582
struct gl_shader *sh,
2583
struct gl_program_parameter_list
2586
add_uniform_to_shader add(shader_program, params);
2588
foreach_list(node, sh->ir) {
2589
ir_variable *var = ((ir_instruction *) node)->as_variable();
2591
if ((var == NULL) || (var->mode != ir_var_uniform)
2592
|| (strncmp(var->name, "gl_", 3) == 0))
2600
_mesa_associate_uniform_storage(struct gl_context *ctx,
2601
struct gl_shader_program *shader_program,
2602
struct gl_program_parameter_list *params)
2604
/* After adding each uniform to the parameter list, connect the storage for
2605
* the parameter with the tracking structure used by the API for the
2608
unsigned last_location = unsigned(~0);
2609
for (unsigned i = 0; i < params->NumParameters; i++) {
2610
if (params->Parameters[i].Type != PROGRAM_UNIFORM)
2615
shader_program->UniformHash->get(location, params->Parameters[i].Name);
2621
if (location != last_location) {
2622
struct gl_uniform_storage *storage =
2623
&shader_program->UniformStorage[location];
2624
enum gl_uniform_driver_format format = uniform_native;
2626
unsigned columns = 0;
2627
switch (storage->type->base_type) {
2628
case GLSL_TYPE_UINT:
2629
assert(ctx->Const.NativeIntegers);
2630
format = uniform_native;
2635
(ctx->Const.NativeIntegers) ? uniform_native : uniform_int_float;
2638
case GLSL_TYPE_FLOAT:
2639
format = uniform_native;
2640
columns = storage->type->matrix_columns;
2642
case GLSL_TYPE_BOOL:
2643
if (ctx->Const.NativeIntegers) {
2644
format = (ctx->Const.UniformBooleanTrue == 1)
2645
? uniform_bool_int_0_1 : uniform_bool_int_0_not0;
2647
format = uniform_bool_float;
2651
case GLSL_TYPE_SAMPLER:
2652
format = uniform_native;
2656
assert(!"Should not get here.");
2660
_mesa_uniform_attach_driver_storage(storage,
2661
4 * sizeof(float) * columns,
2664
¶ms->ParameterValues[i]);
2665
last_location = location;