diff options
Diffstat (limited to 'mesalib/src')
198 files changed, 7807 insertions, 2140 deletions
diff --git a/mesalib/src/Makefile.am b/mesalib/src/Makefile.am index 8edf33373..18cb4ce76 100644 --- a/mesalib/src/Makefile.am +++ b/mesalib/src/Makefile.am @@ -53,7 +53,13 @@ if HAVE_GALLIUM SUBDIRS += gallium endif -EXTRA_DIST = egl/docs getopt hgl SConscript +EXTRA_DIST = \ + egl/drivers/haiku \ + egl/docs \ + getopt hgl SConscript + +AM_CFLAGS = $(VISIBILITY_CFLAGS) +AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS) AM_CPPFLAGS = \ -I$(top_srcdir)/include/ \ diff --git a/mesalib/src/SConscript b/mesalib/src/SConscript index 188ab08b6..b0578e892 100644 --- a/mesalib/src/SConscript +++ b/mesalib/src/SConscript @@ -12,7 +12,8 @@ if env['hostonly']: # compilation Return() -SConscript('loader/SConscript') +if env['platform'] != 'windows': + SConscript('loader/SConscript') # When env['gles'] is set, the targets defined in mapi/glapi/SConscript are not # used. libgl-xlib and libgl-gdi adapt themselves to use the targets defined @@ -30,7 +31,7 @@ SConscript('mesa/SConscript') if not env['embedded']: if env['platform'] not in ('cygwin', 'darwin', 'freebsd', 'haiku', 'windows'): SConscript('glx/SConscript') - if env['platform'] not in ['darwin', 'haiku', 'sunos']: + if env['platform'] not in ['darwin', 'haiku', 'sunos', 'windows']: if env['dri']: SConscript('egl/drivers/dri2/SConscript') SConscript('egl/main/SConscript') diff --git a/mesalib/src/gallium/auxiliary/Makefile.am b/mesalib/src/gallium/auxiliary/Makefile.am index 27a8b3fe4..89c7a13e9 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.am +++ b/mesalib/src/gallium/auxiliary/Makefile.am @@ -10,6 +10,7 @@ include $(top_srcdir)/src/gallium/Automake.inc noinst_LTLIBRARIES = libgallium.la AM_CFLAGS = \ + -I$(top_builddir)/src/glsl/nir \ -I$(top_srcdir)/src/gallium/auxiliary/util \ $(GALLIUM_CFLAGS) \ $(VISIBILITY_CFLAGS) \ @@ -21,6 +22,7 @@ AM_CXXFLAGS = \ libgallium_la_SOURCES = \ $(C_SOURCES) \ + $(NIR_SOURCES) \ $(GENERATED_SOURCES) if HAVE_MESA_LLVM diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index b7174d6e7..ec7547cad 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -251,8 +251,6 @@ C_SOURCES := \ util/u_keymap.h \ util/u_linear.c \ util/u_linear.h \ - util/u_linkage.c \ - util/u_linkage.h \ util/u_math.c \ util/u_math.h \ util/u_memory.h \ @@ -304,6 +302,10 @@ C_SOURCES := \ util/u_vbuf.h \ util/u_video.h +NIR_SOURCES := \ + nir/tgsi_to_nir.c \ + nir/tgsi_to_nir.h + VL_SOURCES := \ vl/vl_compositor.c \ vl/vl_compositor.h \ diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c index b48708c2f..53771fcae 100644 --- a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c +++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c @@ -157,7 +157,8 @@ hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, if (!gr) return; - strcpy(gr->name, name); + strncpy(gr->name, name, sizeof(gr->name)); + gr->name[sizeof(gr->name) - 1] = '\0'; gr->query_data = CALLOC_STRUCT(query_info); if (!gr->query_data) { FREE(gr); diff --git a/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c new file mode 100644 index 000000000..59aaf6778 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c @@ -0,0 +1,1750 @@ +/* + * Copyright © 2014-2015 Broadcom + * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "util/ralloc.h" +#include "glsl/nir/nir.h" +#include "glsl/nir/nir_builder.h" +#include "glsl/list.h" +#include "glsl/shader_enums.h" + +#include "nir/tgsi_to_nir.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_scan.h" + +#define SWIZ(X, Y, Z, W) (unsigned[4]){ \ + TGSI_SWIZZLE_##X, \ + TGSI_SWIZZLE_##Y, \ + TGSI_SWIZZLE_##Z, \ + TGSI_SWIZZLE_##W, \ + } + +struct ttn_reg_info { + /** nir register containing this TGSI index. */ + nir_register *reg; + nir_variable *var; + /** Offset (in vec4s) from the start of var for this TGSI index. */ + int offset; +}; + +struct ttn_compile { + union tgsi_full_token *token; + nir_builder build; + struct tgsi_shader_info *scan; + + struct ttn_reg_info *output_regs; + struct ttn_reg_info *temp_regs; + nir_ssa_def **imm_defs; + + nir_register *addr_reg; + + /** + * Stack of cf_node_lists where instructions should be pushed as we pop + * back out of the control flow stack. + * + * For each IF/ELSE/ENDIF block, if_stack[if_stack_pos] has where the else + * instructions should be placed, and if_stack[if_stack_pos - 1] has where + * the next instructions outside of the if/then/else block go. + */ + struct exec_list **if_stack; + unsigned if_stack_pos; + + /** + * Stack of cf_node_lists where instructions should be pushed as we pop + * back out of the control flow stack. + * + * loop_stack[loop_stack_pos - 1] contains the cf_node_list for the outside + * of the loop. + */ + struct exec_list **loop_stack; + unsigned loop_stack_pos; + + /* How many TGSI_FILE_IMMEDIATE vec4s have been parsed so far. */ + unsigned next_imm; +}; + +#define ttn_swizzle(b, src, x, y, z, w) \ + nir_swizzle(b, src, SWIZ(x, y, z, w), 4, false) +#define ttn_channel(b, src, swiz) \ + nir_swizzle(b, src, SWIZ(swiz, swiz, swiz, swiz), 1, false) + +static nir_ssa_def * +ttn_src_for_dest(nir_builder *b, nir_alu_dest *dest) +{ + nir_alu_src src; + memset(&src, 0, sizeof(src)); + + if (dest->dest.is_ssa) + src.src = nir_src_for_ssa(&dest->dest.ssa); + else { + assert(!dest->dest.reg.indirect); + src.src = nir_src_for_reg(dest->dest.reg.reg); + src.src.reg.base_offset = dest->dest.reg.base_offset; + } + + for (int i = 0; i < 4; i++) + src.swizzle[i] = i; + + return nir_fmov_alu(b, src, 4); +} + +static void +ttn_emit_declaration(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + struct tgsi_full_declaration *decl = &c->token->FullDeclaration; + unsigned array_size = decl->Range.Last - decl->Range.First + 1; + unsigned file = decl->Declaration.File; + unsigned i; + + if (file == TGSI_FILE_TEMPORARY) { + if (decl->Declaration.Array) { + /* for arrays, we create variables instead of registers: */ + nir_variable *var = rzalloc(b->shader, nir_variable); + + var->type = glsl_array_type(glsl_vec4_type(), array_size); + var->data.mode = nir_var_global; + var->name = ralloc_asprintf(var, "arr_%d", decl->Array.ArrayID); + + exec_list_push_tail(&b->shader->globals, &var->node); + + for (i = 0; i < array_size; i++) { + /* point all the matching slots to the same var, + * with appropriate offset set, mostly just so + * we know what to do when tgsi does a non-indirect + * access + */ + c->temp_regs[decl->Range.First + i].reg = NULL; + c->temp_regs[decl->Range.First + i].var = var; + c->temp_regs[decl->Range.First + i].offset = i; + } + } else { + for (i = 0; i < array_size; i++) { + nir_register *reg = nir_local_reg_create(b->impl); + reg->num_components = 4; + c->temp_regs[decl->Range.First + i].reg = reg; + c->temp_regs[decl->Range.First + i].var = NULL; + c->temp_regs[decl->Range.First + i].offset = 0; + } + } + } else if (file == TGSI_FILE_ADDRESS) { + c->addr_reg = nir_local_reg_create(b->impl); + c->addr_reg->num_components = 4; + } else if (file == TGSI_FILE_SYSTEM_VALUE) { + /* Nothing to record for system values. */ + } else if (file == TGSI_FILE_SAMPLER) { + /* Nothing to record for samplers. */ + } else { + nir_variable *var; + assert(file == TGSI_FILE_INPUT || + file == TGSI_FILE_OUTPUT || + file == TGSI_FILE_CONSTANT); + + /* nothing to do for UBOs: */ + if ((file == TGSI_FILE_CONSTANT) && decl->Declaration.Dimension) + return; + + var = rzalloc(b->shader, nir_variable); + var->data.driver_location = decl->Range.First; + + var->type = glsl_vec4_type(); + if (array_size > 1) + var->type = glsl_array_type(var->type, array_size); + + switch (file) { + case TGSI_FILE_INPUT: + var->data.read_only = true; + var->data.mode = nir_var_shader_in; + var->name = ralloc_asprintf(var, "in_%d", decl->Range.First); + + /* We should probably translate to a VERT_ATTRIB_* or VARYING_SLOT_* + * instead, but nothing in NIR core is looking at the value + * currently, and this is less change to drivers. + */ + var->data.location = decl->Semantic.Name; + var->data.index = decl->Semantic.Index; + + /* We definitely need to translate the interpolation field, because + * nir_print will decode it. + */ + switch (decl->Interp.Interpolate) { + case TGSI_INTERPOLATE_CONSTANT: + var->data.interpolation = INTERP_QUALIFIER_FLAT; + break; + case TGSI_INTERPOLATE_LINEAR: + var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; + break; + case TGSI_INTERPOLATE_PERSPECTIVE: + var->data.interpolation = INTERP_QUALIFIER_SMOOTH; + break; + } + + exec_list_push_tail(&b->shader->inputs, &var->node); + break; + case TGSI_FILE_OUTPUT: { + /* Since we can't load from outputs in the IR, we make temporaries + * for the outputs and emit stores to the real outputs at the end of + * the shader. + */ + nir_register *reg = nir_local_reg_create(b->impl); + reg->num_components = 4; + if (array_size > 1) + reg->num_array_elems = array_size; + + var->data.mode = nir_var_shader_out; + var->name = ralloc_asprintf(var, "out_%d", decl->Range.First); + + var->data.location = decl->Semantic.Name; + var->data.index = decl->Semantic.Index; + + for (i = 0; i < array_size; i++) { + c->output_regs[decl->Range.First + i].offset = i; + c->output_regs[decl->Range.First + i].reg = reg; + } + + exec_list_push_tail(&b->shader->outputs, &var->node); + } + break; + case TGSI_FILE_CONSTANT: + var->data.mode = nir_var_uniform; + var->name = ralloc_asprintf(var, "uniform_%d", decl->Range.First); + + exec_list_push_tail(&b->shader->uniforms, &var->node); + break; + default: + unreachable("bad declaration file"); + return; + } + + } +} + +static void +ttn_emit_immediate(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + struct tgsi_full_immediate *tgsi_imm = &c->token->FullImmediate; + nir_load_const_instr *load_const; + int i; + + load_const = nir_load_const_instr_create(b->shader, 4); + c->imm_defs[c->next_imm] = &load_const->def; + c->next_imm++; + + for (i = 0; i < 4; i++) + load_const->value.u[i] = tgsi_imm->u[i].Uint; + + nir_instr_insert_after_cf_list(b->cf_node_list, &load_const->instr); +} + +static nir_src +ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect); + +/* generate either a constant or indirect deref chain for accessing an + * array variable. + */ +static nir_deref_var * +ttn_array_deref(struct ttn_compile *c, nir_intrinsic_instr *instr, + nir_variable *var, unsigned offset, + struct tgsi_ind_register *indirect) +{ + nir_deref_var *deref = nir_deref_var_create(instr, var); + nir_deref_array *arr = nir_deref_array_create(deref); + + arr->base_offset = offset; + arr->deref.type = glsl_get_array_element(var->type); + + if (indirect) { + arr->deref_array_type = nir_deref_array_type_indirect; + arr->indirect = ttn_src_for_indirect(c, indirect); + } else { + arr->deref_array_type = nir_deref_array_type_direct; + } + + deref->deref.child = &arr->deref; + + return deref; +} + +static nir_src +ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index, + struct tgsi_ind_register *indirect, + struct tgsi_dimension *dim, + struct tgsi_ind_register *dimind) +{ + nir_builder *b = &c->build; + nir_src src; + + memset(&src, 0, sizeof(src)); + + switch (file) { + case TGSI_FILE_TEMPORARY: + if (c->temp_regs[index].var) { + unsigned offset = c->temp_regs[index].offset; + nir_variable *var = c->temp_regs[index].var; + nir_intrinsic_instr *load; + + load = nir_intrinsic_instr_create(b->shader, + nir_intrinsic_load_var); + load->num_components = 4; + load->variables[0] = ttn_array_deref(c, load, var, offset, indirect); + + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src = nir_src_for_ssa(&load->dest.ssa); + + } else { + assert(!indirect); + src.reg.reg = c->temp_regs[index].reg; + } + assert(!dim); + break; + + case TGSI_FILE_ADDRESS: + src.reg.reg = c->addr_reg; + assert(!dim); + break; + + case TGSI_FILE_IMMEDIATE: + src = nir_src_for_ssa(c->imm_defs[index]); + assert(!indirect); + assert(!dim); + break; + + case TGSI_FILE_SYSTEM_VALUE: { + nir_intrinsic_instr *load; + nir_intrinsic_op op; + unsigned ncomp = 1; + + assert(!indirect); + assert(!dim); + + switch (c->scan->system_value_semantic_name[index]) { + case TGSI_SEMANTIC_VERTEXID_NOBASE: + op = nir_intrinsic_load_vertex_id_zero_base; + break; + case TGSI_SEMANTIC_VERTEXID: + op = nir_intrinsic_load_vertex_id; + break; + case TGSI_SEMANTIC_BASEVERTEX: + op = nir_intrinsic_load_base_vertex; + break; + case TGSI_SEMANTIC_INSTANCEID: + op = nir_intrinsic_load_instance_id; + break; + default: + unreachable("bad system value"); + } + + load = nir_intrinsic_instr_create(b->shader, op); + load->num_components = ncomp; + + nir_ssa_dest_init(&load->instr, &load->dest, ncomp, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src = nir_src_for_ssa(&load->dest.ssa); + break; + } + + case TGSI_FILE_INPUT: + case TGSI_FILE_CONSTANT: { + nir_intrinsic_instr *load; + nir_intrinsic_op op; + unsigned srcn = 0; + + switch (file) { + case TGSI_FILE_INPUT: + op = indirect ? nir_intrinsic_load_input_indirect : + nir_intrinsic_load_input; + assert(!dim); + break; + case TGSI_FILE_CONSTANT: + if (dim) { + op = indirect ? nir_intrinsic_load_ubo_indirect : + nir_intrinsic_load_ubo; + /* convert index from vec4 to byte: */ + index *= 16; + } else { + op = indirect ? nir_intrinsic_load_uniform_indirect : + nir_intrinsic_load_uniform; + } + break; + default: + unreachable("No other load files supported"); + break; + } + + load = nir_intrinsic_instr_create(b->shader, op); + + load->num_components = 4; + load->const_index[0] = index; + load->const_index[1] = 1; + if (dim) { + if (dimind) { + load->src[srcn] = + ttn_src_for_file_and_index(c, dimind->File, dimind->Index, + NULL, NULL, NULL); + } else { + /* UBOs start at index 1 in TGSI: */ + load->src[srcn] = + nir_src_for_ssa(nir_imm_int(b, dim->Index - 1)); + } + srcn++; + } + if (indirect) { + load->src[srcn] = ttn_src_for_indirect(c, indirect); + if (dim) { + assert(load->src[srcn].is_ssa); + /* we also need to covert vec4 to byte here too: */ + load->src[srcn] = + nir_src_for_ssa(nir_ishl(b, load->src[srcn].ssa, + nir_imm_int(b, 4))); + } + srcn++; + } + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src = nir_src_for_ssa(&load->dest.ssa); + break; + } + + default: + unreachable("bad src file"); + } + + + return src; +} + +static nir_src +ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect) +{ + nir_builder *b = &c->build; + nir_alu_src src; + memset(&src, 0, sizeof(src)); + for (int i = 0; i < 4; i++) + src.swizzle[i] = indirect->Swizzle; + src.src = ttn_src_for_file_and_index(c, + indirect->File, + indirect->Index, + NULL, NULL, NULL); + return nir_src_for_ssa(nir_imov_alu(b, src, 1)); +} + +static nir_alu_dest +ttn_get_dest(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst) +{ + struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register; + nir_alu_dest dest; + unsigned index = tgsi_dst->Index; + + memset(&dest, 0, sizeof(dest)); + + if (tgsi_dst->File == TGSI_FILE_TEMPORARY) { + if (c->temp_regs[index].var) { + nir_builder *b = &c->build; + nir_intrinsic_instr *load; + struct tgsi_ind_register *indirect = + tgsi_dst->Indirect ? &tgsi_fdst->Indirect : NULL; + nir_register *reg; + + /* this works, because TGSI will give us a base offset + * (in case of indirect index) that points back into + * the array. Access can be direct or indirect, we + * don't really care. Just create a one-shot dst reg + * that will get store_var'd back into the array var + * at the end of ttn_emit_instruction() + */ + reg = nir_local_reg_create(c->build.impl); + reg->num_components = 4; + dest.dest.reg.reg = reg; + dest.dest.reg.base_offset = 0; + + /* since the alu op might not write to all components + * of the temporary, we must first do a load_var to + * get the previous array elements into the register. + * This is one area that NIR could use a bit of + * improvement (or opt pass to clean up the mess + * once things are scalarized) + */ + + load = nir_intrinsic_instr_create(c->build.shader, + nir_intrinsic_load_var); + load->num_components = 4; + load->variables[0] = + ttn_array_deref(c, load, c->temp_regs[index].var, + c->temp_regs[index].offset, + indirect); + + load->dest = nir_dest_for_reg(reg); + + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + } else { + assert(!tgsi_dst->Indirect); + dest.dest.reg.reg = c->temp_regs[index].reg; + dest.dest.reg.base_offset = c->temp_regs[index].offset; + } + } else if (tgsi_dst->File == TGSI_FILE_OUTPUT) { + dest.dest.reg.reg = c->output_regs[index].reg; + dest.dest.reg.base_offset = c->output_regs[index].offset; + } else if (tgsi_dst->File == TGSI_FILE_ADDRESS) { + assert(index == 0); + dest.dest.reg.reg = c->addr_reg; + } + + dest.write_mask = tgsi_dst->WriteMask; + dest.saturate = false; + + if (tgsi_dst->Indirect && (tgsi_dst->File != TGSI_FILE_TEMPORARY)) { + nir_src *indirect = ralloc(c->build.shader, nir_src); + *indirect = ttn_src_for_indirect(c, &tgsi_fdst->Indirect); + dest.dest.reg.indirect = indirect; + } + + return dest; +} + +static nir_variable * +ttn_get_var(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst) +{ + struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register; + unsigned index = tgsi_dst->Index; + + if (tgsi_dst->File == TGSI_FILE_TEMPORARY) { + /* we should not have an indirect when there is no var! */ + if (!c->temp_regs[index].var) + assert(!tgsi_dst->Indirect); + return c->temp_regs[index].var; + } + + return NULL; +} + +static nir_ssa_def * +ttn_get_src(struct ttn_compile *c, struct tgsi_full_src_register *tgsi_fsrc) +{ + nir_builder *b = &c->build; + struct tgsi_src_register *tgsi_src = &tgsi_fsrc->Register; + unsigned tgsi_opcode = c->token->FullInstruction.Instruction.Opcode; + unsigned tgsi_src_type = tgsi_opcode_infer_src_type(tgsi_opcode); + bool src_is_float = !(tgsi_src_type == TGSI_TYPE_SIGNED || + tgsi_src_type == TGSI_TYPE_UNSIGNED); + nir_alu_src src; + + memset(&src, 0, sizeof(src)); + + if (tgsi_src->File == TGSI_FILE_NULL) { + return nir_imm_float(b, 0.0); + } else if (tgsi_src->File == TGSI_FILE_SAMPLER) { + /* Only the index of the sampler gets used in texturing, and it will + * handle looking that up on its own instead of using the nir_alu_src. + */ + assert(!tgsi_src->Indirect); + return NULL; + } else { + struct tgsi_ind_register *ind = NULL; + struct tgsi_dimension *dim = NULL; + struct tgsi_ind_register *dimind = NULL; + if (tgsi_src->Indirect) + ind = &tgsi_fsrc->Indirect; + if (tgsi_src->Dimension) { + dim = &tgsi_fsrc->Dimension; + if (dim->Indirect) + dimind = &tgsi_fsrc->DimIndirect; + } + src.src = ttn_src_for_file_and_index(c, + tgsi_src->File, + tgsi_src->Index, + ind, dim, dimind); + } + + src.swizzle[0] = tgsi_src->SwizzleX; + src.swizzle[1] = tgsi_src->SwizzleY; + src.swizzle[2] = tgsi_src->SwizzleZ; + src.swizzle[3] = tgsi_src->SwizzleW; + + nir_ssa_def *def = nir_fmov_alu(b, src, 4); + + if (tgsi_src->Absolute) { + if (src_is_float) + def = nir_fabs(b, def); + else + def = nir_iabs(b, def); + } + + if (tgsi_src->Negate) { + if (src_is_float) + def = nir_fneg(b, def); + else + def = nir_ineg(b, def); + } + + return def; +} + +static void +ttn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + unsigned num_srcs = nir_op_infos[op].num_inputs; + nir_alu_instr *instr = nir_alu_instr_create(b->shader, op); + unsigned i; + + for (i = 0; i < num_srcs; i++) + instr->src[i].src = nir_src_for_ssa(src[i]); + + instr->dest = dest; + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); +} + +static void +ttn_move_dest_masked(nir_builder *b, nir_alu_dest dest, + nir_ssa_def *def, unsigned write_mask) +{ + if (!(dest.write_mask & write_mask)) + return; + + nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_imov); + mov->dest = dest; + mov->dest.write_mask &= write_mask; + mov->src[0].src = nir_src_for_ssa(def); + for (unsigned i = def->num_components; i < 4; i++) + mov->src[0].swizzle[i] = def->num_components - 1; + nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr); +} + +static void +ttn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def) +{ + ttn_move_dest_masked(b, dest, def, TGSI_WRITEMASK_XYZW); +} + +static void +ttn_arl(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_f2i(b, nir_ffloor(b, src[0]))); +} + +/* EXP - Approximate Exponential Base 2 + * dst.x = 2^{\lfloor src.x\rfloor} + * dst.y = src.x - \lfloor src.x\rfloor + * dst.z = 2^{src.x} + * dst.w = 1.0 + */ +static void +ttn_exp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *srcx = ttn_channel(b, src[0], X); + + ttn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)), + TGSI_WRITEMASK_X); + ttn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)), + TGSI_WRITEMASK_Y); + ttn_move_dest_masked(b, dest, nir_fexp2(b, srcx), TGSI_WRITEMASK_Z); + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W); +} + +/* LOG - Approximate Logarithm Base 2 + * dst.x = \lfloor\log_2{|src.x|}\rfloor + * dst.y = \frac{|src.x|}{2^{\lfloor\log_2{|src.x|}\rfloor}} + * dst.z = \log_2{|src.x|} + * dst.w = 1.0 + */ +static void +ttn_log(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *abs_srcx = nir_fabs(b, ttn_channel(b, src[0], X)); + nir_ssa_def *log2 = nir_flog2(b, abs_srcx); + + ttn_move_dest_masked(b, dest, nir_ffloor(b, log2), TGSI_WRITEMASK_X); + ttn_move_dest_masked(b, dest, + nir_fdiv(b, abs_srcx, nir_fexp2(b, nir_ffloor(b, log2))), + TGSI_WRITEMASK_Y); + ttn_move_dest_masked(b, dest, nir_flog2(b, abs_srcx), TGSI_WRITEMASK_Z); + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W); +} + +/* DST - Distance Vector + * dst.x = 1.0 + * dst.y = src0.y \times src1.y + * dst.z = src0.z + * dst.w = src1.w + */ +static void +ttn_dst(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_X); + ttn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), TGSI_WRITEMASK_Y); + ttn_move_dest_masked(b, dest, nir_fmov(b, src[0]), TGSI_WRITEMASK_Z); + ttn_move_dest_masked(b, dest, nir_fmov(b, src[1]), TGSI_WRITEMASK_W); +} + +/* LIT - Light Coefficients + * dst.x = 1.0 + * dst.y = max(src.x, 0.0) + * dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0 + * dst.w = 1.0 + */ +static void +ttn_lit(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_XW); + + ttn_move_dest_masked(b, dest, nir_fmax(b, ttn_channel(b, src[0], X), + nir_imm_float(b, 0.0)), TGSI_WRITEMASK_Y); + + if (dest.write_mask & TGSI_WRITEMASK_Z) { + nir_ssa_def *src0_y = ttn_channel(b, src[0], Y); + nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ttn_channel(b, src[0], W), + nir_imm_float(b, 128.0)), + nir_imm_float(b, -128.0)); + nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)), + wclamp); + + ttn_move_dest_masked(b, dest, + nir_bcsel(b, + nir_fge(b, + nir_imm_float(b, 0.0), + ttn_channel(b, src[0], X)), + nir_imm_float(b, 0.0), + pow), + TGSI_WRITEMASK_Z); + } +} + +/* SCS - Sine Cosine + * dst.x = \cos{src.x} + * dst.y = \sin{src.x} + * dst.z = 0.0 + * dst.w = 1.0 + */ +static void +ttn_scs(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest_masked(b, dest, nir_fcos(b, ttn_channel(b, src[0], X)), + TGSI_WRITEMASK_X); + ttn_move_dest_masked(b, dest, nir_fsin(b, ttn_channel(b, src[0], X)), + TGSI_WRITEMASK_Y); + ttn_move_dest_masked(b, dest, nir_imm_float(b, 0.0), TGSI_WRITEMASK_Z); + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W); +} + +static void +ttn_sle(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_sge(b, src[1], src[0])); +} + +static void +ttn_sgt(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_slt(b, src[1], src[0])); +} + +static void +ttn_clamp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_fmin(b, nir_fmax(b, src[0], src[1]), src[2])); +} + +static void +ttn_xpd(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest_masked(b, dest, + nir_fsub(b, + nir_fmul(b, + ttn_swizzle(b, src[0], Y, Z, X, X), + ttn_swizzle(b, src[1], Z, X, Y, X)), + nir_fmul(b, + ttn_swizzle(b, src[1], Y, Z, X, X), + ttn_swizzle(b, src[0], Z, X, Y, X))), + TGSI_WRITEMASK_XYZ); + ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W); +} + +static void +ttn_dp2a(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, + ttn_channel(b, nir_fadd(b, nir_fdot2(b, src[0], src[1]), + src[2]), + X)); +} + +static void +ttn_dp2(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_fdot2(b, src[0], src[1])); +} + +static void +ttn_dp3(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_fdot3(b, src[0], src[1])); +} + +static void +ttn_dp4(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_fdot4(b, src[0], src[1])); +} + +static void +ttn_dph(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_fadd(b, nir_fdot3(b, src[0], src[1]), + ttn_channel(b, src[1], W))); +} + +static void +ttn_umad(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_iadd(b, nir_imul(b, src[0], src[1]), src[2])); +} + +static void +ttn_arr(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_ffloor(b, nir_fadd(b, src[0], nir_imm_float(b, 0.5)))); +} + +static void +ttn_cmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_bcsel(b, + nir_flt(b, src[0], nir_imm_float(b, 0.0)), + src[1], src[2])); +} + +static void +ttn_ucmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + ttn_move_dest(b, dest, nir_bcsel(b, + nir_ine(b, src[0], nir_imm_int(b, 0)), + src[1], src[2])); +} + +static void +ttn_kill(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_intrinsic_instr *discard = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard); + nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr); +} + +static void +ttn_kill_if(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *cmp = nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0))); + nir_intrinsic_instr *discard = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if); + discard->src[0] = nir_src_for_ssa(cmp); + nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr); +} + +static void +ttn_if(struct ttn_compile *c, nir_ssa_def *src, bool is_uint) +{ + nir_builder *b = &c->build; + + /* Save the outside-of-the-if-statement node list. */ + c->if_stack[c->if_stack_pos] = b->cf_node_list; + c->if_stack_pos++; + + src = ttn_channel(b, src, X); + + nir_if *if_stmt = nir_if_create(b->shader); + if (is_uint) { + if_stmt->condition = nir_src_for_ssa(nir_ine(b, src, nir_imm_int(b, 0))); + } else { + if_stmt->condition = nir_src_for_ssa(nir_fne(b, src, nir_imm_int(b, 0))); + } + nir_cf_node_insert_end(b->cf_node_list, &if_stmt->cf_node); + + nir_builder_insert_after_cf_list(b, &if_stmt->then_list); + + c->if_stack[c->if_stack_pos] = &if_stmt->else_list; + c->if_stack_pos++; +} + +static void +ttn_else(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + + nir_builder_insert_after_cf_list(b, c->if_stack[c->if_stack_pos - 1]); +} + +static void +ttn_endif(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + + c->if_stack_pos -= 2; + nir_builder_insert_after_cf_list(b, c->if_stack[c->if_stack_pos]); +} + +static void +ttn_bgnloop(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + + /* Save the outside-of-the-loop node list. */ + c->loop_stack[c->loop_stack_pos] = b->cf_node_list; + c->loop_stack_pos++; + + nir_loop *loop = nir_loop_create(b->shader); + nir_cf_node_insert_end(b->cf_node_list, &loop->cf_node); + + nir_builder_insert_after_cf_list(b, &loop->body); +} + +static void +ttn_cont(nir_builder *b) +{ + nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_continue); + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); +} + +static void +ttn_brk(nir_builder *b) +{ + nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_break); + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); +} + +static void +ttn_endloop(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + + c->loop_stack_pos--; + nir_builder_insert_after_cf_list(b, c->loop_stack[c->loop_stack_pos]); +} + +static void +setup_texture_info(nir_tex_instr *instr, unsigned texture) +{ + switch (texture) { + case TGSI_TEXTURE_1D: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + break; + case TGSI_TEXTURE_1D_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + instr->is_array = true; + break; + case TGSI_TEXTURE_SHADOW1D: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + instr->is_shadow = true; + break; + case TGSI_TEXTURE_SHADOW1D_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + instr->is_shadow = true; + instr->is_array = true; + break; + case TGSI_TEXTURE_2D: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + break; + case TGSI_TEXTURE_2D_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + instr->is_array = true; + break; + case TGSI_TEXTURE_2D_MSAA: + instr->sampler_dim = GLSL_SAMPLER_DIM_MS; + break; + case TGSI_TEXTURE_2D_ARRAY_MSAA: + instr->sampler_dim = GLSL_SAMPLER_DIM_MS; + instr->is_array = true; + break; + case TGSI_TEXTURE_SHADOW2D: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + instr->is_shadow = true; + break; + case TGSI_TEXTURE_SHADOW2D_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + instr->is_shadow = true; + instr->is_array = true; + break; + case TGSI_TEXTURE_3D: + instr->sampler_dim = GLSL_SAMPLER_DIM_3D; + break; + case TGSI_TEXTURE_CUBE: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + break; + case TGSI_TEXTURE_CUBE_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + instr->is_array = true; + break; + case TGSI_TEXTURE_SHADOWCUBE: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + instr->is_shadow = true; + break; + case TGSI_TEXTURE_SHADOWCUBE_ARRAY: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + instr->is_shadow = true; + instr->is_array = true; + break; + case TGSI_TEXTURE_RECT: + instr->sampler_dim = GLSL_SAMPLER_DIM_RECT; + break; + case TGSI_TEXTURE_SHADOWRECT: + instr->sampler_dim = GLSL_SAMPLER_DIM_RECT; + instr->is_shadow = true; + break; + default: + fprintf(stderr, "Unknown TGSI texture target %d\n", texture); + abort(); + } +} + +static void +ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_builder *b = &c->build; + struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction; + nir_tex_instr *instr; + nir_texop op; + unsigned num_srcs, samp = 1, i; + + switch (tgsi_inst->Instruction.Opcode) { + case TGSI_OPCODE_TEX: + op = nir_texop_tex; + num_srcs = 1; + break; + case TGSI_OPCODE_TXP: + op = nir_texop_tex; + num_srcs = 2; + break; + case TGSI_OPCODE_TXB: + op = nir_texop_txb; + num_srcs = 2; + break; + case TGSI_OPCODE_TXL: + op = nir_texop_txl; + num_srcs = 2; + break; + case TGSI_OPCODE_TXL2: + op = nir_texop_txl; + num_srcs = 2; + samp = 2; + break; + case TGSI_OPCODE_TXF: + op = nir_texop_txf; + num_srcs = 2; + break; + case TGSI_OPCODE_TXD: + op = nir_texop_txd; + num_srcs = 3; + samp = 3; + break; + + default: + fprintf(stderr, "unknown TGSI tex op %d\n", tgsi_inst->Instruction.Opcode); + abort(); + } + + if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D_ARRAY || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D_ARRAY || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE || + tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) { + num_srcs++; + } + + num_srcs += tgsi_inst->Texture.NumOffsets; + + instr = nir_tex_instr_create(b->shader, num_srcs); + instr->op = op; + + setup_texture_info(instr, tgsi_inst->Texture.Texture); + + switch (instr->sampler_dim) { + case GLSL_SAMPLER_DIM_1D: + case GLSL_SAMPLER_DIM_BUF: + instr->coord_components = 1; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_EXTERNAL: + case GLSL_SAMPLER_DIM_MS: + instr->coord_components = 2; + break; + case GLSL_SAMPLER_DIM_3D: + case GLSL_SAMPLER_DIM_CUBE: + instr->coord_components = 3; + break; + } + + if (instr->is_array) + instr->coord_components++; + + assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER); + instr->sampler_index = tgsi_inst->Src[samp].Register.Index; + + unsigned src_number = 0; + + instr->src[src_number].src = + nir_src_for_ssa(nir_swizzle(b, src[0], SWIZ(X, Y, Z, W), + instr->coord_components, false)); + instr->src[src_number].src_type = nir_tex_src_coord; + src_number++; + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXP) { + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_projector; + src_number++; + } + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB) { + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_bias; + src_number++; + } + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL) { + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_lod; + src_number++; + } + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL2) { + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[1], X)); + instr->src[src_number].src_type = nir_tex_src_lod; + src_number++; + } + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXF) { + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_lod; + src_number++; + } + + if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXD) { + instr->src[src_number].src = + nir_src_for_ssa(nir_swizzle(b, src[1], SWIZ(X, Y, Z, W), + instr->coord_components, false)); + instr->src[src_number].src_type = nir_tex_src_ddx; + src_number++; + instr->src[src_number].src = + nir_src_for_ssa(nir_swizzle(b, src[2], SWIZ(X, Y, Z, W), + instr->coord_components, false)); + instr->src[src_number].src_type = nir_tex_src_ddy; + src_number++; + } + + if (instr->is_shadow) { + if (instr->coord_components < 3) + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], Z)); + else + instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W)); + + instr->src[src_number].src_type = nir_tex_src_comparitor; + src_number++; + } + + for (i = 0; i < tgsi_inst->Texture.NumOffsets; i++) { + struct tgsi_texture_offset *tex_offset = &tgsi_inst->TexOffsets[i]; + /* since TexOffset ins't using tgsi_full_src_register we get to + * do some extra gymnastics: + */ + nir_alu_src src; + + memset(&src, 0, sizeof(src)); + + src.src = ttn_src_for_file_and_index(c, + tex_offset->File, + tex_offset->Index, + NULL, NULL, NULL); + + src.swizzle[0] = tex_offset->SwizzleX; + src.swizzle[1] = tex_offset->SwizzleY; + src.swizzle[2] = tex_offset->SwizzleZ; + src.swizzle[3] = TGSI_SWIZZLE_W; + + instr->src[src_number].src_type = nir_tex_src_offset; + instr->src[src_number].src = nir_src_for_ssa( + nir_fmov_alu(b, src, nir_tex_instr_src_size(instr, src_number))); + src_number++; + } + + assert(src_number == num_srcs); + + nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); + + /* Resolve the writemask on the texture op. */ + ttn_move_dest(b, dest, &instr->dest.ssa); +} + +/* TGSI_OPCODE_TXQ is actually two distinct operations: + * + * dst.x = texture\_width(unit, lod) + * dst.y = texture\_height(unit, lod) + * dst.z = texture\_depth(unit, lod) + * dst.w = texture\_levels(unit) + * + * dst.xyz map to NIR txs opcode, and dst.w maps to query_levels + */ +static void +ttn_txq(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_builder *b = &c->build; + struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction; + nir_tex_instr *txs, *qlv; + + txs = nir_tex_instr_create(b->shader, 1); + txs->op = nir_texop_txs; + setup_texture_info(txs, tgsi_inst->Texture.Texture); + + qlv = nir_tex_instr_create(b->shader, 0); + qlv->op = nir_texop_query_levels; + setup_texture_info(qlv, tgsi_inst->Texture.Texture); + + assert(tgsi_inst->Src[1].Register.File == TGSI_FILE_SAMPLER); + txs->sampler_index = tgsi_inst->Src[1].Register.Index; + qlv->sampler_index = tgsi_inst->Src[1].Register.Index; + + /* only single src, the lod: */ + txs->src[0].src = nir_src_for_ssa(ttn_channel(b, src[0], X)); + txs->src[0].src_type = nir_tex_src_lod; + + nir_ssa_dest_init(&txs->instr, &txs->dest, 3, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &txs->instr); + + nir_ssa_dest_init(&qlv->instr, &qlv->dest, 1, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &qlv->instr); + + ttn_move_dest_masked(b, dest, &txs->dest.ssa, TGSI_WRITEMASK_XYZ); + ttn_move_dest_masked(b, dest, &qlv->dest.ssa, TGSI_WRITEMASK_W); +} + +static const nir_op op_trans[TGSI_OPCODE_LAST] = { + [TGSI_OPCODE_ARL] = 0, + [TGSI_OPCODE_MOV] = nir_op_fmov, + [TGSI_OPCODE_LIT] = 0, + [TGSI_OPCODE_RCP] = nir_op_frcp, + [TGSI_OPCODE_RSQ] = nir_op_frsq, + [TGSI_OPCODE_EXP] = 0, + [TGSI_OPCODE_LOG] = 0, + [TGSI_OPCODE_MUL] = nir_op_fmul, + [TGSI_OPCODE_ADD] = nir_op_fadd, + [TGSI_OPCODE_DP3] = 0, + [TGSI_OPCODE_DP4] = 0, + [TGSI_OPCODE_DST] = 0, + [TGSI_OPCODE_MIN] = nir_op_fmin, + [TGSI_OPCODE_MAX] = nir_op_fmax, + [TGSI_OPCODE_SLT] = nir_op_slt, + [TGSI_OPCODE_SGE] = nir_op_sge, + [TGSI_OPCODE_MAD] = nir_op_ffma, + [TGSI_OPCODE_SUB] = nir_op_fsub, + [TGSI_OPCODE_LRP] = 0, + [TGSI_OPCODE_SQRT] = nir_op_fsqrt, + [TGSI_OPCODE_DP2A] = 0, + [TGSI_OPCODE_FRC] = nir_op_ffract, + [TGSI_OPCODE_CLAMP] = 0, + [TGSI_OPCODE_FLR] = nir_op_ffloor, + [TGSI_OPCODE_ROUND] = nir_op_fround_even, + [TGSI_OPCODE_EX2] = nir_op_fexp2, + [TGSI_OPCODE_LG2] = nir_op_flog2, + [TGSI_OPCODE_POW] = nir_op_fpow, + [TGSI_OPCODE_XPD] = 0, + [TGSI_OPCODE_ABS] = nir_op_fabs, + [TGSI_OPCODE_DPH] = 0, + [TGSI_OPCODE_COS] = nir_op_fcos, + [TGSI_OPCODE_DDX] = nir_op_fddx, + [TGSI_OPCODE_DDY] = nir_op_fddy, + [TGSI_OPCODE_KILL] = 0, + [TGSI_OPCODE_PK2H] = 0, /* XXX */ + [TGSI_OPCODE_PK2US] = 0, /* XXX */ + [TGSI_OPCODE_PK4B] = 0, /* XXX */ + [TGSI_OPCODE_PK4UB] = 0, /* XXX */ + [TGSI_OPCODE_SEQ] = nir_op_seq, + [TGSI_OPCODE_SGT] = 0, + [TGSI_OPCODE_SIN] = nir_op_fsin, + [TGSI_OPCODE_SLE] = 0, + [TGSI_OPCODE_TEX] = 0, + [TGSI_OPCODE_TXD] = 0, + [TGSI_OPCODE_TXP] = 0, + [TGSI_OPCODE_UP2H] = 0, /* XXX */ + [TGSI_OPCODE_UP2US] = 0, /* XXX */ + [TGSI_OPCODE_UP4B] = 0, /* XXX */ + [TGSI_OPCODE_UP4UB] = 0, /* XXX */ + [TGSI_OPCODE_ARR] = 0, + + /* No function calls, yet. */ + [TGSI_OPCODE_CAL] = 0, /* XXX */ + [TGSI_OPCODE_RET] = 0, /* XXX */ + + [TGSI_OPCODE_SSG] = nir_op_fsign, + [TGSI_OPCODE_CMP] = 0, + [TGSI_OPCODE_SCS] = 0, + [TGSI_OPCODE_TXB] = 0, + [TGSI_OPCODE_DIV] = nir_op_fdiv, + [TGSI_OPCODE_DP2] = 0, + [TGSI_OPCODE_DP2A] = 0, + [TGSI_OPCODE_TXL] = 0, + + [TGSI_OPCODE_BRK] = 0, + [TGSI_OPCODE_IF] = 0, + [TGSI_OPCODE_UIF] = 0, + [TGSI_OPCODE_ELSE] = 0, + [TGSI_OPCODE_ENDIF] = 0, + + [TGSI_OPCODE_DDX_FINE] = nir_op_fddx_fine, + [TGSI_OPCODE_DDY_FINE] = nir_op_fddy_fine, + + [TGSI_OPCODE_PUSHA] = 0, /* XXX */ + [TGSI_OPCODE_POPA] = 0, /* XXX */ + + [TGSI_OPCODE_CEIL] = nir_op_fceil, + [TGSI_OPCODE_I2F] = nir_op_i2f, + [TGSI_OPCODE_NOT] = nir_op_inot, + [TGSI_OPCODE_TRUNC] = nir_op_ftrunc, + [TGSI_OPCODE_SHL] = nir_op_ishl, + [TGSI_OPCODE_AND] = nir_op_iand, + [TGSI_OPCODE_OR] = nir_op_ior, + [TGSI_OPCODE_MOD] = nir_op_umod, + [TGSI_OPCODE_XOR] = nir_op_ixor, + [TGSI_OPCODE_SAD] = 0, /* XXX */ + [TGSI_OPCODE_TXF] = 0, + [TGSI_OPCODE_TXQ] = 0, + + [TGSI_OPCODE_CONT] = 0, + + [TGSI_OPCODE_EMIT] = 0, /* XXX */ + [TGSI_OPCODE_ENDPRIM] = 0, /* XXX */ + + [TGSI_OPCODE_BGNLOOP] = 0, + [TGSI_OPCODE_BGNSUB] = 0, /* XXX: no function calls */ + [TGSI_OPCODE_ENDLOOP] = 0, + [TGSI_OPCODE_ENDSUB] = 0, /* XXX: no function calls */ + + [TGSI_OPCODE_TXQ_LZ] = 0, + [TGSI_OPCODE_NOP] = 0, + [TGSI_OPCODE_FSEQ] = nir_op_feq, + [TGSI_OPCODE_FSGE] = nir_op_fge, + [TGSI_OPCODE_FSLT] = nir_op_flt, + [TGSI_OPCODE_FSNE] = nir_op_fne, + + /* No control flow yet */ + [TGSI_OPCODE_CALLNZ] = 0, /* XXX */ + [TGSI_OPCODE_BREAKC] = 0, /* not emitted by glsl_to_tgsi.cpp */ + + [TGSI_OPCODE_KILL_IF] = 0, + + [TGSI_OPCODE_END] = 0, + + [TGSI_OPCODE_F2I] = nir_op_f2i, + [TGSI_OPCODE_IDIV] = nir_op_idiv, + [TGSI_OPCODE_IMAX] = nir_op_imax, + [TGSI_OPCODE_IMIN] = nir_op_imin, + [TGSI_OPCODE_INEG] = nir_op_ineg, + [TGSI_OPCODE_ISGE] = nir_op_ige, + [TGSI_OPCODE_ISHR] = nir_op_ishr, + [TGSI_OPCODE_ISLT] = nir_op_ilt, + [TGSI_OPCODE_F2U] = nir_op_f2u, + [TGSI_OPCODE_U2F] = nir_op_u2f, + [TGSI_OPCODE_UADD] = nir_op_iadd, + [TGSI_OPCODE_UDIV] = nir_op_udiv, + [TGSI_OPCODE_UMAD] = 0, + [TGSI_OPCODE_UMAX] = nir_op_umax, + [TGSI_OPCODE_UMIN] = nir_op_umin, + [TGSI_OPCODE_UMOD] = nir_op_umod, + [TGSI_OPCODE_UMUL] = nir_op_imul, + [TGSI_OPCODE_USEQ] = nir_op_ieq, + [TGSI_OPCODE_USGE] = nir_op_uge, + [TGSI_OPCODE_USHR] = nir_op_ushr, + [TGSI_OPCODE_USLT] = nir_op_ult, + [TGSI_OPCODE_USNE] = nir_op_ine, + + [TGSI_OPCODE_SWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */ + [TGSI_OPCODE_CASE] = 0, /* not emitted by glsl_to_tgsi.cpp */ + [TGSI_OPCODE_DEFAULT] = 0, /* not emitted by glsl_to_tgsi.cpp */ + [TGSI_OPCODE_ENDSWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */ + + /* XXX: SAMPLE opcodes */ + + [TGSI_OPCODE_UARL] = nir_op_imov, + [TGSI_OPCODE_UCMP] = 0, + [TGSI_OPCODE_IABS] = nir_op_iabs, + [TGSI_OPCODE_ISSG] = nir_op_isign, + + /* XXX: atomics */ + + [TGSI_OPCODE_TEX2] = 0, + [TGSI_OPCODE_TXB2] = 0, + [TGSI_OPCODE_TXL2] = 0, + + [TGSI_OPCODE_IMUL_HI] = nir_op_imul_high, + [TGSI_OPCODE_UMUL_HI] = nir_op_umul_high, + + [TGSI_OPCODE_TG4] = 0, + [TGSI_OPCODE_LODQ] = 0, /* XXX */ + + [TGSI_OPCODE_IBFE] = nir_op_ibitfield_extract, + [TGSI_OPCODE_UBFE] = nir_op_ubitfield_extract, + [TGSI_OPCODE_BFI] = nir_op_bitfield_insert, + [TGSI_OPCODE_BREV] = nir_op_bitfield_reverse, + [TGSI_OPCODE_POPC] = nir_op_bit_count, + [TGSI_OPCODE_LSB] = nir_op_find_lsb, + [TGSI_OPCODE_IMSB] = nir_op_ifind_msb, + [TGSI_OPCODE_UMSB] = nir_op_ifind_msb, /* XXX: signed vs unsigned */ + + [TGSI_OPCODE_INTERP_CENTROID] = 0, /* XXX */ + [TGSI_OPCODE_INTERP_SAMPLE] = 0, /* XXX */ + [TGSI_OPCODE_INTERP_OFFSET] = 0, /* XXX */ +}; + +static void +ttn_emit_instruction(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction; + unsigned i; + unsigned tgsi_op = tgsi_inst->Instruction.Opcode; + struct tgsi_full_dst_register *tgsi_dst = &tgsi_inst->Dst[0]; + + if (tgsi_op == TGSI_OPCODE_END) + return; + + nir_ssa_def *src[TGSI_FULL_MAX_SRC_REGISTERS]; + for (i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++) { + src[i] = ttn_get_src(c, &tgsi_inst->Src[i]); + } + nir_alu_dest dest = ttn_get_dest(c, tgsi_dst); + + switch (tgsi_op) { + case TGSI_OPCODE_RSQ: + ttn_move_dest(b, dest, nir_frsq(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_SQRT: + ttn_move_dest(b, dest, nir_fsqrt(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_RCP: + ttn_move_dest(b, dest, nir_frcp(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_EX2: + ttn_move_dest(b, dest, nir_fexp2(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_LG2: + ttn_move_dest(b, dest, nir_flog2(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_POW: + ttn_move_dest(b, dest, nir_fpow(b, + ttn_channel(b, src[0], X), + ttn_channel(b, src[1], X))); + break; + + case TGSI_OPCODE_COS: + ttn_move_dest(b, dest, nir_fcos(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_SIN: + ttn_move_dest(b, dest, nir_fsin(b, ttn_channel(b, src[0], X))); + break; + + case TGSI_OPCODE_ARL: + ttn_arl(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_EXP: + ttn_exp(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_LOG: + ttn_log(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DST: + ttn_dst(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_LIT: + ttn_lit(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_CLAMP: + ttn_clamp(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_XPD: + ttn_xpd(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DP2: + ttn_dp2(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DP3: + ttn_dp3(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DP4: + ttn_dp4(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DP2A: + ttn_dp2a(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_DPH: + ttn_dph(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_UMAD: + ttn_umad(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_LRP: + ttn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0])); + break; + + case TGSI_OPCODE_KILL: + ttn_kill(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_ARR: + ttn_arr(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_CMP: + ttn_cmp(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_UCMP: + ttn_ucmp(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_SCS: + ttn_scs(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_SGT: + ttn_sgt(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_SLE: + ttn_sle(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_KILL_IF: + ttn_kill_if(b, op_trans[tgsi_op], dest, src); + break; + + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TXP: + case TGSI_OPCODE_TXL: + case TGSI_OPCODE_TXB: + case TGSI_OPCODE_TXD: + case TGSI_OPCODE_TXL2: + case TGSI_OPCODE_TXB2: + case TGSI_OPCODE_TXQ_LZ: + case TGSI_OPCODE_TXF: + case TGSI_OPCODE_TG4: + ttn_tex(c, dest, src); + break; + + case TGSI_OPCODE_TXQ: + ttn_txq(c, dest, src); + break; + + case TGSI_OPCODE_NOP: + break; + + case TGSI_OPCODE_IF: + ttn_if(c, src[0], false); + break; + + case TGSI_OPCODE_UIF: + ttn_if(c, src[0], true); + break; + + case TGSI_OPCODE_ELSE: + ttn_else(c); + break; + + case TGSI_OPCODE_ENDIF: + ttn_endif(c); + break; + + case TGSI_OPCODE_BGNLOOP: + ttn_bgnloop(c); + break; + + case TGSI_OPCODE_BRK: + ttn_brk(b); + break; + + case TGSI_OPCODE_CONT: + ttn_cont(b); + break; + + case TGSI_OPCODE_ENDLOOP: + ttn_endloop(c); + break; + + default: + if (op_trans[tgsi_op] != 0 || tgsi_op == TGSI_OPCODE_MOV) { + ttn_alu(b, op_trans[tgsi_op], dest, src); + } else { + fprintf(stderr, "unknown TGSI opcode: %s\n", + tgsi_get_opcode_name(tgsi_op)); + abort(); + } + break; + } + + if (tgsi_inst->Instruction.Saturate) { + assert(tgsi_inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE); + assert(!dest.dest.is_ssa); + ttn_move_dest(b, dest, nir_fsat(b, ttn_src_for_dest(b, &dest))); + } + + /* if the dst has a matching var, append store_global to move + * output from reg to var + */ + nir_variable *var = ttn_get_var(c, tgsi_dst); + if (var) { + unsigned index = tgsi_dst->Register.Index; + unsigned offset = c->temp_regs[index].offset; + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var); + struct tgsi_ind_register *indirect = tgsi_dst->Register.Indirect ? + &tgsi_dst->Indirect : NULL; + + store->num_components = 4; + store->variables[0] = ttn_array_deref(c, store, var, offset, indirect); + store->src[0] = nir_src_for_reg(dest.dest.reg.reg); + + nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr); + } +} + +/** + * Puts a NIR intrinsic to store of each TGSI_FILE_OUTPUT value to the output + * variables at the end of the shader. + * + * We don't generate these incrementally as the TGSI_FILE_OUTPUT values are + * written, because there's no output load intrinsic, which means we couldn't + * handle writemasks. + */ +static void +ttn_add_output_stores(struct ttn_compile *c) +{ + nir_builder *b = &c->build; + + foreach_list_typed(nir_variable, var, node, &b->shader->outputs) { + unsigned array_len = MAX2(glsl_get_length(var->type), 1); + unsigned i; + + for (i = 0; i < array_len; i++) { + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_output); + store->num_components = 4; + store->const_index[0] = var->data.driver_location + i; + store->const_index[1] = 1; + store->src[0].reg.reg = c->output_regs[var->data.driver_location].reg; + nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr); + } + } +} + +struct nir_shader * +tgsi_to_nir(const void *tgsi_tokens, + const nir_shader_compiler_options *options) +{ + struct tgsi_parse_context parser; + struct tgsi_shader_info scan; + struct ttn_compile *c; + struct nir_shader *s; + int ret; + + c = rzalloc(NULL, struct ttn_compile); + s = nir_shader_create(NULL, options); + + nir_function *func = nir_function_create(s, "main"); + nir_function_overload *overload = nir_function_overload_create(func); + nir_function_impl *impl = nir_function_impl_create(overload); + + nir_builder_init(&c->build, impl); + nir_builder_insert_after_cf_list(&c->build, &impl->body); + + tgsi_scan_shader(tgsi_tokens, &scan); + c->scan = &scan; + + s->num_inputs = scan.file_max[TGSI_FILE_INPUT] + 1; + s->num_uniforms = scan.const_file_max[0] + 1; + s->num_outputs = scan.file_max[TGSI_FILE_OUTPUT] + 1; + + c->output_regs = rzalloc_array(c, struct ttn_reg_info, + scan.file_max[TGSI_FILE_OUTPUT] + 1); + c->temp_regs = rzalloc_array(c, struct ttn_reg_info, + scan.file_max[TGSI_FILE_TEMPORARY] + 1); + c->imm_defs = rzalloc_array(c, nir_ssa_def *, + scan.file_max[TGSI_FILE_IMMEDIATE] + 1); + + c->if_stack = rzalloc_array(c, struct exec_list *, + (scan.opcode_count[TGSI_OPCODE_IF] + + scan.opcode_count[TGSI_OPCODE_UIF]) * 2); + c->loop_stack = rzalloc_array(c, struct exec_list *, + scan.opcode_count[TGSI_OPCODE_BGNLOOP]); + + ret = tgsi_parse_init(&parser, tgsi_tokens); + assert(ret == TGSI_PARSE_OK); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + c->token = &parser.FullToken; + + switch (parser.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_DECLARATION: + ttn_emit_declaration(c); + break; + + case TGSI_TOKEN_TYPE_INSTRUCTION: + ttn_emit_instruction(c); + break; + + case TGSI_TOKEN_TYPE_IMMEDIATE: + ttn_emit_immediate(c); + break; + } + } + + tgsi_parse_free(&parser); + + ttn_add_output_stores(c); + + ralloc_free(c); + return s; +} diff --git a/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h new file mode 100644 index 000000000..687348a80 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "glsl/nir/nir.h" + +struct nir_shader_compiler_options *options; + +struct nir_shader * +tgsi_to_nir(const void *tgsi_tokens, + const struct nir_shader_compiler_options *options); diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c index bba9122e7..542493252 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c @@ -82,18 +82,10 @@ getDbgHelpProcAddress(LPCSTR lpProcName) hModule = LoadLibraryA("mgwhelp.dll"); if (!hModule) { _debug_printf("warning: mgwhelp.dll not found: symbol names will not be resolved\n" - "warning: download it from http://code.google.com/p/jrfonseca/wiki/DrMingw#MgwHelp\n"); + "warning: download it from https://github.com/jrfonseca/drmingw/#mgwhelp\n"); } } - - /* - * bfdhelp.dll was the predecessor of mgwhelp.dll. It is available from - * http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now. - */ - if (!hModule) { - hModule = LoadLibraryA("bfdhelp.dll"); - } - #endif +#endif /* * Fallback to the real DbgHelp. diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.c b/mesalib/src/gallium/auxiliary/util/u_linkage.c deleted file mode 100644 index 245d941dc..000000000 --- a/mesalib/src/gallium/auxiliary/util/u_linkage.c +++ /dev/null @@ -1,149 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_debug.h" -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_scan.h" -#include "util/u_linkage.h" - -/* we must only record the registers that are actually used, not just declared */ -static INLINE boolean -util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value) -{ - unsigned mask = 1 << (value % (sizeof(long) * 8)); - unsigned long *p = &set->masks[value / (sizeof(long) * 8)]; - unsigned long v = *p & mask; - *p |= mask; - return !!v; -} - -unsigned -util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file) -{ - struct tgsi_shader_info info; - struct tgsi_parse_context parse; - unsigned count = 0; - ubyte *semantic_name; - ubyte *semantic_index; - - tgsi_scan_shader(tokens, &info); - - if(file == TGSI_FILE_INPUT) - { - semantic_name = info.input_semantic_name; - semantic_index = info.input_semantic_index; - } - else if(file == TGSI_FILE_OUTPUT) - { - semantic_name = info.output_semantic_name; - semantic_index = info.output_semantic_index; - } - else - { - assert(0); - semantic_name = NULL; - semantic_index = NULL; - } - - tgsi_parse_init(&parse, tokens); - - memset(set->masks, 0, sizeof(set->masks)); - while(!tgsi_parse_end_of_tokens(&parse)) - { - tgsi_parse_token(&parse); - - if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION) - { - const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction; - unsigned i; - for(i = 0; i < finst->Instruction.NumDstRegs; ++i) - { - if(finst->Dst[i].Register.File == file) - { - unsigned idx = finst->Dst[i].Register.Index; - if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC) - { - if(!util_semantic_set_test_and_set(set, semantic_index[idx])) - ++count; - } - } - } - - for(i = 0; i < finst->Instruction.NumSrcRegs; ++i) - { - if(finst->Src[i].Register.File == file) - { - unsigned idx = finst->Src[i].Register.Index; - if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC) - { - if(!util_semantic_set_test_and_set(set, semantic_index[idx])) - ++count; - } - } - } - } - } - tgsi_parse_free(&parse); - - return count; -} - -#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8)))) - -void -util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots) -{ - int first = -1; - int last = -1; - unsigned i; - - memset(layout, 0xff, num_slots); - - UTIL_SEMANTIC_SET_FOR_EACH(i, set) - { - if(first < 0) - first = i; - last = i; - } - - if (last < (int) efficient_slots) - { - UTIL_SEMANTIC_SET_FOR_EACH(i, set) - layout[i] = i; - } - else if ((last - first) < (int) efficient_slots) - { - UTIL_SEMANTIC_SET_FOR_EACH(i, set) - layout[i - first] = i; - } - else - { - unsigned idx = 0; - UTIL_SEMANTIC_SET_FOR_EACH(i, set) - layout[idx++] = i; - } -} diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.h b/mesalib/src/gallium/auxiliary/util/u_linkage.h deleted file mode 100644 index 7b23123d3..000000000 --- a/mesalib/src/gallium/auxiliary/util/u_linkage.h +++ /dev/null @@ -1,67 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Luca Barbieri - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef U_LINKAGE_H_ -#define U_LINKAGE_H_ - -#include "pipe/p_compiler.h" -#include "pipe/p_shader_tokens.h" - -struct util_semantic_set -{ - unsigned long masks[256 / 8 / sizeof(unsigned long)]; -}; - -static INLINE boolean -util_semantic_set_contains(struct util_semantic_set *set, unsigned char value) -{ - return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8)))); -} - -unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file); - -/* efficient_slots is the number of slots such that hardware performance is - * the same for using that amount, with holes, or less slots but with less - * holes. - * - * num_slots is the size of the layout array and hardware limit instead. - * - * efficient_slots == 0 or efficient_slots == num_slots are typical settings. - */ -void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots); - -static INLINE void -util_semantic_table_from_layout(unsigned char *table, size_t table_size, unsigned char *layout, - unsigned char first_slot_value, unsigned char num_slots) -{ - unsigned char i; - memset(table, 0xff, table_size); - - for(i = 0; i < num_slots; ++i) - table[layout[i]] = first_slot_value + i; -} - -#endif /* U_LINKAGE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index 8f62cac66..3d27a59e8 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -383,14 +383,28 @@ unsigned ffs( unsigned u ) return i; } -#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID) +#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID) || \ + defined(HAVE___BUILTIN_FFS) #define ffs __builtin_ffs -#define ffsll __builtin_ffsll #endif #endif /* FFS_DEFINED */ /** + * Find first bit set in long long. Least significant bit is 1. + * Return 0 if no bits set. + */ +#ifndef FFSLL_DEFINED +#define FFSLL_DEFINED 1 + +#if defined(__MINGW32__) || defined(PIPE_OS_ANDROID) || \ + defined(HAVE___BUILTIN_FFSLL) +#define ffsll __builtin_ffsll +#endif + +#endif /* FFSLL_DEFINED */ + +/** * Find last bit set in a word. The least significant bit is 1. * Return 0 if no bits are set. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c index 6252e5dcf..8e199200f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_tile.c +++ b/mesalib/src/gallium/auxiliary/util/u_tile.c @@ -214,13 +214,13 @@ s8x24_get_tile_rgba(const unsigned *src, unsigned i, j; for (i = 0; i < h; i++) { - float *pRow = p; + uint32_t *pRow = (uint32_t *)p; for (j = 0; j < w; j++, pRow += 4) { pRow[0] = pRow[1] = pRow[2] = - pRow[3] = (float)((*src++ >> 24) & 0xff); + pRow[3] = ((*src++ >> 24) & 0xff); } p += dst_stride; @@ -241,12 +241,12 @@ x24s8_get_tile_rgba(const unsigned *src, unsigned i, j; for (i = 0; i < h; i++) { - float *pRow = p; + uint32_t *pRow = (uint32_t *)p; for (j = 0; j < w; j++, pRow += 4) { pRow[0] = pRow[1] = pRow[2] = - pRow[3] = (float)(*src++ & 0xff); + pRow[3] = (*src++ & 0xff); } p += dst_stride; } @@ -265,12 +265,12 @@ s8_get_tile_rgba(const unsigned char *src, unsigned i, j; for (i = 0; i < h; i++) { - float *pRow = p; + uint32_t *pRow = (uint32_t *)p; for (j = 0; j < w; j++, pRow += 4) { pRow[0] = pRow[1] = pRow[2] = - pRow[3] = (float)(*src++ & 0xff); + pRow[3] = (*src++ & 0xff); } p += dst_stride; } diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am index b466a3b5c..23c6fe8bb 100644 --- a/mesalib/src/glsl/Makefile.am +++ b/mesalib/src/glsl/Makefile.am @@ -46,6 +46,7 @@ EXTRA_DIST = tests glcpp/tests README TODO glcpp/README \ glcpp/glcpp-lex.l \ glcpp/glcpp-parse.y \ nir/nir_algebraic.py \ + nir/nir_builder_opcodes_h.py \ nir/nir_constant_expressions.py \ nir/nir_opcodes.py \ nir/nir_opcodes_c.py \ @@ -67,7 +68,7 @@ TESTS_ENVIRONMENT= \ export PYTHON2=$(PYTHON2); \ export PYTHON_FLAGS=$(PYTHON_FLAGS); -noinst_LTLIBRARIES = libglsl.la libglcpp.la +noinst_LTLIBRARIES = libnir.la libglsl.la libglcpp.la check_PROGRAMS = \ glcpp/glcpp \ glsl_test \ @@ -147,6 +148,12 @@ libglsl_la_SOURCES = \ $(LIBGLSL_FILES) \ $(NIR_FILES) +libnir_la_SOURCES = \ + glsl_types.cpp \ + builtin_types.cpp \ + glsl_symbol_table.cpp \ + $(NIR_FILES) + glsl_compiler_SOURCES = \ $(GLSL_COMPILER_CXX_FILES) @@ -251,8 +258,6 @@ nir/nir_opcodes.h: nir/nir_opcodes.py nir/nir_opcodes_h.py $(MKDIR_P) nir; \ $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_opcodes_h.py > $@ -nir/nir.h: nir/nir_opcodes.h - nir/nir_opcodes.c: nir/nir_opcodes.py nir/nir_opcodes_c.py $(MKDIR_P) nir; \ $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_opcodes_c.py > $@ diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index b876642e8..c471eca23 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -22,6 +22,7 @@ NIR_FILES = \ nir/glsl_to_nir.h \ nir/nir.c \ nir/nir.h \ + nir/nir_builder.h \ nir/nir_constant_expressions.h \ nir/nir_dominance.c \ nir/nir_from_ssa.c \ @@ -32,21 +33,25 @@ NIR_FILES = \ nir/nir_lower_atomics.c \ nir/nir_lower_global_vars_to_local.c \ nir/nir_lower_locals_to_regs.c \ + nir/nir_lower_idiv.c \ nir/nir_lower_io.c \ nir/nir_lower_phis_to_scalar.c \ nir/nir_lower_samplers.cpp \ nir/nir_lower_system_values.c \ + nir/nir_lower_tex_projector.c \ nir/nir_lower_to_source_mods.c \ nir/nir_lower_vars_to_ssa.c \ nir/nir_lower_var_copies.c \ nir/nir_lower_vec_to_movs.c \ nir/nir_metadata.c \ + nir/nir_normalize_cubemap_coords.c \ nir/nir_opt_constant_folding.c \ nir/nir_opt_copy_propagate.c \ nir/nir_opt_cse.c \ nir/nir_opt_dce.c \ nir/nir_opt_gcm.c \ nir/nir_opt_global_to_local.c \ + nir/nir_opt_peephole_ffma.c \ nir/nir_opt_peephole_select.c \ nir/nir_opt_remove_phis.c \ nir/nir_print.c \ @@ -54,9 +59,11 @@ NIR_FILES = \ nir/nir_search.c \ nir/nir_search.h \ nir/nir_split_var_copies.c \ + nir/nir_sweep.c \ nir/nir_to_ssa.c \ nir/nir_types.h \ nir/nir_validate.c \ + nir/nir_vla.h \ nir/nir_worklist.c \ nir/nir_worklist.h \ nir/nir_types.cpp \ @@ -183,7 +190,8 @@ LIBGLSL_FILES = \ opt_vectorize.cpp \ program.h \ s_expression.cpp \ - s_expression.h + s_expression.h \ + shader_enums.h # glsl_compiler diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 918be6966..87df93e68 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -1370,71 +1370,59 @@ emit_inline_matrix_constructor(const glsl_type *type, } else { const unsigned cols = type->matrix_columns; const unsigned rows = type->vector_elements; + unsigned remaining_slots = rows * cols; unsigned col_idx = 0; unsigned row_idx = 0; foreach_in_list(ir_rvalue, rhs, parameters) { - const unsigned components_remaining_this_column = rows - row_idx; - unsigned rhs_components = rhs->type->components(); - unsigned rhs_base = 0; - - /* Since the parameter might be used in the RHS of two assignments, - * generate a temporary and copy the paramter there. - */ - ir_variable *rhs_var = - new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary); - instructions->push_tail(rhs_var); - - ir_dereference *rhs_var_ref = - new(ctx) ir_dereference_variable(rhs_var); - ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL); - instructions->push_tail(inst); - - /* Assign the current parameter to as many components of the matrix - * as it will fill. - * - * NOTE: A single vector parameter can span two matrix columns. A - * single vec4, for example, can completely fill a mat2. - */ - if (rhs_components >= components_remaining_this_column) { - const unsigned count = MIN2(rhs_components, - components_remaining_this_column); - - rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); - - ir_instruction *inst = assign_to_matrix_column(var, col_idx, - row_idx, - rhs_var_ref, 0, - count, ctx); - instructions->push_tail(inst); - - rhs_base = count; - - col_idx++; - row_idx = 0; - } - - /* If there is data left in the parameter and components left to be - * set in the destination, emit another assignment. It is possible - * that the assignment could be of a vec4 to the last element of the - * matrix. In this case col_idx==cols, but there is still data - * left in the source parameter. Obviously, don't emit an assignment - * to data outside the destination matrix. - */ - if ((col_idx < cols) && (rhs_base < rhs_components)) { - const unsigned count = rhs_components - rhs_base; - - rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); - - ir_instruction *inst = assign_to_matrix_column(var, col_idx, - row_idx, - rhs_var_ref, - rhs_base, - count, ctx); - instructions->push_tail(inst); - - row_idx += count; - } + unsigned rhs_components = rhs->type->components(); + unsigned rhs_base = 0; + + if (remaining_slots == 0) + break; + + /* Since the parameter might be used in the RHS of two assignments, + * generate a temporary and copy the paramter there. + */ + ir_variable *rhs_var = + new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary); + instructions->push_tail(rhs_var); + + ir_dereference *rhs_var_ref = + new(ctx) ir_dereference_variable(rhs_var); + ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL); + instructions->push_tail(inst); + + do { + /* Assign the current parameter to as many components of the matrix + * as it will fill. + * + * NOTE: A single vector parameter can span two matrix columns. A + * single vec4, for example, can completely fill a mat2. + */ + unsigned count = MIN2(rows - row_idx, + rhs_components - rhs_base); + + rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); + ir_instruction *inst = assign_to_matrix_column(var, col_idx, + row_idx, + rhs_var_ref, + rhs_base, + count, ctx); + instructions->push_tail(inst); + rhs_base += count; + row_idx += count; + remaining_slots -= count; + + /* Sometimes, there is still data left in the parameters and + * components left to be set in the destination but in other + * column. + */ + if (row_idx >= rows) { + row_idx = 0; + col_idx++; + } + } while(remaining_slots > 0 && rhs_base < rhs_components); } } @@ -1791,7 +1779,7 @@ ast_function_expression::hir(exec_list *instructions, return value; } - return ir_rvalue::error_value(ctx); + unreachable("not reached"); } ir_rvalue * diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index d387b2e35..78369360f 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -375,66 +375,14 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, if (type_a == type_b) return type_a; } else { - if (type_a->is_matrix() && type_b->is_matrix()) { - /* Matrix multiply. The columns of A must match the rows of B. Given - * the other previously tested constraints, this means the vector type - * of a row from A must be the same as the vector type of a column from - * B. - */ - if (type_a->row_type() == type_b->column_type()) { - /* The resulting matrix has the number of columns of matrix B and - * the number of rows of matrix A. We get the row count of A by - * looking at the size of a vector that makes up a column. The - * transpose (size of a row) is done for B. - */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_a->column_type()->vector_elements, - type_b->row_type()->vector_elements); - assert(type != glsl_type::error_type); - - return type; - } - } else if (type_a->is_matrix()) { - /* A is a matrix and B is a column vector. Columns of A must match - * rows of B. Given the other previously tested constraints, this - * means the vector type of a row from A must be the same as the - * vector the type of B. - */ - if (type_a->row_type() == type_b) { - /* The resulting vector has a number of elements equal to - * the number of rows of matrix A. */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_a->column_type()->vector_elements, - 1); - assert(type != glsl_type::error_type); - - return type; - } - } else { - assert(type_b->is_matrix()); + const glsl_type *type = glsl_type::get_mul_type(type_a, type_b); - /* A is a row vector and B is a matrix. Columns of A must match rows - * of B. Given the other previously tested constraints, this means - * the type of A must be the same as the vector type of a column from - * B. - */ - if (type_a == type_b->column_type()) { - /* The resulting vector has a number of elements equal to - * the number of columns of matrix B. */ - const glsl_type *const type = - glsl_type::get_instance(type_a->base_type, - type_b->row_type()->vector_elements, - 1); - assert(type != glsl_type::error_type); - - return type; - } + if (type == glsl_type::error_type) { + _mesa_glsl_error(loc, state, + "size mismatch for matrix multiplication"); } - _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication"); - return glsl_type::error_type; + return type; } @@ -5776,6 +5724,9 @@ ast_interface_block::hir(exec_list *instructions, var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; + if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) + var->data.read_only = true; + if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) handle_geometry_shader_input_decl(state, loc, var); @@ -5816,6 +5767,9 @@ ast_interface_block::hir(exec_list *instructions, var->data.sample = fields[i].sample; var->init_interface_type(block_type); + if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) + var->data.read_only = true; + if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) { var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index e46db8552..98d0b1887 100755 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -60,7 +60,7 @@ #include "ir_builder.h" #include "glsl_parser_extras.h" #include "program/prog_instruction.h" -#include <limits> +#include <math.h> #define M_PIf ((float) M_PI) #define M_PI_2f ((float) M_PI/2.0f) @@ -3215,7 +3215,7 @@ builtin_builder::_isinf(builtin_available_predicate avail, const glsl_type *type ir_constant_data infinities; for (int i = 0; i < type->vector_elements; i++) { - infinities.f[i] = std::numeric_limits<float>::infinity(); + infinities.f[i] = INFINITY; } body.emit(ret(equal(abs(x), imm(type, infinities)))); diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 8dc3d106b..2785ed168 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -36,14 +36,13 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); #define YY_USER_ACTION \ do { \ - yylloc->source = 0; \ yylloc->first_column = yycolumn + 1; \ yylloc->first_line = yylloc->last_line = yylineno + 1; \ yycolumn += yyleng; \ yylloc->last_column = yycolumn + 1; \ } while(0); -#define YY_USER_INIT yylineno = 0; yycolumn = 0; +#define YY_USER_INIT yylineno = 0; yycolumn = 0; yylloc->source = 0; /* A macro for handling reserved words and keywords across language versions. * @@ -188,6 +187,15 @@ HASH ^{SPC}#{SPC} * one-based. */ yylineno = strtol(ptr, &ptr, 0) - 1; + + /* From GLSL 3.30 and GLSL ES on, after processing the + * line directive (including its new-line), the implementation + * will behave as if it is compiling at the line number passed + * as argument. It was line number + 1 in older specifications. + */ + if (yyextra->is_version(330, 100)) + yylineno--; + yylloc->source = strtol(ptr, NULL, 0); } {HASH}line{SPCP}{INT}{SPC}$ { @@ -203,6 +211,14 @@ HASH ^{SPC}#{SPC} * one-based. */ yylineno = strtol(ptr, &ptr, 0) - 1; + + /* From GLSL 3.30 and GLSL ES on, after processing the + * line directive (including its new-line), the implementation + * will behave as if it is compiling at the line number passed + * as argument. It was line number + 1 in older specifications. + */ + if (yyextra->is_version(330, 100)) + yylineno--; } ^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}on{SPC}\) { BEGIN PP; diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 79624bc26..0aa3c54fc 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -73,8 +73,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->uses_builtin_functions = false; /* Set default language version and extensions */ - this->language_version = ctx->Const.ForceGLSLVersion ? - ctx->Const.ForceGLSLVersion : 110; + this->language_version = 110; + this->forced_language_version = ctx->Const.ForceGLSLVersion; this->es_shader = false; this->ARB_texture_rectangle_enable = true; @@ -320,11 +320,14 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, this->ARB_texture_rectangle_enable = false; } - this->language_version = version; + if (this->forced_language_version) + this->language_version = this->forced_language_version; + else + this->language_version = version; bool supported = false; for (unsigned i = 0; i < this->num_supported_versions; i++) { - if (this->supported_versions[i].ver == (unsigned) version + if (this->supported_versions[i].ver == this->language_version && this->supported_versions[i].es == this->es_shader) { supported = true; break; diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index c5670fdb1..5047049fb 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -109,8 +109,10 @@ struct _mesa_glsl_parse_state { { unsigned required_version = this->es_shader ? required_glsl_es_version : required_glsl_version; + unsigned this_version = this->forced_language_version + ? this->forced_language_version : this->language_version; return required_version != 0 - && this->language_version >= required_version; + && this_version >= required_version; } bool check_version(unsigned required_glsl_version, @@ -230,6 +232,7 @@ struct _mesa_glsl_parse_state { bool es_shader; unsigned language_version; + unsigned forced_language_version; gl_shader_stage stage; /** diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 38b37a6a9..4aa36a794 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -825,6 +825,73 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields, const glsl_type * +glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b) +{ + if (type_a == type_b) { + return type_a; + } else if (type_a->is_matrix() && type_b->is_matrix()) { + /* Matrix multiply. The columns of A must match the rows of B. Given + * the other previously tested constraints, this means the vector type + * of a row from A must be the same as the vector type of a column from + * B. + */ + if (type_a->row_type() == type_b->column_type()) { + /* The resulting matrix has the number of columns of matrix B and + * the number of rows of matrix A. We get the row count of A by + * looking at the size of a vector that makes up a column. The + * transpose (size of a row) is done for B. + */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + type_b->row_type()->vector_elements); + assert(type != error_type); + + return type; + } + } else if (type_a->is_matrix()) { + /* A is a matrix and B is a column vector. Columns of A must match + * rows of B. Given the other previously tested constraints, this + * means the vector type of a row from A must be the same as the + * vector the type of B. + */ + if (type_a->row_type() == type_b) { + /* The resulting vector has a number of elements equal to + * the number of rows of matrix A. */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_a->column_type()->vector_elements, + 1); + assert(type != error_type); + + return type; + } + } else { + assert(type_b->is_matrix()); + + /* A is a row vector and B is a matrix. Columns of A must match rows + * of B. Given the other previously tested constraints, this means + * the type of A must be the same as the vector type of a column from + * B. + */ + if (type_a == type_b->column_type()) { + /* The resulting vector has a number of elements equal to + * the number of columns of matrix B. */ + const glsl_type *const type = + get_instance(type_a->base_type, + type_b->row_type()->vector_elements, + 1); + assert(type != error_type); + + return type; + } + } + + return error_type; +} + + +const glsl_type * glsl_type::field_type(const char *name) const { if (this->base_type != GLSL_TYPE_STRUCT @@ -1077,15 +1144,6 @@ glsl_type::std140_base_alignment(bool row_major) const return base_alignment; } - /* A sampler may never occur in a UBO (without bindless of some sort), - * however it is convenient to use this alignment function even with - * regular uniforms. This allows use of this function on uniform structs - * that contain samplers. - */ - if (this->is_sampler()) { - return 0; - } - assert(!"not reached"); return -1; } diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 7359e9476..d383dd5be 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -276,6 +276,12 @@ struct glsl_type { const char *block_name); /** + * Get the type resulting from a multiplication of \p type_a * \p type_b + */ + static const glsl_type *get_mul_type(const glsl_type *type_a, + const glsl_type *type_b); + + /** * Query the total number of scalars that make up a scalar, vector or matrix */ unsigned components() const diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 516a53499..68c37275c 100755 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -240,8 +240,6 @@ ir_expression::ir_expression(int op, ir_rvalue *op0) case ir_unop_round_even: case ir_unop_sin: case ir_unop_cos: - case ir_unop_sin_reduced: - case ir_unop_cos_reduced: case ir_unop_dFdx: case ir_unop_dFdx_coarse: case ir_unop_dFdx_fine: @@ -380,10 +378,12 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1) } else if (op1->type->is_scalar()) { this->type = op0->type; } else { - /* FINISHME: matrix types */ - assert(!op0->type->is_matrix() && !op1->type->is_matrix()); - assert(op0->type == op1->type); - this->type = op0->type; + if (this->operation == ir_binop_mul) { + this->type = glsl_type::get_mul_type(op0->type, op1->type); + } else { + assert(op0->type == op1->type); + this->type = op0->type; + } } break; @@ -540,8 +540,6 @@ static const char *const operator_strs[] = { "round_even", "sin", "cos", - "sin_reduced", - "cos_reduced", "dFdx", "dFdxCoarse", "dFdxFine", diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index fdc22edf1..fab1cd2d2 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -109,6 +109,31 @@ public: virtual ir_instruction *clone(void *mem_ctx, struct hash_table *ht) const = 0; + bool is_rvalue() const + { + return ir_type == ir_type_dereference_array || + ir_type == ir_type_dereference_record || + ir_type == ir_type_dereference_variable || + ir_type == ir_type_constant || + ir_type == ir_type_expression || + ir_type == ir_type_swizzle || + ir_type == ir_type_texture; + } + + bool is_dereference() const + { + return ir_type == ir_type_dereference_array || + ir_type == ir_type_dereference_record || + ir_type == ir_type_dereference_variable; + } + + bool is_jump() const + { + return ir_type == ir_type_loop_jump || + ir_type == ir_type_return || + ir_type == ir_type_discard; + } + /** * \name IR instruction downcast functions * @@ -117,45 +142,33 @@ public: * Additional downcast functions will be added as needed. */ /*@{*/ - class ir_rvalue *as_rvalue() - { - assume(this != NULL); - if (ir_type == ir_type_dereference_array || - ir_type == ir_type_dereference_record || - ir_type == ir_type_dereference_variable || - ir_type == ir_type_constant || - ir_type == ir_type_expression || - ir_type == ir_type_swizzle || - ir_type == ir_type_texture) - return (class ir_rvalue *) this; - return NULL; - } - - class ir_dereference *as_dereference() - { - assume(this != NULL); - if (ir_type == ir_type_dereference_array || - ir_type == ir_type_dereference_record || - ir_type == ir_type_dereference_variable) - return (class ir_dereference *) this; - return NULL; - } - - class ir_jump *as_jump() - { - assume(this != NULL); - if (ir_type == ir_type_loop_jump || - ir_type == ir_type_return || - ir_type == ir_type_discard) - return (class ir_jump *) this; - return NULL; - } + #define AS_BASE(TYPE) \ + class ir_##TYPE *as_##TYPE() \ + { \ + assume(this != NULL); \ + return is_##TYPE() ? (ir_##TYPE *) this : NULL; \ + } \ + const class ir_##TYPE *as_##TYPE() const \ + { \ + assume(this != NULL); \ + return is_##TYPE() ? (ir_##TYPE *) this : NULL; \ + } + + AS_BASE(rvalue) + AS_BASE(dereference) + AS_BASE(jump) + #undef AS_BASE #define AS_CHILD(TYPE) \ class ir_##TYPE * as_##TYPE() \ { \ assume(this != NULL); \ return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \ + } \ + const class ir_##TYPE * as_##TYPE() const \ + { \ + assume(this != NULL); \ + return ir_type == ir_type_##TYPE ? (const ir_##TYPE *) this : NULL; \ } AS_CHILD(variable) AS_CHILD(function) @@ -183,7 +196,8 @@ public: * in particular. No support for other instruction types (assignments, * jumps, calls, etc.) is planned. */ - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; protected: ir_instruction(enum ir_node_type t) @@ -1300,8 +1314,6 @@ enum ir_expression_operation { /*@{*/ ir_unop_sin, ir_unop_cos, - ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */ - ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */ /*@}*/ /** @@ -1598,7 +1610,8 @@ public: */ ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const; @@ -1909,7 +1922,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Return a string representing the ir_texture_opcode. @@ -2010,7 +2024,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; bool is_lvalue() const { @@ -2063,7 +2078,8 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get the variable that is ultimately referenced by an r-value @@ -2109,7 +2125,8 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get the variable that is ultimately referenced by an r-value @@ -2219,7 +2236,8 @@ public: virtual ir_visitor_status accept(ir_hierarchical_visitor *); - virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset); + virtual bool equals(const ir_instruction *ir, + enum ir_node_type ignore = ir_type_unset) const; /** * Get a particular component of a constant as a specific type diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index d198276c6..bbf2b0ca8 100755 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -774,7 +774,6 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) break; case ir_unop_sin: - case ir_unop_sin_reduced: assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); for (unsigned c = 0; c < op[0]->type->components(); c++) { data.f[c] = sinf(op[0]->value.f[c]); @@ -782,7 +781,6 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) break; case ir_unop_cos: - case ir_unop_cos_reduced: assert(op[0]->type->base_type == GLSL_TYPE_FLOAT); for (unsigned c = 0; c < op[0]->type->components(); c++) { data.f[c] = cosf(op[0]->value.f[c]); diff --git a/mesalib/src/glsl/ir_equals.cpp b/mesalib/src/glsl/ir_equals.cpp index 65376cd94..cc1964eef 100644 --- a/mesalib/src/glsl/ir_equals.cpp +++ b/mesalib/src/glsl/ir_equals.cpp @@ -28,7 +28,8 @@ * can't access a's vtable in that case. */ static bool -possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ignore) +possibly_null_equals(const ir_instruction *a, const ir_instruction *b, + enum ir_node_type ignore) { if (!a || !b) return !a && !b; @@ -41,13 +42,13 @@ possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ign * about. */ bool -ir_instruction::equals(ir_instruction *, enum ir_node_type) +ir_instruction::equals(const ir_instruction *, enum ir_node_type) const { return false; } bool -ir_constant::equals(ir_instruction *ir, enum ir_node_type) +ir_constant::equals(const ir_instruction *ir, enum ir_node_type) const { const ir_constant *other = ir->as_constant(); if (!other) @@ -65,7 +66,8 @@ ir_constant::equals(ir_instruction *ir, enum ir_node_type) } bool -ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type) +ir_dereference_variable::equals(const ir_instruction *ir, + enum ir_node_type) const { const ir_dereference_variable *other = ir->as_dereference_variable(); if (!other) @@ -75,7 +77,8 @@ ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type) } bool -ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore) +ir_dereference_array::equals(const ir_instruction *ir, + enum ir_node_type ignore) const { const ir_dereference_array *other = ir->as_dereference_array(); if (!other) @@ -94,7 +97,8 @@ ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore) } bool -ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore) +ir_swizzle::equals(const ir_instruction *ir, + enum ir_node_type ignore) const { const ir_swizzle *other = ir->as_swizzle(); if (!other) @@ -116,7 +120,7 @@ ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore) } bool -ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore) +ir_texture::equals(const ir_instruction *ir, enum ir_node_type ignore) const { const ir_texture *other = ir->as_texture(); if (!other) @@ -179,7 +183,7 @@ ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore) } bool -ir_expression::equals(ir_instruction *ir, enum ir_node_type ignore) +ir_expression::equals(const ir_instruction *ir, enum ir_node_type ignore) const { const ir_expression *other = ir->as_expression(); if (!other) diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 7a7688cb2..cfe0df3dc 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -334,8 +334,6 @@ ir_validate::visit_leave(ir_expression *ir) break; case ir_unop_sin: case ir_unop_cos: - case ir_unop_sin_reduced: - case ir_unop_cos_reduced: case ir_unop_dFdx: case ir_unop_dFdx_coarse: case ir_unop_dFdx_fine: @@ -543,9 +541,9 @@ ir_validate::visit_leave(ir_expression *ir) case ir_binop_logic_and: case ir_binop_logic_xor: case ir_binop_logic_or: - assert(ir->type == glsl_type::bool_type); - assert(ir->operands[0]->type == glsl_type::bool_type); - assert(ir->operands[1]->type == glsl_type::bool_type); + assert(ir->type->base_type == GLSL_TYPE_BOOL); + assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL); + assert(ir->operands[1]->type->base_type == GLSL_TYPE_BOOL); break; case ir_binop_dot: diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 972ba8100..51b939098 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -547,6 +547,8 @@ private: virtual void enter_record(const glsl_type *type, const char *name, bool row_major) { assert(type->is_record()); + if (this->ubo_block_index == -1) + return; this->ubo_byte_offset = glsl_align( this->ubo_byte_offset, type->std140_base_alignment(row_major)); } @@ -554,6 +556,8 @@ private: virtual void leave_record(const glsl_type *type, const char *name, bool row_major) { assert(type->is_record()); + if (this->ubo_block_index == -1) + return; this->ubo_byte_offset = glsl_align( this->ubo_byte_offset, type->std140_base_alignment(row_major)); } diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index 22617990f..605748a9c 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -263,6 +263,19 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, if (output != NULL) { cross_validate_types_and_qualifiers(prog, input, output, consumer->Stage, producer->Stage); + } else { + /* Check for input vars with unmatched output vars in prev stage + * taking into account that interface blocks could have a matching + * output but with different name, so we ignore them. + */ + assert(!input->data.assigned); + if (input->data.used && !input->get_interface_type() && + !input->data.explicit_location && !prog->SeparateShader) + linker_error(prog, + "%s shader input `%s' " + "has no matching output in the previous stage\n", + _mesa_shader_stage_to_string(consumer->Stage), + input->name); } } } diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 4349f0973..b6baa5d36 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1377,24 +1377,13 @@ link_fs_input_layout_qualifiers(struct gl_shader_program *prog, * "If gl_FragCoord is redeclared in any fragment shader in a program, * it must be redeclared in all the fragment shaders in that program * that have a static use gl_FragCoord." - * - * Exclude the case when one of the 'linked_shader' or 'shader' redeclares - * gl_FragCoord with no layout qualifiers but the other one doesn't - * redeclare it. If we strictly follow GLSL 1.50 spec's language, it - * should be a link error. But, generating link error for this case will - * be a wrong behaviour which spec didn't intend to do and it could also - * break some applications. */ if ((linked_shader->redeclares_gl_fragcoord && !shader->redeclares_gl_fragcoord - && shader->uses_gl_fragcoord - && (linked_shader->origin_upper_left - || linked_shader->pixel_center_integer)) + && shader->uses_gl_fragcoord) || (shader->redeclares_gl_fragcoord && !linked_shader->redeclares_gl_fragcoord - && linked_shader->uses_gl_fragcoord - && (shader->origin_upper_left - || shader->pixel_center_integer))) { + && linked_shader->uses_gl_fragcoord)) { linker_error(prog, "fragment shader defined with conflicting " "layout qualifiers for gl_FragCoord\n"); } @@ -2503,6 +2492,194 @@ check_explicit_uniform_locations(struct gl_context *ctx, delete uniform_map; } +static bool +add_program_resource(struct gl_shader_program *prog, GLenum type, + const void *data, uint8_t stages) +{ + assert(data); + + /* If resource already exists, do not add it again. */ + for (unsigned i = 0; i < prog->NumProgramResourceList; i++) + if (prog->ProgramResourceList[i].Data == data) + return true; + + prog->ProgramResourceList = + reralloc(prog, + prog->ProgramResourceList, + gl_program_resource, + prog->NumProgramResourceList + 1); + + if (!prog->ProgramResourceList) { + linker_error(prog, "Out of memory during linking.\n"); + return false; + } + + struct gl_program_resource *res = + &prog->ProgramResourceList[prog->NumProgramResourceList]; + + res->Type = type; + res->Data = data; + res->StageReferences = stages; + + prog->NumProgramResourceList++; + + return true; +} + +/** + * Function builds a stage reference bitmask from variable name. + */ +static uint8_t +build_stageref(struct gl_shader_program *shProg, const char *name) +{ + uint8_t stages = 0; + + /* Note, that we assume MAX 8 stages, if there will be more stages, type + * used for reference mask in gl_program_resource will need to be changed. + */ + assert(MESA_SHADER_STAGES < 8); + + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_shader *sh = shProg->_LinkedShaders[i]; + if (!sh) + continue; + ir_variable *var = sh->symbols->get_variable(name); + if (var) + stages |= (1 << i); + } + return stages; +} + +static bool +add_interface_variables(struct gl_shader_program *shProg, + struct gl_shader *sh, GLenum programInterface) +{ + foreach_in_list(ir_instruction, node, sh->ir) { + ir_variable *var = node->as_variable(); + + if (!var) + continue; + + switch (var->data.mode) { + /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes): + * "For GetActiveAttrib, all active vertex shader input variables + * are enumerated, including the special built-in inputs gl_VertexID + * and gl_InstanceID." + */ + case ir_var_system_value: + if (var->data.location != SYSTEM_VALUE_VERTEX_ID && + var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE && + var->data.location != SYSTEM_VALUE_INSTANCE_ID) + continue; + case ir_var_shader_in: + if (programInterface != GL_PROGRAM_INPUT) + continue; + break; + case ir_var_shader_out: + if (programInterface != GL_PROGRAM_OUTPUT) + continue; + break; + default: + continue; + }; + + if (!add_program_resource(shProg, programInterface, var, + build_stageref(shProg, var->name))) + return false; + } + return true; +} + +/** + * Builds up a list of program resources that point to existing + * resource data. + */ +static void +build_program_resource_list(struct gl_context *ctx, + struct gl_shader_program *shProg) +{ + /* Rebuild resource list. */ + if (shProg->ProgramResourceList) { + ralloc_free(shProg->ProgramResourceList); + shProg->ProgramResourceList = NULL; + shProg->NumProgramResourceList = 0; + } + + int input_stage = MESA_SHADER_STAGES, output_stage = 0; + + /* Determine first input and final output stage. These are used to + * detect which variables should be enumerated in the resource list + * for GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT. + */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (!shProg->_LinkedShaders[i]) + continue; + if (input_stage == MESA_SHADER_STAGES) + input_stage = i; + output_stage = i; + } + + /* Empty shader, no resources. */ + if (input_stage == MESA_SHADER_STAGES && output_stage == 0) + return; + + /* Add inputs and outputs to the resource list. */ + if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage], + GL_PROGRAM_INPUT)) + return; + + if (!add_interface_variables(shProg, shProg->_LinkedShaders[output_stage], + GL_PROGRAM_OUTPUT)) + return; + + /* Add transform feedback varyings. */ + if (shProg->LinkedTransformFeedback.NumVarying > 0) { + for (int i = 0; i < shProg->LinkedTransformFeedback.NumVarying; i++) { + uint8_t stageref = + build_stageref(shProg, + shProg->LinkedTransformFeedback.Varyings[i].Name); + if (!add_program_resource(shProg, GL_TRANSFORM_FEEDBACK_VARYING, + &shProg->LinkedTransformFeedback.Varyings[i], + stageref)) + return; + } + } + + /* Add uniforms from uniform storage. */ + for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) { + /* Do not add uniforms internally used by Mesa. */ + if (shProg->UniformStorage[i].hidden) + continue; + + uint8_t stageref = + build_stageref(shProg, shProg->UniformStorage[i].name); + if (!add_program_resource(shProg, GL_UNIFORM, + &shProg->UniformStorage[i], stageref)) + return; + } + + /* Add program uniform blocks. */ + for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) { + if (!add_program_resource(shProg, GL_UNIFORM_BLOCK, + &shProg->UniformBlocks[i], 0)) + return; + } + + /* Add atomic counter buffers. */ + for (unsigned i = 0; i < shProg->NumAtomicBuffers; i++) { + if (!add_program_resource(shProg, GL_ATOMIC_COUNTER_BUFFER, + &shProg->AtomicBuffers[i], 0)) + return; + } + + /* TODO - following extensions will require more resource types: + * + * GL_ARB_shader_storage_buffer_object + * GL_ARB_shader_subroutine + */ +} + + void link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -2737,10 +2914,18 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - unsigned first; - for (first = 0; first <= MESA_SHADER_FRAGMENT; first++) { - if (prog->_LinkedShaders[first] != NULL) - break; + unsigned first, last; + + first = MESA_SHADER_STAGES; + last = 0; + + /* Determine first and last stage. */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (!prog->_LinkedShaders[i]) + continue; + if (first == MESA_SHADER_STAGES) + first = i; + last = i; } if (num_tfeedback_decls != 0) { @@ -2769,13 +2954,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * ensures that inter-shader outputs written to in an earlier stage are * eliminated if they are (transitively) not used in a later stage. */ - int last, next; - for (last = MESA_SHADER_FRAGMENT; last >= 0; last--) { - if (prog->_LinkedShaders[last] != NULL) - break; - } + int next; - if (last >= 0 && last < MESA_SHADER_FRAGMENT) { + if (first < MESA_SHADER_FRAGMENT) { gl_shader *const sh = prog->_LinkedShaders[last]; if (first == MESA_SHADER_GEOMETRY) { @@ -2787,13 +2968,14 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * MESA_SHADER_GEOMETRY. */ if (!assign_varying_locations(ctx, mem_ctx, prog, - NULL, sh, + NULL, prog->_LinkedShaders[first], num_tfeedback_decls, tfeedback_decls, prog->Geom.VerticesIn)) goto done; } - if (num_tfeedback_decls != 0 || prog->SeparateShader) { + if (last != MESA_SHADER_FRAGMENT && + (num_tfeedback_decls != 0 || prog->SeparateShader)) { /* There was no fragment shader, but we still have to assign varying * locations for use by transform feedback. */ @@ -2905,6 +3087,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } } + build_program_resource_list(ctx, prog); + if (!prog->LinkStatus) + goto done; + /* FINISHME: Assign fragment shader output locations. */ done: diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp index d7f0b2809..51804bb5f 100644 --- a/mesalib/src/glsl/loop_controls.cpp +++ b/mesalib/src/glsl/loop_controls.cpp @@ -139,7 +139,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, iter = new(mem_ctx) ir_constant(double(iter_value + bias[i])); break; default: - unreachable(!"Unsupported type for loop iterator."); + unreachable("Unsupported type for loop iterator."); } ir_expression *const mul = diff --git a/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp index 2243f479a..44967dcdb 100644 --- a/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp +++ b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp @@ -49,7 +49,6 @@ public: { instructions = insts; progress = false; - index = 0; } bool run() @@ -63,7 +62,6 @@ public: private: exec_list *instructions; bool progress; - unsigned index; }; void @@ -82,7 +80,7 @@ lower_const_array_visitor::handle_rvalue(ir_rvalue **rvalue) void *mem_ctx = ralloc_parent(con); - char *uniform_name = ralloc_asprintf(mem_ctx, "constarray__%d", index++); + char *uniform_name = ralloc_asprintf(mem_ctx, "constarray__%p", dra); ir_variable *uni = new(mem_ctx) ir_variable(con->type, uniform_name, ir_var_uniform); diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp index 357944da6..f6b8331d4 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.cpp +++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp @@ -88,6 +88,8 @@ private: exec_list *cf_node_list; nir_instr *result; /* result of the expression tree last visited */ + nir_deref_var *evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir); + /* the head of the dereference chain we're creating */ nir_deref_var *deref_head; /* the tail of the dereference chain we're creating */ @@ -156,6 +158,14 @@ nir_visitor::~nir_visitor() _mesa_hash_table_destroy(this->overload_table, NULL); } +nir_deref_var * +nir_visitor::evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir) +{ + ir->accept(this); + ralloc_steal(mem_ctx, this->deref_head); + return this->deref_head; +} + static nir_constant * constant_copy(ir_constant *ir, void *mem_ctx) { @@ -582,13 +592,11 @@ void nir_visitor::visit(ir_return *ir) { if (ir->value != NULL) { - ir->value->accept(this); nir_intrinsic_instr *copy = nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var); - copy->variables[0] = nir_deref_var_create(this->shader, - this->impl->return_var); - copy->variables[1] = this->deref_head; + copy->variables[0] = nir_deref_var_create(copy, this->impl->return_var); + copy->variables[1] = evaluate_deref(©->instr, ir->value); } nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return); @@ -613,8 +621,7 @@ nir_visitor::visit(ir_call *ir) nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op); ir_dereference *param = (ir_dereference *) ir->actual_parameters.get_head(); - param->accept(this); - instr->variables[0] = this->deref_head; + instr->variables[0] = evaluate_deref(&instr->instr, param); nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL); nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); @@ -623,8 +630,7 @@ nir_visitor::visit(ir_call *ir) nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); store_instr->num_components = 1; - ir->return_deref->accept(this); - store_instr->variables[0] = this->deref_head; + store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref); store_instr->src[0].is_ssa = true; store_instr->src[0].ssa = &instr->dest.ssa; @@ -642,13 +648,11 @@ nir_visitor::visit(ir_call *ir) unsigned i = 0; foreach_in_list(ir_dereference, param, &ir->actual_parameters) { - param->accept(this); - instr->params[i] = this->deref_head; + instr->params[i] = evaluate_deref(&instr->instr, param); i++; } - ir->return_deref->accept(this); - instr->return_deref = this->deref_head; + instr->return_deref = evaluate_deref(&instr->instr, ir->return_deref); nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); } @@ -663,12 +667,8 @@ nir_visitor::visit(ir_assignment *ir) nir_intrinsic_instr *copy = nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var); - ir->lhs->accept(this); - copy->variables[0] = this->deref_head; - - ir->rhs->accept(this); - copy->variables[1] = this->deref_head; - + copy->variables[0] = evaluate_deref(©->instr, ir->lhs); + copy->variables[1] = evaluate_deref(©->instr, ir->rhs); if (ir->condition) { nir_if *if_stmt = nir_if_create(this->shader); @@ -700,6 +700,7 @@ nir_visitor::visit(ir_assignment *ir) load->num_components = ir->lhs->type->vector_elements; nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL); load->variables[0] = lhs_deref; + ralloc_steal(load, load->variables[0]); nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr); nir_op vec_op; @@ -741,7 +742,7 @@ nir_visitor::visit(ir_assignment *ir) nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var); store->num_components = ir->lhs->type->vector_elements; - nir_deref *store_deref = nir_copy_deref(this->shader, &lhs_deref->deref); + nir_deref *store_deref = nir_copy_deref(store, &lhs_deref->deref); store->variables[0] = nir_deref_as_var(store_deref); store->src[0] = src; @@ -816,6 +817,7 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir) nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var); load_instr->num_components = ir->type->vector_elements; load_instr->variables[0] = this->deref_head; + ralloc_steal(load_instr, load_instr->variables[0]); add_instr(&load_instr->instr, ir->type->vector_elements); } @@ -959,6 +961,7 @@ nir_visitor::visit(ir_expression *ir) nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(shader, op); intrin->num_components = deref->type->vector_elements; intrin->variables[0] = this->deref_head; + ralloc_steal(intrin, intrin->variables[0]); if (intrin->intrinsic == nir_intrinsic_interp_var_at_offset || intrin->intrinsic == nir_intrinsic_interp_var_at_sample) @@ -1087,12 +1090,6 @@ nir_visitor::visit(ir_expression *ir) case ir_unop_round_even: emit(nir_op_fround_even, dest_size, srcs); break; case ir_unop_sin: emit(nir_op_fsin, dest_size, srcs); break; case ir_unop_cos: emit(nir_op_fcos, dest_size, srcs); break; - case ir_unop_sin_reduced: - emit(nir_op_fsin_reduced, dest_size, srcs); - break; - case ir_unop_cos_reduced: - emit(nir_op_fcos_reduced, dest_size, srcs); - break; case ir_unop_dFdx: emit(nir_op_fddx, dest_size, srcs); break; case ir_unop_dFdy: emit(nir_op_fddy, dest_size, srcs); break; case ir_unop_dFdx_fine: emit(nir_op_fddx_fine, dest_size, srcs); break; @@ -1210,6 +1207,9 @@ nir_visitor::visit(ir_expression *ir) case ir_binop_bit_and: case ir_binop_bit_or: case ir_binop_bit_xor: + case ir_binop_logic_and: + case ir_binop_logic_or: + case ir_binop_logic_xor: case ir_binop_lshift: case ir_binop_rshift: switch (ir->operation) { @@ -1270,6 +1270,24 @@ nir_visitor::visit(ir_expression *ir) case ir_binop_bit_xor: op = nir_op_ixor; break; + case ir_binop_logic_and: + if (supports_ints) + op = nir_op_iand; + else + op = nir_op_fand; + break; + case ir_binop_logic_or: + if (supports_ints) + op = nir_op_ior; + else + op = nir_op_for; + break; + case ir_binop_logic_xor: + if (supports_ints) + op = nir_op_ixor; + else + op = nir_op_fxor; + break; case ir_binop_lshift: op = nir_op_ishl; break; @@ -1444,24 +1462,6 @@ nir_visitor::visit(ir_expression *ir) } } break; - case ir_binop_logic_and: - if (supports_ints) - emit(nir_op_iand, dest_size, srcs); - else - emit(nir_op_fand, dest_size, srcs); - break; - case ir_binop_logic_or: - if (supports_ints) - emit(nir_op_ior, dest_size, srcs); - else - emit(nir_op_for, dest_size, srcs); - break; - case ir_binop_logic_xor: - if (supports_ints) - emit(nir_op_ixor, dest_size, srcs); - else - emit(nir_op_fxor, dest_size, srcs); - break; case ir_binop_dot: switch (ir->operands[0]->type->vector_elements) { case 2: emit(nir_op_fdot2, dest_size, srcs); break; @@ -1633,8 +1633,7 @@ nir_visitor::visit(ir_texture *ir) unreachable("not reached"); } - ir->sampler->accept(this); - instr->sampler = this->deref_head; + instr->sampler = evaluate_deref(&instr->instr, ir->sampler); unsigned src_number = 0; @@ -1759,7 +1758,7 @@ nir_visitor::visit(ir_dereference_record *ir) int field_index = this->deref_tail->type->field_index(ir->field); assert(field_index >= 0); - nir_deref_struct *deref = nir_deref_struct_create(this->shader, field_index); + nir_deref_struct *deref = nir_deref_struct_create(this->deref_tail, field_index); deref->deref.type = ir->type; this->deref_tail->child = &deref->deref; this->deref_tail = &deref->deref; @@ -1783,5 +1782,6 @@ nir_visitor::visit(ir_dereference_array *ir) ir->array->accept(this); this->deref_tail->child = &deref->deref; + ralloc_steal(this->deref_tail, deref); this->deref_tail = &deref->deref; } diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c index 6459d5108..c6e53612b 100644 --- a/mesalib/src/glsl/nir/nir.c +++ b/mesalib/src/glsl/nir/nir.c @@ -58,11 +58,11 @@ reg_create(void *mem_ctx, struct exec_list *list) nir_register *reg = ralloc(mem_ctx, nir_register); reg->parent_instr = NULL; - reg->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + reg->uses = _mesa_set_create(reg, _mesa_hash_pointer, _mesa_key_pointer_equal); - reg->defs = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + reg->defs = _mesa_set_create(reg, _mesa_hash_pointer, _mesa_key_pointer_equal); - reg->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + reg->if_uses = _mesa_set_create(reg, _mesa_hash_pointer, _mesa_key_pointer_equal); reg->num_components = 0; @@ -108,7 +108,7 @@ nir_function_create(nir_shader *shader, const char *name) exec_list_push_tail(&shader->functions, &func->node); exec_list_make_empty(&func->overload_list); - func->name = name; + func->name = ralloc_strdup(func, name); func->shader = shader; return func; @@ -285,10 +285,10 @@ nir_block_create(void *mem_ctx) cf_init(&block->cf_node, nir_cf_node_block); block->successors[0] = block->successors[1] = NULL; - block->predecessors = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + block->predecessors = _mesa_set_create(block, _mesa_hash_pointer, _mesa_key_pointer_equal); block->imm_dom = NULL; - block->dom_frontier = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + block->dom_frontier = _mesa_set_create(block, _mesa_hash_pointer, _mesa_key_pointer_equal); exec_list_make_empty(&block->instr_list); @@ -381,11 +381,11 @@ alu_src_init(nir_alu_src *src) } nir_alu_instr * -nir_alu_instr_create(void *mem_ctx, nir_op op) +nir_alu_instr_create(nir_shader *shader, nir_op op) { unsigned num_srcs = nir_op_infos[op].num_inputs; nir_alu_instr *instr = - ralloc_size(mem_ctx, + ralloc_size(shader, sizeof(nir_alu_instr) + num_srcs * sizeof(nir_alu_src)); instr_init(&instr->instr, nir_instr_type_alu); @@ -398,18 +398,18 @@ nir_alu_instr_create(void *mem_ctx, nir_op op) } nir_jump_instr * -nir_jump_instr_create(void *mem_ctx, nir_jump_type type) +nir_jump_instr_create(nir_shader *shader, nir_jump_type type) { - nir_jump_instr *instr = ralloc(mem_ctx, nir_jump_instr); + nir_jump_instr *instr = ralloc(shader, nir_jump_instr); instr_init(&instr->instr, nir_instr_type_jump); instr->type = type; return instr; } nir_load_const_instr * -nir_load_const_instr_create(void *mem_ctx, unsigned num_components) +nir_load_const_instr_create(nir_shader *shader, unsigned num_components) { - nir_load_const_instr *instr = ralloc(mem_ctx, nir_load_const_instr); + nir_load_const_instr *instr = ralloc(shader, nir_load_const_instr); instr_init(&instr->instr, nir_instr_type_load_const); nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL); @@ -418,11 +418,11 @@ nir_load_const_instr_create(void *mem_ctx, unsigned num_components) } nir_intrinsic_instr * -nir_intrinsic_instr_create(void *mem_ctx, nir_intrinsic_op op) +nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op) { unsigned num_srcs = nir_intrinsic_infos[op].num_srcs; nir_intrinsic_instr *instr = - ralloc_size(mem_ctx, + ralloc_size(shader, sizeof(nir_intrinsic_instr) + num_srcs * sizeof(nir_src)); instr_init(&instr->instr, nir_instr_type_intrinsic); @@ -438,29 +438,29 @@ nir_intrinsic_instr_create(void *mem_ctx, nir_intrinsic_op op) } nir_call_instr * -nir_call_instr_create(void *mem_ctx, nir_function_overload *callee) +nir_call_instr_create(nir_shader *shader, nir_function_overload *callee) { - nir_call_instr *instr = ralloc(mem_ctx, nir_call_instr); + nir_call_instr *instr = ralloc(shader, nir_call_instr); instr_init(&instr->instr, nir_instr_type_call); instr->callee = callee; instr->num_params = callee->num_params; - instr->params = ralloc_array(mem_ctx, nir_deref_var *, instr->num_params); + instr->params = ralloc_array(instr, nir_deref_var *, instr->num_params); instr->return_deref = NULL; return instr; } nir_tex_instr * -nir_tex_instr_create(void *mem_ctx, unsigned num_srcs) +nir_tex_instr_create(nir_shader *shader, unsigned num_srcs) { - nir_tex_instr *instr = ralloc(mem_ctx, nir_tex_instr); + nir_tex_instr *instr = ralloc(shader, nir_tex_instr); instr_init(&instr->instr, nir_instr_type_tex); dest_init(&instr->dest); instr->num_srcs = num_srcs; - instr->src = ralloc_array(mem_ctx, nir_tex_src, num_srcs); + instr->src = ralloc_array(instr, nir_tex_src, num_srcs); for (unsigned i = 0; i < num_srcs; i++) src_init(&instr->src[i].src); @@ -472,9 +472,9 @@ nir_tex_instr_create(void *mem_ctx, unsigned num_srcs) } nir_phi_instr * -nir_phi_instr_create(void *mem_ctx) +nir_phi_instr_create(nir_shader *shader) { - nir_phi_instr *instr = ralloc(mem_ctx, nir_phi_instr); + nir_phi_instr *instr = ralloc(shader, nir_phi_instr); instr_init(&instr->instr, nir_instr_type_phi); dest_init(&instr->dest); @@ -483,9 +483,9 @@ nir_phi_instr_create(void *mem_ctx) } nir_parallel_copy_instr * -nir_parallel_copy_instr_create(void *mem_ctx) +nir_parallel_copy_instr_create(nir_shader *shader) { - nir_parallel_copy_instr *instr = ralloc(mem_ctx, nir_parallel_copy_instr); + nir_parallel_copy_instr *instr = ralloc(shader, nir_parallel_copy_instr); instr_init(&instr->instr, nir_instr_type_parallel_copy); exec_list_make_empty(&instr->entries); @@ -494,9 +494,9 @@ nir_parallel_copy_instr_create(void *mem_ctx) } nir_ssa_undef_instr * -nir_ssa_undef_instr_create(void *mem_ctx, unsigned num_components) +nir_ssa_undef_instr_create(nir_shader *shader, unsigned num_components) { - nir_ssa_undef_instr *instr = ralloc(mem_ctx, nir_ssa_undef_instr); + nir_ssa_undef_instr *instr = ralloc(shader, nir_ssa_undef_instr); instr_init(&instr->instr, nir_instr_type_ssa_undef); nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL); @@ -543,7 +543,7 @@ copy_deref_var(void *mem_ctx, nir_deref_var *deref) nir_deref_var *ret = nir_deref_var_create(mem_ctx, deref->var); ret->deref.type = deref->deref.type; if (deref->deref.child) - ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child); + ret->deref.child = nir_copy_deref(ret, deref->deref.child); return ret; } @@ -558,7 +558,7 @@ copy_deref_array(void *mem_ctx, nir_deref_array *deref) } ret->deref.type = deref->deref.type; if (deref->deref.child) - ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child); + ret->deref.child = nir_copy_deref(ret, deref->deref.child); return ret; } @@ -568,7 +568,7 @@ copy_deref_struct(void *mem_ctx, nir_deref_struct *deref) nir_deref_struct *ret = nir_deref_struct_create(mem_ctx, deref->index); ret->deref.type = deref->deref.type; if (deref->deref.child) - ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child); + ret->deref.child = nir_copy_deref(ret, deref->deref.child); return ret; } @@ -1834,13 +1834,11 @@ void nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def, unsigned num_components, const char *name) { - void *mem_ctx = ralloc_parent(instr); - def->name = name; def->parent_instr = instr; - def->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + def->uses = _mesa_set_create(instr, _mesa_hash_pointer, _mesa_key_pointer_equal); - def->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer, + def->if_uses = _mesa_set_create(instr, _mesa_hash_pointer, _mesa_key_pointer_equal); def->num_components = num_components; diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h index 29fe94243..74772c798 100644 --- a/mesalib/src/glsl/nir/nir.h +++ b/mesalib/src/glsl/nir/nir.h @@ -34,6 +34,7 @@ #include "util/set.h" #include "util/bitset.h" #include "nir_types.h" +#include "glsl/shader_enums.h" #include <stdio.h> #include "nir_opcodes.h" @@ -529,6 +530,16 @@ nir_src_for_reg(nir_register *reg) return src; } +static inline nir_instr * +nir_src_get_parent_instr(const nir_src *src) +{ + if (src->is_ssa) { + return src->ssa->parent_instr; + } else { + return src->reg.reg->parent_instr; + } +} + static inline nir_dest nir_dest_for_reg(nir_register *reg) { @@ -1365,11 +1376,17 @@ typedef struct nir_function { typedef struct nir_shader_compiler_options { bool lower_ffma; + bool lower_flrp; bool lower_fpow; bool lower_fsat; bool lower_fsqrt; /** lowers fneg and ineg to fsub and isub. */ bool lower_negate; + /** lowers fsub and isub to fadd+fneg and iadd+ineg. */ + bool lower_sub; + + /* lower {slt,sge,seq,sne} to {flt,fge,feq,fne} + b2f: */ + bool lower_scmp; /** * Does the driver support real 32-bit integers? (Otherwise, integers @@ -1414,6 +1431,9 @@ typedef struct nir_shader { * access plus one */ unsigned num_inputs, num_uniforms, num_outputs; + + /** the number of uniforms that are only accessed directly */ + unsigned num_direct_uniforms; } nir_shader; #define nir_foreach_overload(shader, overload) \ @@ -1466,26 +1486,26 @@ void nir_metadata_require(nir_function_impl *impl, nir_metadata required); void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved); /** creates an instruction with default swizzle/writemask/etc. with NULL registers */ -nir_alu_instr *nir_alu_instr_create(void *mem_ctx, nir_op op); +nir_alu_instr *nir_alu_instr_create(nir_shader *shader, nir_op op); -nir_jump_instr *nir_jump_instr_create(void *mem_ctx, nir_jump_type type); +nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type); -nir_load_const_instr *nir_load_const_instr_create(void *mem_ctx, +nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader, unsigned num_components); -nir_intrinsic_instr *nir_intrinsic_instr_create(void *mem_ctx, +nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op); -nir_call_instr *nir_call_instr_create(void *mem_ctx, +nir_call_instr *nir_call_instr_create(nir_shader *shader, nir_function_overload *callee); -nir_tex_instr *nir_tex_instr_create(void *mem_ctx, unsigned num_srcs); +nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs); -nir_phi_instr *nir_phi_instr_create(void *mem_ctx); +nir_phi_instr *nir_phi_instr_create(nir_shader *shader); -nir_parallel_copy_instr *nir_parallel_copy_instr_create(void *mem_ctx); +nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader); -nir_ssa_undef_instr *nir_ssa_undef_instr_create(void *mem_ctx, +nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader, unsigned num_components); nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var); @@ -1550,7 +1570,7 @@ void nir_print_instr(const nir_instr *instr, FILE *fp); #ifdef DEBUG void nir_validate_shader(nir_shader *shader); #else -static inline void nir_validate_shader(nir_shader *shader) { } +static inline void nir_validate_shader(nir_shader *shader) { (void) shader; } #endif /* DEBUG */ void nir_calc_dominance_impl(nir_function_impl *impl); @@ -1596,14 +1616,18 @@ void nir_lower_alu_to_scalar(nir_shader *shader); void nir_lower_phis_to_scalar(nir_shader *shader); void nir_lower_samplers(nir_shader *shader, - struct gl_shader_program *shader_program, - struct gl_program *prog); + const struct gl_shader_program *shader_program, + gl_shader_stage stage); void nir_lower_system_values(nir_shader *shader); +void nir_lower_tex_projector(nir_shader *shader); +void nir_lower_idiv(nir_shader *shader); void nir_lower_atomics(nir_shader *shader); void nir_lower_to_source_mods(nir_shader *shader); +void nir_normalize_cubemap_coords(nir_shader *shader); + void nir_live_variables_impl(nir_function_impl *impl); bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b); @@ -1612,6 +1636,7 @@ void nir_convert_to_ssa(nir_shader *shader); void nir_convert_from_ssa(nir_shader *shader); bool nir_opt_algebraic(nir_shader *shader); +bool nir_opt_algebraic_late(nir_shader *shader); bool nir_opt_constant_folding(nir_shader *shader); bool nir_opt_global_to_local(nir_shader *shader); @@ -1631,6 +1656,8 @@ bool nir_opt_peephole_ffma(nir_shader *shader); bool nir_opt_remove_phis(nir_shader *shader); +void nir_sweep(nir_shader *shader); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/mesalib/src/glsl/nir/nir_algebraic.py b/mesalib/src/glsl/nir/nir_algebraic.py index afab1a008..bbf4f08ef 100644 --- a/mesalib/src/glsl/nir/nir_algebraic.py +++ b/mesalib/src/glsl/nir/nir_algebraic.py @@ -181,12 +181,23 @@ _algebraic_pass_template = mako.template.Template(""" #include "nir.h" #include "nir_search.h" +#ifndef NIR_OPT_ALGEBRAIC_STRUCT_DEFS +#define NIR_OPT_ALGEBRAIC_STRUCT_DEFS + struct transform { const nir_search_expression *search; const nir_search_value *replace; unsigned condition_offset; }; +struct opt_state { + void *mem_ctx; + bool progress; + const bool *condition_flags; +}; + +#endif + % for (opcode, xform_list) in xform_dict.iteritems(): % for xform in xform_list: ${xform.search.render()} @@ -200,12 +211,6 @@ static const struct transform ${pass_name}_${opcode}_xforms[] = { }; % endfor -struct opt_state { - void *mem_ctx; - bool progress; - const bool *condition_flags; -}; - static bool ${pass_name}_block(nir_block *block, void *void_state) { diff --git a/mesalib/src/glsl/nir/nir_builder.h b/mesalib/src/glsl/nir/nir_builder.h index 7c4f7fd96..d1419ee21 100644 --- a/mesalib/src/glsl/nir/nir_builder.h +++ b/mesalib/src/glsl/nir/nir_builder.h @@ -28,6 +28,9 @@ struct exec_list; typedef struct nir_builder { struct exec_list *cf_node_list; + nir_instr *before_instr; + nir_instr *after_instr; + nir_shader *shader; nir_function_impl *impl; } nir_builder; @@ -45,8 +48,75 @@ nir_builder_insert_after_cf_list(nir_builder *build, struct exec_list *cf_node_list) { build->cf_node_list = cf_node_list; + build->before_instr = NULL; + build->after_instr = NULL; +} + +static inline void +nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr) +{ + build->cf_node_list = NULL; + build->before_instr = before_instr; + build->after_instr = NULL; } +static inline void +nir_builder_insert_after_instr(nir_builder *build, nir_instr *after_instr) +{ + build->cf_node_list = NULL; + build->before_instr = NULL; + build->after_instr = after_instr; +} + +static inline void +nir_builder_instr_insert(nir_builder *build, nir_instr *instr) +{ + if (build->cf_node_list) { + nir_instr_insert_after_cf_list(build->cf_node_list, instr); + } else if (build->before_instr) { + nir_instr_insert_before(build->before_instr, instr); + } else { + assert(build->after_instr); + nir_instr_insert_after(build->after_instr, instr); + build->after_instr = instr; + } +} + +static inline nir_ssa_def * +nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value) +{ + nir_load_const_instr *load_const = + nir_load_const_instr_create(build->shader, num_components); + if (!load_const) + return NULL; + + load_const->value = value; + + nir_builder_instr_insert(build, &load_const->instr); + + return &load_const->def; +} + +static inline nir_ssa_def * +nir_imm_float(nir_builder *build, float x) +{ + nir_const_value v = { { .f = {x, 0, 0, 0} } }; + return nir_build_imm(build, 1, v); +} + +static inline nir_ssa_def * +nir_imm_vec4(nir_builder *build, float x, float y, float z, float w) +{ + nir_const_value v = { { .f = {x, y, z, w} } }; + return nir_build_imm(build, 4, v); +} + +static inline nir_ssa_def * +nir_imm_int(nir_builder *build, int x) +{ + nir_const_value v = { { .i = {x, 0, 0, 0} } }; + return nir_build_imm(build, 1, v); +} static inline nir_ssa_def * nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0, @@ -90,7 +160,7 @@ nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0, nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL); instr->dest.write_mask = (1 << num_components) - 1; - nir_instr_insert_after_cf_list(build->cf_node_list, &instr->instr); + nir_builder_instr_insert(build, &instr->instr); return &instr->dest.dest.ssa; } @@ -127,4 +197,67 @@ nir_##op(nir_builder *build, nir_ssa_def *src0, \ #include "nir_builder_opcodes.h" +/** + * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def. + */ +static inline nir_ssa_def * +nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components) +{ + nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov); + nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL); + mov->dest.write_mask = (1 << num_components) - 1; + mov->src[0] = src; + nir_builder_instr_insert(build, &mov->instr); + + return &mov->dest.dest.ssa; +} + +static inline nir_ssa_def * +nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components) +{ + nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov); + nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL); + mov->dest.write_mask = (1 << num_components) - 1; + mov->src[0] = src; + nir_builder_instr_insert(build, &mov->instr); + + return &mov->dest.dest.ssa; +} + +/** + * Construct an fmov or imov that reswizzles the source's components. + */ +static inline nir_ssa_def * +nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4], + unsigned num_components, bool use_fmov) +{ + nir_alu_src alu_src; + memset(&alu_src, 0, sizeof(alu_src)); + alu_src.src = nir_src_for_ssa(src); + for (int i = 0; i < 4; i++) + alu_src.swizzle[i] = swiz[i]; + + return use_fmov ? nir_fmov_alu(build, alu_src, num_components) : + nir_imov_alu(build, alu_src, num_components); +} + +/** + * Turns a nir_src into a nir_ssa_def * so it can be passed to + * nir_build_alu()-based builder calls. + */ +static inline nir_ssa_def * +nir_ssa_for_src(nir_builder *build, nir_src src, int num_components) +{ + if (src.is_ssa && src.ssa->num_components == num_components) + return src.ssa; + + nir_alu_src alu; + memset(&alu, 0, sizeof(alu)); + alu.src = src; + for (int j = 0; j < 4; j++) + alu.swizzle[j] = j; + + return nir_imov_alu(build, alu, num_components); +} + #endif /* NIR_BUILDER_H */ diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c index c3090fb06..184698abd 100644 --- a/mesalib/src/glsl/nir/nir_from_ssa.c +++ b/mesalib/src/glsl/nir/nir_from_ssa.c @@ -509,12 +509,13 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state) reg->num_components = def->num_components; reg->num_array_elems = 0; - /* This register comes from an SSA definition that was not part of a - * phi-web. Therefore, we know it has a single unique definition - * that dominates all of its uses. Therefore, we can copy the + /* This register comes from an SSA definition that is defined and not + * part of a phi-web. Therefore, we know it has a single unique + * definition that dominates all of its uses; we can copy the * parent_instr from the SSA def safely. */ - reg->parent_instr = def->parent_instr; + if (def->parent_instr->type != nir_instr_type_ssa_undef) + reg->parent_instr = def->parent_instr; _mesa_hash_table_insert(state->ssa_table, def, reg); return reg; diff --git a/mesalib/src/glsl/nir/nir_lower_idiv.c b/mesalib/src/glsl/nir/nir_lower_idiv.c new file mode 100644 index 000000000..7b6803207 --- /dev/null +++ b/mesalib/src/glsl/nir/nir_lower_idiv.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2015 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Rob Clark <robclark@freedesktop.org> + */ + +#include "nir.h" +#include "nir_builder.h" + +/* Lowers idiv/udiv/umod + * Based on NV50LegalizeSSA::handleDIV() + * + * Note that this is probably not enough precision for compute shaders. + * Perhaps we want a second higher precision (looping) version of this? + * Or perhaps we assume if you can do compute shaders you can also + * branch out to a pre-optimized shader library routine.. + */ + +static void +convert_instr(nir_builder *bld, nir_alu_instr *alu) +{ + nir_ssa_def *numer, *denom, *af, *bf, *a, *b, *q, *r; + nir_op op = alu->op; + bool is_signed; + + if ((op != nir_op_idiv) && + (op != nir_op_udiv) && + (op != nir_op_umod)) + return; + + is_signed = (op == nir_op_idiv); + + nir_builder_insert_before_instr(bld, &alu->instr); + + numer = nir_ssa_for_src(bld, alu->src[0].src, + nir_ssa_alu_instr_src_components(alu, 0)); + denom = nir_ssa_for_src(bld, alu->src[1].src, + nir_ssa_alu_instr_src_components(alu, 1)); + + if (is_signed) { + af = nir_i2f(bld, numer); + bf = nir_i2f(bld, denom); + af = nir_fabs(bld, af); + bf = nir_fabs(bld, bf); + a = nir_iabs(bld, numer); + b = nir_iabs(bld, denom); + } else { + af = nir_u2f(bld, numer); + bf = nir_u2f(bld, denom); + a = numer; + b = denom; + } + + /* get first result: */ + bf = nir_frcp(bld, bf); + bf = nir_isub(bld, bf, nir_imm_int(bld, 2)); /* yes, really */ + q = nir_fmul(bld, af, bf); + + if (is_signed) { + q = nir_f2i(bld, q); + } else { + q = nir_f2u(bld, q); + } + + /* get error of first result: */ + r = nir_imul(bld, q, b); + r = nir_isub(bld, a, r); + r = nir_u2f(bld, r); + r = nir_fmul(bld, r, bf); + r = nir_f2u(bld, r); + + /* add quotients: */ + q = nir_iadd(bld, q, r); + + /* correction: if modulus >= divisor, add 1 */ + r = nir_imul(bld, q, b); + r = nir_isub(bld, a, r); + + r = nir_ige(bld, r, b); + r = nir_b2i(bld, r); + + q = nir_iadd(bld, q, r); + if (is_signed) { + /* fix the sign: */ + r = nir_ixor(bld, numer, denom); + r = nir_ushr(bld, r, nir_imm_int(bld, 31)); + r = nir_i2b(bld, r); + b = nir_ineg(bld, q); + q = nir_bcsel(bld, r, b, q); + } + + if (op == nir_op_umod) { + /* division result in q */ + r = nir_imul(bld, q, b); + q = nir_isub(bld, a, r); + } + + assert(alu->dest.dest.is_ssa); + nir_ssa_def_rewrite_uses(&alu->dest.dest.ssa, + nir_src_for_ssa(q), + ralloc_parent(alu)); +} + +static bool +convert_block(nir_block *block, void *state) +{ + nir_builder *b = state; + + nir_foreach_instr_safe(block, instr) { + if (instr->type == nir_instr_type_alu) + convert_instr(b, nir_instr_as_alu(instr)); + } + + return true; +} + +static void +convert_impl(nir_function_impl *impl) +{ + nir_builder b; + nir_builder_init(&b, impl); + + nir_foreach_block(impl, convert_block, &b); + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); +} + +void +nir_lower_idiv(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) { + if (overload->impl) + convert_impl(overload->impl); + } +} diff --git a/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c b/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c index 7cd93ea0a..4bdb80072 100644 --- a/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c +++ b/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c @@ -223,7 +223,7 @@ lower_phis_to_scalar_block(nir_block *block, void *void_state) else nir_instr_insert_after_block(src->pred, &mov->instr); - nir_phi_src *new_src = ralloc(state->mem_ctx, nir_phi_src); + nir_phi_src *new_src = ralloc(new_phi, nir_phi_src); new_src->pred = src->pred; new_src->src = nir_src_for_ssa(&mov->dest.dest.ssa); diff --git a/mesalib/src/glsl/nir/nir_lower_samplers.cpp b/mesalib/src/glsl/nir/nir_lower_samplers.cpp index 3015dbd09..cf8ab8325 100644 --- a/mesalib/src/glsl/nir/nir_lower_samplers.cpp +++ b/mesalib/src/glsl/nir/nir_lower_samplers.cpp @@ -36,33 +36,26 @@ extern "C" { } static unsigned -get_sampler_index(struct gl_shader_program *shader_program, const char *name, - const struct gl_program *prog) +get_sampler_index(const struct gl_shader_program *shader_program, + gl_shader_stage stage, const char *name) { - GLuint shader = _mesa_program_enum_to_shader_stage(prog->Target); - unsigned location; if (!shader_program->UniformHash->get(location, name)) { - linker_error(shader_program, - "failed to find sampler named %s.\n", name); + assert(!"failed to find sampler"); return 0; } - if (!shader_program->UniformStorage[location].sampler[shader].active) { - assert(0 && "cannot return a sampler"); - linker_error(shader_program, - "cannot return a sampler named %s, because it is not " - "used in this shader stage. This is a driver bug.\n", - name); + if (!shader_program->UniformStorage[location].sampler[stage].active) { + assert(!"cannot return a sampler"); return 0; } - return shader_program->UniformStorage[location].sampler[shader].index; + return shader_program->UniformStorage[location].sampler[stage].index; } static void -lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program, - const struct gl_program *prog, void *mem_ctx) +lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program, + gl_shader_stage stage, void *mem_ctx) { if (instr->sampler == NULL) return; @@ -90,7 +83,7 @@ lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program, ralloc_asprintf_append(&name, "[%u]", deref_array->base_offset); break; case nir_deref_array_type_indirect: { - instr->src = reralloc(mem_ctx, instr->src, nir_tex_src, + instr->src = reralloc(instr, instr->src, nir_tex_src, instr->num_srcs + 1); memset(&instr->src[instr->num_srcs], 0, sizeof *instr->src); instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset; @@ -133,15 +126,15 @@ lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program, } } - instr->sampler_index += get_sampler_index(shader_program, name, prog); + instr->sampler_index += get_sampler_index(shader_program, stage, name); instr->sampler = NULL; } typedef struct { void *mem_ctx; - struct gl_shader_program *shader_program; - struct gl_program *prog; + const struct gl_shader_program *shader_program; + gl_shader_stage stage; } lower_state; static bool @@ -152,7 +145,7 @@ lower_block_cb(nir_block *block, void *_state) nir_foreach_instr(block, instr) { if (instr->type == nir_instr_type_tex) { nir_tex_instr *tex_instr = nir_instr_as_tex(instr); - lower_sampler(tex_instr, state->shader_program, state->prog, + lower_sampler(tex_instr, state->shader_program, state->stage, state->mem_ctx); } } @@ -161,24 +154,24 @@ lower_block_cb(nir_block *block, void *_state) } static void -lower_impl(nir_function_impl *impl, struct gl_shader_program *shader_program, - struct gl_program *prog) +lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_program, + gl_shader_stage stage) { lower_state state; state.mem_ctx = ralloc_parent(impl); state.shader_program = shader_program; - state.prog = prog; + state.stage = stage; nir_foreach_block(impl, lower_block_cb, &state); } extern "C" void -nir_lower_samplers(nir_shader *shader, struct gl_shader_program *shader_program, - struct gl_program *prog) +nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_program, + gl_shader_stage stage) { nir_foreach_overload(shader, overload) { if (overload->impl) - lower_impl(overload->impl, shader_program, prog); + lower_impl(overload->impl, shader_program, stage); } } diff --git a/mesalib/src/glsl/nir/nir_lower_tex_projector.c b/mesalib/src/glsl/nir/nir_lower_tex_projector.c new file mode 100644 index 000000000..6b0e9c340 --- /dev/null +++ b/mesalib/src/glsl/nir/nir_lower_tex_projector.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * This lowering pass converts the coordinate division for texture projection + * to be done in ALU instructions instead of asking the texture operation to + * do so. + */ + +#include "nir.h" +#include "nir_builder.h" + +static nir_ssa_def * +channel(nir_builder *b, nir_ssa_def *def, int c) +{ + return nir_swizzle(b, def, (unsigned[4]){c, c, c, c}, 1, false); +} + +static bool +nir_lower_tex_projector_block(nir_block *block, void *void_state) +{ + nir_builder *b = void_state; + + nir_foreach_instr_safe(block, instr) { + if (instr->type != nir_instr_type_tex) + continue; + + nir_tex_instr *tex = nir_instr_as_tex(instr); + nir_builder_insert_before_instr(b, &tex->instr); + + /* Find the projector in the srcs list, if present. */ + int proj_index; + for (proj_index = 0; proj_index < tex->num_srcs; proj_index++) { + if (tex->src[proj_index].src_type == nir_tex_src_projector) + break; + } + if (proj_index == tex->num_srcs) + continue; + nir_ssa_def *inv_proj = + nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1)); + + /* Walk through the sources projecting the arguments. */ + for (int i = 0; i < tex->num_srcs; i++) { + switch (tex->src[i].src_type) { + case nir_tex_src_coord: + case nir_tex_src_comparitor: + break; + default: + continue; + } + nir_ssa_def *unprojected = + nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i)); + nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj); + + /* Array indices don't get projected, so make an new vector with the + * coordinate's array index untouched. + */ + if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) { + switch (tex->coord_components) { + case 4: + projected = nir_vec4(b, + channel(b, projected, 0), + channel(b, projected, 1), + channel(b, projected, 2), + channel(b, unprojected, 3)); + break; + case 3: + projected = nir_vec3(b, + channel(b, projected, 0), + channel(b, projected, 1), + channel(b, unprojected, 2)); + break; + case 2: + projected = nir_vec2(b, + channel(b, projected, 0), + channel(b, unprojected, 1)); + break; + default: + unreachable("bad texture coord count for array"); + break; + } + } + + nir_instr_rewrite_src(&tex->instr, + &tex->src[i].src, + nir_src_for_ssa(projected)); + } + + /* Now move the later tex sources down the array so that the projector + * disappears. + */ + nir_src dead; + memset(&dead, 0, sizeof dead); + nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src, dead); + memmove(&tex->src[proj_index], + &tex->src[proj_index + 1], + (tex->num_srcs - proj_index) * sizeof(*tex->src)); + tex->num_srcs--; + } + + return true; +} + +static void +nir_lower_tex_projector_impl(nir_function_impl *impl) +{ + nir_builder b; + nir_builder_init(&b, impl); + + nir_foreach_block(impl, nir_lower_tex_projector_block, &b); + + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); +} + +void +nir_lower_tex_projector(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_lower_tex_projector_impl(overload->impl); + } +} diff --git a/mesalib/src/glsl/nir/nir_lower_var_copies.c b/mesalib/src/glsl/nir/nir_lower_var_copies.c index 85ebb281c..58389a7c7 100644 --- a/mesalib/src/glsl/nir/nir_lower_var_copies.c +++ b/mesalib/src/glsl/nir/nir_lower_var_copies.c @@ -148,13 +148,10 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr, unsigned num_components = glsl_get_vector_elements(src_tail->type); - nir_deref *src_deref = nir_copy_deref(mem_ctx, &src_head->deref); - nir_deref *dest_deref = nir_copy_deref(mem_ctx, &dest_head->deref); - nir_intrinsic_instr *load = nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_load_var); load->num_components = num_components; - load->variables[0] = nir_deref_as_var(src_deref); + load->variables[0] = nir_deref_as_var(nir_copy_deref(load, &src_head->deref)); nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL); nir_instr_insert_before(©_instr->instr, &load->instr); @@ -162,7 +159,8 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr, nir_intrinsic_instr *store = nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_store_var); store->num_components = num_components; - store->variables[0] = nir_deref_as_var(dest_deref); + store->variables[0] = nir_deref_as_var(nir_copy_deref(store, &dest_head->deref)); + store->src[0].is_ssa = true; store->src[0].ssa = &load->dest.ssa; diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c index 86e6ab416..2ca74d71b 100644 --- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c @@ -642,7 +642,7 @@ add_phi_sources(nir_block *block, nir_block *pred, struct deref_node *node = entry->data; - nir_phi_src *src = ralloc(state->mem_ctx, nir_phi_src); + nir_phi_src *src = ralloc(phi, nir_phi_src); src->pred = pred; src->src.is_ssa = true; src->src.ssa = get_ssa_def_for_block(node, pred, state); diff --git a/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c b/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c new file mode 100644 index 000000000..0da8447ac --- /dev/null +++ b/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Jason Ekstrand <jason@jlekstrand.net> + */ + +#include "nir.h" +#include "nir_builder.h" + +/** + * This file implements a NIR lowering pass to perform the normalization of + * the cubemap coordinates to have the largest magnitude component be -1.0 + * or 1.0. This is based on the old GLSL IR based pass by Eric. + */ + +static nir_ssa_def * +channel(nir_builder *b, nir_ssa_def *def, int c) +{ + return nir_swizzle(b, def, (unsigned[4]){c, c, c, c}, 1, false); +} + +static bool +normalize_cubemap_coords_block(nir_block *block, void *void_state) +{ + nir_builder *b = void_state; + + nir_foreach_instr(block, instr) { + if (instr->type != nir_instr_type_tex) + continue; + + nir_tex_instr *tex = nir_instr_as_tex(instr); + if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE) + continue; + + nir_builder_insert_before_instr(b, &tex->instr); + + for (unsigned i = 0; i < tex->num_srcs; i++) { + if (tex->src[i].src_type != nir_tex_src_coord) + continue; + + nir_ssa_def *orig_coord = + nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i)); + assert(orig_coord->num_components >= 3); + + nir_ssa_def *abs = nir_fabs(b, orig_coord); + nir_ssa_def *norm = nir_fmax(b, channel(b, abs, 0), + nir_fmax(b, channel(b, abs, 1), + channel(b, abs, 2))); + + nir_ssa_def *normalized = nir_fmul(b, orig_coord, nir_frcp(b, norm)); + + /* Array indices don't have to be normalized, so make a new vector + * with the coordinate's array index untouched. + */ + if (tex->coord_components == 4) { + normalized = nir_vec4(b, + channel(b, normalized, 0), + channel(b, normalized, 1), + channel(b, normalized, 2), + channel(b, orig_coord, 3)); + } + + nir_instr_rewrite_src(&tex->instr, + &tex->src[i].src, + nir_src_for_ssa(normalized)); + } + } + + return true; +} + +static void +normalize_cubemap_coords_impl(nir_function_impl *impl) +{ + nir_builder b; + nir_builder_init(&b, impl); + + nir_foreach_block(impl, normalize_cubemap_coords_block, &b); + + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); +} + +void +nir_normalize_cubemap_coords(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) + if (overload->impl) + normalize_cubemap_coords_impl(overload->impl); +} diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py index 062cd628b..264806f5d 100644 --- a/mesalib/src/glsl/nir/nir_opcodes.py +++ b/mesalib/src/glsl/nir/nir_opcodes.py @@ -161,12 +161,12 @@ unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion. unop_convert("f2u", tfloat, tunsigned, "src0") # Float-to-unsigned conversion unop_convert("i2f", tint, tfloat, "src0") # Integer-to-float conversion. # Float-to-boolean conversion -unop_convert("f2b", tfloat, tbool, "src0 == 0.0f") +unop_convert("f2b", tfloat, tbool, "src0 != 0.0f") # Boolean-to-float conversion unop_convert("b2f", tbool, tfloat, "src0 ? 1.0f : 0.0f") # Int-to-boolean conversion -unop_convert("i2b", tint, tbool, "src0 == 0") -unop_convert("b2i", tbool, tint, "src0 ? 0 : -1") # Boolean-to-int conversion +unop_convert("i2b", tint, tbool, "src0 != 0") +unop_convert("b2i", tbool, tint, "src0 ? 1 : 0") # Boolean-to-int conversion unop_convert("u2f", tunsigned, tfloat, "src0") #Unsigned-to-float conversion. unop_reduce("bany", 1, tbool, tbool, "{src}", "{src0} || {src1}", "{src}") @@ -191,8 +191,6 @@ unop("fround_even", tfloat, "_mesa_roundevenf(src0)") unop("fsin", tfloat, "sinf(src0)") unop("fcos", tfloat, "cosf(src0)") -unop("fsin_reduced", tfloat, "sinf(src0)") -unop("fcos_reduced", tfloat, "cosf(src0)") # Partial derivatives. diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py index ef855aa77..cdb19241c 100644 --- a/mesalib/src/glsl/nir/nir_opt_algebraic.py +++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py @@ -75,6 +75,9 @@ optimizations = [ (('flrp', a, b, 1.0), b), (('flrp', a, a, b), a), (('flrp', 0.0, a, b), ('fmul', a, b)), + (('flrp', a, b, c), ('fadd', ('fmul', c, ('fsub', b, a)), a), 'options->lower_flrp'), + (('fadd', ('fmul', a, ('fadd', 1.0, ('fneg', c))), ('fmul', b, c)), ('flrp', a, b, c), '!options->lower_flrp'), + (('fadd', a, ('fmul', c, ('fadd', b, ('fneg', a)))), ('flrp', a, b, c), '!options->lower_flrp'), (('ffma', a, b, c), ('fadd', ('fmul', a, b), c), 'options->lower_ffma'), (('fadd', ('fmul', a, b), c), ('ffma', a, b, c), '!options->lower_ffma'), # Comparison simplifications @@ -82,10 +85,6 @@ optimizations = [ (('inot', ('fge', a, b)), ('flt', a, b)), (('inot', ('ilt', a, b)), ('ige', a, b)), (('inot', ('ige', a, b)), ('ilt', a, b)), - (('flt', ('fadd', a, b), 0.0), ('flt', a, ('fneg', b))), - (('fge', ('fadd', a, b), 0.0), ('fge', a, ('fneg', b))), - (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))), - (('fne', ('fadd', a, b), 0.0), ('fne', a, ('fneg', b))), (('fge', ('fneg', ('fabs', a)), 0.0), ('feq', a, 0.0)), (('bcsel', ('flt', a, b), a, b), ('fmin', a, b)), (('bcsel', ('flt', a, b), b, a), ('fmax', a, b)), @@ -95,6 +94,18 @@ optimizations = [ (('fsat', a), ('fmin', ('fmax', a, 0.0), 1.0), 'options->lower_fsat'), (('fsat', ('fsat', a)), ('fsat', a)), (('fmin', ('fmax', ('fmin', ('fmax', a, 0.0), 1.0), 0.0), 1.0), ('fmin', ('fmax', a, 0.0), 1.0)), + (('ior', ('flt', a, b), ('flt', a, c)), ('flt', a, ('fmax', b, c))), + (('ior', ('fge', a, b), ('fge', a, c)), ('fge', a, ('fmin', b, c))), + (('slt', a, b), ('b2f', ('flt', a, b)), 'options->lower_scmp'), + (('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'), + (('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'), + (('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'), + # Emulating booleans + (('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))), + (('fsat', ('fadd', ('b2f', a), ('b2f', b))), ('b2f', ('ior', a, b))), + (('iand', 'a@bool', 1.0), ('b2f', a)), + (('flt', ('fneg', ('b2f', a)), 0), a), # Generated by TGSI KILL_IF. + (('flt', ('fsub', 0.0, ('b2f', a)), 0), a), # Generated by TGSI KILL_IF. # Comparison with the same args. Note that these are not done for # the float versions because NaN always returns false on float # inequalities. @@ -122,7 +133,7 @@ optimizations = [ (('ishr', 0, a), 0), (('ishr', a, 0), a), (('ushr', 0, a), 0), - (('ushr', a, 0), 0), + (('ushr', a, 0), a), # Exponential/logarithmic identities (('fexp2', ('flog2', a)), a), # 2^lg2(a) = a (('fexp', ('flog', a)), a), # e^ln(a) = a @@ -134,6 +145,26 @@ optimizations = [ (('fpow', a, 1.0), a), (('fpow', a, 2.0), ('fmul', a, a)), (('fpow', 2.0, a), ('fexp2', a)), + (('fsqrt', ('fexp2', a)), ('fexp2', ('fmul', 0.5, a))), + (('fsqrt', ('fexp', a)), ('fexp', ('fmul', 0.5, a))), + (('frcp', ('fexp2', a)), ('fexp2', ('fneg', a))), + (('frcp', ('fexp', a)), ('fexp', ('fneg', a))), + (('frsq', ('fexp2', a)), ('fexp2', ('fmul', -0.5, a))), + (('frsq', ('fexp', a)), ('fexp', ('fmul', -0.5, a))), + (('flog2', ('fsqrt', a)), ('fmul', 0.5, ('flog2', a))), + (('flog', ('fsqrt', a)), ('fmul', 0.5, ('flog', a))), + (('flog2', ('frcp', a)), ('fneg', ('flog2', a))), + (('flog', ('frcp', a)), ('fneg', ('flog', a))), + (('flog2', ('frsq', a)), ('fmul', -0.5, ('flog2', a))), + (('flog', ('frsq', a)), ('fmul', -0.5, ('flog', a))), + (('flog2', ('fpow', a, b)), ('fmul', b, ('flog2', a))), + (('flog', ('fpow', a, b)), ('fmul', b, ('flog', a))), + (('fadd', ('flog2', a), ('flog2', b)), ('flog2', ('fmul', a, b))), + (('fadd', ('flog', a), ('flog', b)), ('flog', ('fmul', a, b))), + (('fadd', ('flog2', a), ('fneg', ('flog2', b))), ('flog2', ('fdiv', a, b))), + (('fadd', ('flog', a), ('fneg', ('flog', b))), ('flog', ('fdiv', a, b))), + (('fmul', ('fexp2', a), ('fexp2', b)), ('fexp2', ('fadd', a, b))), + (('fmul', ('fexp', a), ('fexp', b)), ('fexp', ('fadd', a, b))), # Division and reciprocal (('fdiv', 1.0, a), ('frcp', a)), (('frcp', ('frcp', a)), a), @@ -154,18 +185,21 @@ optimizations = [ (('bcsel', a, b, b), b), (('fcsel', a, b, b), b), + # Conversions + (('f2i', ('ftrunc', a)), ('f2i', a)), + (('f2u', ('ftrunc', a)), ('f2u', a)), + # Subtracts (('fsub', a, ('fsub', 0.0, b)), ('fadd', a, b)), (('isub', a, ('isub', 0, b)), ('iadd', a, b)), + (('fsub', a, b), ('fadd', a, ('fneg', b)), 'options->lower_sub'), + (('isub', a, b), ('iadd', a, ('ineg', b)), 'options->lower_sub'), (('fneg', a), ('fsub', 0.0, a), 'options->lower_negate'), (('ineg', a), ('isub', 0, a), 'options->lower_negate'), (('fadd', a, ('fsub', 0.0, b)), ('fsub', a, b)), (('iadd', a, ('isub', 0, b)), ('isub', a, b)), (('fabs', ('fsub', 0.0, a)), ('fabs', a)), (('iabs', ('isub', 0, a)), ('iabs', a)), - -# This one may not be exact - (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))), ] # Add optimizations to handle the case where the result of a ternary is @@ -189,4 +223,17 @@ for op in ['flt', 'fge', 'feq', 'fne', ('bcsel', 'a', (op, 'd', 'b'), (op, 'd', 'c'))), ] +# This section contains "late" optimizations that should be run after the +# regular optimizations have finished. Optimizations should go here if +# they help code generation but do not necessarily produce code that is +# more easily optimizable. +late_optimizations = [ + (('flt', ('fadd', a, b), 0.0), ('flt', a, ('fneg', b))), + (('fge', ('fadd', a, b), 0.0), ('fge', a, ('fneg', b))), + (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))), + (('fne', ('fadd', a, b), 0.0), ('fne', a, ('fneg', b))), +] + print nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render() +print nir_algebraic.AlgebraicPass("nir_opt_algebraic_late", + late_optimizations).render() diff --git a/mesalib/src/glsl/nir/nir_opt_cse.c b/mesalib/src/glsl/nir/nir_opt_cse.c index 9b383202d..553906e12 100644 --- a/mesalib/src/glsl/nir/nir_opt_cse.c +++ b/mesalib/src/glsl/nir/nir_opt_cse.c @@ -37,20 +37,19 @@ struct cse_state { }; static bool -nir_alu_srcs_equal(nir_alu_src src1, nir_alu_src src2, uint8_t read_mask) +nir_alu_srcs_equal(nir_alu_instr *alu1, nir_alu_instr *alu2, unsigned src1, + unsigned src2) { - if (src1.abs != src2.abs || src1.negate != src2.negate) + if (alu1->src[src1].abs != alu2->src[src2].abs || + alu1->src[src1].negate != alu2->src[src2].negate) return false; - for (int i = 0; i < 4; ++i) { - if (!(read_mask & (1 << i))) - continue; - - if (src1.swizzle[i] != src2.swizzle[i]) + for (unsigned i = 0; i < nir_ssa_alu_instr_src_components(alu1, src1); i++) { + if (alu1->src[src1].swizzle[i] != alu2->src[src2].swizzle[i]) return false; } - return nir_srcs_equal(src1.src, src2.src); + return nir_srcs_equal(alu1->src[src1].src, alu2->src[src2].src); } static bool @@ -73,10 +72,17 @@ nir_instrs_equal(nir_instr *instr1, nir_instr *instr2) if (alu1->dest.dest.ssa.num_components != alu2->dest.dest.ssa.num_components) return false; - for (unsigned i = 0; i < nir_op_infos[alu1->op].num_inputs; i++) { - if (!nir_alu_srcs_equal(alu1->src[i], alu2->src[i], - (1 << alu1->dest.dest.ssa.num_components) - 1)) - return false; + if (nir_op_infos[alu1->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) { + assert(nir_op_infos[alu1->op].num_inputs == 2); + return (nir_alu_srcs_equal(alu1, alu2, 0, 0) && + nir_alu_srcs_equal(alu1, alu2, 1, 1)) || + (nir_alu_srcs_equal(alu1, alu2, 0, 1) && + nir_alu_srcs_equal(alu1, alu2, 1, 0)); + } else { + for (unsigned i = 0; i < nir_op_infos[alu1->op].num_inputs; i++) { + if (!nir_alu_srcs_equal(alu1, alu2, i, i)) + return false; + } } return true; } @@ -154,12 +160,14 @@ nir_instrs_equal(nir_instr *instr1, nir_instr *instr2) static bool src_is_ssa(nir_src *src, void *data) { + (void) data; return src->is_ssa; } static bool dest_is_ssa(nir_dest *dest, void *data) { + (void) data; return dest->is_ssa; } diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c new file mode 100644 index 000000000..9d5646fe6 --- /dev/null +++ b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c @@ -0,0 +1,261 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Jason Ekstrand (jason@jlekstrand.net) + * + */ + +#include "nir.h" + +/* + * Implements a small peephole optimization that looks for a multiply that + * is only ever used in an add and replaces both with an fma. + */ + +struct peephole_ffma_state { + void *mem_ctx; + nir_function_impl *impl; + bool progress; +}; + +static inline bool +are_all_uses_fadd(nir_ssa_def *def) +{ + if (def->if_uses->entries > 0) + return false; + + struct set_entry *use_iter; + set_foreach(def->uses, use_iter) { + nir_instr *use_instr = (nir_instr *)use_iter->key; + + if (use_instr->type != nir_instr_type_alu) + return false; + + nir_alu_instr *use_alu = nir_instr_as_alu(use_instr); + switch (use_alu->op) { + case nir_op_fadd: + break; /* This one's ok */ + + case nir_op_imov: + case nir_op_fmov: + case nir_op_fneg: + case nir_op_fabs: + assert(use_alu->dest.dest.is_ssa); + if (!are_all_uses_fadd(&use_alu->dest.dest.ssa)) + return false; + break; + + default: + return false; + } + } + + return true; +} + +static nir_alu_instr * +get_mul_for_src(nir_alu_src *src, uint8_t swizzle[4], bool *negate, bool *abs) +{ + assert(src->src.is_ssa && !src->abs && !src->negate); + + nir_instr *instr = src->src.ssa->parent_instr; + if (instr->type != nir_instr_type_alu) + return NULL; + + nir_alu_instr *alu = nir_instr_as_alu(instr); + switch (alu->op) { + case nir_op_imov: + case nir_op_fmov: + alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs); + break; + + case nir_op_fneg: + alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs); + *negate = !*negate; + break; + + case nir_op_fabs: + alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs); + *negate = false; + *abs = true; + break; + + case nir_op_fmul: + /* Only absorb a fmul into a ffma if the fmul is is only used in fadd + * operations. This prevents us from being too aggressive with our + * fusing which can actually lead to more instructions. + */ + if (!are_all_uses_fadd(&alu->dest.dest.ssa)) + return NULL; + break; + + default: + return NULL; + } + + if (!alu) + return NULL; + + for (unsigned i = 0; i < 4; i++) { + if (!(alu->dest.write_mask & (1 << i))) + break; + + swizzle[i] = swizzle[src->swizzle[i]]; + } + + return alu; +} + +static bool +nir_opt_peephole_ffma_block(nir_block *block, void *void_state) +{ + struct peephole_ffma_state *state = void_state; + + nir_foreach_instr_safe(block, instr) { + if (instr->type != nir_instr_type_alu) + continue; + + nir_alu_instr *add = nir_instr_as_alu(instr); + if (add->op != nir_op_fadd) + continue; + + /* TODO: Maybe bail if this expression is considered "precise"? */ + + assert(add->src[0].src.is_ssa && add->src[1].src.is_ssa); + + /* This, is the case a + a. We would rather handle this with an + * algebraic reduction than fuse it. Also, we want to only fuse + * things where the multiply is used only once and, in this case, + * it would be used twice by the same instruction. + */ + if (add->src[0].src.ssa == add->src[1].src.ssa) + continue; + + nir_alu_instr *mul; + uint8_t add_mul_src, swizzle[4]; + bool negate, abs; + for (add_mul_src = 0; add_mul_src < 2; add_mul_src++) { + for (unsigned i = 0; i < 4; i++) + swizzle[i] = i; + + negate = false; + abs = false; + + mul = get_mul_for_src(&add->src[add_mul_src], swizzle, &negate, &abs); + + if (mul != NULL) + break; + } + + if (mul == NULL) + continue; + + nir_ssa_def *mul_src[2]; + mul_src[0] = mul->src[0].src.ssa; + mul_src[1] = mul->src[1].src.ssa; + + if (abs) { + for (unsigned i = 0; i < 2; i++) { + nir_alu_instr *abs = nir_alu_instr_create(state->mem_ctx, + nir_op_fabs); + abs->src[0].src = nir_src_for_ssa(mul_src[i]); + nir_ssa_dest_init(&abs->instr, &abs->dest.dest, + mul_src[i]->num_components, NULL); + abs->dest.write_mask = (1 << mul_src[i]->num_components) - 1; + nir_instr_insert_before(&add->instr, &abs->instr); + mul_src[i] = &abs->dest.dest.ssa; + } + } + + if (negate) { + nir_alu_instr *neg = nir_alu_instr_create(state->mem_ctx, + nir_op_fneg); + neg->src[0].src = nir_src_for_ssa(mul_src[0]); + nir_ssa_dest_init(&neg->instr, &neg->dest.dest, + mul_src[0]->num_components, NULL); + neg->dest.write_mask = (1 << mul_src[0]->num_components) - 1; + nir_instr_insert_before(&add->instr, &neg->instr); + mul_src[0] = &neg->dest.dest.ssa; + } + + nir_alu_instr *ffma = nir_alu_instr_create(state->mem_ctx, nir_op_ffma); + ffma->dest.saturate = add->dest.saturate; + ffma->dest.write_mask = add->dest.write_mask; + + for (unsigned i = 0; i < 2; i++) { + ffma->src[i].src = nir_src_for_ssa(mul_src[i]); + for (unsigned j = 0; j < add->dest.dest.ssa.num_components; j++) + ffma->src[i].swizzle[j] = mul->src[i].swizzle[swizzle[j]]; + } + nir_alu_src_copy(&ffma->src[2], &add->src[1 - add_mul_src], + state->mem_ctx); + + assert(add->dest.dest.is_ssa); + + nir_ssa_dest_init(&ffma->instr, &ffma->dest.dest, + add->dest.dest.ssa.num_components, + add->dest.dest.ssa.name); + nir_ssa_def_rewrite_uses(&add->dest.dest.ssa, + nir_src_for_ssa(&ffma->dest.dest.ssa), + state->mem_ctx); + + nir_instr_insert_before(&add->instr, &ffma->instr); + assert(add->dest.dest.ssa.uses->entries == 0); + nir_instr_remove(&add->instr); + + state->progress = true; + } + + return true; +} + +static bool +nir_opt_peephole_ffma_impl(nir_function_impl *impl) +{ + struct peephole_ffma_state state; + + state.mem_ctx = ralloc_parent(impl); + state.impl = impl; + state.progress = false; + + nir_foreach_block(impl, nir_opt_peephole_ffma_block, &state); + + if (state.progress) + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); + + return state.progress; +} + +bool +nir_opt_peephole_ffma(nir_shader *shader) +{ + bool progress = false; + + nir_foreach_overload(shader, overload) { + if (overload->impl) + progress |= nir_opt_peephole_ffma_impl(overload->impl); + } + + return progress; +} diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c index b89451b09..f400cfd66 100644 --- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c +++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c @@ -84,7 +84,9 @@ block_check_for_allowed_instrs(nir_block *block) case nir_instr_type_alu: { /* It must be a move operation */ nir_alu_instr *mov = nir_instr_as_alu(instr); - if (mov->op != nir_op_fmov && mov->op != nir_op_imov) + if (mov->op != nir_op_fmov && mov->op != nir_op_imov && + mov->op != nir_op_fneg && mov->op != nir_op_ineg && + mov->op != nir_op_fabs && mov->op != nir_op_iabs) return false; /* Can't handle saturate */ diff --git a/mesalib/src/glsl/nir/nir_print.c b/mesalib/src/glsl/nir/nir_print.c index fa11a312e..fb8c9344c 100644 --- a/mesalib/src/glsl/nir/nir_print.c +++ b/mesalib/src/glsl/nir/nir_print.c @@ -137,25 +137,37 @@ print_dest(nir_dest *dest, FILE *fp) } static void -print_alu_src(nir_alu_src *src, FILE *fp) +print_alu_src(nir_alu_instr *instr, unsigned src, FILE *fp) { - if (src->negate) + if (instr->src[src].negate) fprintf(fp, "-"); - if (src->abs) + if (instr->src[src].abs) fprintf(fp, "abs("); - print_src(&src->src, fp); + print_src(&instr->src[src].src, fp); - if (src->swizzle[0] != 0 || - src->swizzle[1] != 1 || - src->swizzle[2] != 2 || - src->swizzle[3] != 3) { + bool print_swizzle = false; + for (unsigned i = 0; i < 4; i++) { + if (!nir_alu_instr_channel_used(instr, src, i)) + continue; + + if (instr->src[src].swizzle[i] != i) { + print_swizzle = true; + break; + } + } + + if (print_swizzle) { fprintf(fp, "."); - for (unsigned i = 0; i < 4; i++) - fprintf(fp, "%c", "xyzw"[src->swizzle[i]]); + for (unsigned i = 0; i < 4; i++) { + if (!nir_alu_instr_channel_used(instr, src, i)) + continue; + + fprintf(fp, "%c", "xyzw"[instr->src[src].swizzle[i]]); + } } - if (src->abs) + if (instr->src[src].abs) fprintf(fp, ")"); } @@ -189,7 +201,7 @@ print_alu_instr(nir_alu_instr *instr, FILE *fp) if (i != 0) fprintf(fp, ", "); - print_alu_src(&instr->src[i], fp); + print_alu_src(instr, i, fp); } } diff --git a/mesalib/src/glsl/nir/nir_remove_dead_variables.c b/mesalib/src/glsl/nir/nir_remove_dead_variables.c index e7f8aeacb..4417e2a48 100644 --- a/mesalib/src/glsl/nir/nir_remove_dead_variables.c +++ b/mesalib/src/glsl/nir/nir_remove_dead_variables.c @@ -98,22 +98,14 @@ add_var_use_shader(nir_shader *shader, struct set *live) } static void -remove_dead_local_vars(nir_function_impl *impl, struct set *live) +remove_dead_vars(struct exec_list *var_list, struct set *live) { - foreach_list_typed_safe(nir_variable, var, node, &impl->locals) { + foreach_list_typed_safe(nir_variable, var, node, var_list) { struct set_entry *entry = _mesa_set_search(live, var); - if (entry == NULL) - exec_node_remove(&var->node); - } -} - -static void -remove_dead_global_vars(nir_shader *shader, struct set *live) -{ - foreach_list_typed_safe(nir_variable, var, node, &shader->globals) { - struct set_entry *entry = _mesa_set_search(live, var); - if (entry == NULL) + if (entry == NULL) { exec_node_remove(&var->node); + ralloc_free(var); + } } } @@ -125,11 +117,11 @@ nir_remove_dead_variables(nir_shader *shader) add_var_use_shader(shader, live); - remove_dead_global_vars(shader, live); + remove_dead_vars(&shader->globals, live); nir_foreach_overload(shader, overload) { if (overload->impl) - remove_dead_local_vars(overload->impl, live); + remove_dead_vars(&overload->impl->locals, live); } _mesa_set_destroy(live, NULL); diff --git a/mesalib/src/glsl/nir/nir_search.c b/mesalib/src/glsl/nir/nir_search.c index 73a802be7..5ba016085 100644 --- a/mesalib/src/glsl/nir/nir_search.c +++ b/mesalib/src/glsl/nir/nir_search.c @@ -218,8 +218,8 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr, if (matched) return true; - if (nir_op_infos[instr->op].num_inputs == 2 && - (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE)) { + if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) { + assert(nir_op_infos[instr->op].num_inputs == 2); if (!match_value(expr->srcs[0], instr, 1, num_components, swizzle, state)) return false; diff --git a/mesalib/src/glsl/nir/nir_split_var_copies.c b/mesalib/src/glsl/nir/nir_split_var_copies.c index 4d663b51b..fc72c078c 100644 --- a/mesalib/src/glsl/nir/nir_split_var_copies.c +++ b/mesalib/src/glsl/nir/nir_split_var_copies.c @@ -188,8 +188,8 @@ split_var_copy_instr(nir_intrinsic_instr *old_copy, * belongs to the copy instruction and b) the deref chains may * have some of the same links due to the way we constructed them */ - nir_deref *src = nir_copy_deref(state->mem_ctx, src_head); - nir_deref *dest = nir_copy_deref(state->mem_ctx, dest_head); + nir_deref *src = nir_copy_deref(new_copy, src_head); + nir_deref *dest = nir_copy_deref(new_copy, dest_head); new_copy->variables[0] = nir_deref_as_var(dest); new_copy->variables[1] = nir_deref_as_var(src); diff --git a/mesalib/src/glsl/nir/nir_sweep.c b/mesalib/src/glsl/nir/nir_sweep.c new file mode 100644 index 000000000..d3549756a --- /dev/null +++ b/mesalib/src/glsl/nir/nir_sweep.c @@ -0,0 +1,172 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "nir.h" + +/** + * \file nir_sweep.c + * + * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated + * memory - anything still connected to the program will be kept, and any dead memory + * we dropped on the floor will be freed. + * + * The expectation is that drivers should call this when finished compiling the shader + * (after any optimization, lowering, and so on). However, it's also fine to call it + * earlier, and even many times, trading CPU cycles for memory savings. + */ + +#define steal_list(mem_ctx, type, list) \ + foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); } + +static void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node); + +static bool +sweep_src_indirect(nir_src *src, void *nir) +{ + if (!src->is_ssa && src->reg.indirect) + ralloc_steal(nir, src->reg.indirect); + + return true; +} + +static bool +sweep_dest_indirect(nir_dest *dest, void *nir) +{ + if (!dest->is_ssa && dest->reg.indirect) + ralloc_steal(nir, dest->reg.indirect); + + return true; +} + +static void +sweep_block(nir_shader *nir, nir_block *block) +{ + ralloc_steal(nir, block); + + nir_foreach_instr(block, instr) { + ralloc_steal(nir, instr); + + nir_foreach_src(instr, sweep_src_indirect, nir); + nir_foreach_dest(instr, sweep_dest_indirect, nir); + } +} + +static void +sweep_if(nir_shader *nir, nir_if *iff) +{ + ralloc_steal(nir, iff); + + foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) { + sweep_cf_node(nir, cf_node); + } + + foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) { + sweep_cf_node(nir, cf_node); + } +} + +static void +sweep_loop(nir_shader *nir, nir_loop *loop) +{ + ralloc_steal(nir, loop); + + foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) { + sweep_cf_node(nir, cf_node); + } +} + +static void +sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node) +{ + switch (cf_node->type) { + case nir_cf_node_block: + sweep_block(nir, nir_cf_node_as_block(cf_node)); + break; + case nir_cf_node_if: + sweep_if(nir, nir_cf_node_as_if(cf_node)); + break; + case nir_cf_node_loop: + sweep_loop(nir, nir_cf_node_as_loop(cf_node)); + break; + default: + unreachable("Invalid CF node type"); + } +} + +static void +sweep_impl(nir_shader *nir, nir_function_impl *impl) +{ + ralloc_steal(nir, impl); + + ralloc_steal(nir, impl->params); + ralloc_steal(nir, impl->return_var); + steal_list(nir, nir_variable, &impl->locals); + steal_list(nir, nir_register, &impl->registers); + + foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) { + sweep_cf_node(nir, cf_node); + } + + sweep_block(nir, impl->end_block); + + /* Wipe out all the metadata, if any. */ + nir_metadata_preserve(impl, nir_metadata_none); +} + +static void +sweep_function(nir_shader *nir, nir_function *f) +{ + ralloc_steal(nir, f); + + foreach_list_typed(nir_function_overload, overload, node, &f->overload_list) { + ralloc_steal(nir, overload); + ralloc_steal(nir, overload->params); + if (overload->impl) + sweep_impl(nir, overload->impl); + } +} + +void +nir_sweep(nir_shader *nir) +{ + void *rubbish = ralloc_context(NULL); + + /* First, move ownership of all the memory to a temporary context; assume dead. */ + ralloc_adopt(rubbish, nir); + + /* Variables and registers are not dead. Steal them back. */ + steal_list(nir, nir_variable, &nir->uniforms); + steal_list(nir, nir_variable, &nir->inputs); + steal_list(nir, nir_variable, &nir->outputs); + steal_list(nir, nir_variable, &nir->globals); + steal_list(nir, nir_variable, &nir->system_values); + steal_list(nir, nir_register, &nir->registers); + + /* Recurse into functions, stealing their contents back. */ + foreach_list_typed(nir_function, func, node, &nir->functions) { + sweep_function(nir, func); + } + + /* Free everything we didn't steal back. */ + ralloc_free(rubbish); +} diff --git a/mesalib/src/glsl/nir/nir_to_ssa.c b/mesalib/src/glsl/nir/nir_to_ssa.c index 47cf45393..53ff54766 100644 --- a/mesalib/src/glsl/nir/nir_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_to_ssa.c @@ -47,7 +47,7 @@ insert_trivial_phi(nir_register *reg, nir_block *block, void *mem_ctx) set_foreach(block->predecessors, entry) { nir_block *pred = (nir_block *) entry->key; - nir_phi_src *src = ralloc(mem_ctx, nir_phi_src); + nir_phi_src *src = ralloc(instr, nir_phi_src); src->pred = pred; src->src.is_ssa = false; src->src.reg.base_offset = 0; diff --git a/mesalib/src/glsl/nir/nir_types.cpp b/mesalib/src/glsl/nir/nir_types.cpp index a13c3e12a..f0d0b46d2 100644 --- a/mesalib/src/glsl/nir/nir_types.cpp +++ b/mesalib/src/glsl/nir/nir_types.cpp @@ -143,6 +143,12 @@ glsl_void_type(void) } const glsl_type * +glsl_float_type(void) +{ + return glsl_type::float_type; +} + +const glsl_type * glsl_vec4_type(void) { return glsl_type::vec4_type; diff --git a/mesalib/src/glsl/nir/nir_types.h b/mesalib/src/glsl/nir/nir_types.h index 494051a67..276d4ad62 100644 --- a/mesalib/src/glsl/nir/nir_types.h +++ b/mesalib/src/glsl/nir/nir_types.h @@ -69,6 +69,7 @@ bool glsl_type_is_scalar(const struct glsl_type *type); bool glsl_type_is_matrix(const struct glsl_type *type); const struct glsl_type *glsl_void_type(void); +const struct glsl_type *glsl_float_type(void); const struct glsl_type *glsl_vec4_type(void); const struct glsl_type *glsl_array_type(const struct glsl_type *base, unsigned elements); diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c index f247ae069..a7aa79837 100644 --- a/mesalib/src/glsl/nir/nir_validate.c +++ b/mesalib/src/glsl/nir/nir_validate.c @@ -295,6 +295,8 @@ validate_alu_instr(nir_alu_instr *instr, validate_state *state) static void validate_deref_chain(nir_deref *deref, validate_state *state) { + assert(deref->child == NULL || ralloc_parent(deref->child) == deref); + nir_deref *parent = NULL; while (deref != NULL) { switch (deref->deref_type) { @@ -336,9 +338,10 @@ validate_var_use(nir_variable *var, validate_state *state) } static void -validate_deref_var(nir_deref_var *deref, validate_state *state) +validate_deref_var(void *parent_mem_ctx, nir_deref_var *deref, validate_state *state) { assert(deref != NULL); + assert(ralloc_parent(deref) == parent_mem_ctx); assert(deref->deref.type == deref->var->type); validate_var_use(deref->var, state); @@ -386,7 +389,7 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables; for (unsigned i = 0; i < num_vars; i++) { - validate_deref_var(instr->variables[i], state); + validate_deref_var(instr, instr->variables[i], state); } switch (instr->intrinsic) { @@ -423,7 +426,7 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state) } if (instr->sampler != NULL) - validate_deref_var(instr->sampler, state); + validate_deref_var(instr, instr->sampler, state); } static void @@ -438,10 +441,10 @@ validate_call_instr(nir_call_instr *instr, validate_state *state) for (unsigned i = 0; i < instr->num_params; i++) { assert(instr->callee->params[i].type == instr->params[i]->deref.type); - validate_deref_var(instr->params[i], state); + validate_deref_var(instr, instr->params[i], state); } - validate_deref_var(instr->return_deref, state); + validate_deref_var(instr, instr->return_deref, state); } static void @@ -680,8 +683,7 @@ validate_cf_node(nir_cf_node *node, validate_state *state) break; default: - assert(!"Invalid ALU instruction type"); - break; + unreachable("Invalid CF node type"); } } diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 69c03ea8b..3d2f2ca0b 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -290,6 +290,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL}; unsigned int i; + if (ir->operation == ir_binop_mul && + ir->operands[0]->type->is_matrix() && + ir->operands[1]->type->is_vector()) { + ir_expression *matrix_mul = ir->operands[0]->as_expression(); + + if (matrix_mul && matrix_mul->operation == ir_binop_mul && + matrix_mul->operands[0]->type->is_matrix() && + matrix_mul->operands[1]->type->is_matrix()) { + + return mul(matrix_mul->operands[0], + mul(matrix_mul->operands[1], ir->operands[1])); + } + } + assert(ir->get_num_operands() <= 4); for (i = 0; i < ir->get_num_operands(); i++) { if (ir->operands[i]->type->is_matrix()) @@ -421,6 +435,18 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) break; } + case ir_unop_saturate: + if (op_expr[0] && op_expr[0]->operation == ir_binop_add) { + ir_expression *b2f_0 = op_expr[0]->operands[0]->as_expression(); + ir_expression *b2f_1 = op_expr[0]->operands[1]->as_expression(); + + if (b2f_0 && b2f_0->operation == ir_unop_b2f && + b2f_1 && b2f_1->operation == ir_unop_b2f) { + return b2f(logic_or(b2f_0->operands[0], b2f_1->operands[0])); + } + } + break; + case ir_binop_add: if (is_vec_zero(op_const[0])) return ir->operands[1]; @@ -518,6 +544,10 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (is_vec_negative_one(op_const[1])) return neg(ir->operands[0]); + if (op_expr[0] && op_expr[0]->operation == ir_unop_b2f && + op_expr[1] && op_expr[1]->operation == ir_unop_b2f) { + return b2f(logic_and(op_expr[0]->operands[0], op_expr[1]->operands[0])); + } /* Reassociate multiplication of constants so that we can do * constant folding. @@ -544,6 +574,8 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) continue; ir_expression *add_expr = floor_expr->operands[0]->as_expression(); + if (!add_expr) + continue; for (int j = 0; j < 2; j++) { ir_expression *abs_expr = add_expr->operands[j]->as_expression(); diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp index b0b67f496..4b8e9a07b 100644 --- a/mesalib/src/glsl/opt_cse.cpp +++ b/mesalib/src/glsl/opt_cse.cpp @@ -63,6 +63,17 @@ public: var = NULL; } + void init(ir_instruction *base_ir, ir_rvalue **val) + { + this->val = val; + this->base_ir = base_ir; + this->var = NULL; + + assert(val); + assert(*val); + assert(base_ir); + } + /** * The pointer to the expression that we might be able to reuse * @@ -116,6 +127,18 @@ private: ir_rvalue *try_cse(ir_rvalue *rvalue); void add_to_ae(ir_rvalue **rvalue); + /** + * Move all nodes from the ae list to the free list + */ + void empty_ae_list(); + + /** + * Get and initialize a new ae_entry + * + * This will either come from the free list or be freshly allocated. + */ + ae_entry *get_ae_entry(ir_rvalue **rvalue); + /** List of ae_entry: The available expressions to reuse */ exec_list *ae; @@ -126,6 +149,11 @@ private: * right. */ exec_list *validate_instructions; + + /** + * List of available-for-use ae_entry objects. + */ + exec_list free_ae_entries; }; /** @@ -322,6 +350,25 @@ cse_visitor::try_cse(ir_rvalue *rvalue) return NULL; } +void +cse_visitor::empty_ae_list() +{ + free_ae_entries.append_list(ae); +} + +ae_entry * +cse_visitor::get_ae_entry(ir_rvalue **rvalue) +{ + ae_entry *entry = (ae_entry *) free_ae_entries.pop_head(); + if (entry) { + entry->init(base_ir, rvalue); + } else { + entry = new(mem_ctx) ae_entry(base_ir, rvalue); + } + + return entry; +} + /** Add the rvalue to the list of available expressions for CSE. */ void cse_visitor::add_to_ae(ir_rvalue **rvalue) @@ -332,7 +379,7 @@ cse_visitor::add_to_ae(ir_rvalue **rvalue) printf("\n"); } - ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue)); + ae->push_tail(get_ae_entry(rvalue)); if (debug) dump_ae(ae); @@ -370,33 +417,33 @@ cse_visitor::visit_enter(ir_if *ir) { handle_rvalue(&ir->condition); - ae->make_empty(); + empty_ae_list(); visit_list_elements(this, &ir->then_instructions); - ae->make_empty(); + empty_ae_list(); visit_list_elements(this, &ir->else_instructions); - ae->make_empty(); + empty_ae_list(); return visit_continue_with_parent; } ir_visitor_status cse_visitor::visit_enter(ir_function_signature *ir) { - ae->make_empty(); + empty_ae_list(); visit_list_elements(this, &ir->body); - ae->make_empty(); + empty_ae_list(); return visit_continue_with_parent; } ir_visitor_status cse_visitor::visit_enter(ir_loop *ir) { - ae->make_empty(); + empty_ae_list(); visit_list_elements(this, &ir->body_instructions); - ae->make_empty(); + empty_ae_list(); return visit_continue_with_parent; } diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp index 7eaa491e2..f82e155a6 100644 --- a/mesalib/src/glsl/s_expression.cpp +++ b/mesalib/src/glsl/s_expression.cpp @@ -23,8 +23,8 @@ */ #include <assert.h> -#include <limits> #include <stdio.h> +#include <math.h> #include "s_expression.h" s_symbol::s_symbol(const char *str, size_t n) @@ -70,7 +70,7 @@ read_atom(void *ctx, const char *&src, char *&symbol_buffer) // requires strtof to parse '+INF' as +Infinity, but we still support some // non-C99-compliant compilers (e.g. MSVC). if (n == 4 && strncmp(src, "+INF", 4) == 0) { - expr = new(ctx) s_float(std::numeric_limits<float>::infinity()); + expr = new(ctx) s_float(INFINITY); } else { // Check if the atom is a number. char *float_end = NULL; diff --git a/mesalib/src/glsl/shader_enums.h b/mesalib/src/glsl/shader_enums.h new file mode 100644 index 000000000..79e0f6b5f --- /dev/null +++ b/mesalib/src/glsl/shader_enums.h @@ -0,0 +1,187 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SHADER_ENUMS_H +#define SHADER_ENUMS_H + +/** + * Shader stages. Note that these will become 5 with tessellation. + * + * The order must match how shaders are ordered in the pipeline. + * The GLSL linker assumes that if i<j, then the j-th shader is + * executed later than the i-th shader. + */ +typedef enum +{ + MESA_SHADER_VERTEX = 0, + MESA_SHADER_GEOMETRY = 1, + MESA_SHADER_FRAGMENT = 2, + MESA_SHADER_COMPUTE = 3, +} gl_shader_stage; + +#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1) + +/** + * Bitflags for system values. + */ +#define SYSTEM_BIT_SAMPLE_ID ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_ID) +#define SYSTEM_BIT_SAMPLE_POS ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_POS) +#define SYSTEM_BIT_SAMPLE_MASK_IN ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_MASK_IN) +/** + * If the gl_register_file is PROGRAM_SYSTEM_VALUE, the register index will be + * one of these values. If a NIR variable's mode is nir_var_system_value, it + * will be one of these values. + */ +typedef enum +{ + /** + * \name Vertex shader system values + */ + /*@{*/ + /** + * OpenGL-style vertex ID. + * + * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the + * OpenGL 3.3 core profile spec says: + * + * "gl_VertexID holds the integer index i implicitly passed by + * DrawArrays or one of the other drawing commands defined in section + * 2.8.3." + * + * Section 2.8.3 (Drawing Commands) of the same spec says: + * + * "The commands....are equivalent to the commands with the same base + * name (without the BaseVertex suffix), except that the ith element + * transferred by the corresponding draw call will be taken from + * element indices[i] + basevertex of each enabled array." + * + * Additionally, the overview in the GL_ARB_shader_draw_parameters spec + * says: + * + * "In unextended GL, vertex shaders have inputs named gl_VertexID and + * gl_InstanceID, which contain, respectively the index of the vertex + * and instance. The value of gl_VertexID is the implicitly passed + * index of the vertex being processed, which includes the value of + * baseVertex, for those commands that accept it." + * + * gl_VertexID gets basevertex added in. This differs from DirectX where + * SV_VertexID does \b not get basevertex added in. + * + * \note + * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be + * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus + * \c SYSTEM_VALUE_BASE_VERTEX. + * + * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX + */ + SYSTEM_VALUE_VERTEX_ID, + + /** + * Instanced ID as supplied to gl_InstanceID + * + * Values assigned to gl_InstanceID always begin with zero, regardless of + * the value of baseinstance. + * + * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec + * says: + * + * "gl_InstanceID holds the integer instance number of the current + * primitive in an instanced draw call (see section 10.5)." + * + * Through a big chain of pseudocode, section 10.5 describes that + * baseinstance is not counted by gl_InstanceID. In that section, notice + * + * "If an enabled vertex attribute array is instanced (it has a + * non-zero divisor as specified by VertexAttribDivisor), the element + * index that is transferred to the GL, for all vertices, is given by + * + * floor(instance/divisor) + baseinstance + * + * If an array corresponding to an attribute required by a vertex + * shader is not enabled, then the corresponding element is taken from + * the current attribute state (see section 10.2)." + * + * Note that baseinstance is \b not included in the value of instance. + */ + SYSTEM_VALUE_INSTANCE_ID, + + /** + * DirectX-style vertex ID. + * + * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include + * the value of basevertex. + * + * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX + */ + SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, + + /** + * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar + * functions. + * + * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE + */ + SYSTEM_VALUE_BASE_VERTEX, + /*@}*/ + + /** + * \name Geometry shader system values + */ + /*@{*/ + SYSTEM_VALUE_INVOCATION_ID, + /*@}*/ + + /** + * \name Fragment shader system values + */ + /*@{*/ + SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */ + SYSTEM_VALUE_SAMPLE_ID, + SYSTEM_VALUE_SAMPLE_POS, + SYSTEM_VALUE_SAMPLE_MASK_IN, + /*@}*/ + + SYSTEM_VALUE_MAX /**< Number of values */ +} gl_system_value; + + +/** + * The possible interpolation qualifiers that can be applied to a fragment + * shader input in GLSL. + * + * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the + * gl_fragment_program data structure to 0 causes the default behavior. + */ +enum glsl_interp_qualifier +{ + INTERP_QUALIFIER_NONE = 0, + INTERP_QUALIFIER_SMOOTH, + INTERP_QUALIFIER_FLAT, + INTERP_QUALIFIER_NOPERSPECTIVE, + INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */ +}; + + +#endif /* SHADER_ENUMS_H */ diff --git a/mesalib/src/loader/Makefile.am b/mesalib/src/loader/Makefile.am index 3d32279ea..36ddba82b 100755 --- a/mesalib/src/loader/Makefile.am +++ b/mesalib/src/loader/Makefile.am @@ -30,7 +30,6 @@ libloader_la_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src \ $(VISIBILITY_CFLAGS) \ - $(MSVC2013_COMPAT_CFLAGS) \ $(LIBUDEV_CFLAGS) libloader_la_SOURCES = $(LOADER_C_FILES) diff --git a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml index 641e68f71..8a092d697 100644 --- a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml +++ b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml @@ -7,6 +7,47 @@ <enum name="QUERY_TARGET" value="0x82EA"/> <enum name="TEXTURE_BINDING" value="0x82EB"/> + <!-- Transform Feedback object functions --> + + <function name="CreateTransformFeedbacks" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="ids" type="GLuint *" /> + </function> + + <function name="TransformFeedbackBufferBase" offset="assign"> + <param name="xfb" type="GLuint" /> + <param name="index" type="GLuint" /> + <param name="buffer" type="GLuint" /> + </function> + + <function name="TransformFeedbackBufferRange" offset="assign"> + <param name="xfb" type="GLuint" /> + <param name="index" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + </function> + + <function name="GetTransformFeedbackiv" offset="assign"> + <param name="xfb" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint *" /> + </function> + + <function name="GetTransformFeedbacki_v" offset="assign"> + <param name="xfb" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="index" type="GLuint" /> + <param name="param" type="GLint *" /> + </function> + + <function name="GetTransformFeedbacki64_v" offset="assign"> + <param name="xfb" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="index" type="GLuint" /> + <param name="param" type="GLint64 *" /> + </function> + <!-- Buffer object functions --> <function name="CreateBuffers" offset="assign"> @@ -111,6 +152,34 @@ <param name="data" type="GLvoid *" /> </function> + <!-- Renderbuffer object functions --> + + <function name="CreateRenderbuffers" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="renderbuffers" type="GLuint *" /> + </function> + + <function name="NamedRenderbufferStorage" offset="assign"> + <param name="renderbuffer" type="GLuint" /> + <param name="internalformat" type="GLenum" /> + <param name="width" type="GLsizei" /> + <param name="height" type="GLsizei" /> + </function> + + <function name="NamedRenderbufferStorageMultisample" offset="assign"> + <param name="renderbuffer" type="GLuint" /> + <param name="samples" type="GLsizei" /> + <param name="internalformat" type="GLenum" /> + <param name="width" type="GLsizei" /> + <param name="height" type="GLsizei" /> + </function> + + <function name="GetNamedRenderbufferParameteriv" offset="assign"> + <param name="renderbuffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint *" /> + </function> + <!-- Texture object functions --> <function name="CreateTextures" offset="assign"> @@ -379,5 +448,54 @@ <param name="params" type="GLint *" /> </function> + <!-- Sampler object functions --> + + <function name="CreateSamplers" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="samplers" type="GLuint *" /> + </function> + + <!-- Program Pipeline object functions --> + + <function name="CreateProgramPipelines" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="pipelines" type="GLuint *" /> + </function> + + <!-- Query object functions --> + + <function name="CreateQueries" offset="assign"> + <param name="target" type="GLenum" /> + <param name="n" type="GLsizei" /> + <param name="ids" type="GLuint *" /> + </function> + + <function name="GetQueryBufferObjectiv" offset="assign"> + <param name="id" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="offset" type="GLintptr" /> + </function> + + <function name="GetQueryBufferObjectuiv" offset="assign"> + <param name="id" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="offset" type="GLintptr" /> + </function> + + <function name="GetQueryBufferObjecti64v" offset="assign"> + <param name="id" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="offset" type="GLintptr" /> + </function> + + <function name="GetQueryBufferObjectui64v" offset="assign"> + <param name="id" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="offset" type="GLintptr" /> + </function> </category> </OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml b/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml new file mode 100644 index 000000000..59eb59c64 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml @@ -0,0 +1,109 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_program_interface_query" number="134"> + + <enum name="UNIFORM" value="0x92E1"/> + <enum name="UNIFORM_BLOCK" value="0x92E2"/> + <enum name="PROGRAM_INPUT" value="0x92E3"/> + <enum name="PROGRAM_OUTPUT" value="0x92E4"/> + <enum name="BUFFER_VARIABLE" value="0x92E5"/> + <enum name="SHADER_STORAGE_BLOCK" value="0x92E6"/> + <enum name="ATOMIC_COUNTER_BUFFER" value="0x92C0"/> + <enum name="VERTEX_SUBROUTINE" value="0x92E8"/> + <enum name="TESS_CONTROL_SUBROUTINE" value="0x92E9"/> + <enum name="TESS_EVALUATION_SUBROUTINE" value="0x92EA"/> + <enum name="GEOMETRY_SUBROUTINE" value="0x92EB"/> + <enum name="FRAGMENT_SUBROUTINE" value="0x92EC"/> + <enum name="COMPUTE_SUBROUTINE" value="0x92ED"/> + <enum name="VERTEX_SUBROUTINE_UNIFORM" value="0x92EE"/> + <enum name="TESS_CONTROL_SUBROUTINE_UNIFORM" value="0x92EF"/> + <enum name="TESS_EVALUATION_SUBROUTINE_UNIFORM" value="0x92F0"/> + <enum name="GEOMETRY_SUBROUTINE_UNIFORM" value="0x92F1"/> + <enum name="FRAGMENT_SUBROUTINE_UNIFORM" value="0x92F2"/> + <enum name="COMPUTE_SUBROUTINE_UNIFORM" value="0x92F3"/> + <enum name="TRANSFORM_FEEDBACK_VARYING" value="0x92F4"/> + <enum name="ACTIVE_RESOURCES" value="0x92F5"/> + <enum name="MAX_NAME_LENGTH" value="0x92F6"/> + <enum name="MAX_NUM_ACTIVE_VARIABLES" value="0x92F7"/> + <enum name="MAX_NUM_COMPATIBLE_SUBROUTINES" value="0x92F8"/> + <enum name="NAME_LENGTH" value="0x92F9"/> + <enum name="TYPE" value="0x92FA"/> + <enum name="ARRAY_SIZE" value="0x92FB"/> + <enum name="OFFSET" value="0x92FC"/> + <enum name="BLOCK_INDEX" value="0x92FD"/> + <enum name="ARRAY_STRIDE" value="0x92FE"/> + <enum name="MATRIX_STRIDE" value="0x92FF"/> + <enum name="IS_ROW_MAJOR" value="0x9300"/> + <enum name="ATOMIC_COUNTER_BUFFER_INDEX" value="0x9301"/> + <enum name="BUFFER_BINDING" value="0x9302"/> + <enum name="BUFFER_DATA_SIZE" value="0x9303"/> + <enum name="NUM_ACTIVE_VARIABLES" value="0x9304"/> + <enum name="ACTIVE_VARIABLES" value="0x9305"/> + <enum name="REFERENCED_BY_VERTEX_SHADER" value="0x9306"/> + <enum name="REFERENCED_BY_TESS_CONTROL_SHADER" value="0x9307"/> + <enum name="REFERENCED_BY_TESS_EVALUATION_SHADER" value="0x9308"/> + <enum name="REFERENCED_BY_GEOMETRY_SHADER" value="0x9309"/> + <enum name="REFERENCED_BY_FRAGMENT_SHADER" value="0x930A"/> + <enum name="REFERENCED_BY_COMPUTE_SHADER" value="0x930B"/> + <enum name="TOP_LEVEL_ARRAY_SIZE" value="0x930C"/> + <enum name="TOP_LEVEL_ARRAY_STRIDE" value="0x930D"/> + <enum name="LOCATION" value="0x930E"/> + <enum name="LOCATION_INDEX" value="0x930F"/> + <enum name="IS_PER_PATCH" value="0x92E7"/> + <enum name="NUM_COMPATIBLE_SUBROUTINES" value="0x8E4A"/> + <enum name="COMPATIBLE_SUBROUTINES" value="0x8E4B"/> + + <function name="GetProgramInterfaceiv" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="pname" type="GLenum"/> + <param name="params" type="GLint *" output="true"/> + </function> + + <function name="GetProgramResourceIndex" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="name" type="const GLchar *"/> + <return type="GLuint"/> + </function> + + <function name="GetProgramResourceName" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="index" type="GLuint"/> + <param name="bufSize" type="GLsizei "/> + <param name="length" type="GLsizei *" output="true"/> + <param name="name" type="GLchar *" output="true"/> + </function> + + <function name="GetProgramResourceiv" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="index" type="GLuint"/> + <param name="propCount" type="GLsizei "/> + <param name="props" type="const GLenum *" output="true"/> + <param name="bufSize" type="GLsizei "/> + <param name="length" type="GLsizei *" output="true"/> + <param name="params" type="GLint *" output="true"/> + </function> + + <function name="GetProgramResourceLocation" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="name" type="const GLchar *"/> + <return type="GLint"/> + </function> + + <function name="GetProgramResourceLocationIndex" offset="assign"> + <param name="program" type="GLuint"/> + <param name="programInterface" type="GLenum"/> + <param name="name" type="const GLchar *"/> + <return type="GLint"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index a640241e9..5fa2e14a1 100755 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8337,7 +8337,9 @@ <!-- ARB extension #133 is ARB_multi_draw_indirect, defined in the same file as ARB_draw_indirect --> -<!-- ARB extensions #134...#138 --> +<xi:include href="ARB_program_interface_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<!-- ARB extensions #135...#138 --> <xi:include href="ARB_texture_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index d479e66da..7151f0de1 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -92,6 +92,7 @@ header = """/** #include "main/pixelstore.h" #include "main/points.h" #include "main/polygon.h" +#include "main/program_resource.h" #include "main/querymatrix.h" #include "main/queryobj.h" #include "main/readpix.h" diff --git a/mesalib/src/mapi/stub.c b/mesalib/src/mapi/stub.c index 05436bab6..45e4f7dc6 100644 --- a/mesalib/src/mapi/stub.c +++ b/mesalib/src/mapi/stub.c @@ -102,7 +102,7 @@ stub_add_dynamic(const char *name) if (!stub->addr) return NULL; - stub->name = (const void *) name; + stub->name = (const void *) strdup(name); /* to be fixed later */ stub->slot = -1; diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index 3dab8f03f..60114e4f6 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -174,6 +174,7 @@ endif libmesa_la_SOURCES = \ $(MESA_FILES) \ $(PROGRAM_FILES) \ + $(PROGRAM_NIR_FILES) \ $(MESA_ASM_FILES_FOR_ARCH) libmesa_la_LIBADD = \ @@ -183,6 +184,7 @@ libmesa_la_LIBADD = \ libmesagallium_la_SOURCES = \ $(MESA_GALLIUM_FILES) \ $(PROGRAM_FILES) \ + $(PROGRAM_NIR_FILES) \ $(MESA_ASM_FILES_FOR_ARCH) libmesagallium_la_LIBADD = \ diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index 217be9ab3..1293d4135 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -152,6 +152,8 @@ MAIN_FILES = \ main/points.h \ main/polygon.c \ main/polygon.h \ + main/program_resource.c \ + main/program_resource.h \ main/querymatrix.c \ main/querymatrix.h \ main/queryobj.c \ @@ -520,6 +522,10 @@ PROGRAM_FILES = \ program/symbol_table.c \ program/symbol_table.h +PROGRAM_NIR_FILES = \ + program/prog_to_nir.c \ + program/prog_to_nir.h + ASM_C_FILES = \ x86/common_x86.c \ x86/x86_xform.c \ @@ -608,6 +614,7 @@ INCLUDE_DIRS = \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/glsl \ -I$(top_builddir)/src/glsl \ + -I$(top_builddir)/src/glsl/nir \ -I$(top_srcdir)/src/glsl/glcpp \ -I$(top_srcdir)/src/mesa \ -I$(top_builddir)/src/mesa \ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index a563fd2ff..5b80a216f 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -130,9 +130,10 @@ def write_git_sha1_h_file(filename): (commit, foo) = subprocess.Popen(args, stdout=subprocess.PIPE).communicate() except: # git log command didn't work - dirname = os.path.dirname(filename) - if not os.path.exists(dirname): - os.makedirs(dirname) + if not os.path.exists(filename): + dirname = os.path.dirname(filename) + if not os.path.exists(dirname): + os.makedirs(dirname) # create an empty file if none already exists f = open(filename, "w") f.close() diff --git a/mesalib/src/mesa/drivers/SConscript b/mesalib/src/mesa/drivers/SConscript index 17813da96..db656780c 100644 --- a/mesalib/src/mesa/drivers/SConscript +++ b/mesalib/src/mesa/drivers/SConscript @@ -1,7 +1,5 @@ Import('*') -SConscript('osmesa/SConscript') - if env['x11']: SConscript('x11/SConscript') diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c index bb22107e9..70d34e8ce 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.c +++ b/mesalib/src/mesa/drivers/dri/common/utils.c @@ -227,7 +227,7 @@ driCreateConfigs(mesa_format format, break; default: fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n", - __FUNCTION__, __LINE__, + __func__, __LINE__, _mesa_get_format_name(format), format); return NULL; } diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index a90a97fa9..7ae38d07a 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -56,7 +56,7 @@ extern char *program_invocation_name, *program_invocation_short_name; # include <stdlib.h> # define GET_PROGRAM_NAME() getprogname() # endif -#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100) +#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) # include <stdlib.h> # define GET_PROGRAM_NAME() getprogname() #elif defined(__APPLE__) diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am index 555771685..a6f1652d1 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am +++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am @@ -52,14 +52,19 @@ POT=xmlpool.pot .PHONY: all clean pot po mo -EXTRA_DIST = gen_xmlpool.py options.h t_options.h $(POS) SConscript -BUILT_SOURCES = options.h -CLEANFILES = $(MOS) options.h +EXTRA_DIST = \ + gen_xmlpool.py \ + options.h \ + t_options.h \ + $(POS) \ + $(MOS) \ + SConscript -# All generated files are cleaned up. -clean: - -rm -f $(POT) options.h *~ - -rm -rf $(LANGS) +BUILT_SOURCES = options.h +CLEANFILES = \ + options.h + $(POS) \ + $(MOS) # Default target options.h options.h: LOCALEDIR := . diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index e84059073..d07988a40 100755 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -335,7 +335,7 @@ choose_pixel_format(const struct gl_config *v) && v->blueMask == 0xc0) return PF_R3G3B2; - _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); + _mesa_problem( NULL, "unexpected format in %s", __func__ ); return 0; } diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h index 8dccc2265..8182e7677 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h @@ -48,13 +48,13 @@ #define DEBUG_SPAN 0 #if DEBUG_CORE -#define TRACE printf("--> %s\n", __FUNCTION__) +#define TRACE printf("--> %s\n", __func__) #else #define TRACE #endif #if DEBUG_SPAN -#define TRACE_SPAN printf("--> %s\n", __FUNCTION__) +#define TRACE_SPAN printf("--> %s\n", __func__) #else #define TRACE_SPAN #endif diff --git a/mesalib/src/mesa/main/.gitignore b/mesalib/src/mesa/main/.gitignore index 54885405f..58c73d333 100755 --- a/mesalib/src/mesa/main/.gitignore +++ b/mesalib/src/mesa/main/.gitignore @@ -8,5 +8,6 @@ get_hash.h get_hash.h.tmp
format_info.h
glapitable.h
+format_info.c
format_pack.c
format_unpack.c
diff --git a/mesalib/src/mesa/main/atifragshader.c b/mesalib/src/mesa/main/atifragshader.c index 9d967b9e6..9fc35520a 100644 --- a/mesalib/src/mesa/main/atifragshader.c +++ b/mesalib/src/mesa/main/atifragshader.c @@ -476,7 +476,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) curI->swizzle = swizzle; #if MESA_DEBUG_ATI_FS - _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), _mesa_lookup_enum_by_nr(swizzle)); #endif @@ -549,7 +549,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) curI->swizzle = swizzle; #if MESA_DEBUG_ATI_FS - _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__, _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), _mesa_lookup_enum_by_nr(swizzle)); #endif diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 20216a87d..b163c0aa6 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -32,7 +32,6 @@ #include "buffers.h" #include "bufferobj.h" #include "clear.h" -#include "colormac.h" #include "context.h" #include "depth.h" #include "enable.h" diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 25110c33b..4a116acfe 100755 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -1333,6 +1333,7 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa) buf = ctx->Driver.NewBufferObject(ctx, buffers[i]); if (!buf) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + mtx_unlock(&ctx->Shared->Mutex); return; } } @@ -3885,8 +3886,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index, switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj, - offset, size); + _mesa_bind_buffer_range_transform_feedback(ctx, + ctx->TransformFeedback.CurrentObject, + index, bufObj, offset, size, + false); return; case GL_UNIFORM_BUFFER: bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); @@ -3950,7 +3953,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj); + _mesa_bind_buffer_base_transform_feedback(ctx, + ctx->TransformFeedback.CurrentObject, + index, bufObj, false); return; case GL_UNIFORM_BUFFER: bind_buffer_base_uniform_buffer(ctx, index, bufObj); diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h index bc69f4673..33ca5af07 100644 --- a/mesalib/src/mesa/main/colormac.h +++ b/mesalib/src/mesa/main/colormac.h @@ -52,70 +52,25 @@ _mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4]) /** * \name Generic color packing macros. All inputs should be GLubytes. - * - * \todo We may move these into texstore.h at some point. */ /*@{*/ #define PACK_COLOR_8888( X, Y, Z, W ) \ (((X) << 24) | ((Y) << 16) | ((Z) << 8) | (W)) -#define PACK_COLOR_8888_REV( X, Y, Z, W ) \ - (((W) << 24) | ((Z) << 16) | ((Y) << 8) | (X)) - -#define PACK_COLOR_888( X, Y, Z ) \ - (((X) << 16) | ((Y) << 8) | (Z)) - #define PACK_COLOR_565( X, Y, Z ) \ ((((X) & 0xf8) << 8) | (((Y) & 0xfc) << 3) | (((Z) & 0xf8) >> 3)) -#define PACK_COLOR_5551( R, G, B, A ) \ - ((((R) & 0xf8) << 8) | (((G) & 0xf8) << 3) | (((B) & 0xf8) >> 2) | \ - ((A) >> 7)) - #define PACK_COLOR_1555( A, B, G, R ) \ ((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \ (((A) & 0x80) << 8)) -#define PACK_COLOR_1555_REV( A, B, G, R ) \ - ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \ - ((A) ? 0x80 : 0)) - -#define PACK_COLOR_2101010_UB( A, B, G, R ) \ - (((B) << 22) | ((G) << 12) | ((R) << 2) | \ - (((A) & 0xc0) << 24)) - -#define PACK_COLOR_2101010_US( A, B, G, R ) \ - ((((B) >> 6) << 20) | (((G) >> 6) << 10) | ((R) >> 6) | \ - (((A) >> 14) << 30)) - #define PACK_COLOR_4444( R, G, B, A ) \ ((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4)) -#define PACK_COLOR_4444_REV( R, G, B, A ) \ - ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4)) - -#define PACK_COLOR_44( L, A ) \ - (((L) & 0xf0) | (((A) & 0xf0) >> 4)) - #define PACK_COLOR_88( L, A ) \ (((L) << 8) | (A)) -#define PACK_COLOR_88_REV( L, A ) \ - (((A) << 8) | (L)) - -#define PACK_COLOR_1616( L, A ) \ - (((L) << 16) | (A)) - -#define PACK_COLOR_1616_REV( L, A ) \ - (((A) << 16) | (L)) - -#define PACK_COLOR_332( R, G, B ) \ - (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6)) - -#define PACK_COLOR_233( B, G, R ) \ - (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5)) - /*@}*/ diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index c1acda980..adf64976e 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -1288,7 +1288,6 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); - _mesa_free_viewport_data( ctx ); _mesa_free_pipeline_data(ctx); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); @@ -1449,17 +1448,10 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst, dst->Transform = src->Transform; } if (mask & GL_VIEWPORT_BIT) { - /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */ unsigned i; for (i = 0; i < src->Const.MaxViewports; i++) { - dst->ViewportArray[i].X = src->ViewportArray[i].X; - dst->ViewportArray[i].Y = src->ViewportArray[i].Y; - dst->ViewportArray[i].Width = src->ViewportArray[i].Width; - dst->ViewportArray[i].Height = src->ViewportArray[i].Height; - dst->ViewportArray[i].Near = src->ViewportArray[i].Near; - dst->ViewportArray[i].Far = src->ViewportArray[i].Far; - _math_matrix_copy(&dst->ViewportArray[i]._WindowMap, - &src->ViewportArray[i]._WindowMap); + /* OK to memcpy */ + dst->ViewportArray[i] = src->ViewportArray[i]; } } diff --git a/mesalib/src/mesa/main/debug.c b/mesalib/src/mesa/main/debug.c index b50d79e0c..c93e84a04 100644 --- a/mesalib/src/mesa/main/debug.c +++ b/mesalib/src/mesa/main/debug.c @@ -26,11 +26,11 @@ #include <stdio.h> #include "mtypes.h" #include "attrib.h" -#include "colormac.h" #include "enums.h" #include "formats.h" #include "hash.h" #include "imports.h" +#include "macros.h" #include "debug.h" #include "get.h" #include "pixelstore.h" diff --git a/mesalib/src/mesa/main/dlopen.h b/mesalib/src/mesa/main/dlopen.h index 93d1258cf..93d1258cf 100644..100755 --- a/mesalib/src/mesa/main/dlopen.h +++ b/mesalib/src/mesa/main/dlopen.h diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index 8ffbf413c..2aa1deb63 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -1232,12 +1232,14 @@ _mesa_free_errors_data(struct gl_context *ctx) /** \name Diagnostics */ /*@{*/ +static FILE *LogFile = NULL; + + static void output_if_debug(const char *prefixString, const char *outputString, GLboolean newline) { static int debug = -1; - static FILE *fout = NULL; /* Init the local 'debug' var once. * Note: the _mesa_init_debug() function should have been called @@ -1249,9 +1251,9 @@ output_if_debug(const char *prefixString, const char *outputString, */ const char *logFile = getenv("MESA_LOG_FILE"); if (logFile) - fout = fopen(logFile, "w"); - if (!fout) - fout = stderr; + LogFile = fopen(logFile, "w"); + if (!LogFile) + LogFile = stderr; #ifdef DEBUG /* in debug builds, print messages unless MESA_DEBUG="silent" */ if (MESA_DEBUG_FLAGS & DEBUG_SILENT) @@ -1266,10 +1268,13 @@ output_if_debug(const char *prefixString, const char *outputString, /* Now only print the string if we're required to do so. */ if (debug) { - fprintf(fout, "%s: %s", prefixString, outputString); + if (prefixString) + fprintf(LogFile, "%s: %s", prefixString, outputString); + else + fprintf(LogFile, "%s", outputString); if (newline) - fprintf(fout, "\n"); - fflush(fout); + fprintf(LogFile, "\n"); + fflush(LogFile); #if defined(_WIN32) /* stderr from windows applications without console is not usually @@ -1285,6 +1290,18 @@ output_if_debug(const char *prefixString, const char *outputString, /** + * Return the file handle to use for debug/logging. Defaults to stderr + * unless MESA_LOG_FILE is defined. + */ +FILE * +_mesa_get_log_file(void) +{ + assert(LogFile); + return LogFile; +} + + +/** * When a new type of error is recorded, print a message describing * previous errors which were accumulated. */ @@ -1525,6 +1542,18 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) } +void +_mesa_log(const char *fmtString, ...) +{ + char s[MAX_DEBUG_MESSAGE_LENGTH]; + va_list args; + va_start(args, fmtString); + _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); + va_end(args); + output_if_debug("", s, GL_FALSE); +} + + /** * Report debug information from the shader compiler via GL_ARB_debug_output. * diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h index 0c521c0d0..e6dc9b5f1 100644 --- a/mesalib/src/mesa/main/errors.h +++ b/mesalib/src/mesa/main/errors.h @@ -36,6 +36,7 @@ #define ERRORS_H +#include <stdio.h> #include "compiler.h" #include "glheader.h" #include "mtypes.h" @@ -69,6 +70,12 @@ extern void _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3); extern void +_mesa_log(const char *fmtString, ...) PRINTFLIKE(1, 2); + +extern FILE * +_mesa_get_log_file(void); + +extern void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, enum mesa_debug_source source, diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index f21201538..861b15006 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -139,6 +139,7 @@ static const struct extension extension_table[] = { { "GL_ARB_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 }, { "GL_ARB_point_parameters", o(EXT_point_parameters), GLL, 1997 }, { "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 }, + { "GL_ARB_program_interface_query", o(dummy_true), GL, 2012 }, { "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 }, { "GL_ARB_robustness", o(dummy_true), GL, 2010 }, { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index f8d0d92bf..8032585ab 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -212,13 +212,13 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, */ i = attachment - GL_COLOR_ATTACHMENT0_EXT; if (i >= ctx->Const.MaxColorAttachments - || (i > 0 && ctx->API == API_OPENGLES)) { - return NULL; + || (i > 0 && ctx->API == API_OPENGLES)) { + return NULL; } return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_STENCIL_ATTACHMENT: if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) - return NULL; + return NULL; /* fall-through */ case GL_DEPTH_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_DEPTH]; @@ -1122,28 +1122,28 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { /* Check that all DrawBuffers are present */ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { - if (fb->ColorDrawBuffer[j] != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; - fbo_incomplete(ctx, "missing drawbuffer", j); - return; - } - } + if (fb->ColorDrawBuffer[j] != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; + fbo_incomplete(ctx, "missing drawbuffer", j); + return; + } + } } /* Check that the ReadBuffer is present */ if (fb->ColorReadBuffer != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = get_attachment(ctx, fb, fb->ColorReadBuffer); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorReadBuffer); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; fbo_incomplete(ctx, "missing readbuffer", -1); - return; - } + return; + } } } @@ -1205,6 +1205,28 @@ _mesa_IsRenderbuffer(GLuint renderbuffer) } +static struct gl_renderbuffer * +allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer, + const char *func) +{ + struct gl_renderbuffer *newRb; + + /* create new renderbuffer object */ + newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); + if (!newRb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return NULL; + } + assert(newRb->AllocStorage); + mtx_lock(&ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); + newRb->RefCount = 1; /* referenced by hash table */ + mtx_unlock(&ctx->Shared->Mutex); + + return newRb; +} + + static void bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names) { @@ -1233,15 +1255,7 @@ bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names) } if (!newRb) { - /* create new renderbuffer object */ - newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); - if (!newRb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); - return; - } - assert(newRb->AllocStorage); - _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); - newRb->RefCount = 1; /* referenced by hash table */ + newRb = allocate_renderbuffer(ctx, renderbuffer, "glBindRenderbufferEXT"); } } else { @@ -1333,9 +1347,9 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) for (i = 0; i < n; i++) { if (renderbuffers[i] > 0) { - struct gl_renderbuffer *rb; - rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); - if (rb) { + struct gl_renderbuffer *rb; + rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); + if (rb) { /* check if deleting currently bound renderbuffer object */ if (rb == ctx->CurrentRenderbuffer) { /* bind default */ @@ -1368,31 +1382,31 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb); } - /* Remove from hash table immediately, to free the ID. + /* Remove from hash table immediately, to free the ID. * But the object will not be freed until it's no longer * referenced anywhere else. */ - _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); + _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); if (rb != &DummyRenderbuffer) { /* no longer referenced by hash table */ _mesa_reference_renderbuffer(&rb, NULL); - } - } + } + } } } } - -void GLAPIENTRY -_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) +static void +create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers, + bool dsa) { - GET_CURRENT_CONTEXT(ctx); + const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers"; GLuint first; GLint i; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func); return; } @@ -1404,14 +1418,35 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) for (i = 0; i < n; i++) { GLuint name = first + i; renderbuffers[i] = name; - /* insert dummy placeholder into hash table */ - mtx_lock(&ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); - mtx_unlock(&ctx->Shared->Mutex); + + if (dsa) { + allocate_renderbuffer(ctx, name, func); + } else { + /* insert a dummy renderbuffer into the hash table */ + mtx_lock(&ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); + mtx_unlock(&ctx->Shared->Mutex); + } } } +void GLAPIENTRY +_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + create_render_buffers(ctx, n, renderbuffers, false); +} + + +void GLAPIENTRY +_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + create_render_buffers(ctx, n, renderbuffers, true); +} + + /** * Given an internal format token for a render buffer, return the * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, @@ -1749,40 +1784,17 @@ invalidate_rb(GLuint key, void *data, void *userData) /** - * Helper function used by _mesa_RenderbufferStorage() and - * _mesa_RenderbufferStorageMultisample(). - * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage(). + * Helper function used by renderbuffer_storage_direct() and + * renderbuffer_storage_target(). + * samples will be NO_SAMPLES if called by a non-multisample function. */ static void -renderbuffer_storage(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei samples) +renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei samples, const char *func) { - const char *func = samples == NO_SAMPLES ? - "glRenderbufferStorage" : "glRenderbufferStorageMultisample"; - struct gl_renderbuffer *rb; GLenum baseFormat; GLenum sample_count_error; - GET_CURRENT_CONTEXT(ctx); - - if (MESA_VERBOSE & VERBOSE_API) { - if (samples == NO_SAMPLES) - _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", - func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), - width, height); - else - _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", - func, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internalFormat), - width, height, samples); - } - - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); - return; - } baseFormat = _mesa_base_fbo_format(ctx, internalFormat); if (baseFormat == 0) { @@ -1792,12 +1804,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func, + width); return; } if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func, + height); return; } @@ -1809,7 +1823,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, /* check the sample count; * note: driver may choose to use more samples than what's requested */ - sample_count_error = _mesa_check_sample_count(ctx, target, + sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER, internalFormat, samples); if (sample_count_error != GL_NO_ERROR) { _mesa_error(ctx, sample_count_error, "%s(samples)", func); @@ -1817,12 +1831,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } } - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); - return; - } - FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (rb->InternalFormat == internalFormat && @@ -1864,6 +1872,83 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, } } +/** + * Helper function used by _mesa_NamedRenderbufferStorage*(). + * samples will be NO_SAMPLES if called by a non-multisample function. + */ +static void +renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei samples, + const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) { + if (samples == NO_SAMPLES) + _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n", + func, renderbuffer, + _mesa_lookup_enum_by_nr(internalFormat), + width, height); + else + _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n", + func, renderbuffer, + _mesa_lookup_enum_by_nr(internalFormat), + width, height, samples); + } + + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb || rb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)", + func, renderbuffer); + return; + } + + renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func); +} + +/** + * Helper function used by _mesa_RenderbufferStorage() and + * _mesa_RenderbufferStorageMultisample(). + * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage(). + */ +static void +renderbuffer_storage_target(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei samples, + const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) { + if (samples == NO_SAMPLES) + _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height); + else + _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height, samples); + } + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); + return; + } + + if (!ctx->CurrentRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)", + func); + return; + } + + renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width, + height, samples, func); +} + void GLAPIENTRY _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) @@ -1923,7 +2008,8 @@ _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat, * glRenderbufferStorageMultisample() with samples=0. We pass in * a token value here just for error reporting purposes. */ - renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); + renderbuffer_storage_target(target, internalFormat, width, height, + NO_SAMPLES, "glRenderbufferStorage"); } @@ -1932,7 +2018,8 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) { - renderbuffer_storage(target, internalFormat, width, height, samples); + renderbuffer_storage_target(target, internalFormat, width, height, + samples, "glRenderbufferStorageMultisample"); } @@ -1941,7 +2028,7 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, */ void GLAPIENTRY _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height) + GLsizei width, GLsizei height) { switch (internalFormat) { case GL_RGB565: @@ -1953,29 +2040,38 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, break; } - renderbuffer_storage(target, internalFormat, width, height, 0); + renderbuffer_storage_target(target, internalFormat, width, height, 0, + "glRenderbufferStorageEXT"); } - void GLAPIENTRY -_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) +_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, + GLsizei width, GLsizei height) { - struct gl_renderbuffer *rb; - GET_CURRENT_CONTEXT(ctx); + /* GL_ARB_fbo says calling this function is equivalent to calling + * glRenderbufferStorageMultisample() with samples=0. We pass in + * a token value here just for error reporting purposes. + */ + renderbuffer_storage_named(renderbuffer, internalformat, width, height, + NO_SAMPLES, "glNamedRenderbufferStorage"); +} - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetRenderbufferParameterivEXT(target)"); - return; - } +void GLAPIENTRY +_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, + GLenum internalformat, + GLsizei width, GLsizei height) +{ + renderbuffer_storage_named(renderbuffer, internalformat, width, height, + samples, + "glNamedRenderbufferStorageMultisample"); +} - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetRenderbufferParameterivEXT"); - return; - } +static void +get_render_buffer_parameteriv(struct gl_context *ctx, + struct gl_renderbuffer *rb, GLenum pname, + GLint *params, const char *func) +{ /* No need to flush here since we're just quering state which is * not effected by rendering. */ @@ -2006,10 +2102,51 @@ _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) } /* fallthrough */ default: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func, + _mesa_lookup_enum_by_nr(pname)); + return; + } +} + + +void GLAPIENTRY +_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + + if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetRenderbufferParameterivEXT(target)"); return; } + + if (!ctx->CurrentRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT" + "(no renderbuffer bound)"); + return; + } + + get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname, + params, "glGetRenderbufferParameteriv"); +} + + +void GLAPIENTRY +_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb || rb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv" + "(invalid renderbuffer %i)", renderbuffer); + return; + } + + get_render_buffer_parameteriv(ctx, rb, pname, params, + "glGetNamedRenderbufferParameteriv"); } @@ -2116,12 +2253,12 @@ bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names) } if (!newDrawFb) { - /* create new framebuffer object */ - newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); - if (!newDrawFb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); - return; - } + /* create new framebuffer object */ + newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); + if (!newDrawFb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); + return; + } _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); } newReadFb = newDrawFb; @@ -2224,9 +2361,9 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) for (i = 0; i < n; i++) { if (framebuffers[i] > 0) { - struct gl_framebuffer *fb; - fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); - if (fb) { + struct gl_framebuffer *fb; + fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); + if (fb) { assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* check if deleting currently bound framebuffer object */ @@ -2241,16 +2378,16 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0); } - /* remove from hash table immediately, to free the ID */ - _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); if (fb != &DummyFramebuffer) { /* But the object will not be freed until it's no longer * bound in any context. */ _mesa_reference_framebuffer(&fb, NULL); - } - } + } + } } } } @@ -2498,34 +2635,34 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_STENCIL].CubeMapFace && zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { - /* The texture object is already attached to the stencil attachment - * point. Don't create a new renderbuffer; just reuse the stencil - * attachment's. This is required to prevent a GL error in - * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). - */ - reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, - BUFFER_STENCIL); + /* The texture object is already attached to the stencil attachment + * point. Don't create a new renderbuffer; just reuse the stencil + * attachment's. This is required to prevent a GL error in + * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). + */ + reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, + BUFFER_STENCIL); } else if (attachment == GL_STENCIL_ATTACHMENT && - texObj == fb->Attachment[BUFFER_DEPTH].Texture && + texObj == fb->Attachment[BUFFER_DEPTH].Texture && level == fb->Attachment[BUFFER_DEPTH].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_DEPTH].CubeMapFace && zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { - /* As above, but with depth and stencil transposed. */ - reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, - BUFFER_DEPTH); + /* As above, but with depth and stencil transposed. */ + reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, + BUFFER_DEPTH); } else { - set_texture_attachment(ctx, fb, att, texObj, textarget, - level, zoffset, layered); - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - /* Above we created a new renderbuffer and attached it to the - * depth attachment point. Now attach it to the stencil attachment - * point too. - */ - assert(att == &fb->Attachment[BUFFER_DEPTH]); - reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, - BUFFER_DEPTH); - } + set_texture_attachment(ctx, fb, att, texObj, textarget, + level, zoffset, layered); + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { + /* Above we created a new renderbuffer and attached it to the + * depth attachment point. Now attach it to the stencil attachment + * point too. + */ + assert(att == &fb->Attachment[BUFFER_DEPTH]); + reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, + BUFFER_DEPTH); + } } /* Set the render-to-texture flag. We'll check this flag in @@ -2541,8 +2678,8 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, else { remove_attachment(ctx, att); if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - assert(att == &fb->Attachment[BUFFER_DEPTH]); - remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); + assert(att == &fb->Attachment[BUFFER_DEPTH]); + remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); } } @@ -2721,16 +2858,16 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, if (renderbuffer) { rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(non-existant" + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbuffer(non-existant" " renderbuffer %u)", renderbuffer); - return; + return; } else if (rb == &DummyRenderbuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer %u)", + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbuffer(renderbuffer %u)", renderbuffer); - return; + return; } } else { @@ -2795,9 +2932,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) && !_mesa_is_gles3(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); - return; + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); + return; } if (_mesa_is_gles3(ctx) && attachment != GL_BACK && @@ -2855,10 +2992,10 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: if (att->Type == GL_RENDERBUFFER_EXT) { - *params = att->Renderbuffer->Name; + *params = att->Renderbuffer->Name; } else if (att->Type == GL_TEXTURE) { - *params = att->Texture->Name; + *params = att->Texture->Name; } else { assert(att->Type == GL_NONE); @@ -2871,7 +3008,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: if (att->Type == GL_TEXTURE) { - *params = att->TextureLevel; + *params = att->TextureLevel; } else if (att->Type == GL_NONE) { _mesa_error(ctx, err, diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index 77fdef415..61aa1f503 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -115,6 +115,9 @@ extern void GLAPIENTRY _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers); extern void GLAPIENTRY +_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers); + +extern void GLAPIENTRY _mesa_RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); @@ -128,12 +131,25 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); extern void GLAPIENTRY +_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY +_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples, + GLenum internalformat, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); extern void GLAPIENTRY _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params); +void GLAPIENTRY +_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, + GLint *params); + extern GLboolean GLAPIENTRY _mesa_IsFramebuffer(GLuint framebuffer); diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c index 395b00e15..edf7e3390 100644 --- a/mesalib/src/mesa/main/ffvertex_prog.c +++ b/mesalib/src/mesa/main/ffvertex_prog.c @@ -619,13 +619,13 @@ static void emit_op3fn(struct tnl_program *p, #define emit_op3(p, op, dst, mask, src0, src1, src2) \ - emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, src1, src2, __func__, __LINE__) #define emit_op2(p, op, dst, mask, src0, src1) \ - emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, src1, undef, __func__, __LINE__) #define emit_op1(p, op, dst, mask, src0) \ - emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__) + emit_op3fn(p, op, dst, mask, src0, undef, undef, __func__, __LINE__) static struct ureg make_temp( struct tnl_program *p, struct ureg reg ) diff --git a/mesalib/src/mesa/main/format_pack.py b/mesalib/src/mesa/main/format_pack.py index f141da83c..2f43a30dd 100644 --- a/mesalib/src/mesa/main/format_pack.py +++ b/mesalib/src/mesa/main/format_pack.py @@ -43,7 +43,6 @@ string = """/* #include <stdint.h> -#include "colormac.h" #include "format_pack.h" #include "format_utils.h" #include "macros.h" diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h index eba3c6650..964c6077a 100644 --- a/mesalib/src/mesa/main/format_unpack.h +++ b/mesalib/src/mesa/main/format_unpack.h @@ -25,6 +25,8 @@ #ifndef FORMAT_UNPACK_H #define FORMAT_UNPACK_H +#include "formats.h" + extern void _mesa_unpack_rgba_row(mesa_format format, GLuint n, const void *src, GLfloat dst[][4]); diff --git a/mesalib/src/mesa/main/format_unpack.py b/mesalib/src/mesa/main/format_unpack.py index 53bdf641d..0ae73b897 100644 --- a/mesalib/src/mesa/main/format_unpack.py +++ b/mesalib/src/mesa/main/format_unpack.py @@ -43,7 +43,6 @@ string = """/* #include <stdint.h> -#include "colormac.h" #include "format_unpack.h" #include "format_utils.h" #include "macros.h" @@ -333,7 +332,7 @@ _mesa_unpack_rgba_row(mesa_format format, GLuint n, unpack_float_ycbcr_rev(src, dst, n); break; default: - _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__, + _mesa_problem(NULL, "%s: bad format %s", __func__, _mesa_get_format_name(format)); return; } @@ -402,7 +401,7 @@ _mesa_unpack_uint_rgba_row(mesa_format format, GLuint n, break; %endfor default: - _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__, + _mesa_problem(NULL, "%s: bad format %s", __func__, _mesa_get_format_name(format)); return; } diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 4e05229cf..8ced57949 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1393,7 +1393,7 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname) return GL_FALSE; default: _mesa_warning(NULL, "%s: Unexpected channel token 0x%x\n", - __FUNCTION__, pname); + __func__, pname); return GL_FALSE; } diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 8877966ec..27f54d585 100755 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -432,6 +432,30 @@ _mesa_fls(unsigned int n) #endif } +/** + * Find the last (most significant) bit set in a uint64_t value. + * + * Essentially ffsll() in the reverse direction. + */ +static inline unsigned int +_mesa_flsll(uint64_t n) +{ +#ifdef HAVE___BUILTIN_CLZLL + return n == 0 ? 0 : 64 - __builtin_clzll(n); +#else + unsigned int v = 1; + + if (n == 0) + return 0; + + while (n >>= 1) + v++; + + return v; +#endif +} + + extern GLhalfARB _mesa_float_to_half(float f); diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h index b22510965..5680b2ee1 100755 --- a/mesalib/src/mesa/main/macros.h +++ b/mesalib/src/mesa/main/macros.h @@ -789,7 +789,14 @@ NORMALIZE_3FV(GLfloat v[3]) static inline GLboolean DIFFERENT_SIGNS(GLfloat x, GLfloat y) { +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 6334 ) /* sizeof operator applied to an expression with an operator may yield unexpected results */ +#endif return signbit(x) != signbit(y); +#ifdef _MSC_VER +#pragma warning( pop ) +#endif } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 8e1dba6f0..1c751cfff 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -42,6 +42,7 @@ #include "main/config.h" #include "glapi/glapi.h" #include "math/m_matrix.h" /* GLmatrix */ +#include "glsl/shader_enums.h" #include "util/simple_list.h" /* struct simple_node */ #include "main/formats.h" /* MESA_FORMAT_COUNT */ @@ -280,13 +281,6 @@ typedef enum /*@}*/ /** - * Bitflags for system values. - */ -#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID) -#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS) -#define SYSTEM_BIT_SAMPLE_MASK_IN BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_MASK_IN) - -/** * Determine if the given gl_varying_slot appears in the fragment shader. */ static inline GLboolean @@ -395,25 +389,6 @@ typedef enum BUFFER_BIT_COLOR6 | \ BUFFER_BIT_COLOR7) - -/** - * Shader stages. Note that these will become 5 with tessellation. - * - * The order must match how shaders are ordered in the pipeline. - * The GLSL linker assumes that if i<j, then the j-th shader is - * executed later than the i-th shader. - */ -typedef enum -{ - MESA_SHADER_VERTEX = 0, - MESA_SHADER_GEOMETRY = 1, - MESA_SHADER_FRAGMENT = 2, - MESA_SHADER_COMPUTE = 3, -} gl_shader_stage; - -#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1) - - /** * Framebuffer configuration (aka visual / pixelformat) * Note: some of these fields should be boolean, but it appears that @@ -1456,7 +1431,6 @@ struct gl_viewport_attrib GLfloat X, Y; /**< position */ GLfloat Width, Height; /**< size */ GLdouble Near, Far; /**< Depth buffer range */ - GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */ }; @@ -2082,140 +2056,6 @@ typedef enum /** - * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be - * one of these values. - */ -typedef enum -{ - /** - * \name Vertex shader system values - */ - /*@{*/ - /** - * OpenGL-style vertex ID. - * - * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the - * OpenGL 3.3 core profile spec says: - * - * "gl_VertexID holds the integer index i implicitly passed by - * DrawArrays or one of the other drawing commands defined in section - * 2.8.3." - * - * Section 2.8.3 (Drawing Commands) of the same spec says: - * - * "The commands....are equivalent to the commands with the same base - * name (without the BaseVertex suffix), except that the ith element - * transferred by the corresponding draw call will be taken from - * element indices[i] + basevertex of each enabled array." - * - * Additionally, the overview in the GL_ARB_shader_draw_parameters spec - * says: - * - * "In unextended GL, vertex shaders have inputs named gl_VertexID and - * gl_InstanceID, which contain, respectively the index of the vertex - * and instance. The value of gl_VertexID is the implicitly passed - * index of the vertex being processed, which includes the value of - * baseVertex, for those commands that accept it." - * - * gl_VertexID gets basevertex added in. This differs from DirectX where - * SV_VertexID does \b not get basevertex added in. - * - * \note - * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be - * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus - * \c SYSTEM_VALUE_BASE_VERTEX. - * - * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX - */ - SYSTEM_VALUE_VERTEX_ID, - - /** - * Instanced ID as supplied to gl_InstanceID - * - * Values assigned to gl_InstanceID always begin with zero, regardless of - * the value of baseinstance. - * - * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec - * says: - * - * "gl_InstanceID holds the integer instance number of the current - * primitive in an instanced draw call (see section 10.5)." - * - * Through a big chain of pseudocode, section 10.5 describes that - * baseinstance is not counted by gl_InstanceID. In that section, notice - * - * "If an enabled vertex attribute array is instanced (it has a - * non-zero divisor as specified by VertexAttribDivisor), the element - * index that is transferred to the GL, for all vertices, is given by - * - * floor(instance/divisor) + baseinstance - * - * If an array corresponding to an attribute required by a vertex - * shader is not enabled, then the corresponding element is taken from - * the current attribute state (see section 10.2)." - * - * Note that baseinstance is \b not included in the value of instance. - */ - SYSTEM_VALUE_INSTANCE_ID, - - /** - * DirectX-style vertex ID. - * - * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include - * the value of basevertex. - * - * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX - */ - SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, - - /** - * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar - * functions. - * - * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE - */ - SYSTEM_VALUE_BASE_VERTEX, - /*@}*/ - - /** - * \name Geometry shader system values - */ - /*@{*/ - SYSTEM_VALUE_INVOCATION_ID, - /*@}*/ - - /** - * \name Fragment shader system values - */ - /*@{*/ - SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */ - SYSTEM_VALUE_SAMPLE_ID, - SYSTEM_VALUE_SAMPLE_POS, - SYSTEM_VALUE_SAMPLE_MASK_IN, - /*@}*/ - - SYSTEM_VALUE_MAX /**< Number of values */ -} gl_system_value; - - -/** - * The possible interpolation qualifiers that can be applied to a fragment - * shader input in GLSL. - * - * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the - * gl_fragment_program data structure to 0 causes the default behavior. - */ -enum glsl_interp_qualifier -{ - INTERP_QUALIFIER_NONE = 0, - INTERP_QUALIFIER_SMOOTH, - INTERP_QUALIFIER_FLAT, - INTERP_QUALIFIER_NOPERSPECTIVE, - INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */ -}; - - -/** * \brief Layout qualifiers for gl_FragDepth. * * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with @@ -2247,6 +2087,8 @@ struct gl_program struct prog_instruction *Instructions; + struct nir_shader *nir; + GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ @@ -2762,6 +2604,16 @@ struct gl_active_atomic_buffer }; /** + * Active resource in a gl_shader_program + */ +struct gl_program_resource +{ + GLenum Type; /** Program interface type. */ + const void *Data; /** Pointer to resource associated data structure. */ + uint8_t StageReferences; /** Bitmask of shader stage references. */ +}; + +/** * A GLSL program object. * Basically a linked collection of vertex and fragment shaders. */ @@ -2935,6 +2787,10 @@ struct gl_shader_program */ struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES]; + /** List of all active resources after linking. */ + struct gl_program_resource *ProgramResourceList; + unsigned NumProgramResourceList; + /* True if any of the fragment shaders attached to this program use: * #extension ARB_fragment_coord_conventions: enable */ @@ -3527,8 +3383,8 @@ struct gl_constants GLboolean ForceGLSLExtensionsWarn; /** - * If non-zero, forces GLSL shaders without the #version directive to behave - * as if they began with "#version ForceGLSLVersion". + * If non-zero, forces GLSL shaders to behave as if they began + * with "#version ForceGLSLVersion". */ GLuint ForceGLSLVersion; @@ -4523,7 +4379,7 @@ struct gl_context #ifdef DEBUG extern int MESA_VERBOSE; extern int MESA_DEBUG_FLAGS; -# define MESA_FUNCTION __FUNCTION__ +# define MESA_FUNCTION __func__ #else # define MESA_VERBOSE 0 # define MESA_DEBUG_FLAGS 0 diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c index 0e9207bc1..816837b95 100644 --- a/mesalib/src/mesa/main/multisample.c +++ b/mesalib/src/mesa/main/multisample.c @@ -150,6 +150,15 @@ GLenum _mesa_check_sample_count(struct gl_context *ctx, GLenum target, GLenum internalFormat, GLsizei samples) { + /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16: + * + * "If a negative number is provided where an argument of type sizei or + * sizeiptr is specified, the error INVALID VALUE is generated." + */ + if (samples < 0) { + return GL_INVALID_VALUE; + } + /* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0 * specification says: * diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c index fb241af1e..0fefa7d56 100644 --- a/mesalib/src/mesa/main/pipelineobj.c +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -498,16 +498,18 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) * \param n Number of IDs to generate. * \param pipelines pipeline of \c n locations to store the IDs. */ -void GLAPIENTRY -_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) +static void +create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines, + bool dsa) { - GET_CURRENT_CONTEXT(ctx); - + const char *func; GLuint first; GLint i; + func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines"; + if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func); return; } @@ -523,16 +525,37 @@ _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) obj = _mesa_new_pipeline_object(ctx, name); if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } + if (dsa) { + /* make dsa-allocated objects behave like program objects */ + obj->EverBound = GL_TRUE; + } + save_pipeline_object(ctx, obj); pipelines[i] = first + i; } } +void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + create_program_pipelines(ctx, n, pipelines, false); +} + +void GLAPIENTRY +_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + create_program_pipelines(ctx, n, pipelines, true); +} + /** * Determine if ID is the name of an pipeline object. * diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h index 7285a78f1..b57bcb99e 100644 --- a/mesalib/src/mesa/main/pipelineobj.h +++ b/mesalib/src/mesa/main/pipelineobj.h @@ -82,6 +82,9 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines); extern void GLAPIENTRY _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines); +void GLAPIENTRY +_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines); + extern GLboolean GLAPIENTRY _mesa_IsProgramPipeline(GLuint pipeline); diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c index 7162c6fef..ecda2694f 100644 --- a/mesalib/src/mesa/main/pixel.c +++ b/mesalib/src/mesa/main/pixel.c @@ -30,7 +30,6 @@ #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" #include "context.h" #include "macros.h" #include "pixel.h" diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c index 8bbeeb853..94464ea67 100644 --- a/mesalib/src/mesa/main/pixeltransfer.c +++ b/mesalib/src/mesa/main/pixeltransfer.c @@ -31,7 +31,7 @@ #include "glheader.h" -#include "colormac.h" +#include "macros.h" #include "pixeltransfer.h" #include "imports.h" #include "mtypes.h" diff --git a/mesalib/src/mesa/main/program_resource.c b/mesalib/src/mesa/main/program_resource.c new file mode 100644 index 000000000..b15a13210 --- /dev/null +++ b/mesalib/src/mesa/main/program_resource.c @@ -0,0 +1,417 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "main/enums.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/shaderapi.h" +#include "main/shaderobj.h" +#include "program_resource.h" + +static bool +supported_interface_enum(GLenum iface) +{ + switch (iface) { + case GL_UNIFORM: + case GL_UNIFORM_BLOCK: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_ATOMIC_COUNTER_BUFFER: + return true; + case GL_VERTEX_SUBROUTINE: + case GL_TESS_CONTROL_SUBROUTINE: + case GL_TESS_EVALUATION_SUBROUTINE: + case GL_GEOMETRY_SUBROUTINE: + case GL_FRAGMENT_SUBROUTINE: + case GL_COMPUTE_SUBROUTINE: + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_BUFFER_VARIABLE: + case GL_SHADER_STORAGE_BLOCK: + default: + return false; + } +} + +void GLAPIENTRY +_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + unsigned i; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramInterfaceiv"); + if (!shProg) + return; + + if (!params) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(params NULL)"); + return; + } + + /* Validate interface. */ + if (!supported_interface_enum(programInterface)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return; + } + + /* Validate pname against interface. */ + switch(pname) { + case GL_ACTIVE_RESOURCES: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) + if (shProg->ProgramResourceList[i].Type == programInterface) + (*params)++; + break; + case GL_MAX_NAME_LENGTH: + if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_lookup_enum_by_nr(programInterface), + _mesa_lookup_enum_by_nr(pname)); + return; + } + /* Name length consists of base name, 3 additional chars '[0]' if + * resource is an array and finally 1 char for string terminator. + */ + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type != programInterface) + continue; + const char *name = + _mesa_program_resource_name(&shProg->ProgramResourceList[i]); + unsigned array_size = + _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]); + *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1); + } + break; + case GL_MAX_NUM_ACTIVE_VARIABLES: + switch (programInterface) { + case GL_UNIFORM_BLOCK: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_uniform_block *block = + (struct gl_uniform_block *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, block->NumUniforms); + } + } + break; + case GL_ATOMIC_COUNTER_BUFFER: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_active_atomic_buffer *buffer = + (struct gl_active_atomic_buffer *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, buffer->NumUniforms); + } + } + break; + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_lookup_enum_by_nr(programInterface), + _mesa_lookup_enum_by_nr(pname)); + }; + break; + case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(pname %s)", + _mesa_lookup_enum_by_nr(pname)); + } +} + +static bool +is_xfb_marker(const char *str) +{ + static const char *markers[] = { + "gl_NextBuffer", + "gl_SkipComponents1", + "gl_SkipComponents2", + "gl_SkipComponents3", + "gl_SkipComponents4", + NULL + }; + const char **m = markers; + + if (strncmp(str, "gl_", 3) != 0) + return false; + + for (; *m; m++) + if (strcmp(*m, str) == 0) + return true; + + return false; +} + +/** + * Checks if given name index is legal for GetProgramResourceIndex, + * check is written to be compatible with GL_ARB_array_of_arrays. + */ +static bool +valid_program_resource_index_name(const GLchar *name) +{ + const char *array = strstr(name, "["); + const char *close = strrchr(name, ']'); + + /* Not array, no need for the check. */ + if (!array) + return true; + + /* Last array index has to be zero. */ + if (!close || *--close != '0') + return false; + + return true; +} + +GLuint GLAPIENTRY +_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_program_resource *res; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramResourceIndex"); + if (!shProg || !name) + return GL_INVALID_INDEX; + + /* + * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX + * should be returned when querying the index assigned to the special names + * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", + * "gl_SkipComponents3", and "gl_SkipComponents4". + */ + if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING && + is_xfb_marker(name)) + return GL_INVALID_INDEX; + + switch (programInterface) { + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM: + case GL_UNIFORM_BLOCK: + case GL_TRANSFORM_FEEDBACK_VARYING: + /* Validate name syntax for arrays. */ + if (!valid_program_resource_index_name(name)) + return GL_INVALID_INDEX; + + res = _mesa_program_resource_find_name(shProg, programInterface, name); + if (!res) + return GL_INVALID_INDEX; + + return _mesa_program_resource_index(shProg, res); + case GL_ATOMIC_COUNTER_BUFFER: + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + } + + return GL_INVALID_INDEX; +} + +void GLAPIENTRY +_mesa_GetProgramResourceName(GLuint program, GLenum programInterface, + GLuint index, GLsizei bufSize, GLsizei *length, + GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramResourceName"); + + /* Set user friendly return values in case of errors. */ + if (name) + *name = '\0'; + if (length) + *length = 0; + + if (!shProg || !name) + return; + + if (programInterface == GL_ATOMIC_COUNTER_BUFFER || + !supported_interface_enum(programInterface)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return; + } + + _mesa_get_program_resource_name(shProg, programInterface, index, bufSize, + length, name, "glGetProgramResourceName"); +} + +void GLAPIENTRY +_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, + GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv"); + + if (!shProg || !params) + return; + + /* The error INVALID_VALUE is generated if <propCount> is zero. + * Note that we check < 0 here because it makes sense to bail early. + */ + if (propCount <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramResourceiv(propCount <= 0)"); + return; + } + + /* No need to write any properties, user requested none. */ + if (bufSize == 0) + return; + + _mesa_get_program_resourceiv(shProg, programInterface, index, + propCount, props, bufSize, length, params); +} + +/** + * Function verifies syntax of given name for GetProgramResourceLocation + * and GetProgramResourceLocationIndex for the following cases: + * + * "array element portion of a string passed to GetProgramResourceLocation + * or GetProgramResourceLocationIndex must not have, a "+" sign, extra + * leading zeroes, or whitespace". + * + * Check is written to be compatible with GL_ARB_array_of_arrays. + */ +static bool +invalid_array_element_syntax(const GLchar *name) +{ + char *first = strchr(name, '['); + char *last = strrchr(name, '['); + + if (!first) + return false; + + /* No '+' or ' ' allowed anywhere. */ + if (strchr(first, '+') || strchr(first, ' ')) + return true; + + /* Check that last array index is 0. */ + if (last[1] == '0' && last[2] != ']') + return true; + + return false; +} + +static struct gl_shader_program * +lookup_linked_program(GLuint program, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *prog = + _mesa_lookup_shader_program_err(ctx, program, caller); + + if (!prog) + return NULL; + + if (prog->LinkStatus == GL_FALSE) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", + caller); + return NULL; + } + return prog; +} + +GLint GLAPIENTRY +_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + lookup_linked_program(program, "glGetProgramResourceLocation"); + + if (!shProg || !name || invalid_array_element_syntax(name)) + return -1; + + /* Validate programInterface. */ + switch (programInterface) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + break; + + /* For reference valid cases requiring additional extension support: + * GL_ARB_shader_subroutine + * GL_ARB_tessellation_shader + * GL_ARB_compute_shader + */ + case GL_VERTEX_SUBROUTINE_UNIFORM: + case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: + case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: + case GL_GEOMETRY_SUBROUTINE_UNIFORM: + case GL_FRAGMENT_SUBROUTINE_UNIFORM: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)", + _mesa_lookup_enum_by_nr(programInterface), name); + } + + return _mesa_program_resource_location(shProg, programInterface, name); +} + +/** + * Returns output index for dual source blending. + */ +GLint GLAPIENTRY +_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, + const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + lookup_linked_program(program, "glGetProgramResourceLocationIndex"); + + if (!shProg || !name || invalid_array_element_syntax(name)) + return -1; + + /* From the GL_ARB_program_interface_query spec: + * + * "For GetProgramResourceLocationIndex, <programInterface> must be + * PROGRAM_OUTPUT." + */ + if (programInterface != GL_PROGRAM_OUTPUT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramResourceLocationIndex(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return -1; + } + + return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, + name); +} diff --git a/mesalib/src/mesa/main/program_resource.h b/mesalib/src/mesa/main/program_resource.h new file mode 100644 index 000000000..326ae1f93 --- /dev/null +++ b/mesalib/src/mesa/main/program_resource.h @@ -0,0 +1,58 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef PROGRAM_RESOURCE_H +#define PROGRAM_RESOURCE_H + +#include "glheader.h" + +extern void GLAPIENTRY +_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, + GLenum pname, GLint *params); + +extern GLuint GLAPIENTRY +_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, + const GLchar *name); + +extern void GLAPIENTRY +_mesa_GetProgramResourceName(GLuint program, GLenum programInterface, + GLuint index, GLsizei bufSize, GLsizei *length, + GLchar *name); + +extern void GLAPIENTRY +_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, + GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params); + +extern GLint GLAPIENTRY +_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, + const GLchar *name); + +extern GLint GLAPIENTRY +_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, + const GLchar *name); + +#endif diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index 9ecc7d3b5..12363de7b 100755 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -233,18 +233,22 @@ get_query_binding_point(struct gl_context *ctx, GLenum target, GLuint index) } } - -void GLAPIENTRY -_mesa_GenQueries(GLsizei n, GLuint *ids) +/** + * Create $n query objects and store them in *ids. Make them of type $target + * if dsa is set. Called from _mesa_GenQueries() and _mesa_CreateQueries(). + */ +static void +create_queries(struct gl_context *ctx, GLenum target, GLsizei n, GLuint *ids, + bool dsa) { + const char *func = dsa ? "glGenQueries" : "glCreateQueries"; GLuint first; - GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenQueries(%d)\n", n); + _mesa_debug(ctx, "%s(%d)\n", func, n); if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } @@ -255,8 +259,12 @@ _mesa_GenQueries(GLsizei n, GLuint *ids) struct gl_query_object *q = ctx->Driver.NewQueryObject(ctx, first + i); if (!q) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; + } else if (dsa) { + /* Do the equivalent of binding the buffer with a target */ + q->Target = target; + q->EverBound = GL_TRUE; } ids[i] = first + i; _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); @@ -264,6 +272,36 @@ _mesa_GenQueries(GLsizei n, GLuint *ids) } } +void GLAPIENTRY +_mesa_GenQueries(GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + create_queries(ctx, 0, n, ids, false); +} + +void GLAPIENTRY +_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (target) { + case GL_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + case GL_TIME_ELAPSED: + case GL_TIMESTAMP: + case GL_PRIMITIVES_GENERATED: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glCreateQueries(invalid target = %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + create_queries(ctx, target, n, ids, true); +} + void GLAPIENTRY _mesa_DeleteQueries(GLsizei n, const GLuint *ids) @@ -424,6 +462,18 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) } } + /* This possibly changes the target of a buffer allocated by + * CreateQueries. Issue 39) in the ARB_direct_state_access extension states + * the following: + * + * "CreateQueries adds a <target>, so strictly speaking the <target> + * command isn't needed for BeginQuery/EndQuery, but in the end, this also + * isn't a selector, so we decided not to change it." + * + * Updating the target of the query object should be acceptable, so let's + * do that. + */ + q->Target = target; q->Active = GL_TRUE; q->Result = 0; @@ -541,6 +591,18 @@ _mesa_QueryCounter(GLuint id, GLenum target) return; } + /* This possibly changes the target of a buffer allocated by + * CreateQueries. Issue 39) in the ARB_direct_state_access extension states + * the following: + * + * "CreateQueries adds a <target>, so strictly speaking the <target> + * command isn't needed for BeginQuery/EndQuery, but in the end, this also + * isn't a selector, so we decided not to change it." + * + * Updating the target of the query object should be acceptable, so let's + * do that. + */ + q->Target = target; q->Result = 0; q->Ready = GL_FALSE; @@ -710,8 +772,8 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -761,8 +823,8 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) } break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -801,8 +863,8 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -841,8 +903,8 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: - if (!q->Ready) - ctx->Driver.CheckQuery( ctx, q ); + if (!q->Ready) + ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; default: @@ -852,6 +914,45 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) } /** + * New with GL_ARB_query_buffer_object + */ +void GLAPIENTRY +_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectiv"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectuiv"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjecti64v"); +} + + +void GLAPIENTRY +_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectui64v"); +} + + +/** * Allocate/init the context state related to query objects. */ void diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h index 6cbcabd46..d1036fcce 100644 --- a/mesalib/src/mesa/main/queryobj.h +++ b/mesalib/src/mesa/main/queryobj.h @@ -51,6 +51,8 @@ _mesa_free_queryobj_data(struct gl_context *ctx); void GLAPIENTRY _mesa_GenQueries(GLsizei n, GLuint *ids); void GLAPIENTRY +_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids); +void GLAPIENTRY _mesa_DeleteQueries(GLsizei n, const GLuint *ids); GLboolean GLAPIENTRY _mesa_IsQuery(GLuint id); @@ -77,5 +79,17 @@ void GLAPIENTRY _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params); void GLAPIENTRY _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params); +void GLAPIENTRY +_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); +void GLAPIENTRY +_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname, + GLintptr offset); #endif /* QUERYOBJ_H */ diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index d66b0b5e8..a3aacc66a 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -181,19 +181,18 @@ _mesa_delete_sampler_object(struct gl_context *ctx, free(sampObj); } - -void GLAPIENTRY -_mesa_GenSamplers(GLsizei count, GLuint *samplers) +static void +create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, + const char *caller) { - GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenSamplers(%d)\n", count); + _mesa_debug(ctx, "%s(%d)\n", caller, count); if (count < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller); return; } @@ -211,6 +210,20 @@ _mesa_GenSamplers(GLsizei count, GLuint *samplers) } } +void GLAPIENTRY +_mesa_GenSamplers(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + create_samplers(ctx, count, samplers, "glGenSamplers"); +} + +void GLAPIENTRY +_mesa_CreateSamplers(GLsizei count, GLuint *samplers) +{ + GET_CURRENT_CONTEXT(ctx); + create_samplers(ctx, count, samplers, "glCreateSamplers"); +} + void GLAPIENTRY _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h index 1bb3193e4..7bea91114 100644 --- a/mesalib/src/mesa/main/samplerobj.h +++ b/mesalib/src/mesa/main/samplerobj.h @@ -32,6 +32,9 @@ extern "C" { #endif +#include "mtypes.h" + + struct dd_function_table; static inline struct gl_sampler_object * @@ -80,6 +83,8 @@ _mesa_init_sampler_object_functions(struct dd_function_table *driver); void GLAPIENTRY _mesa_GenSamplers(GLsizei count, GLuint *samplers); void GLAPIENTRY +_mesa_CreateSamplers(GLsizei count, GLuint *samplers); +void GLAPIENTRY _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers); GLboolean GLAPIENTRY _mesa_IsSampler(GLuint sampler); diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp index df9081b73..b5f1d082c 100644 --- a/mesalib/src/mesa/main/shader_query.cpp +++ b/mesalib/src/mesa/main/shader_query.cpp @@ -34,11 +34,33 @@ #include "shaderobj.h" #include "program/hash_table.h" #include "../glsl/program.h" +#include "uniforms.h" +#include "main/enums.h" extern "C" { #include "shaderapi.h" } +static GLint +program_resource_location(struct gl_shader_program *shProg, + struct gl_program_resource *res, const char *name); + +/** + * Declare convenience functions to return resource data in a given type. + * Warning! this is not type safe so be *very* careful when using these. + */ +#define DECL_RESOURCE_FUNC(name, type) \ +const type * RESOURCE_ ## name (gl_program_resource *res) { \ + assert(res->Data); \ + return (type *) res->Data; \ +} + +DECL_RESOURCE_FUNC(VAR, ir_variable); +DECL_RESOURCE_FUNC(UBO, gl_uniform_block); +DECL_RESOURCE_FUNC(UNI, gl_uniform_storage); +DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer); +DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info); + void GLAPIENTRY _mesa_BindAttribLocation(GLhandleARB program, GLuint index, const GLcharARB *name) @@ -129,45 +151,41 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index, return; } - exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; - unsigned current_index = 0; - - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - if (!is_active_attrib(var)) - continue; + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT, + desired_index); - if (current_index == desired_index) { - const char *var_name = var->name; + /* User asked for index that does not exist. */ + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); + return; + } - /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to - * consider gl_VertexIDMESA as gl_VertexID for purposes of checking - * active attributes. - */ - if (var->data.mode == ir_var_system_value && - var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { - var_name = "gl_VertexID"; - } + const ir_variable *const var = RESOURCE_VAR(res); - _mesa_copy_string(name, maxLength, length, var_name); + if (!is_active_attrib(var)) + return; - if (size) - *size = (var->type->is_array()) ? var->type->length : 1; + const char *var_name = var->name; - if (type) - *type = var->type->gl_type; + /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to + * consider gl_VertexIDMESA as gl_VertexID for purposes of checking + * active attributes. + */ + if (var->data.mode == ir_var_system_value && + var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { + var_name = "gl_VertexID"; + } - return; - } + _mesa_copy_string(name, maxLength, length, var_name); - current_index++; - } + if (size) + _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE, + size, "glGetActiveAttrib"); - /* If the loop did not return early, the caller must have asked for - * an index that did not exit. Set an error. - */ - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); + if (type) + _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE, + (GLint *) type, "glGetActiveAttrib"); } /* Locations associated with shader variables (array or non-array) can be @@ -252,31 +270,25 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name) if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - /* The extra check against VERT_ATTRIB_GENERIC0 is because - * glGetAttribLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - if (var == NULL - || var->data.mode != ir_var_shader_in - || var->data.location == -1 - || var->data.location < VERT_ATTRIB_GENERIC0) - continue; - - int index = get_matching_index(var, (const char *) name); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name); - if (index >= 0) - return var->data.location + index - VERT_ATTRIB_GENERIC0; - } + if (!res) + return -1; - return -1; + GLint loc = program_resource_location(shProg, res, name); + + /* The extra check against against 0 is made because of builtin-attribute + * locations that have offset applied. Function program_resource_location + * can return built-in attribute locations < 0 and glGetAttribLocation + * cannot be used on "conventional" attributes. + * + * From page 95 of the OpenGL 3.0 spec: + * + * "If name is not an active attribute, if name is a conventional + * attribute, or if an error occurs, -1 will be returned." + */ + return (loc >= 0) ? loc : -1; } @@ -416,29 +428,8 @@ _mesa_GetFragDataIndex(GLuint program, const GLchar *name) if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); - - /* The extra check against FRAG_RESULT_DATA0 is because - * glGetFragDataLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - if (var == NULL - || var->data.mode != ir_var_shader_out - || var->data.location == -1 - || var->data.location < FRAG_RESULT_DATA0) - continue; - - if (get_matching_index(var, (const char *) name) >= 0) - return var->data.index; - } - - return -1; + return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, + name); } GLint GLAPIENTRY @@ -472,29 +463,612 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) return -1; - exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; - foreach_in_list(ir_instruction, node, ir) { - const ir_variable *const var = node->as_variable(); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name); - /* The extra check against FRAG_RESULT_DATA0 is because - * glGetFragDataLocation cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: + if (!res) + return -1; + + GLint loc = program_resource_location(shProg, res, name); + + /* The extra check against against 0 is made because of builtin-attribute + * locations that have offset applied. Function program_resource_location + * can return built-in attribute locations < 0 and glGetFragDataLocation + * cannot be used on "conventional" attributes. + * + * From page 95 of the OpenGL 3.0 spec: + * + * "If name is not an active attribute, if name is a conventional + * attribute, or if an error occurs, -1 will be returned." + */ + return (loc >= 0) ? loc : -1; +} + +const char* +_mesa_program_resource_name(struct gl_program_resource *res) +{ + switch (res->Type) { + case GL_UNIFORM_BLOCK: + return RESOURCE_UBO(res)->Name; + case GL_TRANSFORM_FEEDBACK_VARYING: + return RESOURCE_XFB(res)->Name; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->name; + case GL_UNIFORM: + return RESOURCE_UNI(res)->name; + default: + assert(!"support for resource type not implemented"); + } + return NULL; +} + + +unsigned +_mesa_program_resource_array_size(struct gl_program_resource *res) +{ + switch (res->Type) { + case GL_TRANSFORM_FEEDBACK_VARYING: + return RESOURCE_XFB(res)->Size > 1 ? + RESOURCE_XFB(res)->Size : 0; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->data.max_array_access; + case GL_UNIFORM: + return RESOURCE_UNI(res)->array_elements; + case GL_ATOMIC_COUNTER_BUFFER: + case GL_UNIFORM_BLOCK: + return 0; + default: + assert(!"support for resource type not implemented"); + } + return 0; +} + +static int +array_index_of_resource(struct gl_program_resource *res, + const char *name) +{ + assert(res->Data); + + switch (res->Type) { + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + return get_matching_index(RESOURCE_VAR(res), name); + default: + assert(!"support for resource type not implemented"); + } +} + +/* Find a program resource with specific name in given interface. + */ +struct gl_program_resource * +_mesa_program_resource_find_name(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = shProg->ProgramResourceList; + for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) { + if (res->Type != programInterface) + continue; + + /* Resource basename. */ + const char *rname = _mesa_program_resource_name(res); + unsigned baselen = strlen(rname); + + switch (programInterface) { + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_UNIFORM_BLOCK: + case GL_UNIFORM: + if (strncmp(rname, name, baselen) == 0) { + /* Basename match, check if array or struct. */ + if (name[baselen] == '\0' || + name[baselen] == '[' || + name[baselen] == '.') { + return res; + } + } + break; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + if (array_index_of_resource(res, name) >= 0) + return res; + break; + default: + assert(!"not implemented for given interface"); + } + } + return NULL; +} + +static GLuint +calc_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res) +{ + unsigned i; + GLuint index = 0; + for (i = 0; i < shProg->NumProgramResourceList; i++) { + if (&shProg->ProgramResourceList[i] == res) + return index; + if (shProg->ProgramResourceList[i].Type == res->Type) + index++; + } + return GL_INVALID_INDEX; +} + +/** + * Calculate index for the given resource. + */ +GLuint +_mesa_program_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res) +{ + if (!res) + return GL_INVALID_INDEX; + + switch (res->Type) { + case GL_UNIFORM_BLOCK: + return RESOURCE_UBO(res)- shProg->UniformBlocks; + case GL_ATOMIC_COUNTER_BUFFER: + return RESOURCE_ATC(res) - shProg->AtomicBuffers; + case GL_TRANSFORM_FEEDBACK_VARYING: + default: + return calc_resource_index(shProg, res); + } +} + +/* Find a program resource with specific index in given interface. + */ +struct gl_program_resource * +_mesa_program_resource_find_index(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index) +{ + struct gl_program_resource *res = shProg->ProgramResourceList; + int idx = -1; + + for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) { + if (res->Type != programInterface) + continue; + + switch (res->Type) { + case GL_UNIFORM_BLOCK: + case GL_ATOMIC_COUNTER_BUFFER: + if (_mesa_program_resource_index(shProg, res) == index) + return res; + + case GL_TRANSFORM_FEEDBACK_VARYING: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM: + if (++idx == (int) index) + return res; + break; + default: + assert(!"not implemented for given interface"); + } + } + return NULL; +} + +/* Get full name of a program resource. + */ +bool +_mesa_get_program_resource_name(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei bufSize, GLsizei *length, + GLchar *name, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + + /* Find resource with given interface and index. */ + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, programInterface, index); + + /* The error INVALID_VALUE is generated if <index> is greater than + * or equal to the number of entries in the active resource list for + * <programInterface>. + */ + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index); + return false; + } + + if (bufSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize); + return false; + } + + GLsizei localLength; + + if (length == NULL) + length = &localLength; + + _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res)); + + /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 + * spec says: + * + * "If the active uniform is an array, the uniform name returned in + * name will always be the name of the uniform array appended with + * "[0]"." + * + * The same text also appears in the OpenGL 4.2 spec. It does not, + * however, appear in any previous spec. Previous specifications are + * ambiguous in this regard. However, either name can later be passed + * to glGetUniformLocation (and related APIs), so there shouldn't be any + * harm in always appending "[0]" to uniform array names. + * + * Geometry shader stage has different naming convention where the 'normal' + * condition is an array, therefore for variables referenced in geometry + * stage we do not add '[0]'. + * + * Note, that TCS outputs and TES inputs should not have index appended + * either. + */ + bool add_index = !(((programInterface == GL_PROGRAM_INPUT) && + res->StageReferences & (1 << MESA_SHADER_GEOMETRY))); + + if (add_index && _mesa_program_resource_array_size(res)) { + int i; + + /* The comparison is strange because *length does *NOT* include the + * terminating NUL, but maxLength does. + */ + for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++) + name[*length + i] = "[0]"[i]; + + name[*length + i] = '\0'; + *length += i; + } + return true; +} + +static GLint +program_resource_location(struct gl_shader_program *shProg, + struct gl_program_resource *res, const char *name) +{ + unsigned index, offset; + int array_index = -1; + + if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) { + array_index = array_index_of_resource(res, name); + if (array_index < 0) + return -1; + } + + /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these + * offsets are used internally to differentiate between built-in attributes + * and user-defined attributes. + */ + switch (res->Type) { + case GL_PROGRAM_INPUT: + return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0; + case GL_PROGRAM_OUTPUT: + return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0; + case GL_UNIFORM: + index = _mesa_get_uniform_location(shProg, name, &offset); + + if (index == GL_INVALID_INDEX) + return -1; + + /* From the GL_ARB_uniform_buffer_object spec: * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." + * "The value -1 will be returned if <name> does not correspond to an + * active uniform variable name in <program>, if <name> is associated + * with a named uniform block, or if <name> starts with the reserved + * prefix "gl_"." */ - if (var == NULL - || var->data.mode != ir_var_shader_out - || var->data.location == -1 - || var->data.location < FRAG_RESULT_DATA0) - continue; + if (RESOURCE_UNI(res)->block_index != -1 || + RESOURCE_UNI(res)->atomic_buffer_index != -1) + return -1; - int index = get_matching_index(var, (const char *) name); + /* location in remap table + array element offset */ + return RESOURCE_UNI(res)->remap_location + offset; - if (index >= 0) - return var->data.location + index - FRAG_RESULT_DATA0; + default: + return -1; } +} - return -1; +/** + * Function implements following location queries: + * glGetAttribLocation + * glGetFragDataLocation + * glGetUniformLocation + */ +GLint +_mesa_program_resource_location(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, programInterface, name); + + /* Resource not found. */ + if (!res) + return -1; + + return program_resource_location(shProg, res, name); +} + +/** + * Function implements following index queries: + * glGetFragDataIndex + */ +GLint +_mesa_program_resource_location_index(struct gl_shader_program *shProg, + GLenum programInterface, const char *name) +{ + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, programInterface, name); + + /* Non-existent variable or resource is not referenced by fragment stage. */ + if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT))) + return -1; + + return RESOURCE_VAR(res)->data.index; +} + +static uint8_t +stage_from_enum(GLenum ref) +{ + switch (ref) { + case GL_REFERENCED_BY_VERTEX_SHADER: + return MESA_SHADER_VERTEX; + case GL_REFERENCED_BY_GEOMETRY_SHADER: + return MESA_SHADER_GEOMETRY; + case GL_REFERENCED_BY_FRAGMENT_SHADER: + return MESA_SHADER_FRAGMENT; + default: + assert(!"shader stage not supported"); + return MESA_SHADER_STAGES; + } +} + +/** + * Check if resource is referenced by given 'referenced by' stage enum. + * ATC and UBO resources hold stage references of their own. + */ +static bool +is_resource_referenced(struct gl_shader_program *shProg, + struct gl_program_resource *res, + GLuint index, uint8_t stage) +{ + if (res->Type == GL_ATOMIC_COUNTER_BUFFER) + return RESOURCE_ATC(res)->StageReferences[stage]; + + if (res->Type == GL_UNIFORM_BLOCK) + return shProg->UniformBlockStageIndex[stage][index] != -1; + + return res->StageReferences & (1 << stage); +} + +static unsigned +get_buffer_property(struct gl_shader_program *shProg, + struct gl_program_resource *res, const GLenum prop, + GLint *val, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + if (res->Type != GL_UNIFORM_BLOCK && + res->Type != GL_ATOMIC_COUNTER_BUFFER) + goto invalid_operation; + + if (res->Type == GL_UNIFORM_BLOCK) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_UBO(res)->Binding; + return 1; + case GL_BUFFER_DATA_SIZE: + *val = RESOURCE_UBO(res)->UniformBufferSize; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = RESOURCE_UBO(res)->NumUniforms; + return 1; + case GL_ACTIVE_VARIABLES: + for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) { + const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName; + struct gl_program_resource *uni = + _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname); + *val++ = + _mesa_program_resource_index(shProg, uni); + } + return RESOURCE_UBO(res)->NumUniforms; + } + } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_ATC(res)->Binding; + return 1; + case GL_BUFFER_DATA_SIZE: + *val = RESOURCE_ATC(res)->MinimumSize; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = RESOURCE_ATC(res)->NumUniforms; + return 1; + case GL_ACTIVE_VARIABLES: + for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++) + *val++ = RESOURCE_ATC(res)->Uniforms[i]; + return RESOURCE_ATC(res)->NumUniforms; + } + } + assert(!"support for property type not implemented"); + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + + return 0; +} + +unsigned +_mesa_program_resource_prop(struct gl_shader_program *shProg, + struct gl_program_resource *res, GLuint index, + const GLenum prop, GLint *val, const char *caller) +{ + GET_CURRENT_CONTEXT(ctx); + +#define VALIDATE_TYPE(type)\ + if (res->Type != type)\ + goto invalid_operation; + + switch(prop) { + case GL_NAME_LENGTH: + if (res->Type == GL_ATOMIC_COUNTER_BUFFER) + goto invalid_operation; + /* Base name +3 if array '[0]' + terminator. */ + *val = strlen(_mesa_program_resource_name(res)) + + (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1; + return 1; + case GL_TYPE: + switch (res->Type) { + case GL_UNIFORM: + *val = RESOURCE_UNI(res)->type->gl_type; + return 1; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = RESOURCE_VAR(res)->type->gl_type; + return 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = RESOURCE_XFB(res)->Type; + return 1; + default: + goto invalid_operation; + } + case GL_ARRAY_SIZE: + switch (res->Type) { + case GL_UNIFORM: + *val = MAX2(RESOURCE_UNI(res)->array_elements, 1); + return 1; + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = MAX2(RESOURCE_VAR(res)->type->length, 1); + return 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = MAX2(RESOURCE_XFB(res)->Size, 1); + return 1; + default: + goto invalid_operation; + } + case GL_OFFSET: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->offset; + return 1; + case GL_BLOCK_INDEX: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->block_index; + return 1; + case GL_ARRAY_STRIDE: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->array_stride; + return 1; + case GL_MATRIX_STRIDE: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->matrix_stride; + return 1; + case GL_IS_ROW_MAJOR: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->row_major; + return 1; + case GL_ATOMIC_COUNTER_BUFFER_INDEX: + VALIDATE_TYPE(GL_UNIFORM); + *val = RESOURCE_UNI(res)->atomic_buffer_index; + return 1; + case GL_BUFFER_BINDING: + case GL_BUFFER_DATA_SIZE: + case GL_NUM_ACTIVE_VARIABLES: + case GL_ACTIVE_VARIABLES: + return get_buffer_property(shProg, res, prop, val, caller); + case GL_REFERENCED_BY_VERTEX_SHADER: + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_FRAGMENT_SHADER: + switch (res->Type) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_UNIFORM_BLOCK: + case GL_ATOMIC_COUNTER_BUFFER: + *val = is_resource_referenced(shProg, res, index, + stage_from_enum(prop)); + return 1; + default: + goto invalid_operation; + } + case GL_LOCATION: + switch (res->Type) { + case GL_UNIFORM: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + *val = program_resource_location(shProg, res, + _mesa_program_resource_name(res)); + return 1; + default: + goto invalid_operation; + } + case GL_LOCATION_INDEX: + if (res->Type != GL_PROGRAM_OUTPUT) + goto invalid_operation; + *val = RESOURCE_VAR(res)->data.index; + return 1; + + /* GL_ARB_tessellation_shader */ + case GL_IS_PER_PATCH: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + /* GL_ARB_compute_shader */ + case GL_REFERENCED_BY_COMPUTE_SHADER: + default: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + return 0; + } + +#undef VALIDATE_TYPE + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + return 0; +} + +extern void +_mesa_get_program_resourceiv(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, GLsizei propCount, + const GLenum *props, GLsizei bufSize, + GLsizei *length, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLint *val = (GLint *) params; + const GLenum *prop = props; + GLsizei amount = 0; + + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, programInterface, index); + + /* No such resource found or bufSize negative. */ + if (!res || bufSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramResourceiv(%s index %d bufSize %d)", + _mesa_lookup_enum_by_nr(programInterface), index, bufSize); + return; + } + + /* Write propCount values until error occurs or bufSize reached. */ + for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) { + int props_written = + _mesa_program_resource_prop(shProg, res, index, *prop, val, + "glGetProgramResourceiv"); + + /* Error happened. */ + if (props_written == 0) + return; + + amount += props_written; + } + + /* If <length> is not NULL, the actual number of integer values + * written to <params> will be written to <length>. + */ + if (length) + *length = amount; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 30716f5e3..77e2b8745 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -882,10 +882,9 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) sh->CompileStatus = GL_FALSE; } else { if (ctx->_Shader->Flags & GLSL_DUMP) { - fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_log("GLSL source for %s shader %d:\n", _mesa_shader_stage_to_string(sh->Stage), sh->Name); - fprintf(stderr, "%s\n", sh->Source); - fflush(stderr); + _mesa_log("%s\n", sh->Source); } /* this call will set the shader->CompileStatus field to indicate if @@ -899,27 +898,25 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (ctx->_Shader->Flags & GLSL_DUMP) { if (sh->CompileStatus) { - fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name); - _mesa_print_ir(stderr, sh->ir, NULL); - fprintf(stderr, "\n\n"); + _mesa_log("GLSL IR for shader %d:\n", sh->Name); + _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL); + _mesa_log("\n\n"); } else { - fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name); + _mesa_log("GLSL shader %d failed to compile.\n", sh->Name); } if (sh->InfoLog && sh->InfoLog[0] != 0) { - fprintf(stderr, "GLSL shader %d info log:\n", sh->Name); - fprintf(stderr, "%s\n", sh->InfoLog); + _mesa_log("GLSL shader %d info log:\n", sh->Name); + _mesa_log("%s\n", sh->InfoLog); } - fflush(stderr); } } if (!sh->CompileStatus) { if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) { - fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_log("GLSL source for %s shader %d:\n", _mesa_shader_stage_to_string(sh->Stage), sh->Name); - fprintf(stderr, "%s\n", sh->Source); - fprintf(stderr, "Info Log:\n%s\n", sh->InfoLog); - fflush(stderr); + _mesa_log("%s\n", sh->Source); + _mesa_log("Info Log:\n%s\n", sh->InfoLog); } if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) { diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 047d2562d..aba6d5d83 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -219,6 +219,51 @@ extern GLuint GLAPIENTRY _mesa_CreateShaderProgramv(GLenum type, GLsizei count, const GLchar* const *strings); +/* GL_ARB_program_resource_query */ +extern const char* +_mesa_program_resource_name(struct gl_program_resource *res); + +extern unsigned +_mesa_program_resource_array_size(struct gl_program_resource *res); + +extern GLuint +_mesa_program_resource_index(struct gl_shader_program *shProg, + struct gl_program_resource *res); + +extern struct gl_program_resource * +_mesa_program_resource_find_name(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern struct gl_program_resource * +_mesa_program_resource_find_index(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index); + +extern bool +_mesa_get_program_resource_name(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei bufSize, GLsizei *length, + GLchar *name, const char *caller); + +extern GLint +_mesa_program_resource_location(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern GLint +_mesa_program_resource_location_index(struct gl_shader_program *shProg, + GLenum programInterface, const char *name); + +extern unsigned +_mesa_program_resource_prop(struct gl_shader_program *shProg, + struct gl_program_resource *res, GLuint index, + const GLenum prop, GLint *val, const char *caller); + +extern void +_mesa_get_program_resourceiv(struct gl_shader_program *shProg, + GLenum programInterface, GLuint index, + GLsizei propCount, const GLenum *props, + GLsizei bufSize, GLsizei *length, + GLint *params); + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index d7620c8ef..e42896036 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -315,6 +315,12 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) ralloc_free(shProg->AtomicBuffers); shProg->AtomicBuffers = NULL; shProg->NumAtomicBuffers = 0; + + if (shProg->ProgramResourceList) { + ralloc_free(shProg->ProgramResourceList); + shProg->ProgramResourceList = NULL; + shProg->NumProgramResourceList = 0; + } } diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index dadfb3c8c..cc84c6148 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -269,28 +269,6 @@ update_program_constants(struct gl_context *ctx) -static void -update_viewport_matrix(struct gl_context *ctx) -{ - const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; - unsigned i; - - assert(depthMax > 0); - - /* Compute scale and bias values. This is really driver-specific - * and should be maintained elsewhere if at all. - * NOTE: RasterPos uses this. - */ - for (i = 0; i < ctx->Const.MaxViewports; i++) { - double scale[3], translate[3]; - - _mesa_get_viewport_xform(ctx, i, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, - scale, translate, depthMax); - } -} - - /** * Update the ctx->Polygon._FrontBit flag. */ @@ -407,9 +385,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & _NEW_PIXEL) _mesa_update_pixel( ctx, new_state ); - if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) - update_viewport_matrix(ctx); - if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) update_multisample( ctx ); @@ -507,7 +482,7 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx, ctx->FragmentProgram._TexEnvProgram) { ctx->NewState |= _NEW_VARYING_VP_INPUTS; } - /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/ + /*printf("%s %x\n", __func__, varying_inputs);*/ } } diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 00234d4cc..0fd1a3683 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -32,7 +32,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "context.h" #include "formats.h" #include "mtypes.h" diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c index 562359410..f06f04882 100644 --- a/mesalib/src/mesa/main/texcompress_fxt1.c +++ b/mesalib/src/mesa/main/texcompress_fxt1.c @@ -31,7 +31,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "image.h" #include "macros.h" #include "mipmap.h" diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index f40e4e6c0..66de1f17d 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -35,7 +35,6 @@ #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "image.h" #include "macros.h" #include "mipmap.h" diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 41d00d4e9..7ce3cb88e 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -29,13 +29,8 @@ * GL_EXT_texture_compression_s3tc support. */ -#ifndef USE_EXTERNAL_DXTN_LIB -#define USE_EXTERNAL_DXTN_LIB 1 -#endif - #include "glheader.h" #include "imports.h" -#include "colormac.h" #include "dlopen.h" #include "image.h" #include "macros.h" @@ -77,7 +72,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx ) { /* called during context initialization */ ctx->Mesa_DXTn = GL_FALSE; -#if USE_EXTERNAL_DXTN_LIB if (!dxtlibhandle) { dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0); if (!dxtlibhandle) { @@ -118,9 +112,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx ) if (dxtlibhandle) { ctx->Mesa_DXTn = GL_TRUE; } -#else - (void) ctx; -#endif } /** diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 1ef728660..b5d42d304 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -32,7 +32,6 @@ #include <stdbool.h> #include "main/glheader.h" #include "main/blend.h" -#include "main/colormac.h" #include "main/context.h" #include "main/enums.h" #include "main/formats.h" diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c index 0a7f983fb..1af9d47f0 100644 --- a/mesalib/src/mesa/main/texstate.c +++ b/mesalib/src/mesa/main/texstate.c @@ -31,8 +31,6 @@ #include <stdio.h> #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" -#include "colortab.h" #include "context.h" #include "enums.h" #include "macros.h" diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 7ad9d2b68..152520598 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -53,7 +53,6 @@ #include "glheader.h" #include "bufferobj.h" -#include "colormac.h" #include "format_pack.h" #include "format_utils.h" #include "image.h" diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index ce678c864..103011ce5 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -514,22 +514,24 @@ _mesa_EndTransformFeedback(void) * Helper used by BindBufferRange() and BindBufferBase(). */ static void -bind_buffer_range(struct gl_context *ctx, GLuint index, +bind_buffer_range(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, + GLuint index, struct gl_buffer_object *bufObj, - GLintptr offset, GLsizeiptr size) + GLintptr offset, GLsizeiptr size, + bool dsa) { - struct gl_transform_feedback_object *obj = - ctx->TransformFeedback.CurrentObject; - /* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because * transform feedback buffers can't be changed while transform feedback is * active. */ - /* The general binding point */ - _mesa_reference_buffer_object(ctx, - &ctx->TransformFeedback.CurrentBuffer, - bufObj); + if (!dsa) { + /* The general binding point */ + _mesa_reference_buffer_object(ctx, + &ctx->TransformFeedback.CurrentBuffer, + bufObj); + } /* The per-attribute binding point */ _mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size); @@ -539,75 +541,209 @@ bind_buffer_range(struct gl_context *ctx, GLuint index, /** * Specify a buffer object to receive transform feedback results. Plus, * specify the starting offset to place the results, and max size. - * Called from the glBindBufferRange() function. + * Called from the glBindBufferRange() and glTransformFeedbackBufferRange + * functions. */ void _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx, - GLuint index, - struct gl_buffer_object *bufObj, - GLintptr offset, - GLsizeiptr size) + struct gl_transform_feedback_object *obj, + GLuint index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + bool dsa) { - struct gl_transform_feedback_object *obj; + const char *gl_methd_name; + if (dsa) + gl_methd_name = "glTransformFeedbackBufferRange"; + else + gl_methd_name = "glBindBufferRange"; - obj = ctx->TransformFeedback.CurrentObject; if (obj->Active) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindBufferRange(transform feedback active)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(transform feedback active)", + gl_methd_name); return; } if (index >= ctx->Const.MaxTransformFeedbackBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated if index is greater than or equal to the number of binding + * points for transform feedback, as described in section 6.7.1." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)", + gl_methd_name, index); return; } if (size & 0x3) { - /* must a multiple of four */ - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size); + /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be a multiple of " + "four)", gl_methd_name, (int) size); return; } if (offset & 0x3) { - /* must be multiple of four */ - _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBufferRange(offset=%d)", (int) offset); + /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be a multiple " + "of four)", gl_methd_name, (int) offset); return; - } + } + + if (offset < 0) { + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated by BindBufferRange if offset is negative." + * + * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error + * is generated by TransformFeedbackBufferRange if offset is negative." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be >= 0)", + gl_methd_name, + (int) offset); + return; + } - bind_buffer_range(ctx, index, bufObj, offset, size); + if (size <= 0 && (dsa || bufObj != ctx->Shared->NullBufferObj)) { + /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is + * generated by BindBufferRange if buffer is non-zero and size is less + * than or equal to zero." + * + * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error + * is generated by TransformFeedbackBufferRange if size is less than or + * equal to zero." + */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be > 0)", + gl_methd_name, (int) size); + return; + } + + bind_buffer_range(ctx, obj, index, bufObj, offset, size, dsa); } /** * Specify a buffer object to receive transform feedback results. * As above, but start at offset = 0. - * Called from the glBindBufferBase() function. + * Called from the glBindBufferBase() and glTransformFeedbackBufferBase() + * functions. */ void _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, - GLuint index, - struct gl_buffer_object *bufObj) + struct gl_transform_feedback_object *obj, + GLuint index, + struct gl_buffer_object *bufObj, + bool dsa) { - struct gl_transform_feedback_object *obj; - - obj = ctx->TransformFeedback.CurrentObject; - if (obj->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindBufferBase(transform feedback active)"); + "%s(transform feedback active)", + dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase"); return; } if (index >= ctx->Const.MaxTransformFeedbackBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)", + dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase", + index); + return; + } + + bind_buffer_range(ctx, obj, index, bufObj, 0, 0, dsa); +} + +/** + * Wrapper around lookup_transform_feedback_object that throws + * GL_INVALID_OPERATION if id is not in the hash table. After calling + * _mesa_error, it returns NULL. + */ +static struct gl_transform_feedback_object * +lookup_transform_feedback_object_err(struct gl_context *ctx, + GLuint xfb, const char* func) +{ + struct gl_transform_feedback_object *obj; + + obj = _mesa_lookup_transform_feedback_object(ctx, xfb); + if (!obj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(xfb=%u: non-generated object name)", func, xfb); + } + + return obj; +} + +/** + * Wrapper around _mesa_lookup_bufferobj that throws GL_INVALID_VALUE if id + * is not in the hash table. Specialised version for the + * transform-feedback-related functions. After calling _mesa_error, it + * returns NULL. + */ +static struct gl_buffer_object * +lookup_transform_feedback_bufferobj_err(struct gl_context *ctx, + GLuint buffer, const char* func) +{ + struct gl_buffer_object *bufObj; + + /* OpenGL 4.5 core profile, 13.2, pdf page 444: buffer must be zero or the + * name of an existing buffer object. + */ + if (buffer == 0) { + bufObj = ctx->Shared->NullBufferObj; + } else { + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid buffer=%u)", func, + buffer); + } + } + + return bufObj; +} + +void GLAPIENTRY +_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_transform_feedback_object *obj; + struct gl_buffer_object *bufObj; + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glTransformFeedbackBufferBase"); + if(!obj) { + return; + } + + bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, + "glTransformFeedbackBufferBase"); + if(!bufObj) { return; } - bind_buffer_range(ctx, index, bufObj, 0, 0); + _mesa_bind_buffer_base_transform_feedback(ctx, obj, index, bufObj, true); } +void GLAPIENTRY +_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, + GLintptr offset, GLsizeiptr size) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_transform_feedback_object *obj; + struct gl_buffer_object *bufObj; + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glTransformFeedbackBufferRange"); + if(!obj) { + return; + } + + bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer, + "glTransformFeedbackBufferRange"); + if(!bufObj) { + return; + } + + _mesa_bind_buffer_range_transform_feedback(ctx, obj, index, bufObj, offset, + size, true); +} /** * Specify a buffer object to receive transform feedback results, plus the @@ -660,7 +796,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, return; } - bind_buffer_range(ctx, index, bufObj, offset, 0); + bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false); } @@ -784,7 +920,7 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei *size, GLenum *type, GLchar *name) { const struct gl_shader_program *shProg; - const struct gl_transform_feedback_info *linked_xfb_info; + struct gl_program_resource *res; GET_CURRENT_CONTEXT(ctx); shProg = _mesa_lookup_shader_program(ctx, program); @@ -794,22 +930,27 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, return; } - linked_xfb_info = &shProg->LinkedTransformFeedback; - if (index >= (GLuint) linked_xfb_info->NumVarying) { + res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg, + GL_TRANSFORM_FEEDBACK_VARYING, + index); + if (!res) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetTransformFeedbackVarying(index=%u)", index); return; } /* return the varying's name and length */ - _mesa_copy_string(name, bufSize, length, - linked_xfb_info->Varyings[index].Name); + _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res)); /* return the datatype and value's size (in datatype units) */ if (type) - *type = linked_xfb_info->Varyings[index].Type; + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_TYPE, (GLint*) type, + "glGetTransformFeedbackVarying"); if (size) - *size = linked_xfb_info->Varyings[index].Size; + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_ARRAY_SIZE, (GLint*) size, + "glGetTransformFeedbackVarying"); } @@ -817,6 +958,10 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, struct gl_transform_feedback_object * _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) { + /* OpenGL 4.5 core profile, 13.2 pdf page 444: "xfb must be zero, indicating + * the default transform feedback object, or the name of an existing + * transform feedback object." + */ if (name == 0) { return ctx->TransformFeedback.DefaultObject; } @@ -825,25 +970,24 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name) _mesa_HashLookup(ctx->TransformFeedback.Objects, name); } - -/** - * Create new transform feedback objects. Transform feedback objects - * encapsulate the state related to transform feedback to allow quickly - * switching state (and drawing the results, below). - * Part of GL_ARB_transform_feedback2. - */ -void GLAPIENTRY -_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) +static void +create_transform_feedbacks(struct gl_context *ctx, GLsizei n, GLuint *ids, + bool dsa) { GLuint first; - GET_CURRENT_CONTEXT(ctx); + const char* func; + + if (dsa) + func = "glCreateTransformFeedbacks"; + else + func = "glGenTransformFeedbacks"; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } - if (!names) + if (!ids) return; /* we don't need contiguous IDs, but this might be faster */ @@ -854,18 +998,56 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) struct gl_transform_feedback_object *obj = ctx->Driver.NewTransformFeedback(ctx, first + i); if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } - names[i] = first + i; + ids[i] = first + i; _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj); + if (dsa) { + /* this is normally done at bind time in the non-dsa case */ + obj->EverBound = GL_TRUE; + } } } else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); } } +/** + * Create new transform feedback objects. Transform feedback objects + * encapsulate the state related to transform feedback to allow quickly + * switching state (and drawing the results, below). + * Part of GL_ARB_transform_feedback2. + */ +void GLAPIENTRY +_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) +{ + GET_CURRENT_CONTEXT(ctx); + + /* GenTransformFeedbacks should just reserve the object names that a + * subsequent call to BindTransformFeedback should actively create. For + * the sake of simplicity, we reserve the names and create the objects + * straight away. + */ + + create_transform_feedbacks(ctx, n, names, false); +} + +/** + * Create new transform feedback objects. Transform feedback objects + * encapsulate the state related to transform feedback to allow quickly + * switching state (and drawing the results, below). + * Part of GL_ARB_direct_state_access. + */ +void GLAPIENTRY +_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names) +{ + GET_CURRENT_CONTEXT(ctx); + + create_transform_feedbacks(ctx, n, names, true); +} + /** * Is the given ID a transform feedback object? @@ -1026,3 +1208,89 @@ _mesa_ResumeTransformFeedback(void) assert(ctx->Driver.ResumeTransformFeedback); ctx->Driver.ResumeTransformFeedback(ctx, obj); } + +extern void GLAPIENTRY +_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbackiv"); + if(!obj) { + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_PAUSED: + *param = obj->Paused; + break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: + *param = obj->Active; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbackiv(pname=%i)", pname); + } +} + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, + GLint *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbacki_v"); + if(!obj) { + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbacki_v(index=%i)", index); + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *param = obj->BufferNames[index]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbacki_v(pname=%i)", pname); + } +} + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, + GLint64 *param) +{ + struct gl_transform_feedback_object *obj; + GET_CURRENT_CONTEXT(ctx); + + obj = lookup_transform_feedback_object_err(ctx, xfb, + "glGetTransformFeedbacki64_v"); + if(!obj) { + return; + } + + if (index >= ctx->Const.MaxTransformFeedbackBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetTransformFeedbacki64_v(index=%i)", index); + return; + } + + switch(pname) { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + *param = obj->Offset[index]; + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + *param = obj->RequestedSize[index]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTransformFeedbacki64_v(pname=%i)", pname); + } +} diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 87f4080e0..bb9729cdb 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -65,15 +65,18 @@ _mesa_EndTransformFeedback(void); extern void _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, GLuint index, struct gl_buffer_object *bufObj, GLintptr offset, - GLsizeiptr size); + GLsizeiptr size, bool dsa); extern void _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, GLuint index, - struct gl_buffer_object *bufObj); + struct gl_buffer_object *bufObj, + bool dsa); extern void GLAPIENTRY _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, @@ -102,6 +105,9 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name); extern void GLAPIENTRY _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names); +extern void GLAPIENTRY +_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names); + extern GLboolean GLAPIENTRY _mesa_IsTransformFeedback(GLuint name); @@ -141,4 +147,24 @@ _mesa_set_transform_feedback_binding(struct gl_context *ctx, tfObj->RequestedSize[index] = size; } +/*** GL_ARB_direct_state_access ***/ + +extern void GLAPIENTRY +_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer); + +extern void GLAPIENTRY +_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, + GLintptr offset, GLsizeiptr size); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, + GLint *param); + +extern void GLAPIENTRY +_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, + GLint64 *param); + #endif /* TRANSFORM_FEEDBACK_H */ diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 2ab5528c3..4e77b3284 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -46,6 +46,7 @@ _mesa_GetActiveUniform(GLuint program, GLuint index, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; + struct gl_program_resource *res; if (maxLength < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)"); @@ -56,26 +57,51 @@ _mesa_GetActiveUniform(GLuint program, GLuint index, if (!shProg) return; - if (index >= shProg->NumUserUniformStorage) { + res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg, + GL_UNIFORM, index); + + if (!res) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); return; } - const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index]; - - if (nameOut) { - _mesa_get_uniform_name(uni, maxLength, length, nameOut); - } - - if (size) { - /* array_elements is zero for non-arrays, but the API requires that 1 be - * returned. - */ - *size = MAX2(1, uni->array_elements); - } + if (nameOut) + _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength, + length, nameOut, "glGetActiveUniform"); + if (type) + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_TYPE, (GLint*) type, + "glGetActiveUniform"); + if (size) + _mesa_program_resource_prop((struct gl_shader_program *) shProg, + res, index, GL_ARRAY_SIZE, (GLint*) size, + "glGetActiveUniform"); +} - if (type) { - *type = uni->type->gl_type; +static GLenum +resource_prop_from_uniform_prop(GLenum uni_prop) +{ + switch (uni_prop) { + case GL_UNIFORM_TYPE: + return GL_TYPE; + case GL_UNIFORM_SIZE: + return GL_ARRAY_SIZE; + case GL_UNIFORM_NAME_LENGTH: + return GL_NAME_LENGTH; + case GL_UNIFORM_BLOCK_INDEX: + return GL_BLOCK_INDEX; + case GL_UNIFORM_OFFSET: + return GL_OFFSET; + case GL_UNIFORM_ARRAY_STRIDE: + return GL_ARRAY_STRIDE; + case GL_UNIFORM_MATRIX_STRIDE: + return GL_MATRIX_STRIDE; + case GL_UNIFORM_IS_ROW_MAJOR: + return GL_IS_ROW_MAJOR; + case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: + return GL_ATOMIC_COUNTER_BUFFER_INDEX; + default: + return 0; } } @@ -88,7 +114,8 @@ _mesa_GetActiveUniformsiv(GLuint program, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - GLsizei i; + struct gl_program_resource *res; + GLenum res_prop; if (uniformCount < 0) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -100,80 +127,21 @@ _mesa_GetActiveUniformsiv(GLuint program, if (!shProg) return; - for (i = 0; i < uniformCount; i++) { - GLuint index = uniformIndices[i]; + res_prop = resource_prop_from_uniform_prop(pname); - if (index >= shProg->NumUserUniformStorage) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); - return; + for (int i = 0; i < uniformCount; i++) { + res = _mesa_program_resource_find_index(shProg, GL_UNIFORM, + uniformIndices[i]); + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)"); + break; } - } - - for (i = 0; i < uniformCount; i++) { - GLuint index = uniformIndices[i]; - const struct gl_uniform_storage *uni = &shProg->UniformStorage[index]; - - switch (pname) { - case GL_UNIFORM_TYPE: - params[i] = uni->type->gl_type; - break; - - case GL_UNIFORM_SIZE: - /* array_elements is zero for non-arrays, but the API requires that 1 be - * returned. - */ - params[i] = MAX2(1, uni->array_elements); - break; - case GL_UNIFORM_NAME_LENGTH: - params[i] = strlen(uni->name) + 1; - - /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 - * spec says: - * - * "If the active uniform is an array, the uniform name returned - * in name will always be the name of the uniform array appended - * with "[0]"." - */ - if (uni->array_elements != 0) - params[i] += 3; - break; - - case GL_UNIFORM_BLOCK_INDEX: - params[i] = uni->block_index; - break; - - case GL_UNIFORM_OFFSET: - params[i] = uni->offset; - break; - - case GL_UNIFORM_ARRAY_STRIDE: - params[i] = uni->array_stride; - break; - - case GL_UNIFORM_MATRIX_STRIDE: - params[i] = uni->matrix_stride; - break; - - case GL_UNIFORM_IS_ROW_MAJOR: - params[i] = uni->row_major; - break; - - case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: - if (!ctx->Extensions.ARB_shader_atomic_counters) - goto invalid_enum; - params[i] = uni->atomic_buffer_index; + if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i], + res_prop, ¶ms[i], + "glGetActiveUniformsiv")) break; - - default: - goto invalid_enum; - } } - - return; - - invalid_enum: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); } static struct gl_uniform_storage * diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index fb1482f9c..5548d1d02 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -911,7 +911,6 @@ GLint GLAPIENTRY _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name) { struct gl_shader_program *shProg; - GLuint index, offset; GET_CURRENT_CONTEXT(ctx); @@ -931,23 +930,7 @@ _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name) return -1; } - index = _mesa_get_uniform_location(shProg, name, &offset); - if (index == GL_INVALID_INDEX) - return -1; - - /* From the GL_ARB_uniform_buffer_object spec: - * - * "The value -1 will be returned if <name> does not correspond to an - * active uniform variable name in <program>, if <name> is associated - * with a named uniform block, or if <name> starts with the reserved - * prefix "gl_"." - */ - if (shProg->UniformStorage[index].block_index != -1 || - shProg->UniformStorage[index].atomic_buffer_index != -1) - return -1; - - /* location in remap table + array element offset */ - return shProg->UniformStorage[index].remap_location + offset; + return _mesa_program_resource_location(shProg, GL_UNIFORM, name); } GLuint GLAPIENTRY @@ -955,7 +938,6 @@ _mesa_GetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) { GET_CURRENT_CONTEXT(ctx); - GLuint i; struct gl_shader_program *shProg; if (!ctx->Extensions.ARB_uniform_buffer_object) { @@ -968,12 +950,13 @@ _mesa_GetUniformBlockIndex(GLuint program, if (!shProg) return GL_INVALID_INDEX; - for (i = 0; i < shProg->NumUniformBlocks; i++) { - if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName)) - return i; - } + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_UNIFORM_BLOCK, + uniformBlockName); + if (!res) + return GL_INVALID_INDEX; - return GL_INVALID_INDEX; + return _mesa_program_resource_index(shProg, res); } void GLAPIENTRY @@ -1003,9 +986,9 @@ _mesa_GetUniformIndices(GLuint program, } for (i = 0; i < uniformCount; i++) { - unsigned offset; - uniformIndices[i] = _mesa_get_uniform_location(shProg, - uniformNames[i], &offset); + struct gl_program_resource *res = + _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i]); + uniformIndices[i] = _mesa_program_resource_index(shProg, res); } } @@ -1061,104 +1044,104 @@ _mesa_UniformBlockBinding(GLuint program, } } -void GLAPIENTRY -_mesa_GetActiveUniformBlockiv(GLuint program, - GLuint uniformBlockIndex, - GLenum pname, - GLint *params) + +/** + * Generic program resource property query. + */ +static void +mesa_bufferiv(struct gl_shader_program *shProg, GLenum type, + GLuint index, GLenum pname, GLint *params, const char *caller) { GET_CURRENT_CONTEXT(ctx); - struct gl_shader_program *shProg; - struct gl_uniform_block *block; - unsigned i; + struct gl_program_resource *res = + _mesa_program_resource_find_index(shProg, type, index); - if (!ctx->Extensions.ARB_uniform_buffer_object) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); + if (!res) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufferindex %d)", caller, index); return; } - shProg = _mesa_lookup_shader_program_err(ctx, program, - "glGetActiveUniformBlockiv"); - if (!shProg) - return; - - if (uniformBlockIndex >= shProg->NumUniformBlocks) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %u >= %u)", - uniformBlockIndex, shProg->NumUniformBlocks); - return; - } - - block = &shProg->UniformBlocks[uniformBlockIndex]; - switch (pname) { case GL_UNIFORM_BLOCK_BINDING: - params[0] = block->Binding; + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_BINDING, + params, caller); return; - case GL_UNIFORM_BLOCK_DATA_SIZE: - params[0] = block->UniformBufferSize; + case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: + _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_DATA_SIZE, + params, caller); return; - case GL_UNIFORM_BLOCK_NAME_LENGTH: - params[0] = strlen(block->Name) + 1; + _mesa_program_resource_prop(shProg, res, index, GL_NAME_LENGTH, + params, caller); return; - - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { - unsigned count = 0; - - for (i = 0; i < block->NumUniforms; i++) { - unsigned offset; - const int idx = - _mesa_get_uniform_location(shProg, - block->Uniforms[i].IndexName, - &offset); - if (idx != -1) - count++; - } - - params[0] = count; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: + _mesa_program_resource_prop(shProg, res, index, GL_NUM_ACTIVE_VARIABLES, + params, caller); return; - } - - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: { - unsigned count = 0; - - for (i = 0; i < block->NumUniforms; i++) { - unsigned offset; - const int idx = - _mesa_get_uniform_location(shProg, - block->Uniforms[i].IndexName, - &offset); - - if (idx != -1) - params[count++] = idx; - } + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: + _mesa_program_resource_prop(shProg, res, index, GL_ACTIVE_VARIABLES, + params, caller); return; - } - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_VERTEX_SHADER, params, + caller); return; - case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: - if (!_mesa_has_geometry_shaders(ctx)) - break; - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_GEOMETRY_SHADER, params, + caller); return; - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: + _mesa_program_resource_prop(shProg, res, index, + GL_REFERENCED_BY_FRAGMENT_SHADER, params, + caller); + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: + params[0] = GL_FALSE; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: + params[0] = GL_FALSE; return; - default: _mesa_error(ctx, GL_INVALID_ENUM, - "glGetActiveUniformBlockiv(pname 0x%x (%s))", - pname, _mesa_lookup_enum_by_nr(pname)); + "%s(pname 0x%x (%s))", caller, pname, + _mesa_lookup_enum_by_nr(pname)); return; } } + +void GLAPIENTRY +_mesa_GetActiveUniformBlockiv(GLuint program, + GLuint uniformBlockIndex, + GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg; + + if (!ctx->Extensions.ARB_uniform_buffer_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glGetActiveUniformBlockiv"); + if (!shProg) + return; + + mesa_bufferiv(shProg, GL_UNIFORM_BLOCK, uniformBlockIndex, pname, params, + "glGetActiveUniformBlockiv"); +} + void GLAPIENTRY _mesa_GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, @@ -1168,7 +1151,6 @@ _mesa_GetActiveUniformBlockName(GLuint program, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_uniform_block *block; if (!ctx->Extensions.ARB_uniform_buffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv"); @@ -1187,18 +1169,11 @@ _mesa_GetActiveUniformBlockName(GLuint program, if (!shProg) return; - if (uniformBlockIndex >= shProg->NumUniformBlocks) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveUniformBlockiv(block index %u >= %u)", - uniformBlockIndex, shProg->NumUniformBlocks); - return; - } - - block = &shProg->UniformBlocks[uniformBlockIndex]; - - if (uniformBlockName) { - _mesa_copy_string(uniformBlockName, bufSize, length, block->Name); - } + if (uniformBlockName) + _mesa_get_program_resource_name(shProg, GL_UNIFORM_BLOCK, + uniformBlockIndex, bufSize, length, + uniformBlockName, + "glGetActiveUniformBlockName"); } void GLAPIENTRY @@ -1226,54 +1201,8 @@ _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex, if (!shProg) return; - if (uniformIndex >= shProg->NumUserUniformStorage) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); - return; - } - - if (uniformName) { - _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex], - bufSize, length, uniformName); - } -} - -void -_mesa_get_uniform_name(const struct gl_uniform_storage *uni, - GLsizei maxLength, GLsizei *length, - GLchar *nameOut) -{ - GLsizei localLength; - - if (length == NULL) - length = &localLength; - - _mesa_copy_string(nameOut, maxLength, length, uni->name); - - /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0 - * spec says: - * - * "If the active uniform is an array, the uniform name returned in - * name will always be the name of the uniform array appended with - * "[0]"." - * - * The same text also appears in the OpenGL 4.2 spec. It does not, - * however, appear in any previous spec. Previous specifications are - * ambiguous in this regard. However, either name can later be passed - * to glGetUniformLocation (and related APIs), so there shouldn't be any - * harm in always appending "[0]" to uniform array names. - */ - if (uni->array_elements != 0) { - int i; - - /* The comparison is strange because *length does *NOT* include the - * terminating NUL, but maxLength does. - */ - for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++) - nameOut[*length + i] = "[0]"[i]; - - nameOut[*length + i] = '\0'; - *length += i; - } + _mesa_get_program_resource_name(shProg, GL_UNIFORM, uniformIndex, bufSize, + length, uniformName, "glGetActiveUniformName"); } void GLAPIENTRY @@ -1282,8 +1211,6 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_active_atomic_buffer *ab; - GLuint i; if (!ctx->Extensions.ARB_shader_atomic_counters) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1296,49 +1223,8 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, if (!shProg) return; - if (bufferIndex >= shProg->NumAtomicBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glGetActiveAtomicCounterBufferiv(bufferIndex)"); - return; - } - - ab = &shProg->AtomicBuffers[bufferIndex]; - - switch (pname) { - case GL_ATOMIC_COUNTER_BUFFER_BINDING: - params[0] = ab->Binding; - return; - case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: - params[0] = ab->MinimumSize; - return; - case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: - params[0] = ab->NumUniforms; - return; - case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: - for (i = 0; i < ab->NumUniforms; ++i) - params[i] = ab->Uniforms[i]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_VERTEX]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: - params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT]; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: - params[0] = GL_FALSE; - return; - case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: - params[0] = GL_FALSE; - return; - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))", - pname, _mesa_lookup_enum_by_nr(pname)); - return; - } + mesa_bufferiv(shProg, GL_ATOMIC_COUNTER_BUFFER, bufferIndex, pname, params, + "glGetActiveAtomicCounterBufferiv"); } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index 0e6113fe9..55fa2357e 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -398,11 +398,6 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *); extern const struct gl_program_parameter * get_uniform_parameter(struct gl_shader_program *shProg, GLint index); -extern void -_mesa_get_uniform_name(const struct gl_uniform_storage *uni, - GLsizei maxLength, GLsizei *length, - GLchar *nameOut); - struct gl_builtin_uniform_element { const char *field; int tokens[STATE_LENGTH]; diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index d8e22d438..5df5a2922 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -382,6 +382,7 @@ compute_version_es2(const struct gl_extensions *extensions) extensions->ARB_shader_texture_lod && extensions->ARB_texture_float && extensions->ARB_texture_rg && + extensions->ARB_depth_buffer_float && extensions->EXT_draw_buffers2 && /* extensions->ARB_framebuffer_object && */ extensions->EXT_framebuffer_sRGB && diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c index 0adce9c78..b27063031 100644 --- a/mesalib/src/mesa/main/viewport.c +++ b/mesalib/src/mesa/main/viewport.c @@ -40,8 +40,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx, GLfloat x, GLfloat y, GLfloat width, GLfloat height) { - double scale[3], translate[3]; - /* clamp width and height to the implementation dependent range */ width = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth); height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight); @@ -72,16 +70,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx, ctx->ViewportArray[idx].Y = y; ctx->ViewportArray[idx].Height = height; ctx->NewState |= _NEW_VIEWPORT; - -#if 1 - /* XXX remove this someday. Currently the DRI drivers rely on - * the WindowMap matrix being up to date in the driver's Viewport - * and DepthRange functions. - */ - _mesa_get_viewport_xform(ctx, idx, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap, - scale, translate, ctx->DrawBuffer->_DepthMaxF); -#endif } struct gl_viewport_inputs { @@ -140,8 +128,8 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height) /** - * Set new viewport parameters and update derived state (the _WindowMap - * matrix). Usually called from _mesa_Viewport(). + * Set new viewport parameters and update derived state. + * Usually called from _mesa_Viewport(). * * \param ctx GL context. * \param idx Index of the viewport to be updated. @@ -246,8 +234,6 @@ static void set_depth_range_no_notify(struct gl_context *ctx, unsigned idx, GLclampd nearval, GLclampd farval) { - double scale[3], translate[3]; - if (ctx->ViewportArray[idx].Near == nearval && ctx->ViewportArray[idx].Far == farval) return; @@ -255,16 +241,6 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx, ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0); ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0); ctx->NewState |= _NEW_VIEWPORT; - -#if 1 - /* XXX remove this someday. Currently the DRI drivers rely on - * the WindowMap matrix being up to date in the driver's Viewport - * and DepthRange functions. - */ - _mesa_get_viewport_xform(ctx, idx, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap, - scale, translate, ctx->DrawBuffer->_DepthMaxF); -#endif } void @@ -388,7 +364,6 @@ _mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval) */ void _mesa_init_viewport(struct gl_context *ctx) { - GLfloat depthMax = 65535.0F; /* sorf of arbitrary */ unsigned i; ctx->Transform.ClipOrigin = GL_LOWER_LEFT; @@ -398,8 +373,6 @@ void _mesa_init_viewport(struct gl_context *ctx) * so just initialize all of them. */ for (i = 0; i < MAX_VIEWPORTS; i++) { - double scale[3], translate[3]; - /* Viewport group */ ctx->ViewportArray[i].X = 0; ctx->ViewportArray[i].Y = 0; @@ -407,27 +380,10 @@ void _mesa_init_viewport(struct gl_context *ctx) ctx->ViewportArray[i].Height = 0; ctx->ViewportArray[i].Near = 0.0; ctx->ViewportArray[i].Far = 1.0; - _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap); - - _mesa_get_viewport_xform(ctx, i, scale, translate); - _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap, - scale, translate, depthMax); } } -/** - * Free the context viewport attribute group data. - * \param ctx the GL context. - */ -void _mesa_free_viewport_data(struct gl_context *ctx) -{ - unsigned i; - - for (i = 0; i < MAX_VIEWPORTS; i++) - _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap); -} - extern void GLAPIENTRY _mesa_ClipControl(GLenum origin, GLenum depth) { diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h index 426e194bd..899dc2d0b 100644 --- a/mesalib/src/mesa/main/viewport.h +++ b/mesalib/src/mesa/main/viewport.h @@ -68,9 +68,6 @@ extern void _mesa_init_viewport(struct gl_context *ctx); -extern void -_mesa_free_viewport_data(struct gl_context *ctx); - extern void GLAPIENTRY _mesa_ClipControl(GLenum origin, GLenum depth); diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 39790ec8e..3dcb53702 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -303,9 +303,6 @@ public: void emit_scalar(ir_instruction *ir, enum prog_opcode op, dst_reg dst, src_reg src0, src_reg src1); - void emit_scs(ir_instruction *ir, enum prog_opcode op, - dst_reg dst, const src_reg &src); - bool try_emit_mad(ir_expression *ir, int mul_operand); bool try_emit_mad_for_and_not(ir_expression *ir, @@ -479,101 +476,6 @@ ir_to_mesa_visitor::emit_scalar(ir_instruction *ir, enum prog_opcode op, emit_scalar(ir, op, dst, src0, undef); } -/** - * Emit an OPCODE_SCS instruction - * - * The \c SCS opcode functions a bit differently than the other Mesa (or - * ARB_fragment_program) opcodes. Instead of splatting its result across all - * four components of the destination, it writes one value to the \c x - * component and another value to the \c y component. - * - * \param ir IR instruction being processed - * \param op Either \c OPCODE_SIN or \c OPCODE_COS depending on which - * value is desired. - * \param dst Destination register - * \param src Source register - */ -void -ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op, - dst_reg dst, - const src_reg &src) -{ - /* Vertex programs cannot use the SCS opcode. - */ - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) { - emit_scalar(ir, op, dst, src); - return; - } - - const unsigned component = (op == OPCODE_SIN) ? 0 : 1; - const unsigned scs_mask = (1U << component); - int done_mask = ~dst.writemask; - src_reg tmp; - - assert(op == OPCODE_SIN || op == OPCODE_COS); - - /* If there are compnents in the destination that differ from the component - * that will be written by the SCS instrution, we'll need a temporary. - */ - if (scs_mask != unsigned(dst.writemask)) { - tmp = get_temp(glsl_type::vec4_type); - } - - for (unsigned i = 0; i < 4; i++) { - unsigned this_mask = (1U << i); - src_reg src0 = src; - - if ((done_mask & this_mask) != 0) - continue; - - /* The source swizzle specified which component of the source generates - * sine / cosine for the current component in the destination. The SCS - * instruction requires that this value be swizzle to the X component. - * Replace the current swizzle with a swizzle that puts the source in - * the X component. - */ - unsigned src0_swiz = GET_SWZ(src.swizzle, i); - - src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz, - src0_swiz, src0_swiz); - for (unsigned j = i + 1; j < 4; j++) { - /* If there is another enabled component in the destination that is - * derived from the same inputs, generate its value on this pass as - * well. - */ - if (!(done_mask & (1 << j)) && - GET_SWZ(src0.swizzle, j) == src0_swiz) { - this_mask |= (1 << j); - } - } - - if (this_mask != scs_mask) { - ir_to_mesa_instruction *inst; - dst_reg tmp_dst = dst_reg(tmp); - - /* Emit the SCS instruction. - */ - inst = emit(ir, OPCODE_SCS, tmp_dst, src0); - inst->dst.writemask = scs_mask; - - /* Move the result of the SCS instruction to the desired location in - * the destination. - */ - tmp.swizzle = MAKE_SWIZZLE4(component, component, - component, component); - inst = emit(ir, OPCODE_SCS, dst, tmp); - inst->dst.writemask = this_mask; - } else { - /* Emit the SCS instruction to write directly to the destination. - */ - ir_to_mesa_instruction *inst = emit(ir, OPCODE_SCS, dst, src0); - inst->dst.writemask = scs_mask; - } - - done_mask |= this_mask; - } -} - src_reg ir_to_mesa_visitor::src_reg_for_float(float val) { @@ -1122,12 +1024,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_cos: emit_scalar(ir, OPCODE_COS, result_dst, op[0]); break; - case ir_unop_sin_reduced: - emit_scs(ir, OPCODE_SIN, result_dst, op[0]); - break; - case ir_unop_cos_reduced: - emit_scs(ir, OPCODE_COS, result_dst, op[0]); - break; case ir_unop_dFdx: emit(ir, OPCODE_DDX, result_dst, op[0]); diff --git a/mesalib/src/mesa/program/prog_execute.c b/mesalib/src/mesa/program/prog_execute.c index dc4919ae8..16e8e340d 100644 --- a/mesalib/src/mesa/program/prog_execute.c +++ b/mesalib/src/mesa/program/prog_execute.c @@ -37,7 +37,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "prog_execute.h" #include "prog_instruction.h" diff --git a/mesalib/src/mesa/program/prog_instruction.h b/mesalib/src/mesa/program/prog_instruction.h index ab3acbc02..96da198f8 100644 --- a/mesalib/src/mesa/program/prog_instruction.h +++ b/mesalib/src/mesa/program/prog_instruction.h @@ -59,6 +59,8 @@ #define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3) #define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7) #define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1) +/** Determine if swz contains SWIZZLE_ZERO/ONE/NIL for any components. */ +#define HAS_EXTENDED_SWIZZLE(swz) (swz & 0x924) #define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) #define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X) diff --git a/mesalib/src/mesa/program/prog_parameter.c b/mesalib/src/mesa/program/prog_parameter.c index cdfe25145..53e9813e6 100644 --- a/mesalib/src/mesa/program/prog_parameter.c +++ b/mesalib/src/mesa/program/prog_parameter.c @@ -190,40 +190,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, /** - * Add a new named constant to the parameter list. - * This will be used when the program contains something like this: - * PARAM myVals = { 0, 1, 2, 3 }; - * - * \param paramList the parameter list - * \param name the name for the constant - * \param values four float values - * \return index/position of the new parameter in the parameter list - */ -GLint -_mesa_add_named_constant(struct gl_program_parameter_list *paramList, - const char *name, const gl_constant_value values[4], - GLuint size) -{ - /* first check if this is a duplicate constant */ - GLint pos; - for (pos = 0; pos < (GLint)paramList->NumParameters; pos++) { - const gl_constant_value *pvals = paramList->ParameterValues[pos]; - if (pvals[0].u == values[0].u && - pvals[1].u == values[1].u && - pvals[2].u == values[2].u && - pvals[3].u == values[3].u && - strcmp(paramList->Parameters[pos].Name, name) == 0) { - /* Same name and value is already in the param list - reuse it */ - return pos; - } - } - /* not found, add new parameter */ - return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, - size, GL_NONE, values, NULL); -} - - -/** * Add a new unnamed constant to the parameter list. This will be used * when a fragment/vertex program contains something like this: * MOV r, { 0, 1, 2, 3 }; @@ -303,28 +269,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, swizzleOut); } -#if 0 /* not used yet */ -/** - * Returns the number of 4-component registers needed to store a piece - * of GL state. For matrices this may be as many as 4 registers, - * everything else needs - * just 1 register. - */ -static GLuint -sizeof_state_reference(const GLint *stateTokens) -{ - if (stateTokens[0] == STATE_MATRIX) { - GLuint rows = stateTokens[4] - stateTokens[3] + 1; - assert(rows >= 1); - assert(rows <= 4); - return rows; - } - else { - return 1; - } -} -#endif - /** * Add a new state reference to the parameter list. @@ -365,22 +309,6 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList, /** - * Lookup a parameter value by name in the given parameter list. - * \return pointer to the float[4] values. - */ -gl_constant_value * -_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, - GLsizei nameLen, const char *name) -{ - GLint i = _mesa_lookup_parameter_index(paramList, nameLen, name); - if (i < 0) - return NULL; - else - return paramList->ParameterValues[i]; -} - - -/** * Given a program parameter name, find its position in the list of parameters. * \param paramList the parameter list to search * \param nameLen length of name (in chars). diff --git a/mesalib/src/mesa/program/prog_parameter.h b/mesalib/src/mesa/program/prog_parameter.h index 6b3b3c262..74a5fd918 100644 --- a/mesalib/src/mesa/program/prog_parameter.h +++ b/mesalib/src/mesa/program/prog_parameter.h @@ -120,11 +120,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, const gl_state_index state[STATE_LENGTH]); extern GLint -_mesa_add_named_constant(struct gl_program_parameter_list *paramList, - const char *name, const gl_constant_value values[4], - GLuint size); - -extern GLint _mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList, const gl_constant_value values[4], GLuint size, GLenum datatype, GLuint *swizzleOut); @@ -138,10 +133,6 @@ extern GLint _mesa_add_state_reference(struct gl_program_parameter_list *paramList, const gl_state_index stateTokens[STATE_LENGTH]); -extern gl_constant_value * -_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, - GLsizei nameLen, const char *name); - extern GLint _mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, GLsizei nameLen, const char *name); diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c new file mode 100644 index 000000000..c738f5073 --- /dev/null +++ b/mesalib/src/mesa/program/prog_to_nir.c @@ -0,0 +1,1096 @@ +/* + * Copyright © 2015 Intel Corporation + * Copyright © 2014-2015 Broadcom + * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "nir/nir.h" +#include "nir/nir_builder.h" +#include "glsl/list.h" +#include "main/imports.h" +#include "util/ralloc.h" + +#include "prog_to_nir.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" + +/** + * \file prog_to_nir.c + * + * A translator from Mesa IR (prog_instruction.h) to NIR. This is primarily + * intended to support ARB_vertex_program, ARB_fragment_program, and fixed-function + * vertex processing. Full GLSL support should use glsl_to_nir instead. + */ + +struct ptn_compile { + const struct gl_program *prog; + nir_builder build; + bool error; + + nir_variable *input_vars[VARYING_SLOT_MAX]; + nir_variable *output_vars[VARYING_SLOT_MAX]; + nir_register **output_regs; + nir_register **temp_regs; + + nir_register *addr_reg; +}; + +#define SWIZ(X, Y, Z, W) \ + (unsigned[4]){ SWIZZLE_##X, SWIZZLE_##Y, SWIZZLE_##Z, SWIZZLE_##W } +#define ptn_swizzle(b, src, x, y, z, w) nir_swizzle(b, src, SWIZ(x, y, z, w), 4, true) +#define ptn_channel(b, src, ch) nir_swizzle(b, src, SWIZ(ch, ch, ch, ch), 1, true) + +static nir_ssa_def * +ptn_src_for_dest(struct ptn_compile *c, nir_alu_dest *dest) +{ + nir_builder *b = &c->build; + + nir_alu_src src; + memset(&src, 0, sizeof(src)); + + if (dest->dest.is_ssa) + src.src = nir_src_for_ssa(&dest->dest.ssa); + else { + assert(!dest->dest.reg.indirect); + src.src = nir_src_for_reg(dest->dest.reg.reg); + src.src.reg.base_offset = dest->dest.reg.base_offset; + } + + for (int i = 0; i < 4; i++) + src.swizzle[i] = i; + + return nir_fmov_alu(b, src, 4); +} + +static nir_alu_dest +ptn_get_dest(struct ptn_compile *c, const struct prog_dst_register *prog_dst) +{ + nir_alu_dest dest; + + memset(&dest, 0, sizeof(dest)); + + switch (prog_dst->File) { + case PROGRAM_TEMPORARY: + dest.dest.reg.reg = c->temp_regs[prog_dst->Index]; + break; + case PROGRAM_OUTPUT: + dest.dest.reg.reg = c->output_regs[prog_dst->Index]; + break; + case PROGRAM_ADDRESS: + assert(prog_dst->Index == 0); + dest.dest.reg.reg = c->addr_reg; + break; + case PROGRAM_UNDEFINED: + break; + } + + dest.write_mask = prog_dst->WriteMask; + dest.saturate = false; + + assert(!prog_dst->RelAddr); + + return dest; +} + +/** + * Multiply the contents of the ADDR register by 4 to convert from the number + * of vec4s to the number of floating point components. + */ +static nir_ssa_def * +ptn_addr_reg_value(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + nir_alu_src src; + memset(&src, 0, sizeof(src)); + src.src = nir_src_for_reg(c->addr_reg); + + return nir_imul(b, nir_fmov_alu(b, src, 1), nir_imm_int(b, 4)); +} + +static nir_ssa_def * +ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src) +{ + nir_builder *b = &c->build; + nir_alu_src src; + + memset(&src, 0, sizeof(src)); + + switch (prog_src->File) { + case PROGRAM_UNDEFINED: + return nir_imm_float(b, 0.0); + case PROGRAM_TEMPORARY: + assert(!prog_src->RelAddr && prog_src->Index >= 0); + src.src.reg.reg = c->temp_regs[prog_src->Index]; + break; + case PROGRAM_INPUT: { + /* ARB_vertex_program doesn't allow relative addressing on vertex + * attributes; ARB_fragment_program has no relative addressing at all. + */ + assert(!prog_src->RelAddr); + + assert(prog_src->Index >= 0 && prog_src->Index < VARYING_SLOT_MAX); + + nir_intrinsic_instr *load = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var); + load->num_components = 4; + load->variables[0] = nir_deref_var_create(load, c->input_vars[prog_src->Index]); + + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src.src = nir_src_for_ssa(&load->dest.ssa); + break; + } + case PROGRAM_STATE_VAR: + case PROGRAM_CONSTANT: { + /* We actually want to look at the type in the Parameters list for this, + * because it lets us upload constant builtin uniforms as actual + * constants. + */ + struct gl_program_parameter_list *plist = c->prog->Parameters; + gl_register_file file = prog_src->RelAddr ? prog_src->File : + plist->Parameters[prog_src->Index].Type; + + switch (file) { + case PROGRAM_CONSTANT: + if ((c->prog->IndirectRegisterFiles & (1 << PROGRAM_CONSTANT)) == 0) { + float *v = (float *) plist->ParameterValues[prog_src->Index]; + src.src = nir_src_for_ssa(nir_imm_vec4(b, v[0], v[1], v[2], v[3])); + break; + } + /* FALLTHROUGH */ + case PROGRAM_STATE_VAR: { + nir_intrinsic_op load_op = + prog_src->RelAddr ? nir_intrinsic_load_uniform_indirect : + nir_intrinsic_load_uniform; + nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, load_op); + nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL); + load->num_components = 4; + + /* Multiply src->Index by 4 to scale from # of vec4s to components. */ + load->const_index[0] = 4 * prog_src->Index; + load->const_index[1] = 1; + + if (prog_src->RelAddr) { + nir_ssa_def *reladdr = ptn_addr_reg_value(c); + if (prog_src->Index < 0) { + /* This is a negative offset which should be added to the address + * register's value. + */ + reladdr = nir_iadd(b, reladdr, nir_imm_int(b, load->const_index[0])); + load->const_index[0] = 0; + } + load->src[0] = nir_src_for_ssa(reladdr); + } + + nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr); + + src.src = nir_src_for_ssa(&load->dest.ssa); + break; + } + default: + fprintf(stderr, "bad uniform src register file: %s (%d)\n", + _mesa_register_file_name(file), file); + abort(); + } + break; + } + default: + fprintf(stderr, "unknown src register file: %s (%d)\n", + _mesa_register_file_name(prog_src->File), prog_src->File); + abort(); + } + + nir_ssa_def *def; + if (!HAS_EXTENDED_SWIZZLE(prog_src->Swizzle)) { + for (int i = 0; i < 4; i++) + src.swizzle[i] = GET_SWZ(prog_src->Swizzle, i); + + def = nir_fmov_alu(b, src, 4); + } else { + nir_ssa_def *chans[4]; + for (int i = 0; i < 4; i++) { + int swizzle = GET_SWZ(prog_src->Swizzle, i); + if (swizzle == SWIZZLE_ZERO) { + chans[i] = nir_imm_float(b, 0.0); + } else if (swizzle == SWIZZLE_ONE) { + chans[i] = nir_imm_float(b, 1.0); + } else { + assert(swizzle != SWIZZLE_NIL); + nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov); + nir_ssa_dest_init(&mov->instr, &mov->dest.dest, 1, NULL); + mov->dest.write_mask = 0x1; + mov->src[0] = src; + mov->src[0].swizzle[0] = swizzle; + nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr); + + chans[i] = &mov->dest.dest.ssa; + } + } + def = nir_vec4(b, chans[0], chans[1], chans[2], chans[3]); + } + + if (prog_src->Abs) + def = nir_fabs(b, def); + + if (prog_src->Negate) + def = nir_fneg(b, def); + + return def; +} + +static void +ptn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src) +{ + unsigned num_srcs = nir_op_infos[op].num_inputs; + nir_alu_instr *instr = nir_alu_instr_create(b->shader, op); + unsigned i; + + for (i = 0; i < num_srcs; i++) + instr->src[i].src = nir_src_for_ssa(src[i]); + + instr->dest = dest; + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); +} + +static void +ptn_move_dest_masked(nir_builder *b, nir_alu_dest dest, + nir_ssa_def *def, unsigned write_mask) +{ + if (!(dest.write_mask & write_mask)) + return; + + nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov); + if (!mov) + return; + + mov->dest = dest; + mov->dest.write_mask &= write_mask; + mov->src[0].src = nir_src_for_ssa(def); + for (unsigned i = def->num_components; i < 4; i++) + mov->src[0].swizzle[i] = def->num_components - 1; + nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr); +} + +static void +ptn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def) +{ + ptn_move_dest_masked(b, dest, def, WRITEMASK_XYZW); +} + +static void +ptn_arl(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_f2i(b, nir_ffloor(b, src[0]))); +} + +/* EXP - Approximate Exponential Base 2 + * dst.x = 2^{\lfloor src.x\rfloor} + * dst.y = src.x - \lfloor src.x\rfloor + * dst.z = 2^{src.x} + * dst.w = 1.0 + */ +static void +ptn_exp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *srcx = ptn_channel(b, src[0], X); + + ptn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)), WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)), WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_fexp2(b, srcx), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/* LOG - Approximate Logarithm Base 2 + * dst.x = \lfloor\log_2{|src.x|}\rfloor + * dst.y = |src.x| * 2^{-\lfloor\log_2{|src.x|}\rfloor}} + * dst.z = \log_2{|src.x|} + * dst.w = 1.0 + */ +static void +ptn_log(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *abs_srcx = nir_fabs(b, ptn_channel(b, src[0], X)); + nir_ssa_def *log2 = nir_flog2(b, abs_srcx); + nir_ssa_def *floor_log2 = nir_ffloor(b, log2); + + ptn_move_dest_masked(b, dest, floor_log2, WRITEMASK_X); + ptn_move_dest_masked(b, dest, + nir_fmul(b, abs_srcx, + nir_fexp2(b, nir_fneg(b, floor_log2))), + WRITEMASK_Y); + ptn_move_dest_masked(b, dest, log2, WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/* DST - Distance Vector + * dst.x = 1.0 + * dst.y = src0.y \times src1.y + * dst.z = src0.z + * dst.w = src1.w + */ +static void +ptn_dst(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_fmov(b, src[0]), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_fmov(b, src[1]), WRITEMASK_W); +} + +/* LIT - Light Coefficients + * dst.x = 1.0 + * dst.y = max(src.x, 0.0) + * dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0 + * dst.w = 1.0 + */ +static void +ptn_lit(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_XW); + + ptn_move_dest_masked(b, dest, nir_fmax(b, ptn_channel(b, src[0], X), + nir_imm_float(b, 0.0)), WRITEMASK_Y); + + if (dest.write_mask & WRITEMASK_Z) { + nir_ssa_def *src0_y = ptn_channel(b, src[0], Y); + nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ptn_channel(b, src[0], W), + nir_imm_float(b, 128.0)), + nir_imm_float(b, -128.0)); + nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)), + wclamp); + + nir_ssa_def *z; + if (b->shader->options->native_integers) { + z = nir_bcsel(b, + nir_fge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)), + nir_imm_float(b, 0.0), + pow); + } else { + z = nir_fcsel(b, + nir_sge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)), + nir_imm_float(b, 0.0), + pow); + } + + ptn_move_dest_masked(b, dest, z, WRITEMASK_Z); + } +} + +/* SCS - Sine Cosine + * dst.x = \cos{src.x} + * dst.y = \sin{src.x} + * dst.z = 0.0 + * dst.w = 1.0 + */ +static void +ptn_scs(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, nir_fcos(b, ptn_channel(b, src[0], X)), + WRITEMASK_X); + ptn_move_dest_masked(b, dest, nir_fsin(b, ptn_channel(b, src[0], X)), + WRITEMASK_Y); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 0.0), WRITEMASK_Z); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +/** + * Emit SLT. For platforms with integers, prefer b2f(flt(...)). + */ +static void +ptn_slt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_flt(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_slt(b, src[0], src[1])); + } +} + +/** + * Emit SGE. For platforms with integers, prefer b2f(fge(...)). + */ +static void +ptn_sge(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_fge(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_sge(b, src[0], src[1])); + } +} + +static void +ptn_sle(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *commuted[] = { src[1], src[0] }; + ptn_sge(b, dest, commuted); +} + +static void +ptn_sgt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *commuted[] = { src[1], src[0] }; + ptn_slt(b, dest, commuted); +} + +/** + * Emit SEQ. For platforms with integers, prefer b2f(feq(...)). + */ +static void +ptn_seq(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_feq(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_seq(b, src[0], src[1])); + } +} + +/** + * Emit SNE. For platforms with integers, prefer b2f(fne(...)). + */ +static void +ptn_sne(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_b2f(b, nir_fne(b, src[0], src[1]))); + } else { + ptn_move_dest(b, dest, nir_sne(b, src[0], src[1])); + } +} + +static void +ptn_xpd(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest_masked(b, dest, + nir_fsub(b, + nir_fmul(b, + ptn_swizzle(b, src[0], Y, Z, X, X), + ptn_swizzle(b, src[1], Z, X, Y, X)), + nir_fmul(b, + ptn_swizzle(b, src[1], Y, Z, X, X), + ptn_swizzle(b, src[0], Z, X, Y, X))), + WRITEMASK_XYZ); + ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); +} + +static void +ptn_dp2(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot2(b, src[0], src[1])); +} + +static void +ptn_dp3(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot3(b, src[0], src[1])); +} + +static void +ptn_dp4(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_fdot4(b, src[0], src[1])); +} + +static void +ptn_dph(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *dp3 = nir_fdot3(b, src[0], src[1]); + ptn_move_dest(b, dest, nir_fadd(b, dp3, ptn_channel(b, src[1], W))); +} + +static void +ptn_cmp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + if (b->shader->options->native_integers) { + ptn_move_dest(b, dest, nir_bcsel(b, + nir_flt(b, src[0], nir_imm_float(b, 0.0)), + src[1], src[2])); + } else { + ptn_move_dest(b, dest, nir_fcsel(b, + nir_slt(b, src[0], nir_imm_float(b, 0.0)), + src[1], src[2])); + } +} + +static void +ptn_lrp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + ptn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0])); +} + +static void +ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +{ + nir_ssa_def *cmp = b->shader->options->native_integers ? + nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0))) : + nir_fany4(b, nir_slt(b, src[0], nir_imm_float(b, 0.0))); + + nir_intrinsic_instr *discard = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if); + discard->src[0] = nir_src_for_ssa(cmp); + nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr); +} + +static void +ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src, + struct prog_instruction *prog_inst) +{ + nir_tex_instr *instr; + nir_texop op; + unsigned num_srcs; + + switch (prog_inst->Opcode) { + case OPCODE_TEX: + op = nir_texop_tex; + num_srcs = 1; + break; + case OPCODE_TXB: + op = nir_texop_txb; + num_srcs = 2; + break; + case OPCODE_TXD: + op = nir_texop_txd; + num_srcs = 3; + break; + case OPCODE_TXL: + op = nir_texop_txl; + num_srcs = 2; + break; + case OPCODE_TXP: + op = nir_texop_tex; + num_srcs = 2; + break; + case OPCODE_TXP_NV: + assert(!"not handled"); + op = nir_texop_tex; + num_srcs = 2; + break; + default: + fprintf(stderr, "unknown tex op %d\n", prog_inst->Opcode); + abort(); + } + + if (prog_inst->TexShadow) + num_srcs++; + + instr = nir_tex_instr_create(b->shader, num_srcs); + instr->op = op; + instr->dest_type = nir_type_float; + instr->is_shadow = prog_inst->TexShadow; + instr->sampler_index = prog_inst->TexSrcUnit; + + switch (prog_inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_1D; + break; + case TEXTURE_2D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_2D; + break; + case TEXTURE_3D_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_3D; + break; + case TEXTURE_CUBE_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE; + break; + case TEXTURE_RECT_INDEX: + instr->sampler_dim = GLSL_SAMPLER_DIM_RECT; + break; + default: + fprintf(stderr, "Unknown texture target %d\n", prog_inst->TexSrcTarget); + abort(); + } + + switch (instr->sampler_dim) { + case GLSL_SAMPLER_DIM_1D: + case GLSL_SAMPLER_DIM_BUF: + instr->coord_components = 1; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_EXTERNAL: + case GLSL_SAMPLER_DIM_MS: + instr->coord_components = 2; + break; + case GLSL_SAMPLER_DIM_3D: + case GLSL_SAMPLER_DIM_CUBE: + instr->coord_components = 3; + break; + } + + unsigned src_number = 0; + + instr->src[src_number].src = + nir_src_for_ssa(ptn_swizzle(b, src[0], X, Y, Z, W)); + instr->src[src_number].src_type = nir_tex_src_coord; + src_number++; + + if (prog_inst->Opcode == OPCODE_TXP) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_projector; + src_number++; + } + + if (prog_inst->Opcode == OPCODE_TXB) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_bias; + src_number++; + } + + if (prog_inst->Opcode == OPCODE_TXL) { + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + instr->src[src_number].src_type = nir_tex_src_lod; + src_number++; + } + + if (instr->is_shadow) { + if (instr->coord_components < 3) + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], Z)); + else + instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W)); + + instr->src[src_number].src_type = nir_tex_src_comparitor; + src_number++; + } + + assert(src_number == num_srcs); + + nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr); + + /* Resolve the writemask on the texture op. */ + ptn_move_dest(b, dest, &instr->dest.ssa); +} + +static const nir_op op_trans[MAX_OPCODE] = { + [OPCODE_NOP] = 0, + [OPCODE_ABS] = nir_op_fabs, + [OPCODE_ADD] = nir_op_fadd, + [OPCODE_ARL] = 0, + [OPCODE_CMP] = 0, + [OPCODE_COS] = nir_op_fcos, + [OPCODE_DDX] = nir_op_fddx, + [OPCODE_DDY] = nir_op_fddy, + [OPCODE_DP2] = 0, + [OPCODE_DP3] = 0, + [OPCODE_DP4] = 0, + [OPCODE_DPH] = 0, + [OPCODE_DST] = 0, + [OPCODE_END] = 0, + [OPCODE_EX2] = nir_op_fexp2, + [OPCODE_EXP] = nir_op_fexp, + [OPCODE_FLR] = nir_op_ffloor, + [OPCODE_FRC] = nir_op_ffract, + [OPCODE_LG2] = nir_op_flog2, + [OPCODE_LIT] = 0, + [OPCODE_LOG] = 0, + [OPCODE_LRP] = 0, + [OPCODE_MAD] = nir_op_ffma, + [OPCODE_MAX] = nir_op_fmax, + [OPCODE_MIN] = nir_op_fmin, + [OPCODE_MOV] = nir_op_fmov, + [OPCODE_MUL] = nir_op_fmul, + [OPCODE_POW] = nir_op_fpow, + [OPCODE_RCP] = nir_op_frcp, + + [OPCODE_RSQ] = nir_op_frsq, + [OPCODE_SCS] = 0, + [OPCODE_SEQ] = 0, + [OPCODE_SGE] = 0, + [OPCODE_SGT] = 0, + [OPCODE_SIN] = nir_op_fsin, + [OPCODE_SLE] = 0, + [OPCODE_SLT] = 0, + [OPCODE_SNE] = 0, + [OPCODE_SSG] = nir_op_fsign, + [OPCODE_SUB] = nir_op_fsub, + [OPCODE_SWZ] = 0, + [OPCODE_TEX] = 0, + [OPCODE_TRUNC] = nir_op_ftrunc, + [OPCODE_TXB] = 0, + [OPCODE_TXD] = 0, + [OPCODE_TXL] = 0, + [OPCODE_TXP] = 0, + [OPCODE_TXP_NV] = 0, + [OPCODE_XPD] = 0, +}; + +static void +ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst) +{ + nir_builder *b = &c->build; + unsigned i; + const unsigned op = prog_inst->Opcode; + + if (op == OPCODE_END) + return; + + nir_ssa_def *src[3]; + for (i = 0; i < 3; i++) { + src[i] = ptn_get_src(c, &prog_inst->SrcReg[i]); + } + nir_alu_dest dest = ptn_get_dest(c, &prog_inst->DstReg); + if (c->error) + return; + + switch (op) { + case OPCODE_RSQ: + ptn_move_dest(b, dest, nir_frsq(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_RCP: + ptn_move_dest(b, dest, nir_frcp(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_EX2: + ptn_move_dest(b, dest, nir_fexp2(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_LG2: + ptn_move_dest(b, dest, nir_flog2(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_POW: + ptn_move_dest(b, dest, nir_fpow(b, + ptn_channel(b, src[0], X), + ptn_channel(b, src[1], X))); + break; + + case OPCODE_COS: + ptn_move_dest(b, dest, nir_fcos(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_SIN: + ptn_move_dest(b, dest, nir_fsin(b, ptn_channel(b, src[0], X))); + break; + + case OPCODE_ARL: + ptn_arl(b, dest, src); + break; + + case OPCODE_EXP: + ptn_exp(b, dest, src); + break; + + case OPCODE_LOG: + ptn_log(b, dest, src); + break; + + case OPCODE_LRP: + ptn_lrp(b, dest, src); + break; + + case OPCODE_DST: + ptn_dst(b, dest, src); + break; + + case OPCODE_LIT: + ptn_lit(b, dest, src); + break; + + case OPCODE_XPD: + ptn_xpd(b, dest, src); + break; + + case OPCODE_DP2: + ptn_dp2(b, dest, src); + break; + + case OPCODE_DP3: + ptn_dp3(b, dest, src); + break; + + case OPCODE_DP4: + ptn_dp4(b, dest, src); + break; + + case OPCODE_DPH: + ptn_dph(b, dest, src); + break; + + case OPCODE_KIL: + ptn_kil(b, dest, src); + break; + + case OPCODE_CMP: + ptn_cmp(b, dest, src); + break; + + case OPCODE_SCS: + ptn_scs(b, dest, src); + break; + + case OPCODE_SLT: + ptn_slt(b, dest, src); + break; + + case OPCODE_SGT: + ptn_sgt(b, dest, src); + break; + + case OPCODE_SLE: + ptn_sle(b, dest, src); + break; + + case OPCODE_SGE: + ptn_sge(b, dest, src); + break; + + case OPCODE_SEQ: + ptn_seq(b, dest, src); + break; + + case OPCODE_SNE: + ptn_sne(b, dest, src); + break; + + case OPCODE_TEX: + case OPCODE_TXB: + case OPCODE_TXD: + case OPCODE_TXL: + case OPCODE_TXP: + case OPCODE_TXP_NV: + ptn_tex(b, dest, src, prog_inst); + break; + + case OPCODE_SWZ: + /* Extended swizzles were already handled in ptn_get_src(). */ + ptn_alu(b, nir_op_fmov, dest, src); + break; + + case OPCODE_NOP: + break; + + default: + if (op_trans[op] != 0 || op == OPCODE_MOV) { + ptn_alu(b, op_trans[op], dest, src); + } else { + fprintf(stderr, "unknown opcode: %s\n", _mesa_opcode_string(op)); + abort(); + } + break; + } + + if (prog_inst->SaturateMode) { + assert(prog_inst->SaturateMode == SATURATE_ZERO_ONE); + assert(!dest.dest.is_ssa); + ptn_move_dest(b, dest, nir_fsat(b, ptn_src_for_dest(c, &dest))); + } +} + +/** + * Puts a NIR intrinsic to store of each PROGRAM_OUTPUT value to the output + * variables at the end of the shader. + * + * We don't generate these incrementally as the PROGRAM_OUTPUT values are + * written, because there's no output load intrinsic, which means we couldn't + * handle writemasks. + */ +static void +ptn_add_output_stores(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + + foreach_list_typed(nir_variable, var, node, &b->shader->outputs) { + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var); + store->num_components = 4; + store->variables[0] = + nir_deref_var_create(store, c->output_vars[var->data.location]); + store->src[0].reg.reg = c->output_regs[var->data.location]; + nir_instr_insert_after_cf_list(c->build.cf_node_list, &store->instr); + } +} + +static void +setup_registers_and_variables(struct ptn_compile *c) +{ + nir_builder *b = &c->build; + struct nir_shader *shader = b->shader; + + /* Create input variables. */ + const int num_inputs = _mesa_flsll(c->prog->InputsRead); + for (int i = 0; i < num_inputs; i++) { + if (!(c->prog->InputsRead & BITFIELD64_BIT(i))) + continue; + nir_variable *var = rzalloc(shader, nir_variable); + var->type = glsl_vec4_type(); + var->data.read_only = true; + var->data.mode = nir_var_shader_in; + var->name = ralloc_asprintf(var, "in_%d", i); + var->data.location = i; + var->data.index = 0; + + if (c->prog->Target == GL_FRAGMENT_PROGRAM_ARB) { + struct gl_fragment_program *fp = + (struct gl_fragment_program *) c->prog; + + var->data.interpolation = fp->InterpQualifier[i]; + + if (i == VARYING_SLOT_POS) { + var->data.origin_upper_left = fp->OriginUpperLeft; + var->data.pixel_center_integer = fp->PixelCenterInteger; + } else if (i == VARYING_SLOT_FOGC) { + /* fogcoord is defined as <f, 0.0, 0.0, 1.0>. Make the actual + * input variable a float, and create a local containing the + * full vec4 value. + */ + var->type = glsl_float_type(); + + nir_intrinsic_instr *load_x = + nir_intrinsic_instr_create(shader, nir_intrinsic_load_var); + load_x->num_components = 1; + load_x->variables[0] = nir_deref_var_create(load_x, var); + nir_ssa_dest_init(&load_x->instr, &load_x->dest, 1, NULL); + nir_instr_insert_after_cf_list(b->cf_node_list, &load_x->instr); + + nir_ssa_def *f001 = nir_vec4(b, &load_x->dest.ssa, nir_imm_float(b, 0.0), + nir_imm_float(b, 0.0), nir_imm_float(b, 1.0)); + + nir_variable *fullvar = rzalloc(shader, nir_variable); + fullvar->type = glsl_vec4_type(); + fullvar->data.mode = nir_var_local; + fullvar->name = "fogcoord_tmp"; + exec_list_push_tail(&b->impl->locals, &fullvar->node); + + nir_intrinsic_instr *store = + nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); + store->num_components = 4; + store->variables[0] = nir_deref_var_create(store, fullvar); + store->src[0] = nir_src_for_ssa(f001); + nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr); + + /* Insert the real input into the list so the driver has real + * inputs, but set c->input_vars[i] to the temporary so we use + * the splatted value. + */ + exec_list_push_tail(&shader->inputs, &var->node); + c->input_vars[i] = fullvar; + continue; + } + } + + exec_list_push_tail(&shader->inputs, &var->node); + c->input_vars[i] = var; + } + + /* Create output registers and variables. */ + int max_outputs = _mesa_fls(c->prog->OutputsWritten); + c->output_regs = rzalloc_array(c, nir_register *, max_outputs); + + for (int i = 0; i < max_outputs; i++) { + if (!(c->prog->OutputsWritten & BITFIELD64_BIT(i))) + continue; + + /* Since we can't load from outputs in the IR, we make temporaries + * for the outputs and emit stores to the real outputs at the end of + * the shader. + */ + nir_register *reg = nir_local_reg_create(b->impl); + reg->num_components = 4; + + nir_variable *var = rzalloc(shader, nir_variable); + var->type = glsl_vec4_type(); + var->data.mode = nir_var_shader_out; + var->name = ralloc_asprintf(var, "out_%d", i); + + var->data.location = i; + var->data.index = 0; + + c->output_regs[i] = reg; + + exec_list_push_tail(&shader->outputs, &var->node); + c->output_vars[i] = var; + } + + /* Create temporary registers. */ + c->temp_regs = rzalloc_array(c, nir_register *, c->prog->NumTemporaries); + + nir_register *reg; + for (int i = 0; i < c->prog->NumTemporaries; i++) { + reg = nir_local_reg_create(b->impl); + if (!reg) { + c->error = true; + return; + } + reg->num_components = 4; + c->temp_regs[i] = reg; + } + + /* Create the address register (for ARB_vertex_program). */ + reg = nir_local_reg_create(b->impl); + if (!reg) { + c->error = true; + return; + } + reg->num_components = 1; + c->addr_reg = reg; + + /* Set the number of uniforms */ + shader->num_uniforms = 4 * c->prog->Parameters->NumParameters; +} + +struct nir_shader * +prog_to_nir(const struct gl_program *prog, const nir_shader_compiler_options *options) +{ + struct ptn_compile *c; + struct nir_shader *s; + + c = rzalloc(NULL, struct ptn_compile); + if (!c) + return NULL; + s = nir_shader_create(NULL, options); + if (!s) + goto fail; + c->prog = prog; + + nir_function *func = nir_function_create(s, "main"); + nir_function_overload *overload = nir_function_overload_create(func); + nir_function_impl *impl = nir_function_impl_create(overload); + + c->build.shader = s; + c->build.impl = impl; + c->build.cf_node_list = &impl->body; + + setup_registers_and_variables(c); + if (unlikely(c->error)) + goto fail; + + for (unsigned int i = 0; i < prog->NumInstructions; i++) { + ptn_emit_instruction(c, &prog->Instructions[i]); + + if (unlikely(c->error)) + break; + } + + ptn_add_output_stores(c); + +fail: + if (c->error) { + ralloc_free(s); + s = NULL; + } + ralloc_free(c); + return s; +} diff --git a/mesalib/src/mesa/program/prog_to_nir.h b/mesalib/src/mesa/program/prog_to_nir.h new file mode 100644 index 000000000..34e4cd104 --- /dev/null +++ b/mesalib/src/mesa/program/prog_to_nir.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#pragma once +#ifndef PROG_TO_NIR_H +#define PROG_TO_NIR_H +#ifdef __cplusplus +extern "C" { +#endif + +struct nir_shader *prog_to_nir(const struct gl_program *prog, + const nir_shader_compiler_options *options); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 3c214d5e3..4f28e2a3b 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -37,6 +37,7 @@ #include "prog_cache.h" #include "prog_parameter.h" #include "prog_instruction.h" +#include "util/ralloc.h" /** @@ -380,6 +381,10 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) _mesa_free_parameter_list(prog->Parameters); } + if (prog->nir) { + ralloc_free(prog->nir); + } + free(prog); } diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c index f0fe11ffa..428f2d9d7 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.c +++ b/mesalib/src/mesa/state_tracker/st_atom.c @@ -183,7 +183,7 @@ void st_validate_state( struct st_context *st ) if (state->st == 0) return; - /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/ + /*printf("%s %x/%x\n", __func__, state->mesa, state->st);*/ #ifdef DEBUG if (1) { diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c index 9b52f9779..d4fb8b862 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_array.c +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -598,7 +598,7 @@ static void update_array(struct st_context *st) const struct st_tracked_state st_update_array = { "st_update_array", /* name */ { /* dirty */ - 0, /* mesa */ + _NEW_CURRENT_ATTRIB, /* mesa */ ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */ }, update_array /* update */ diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c index 7984bf742..a54e0d9db 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c +++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c @@ -92,7 +92,7 @@ void st_upload_constants( struct st_context *st, if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", - __FUNCTION__, shader_type, params->NumParameters, + __func__, shader_type, params->NumParameters, params->StateFlags); _mesa_print_parameter_list(params); } diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c index 73768ed12..629f54f25 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_shader.c +++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c @@ -40,9 +40,8 @@ #include "program/program.h" #include "pipe/p_context.h" - +#include "pipe/p_shader_tokens.h" #include "util/u_simple_shaders.h" - #include "cso_cache/cso_context.h" #include "st_context.h" diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index dd81a6273..f10e9063a 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -247,7 +247,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) util_framebuffer_get_num_layers(&st->state.framebuffer); /* - printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, + printf("%s %s%s%s %f,%f %f,%f\n", __func__, color ? "color, " : "", depth ? "depth, " : "", stencil ? "stencil" : "", diff --git a/mesalib/src/mesa/state_tracker/st_cb_program.c b/mesalib/src/mesa/state_tracker/st_cb_program.c index aa301d830..c382d7d2c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_program.c +++ b/mesalib/src/mesa/state_tracker/st_cb_program.c @@ -41,6 +41,7 @@ #include "draw/draw_context.h" #include "st_context.h" +#include "st_debug.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" #include "st_cb_program.h" @@ -214,6 +215,9 @@ st_program_string_notify( struct gl_context *ctx, st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } + if (ST_DEBUG & DEBUG_PRECOMPILE) + st_precompile_shader_variant(st, prog); + /* XXX check if program is legal, within limits */ return GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 5c520b44f..bdf236e82 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -123,7 +123,7 @@ gl_target_to_pipe(GLenum target) static struct gl_texture_image * st_NewTextureImage(struct gl_context * ctx) { - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); (void) ctx; return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image); } @@ -144,7 +144,7 @@ st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) { struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object); - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); _mesa_initialize_texture_object(ctx, &obj->base, name, target); return &obj->base; @@ -172,7 +172,7 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, { struct st_texture_image *stImage = st_texture_image(texImage); - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); if (stImage->pt) { pipe_resource_reference(&stImage->pt, NULL); @@ -405,7 +405,7 @@ guess_and_alloc_texture(struct st_context *st, GLuint ptWidth, ptHeight, ptDepth, ptLayers; enum pipe_format fmt; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); assert(!stObj->pt); @@ -473,7 +473,7 @@ guess_and_alloc_texture(struct st_context *st, stObj->lastLevel = lastLevel; - DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); + DBG("%s returning %d\n", __func__, (stObj->pt != NULL)); return stObj->pt != NULL; } @@ -496,7 +496,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, GLuint height = texImage->Height; GLuint depth = texImage->Depth; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); assert(!stImage->pt); /* xxx this might be wrong */ @@ -738,6 +738,11 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, if (gl_target == GL_TEXTURE_CUBE_MAP) { gl_target = GL_TEXTURE_2D; } + /* TexSubImage can specify subsets of cube map array faces + * so we need to upload via 2D array instead */ + if (gl_target == GL_TEXTURE_CUBE_MAP_ARRAY) { + gl_target = GL_TEXTURE_2D_ARRAY; + } /* Initialize the source texture description. */ memset(&src_templ, 0, sizeof(src_templ)); @@ -1148,7 +1153,7 @@ st_GetTexImage(struct gl_context * ctx, } if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback format translation\n", __FUNCTION__); + debug_printf("%s: fallback format translation\n", __func__); dstMesaFormat = _mesa_format_from_format_and_type(format, type); dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type); @@ -1234,7 +1239,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, struct pipe_transfer *transfer; if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback processing\n", __FUNCTION__); + debug_printf("%s: fallback processing\n", __func__); if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcY = strb->Base.Height - srcY - height; @@ -1389,7 +1394,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); if (!strb || !strb->surface || !stImage->pt) { - debug_printf("%s: null strb or stImage\n", __FUNCTION__); + debug_printf("%s: null strb or stImage\n", __func__); return; } diff --git a/mesalib/src/mesa/state_tracker/st_debug.c b/mesalib/src/mesa/state_tracker/st_debug.c index de3e3a9cd..50891c112 100644 --- a/mesalib/src/mesa/state_tracker/st_debug.c +++ b/mesalib/src/mesa/state_tracker/st_debug.c @@ -56,6 +56,7 @@ static const struct debug_named_value st_debug_flags[] = { { "draw", DEBUG_DRAW, NULL }, { "buffer", DEBUG_BUFFER, NULL }, { "wf", DEBUG_WIREFRAME, NULL }, + { "precompile", DEBUG_PRECOMPILE, NULL }, DEBUG_NAMED_VALUE_END }; diff --git a/mesalib/src/mesa/state_tracker/st_debug.h b/mesalib/src/mesa/state_tracker/st_debug.h index cc8197836..288eccf9f 100644 --- a/mesalib/src/mesa/state_tracker/st_debug.h +++ b/mesalib/src/mesa/state_tracker/st_debug.h @@ -47,6 +47,7 @@ st_print_current(void); #define DEBUG_DRAW 0x100 #define DEBUG_BUFFER 0x200 #define DEBUG_WIREFRAME 0x400 +#define DEBUG_PRECOMPILE 0x800 #ifdef DEBUG extern int ST_DEBUG; diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index efee4b258..93671ba9c 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -30,40 +30,25 @@ * Translate GLSL IR to TGSI. */ -#include <stdio.h> -#include "main/compiler.h" -#include "ir.h" -#include "ir_visitor.h" -#include "ir_expression_flattening.h" -#include "glsl_types.h" +#include "st_glsl_to_tgsi.h" + #include "glsl_parser_extras.h" -#include "../glsl/program.h" #include "ir_optimization.h" -#include "ast.h" -#include "main/mtypes.h" +#include "main/errors.h" #include "main/shaderobj.h" #include "main/uniforms.h" #include "main/shaderapi.h" -#include "program/hash_table.h" #include "program/prog_instruction.h" -#include "program/prog_optimize.h" -#include "program/prog_print.h" -#include "program/program.h" -#include "program/prog_parameter.h" #include "program/sampler.h" -#include "pipe/p_compiler.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "pipe/p_shader_tokens.h" -#include "pipe/p_state.h" -#include "util/u_math.h" #include "tgsi/tgsi_ureg.h" #include "tgsi/tgsi_info.h" -#include "st_context.h" +#include "util/u_math.h" +#include "util/u_memory.h" #include "st_program.h" -#include "st_glsl_to_tgsi.h" #include "st_mesa_to_tgsi.h" @@ -328,6 +313,7 @@ public: int num_address_regs; int samplers_used; bool indirect_addr_consts; + int wpos_transform_const; int glsl_version; bool native_integers; @@ -441,9 +427,6 @@ public: void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0); - void emit_scs(ir_instruction *ir, unsigned op, - st_dst_reg dst, const st_src_reg &src); - bool try_emit_mad(ir_expression *ir, int mul_operand); bool try_emit_mad_for_and_not(ir_expression *ir, @@ -966,101 +949,6 @@ glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir, emit(NULL, op, dst, src0); } -/** - * Emit an TGSI_OPCODE_SCS instruction - * - * The \c SCS opcode functions a bit differently than the other TGSI opcodes. - * Instead of splatting its result across all four components of the - * destination, it writes one value to the \c x component and another value to - * the \c y component. - * - * \param ir IR instruction being processed - * \param op Either \c TGSI_OPCODE_SIN or \c TGSI_OPCODE_COS depending - * on which value is desired. - * \param dst Destination register - * \param src Source register - */ -void -glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op, - st_dst_reg dst, - const st_src_reg &src) -{ - /* Vertex programs cannot use the SCS opcode. - */ - if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) { - emit_scalar(ir, op, dst, src); - return; - } - - const unsigned component = (op == TGSI_OPCODE_SIN) ? 0 : 1; - const unsigned scs_mask = (1U << component); - int done_mask = ~dst.writemask; - st_src_reg tmp; - - assert(op == TGSI_OPCODE_SIN || op == TGSI_OPCODE_COS); - - /* If there are compnents in the destination that differ from the component - * that will be written by the SCS instrution, we'll need a temporary. - */ - if (scs_mask != unsigned(dst.writemask)) { - tmp = get_temp(glsl_type::vec4_type); - } - - for (unsigned i = 0; i < 4; i++) { - unsigned this_mask = (1U << i); - st_src_reg src0 = src; - - if ((done_mask & this_mask) != 0) - continue; - - /* The source swizzle specified which component of the source generates - * sine / cosine for the current component in the destination. The SCS - * instruction requires that this value be swizzle to the X component. - * Replace the current swizzle with a swizzle that puts the source in - * the X component. - */ - unsigned src0_swiz = GET_SWZ(src.swizzle, i); - - src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz, - src0_swiz, src0_swiz); - for (unsigned j = i + 1; j < 4; j++) { - /* If there is another enabled component in the destination that is - * derived from the same inputs, generate its value on this pass as - * well. - */ - if (!(done_mask & (1 << j)) && - GET_SWZ(src0.swizzle, j) == src0_swiz) { - this_mask |= (1 << j); - } - } - - if (this_mask != scs_mask) { - glsl_to_tgsi_instruction *inst; - st_dst_reg tmp_dst = st_dst_reg(tmp); - - /* Emit the SCS instruction. - */ - inst = emit(ir, TGSI_OPCODE_SCS, tmp_dst, src0); - inst->dst[0].writemask = scs_mask; - - /* Move the result of the SCS instruction to the desired location in - * the destination. - */ - tmp.swizzle = MAKE_SWIZZLE4(component, component, - component, component); - inst = emit(ir, TGSI_OPCODE_SCS, dst, tmp); - inst->dst[0].writemask = this_mask; - } else { - /* Emit the SCS instruction to write directly to the destination. - */ - glsl_to_tgsi_instruction *inst = emit(ir, TGSI_OPCODE_SCS, dst, src0); - inst->dst[0].writemask = scs_mask; - } - - done_mask |= this_mask; - } -} - int glsl_to_tgsi_visitor::add_constant(gl_register_file file, gl_constant_value values[8], int size, int datatype, @@ -1611,12 +1499,6 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) case ir_unop_cos: emit_scalar(ir, TGSI_OPCODE_COS, result_dst, op[0]); break; - case ir_unop_sin_reduced: - emit_scs(ir, TGSI_OPCODE_SIN, result_dst, op[0]); - break; - case ir_unop_cos_reduced: - emit_scs(ir, TGSI_OPCODE_COS, result_dst, op[0]); - break; case ir_unop_saturate: { glsl_to_tgsi_instruction *inst; inst = emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]); @@ -3134,7 +3016,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) break; case ir_query_levels: opcode = TGSI_OPCODE_TXQ; - lod_info = st_src_reg(PROGRAM_IMMEDIATE, 0, GLSL_TYPE_INT); + lod_info = undef_src; levels_src = get_temp(ir->type); break; case ir_txf: @@ -3456,6 +3338,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() num_address_regs = 0; samplers_used = 0; indirect_addr_consts = false; + wpos_transform_const = -1; glsl_version = 0; native_integers = false; mem_ctx = ralloc_context(NULL); @@ -3465,6 +3348,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() shader = NULL; options = NULL; have_sqrt = false; + have_fma = false; } glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor() @@ -3937,6 +3821,7 @@ glsl_to_tgsi_visitor::copy_propagate(void) inst->dst[0].index == inst->src[0].index) && !inst->dst[0].reladdr && !inst->saturate && + inst->src[0].file != PROGRAM_ARRAY && !inst->src[0].reladdr && !inst->src[0].reladdr2 && !inst->src[0].negate) { @@ -4464,7 +4349,9 @@ struct st_translate { struct ureg_dst arrays[MAX_ARRAYS]; struct ureg_src *constants; + int num_constants; struct ureg_src *immediates; + int num_immediates; struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst address[3]; @@ -4666,7 +4553,7 @@ src_register(struct st_translate *t, const st_src_reg *reg) { switch(reg->file) { case PROGRAM_UNDEFINED: - return ureg_src_undef(); + return ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_TEMPORARY: case PROGRAM_ARRAY: @@ -4674,17 +4561,18 @@ src_register(struct st_translate *t, const st_src_reg *reg) case PROGRAM_UNIFORM: assert(reg->index >= 0); - return t->constants[reg->index]; + return reg->index < t->num_constants ? + t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_STATE_VAR: case PROGRAM_CONSTANT: /* ie, immediate */ if (reg->has_index2) return ureg_src_register(TGSI_FILE_CONSTANT, reg->index); - else if (reg->index < 0) - return ureg_DECL_constant(t->ureg, 0); else - return t->constants[reg->index]; + return reg->index >= 0 && reg->index < t->num_constants ? + t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0); case PROGRAM_IMMEDIATE: + assert(reg->index >= 0 && reg->index < t->num_immediates); return t->immediates[reg->index]; case PROGRAM_INPUT: @@ -4805,6 +4693,7 @@ translate_tex_offset(struct st_translate *t, switch (in_offset->file) { case PROGRAM_IMMEDIATE: + assert(in_offset->index >= 0 && in_offset->index < t->num_immediates); imm_src = t->immediates[in_offset->index]; offset.File = imm_src.File; @@ -4867,10 +4756,8 @@ compile_tgsi_instruction(struct st_translate *t, inst->saturate, clamp_dst_color_output); - for (i = 0; i < num_src; i++) { - assert(inst->src[i].file != PROGRAM_UNDEFINED); + for (i = 0; i < num_src; i++) src[i] = translate_src(t, &inst->src[i]); - } switch(inst->op) { case TGSI_OPCODE_BGNLOOP: @@ -4939,28 +4826,19 @@ compile_tgsi_instruction(struct st_translate *t, */ static void emit_wpos_adjustment( struct st_translate *t, - const struct gl_program *program, + int wpos_transform_const, boolean invert, GLfloat adjX, GLfloat adjY[2]) { struct ureg_program *ureg = t->ureg; + assert(wpos_transform_const >= 0); + /* Fragment program uses fragment position input. * Need to replace instances of INPUT[WPOS] with temp T - * where T = INPUT[WPOS] by y is inverted. + * where T = INPUT[WPOS] is inverted by Y. */ - static const gl_state_index wposTransformState[STATE_LENGTH] - = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, - (gl_state_index)0, (gl_state_index)0, (gl_state_index)0 }; - - /* XXX: note we are modifying the incoming shader here! Need to - * do this before emitting the constant decls below, or this - * will be missed: - */ - unsigned wposTransConst = _mesa_add_state_reference(program->Parameters, - wposTransformState); - - struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst ); + struct ureg_src wpostrans = ureg_DECL_constant(ureg, wpos_transform_const); struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg ); struct ureg_src wpos_input = t->inputs[t->inputMapping[VARYING_SLOT_POS]]; @@ -5024,7 +4902,8 @@ static void emit_wpos(struct st_context *st, struct st_translate *t, const struct gl_program *program, - struct ureg_program *ureg) + struct ureg_program *ureg, + int wpos_transform_const) { const struct gl_fragment_program *fp = (const struct gl_fragment_program *) program; @@ -5121,7 +5000,7 @@ emit_wpos(struct st_context *st, /* we invert after adjustment so that we avoid the MOV to temporary, * and reuse the adjustment ADD instead */ - emit_wpos_adjustment(t, program, invert, adjX, adjY); + emit_wpos_adjustment(t, wpos_transform_const, invert, adjX, adjY); } /** @@ -5238,15 +5117,6 @@ st_translate_program( t->outputMapping = outputMapping; t->ureg = ureg; - if (program->shader_program) { - for (i = 0; i < program->shader_program->NumUserUniformStorage; i++) { - struct gl_uniform_storage *const storage = - &program->shader_program->UniformStorage[i]; - - _mesa_uniform_detach_all_driver_storage(storage); - } - } - /* * Declare input attributes. */ @@ -5260,10 +5130,9 @@ st_translate_program( } if (proginfo->InputsRead & VARYING_BIT_POS) { - /* Must do this after setting up t->inputs, and before - * emitting constant references, below: - */ - emit_wpos(st_context(ctx), t, proginfo, ureg); + /* Must do this after setting up t->inputs. */ + emit_wpos(st_context(ctx), t, proginfo, ureg, + program->wpos_transform_const); } if (proginfo->InputsRead & VARYING_BIT_FACE) @@ -5400,6 +5269,7 @@ st_translate_program( ret = PIPE_ERROR_OUT_OF_MEMORY; goto out; } + t->num_constants = proginfo->Parameters->NumParameters; for (i = 0; i < proginfo->Parameters->NumParameters; i++) { switch (proginfo->Parameters->Parameters[i].Type) { @@ -5451,6 +5321,8 @@ st_translate_program( ret = PIPE_ERROR_OUT_OF_MEMORY; goto out; } + t->num_immediates = program->num_immediates; + i = 0; foreach_in_list(immediate_storage, imm, &program->immediates) { assert(i < program->num_immediates); @@ -5479,33 +5351,21 @@ st_translate_program( t->insn[t->labels[i].branch_target]); } - if (program->shader_program) { - /* This has to be done last. Any operation the can cause - * prog->ParameterValues to get reallocated (e.g., anything that adds a - * program constant) has to happen before creating this linkage. - */ - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (program->shader_program->_LinkedShaders[i] == NULL) - continue; - - _mesa_associate_uniform_storage(ctx, program->shader_program, - program->shader_program->_LinkedShaders[i]->Program->Parameters); - } - } - out: if (t) { free(t->temps); free(t->insn); free(t->labels); free(t->constants); + t->num_constants = 0; free(t->immediates); + t->num_immediates = 0; if (t->error) { - debug_printf("%s: translate error flag set\n", __FUNCTION__); + debug_printf("%s: translate error flag set\n", __func__); } - free(t); + FREE(t); } return ret; @@ -5634,14 +5494,12 @@ get_mesa_program(struct gl_context *ctx, v->emit(NULL, TGSI_OPCODE_END); if (ctx->_Shader->Flags & GLSL_DUMP) { - printf("\n"); - printf("GLSL IR for linked %s program %d:\n", + _mesa_log("\n"); + _mesa_log("GLSL IR for linked %s program %d:\n", _mesa_shader_stage_to_string(shader->Stage), shader_program->Name); - _mesa_print_ir(stdout, shader->ir, NULL); - printf("\n"); - printf("\n"); - fflush(stdout); + _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL); + _mesa_log("\n\n"); } prog->Instructions = NULL; @@ -5650,6 +5508,17 @@ get_mesa_program(struct gl_context *ctx, do_set_program_inouts(shader->ir, prog, shader->Stage); count_resources(v, prog); + /* This must be done before the uniform storage is associated. */ + if (shader->Type == GL_FRAGMENT_SHADER && + prog->InputsRead & VARYING_BIT_POS){ + static const gl_state_index wposTransformState[STATE_LENGTH] = { + STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM + }; + + v->wpos_transform_const = _mesa_add_state_reference(prog->Parameters, + wposTransformState); + } + _mesa_reference_program(ctx, &shader->Program, prog); /* This has to be done last. Any operation the can cause diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h index 5ed640747..2cb80bcf9 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -22,17 +22,18 @@ * DEALINGS IN THE SOFTWARE. */ +#include "pipe/p_defines.h" +#include "main/mtypes.h" + #ifdef __cplusplus extern "C" { #endif -#include "main/glheader.h" -#include "tgsi/tgsi_ureg.h" - struct gl_context; struct gl_shader; struct gl_shader_program; struct glsl_to_tgsi_visitor; +struct ureg_program; enum pipe_error st_translate_program( struct gl_context *ctx, diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index 2f1016110..98d525c86 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -1249,7 +1249,7 @@ out: free(t->constants); if (t->error) { - debug_printf("%s: translate error flag set\n", __FUNCTION__); + debug_printf("%s: translate error flag set\n", __func__); } return ret; diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 4cfd817ce..d93b3c7bc 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -185,9 +185,6 @@ st_prepare_vertex_program(struct gl_context *ctx, if (stvp->Base.IsPositionInvariant) _mesa_insert_mvp_code(ctx, &stvp->Base); - if (!stvp->glsl_to_tgsi) - assert(stvp->Base.Base.NumInstructions > 1); - /* * Determine number of inputs, the mappings between VERT_ATTRIB_x * and TGSI generic input indexes, plus input attrib semantic info. @@ -403,7 +400,7 @@ st_translate_vertex_program(struct st_context *st, return vpv; fail: - debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__); + debug_printf("%s: failed to translate Mesa program:\n", __func__); _mesa_print_program(&stvp->Base.Base); debug_assert(0); @@ -1318,3 +1315,47 @@ st_print_current_vertex_program(void) } } } + + +/** + * Compile one shader variant. + */ +void +st_precompile_shader_variant(struct st_context *st, + struct gl_program *prog) +{ + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: { + struct st_vertex_program *p = (struct st_vertex_program *)prog; + struct st_vp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_vp_variant(st, p, &key); + break; + } + + case GL_GEOMETRY_PROGRAM_NV: { + struct st_geometry_program *p = (struct st_geometry_program *)prog; + struct st_gp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_gp_variant(st, p, &key); + break; + } + + case GL_FRAGMENT_PROGRAM_ARB: { + struct st_fragment_program *p = (struct st_fragment_program *)prog; + struct st_fp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st; + st_get_fp_variant(st, p, &key); + break; + } + + default: + assert(0); + } +} diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h index 451d7bb6a..b2c86faec 100644 --- a/mesalib/src/mesa/state_tracker/st_program.h +++ b/mesalib/src/mesa/state_tracker/st_program.h @@ -329,6 +329,9 @@ st_destroy_program_variants(struct st_context *st); extern void st_print_current_vertex_program(void); +extern void +st_precompile_shader_variant(struct st_context *st, + struct gl_program *prog); #ifdef __cplusplus } diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index ca7c83c21..6beb21e33 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -74,7 +74,7 @@ st_texture_create(struct st_context *st, if (target == PIPE_TEXTURE_CUBE) assert(layers == 6); - DBG("%s target %d format %s last_level %d\n", __FUNCTION__, + DBG("%s target %d format %s last_level %d\n", __func__, (int) target, util_format_name(format), last_level); assert(format); @@ -177,7 +177,7 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture, *widthOut = widthIn; *heightOut = heightIn; *depthOut = 1; - *layersOut = depthIn; + *layersOut = util_align_npot(depthIn, 6); break; default: assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()"); @@ -250,7 +250,7 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, GLuint level; void *map; - DBG("%s \n", __FUNCTION__); + DBG("%s \n", __func__); if (!stImage->pt) return NULL; @@ -304,7 +304,7 @@ st_texture_image_unmap(struct st_context *st, slice += stObj->base.MinLayer; transfer = &stImage->transfer[slice + stImage->base.Face].transfer; - DBG("%s\n", __FUNCTION__); + DBG("%s\n", __func__); pipe_transfer_unmap(pipe, *transfer); *transfer = NULL; diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c index 1d076cc7d..b51098704 100644 --- a/mesalib/src/mesa/swrast/s_aatriangle.c +++ b/mesalib/src/mesa/swrast/s_aatriangle.c @@ -30,7 +30,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/state.h" diff --git a/mesalib/src/mesa/swrast/s_alpha.c b/mesalib/src/mesa/swrast/s_alpha.c index b1a7ff132..841642fa9 100644 --- a/mesalib/src/mesa/swrast/s_alpha.c +++ b/mesalib/src/mesa/swrast/s_alpha.c @@ -29,7 +29,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_alpha.h" diff --git a/mesalib/src/mesa/swrast/s_atifragshader.c b/mesalib/src/mesa/swrast/s_atifragshader.c index 0bf03771f..9e029db25 100644 --- a/mesalib/src/mesa/swrast/s_atifragshader.c +++ b/mesalib/src/mesa/swrast/s_atifragshader.c @@ -20,7 +20,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/atifragshader.h" #include "main/samplerobj.h" diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index ecde292e3..af24207e5 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -27,7 +27,6 @@ #include "main/imports.h" #include "main/bufferobj.h" -#include "main/colormac.h" #include "main/mtypes.h" #include "main/samplerobj.h" #include "main/teximage.h" diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c index 17140ad2d..68c83e44e 100644 --- a/mesalib/src/mesa/swrast/s_copypix.c +++ b/mesalib/src/mesa/swrast/s_copypix.c @@ -25,7 +25,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/condrender.h" #include "main/macros.h" #include "main/pixeltransfer.h" diff --git a/mesalib/src/mesa/swrast/s_feedback.c b/mesalib/src/mesa/swrast/s_feedback.c index f25b89735..71f48ce92 100644 --- a/mesalib/src/mesa/swrast/s_feedback.c +++ b/mesalib/src/mesa/swrast/s_feedback.c @@ -23,7 +23,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/feedback.h" #include "main/macros.h" diff --git a/mesalib/src/mesa/swrast/s_fog.c b/mesalib/src/mesa/swrast/s_fog.c index e270b7e24..8b0bdf8fa 100644 --- a/mesalib/src/mesa/swrast/s_fog.c +++ b/mesalib/src/mesa/swrast/s_fog.c @@ -25,7 +25,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_context.h" diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c index 12bcda311..175915a5a 100644 --- a/mesalib/src/mesa/swrast/s_fragprog.c +++ b/mesalib/src/mesa/swrast/s_fragprog.c @@ -23,7 +23,7 @@ */ #include "main/glheader.h" -#include "main/colormac.h" +#include "main/macros.h" #include "main/samplerobj.h" #include "main/teximage.h" #include "program/prog_instruction.h" diff --git a/mesalib/src/mesa/swrast/s_lines.c b/mesalib/src/mesa/swrast/s_lines.c index 3e626b9e0..58bd2fc72 100644 --- a/mesalib/src/mesa/swrast/s_lines.c +++ b/mesalib/src/mesa/swrast/s_lines.c @@ -25,7 +25,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_aaline.h" #include "s_context.h" diff --git a/mesalib/src/mesa/swrast/s_linetemp.h b/mesalib/src/mesa/swrast/s_linetemp.h index 352c88428..035a1e640 100644 --- a/mesalib/src/mesa/swrast/s_linetemp.h +++ b/mesalib/src/mesa/swrast/s_linetemp.h @@ -106,7 +106,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) } /* - printf("%s():\n", __FUNCTION__); + printf("%s():\n", __func__); printf(" (%f, %f, %f) -> (%f, %f, %f)\n", vert0->attrib[VARYING_SLOT_POS][0], vert0->attrib[VARYING_SLOT_POS][1], @@ -154,7 +154,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) return; /* - printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy, + printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy, vert0->attrib[VARYING_SLOT_COL1][0], vert0->attrib[VARYING_SLOT_COL1][1], vert0->attrib[VARYING_SLOT_COL1][2], diff --git a/mesalib/src/mesa/swrast/s_points.c b/mesalib/src/mesa/swrast/s_points.c index 8180483ba..2212c95fa 100644 --- a/mesalib/src/mesa/swrast/s_points.c +++ b/mesalib/src/mesa/swrast/s_points.c @@ -24,7 +24,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "s_context.h" #include "s_feedback.h" diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index e304b6b5a..3db10e163 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -33,7 +33,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/format_pack.h" #include "main/format_unpack.h" #include "main/macros.h" @@ -1144,7 +1143,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) struct gl_framebuffer *fb = ctx->DrawBuffer; /* - printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, + printf("%s() interp 0x%x array 0x%x\n", __func__, span->interpMask, span->arrayMask); */ diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c index 58ff16465..0adb8e5ba 100644 --- a/mesalib/src/mesa/swrast/s_texcombine.c +++ b/mesalib/src/mesa/swrast/s_texcombine.c @@ -26,8 +26,8 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" +#include "main/macros.h" #include "main/pixeltransfer.h" #include "main/samplerobj.h" #include "program/prog_instruction.h" diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 3c4ee15ba..1fe21c0b4 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -33,7 +33,6 @@ */ -#include "main/colormac.h" #include "main/macros.h" #include "main/texcompress.h" #include "main/texcompress_fxt1.h" diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c index 3ade99519..abc1727cf 100644 --- a/mesalib/src/mesa/swrast/s_texfilter.c +++ b/mesalib/src/mesa/swrast/s_texfilter.c @@ -26,8 +26,8 @@ #include "c99_math.h" #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" +#include "main/macros.h" #include "main/samplerobj.h" #include "main/teximage.h" #include "main/texobj.h" diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c index 29bb270d6..fa853c919 100644 --- a/mesalib/src/mesa/swrast/s_texrender.c +++ b/mesalib/src/mesa/swrast/s_texrender.c @@ -1,6 +1,5 @@ #include "main/context.h" -#include "main/colormac.h" #include "main/fbobject.h" #include "main/macros.h" #include "main/teximage.h" diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c index af039c359..876a74b08 100644 --- a/mesalib/src/mesa/swrast/s_triangle.c +++ b/mesalib/src/mesa/swrast/s_triangle.c @@ -31,7 +31,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/swrast/s_tritemp.h b/mesalib/src/mesa/swrast/s_tritemp.h index fb73b2d59..fddbbfd99 100644 --- a/mesalib/src/mesa/swrast/s_tritemp.h +++ b/mesalib/src/mesa/swrast/s_tritemp.h @@ -92,7 +92,7 @@ #ifndef MAX_GLUINT -#define MAX_GLUINT 0xffffffff +#define MAX_GLUINT 0xffffffffu #endif @@ -156,7 +156,7 @@ static void NAME(struct gl_context *ctx, const SWvertex *v0, #endif /* - printf("%s()\n", __FUNCTION__); + printf("%s()\n", __func__); printf(" %g, %g, %g\n", v0->attrib[VARYING_SLOT_POS][0], v0->attrib[VARYING_SLOT_POS][1], diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c index ab22652c7..9879e2a5f 100644 --- a/mesalib/src/mesa/swrast/s_zoom.c +++ b/mesalib/src/mesa/swrast/s_zoom.c @@ -26,7 +26,6 @@ #include "main/macros.h" #include "main/imports.h" #include "main/format_pack.h" -#include "main/colormac.h" #include "s_context.h" #include "s_span.h" diff --git a/mesalib/src/mesa/swrast_setup/ss_context.c b/mesalib/src/mesa/swrast_setup/ss_context.c index 0b3b9e4df..74b1da342 100644 --- a/mesalib/src/mesa/swrast_setup/ss_context.c +++ b/mesalib/src/mesa/swrast_setup/ss_context.c @@ -27,7 +27,7 @@ #include "main/glheader.h" #include "main/imports.h" -#include "main/colormac.h" +#include "main/macros.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" @@ -167,7 +167,7 @@ setup_vertex_format(struct gl_context *ctx) EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize ); _tnl_install_attrs( ctx, map, e, - ctx->ViewportArray[0]._WindowMap.m, + tnl->_WindowMap.m, sizeof(SWvertex) ); swsetup->last_index_bitset = index_bitset; @@ -265,7 +265,8 @@ _swsetup_Wakeup( struct gl_context *ctx ) void _swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest ) { - const GLfloat *m = ctx->ViewportArray[0]._WindowMap.m; + TNLcontext *tnl = TNL_CONTEXT(ctx); + const GLfloat *m = tnl->_WindowMap.m; GLfloat tmp[4]; GLuint i; diff --git a/mesalib/src/mesa/swrast_setup/ss_triangle.c b/mesalib/src/mesa/swrast_setup/ss_triangle.c index 483c41592..b92c20be2 100644 --- a/mesalib/src/mesa/swrast_setup/ss_triangle.c +++ b/mesalib/src/mesa/swrast_setup/ss_triangle.c @@ -27,7 +27,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c index bc705d7a3..5b9dd54d7 100644 --- a/mesalib/src/mesa/tnl/t_context.c +++ b/mesalib/src/mesa/tnl/t_context.c @@ -35,6 +35,7 @@ #include "math/m_translate.h" #include "math/m_xform.h" #include "main/state.h" +#include "main/viewport.h" #include "tnl.h" #include "t_context.h" @@ -69,6 +70,8 @@ _tnl_CreateContext( struct gl_context *ctx ) _tnl_install_pipeline( ctx, _tnl_default_pipeline ); } + _math_matrix_ctr(&tnl->_WindowMap); + tnl->NeedNdcCoords = GL_TRUE; tnl->AllowVertexFog = GL_TRUE; tnl->AllowPixelFog = GL_TRUE; @@ -108,6 +111,8 @@ _tnl_DestroyContext( struct gl_context *ctx ) struct tnl_shine_tab *s, *tmps; TNLcontext *tnl = TNL_CONTEXT(ctx); + _math_matrix_dtr(&tnl->_WindowMap); + /* Free lighting shininess exponentiation table */ foreach_s( s, tmps, tnl->_ShineTabList ) { free( s ); @@ -182,6 +187,13 @@ _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state ) } } } + + if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) { + double scale[3], translate[3]; + _mesa_get_viewport_xform(ctx, 0, scale, translate); + _math_matrix_viewport(&tnl->_WindowMap, scale, translate, + ctx->DrawBuffer->_DepthMaxF); + } } diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h index e89a7f836..e7adb5f53 100644 --- a/mesalib/src/mesa/tnl/t_context.h +++ b/mesalib/src/mesa/tnl/t_context.h @@ -514,6 +514,7 @@ typedef struct /* Clipspace/ndc/window vertex managment: */ struct tnl_clipspace clipspace; + GLmatrix _WindowMap; /* Probably need a better configuration mechanism: */ diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index 60265d60b..6adf1dce6 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -448,7 +448,7 @@ void _tnl_draw_prims(struct gl_context *ctx, if (0) { - printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + printf("%s %d..%d\n", __func__, min_index, max_index); for (i = 0; i < nr_prims; i++) printf("prim %d: %s start %d count %d\n", i, _mesa_lookup_enum_by_nr(prim[i].mode), diff --git a/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c index 9ecf947df..d4b45bac9 100644 --- a/mesalib/src/mesa/tnl/t_rasterpos.c +++ b/mesalib/src/mesa/tnl/t_rasterpos.c @@ -25,12 +25,12 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/feedback.h" #include "main/light.h" #include "main/macros.h" #include "util/simple_list.h" #include "main/mtypes.h" +#include "main/viewport.h" #include "math/m_matrix.h" #include "tnl/tnl.h" @@ -378,6 +378,7 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]) GLfloat eye[4], clip[4], ndc[3], d; GLfloat *norm, eyenorm[3]; GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; + double scale[3], translate[3]; /* apply modelview matrix: eye = MV * obj */ TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj ); @@ -410,13 +411,10 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]) ndc[1] = clip[1] * d; ndc[2] = clip[2] * d; /* wincoord = viewport_mapping(ndc) */ - ctx->Current.RasterPos[0] = (ndc[0] * ctx->ViewportArray[0]._WindowMap.m[MAT_SX] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TX]); - ctx->Current.RasterPos[1] = (ndc[1] * ctx->ViewportArray[0]._WindowMap.m[MAT_SY] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TY]); - ctx->Current.RasterPos[2] = (ndc[2] * ctx->ViewportArray[0]._WindowMap.m[MAT_SZ] - + ctx->ViewportArray[0]._WindowMap.m[MAT_TZ]) - / ctx->DrawBuffer->_DepthMaxF; + _mesa_get_viewport_xform(ctx, 0, scale, translate); + ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0]; + ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1]; + ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2]; ctx->Current.RasterPos[3] = clip[3]; if (ctx->Transform.DepthClamp) { diff --git a/mesalib/src/mesa/tnl/t_vb_fog.c b/mesalib/src/mesa/tnl/t_vb_fog.c index 3626f1da3..1ca72f866 100644 --- a/mesalib/src/mesa/tnl/t_vb_fog.c +++ b/mesalib/src/mesa/tnl/t_vb_fog.c @@ -28,7 +28,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_light.c b/mesalib/src/mesa/tnl/t_vb_light.c index 7781b6a6c..dbd57fa6b 100644 --- a/mesalib/src/mesa/tnl/t_vb_light.c +++ b/mesalib/src/mesa/tnl/t_vb_light.c @@ -25,7 +25,6 @@ #include "c99_math.h" #include "main/glheader.h" -#include "main/colormac.h" #include "main/light.h" #include "main/macros.h" #include "main/imports.h" diff --git a/mesalib/src/mesa/tnl/t_vb_lighttmp.h b/mesalib/src/mesa/tnl/t_vb_lighttmp.h index 57f569bd7..f8786accb 100644 --- a/mesalib/src/mesa/tnl/t_vb_lighttmp.h +++ b/mesalib/src/mesa/tnl/t_vb_lighttmp.h @@ -68,7 +68,7 @@ static void TAG(light_rgba_spec)( struct gl_context *ctx, const GLuint nr = VB->Count; #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; @@ -249,7 +249,7 @@ static void TAG(light_rgba)( struct gl_context *ctx, const GLuint nr = VB->Count; #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; @@ -429,7 +429,7 @@ static void TAG(light_fast_rgba_single)( struct gl_context *ctx, #endif #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s\n", __func__ ); #endif (void) input; /* doesn't refer to Eye or Obj */ @@ -533,7 +533,7 @@ static void TAG(light_fast_rgba)( struct gl_context *ctx, const struct gl_light *light; #ifdef TRACE - fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); + fprintf(stderr, "%s %d\n", __func__, nr ); #endif (void) input; diff --git a/mesalib/src/mesa/tnl/t_vb_normals.c b/mesalib/src/mesa/tnl/t_vb_normals.c index b67789e42..9aee1a2fb 100644 --- a/mesalib/src/mesa/tnl/t_vb_normals.c +++ b/mesalib/src/mesa/tnl/t_vb_normals.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c index 464a4cddd..149434971 100644 --- a/mesalib/src/mesa/tnl/t_vb_program.c +++ b/mesalib/src/mesa/tnl/t_vb_program.c @@ -32,7 +32,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/samplerobj.h" diff --git a/mesalib/src/mesa/tnl/t_vb_texgen.c b/mesalib/src/mesa/tnl/t_vb_texgen.c index 9a61ef2fe..94066f4f6 100644 --- a/mesalib/src/mesa/tnl/t_vb_texgen.c +++ b/mesalib/src/mesa/tnl/t_vb_texgen.c @@ -35,7 +35,6 @@ */ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_texmat.c b/mesalib/src/mesa/tnl/t_vb_texmat.c index 1cc2c8116..ef034d643 100644 --- a/mesalib/src/mesa/tnl/t_vb_texmat.c +++ b/mesalib/src/mesa/tnl/t_vb_texmat.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c index ea3a56cd1..b56d6803c 100644 --- a/mesalib/src/mesa/tnl/t_vb_vertex.c +++ b/mesalib/src/mesa/tnl/t_vb_vertex.c @@ -27,7 +27,6 @@ #include "main/glheader.h" -#include "main/colormac.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c index 369d6d945..c3294b007 100644 --- a/mesalib/src/mesa/tnl/t_vertex.c +++ b/mesalib/src/mesa/tnl/t_vertex.c @@ -28,7 +28,6 @@ #include <stdio.h> #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "swrast/s_chan.h" #include "t_context.h" #include "t_vertex.h" diff --git a/mesalib/src/mesa/tnl/t_vertex_generic.c b/mesalib/src/mesa/tnl/t_vertex_generic.c index 079d473fc..2a25a9692 100644 --- a/mesalib/src/mesa/tnl/t_vertex_generic.c +++ b/mesalib/src/mesa/tnl/t_vertex_generic.c @@ -28,7 +28,7 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" +#include "main/macros.h" #include "util/simple_list.h" #include "swrast/s_chan.h" #include "t_context.h" @@ -36,7 +36,7 @@ #if 0 -#define DEBUG_INSERT printf("%s\n", __FUNCTION__) +#define DEBUG_INSERT printf("%s\n", __func__) #else #define DEBUG_INSERT #endif diff --git a/mesalib/src/mesa/tnl/t_vertex_sse.c b/mesalib/src/mesa/tnl/t_vertex_sse.c index 963432c48..30dc1a720 100644 --- a/mesalib/src/mesa/tnl/t_vertex_sse.c +++ b/mesalib/src/mesa/tnl/t_vertex_sse.c @@ -29,7 +29,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/colormac.h" #include "util/simple_list.h" #include "main/enums.h" #include "swrast/s_chan.h" diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 02741c2bc..859078f12 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -439,7 +439,7 @@ do { \ } while (0) -#define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ ) +#define ERROR(err) _mesa_error( ctx, err, __func__ ) #define TAG(x) vbo_##x #include "vbo_attrib_tmp.h" diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 91f2ca43a..37b53a830 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -45,7 +45,7 @@ vbo_exec_debug_verts( struct vbo_exec_context *exec ) GLuint i; printf("%s: %u vertices %d primitives, %d vertsize\n", - __FUNCTION__, + __func__, count, exec->vtx.prim_count, exec->vtx.vertex_size); @@ -402,7 +402,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) } if (0) - printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count, + printf("%s %d %d\n", __func__, exec->vtx.prim_count, exec->vtx.vert_count); vbo_context(ctx)->draw_prims( ctx, diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c index 562dedcd5..dafc4fd2a 100644 --- a/mesalib/src/mesa/vbo/vbo_primitive_restart.c +++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c @@ -167,6 +167,8 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct gl_buffer_object *indirect) { GLuint prim_num; + struct _mesa_prim new_prim; + struct _mesa_index_buffer new_ib; struct sub_primitive *sub_prims; struct sub_primitive *sub_prim; GLuint num_sub_prims; @@ -182,8 +184,6 @@ vbo_sw_primitive_restart(struct gl_context *ctx, /* If there is an indirect buffer, map it and extract the draw params */ if (indirect && prims[0].is_indirect) { - struct _mesa_prim new_prim = *prims; - struct _mesa_index_buffer new_ib = *ib; const uint32_t *indirect_params; if (!ctx->Driver.MapBufferRange(ctx, 0, indirect->Size, GL_MAP_READ_BIT, indirect, MAP_INTERNAL)) { @@ -195,6 +195,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, } assert(nr_prims == 1); + new_prim = prims[0]; indirect_params = (const uint32_t *) ADD_POINTERS(indirect->Mappings[MAP_INTERNAL].Pointer, new_prim.indirect_offset); @@ -206,6 +207,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, new_prim.basevertex = indirect_params[3]; new_prim.base_instance = indirect_params[4]; + new_ib = *ib; new_ib.count = new_prim.count; prims = &new_prim; diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c index b06df4ab2..c3c4b64e6 100644 --- a/mesalib/src/mesa/vbo/vbo_rebase.c +++ b/mesalib/src/mesa/vbo/vbo_rebase.c @@ -142,7 +142,7 @@ void vbo_rebase_prims( struct gl_context *ctx, assert(min_index != 0); if (0) - printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + printf("%s %d..%d\n", __func__, min_index, max_index); /* XXX this path is disabled for now. diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index fd9a5de3d..5927beeb3 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -763,7 +763,7 @@ _save_reset_vertex(struct gl_context *ctx) -#define ERROR(err) _mesa_compile_error(ctx, err, __FUNCTION__); +#define ERROR(err) _mesa_compile_error(ctx, err, __func__); /* Only one size for each attribute may be active at once. Eg. if diff --git a/mesalib/src/mesa/x86/common_x86.c b/mesalib/src/mesa/x86/common_x86.c index 86fbca91e..1c8640514 100644 --- a/mesalib/src/mesa/x86/common_x86.c +++ b/mesalib/src/mesa/x86/common_x86.c @@ -42,7 +42,7 @@ #include <sys/types.h> #include <sys/sysctl.h> #endif -#if defined(USE_SSE_ASM) && defined(__OpenBSD__) +#if defined(USE_SSE_ASM) && (defined(__OpenBSD__) || defined(__NetBSD__)) #include <sys/param.h> #include <sys/sysctl.h> #include <machine/cpu.h> diff --git a/mesalib/src/util/ralloc.c b/mesalib/src/util/ralloc.c index 36bc61fd0..01719c888 100644 --- a/mesalib/src/util/ralloc.c +++ b/mesalib/src/util/ralloc.c @@ -271,6 +271,32 @@ ralloc_steal(const void *new_ctx, void *ptr) add_child(parent, info); } +void +ralloc_adopt(const void *new_ctx, void *old_ctx) +{ + ralloc_header *new_info, *old_info, *child; + + if (unlikely(old_ctx == NULL)) + return; + + old_info = get_header(old_ctx); + new_info = get_header(new_ctx); + + /* If there are no children, bail. */ + if (unlikely(old_info->child == NULL)) + return; + + /* Set all the children's parent to new_ctx; get a pointer to the last child. */ + for (child = old_info->child; child->next != NULL; child = child->next) { + child->parent = new_info; + } + + /* Connect the two lists together; parent them to new_ctx; make old_ctx empty. */ + child->next = new_info->child; + new_info->child = old_info->child; + old_info->child = NULL; +} + void * ralloc_parent(const void *ptr) { diff --git a/mesalib/src/util/ralloc.h b/mesalib/src/util/ralloc.h index f088a3627..7587e1190 100644 --- a/mesalib/src/util/ralloc.h +++ b/mesalib/src/util/ralloc.h @@ -46,16 +46,16 @@ #ifndef RALLOC_H #define RALLOC_H -#ifdef __cplusplus -extern "C" { -#endif - #include <stddef.h> #include <stdarg.h> #include <stdbool.h> #include "macros.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * \def ralloc(ctx, type) * Allocate a new object chained off of the given context. @@ -235,6 +235,13 @@ void ralloc_free(void *ptr); void ralloc_steal(const void *new_ctx, void *ptr); /** + * Reparent all children from one context to another. + * + * This effectively calls ralloc_steal(new_ctx, child) for all children of \p old_ctx. + */ +void ralloc_adopt(const void *new_ctx, void *old_ctx); + +/** * Return the given pointer's ralloc context. */ void *ralloc_parent(const void *ptr); diff --git a/mesalib/src/util/u_atomic_test.c b/mesalib/src/util/u_atomic_test.c index 939cfe445..7844f6162 100644 --- a/mesalib/src/util/u_atomic_test.c +++ b/mesalib/src/util/u_atomic_test.c @@ -36,6 +36,11 @@ #include "u_atomic.h" +#ifdef _MSC_VER +#pragma warning( disable : 28112 ) /* Accessing a local variable via an Interlocked function */ +#pragma warning( disable : 28113 ) /* A variable which is accessed via an Interlocked function must always be accessed via an Interlocked function */ +#endif + /* Test only assignment-like operations, which are supported on all types */ #define test_atomic_assign(type, ones) \ |