bifrost_FILES := \
- bifrost/bifrost_compile.c \
- bifrost/bifrost_compile.h \
bifrost/bifrost.h \
- bifrost/bifrost_ops.h \
- bifrost/bifrost_opts.c \
- bifrost/bifrost_opts.h \
- bifrost/bifrost_print.c \
- bifrost/bifrost_print.h \
- bifrost/bifrost_sched.c \
- bifrost/bifrost_sched.h \
+ bifrost/bifrost_compile.h \
bifrost/cmdline.c \
- bifrost/compiler_defines.h \
bifrost/disassemble.c \
bifrost/disassemble.h
unsigned ctrl : 4;
};
+enum bifrost_branch_cond {
+ BR_COND_LT = 0,
+ BR_COND_LE = 1,
+ BR_COND_GE = 2,
+ BR_COND_GT = 3,
+ // Equal vs. not-equal determined by src0/src1 comparison
+ BR_COND_EQ = 4,
+ // floating-point comparisons
+ // Becomes UNE when you flip the arguments
+ BR_COND_OEQ = 5,
+ // TODO what happens when you flip the arguments?
+ BR_COND_OGT = 6,
+ BR_COND_OLT = 7,
+};
+
+enum bifrost_branch_code {
+ BR_ALWAYS = 63,
+};
+
#endif
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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 "compiler/nir/nir_builder.h"
-#include "bifrost_compile.h"
-#include "bifrost_opts.h"
-#include "bifrost_sched.h"
-#include "compiler_defines.h"
-#include "disassemble.h"
-#include "bifrost_print.h"
-
-#define BI_DEBUG
-
-static int
-glsl_type_size(const struct glsl_type *type, bool bindless)
-{
- return glsl_count_attribute_slots(type, false);
-}
-
-static void
-optimize_nir(nir_shader *nir)
-{
- bool progress;
-
- NIR_PASS_V(nir, nir_lower_io, nir_var_all, glsl_type_size, 0);
- NIR_PASS(progress, nir, nir_lower_regs_to_ssa);
-
- do {
- progress = false;
-
- NIR_PASS(progress, nir, nir_lower_io, nir_var_all, glsl_type_size, 0);
-
- NIR_PASS(progress, nir, nir_lower_var_copies);
- NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
-
- NIR_PASS(progress, nir, nir_copy_prop);
- NIR_PASS(progress, nir, nir_opt_constant_folding);
-
- NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
- NIR_PASS(progress, nir, nir_lower_alu_to_scalar, NULL, NULL);
- NIR_PASS(progress, nir, nir_opt_if, true);
-
- } while (progress);
-
- NIR_PASS(progress, nir, nir_copy_prop);
- NIR_PASS(progress, nir, nir_opt_dce);
-}
-
-static unsigned
-nir_src_index(compiler_context *ctx, nir_src *src)
-{
- if (src->is_ssa)
- return src->ssa->index;
- else
- return ctx->func->impl->ssa_alloc + src->reg.reg->index;
-}
-
-static unsigned
-nir_dest_index(compiler_context *ctx, nir_dest *dst)
-{
- if (dst->is_ssa)
- return dst->ssa.index;
- else
- return ctx->func->impl->ssa_alloc + dst->reg.reg->index;
-}
-
-static unsigned
-nir_alu_src_index(compiler_context *ctx, nir_alu_src *src)
-{
- return nir_src_index(ctx, &src->src);
-}
-
-struct bifrost_instruction *
-mir_alloc_ins(struct bifrost_instruction instr)
-{
- struct bifrost_instruction *heap_ins = malloc(sizeof(instr));
- memcpy(heap_ins, &instr, sizeof(instr));
- return heap_ins;
-}
-
-static void
-emit_mir_instruction(struct compiler_context *ctx, struct bifrost_instruction instr)
-{
- list_addtail(&(mir_alloc_ins(instr))->link, &ctx->current_block->instructions);
-}
-
-static void
-bifrost_block_add_successor(bifrost_block *block, bifrost_block *successor)
-{
- assert(block->num_successors < ARRAY_SIZE(block->successors));
- block->successors[block->num_successors++] = successor;
-}
-
-static void
-emit_load_const(struct compiler_context *ctx, nir_load_const_instr *instr)
-{
- nir_ssa_def def = instr->def;
-
- float *v = ralloc_array(NULL, float, 1);
- nir_const_value_to_array(v, instr->value, instr->def.num_components, f32);
- _mesa_hash_table_u64_insert(ctx->ssa_constants, def.index + 1, v);
-}
-
-static uint32_t
-alloc_mir_temp(struct compiler_context *ctx)
-{
- return SSA_TEMP_VALUE(ctx->mir_temp++);
-}
-
-static uint32_t
-emit_ld_vary_addr_constant(struct compiler_context *ctx, uint32_t location)
-{
- // LD_VAR_ADDR.f32 {R0, T1}, R61, R62, location:1, R12
- // ...
- // ST_VAR.v4 T1, R12, R13, R14, R4
-
- // R61-R62 is filled with information needed for varying interpolation
- // This loads a vec3 with the information that ST_VAR needs to work
-
- uint32_t mir_temp_location = alloc_mir_temp(ctx);
- // This instruction loads a vec3 starting from the initial register
- struct bifrost_instruction instr = {
- .op = op_ld_var_addr,
- .dest_components = 3,
- .ssa_args = {
- .dest = mir_temp_location,
- .src0 = SSA_FIXED_REGISTER(61),
- .src1 = SSA_FIXED_REGISTER(62),
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = location,
- };
- emit_mir_instruction(ctx, instr);
-
- return mir_temp_location;
-}
-
-// XXX: Doesn't support duplicated values in the components!
-// RA WILL fail!
-static void
-emit_create_vector(struct compiler_context *ctx, unsigned dest, unsigned num_comps, uint32_t *comps)
-{
- assert(num_comps <= 4 && "Can't make a vector larger than 4 components");
-
- // This instruction loads a vec3 starting from the initial register
- struct bifrost_instruction instr = {
- .op = op_create_vector,
- .dest_components = num_comps,
- .ssa_args = {
- .dest = dest,
- }
- };
-
- uint32_t *srcs[4] = {
- &instr.ssa_args.src0,
- &instr.ssa_args.src1,
- &instr.ssa_args.src2,
- &instr.ssa_args.src3,
- };
-
- for (unsigned i = 0; i < 4; ++i) {
- if (i < num_comps)
- *srcs[i] = comps[i];
- else
- *srcs[i] = SSA_INVALID_VALUE;
- }
- emit_mir_instruction(ctx, instr);
-}
-
-static uint32_t
-emit_extract_vector_element(struct compiler_context *ctx, unsigned ssa_vector, unsigned element)
-{
- uint32_t mir_temp_location = alloc_mir_temp(ctx);
- // This instruction loads a vec3 starting from the initial register
- struct bifrost_instruction instr = {
- .op = op_extract_element,
- .dest_components = 1,
- .ssa_args = {
- .dest = mir_temp_location,
- .src0 = ssa_vector,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = element,
- };
- emit_mir_instruction(ctx, instr);
-
- return mir_temp_location;
-}
-static uint32_t
-emit_movi(struct compiler_context *ctx, uint32_t literal)
-{
- uint32_t mir_temp_location = alloc_mir_temp(ctx);
- // This instruction loads a vec3 starting from the initial register
- struct bifrost_instruction instr = {
- .op = op_movi,
- .dest_components = 1,
- .ssa_args = {
- .dest = mir_temp_location,
- .src0 = SSA_INVALID_VALUE,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = literal,
- };
- emit_mir_instruction(ctx, instr);
-
- return mir_temp_location;
-}
-
-static unsigned
-nir_alu_src_index_scalar(compiler_context *ctx, nir_alu_instr *nir_instr, unsigned src)
-{
- // NIR uses a combination of single channels plus swizzles to determine which component is pulled out of a source
- for (unsigned c = 0; c < NIR_MAX_VEC_COMPONENTS; c++) {
- if (!nir_alu_instr_channel_used(nir_instr, src, c))
- continue;
- // Pull the swizzle from this element that is active and use it as the source
- unsigned element = nir_instr->src[src].swizzle[c];
-
- // Create an op that extracts an element from a vector
- return emit_extract_vector_element(ctx, nir_alu_src_index(ctx, &nir_instr->src[src]), element);
- }
- assert(0);
- return 0;
-}
-
-static void
-emit_intrinsic(struct compiler_context *ctx, nir_intrinsic_instr *nir_instr)
-{
- nir_const_value *const_offset;
- unsigned offset, reg;
-
- switch (nir_instr->intrinsic) {
- case nir_intrinsic_load_ubo: {
- nir_const_value *location = nir_src_as_const_value(nir_instr->src[0]);
- const_offset = nir_src_as_const_value(nir_instr->src[1]);
- assert (location && "no indirect ubo selection");
- assert (const_offset && "no indirect inputs");
-
- enum bifrost_ir_ops op;
-
- // load_ubo <UBO binding>, <byte offset>
- // ld_ubo <byte offset>, <UBO binding>
- switch (nir_dest_num_components(nir_instr->dest)) {
- case 1:
- op = op_ld_ubo_v1;
- break;
- case 2:
- op = op_ld_ubo_v2;
- break;
- case 3:
- op = op_ld_ubo_v3;
- break;
- case 4:
- op = op_ld_ubo_v4;
- break;
- default:
- assert(0);
- break;
- }
-
- reg = nir_dest_index(ctx, &nir_instr->dest);
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = nir_dest_num_components(nir_instr->dest),
- .ssa_args = {
- .dest = reg,
- .src0 = SSA_INVALID_VALUE,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = nir_src_as_uint(nir_instr->src[1]),
- .literal_args[1] = nir_src_as_uint(nir_instr->src[0]),
- };
-
- emit_mir_instruction(ctx, instr);
- break;
- }
- case nir_intrinsic_store_ssbo: {
- nir_const_value *location = nir_src_as_const_value(nir_instr->src[1]);
- const_offset = nir_src_as_const_value(nir_instr->src[2]);
- assert (location && "no indirect ubo selection");
- assert (const_offset && "no indirect inputs");
-
- // store_ssbo <Value>, <binding>, <offset>
- // store_vN <Addr>, <Value>
- reg = nir_src_index(ctx, &nir_instr->src[0]);
-
- enum bifrost_ir_ops op;
- switch (nir_src_num_components(nir_instr->src[0])) {
- case 1:
- op = op_store_v1;
- break;
- case 2:
- op = op_store_v2;
- break;
- case 3:
- op = op_store_v3;
- break;
- case 4:
- op = op_store_v4;
- break;
- default:
- assert(0);
- break;
- }
-
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = reg,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = nir_src_as_uint(nir_instr->src[2]),
- };
- emit_mir_instruction(ctx, instr);
- break;
- }
- case nir_intrinsic_load_uniform:
- offset = nir_intrinsic_base(nir_instr);
-
- if (nir_src_is_const(nir_instr->src[0])) {
- offset += nir_src_as_uint(nir_instr->src[0]);
- } else {
- assert(0 && "Can't handle indirect load_uniform");
- }
-
- reg = nir_dest_index(ctx, &nir_instr->dest);
-
- unsigned num_components = nir_dest_num_components(nir_instr->dest);
- if (num_components == 1) {
- struct bifrost_instruction instr = {
- .op = op_mov,
- .dest_components = 1,
- .ssa_args = {
- .dest = reg,
- .src0 = SSA_FIXED_UREGISTER(offset),
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- };
- emit_mir_instruction(ctx, instr);
- } else {
- uint32_t comps[4];
-
- for (unsigned i = 0; i < nir_dest_num_components(nir_instr->dest); ++i) {
- uint32_t temp_dest = alloc_mir_temp(ctx);
- comps[i] = temp_dest;
- struct bifrost_instruction instr = {
- .op = op_mov,
- .dest_components = 1,
- .ssa_args = {
- .dest = temp_dest,
- .src0 = SSA_FIXED_UREGISTER(offset + (i * 4)),
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- };
- emit_mir_instruction(ctx, instr);
- }
-
- emit_create_vector(ctx, reg, num_components, comps);
- }
- break;
-
- case nir_intrinsic_load_input: {
- const_offset = nir_src_as_const_value(nir_instr->src[0]);
- assert (const_offset && "no indirect inputs");
-
- offset = nir_intrinsic_base(nir_instr) + nir_src_as_uint(nir_instr->src[0]);
-
- reg = nir_dest_index(ctx, &nir_instr->dest);
-
- enum bifrost_ir_ops op;
- switch (nir_dest_num_components(nir_instr->dest)) {
- case 1:
- op = op_ld_attr_v1;
- break;
- case 2:
- op = op_ld_attr_v2;
- break;
- case 3:
- op = op_ld_attr_v3;
- break;
- case 4:
- op = op_ld_attr_v4;
- break;
- default:
- assert(0);
- break;
- }
-
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = nir_dest_num_components(nir_instr->dest),
- .ssa_args = {
- .dest = reg,
- .src0 = offset,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- }
- };
-
- emit_mir_instruction(ctx, instr);
- break;
- }
- case nir_intrinsic_store_output: {
- const_offset = nir_src_as_const_value(nir_instr->src[1]);
- assert(const_offset && "no indirect outputs");
-
- offset = nir_intrinsic_base(nir_instr);
- if (ctx->stage == MESA_SHADER_FRAGMENT) {
- int comp = nir_intrinsic_component(nir_instr);
- offset += comp;
- // XXX: Once we support more than colour output then this will need to change
- void *entry = _mesa_hash_table_u64_search(ctx->outputs_nir_to_bi, offset + FRAG_RESULT_DATA0 + 1);
-
- if (!entry) {
- printf("WARNING: skipping fragment output\n");
- break;
- }
-
- offset = (uintptr_t) (entry) - 1;
- reg = nir_src_index(ctx, &nir_instr->src[0]);
-
- enum bifrost_ir_ops op;
- switch (nir_src_num_components(nir_instr->src[0])) {
- case 1:
- op = op_store_v1;
- break;
- case 2:
- op = op_store_v2;
- break;
- case 3:
- op = op_store_v3;
- break;
- case 4:
- op = op_store_v4;
- break;
- default:
- assert(0);
- break;
- }
-
- // XXX: All offsets aren't vec4 aligned. Will need to adjust this in the future
- // XXX: This needs to offset correctly in to memory so the blend step can pick it up
- uint32_t movi = emit_movi(ctx, offset * 16);
- uint32_t movi2 = emit_movi(ctx, 0);
-
- uint32_t comps[2] = {
- movi, movi2,
- };
- uint32_t offset_val = alloc_mir_temp(ctx);
- emit_create_vector(ctx, offset_val, 2, comps);
-
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = offset_val,
- .src1 = reg,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- }
- };
- emit_mir_instruction(ctx, instr);
- } else if (ctx->stage == MESA_SHADER_VERTEX) {
- int comp = nir_intrinsic_component(nir_instr);
- offset += comp;
- void *entry = _mesa_hash_table_u64_search(ctx->varying_nir_to_bi, offset + 2);
-
- if (!entry) {
- printf("WARNING: skipping varying\n");
- break;
- }
-
- offset = (uintptr_t) (entry) - 1;
-
- reg = nir_src_index(ctx, &nir_instr->src[0]);
- // LD_VAR_ADDR.f32 {R0, T1}, R61, R62, location:1, R12
- // ...
- // ST_VAR.v4 T1, R12, R13, R14, R4
-
- offset = emit_ld_vary_addr_constant(ctx, offset);
- enum bifrost_ir_ops op;
- switch (nir_src_num_components(nir_instr->src[0])) {
- case 1:
- op = op_st_vary_v1;
- break;
- case 2:
- op = op_st_vary_v2;
- break;
- case 3:
- op = op_st_vary_v3;
- break;
- case 4:
- op = op_st_vary_v4;
- break;
- default:
- assert(0);
- break;
- }
-
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = offset,
- .src1 = reg,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- }
- };
- emit_mir_instruction(ctx, instr);
- } else {
- assert(0 && "Unknown store_output stage");
- }
- break;
- }
- default:
- printf ("Unhandled intrinsic %s\n", nir_intrinsic_infos[nir_instr->intrinsic].name);
- break;
- }
-}
-
-#define ALU_CASE(arguments, nir, name) \
- case nir_op_##nir: \
- argument_count = arguments; \
- op = op_##name; \
- break
-#define ALU_CASE_MOD(arguments, nir, name, modifiers) \
- case nir_op_##nir: \
- argument_count = arguments; \
- op = op_##name; \
- src_modifiers = modifiers; \
- break
-
-static void
-emit_alu(struct compiler_context *ctx, nir_alu_instr *nir_instr)
-{
- unsigned dest = nir_dest_index(ctx, &nir_instr->dest.dest);
- unsigned op = ~0U, argument_count;
- unsigned src_modifiers = 0;
-
- switch (nir_instr->op) {
- ALU_CASE(2, fmul, fmul_f32);
- ALU_CASE(2, fadd, fadd_f32);
- ALU_CASE_MOD(2, fsub, fadd_f32, SOURCE_MODIFIER(1, SRC_MOD_NEG));
- ALU_CASE(1, ftrunc, trunc);
- ALU_CASE(1, fceil, ceil);
- ALU_CASE(1, ffloor, floor);
- ALU_CASE(1, fround_even, roundeven);
- ALU_CASE(1, frcp, frcp_fast_f32);
- ALU_CASE(2, fmax, max_f32);
- ALU_CASE(2, fmin, min_f32);
- ALU_CASE(2, iadd, add_i32);
- ALU_CASE(2, isub, sub_i32);
- ALU_CASE(2, imul, mul_i32);
- ALU_CASE(2, iand, and_i32);
- ALU_CASE(2, ior, or_i32);
- ALU_CASE(2, ixor, xor_i32);
- ALU_CASE(2, ishl, lshift_i32);
- ALU_CASE(2, ushr, rshift_i32);
- ALU_CASE(2, ishr, arshift_i32);
- case nir_op_ineg: {
- unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0);
- printf("ineg 0x%08x\n", src0);
- struct bifrost_instruction instr = {
- .op = op_sub_i32,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = SSA_FIXED_CONST_0,
- .src1 = src0,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- };
-
- emit_mir_instruction(ctx, instr);
- return;
-
- }
- case nir_op_vec2: {
- uint32_t comps[3] = {
- nir_alu_src_index(ctx, &nir_instr->src[0]),
- nir_alu_src_index(ctx, &nir_instr->src[1]),
- };
- emit_create_vector(ctx, dest, 2, comps);
- return;
- break;
- }
- case nir_op_vec3: {
- uint32_t comps[3] = {
- nir_alu_src_index(ctx, &nir_instr->src[0]),
- nir_alu_src_index(ctx, &nir_instr->src[1]),
- nir_alu_src_index(ctx, &nir_instr->src[2]),
- };
- emit_create_vector(ctx, dest, 3, comps);
- return;
- break;
- }
- case nir_op_vec4: {
- uint32_t comps[4] = {
- nir_alu_src_index(ctx, &nir_instr->src[0]),
- nir_alu_src_index(ctx, &nir_instr->src[1]),
- nir_alu_src_index(ctx, &nir_instr->src[2]),
- nir_alu_src_index(ctx, &nir_instr->src[3]),
- };
- emit_create_vector(ctx, dest, 4, comps);
- return;
- break;
- }
- case nir_op_fdiv: {
- unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0);
- unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1);
- uint32_t mir_temp_location = alloc_mir_temp(ctx);
- {
- struct bifrost_instruction instr = {
- .op = op_frcp_fast_f32,
- .dest_components = 1,
- .ssa_args = {
- .dest = mir_temp_location,
- .src0 = src1,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- };
- emit_mir_instruction(ctx, instr);
- }
-
- struct bifrost_instruction instr = {
- .op = op_fmul_f32,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = src0,
- .src1 = src1,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .src_modifiers = src_modifiers,
- };
-
- emit_mir_instruction(ctx, instr);
- return;
- break;
- }
- case nir_op_umin:
- case nir_op_imin:
- case nir_op_umax:
- case nir_op_imax: {
- unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0);
- unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1);
- struct bifrost_instruction instr = {
- .op = op_csel_i32,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = src0,
- .src1 = src1,
- .src2 = src0,
- .src3 = src1,
- },
- .src_modifiers = src_modifiers,
- .literal_args[0] = 0, /* XXX: Comparison operator */
- };
-
- emit_mir_instruction(ctx, instr);
- return;
- break;
- }
- case nir_op_umin3:
- case nir_op_imin3:
- case nir_op_umax3:
- case nir_op_imax3: {
- unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0);
- unsigned src1 = nir_alu_src_index_scalar(ctx, nir_instr, 1);
- unsigned src2 = nir_alu_src_index_scalar(ctx, nir_instr, 2);
-
- unsigned op = 0;
- if (nir_instr->op == nir_op_umin3)
- op = op_umin3_i32;
- else if (nir_instr->op == nir_op_imin3)
- op = op_imin3_i32;
- else if (nir_instr->op == nir_op_umax3)
- op = op_umax3_i32;
- else if (nir_instr->op == nir_op_imax3)
- op = op_imax3_i32;
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = src0,
- .src1 = src1,
- .src2 = src2,
- .src3 = SSA_INVALID_VALUE,
- },
- .src_modifiers = src_modifiers,
- };
-
- emit_mir_instruction(ctx, instr);
-
- return;
- break;
- }
- case nir_op_ine: {
- uint32_t movi = emit_movi(ctx, ~0U);
- unsigned src0 = nir_alu_src_index(ctx, &nir_instr->src[0]);
- unsigned src1 = nir_alu_src_index(ctx, &nir_instr->src[1]);
- struct bifrost_instruction instr = {
- .op = op_csel_i32,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = src0,
- .src1 = src1,
- .src2 = movi,
- .src3 = SSA_FIXED_CONST_0,
- },
- .src_modifiers = src_modifiers,
- .literal_args[0] = CSEL_IEQ, /* XXX: Comparison operator */
- };
-
- emit_mir_instruction(ctx, instr);
- return;
- break;
- }
- default:
- printf("Unhandled ALU op %s\n", nir_op_infos[nir_instr->op].name);
- return;
- }
-
- unsigned src0 = nir_alu_src_index_scalar(ctx, nir_instr, 0);
- unsigned src1 = argument_count >= 2 ? nir_alu_src_index_scalar(ctx, nir_instr, 1) : SSA_INVALID_VALUE;
- unsigned src2 = argument_count >= 3 ? nir_alu_src_index_scalar(ctx, nir_instr, 2) : SSA_INVALID_VALUE;
- unsigned src3 = argument_count >= 4 ? nir_alu_src_index_scalar(ctx, nir_instr, 3) : SSA_INVALID_VALUE;
-
- struct bifrost_instruction instr = {
- .op = op,
- .dest_components = 1,
- .ssa_args = {
- .dest = dest,
- .src0 = src0,
- .src1 = src1,
- .src2 = src2,
- .src3 = src3,
- },
- .src_modifiers = src_modifiers,
- };
-
- emit_mir_instruction(ctx, instr);
-}
-
-static void
-emit_instr(struct compiler_context *ctx, struct nir_instr *instr)
-{
- switch (instr->type) {
- case nir_instr_type_load_const:
- emit_load_const(ctx, nir_instr_as_load_const(instr));
- break;
- case nir_instr_type_intrinsic:
- emit_intrinsic(ctx, nir_instr_as_intrinsic(instr));
- break;
- case nir_instr_type_alu:
- emit_alu(ctx, nir_instr_as_alu(instr));
- break;
- case nir_instr_type_tex:
- printf("Unhandled NIR inst tex\n");
- break;
- case nir_instr_type_jump:
- printf("Unhandled NIR inst jump\n");
- break;
- case nir_instr_type_ssa_undef:
- printf("Unhandled NIR inst ssa_undef\n");
- break;
- default:
- printf("Unhandled instruction type\n");
- break;
- }
-
-}
-
-static bifrost_block *
-emit_block(struct compiler_context *ctx, nir_block *block)
-{
- bifrost_block *this_block = calloc(sizeof(bifrost_block), 1);
- list_addtail(&this_block->link, &ctx->blocks);
-
- ++ctx->block_count;
-
- /* Add this block to be a successor to the previous block */
- if (ctx->current_block)
- bifrost_block_add_successor(ctx->current_block, this_block);
-
- /* Set up current block */
- list_inithead(&this_block->instructions);
- ctx->current_block = this_block;
-
- nir_foreach_instr(instr, block) {
- emit_instr(ctx, instr);
- ++ctx->instruction_count;
- }
-
-#ifdef BI_DEBUG
- print_mir_block(this_block, false);
-#endif
- return this_block;
-}
-
-void
-emit_if(struct compiler_context *ctx, nir_if *nir_inst);
-
-static struct bifrost_block *
-emit_cf_list(struct compiler_context *ctx, struct exec_list *list)
-{
- struct bifrost_block *start_block = NULL;
- foreach_list_typed(nir_cf_node, node, node, list) {
- switch (node->type) {
- case nir_cf_node_block: {
- bifrost_block *block = emit_block(ctx, nir_cf_node_as_block(node));
-
- if (!start_block)
- start_block = block;
-
- break;
- }
-
- case nir_cf_node_if:
- emit_if(ctx, nir_cf_node_as_if(node));
- break;
-
- default:
- case nir_cf_node_loop:
- case nir_cf_node_function:
- assert(0);
- break;
- }
- }
-
- return start_block;
-}
-
-void
-emit_if(struct compiler_context *ctx, nir_if *nir_inst)
-{
-
- // XXX: Conditional branch instruction can do a variety of comparisons with the sources
- // Merge the source instruction `ine` with our conditional branch
- {
- uint32_t movi = emit_movi(ctx, ~0U);
- struct bifrost_instruction instr = {
- .op = op_branch,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = nir_src_index(ctx, &nir_inst->condition),
- .src1 = movi,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .src_modifiers = 0,
- .literal_args[0] = BR_COND_EQ, /* XXX: Comparison Arg type */
- .literal_args[1] = 0, /* XXX: Branch target */
- };
-
- emit_mir_instruction(ctx, instr);
- }
-
- bifrost_instruction *true_branch = mir_last_instr_in_block(ctx->current_block);
-
- bifrost_block *true_block = emit_cf_list(ctx, &nir_inst->then_list);
-
- {
- struct bifrost_instruction instr = {
- .op = op_branch,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = SSA_INVALID_VALUE,
- .src1 = SSA_INVALID_VALUE,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .src_modifiers = 0,
- .literal_args[0] = BR_ALWAYS, /* XXX: ALWAYS */
- .literal_args[1] = 0, /* XXX: Branch target */
- };
-
- emit_mir_instruction(ctx, instr);
- }
- bifrost_instruction *true_exit_branch = mir_last_instr_in_block(ctx->current_block);
-
- unsigned false_idx = ctx->block_count;
- unsigned inst_count = ctx->instruction_count;
-
- bifrost_block *false_block = emit_cf_list(ctx, &nir_inst->else_list);
-
- unsigned if_footer_idx = ctx->block_count;
- assert(true_block);
- assert(false_block);
-
-
- if (ctx->instruction_count == inst_count) {
- // If the else branch didn't have anything in it then we can remove the dead jump
- mir_remove_instr(true_exit_branch);
- } else {
- true_exit_branch->literal_args[1] = if_footer_idx;
- }
-
- true_branch->literal_args[1] = false_idx;
-}
-
-int
-bifrost_compile_shader_nir(nir_shader *nir, struct bifrost_program *program)
-{
- struct compiler_context ictx = {
- .nir = nir,
- .stage = nir->info.stage,
- };
-
- struct compiler_context *ctx = &ictx;
-
- ctx->mir_temp = 0;
-
- /* Initialize at a global (not block) level hash tables */
- ctx->ssa_constants = _mesa_hash_table_u64_create(NULL);
- ctx->hash_to_temp = _mesa_hash_table_u64_create(NULL);
-
- /* Assign actual uniform location, skipping over samplers */
- ctx->uniform_nir_to_bi = _mesa_hash_table_u64_create(NULL);
-
- nir_foreach_variable(var, &nir->uniforms) {
- if (glsl_get_base_type(var->type) == GLSL_TYPE_SAMPLER) continue;
-
- for (int col = 0; col < glsl_get_matrix_columns(var->type); ++col) {
- int id = ctx->uniform_count++;
- _mesa_hash_table_u64_insert(ctx->uniform_nir_to_bi, var->data.driver_location + col + 1, (void *) ((uintptr_t) (id + 1)));
- }
- }
-
- if (ctx->stage == MESA_SHADER_VERTEX) {
- ctx->varying_nir_to_bi = _mesa_hash_table_u64_create(NULL);
- nir_foreach_variable(var, &nir->outputs) {
- if (var->data.location < VARYING_SLOT_VAR0) {
- if (var->data.location == VARYING_SLOT_POS)
- ctx->varying_count++;
- _mesa_hash_table_u64_insert(ctx->varying_nir_to_bi, var->data.driver_location + 1, (void *) ((uintptr_t) (1)));
-
- continue;
- }
-
- for (int col = 0; col < glsl_get_matrix_columns(var->type); ++col) {
- for (int comp = 0; comp < 4; ++comp) {
- int id = comp + ctx->varying_count++;
- _mesa_hash_table_u64_insert(ctx->varying_nir_to_bi, var->data.driver_location + col + comp + 1, (void *) ((uintptr_t) (id + 1)));
- }
- }
- }
-
- } else if (ctx->stage == MESA_SHADER_FRAGMENT) {
- ctx->outputs_nir_to_bi = _mesa_hash_table_u64_create(NULL);
- nir_foreach_variable(var, &nir->outputs) {
- if (var->data.location >= FRAG_RESULT_DATA0 && var->data.location <= FRAG_RESULT_DATA7) {
- int id = ctx->outputs_count++;
- printf("Driver location: %d with id %d\n", var->data.location + 1, id);
- _mesa_hash_table_u64_insert(ctx->outputs_nir_to_bi, var->data.location + 1, (void *) ((uintptr_t) (id + 1)));
- }
- }
- }
-
- /* Optimisation passes */
- optimize_nir(nir);
-
-#ifdef BI_DEBUG
- nir_print_shader(nir, stdout);
-#endif
-
- /* Generate machine IR for shader */
- nir_foreach_function(func, nir) {
- nir_builder _b;
- ctx->b = &_b;
- nir_builder_init(ctx->b, func->impl);
-
- list_inithead(&ctx->blocks);
- ctx->block_count = 0;
- ctx->func = func;
-
- emit_cf_list(ctx, &func->impl->body);
-
- break; // XXX: Once we support multi function shaders then implement
- }
-
- util_dynarray_init(&program->compiled, NULL);
-
- // MIR pre-RA optimizations
-
- bool progress = false;
-
- do {
- progress = false;
- mir_foreach_block(ctx, block) {
- // XXX: Not yet working
-// progress |= bifrost_opt_branch_fusion(ctx, block);
- }
- } while (progress);
-
- bifrost_schedule_program(ctx);
-
-#ifdef BI_DEBUG
- nir_print_shader(nir, stdout);
- disassemble_bifrost(stdout, program->compiled.data, program->compiled.size, false);
-#endif
- return 0;
-}
/*
- * Copyright (C) 2018 Ryan Houdek <Sonicadvance1@gmail.com>
+ * Copyright (C) 2018-2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* SOFTWARE.
*/
-#ifndef __bifrost_compile_h__
-#define __bifrost_compile_h__
+#ifndef __BIFROST_PUBLIC_H_
+#define __BIFROST_PUBLIC_H_
#include "compiler/nir/nir.h"
#include "util/u_dynarray.h"
-struct bifrost_program {
+typedef struct {
struct util_dynarray compiled;
-};
+} bifrost_program;
int
-bifrost_compile_shader_nir(nir_shader *nir, struct bifrost_program *program);
+bifrost_compile_shader_nir(nir_shader *nir, bifrost_program *program);
static const nir_shader_compiler_options bifrost_nir_options = {
- .fuse_ffma = true,
- .lower_flrp16 = true,
+ .lower_ffma = true,
+ .lower_sub = true,
+ .lower_scmp = true,
.lower_flrp32 = true,
.lower_flrp64 = true,
+ .lower_ffract = true,
.lower_fmod = true,
- .lower_bitfield_extract = true,
- .lower_bitfield_extract_to_shifts = true,
- .lower_bitfield_insert = true,
- .lower_bitfield_insert_to_shifts = true,
- .lower_bitfield_reverse = true,
+ .lower_fdiv = true,
.lower_idiv = true,
.lower_isign = true,
- .lower_fsign = true,
- .lower_ffract = true,
+ .lower_fpow = true,
+ .lower_find_lsb = true,
.lower_fdph = true,
+
+ .lower_wpos_pntc = true,
+ .lower_fsign = true,
+
+ .lower_extract_byte = true,
+ .lower_extract_word = true,
+ .lower_rotate = true,
+
.lower_pack_half_2x16 = true,
+ .lower_pack_half_2x16_split = true,
.lower_pack_unorm_2x16 = true,
.lower_pack_snorm_2x16 = true,
.lower_pack_unorm_4x8 = true,
.lower_pack_snorm_4x8 = true,
.lower_unpack_half_2x16 = true,
+ .lower_unpack_half_2x16_split = true,
.lower_unpack_unorm_2x16 = true,
.lower_unpack_snorm_2x16 = true,
.lower_unpack_unorm_4x8 = true,
.lower_unpack_snorm_4x8 = true,
- .lower_extract_byte = true,
- .lower_extract_word = true,
- .lower_all_io_to_temps = true,
- .lower_all_io_to_elements = true,
+
+ .lower_doubles_options = nir_lower_dmod,
+
+ .lower_bitfield_extract_to_shifts = true,
+ .vectorize_io = true,
+ .use_interpolated_input_intrinsics = true
};
#endif
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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.
- */
-
-#ifndef __bifrost_ops_h__
-#define __bifrost_ops_h__
-
-enum bifrost_ir_ops {
- op_fma_f32 = 0x0,
- op_fmul_f32,
- op_fadd_f32,
- op_frcp_fast_f32,
- op_max_f32,
- op_min_f32,
- op_add_i32,
- op_sub_i32,
- op_imad,
- op_mul_i32,
- op_or_i32,
- op_and_i32,
- op_lshift_i32,
- op_xor_i32,
- op_rshift_i32,
- op_arshift_i32,
- op_csel_i32,
- op_imin3_i32,
- op_umin3_i32,
- op_imax3_i32,
- op_umax3_i32,
-
- op_branch,
-
- // unary
- op_trunc,
- op_ceil,
- op_floor,
- op_round,
- op_roundeven,
-
- op_mov,
- op_movi,
-
- op_ld_ubo_v1,
- op_ld_ubo_v2,
- op_ld_ubo_v3,
- op_ld_ubo_v4,
-
- op_ld_attr_v1,
- op_ld_attr_v2,
- op_ld_attr_v3,
- op_ld_attr_v4,
-
- op_ld_var_addr,
- op_st_vary_v1,
- op_st_vary_v2,
- op_st_vary_v3,
- op_st_vary_v4,
-
- op_store_v1,
- op_store_v2,
- op_store_v3,
- op_store_v4,
-
- op_create_vector,
- op_extract_element,
- op_last,
-};
-
-
-enum branch_cond {
- BR_COND_LT = 0,
- BR_COND_LE = 1,
- BR_COND_GE = 2,
- BR_COND_GT = 3,
- // Equal vs. not-equal determined by src0/src1 comparison
- BR_COND_EQ = 4,
- // floating-point comparisons
- // Becomes UNE when you flip the arguments
- BR_COND_OEQ = 5,
- // TODO what happens when you flip the arguments?
- BR_COND_OGT = 6,
- BR_COND_OLT = 7,
-};
-
-enum branch_code {
- BR_ALWAYS = 63,
-};
-
-enum csel_cond {
- CSEL_NEQ_0 = 0,
- CSEL_FEQ,
- CSEL_FGTR,
- CSEL_FGE,
- CSEL_IEQ,
- CSEL_IGT,
- CSEL_IGE,
- CSEL_UGT,
- CSEL_UGE,
-};
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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 "bifrost_opts.h"
-#include "compiler_defines.h"
-
-bool
-bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block)
-{
- bool progress = false;
- mir_foreach_instr_in_block_safe(block, instr) {
- if (instr->op != op_branch) continue;
- if (instr->literal_args[0] != BR_COND_EQ) continue;
-
- unsigned src1 = instr->ssa_args.src0;
-
- // Only work on SSA values
- if (src1 >= SSA_FIXED_MINIMUM) continue;
-
- // Find the source for this conditional branch instruction
- // It'll be a CSEL instruction
- // If it's comparision is one of the ops that our conditional branch supports
- // then we can merge the two
- mir_foreach_instr_in_block_from_rev(block, next_instr, instr) {
- if (next_instr->op != op_csel_i32) continue;
-
- if (next_instr->ssa_args.dest == src1) {
- // We found the CSEL instruction that is the source here
- // Check its condition to make sure it matches what we can fuse
- unsigned cond = next_instr->literal_args[0];
- if (cond == CSEL_IEQ) {
- // This CSEL is doing an IEQ for our conditional branch doing EQ
- // We can just emit a conditional branch that does the comparison
- struct bifrost_instruction new_instr = {
- .op = op_branch,
- .dest_components = 0,
- .ssa_args = {
- .dest = SSA_INVALID_VALUE,
- .src0 = next_instr->ssa_args.src0,
- .src1 = next_instr->ssa_args.src1,
- .src2 = SSA_INVALID_VALUE,
- .src3 = SSA_INVALID_VALUE,
- },
- .literal_args[0] = BR_COND_EQ,
- .literal_args[1] = instr->literal_args[1],
- };
- mir_insert_instr_before(instr, new_instr);
- mir_remove_instr(instr);
- progress |= true;
- break;
- }
- }
- }
- }
-
- return progress;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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.
- */
-
-#ifndef bifrost_opts_h
-#define bifrost_opts_h
-#include "compiler_defines.h"
-
-#include <stdbool.h>
-
-bool
-bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block);
-
-#endif /* bifrost_opts_h */
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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 "compiler_defines.h"
-#include "bifrost_print.h"
-
-const char *ir_names[op_last + 1] = {
- "fma.f32",
- "fmul.f32",
- "fadd.f32",
- "frcp_fast.f32",
- "max.f32",
- "min.f32",
- "add.i32",
- "sub.i32",
- "imad",
- "mul.i32",
- "or.i32",
- "and.i32",
- "lshift.i32",
- "xor.i32",
- "rshift.i32",
- "arshift.i32",
- "csel.i32",
- "imin3.i32",
- "umin3.i32",
- "imax3.i32",
- "umax3.i32",
-
- "branch",
-
- // unary
- "trunc",
- "ceil",
- "floor",
- "round",
- "roundeven",
-
- "mov",
- "movi",
-
- "ld_ubo.v1",
- "ld_ubo.v2",
- "ld_ubo.v3",
- "ld_ubo.v4",
-
- "ld_attr.v1",
- "ld_attr.v2",
- "ld_attr.v3",
- "ld_attr.v4",
-
- "ld_var_addr",
- "st_vary.v1",
- "st_vary.v2",
- "st_vary.v3",
- "st_vary.v4",
-
- "store.v1",
- "store.v2",
- "store.v3",
- "store.v4",
-
- "create_vector",
- "extract_element",
- "last",
-};
-
-void
-print_mir_instruction(struct bifrost_instruction *instr, bool post_ra)
-{
- printf("\t");
- if (instr->dest_components != 0) {
- if (post_ra) {
- if (instr->dest_components == 1) {
- printf("r%d = ", instr->args.dest);
- } else {
- printf("r%d..r%d = ", instr->args.dest, instr->args.dest + instr->dest_components - 1);
-
- }
- } else {
- printf("%%0x%08x = ", instr->ssa_args.dest);
- }
- }
-
- printf("%s ", ir_names[instr->op]);
-
- if (post_ra) {
- uint32_t sources[4] = {
- instr->args.src0,
- instr->args.src1,
- instr->args.src2,
- instr->args.src3
- };
- for (unsigned i = 0; i < 4; ++i) {
- if (sources[i] == SSA_INVALID_VALUE) break;
- bool last = i + 1 == 4 ||
- sources[i + 1] == SSA_INVALID_VALUE;
-
- if (sources[i] == SSA_FIXED_CONST_0) {
- printf("#0%s", last ? "" : ", ");
- } else if (sources[i] >= SSA_FIXED_UREG_MINIMUM) {
- printf("u%d%s", SSA_UREG_FROM_FIXED(sources[i]), last ? "" : ", ");
- } else {
- printf("r%d%s", sources[i], last ? "" : ", ");
- }
- }
- } else {
- uint32_t sources[4] = {
- instr->ssa_args.src0,
- instr->ssa_args.src1,
- instr->ssa_args.src2,
- instr->ssa_args.src3
- };
- for (unsigned i = 0; i < 4; ++i) {
- if (sources[i] == SSA_INVALID_VALUE) break;
- bool last = i + 1 == 4 ||
- sources[i + 1] == SSA_INVALID_VALUE;
-
- printf("%%0x%08x%s", sources[i], last ? "" : ", ");
- }
- }
-
- printf("\n");
-}
-
-void
-print_mir_block(struct bifrost_block *block, bool post_ra)
-{
- printf("{\n");
-
- mir_foreach_instr_in_block(block, instr) {
- print_mir_instruction(instr, post_ra);
- }
-
- printf("}\n");
-}
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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.
- */
-
-#ifndef __bifrost_print_h__
-#define __bifrost_print_h__
-
-#include <stdbool.h>
-
-struct bifrost_instruction;
-struct bifrost_block;
-
-void print_mir_instruction(struct bifrost_instruction *ins, bool post_ra);
-void print_mir_block(struct bifrost_block *block, bool post_ra);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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/register_allocate.h"
-#include "compiler_defines.h"
-#include "bifrost_sched.h"
-#include "bifrost_compile.h"
-#include "bifrost_print.h"
-
-#define BI_DEBUG
-const unsigned max_primary_reg = 64; /* Overestimate because of special regs */
-const unsigned max_vec2_reg = 32;
-const unsigned max_vec3_reg = 16; // XXX: Do we need to align vec3 to vec4 boundary?
-const unsigned max_vec4_reg = 16;
-const unsigned max_registers = 128; /* Sum of classes */
-const unsigned primary_base = 0;
-const unsigned vec2_base = 64;
-const unsigned vec3_base = 96; /* above base + max_class_reg */
-const unsigned vec4_base = 112;
-const unsigned vec4_end = 128;
-
-static unsigned
-find_or_allocate_temp(compiler_context *ctx, unsigned hash)
-{
- if (hash >= SSA_FIXED_MINIMUM)
- return hash;
-
- unsigned temp = (uintptr_t) _mesa_hash_table_u64_search(ctx->hash_to_temp, hash + 1);
-
- if (temp)
- return temp - 1;
-
- /* If no temp is find, allocate one */
- temp = ctx->num_temps++;
- ctx->max_hash = MAX2(ctx->max_hash, hash);
-
- _mesa_hash_table_u64_insert(ctx->hash_to_temp, hash + 1, (void *) ((uintptr_t) temp + 1));
-
- return temp;
-}
-
-static bool
-is_live_in_instr(bifrost_instruction *instr, unsigned temp)
-{
- if (instr->ssa_args.src0 == temp) return true;
- if (instr->ssa_args.src1 == temp) return true;
- if (instr->ssa_args.src2 == temp) return true;
- if (instr->ssa_args.src3 == temp) return true;
-
- return false;
-}
-
-static bool
-is_live_after_instr(compiler_context *ctx, bifrost_block *blk, bifrost_instruction *instr, unsigned temp)
-{
- // Scan forward in the block from this location to see if we are still live.
-
- mir_foreach_instr_in_block_from(blk, ins, mir_next_instr(instr)) {
- if (is_live_in_instr(ins, temp))
- return true;
- }
-
- // XXX: Walk all successor blocks and ensure the value isn't used there
-
- return false;
-}
-
-static uint32_t
-ra_select_callback(struct ra_graph *g, BITSET_WORD *regs, void *data)
-{
- for (int i = primary_base; i < vec4_end; ++i) {
- if (BITSET_TEST(regs, i)) {
- return i;
- }
- }
-
- assert(0);
- return 0;
-}
-
-static uint32_t
-ra_get_phys_reg(compiler_context *ctx, struct ra_graph *g, unsigned temp, unsigned max_reg)
-{
- if (temp == SSA_INVALID_VALUE ||
- temp >= SSA_FIXED_UREG_MINIMUM ||
- temp == SSA_FIXED_CONST_0)
- return temp;
-
- if (temp >= SSA_FIXED_MINIMUM)
- return SSA_REG_FROM_FIXED(temp);
-
- assert(temp < max_reg);
- uint32_t r = ra_get_node_reg(g, temp);
- if (r >= vec4_base)
- return (r - vec4_base) * 4;
- else if (r >= vec3_base)
- return (r - vec3_base) * 4;
- else if (r >= vec2_base)
- return (r - vec2_base) * 2;
-
- return r;
-}
-
-static void
-allocate_registers(compiler_context *ctx)
-{
- struct ra_regs *regs = ra_alloc_reg_set(NULL, max_registers, true);
-
- int primary_class = ra_alloc_reg_class(regs);
- int vec2_class = ra_alloc_reg_class(regs);
- int vec3_class = ra_alloc_reg_class(regs);
- int vec4_class = ra_alloc_reg_class(regs);
-
- // Allocate our register classes and conflicts
- {
- unsigned reg = 0;
- unsigned primary_base = 0;
-
- // Add all of our primary scalar registers
- for (unsigned i = 0; i < max_primary_reg; ++i) {
- ra_class_add_reg(regs, primary_class, reg);
- reg++;
- }
-
- // Add all of our vec2 class registers
- // These alias with the scalar registers
- for (unsigned i = 0; i < max_vec2_reg; ++i) {
- ra_class_add_reg(regs, vec2_class, reg);
-
- // Tell RA that this conflicts with primary class registers
- // Make sure to tell the RA utility all conflict slots
- ra_add_reg_conflict(regs, reg, primary_base + i*2 + 0);
- ra_add_reg_conflict(regs, reg, primary_base + i*2 + 1);
-
- reg++;
- }
-
- // Add all of our vec3 class registers
- // These alias with the scalar registers
- for (unsigned i = 0; i < max_vec3_reg; ++i) {
- ra_class_add_reg(regs, vec3_class, reg);
-
- // Tell RA that this conflicts with primary class registers
- // Make sure to tell the RA utility all conflict slots
- // These are aligned to vec4 even though they only conflict with a vec3 wide slot
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0);
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1);
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2);
-
- // State that this class conflicts with the vec2 class
- ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0);
- ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1);
-
- reg++;
- }
-
- // Add all of our vec4 class registers
- // These alias with the scalar registers
- for (unsigned i = 0; i < max_vec4_reg; ++i) {
- ra_class_add_reg(regs, vec4_class, reg);
-
- // Tell RA that this conflicts with primary class registers
- // Make sure to tell the RA utility all conflict slots
- // These are aligned to vec4 even though they only conflict with a vec3 wide slot
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0);
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1);
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2);
- ra_add_reg_conflict(regs, reg, primary_base + i*4 + 3);
-
- // State that this class conflicts with the vec2 class
- ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0);
- ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1);
-
- // State that this class conflicts with the vec3 class
- // They conflict on the exact same location due to alignments
- ra_add_reg_conflict(regs, reg, vec3_base + i);
-
- reg++;
- }
- }
-
- ra_set_finalize(regs, NULL);
- mir_foreach_block(ctx, block) {
- mir_foreach_instr_in_block(block, instr) {
- instr->ssa_args.src0 = find_or_allocate_temp(ctx, instr->ssa_args.src0);
- instr->ssa_args.src1 = find_or_allocate_temp(ctx, instr->ssa_args.src1);
- instr->ssa_args.src2 = find_or_allocate_temp(ctx, instr->ssa_args.src2);
- instr->ssa_args.src3 = find_or_allocate_temp(ctx, instr->ssa_args.src3);
- instr->ssa_args.dest = find_or_allocate_temp(ctx, instr->ssa_args.dest);
- }
- }
-
- uint32_t nodes = ctx->num_temps;
- struct ra_graph *g = ra_alloc_interference_graph(regs, nodes);
-
- mir_foreach_block(ctx, block) {
- mir_foreach_instr_in_block(block, instr) {
- if (instr->ssa_args.dest >= SSA_FIXED_MINIMUM) continue;
- if (instr->dest_components == 4)
- ra_set_node_class(g, instr->ssa_args.dest, vec4_class);
- else if (instr->dest_components == 3)
- ra_set_node_class(g, instr->ssa_args.dest, vec3_class);
- else if (instr->dest_components == 2)
- ra_set_node_class(g, instr->ssa_args.dest, vec2_class);
- else
- ra_set_node_class(g, instr->ssa_args.dest, primary_class);
- }
- }
-
- uint32_t *live_start = malloc(nodes * sizeof(uint32_t));
- uint32_t *live_end = malloc(nodes * sizeof(uint32_t));
-
- memset(live_start, 0xFF, nodes * sizeof(uint32_t));
- memset(live_end, 0xFF, nodes * sizeof(uint32_t));
-
- uint32_t location = 0;
- mir_foreach_block(ctx, block) {
- mir_foreach_instr_in_block(block, instr) {
- if (instr->ssa_args.dest < SSA_FIXED_MINIMUM) {
- // If the destination isn't yet live before this point
- // then this is the point it becomes live since we wrote to it
- if (live_start[instr->ssa_args.dest] == ~0U) {
- live_start[instr->ssa_args.dest] = location;
- }
- }
-
- uint32_t sources[4] = {
- instr->ssa_args.src0,
- instr->ssa_args.src1,
- instr->ssa_args.src2,
- instr->ssa_args.src3,
- };
-
- for (unsigned i = 0; i < 4; ++i) {
- if (sources[i] >= SSA_FIXED_MINIMUM)
- continue;
-
- // If the source is no longer live after this instruction then we can end its liveness
- if (!is_live_after_instr(ctx, block, instr, sources[i])) {
- live_end[sources[i]] = location;
- }
- }
- ++location;
- }
- }
-
- // Spin through the nodes quick and ensure they are all killed by the end of the program
- for (unsigned i = 0; i < nodes; ++i) {
- if (live_end[i] == ~0U)
- live_end[i] = location;
- }
-
- for (int i = 0; i < nodes; ++i) {
- for (int j = i + 1; j < nodes; ++j) {
- if (!(live_start[i] >= live_end[j] || live_start[j] >= live_end[i])) {
- ra_add_node_interference(g, i, j);
- }
- }
- }
-
- ra_set_select_reg_callback(g, ra_select_callback, NULL);
-
- if (!ra_allocate(g)) {
- assert(0);
- }
-
- free(live_start);
- free(live_end);
-
- mir_foreach_block(ctx, block) {
- mir_foreach_instr_in_block(block, instr) {
- instr->args.src0 = ra_get_phys_reg(ctx, g, instr->ssa_args.src0, nodes);
- instr->args.src1 = ra_get_phys_reg(ctx, g, instr->ssa_args.src1, nodes);
- instr->args.src2 = ra_get_phys_reg(ctx, g, instr->ssa_args.src2, nodes);
- instr->args.src3 = ra_get_phys_reg(ctx, g, instr->ssa_args.src3, nodes);
- instr->args.dest = ra_get_phys_reg(ctx, g, instr->ssa_args.dest, nodes);
- }
- }
-}
-
-static void
-bundle_block(compiler_context *ctx, bifrost_block *block)
-{
-}
-
-static void
-remove_create_vectors(compiler_context *ctx, bifrost_block *block)
-{
- mir_foreach_instr_in_block_safe(block, instr) {
- if (instr->op != op_create_vector) continue;
-
- uint32_t vector_ssa_sources[4] = {
- instr->ssa_args.src0,
- instr->ssa_args.src1,
- instr->ssa_args.src2,
- instr->ssa_args.src3,
- };
-
- mir_foreach_instr_in_block_from_rev(block, next_instr, instr) {
- // Walk our block backwards and find the creators of this vector creation instruction
- for (unsigned i = 0; i < instr->dest_components; ++i) {
- // If this instruction is ther one that writes this register then forward it to the real register
- if (vector_ssa_sources[i] == next_instr->ssa_args.dest) {
- next_instr->ssa_args.dest = vector_ssa_sources[i];
- // Source instruction destination is a vector register of size dest_components
- // So dest + i gets the components of it
- next_instr->args.dest = instr->args.dest + i;
- }
- }
- }
-
- // Remove the instruction now that we have copied over all the sources
- mir_remove_instr(instr);
- }
-}
-
-static void
-remove_extract_elements(compiler_context *ctx, bifrost_block *block)
-{
- mir_foreach_instr_in_block_safe(block, instr) {
- if (instr->op != op_extract_element) continue;
-
- mir_foreach_instr_in_block_from(block, next_instr, instr) {
- // Walk our block forward to replace uses of this register with a real register
- // src0 = vector
- // src1 = index in to vector
- uint32_t vector_ssa_sources[4] = {
- next_instr->ssa_args.src0,
- next_instr->ssa_args.src1,
- next_instr->ssa_args.src2,
- next_instr->ssa_args.src3,
- };
- uint32_t *vector_sources[4] = {
- &next_instr->args.src0,
- &next_instr->args.src1,
- &next_instr->args.src2,
- &next_instr->args.src3,
- };
-
- for (unsigned i = 0; i < 4; ++i) {
- if (vector_ssa_sources[i] == instr->ssa_args.dest) {
- // This source uses this vector extraction
- // Replace its usage with the real register
- // src0 is a vector register and src1 is the constant element of the vector
- *vector_sources[i] = instr->args.src0 + instr->literal_args[0];
- }
- }
-
- }
-
- // Remove the instruction now that we have copied over all the sources
- mir_remove_instr(instr);
- }
-}
-
-
-void bifrost_schedule_program(compiler_context *ctx)
-{
- // XXX: we should move instructions together before RA that can feed in to each other and be scheduled in the same clause
- allocate_registers(ctx);
-
- mir_foreach_block(ctx, block) {
- remove_create_vectors(ctx, block);
- remove_extract_elements(ctx, block);
- }
-
- mir_foreach_block(ctx, block) {
-#ifdef BI_DEBUG
- print_mir_block(block, true);
-#endif
-
- bundle_block(ctx, block);
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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.
- */
-#ifndef bifrost_ra_h
-#define bifrost_ra_h
-#include "compiler_defines.h"
-
-void bifrost_schedule_program(compiler_context *ctx);
-
-#endif /* bifrost_ra_h */
#include "compiler/glsl/gl_nir.h"
#include "compiler/nir_types.h"
#include "util/u_dynarray.h"
-
#include "bifrost_compile.h"
static void
prog = standalone_compile_shader(&options, 2, argv, &local_ctx);
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->info.stage = MESA_SHADER_FRAGMENT;
- struct bifrost_program compiled;
+ bifrost_program compiled;
for (unsigned i = 0; i < 2; ++i) {
nir[i] = glsl_to_nir(&local_ctx, prog, shader_types[i], &bifrost_nir_options);
NIR_PASS_V(nir[i], nir_lower_global_vars_to_local);
NIR_PASS_V(nir[i], gl_nir_lower_buffers, prog);
NIR_PASS_V(nir[i], nir_opt_constant_folding);
- bifrost_compile_shader_nir(nir[i], &compiled);
+ //bifrost_compile_shader_nir(nir[i], &compiled);
}
}
+++ /dev/null
-/*
- * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
- *
- * 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.
- */
-
-#ifndef __compiler_defines_h__
-#define __compiler_defines_h__
-#include "bifrost.h"
-#include "bifrost_compile.h"
-#include "bifrost_ops.h"
-
-struct nir_builder;
-
-typedef struct ssa_args {
- uint32_t dest;
- uint32_t src0, src1, src2, src3;
-} ssa_args;
-
-/**
- * @brief Singular unpacked instruction that lives outside of the clause bundle
- */
-typedef struct bifrost_instruction {
- // Must be first
- struct list_head link;
-
- /**
- * @brief Pre-RA arguments
- */
- struct ssa_args ssa_args;
- uint32_t literal_args[4];
- uint32_t src_modifiers;
- unsigned op;
-
-
- /**
- * @brief Post-RA arguments
- */
- struct ssa_args args;
-
- /**
- * @brief The number of components that the destination takes up
- *
- * This allows the RA to understand when it needs to allocate registers from different classes
- */
- unsigned dest_components;
-
-} bifrost_instruction;
-
-typedef struct bifrost_clause {
- struct bifrost_header header;
-
- /* List of bifrost_instructions emitted for the current clause */
- struct list_head instructions;
-
-} bifrost_clause;
-
-typedef struct bifrost_block {
- /* Link to next block. Must be first for mir_get_block */
- struct list_head link;
-
- /* List of bifrost_instructions emitted for the current block */
- struct list_head instructions;
-
- /* List of bifrost clauses to be emitted for the current block*/
- struct util_dynarray clauses;
-
- /* Maximum number of successors is 2 */
- struct bifrost_block *successors[2];
- uint32_t num_successors;
-
-} bifrost_block;
-
-typedef struct compiler_context {
- nir_shader *nir;
- gl_shader_stage stage;
-
- /* Current NIR function */
- nir_function *func;
- struct nir_builder *b;
-
- /* Unordered list of bifrost_blocks */
- uint32_t block_count;
- struct list_head blocks;
-
- /* The current block we are operating on */
- struct bifrost_block *current_block;
-
- struct hash_table_u64 *ssa_constants;
-
- /* Uniform IDs */
- struct hash_table_u64 *uniform_nir_to_bi;
- uint32_t uniform_count;
-
- struct hash_table_u64 *varying_nir_to_bi;
- uint32_t varying_count;
-
- struct hash_table_u64 *outputs_nir_to_bi;
- uint32_t outputs_count;
-
- /* Count of instructions emitted from NIR overall, across all blocks */
- uint32_t instruction_count;
-
- uint32_t mir_temp;
-
- struct hash_table_u64 *hash_to_temp;
- uint32_t num_temps;
-
- uint32_t max_hash;
-
-} compiler_context;
-
-#define mir_foreach_block(ctx, v) list_for_each_entry(struct bifrost_block, v, &ctx->blocks, link)
-#define mir_foreach_block_from(ctx, from, v) list_for_each_entry_from(struct bifrost_block, v, from, &ctx->blocks, link)
-
-#define mir_last_block(ctx) list_last_entry(&ctx->blocks, struct bifrost_block, link)
-
-#define mir_foreach_instr(ctx, v) list_for_each_entry(struct bifrost_instruction, v, &ctx->current_block->instructions, link)
-#define mir_foreach_instr_in_block(block, v) list_for_each_entry(struct bifrost_instruction, v, &block->instructions, link)
-#define mir_foreach_instr_in_block_from(block, v, from) list_for_each_entry_from(struct bifrost_instruction, v, from, &block->instructions, link)
-#define mir_foreach_instr_in_block_safe(block, v) list_for_each_entry_safe(struct bifrost_instruction, v, &block->instructions, link)
-#define mir_last_instr_in_block(block) list_last_entry(&block->instructions, struct bifrost_instruction, link)
-#define mir_foreach_instr_in_block_from_rev(block, v, from) list_for_each_entry_from_rev(struct bifrost_instruction, v, from, &block->instructions, link)
-
-#define mir_next_instr(from) list_first_entry(&(from->link), struct bifrost_instruction, link)
-#define mir_remove_instr(instr) list_del(&instr->link)
-
-#define mir_insert_instr_before(before, ins) list_addtail(&(mir_alloc_ins(ins))->link, &before->link)
-
-#define SSA_INVALID_VALUE ~0U
-#define SSA_TEMP_SHIFT 24
-#define SSA_FIXED_REGISTER_SHIFT 25
-
-#define SSA_FIXED_REGISTER(x) ((1U << SSA_FIXED_REGISTER_SHIFT) + (x))
-#define SSA_REG_FROM_FIXED(x) ((x) & ~(1U << SSA_FIXED_REGISTER_SHIFT))
-
-#define SSA_FIXED_MINIMUM SSA_FIXED_REGISTER(0)
-#define SSA_FIXED_UREG_MINIMUM SSA_FIXED_REGISTER(64)
-#define SSA_FIXED_CONST_0 SSA_FIXED_REGISTER(256 + 64)
-
-#define SSA_FIXED_UREGISTER(x) (SSA_FIXED_REGISTER(x + 64))
-#define SSA_UREG_FROM_FIXED(x) (SSA_REG_FROM_FIXED(x) - 64)
-
-#define SSA_TEMP_VALUE(x) ((1U << SSA_TEMP_SHIFT) + (x))
-#define SSA_TEMP_FROM_VALUE(x) (((x) & ~(1U << SSA_TEMP_SHIFT)))
-#define MIR_TEMP_MINIMUM SSA_TEMP_VALUE(0)
-
-#define SRC_MOD_ABS 1
-#define SRC_MOD_NEG 2
-#define MOD_SIZE 2
-#define SOURCE_MODIFIER(src, mod) (mod << (src * MOD_SIZE))
-
-struct bifrost_instruction *
-mir_alloc_ins(struct bifrost_instruction instr);
-
-#endif
#include <string.h>
#include "bifrost.h"
-#include "bifrost_ops.h"
#include "disassemble.h"
#include "util/macros.h"
}
fprintf(fp, ".v%d", ((ADD.op >> 5) & 0x3) + 1);
} else if (info.src_type == ADD_BRANCH) {
- enum branch_code branchCode = (enum branch_code) ((ADD.op >> 6) & 0x3f);
+ enum bifrost_branch_code branchCode = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f);
if (branchCode == BR_ALWAYS) {
// unconditional branch
} else {
- enum branch_cond cond = (enum branch_cond) ((ADD.op >> 6) & 0x7);
+ enum bifrost_branch_cond cond = (enum bifrost_branch_cond) ((ADD.op >> 6) & 0x7);
enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7);
bool portSwapped = (ADD.op & 0x7) < ADD.src0;
// See the comment in branch_bit_size
dump_16swizzle(fp, (ADD.op >> 8) & 0x3);
break;
case ADD_BRANCH: {
- enum branch_code code = (enum branch_code) ((ADD.op >> 6) & 0x3f);
+ enum bifrost_branch_code code = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f);
enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7);
if (code != BR_ALWAYS) {
dump_src(fp, ADD.src0, regs, consts, false);
# SOFTWARE.
libpanfrost_bifrost_files = files(
- 'bifrost_compile.c',
- 'bifrost_opts.c',
- 'bifrost_sched.c',
- 'bifrost_print.c',
'disassemble.c',
)