

new file mode 100644

index 00000000000..bc58575c789

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefilenew file mode 100644index 00000000000..bc58575c789--- /dev/null+++ b/ src/gallium/drivers/r600/Makefile @@ -0,0 +1,26 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = r600 + +LIBRARY_INCLUDES = \ + $(shell pkg-config libdrm --cflags-only-I) + +C_SOURCES = \ + r600_buffer.c \ + r600_context.c \ + r600_draw.c \ + r600_blit.c \ + r600_helper.c \ + r600_query.c \ + r600_screen.c \ + r600_state.c \ + r600_texture.c \ + r600_shader.c \ + r600_compiler.c \ + r600_compiler_tgsi.c \ + r600_compiler_dump.c \ + r600_compiler_r600.c \ + r600_compiler_r700.c + +include ../../Makefile.template

new file mode 100644

index 00000000000..a88c5452529

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/SConscript b/src/gallium/drivers/r600/SConscriptnew file mode 100644index 00000000000..a88c5452529--- /dev/null+++ b/ src/gallium/drivers/r600/SConscript @@ -0,0 +1,21 @@ +Import('*') + +env = env.Clone() +env.Append(CPPPATH = [ + '#/include', + '#/src/mesa', +]) + +r600 = env.ConvenienceLibrary( + target = 'r600', + source = [ + 'r600_buffer.c', + 'r600_context.c', + 'r600_draw.c', + 'r600_query.c', + 'r600_screen.c', + 'r600_state.c', + 'r600_texture.c', + ]) + +Export('r600')

new file mode 100644

index 00000000000..88b865ef9a6

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.cnew file mode 100644index 00000000000..88b865ef9a6--- /dev/null+++ b/ src/gallium/drivers/r600/r600_blit.c @@ -0,0 +1,81 @@ +/* + * Copyright 2009 Marek Olšák <maraeo@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Authors: + * Jerome Glisse + * Marek Olšák + */ +#include <pipe/p_screen.h> +#include <util/u_blitter.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include "r600_screen.h" +#include "r600_texture.h" +#include "r600_context.h" + +static void r600_blitter_save_states(struct pipe_context *ctx) +{ + struct r600_context *rctx = (struct r600_context*)ctx; + + util_blitter_save_blend(rctx->blitter, + rctx->draw->state[R600_BLEND]); + util_blitter_save_depth_stencil_alpha(rctx->blitter, + rctx->draw->state[R600_DSA]); + util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref); + util_blitter_save_rasterizer(rctx->blitter, + rctx->draw->state[R600_RASTERIZER]); + util_blitter_save_fragment_shader(rctx->blitter, + rctx->ps_shader); + util_blitter_save_vertex_shader(rctx->blitter, + rctx->vs_shader); +} + +void r600_clear(struct pipe_context *ctx, unsigned buffers, + const float *rgba, double depth, unsigned stencil) +{ + struct r600_context *rctx = (struct r600_context*)ctx; + struct pipe_framebuffer_state *fb = &rctx->fb_state; + +#if 0 + r600_blitter_save_states(ctx); + util_blitter_clear(rctx->blitter, fb->width, fb->height, + fb->nr_cbufs, buffers, rgba, depth, + stencil); +#endif +} + +void r600_surface_copy(struct pipe_context *ctx, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + struct pipe_surface *src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ +} + +void r600_surface_fill(struct pipe_context *ctx, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + unsigned value) +{ +}

new file mode 100644

index 00000000000..f3a0208b003

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.cnew file mode 100644index 00000000000..f3a0208b003--- /dev/null+++ b/ src/gallium/drivers/r600/r600_buffer.c @@ -0,0 +1,177 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Authors: + * Jerome Glisse + * Corbin Simpson <MostAwesomeDude@gmail.com> + */ +#include <pipe/p_screen.h> +#include <util/u_format.h> +#include <util/u_math.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include "r600_screen.h" +#include "r600_texture.h" +#include "r600_context.h" + +static u32 r600_domain_from_usage(unsigned usage) +{ + u32 domain = RADEON_GEM_DOMAIN_GTT; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + if (usage & PIPE_BUFFER_USAGE_INDEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + return domain; +} + +static struct pipe_buffer *r600_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct r600_screen *rscreen = r600_screen(screen); + struct r600_pipe_buffer *rbuffer; + struct radeon_bo *bo; + struct pb_desc desc; + + rbuffer = CALLOC_STRUCT(r600_pipe_buffer); + if (rbuffer == NULL) + return NULL; + + pipe_reference_init(&rbuffer->base.reference, 1); + rbuffer->base.screen = screen; + rbuffer->base.alignment = alignment; + rbuffer->base.usage = usage; + rbuffer->base.size = size; + + if (usage & PIPE_BUFFER_USAGE_CONSTANT) { + desc.alignment = alignment; + desc.usage = usage; + rbuffer->pb = pb_malloc_buffer_create(size, &desc); + if (rbuffer->pb == NULL) { + free(rbuffer); + return NULL; + } + return &rbuffer->base; + } + rbuffer->domain = r600_domain_from_usage(usage); + bo = radeon_bo(rscreen->rw, 0, size, alignment, NULL); + if (bo == NULL) { + FREE(rbuffer); + return NULL; + } + rbuffer->bo = bo; + return &rbuffer->base; +} + +static struct pipe_buffer *r600_user_buffer_create(struct pipe_screen *screen, + void *ptr, unsigned bytes) +{ + struct r600_pipe_buffer *rbuffer; + struct r600_screen *rscreen = r600_screen(screen); + + rbuffer = (struct r600_pipe_buffer*)r600_buffer_create(screen, 0, 0, bytes); + if (rbuffer == NULL) { + return NULL; + } + radeon_bo_map(rscreen->rw, rbuffer->bo); + memcpy(rbuffer->bo->data, ptr, bytes); + radeon_bo_unmap(rscreen->rw, rbuffer->bo); + return &rbuffer->base; +} + +static void r600_buffer_destroy(struct pipe_buffer *buffer) +{ + struct r600_pipe_buffer *rbuffer = (struct r600_pipe_buffer*)buffer; + struct r600_screen *rscreen = r600_screen(buffer->screen); + + if (rbuffer->pb) { + pipe_reference_init(&rbuffer->pb->base.reference, 0); + pb_destroy(rbuffer->pb); + rbuffer->pb = NULL; + } + if (rbuffer->bo) { + radeon_bo_decref(rscreen->rw, rbuffer->bo); + } + FREE(rbuffer); +} + +static void *r600_buffer_map_range(struct pipe_screen *screen, + struct pipe_buffer *buffer, + unsigned offset, unsigned length, + unsigned usage) +{ + struct r600_pipe_buffer *rbuffer = (struct r600_pipe_buffer*)buffer; + struct r600_screen *rscreen = r600_screen(buffer->screen); + int write = 0; + + if (rbuffer->pb) { + return pb_map(rbuffer->pb, usage); + } + if (usage & PIPE_BUFFER_USAGE_DONTBLOCK) { + /* FIXME */ + } + if (usage & PIPE_BUFFER_USAGE_CPU_WRITE) { + write = 1; + } + if (radeon_bo_map(rscreen->rw, rbuffer->bo)) { + return NULL; + } + return rbuffer->bo->data; +} + +static void r600_buffer_unmap( struct pipe_screen *screen, struct pipe_buffer *buffer) +{ + struct r600_pipe_buffer *rbuffer = (struct r600_pipe_buffer*)buffer; + struct r600_screen *rscreen = r600_screen(buffer->screen); + + if (rbuffer->pb) { + pb_unmap(rbuffer->pb); + } else { + radeon_bo_unmap(rscreen->rw, rbuffer->bo); + } +} + +static void r600_buffer_flush_mapped_range(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned offset, unsigned length) +{ +} + +void r600_screen_init_buffer_functions(struct pipe_screen *screen) +{ + screen->buffer_create = r600_buffer_create; + screen->user_buffer_create = r600_user_buffer_create; + screen->buffer_map_range = r600_buffer_map_range; + screen->buffer_flush_mapped_range = r600_buffer_flush_mapped_range; + screen->buffer_unmap = r600_buffer_unmap; + screen->buffer_destroy = r600_buffer_destroy; +}

new file mode 100644

index 00000000000..f1be2bbdf4f

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler.c b/src/gallium/drivers/r600/r600_compiler.cnew file mode 100644index 00000000000..f1be2bbdf4f--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler.c @@ -0,0 +1,446 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include "r600_compiler.h" + +struct c_vector *c_vector_new(void) +{ + struct c_vector *v = calloc(1, sizeof(struct c_vector)); + + if (v == NULL) { + return NULL; + } + c_list_init(v); + return v; +} + +static unsigned c_opcode_is_alu(unsigned opcode) +{ + switch (opcode) { + case C_OPCODE_MOV: + case C_OPCODE_MUL: + case C_OPCODE_MAD: + case C_OPCODE_ARL: + case C_OPCODE_LIT: + case C_OPCODE_RCP: + case C_OPCODE_RSQ: + case C_OPCODE_EXP: + case C_OPCODE_LOG: + case C_OPCODE_ADD: + case C_OPCODE_DP3: + case C_OPCODE_DP4: + case C_OPCODE_DST: + case C_OPCODE_MIN: + case C_OPCODE_MAX: + case C_OPCODE_SLT: + case C_OPCODE_SGE: + case C_OPCODE_SUB: + case C_OPCODE_LRP: + case C_OPCODE_CND: + case C_OPCODE_DP2A: + case C_OPCODE_FRC: + case C_OPCODE_CLAMP: + case C_OPCODE_FLR: + case C_OPCODE_ROUND: + case C_OPCODE_EX2: + case C_OPCODE_LG2: + case C_OPCODE_POW: + case C_OPCODE_XPD: + case C_OPCODE_ABS: + case C_OPCODE_RCC: + case C_OPCODE_DPH: + case C_OPCODE_COS: + case C_OPCODE_DDX: + case C_OPCODE_DDY: + case C_OPCODE_PK2H: + case C_OPCODE_PK2US: + case C_OPCODE_PK4B: + case C_OPCODE_PK4UB: + case C_OPCODE_RFL: + case C_OPCODE_SEQ: + case C_OPCODE_SFL: + case C_OPCODE_SGT: + case C_OPCODE_SIN: + case C_OPCODE_SLE: + case C_OPCODE_SNE: + case C_OPCODE_STR: + case C_OPCODE_UP2H: + case C_OPCODE_UP2US: + case C_OPCODE_UP4B: + case C_OPCODE_UP4UB: + case C_OPCODE_X2D: + case C_OPCODE_ARA: + case C_OPCODE_ARR: + case C_OPCODE_BRA: + case C_OPCODE_SSG: + case C_OPCODE_CMP: + case C_OPCODE_SCS: + case C_OPCODE_NRM: + case C_OPCODE_DIV: + case C_OPCODE_DP2: + case C_OPCODE_CEIL: + case C_OPCODE_I2F: + case C_OPCODE_NOT: + case C_OPCODE_TRUNC: + case C_OPCODE_SHL: + case C_OPCODE_AND: + case C_OPCODE_OR: + case C_OPCODE_MOD: + case C_OPCODE_XOR: + case C_OPCODE_SAD: + case C_OPCODE_NRM4: + case C_OPCODE_F2I: + case C_OPCODE_IDIV: + case C_OPCODE_IMAX: + case C_OPCODE_IMIN: + case C_OPCODE_INEG: + case C_OPCODE_ISGE: + case C_OPCODE_ISHR: + case C_OPCODE_ISLT: + case C_OPCODE_F2U: + case C_OPCODE_U2F: + case C_OPCODE_UADD: + case C_OPCODE_UDIV: + case C_OPCODE_UMAD: + case C_OPCODE_UMAX: + case C_OPCODE_UMIN: + case C_OPCODE_UMOD: + case C_OPCODE_UMUL: + case C_OPCODE_USEQ: + case C_OPCODE_USGE: + case C_OPCODE_USHR: + case C_OPCODE_USLT: + case C_OPCODE_USNE: + return 1; + case C_OPCODE_END: + case C_OPCODE_VFETCH: + case C_OPCODE_KILP: + case C_OPCODE_CAL: + case C_OPCODE_RET: + case C_OPCODE_TXB: + case C_OPCODE_TXL: + case C_OPCODE_BRK: + case C_OPCODE_IF: + case C_OPCODE_BGNFOR: + case C_OPCODE_REP: + case C_OPCODE_ELSE: + case C_OPCODE_ENDIF: + case C_OPCODE_ENDFOR: + case C_OPCODE_ENDREP: + case C_OPCODE_PUSHA: + case C_OPCODE_POPA: + case C_OPCODE_TXF: + case C_OPCODE_TXQ: + case C_OPCODE_CONT: + case C_OPCODE_EMIT: + case C_OPCODE_ENDPRIM: + case C_OPCODE_BGNLOOP: + case C_OPCODE_BGNSUB: + case C_OPCODE_ENDLOOP: + case C_OPCODE_ENDSUB: + case C_OPCODE_NOP: + case C_OPCODE_CALLNZ: + case C_OPCODE_IFC: + case C_OPCODE_BREAKC: + case C_OPCODE_KIL: + case C_OPCODE_TEX: + case C_OPCODE_TXD: + case C_OPCODE_TXP: + case C_OPCODE_SWITCH: + case C_OPCODE_CASE: + case C_OPCODE_DEFAULT: + case C_OPCODE_ENDSWITCH: + default: + return 0; + } +} + + +/* NEW */ +void c_node_init(struct c_node *node) +{ + memset(node, 0, sizeof(struct c_node)); + c_list_init(&node->predecessors); + c_list_init(&node->successors); + c_list_init(&node->childs); + c_list_init(&node->insts); + node->parent = NULL; +} + +static struct c_node_link *c_node_link_new(struct c_node *node) +{ + struct c_node_link *link; + + link = calloc(1, sizeof(struct c_node_link)); + if (link == NULL) + return NULL; + c_list_init(link); + link->node = node; + return link; +} + +int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor) +{ + struct c_node_link *pedge, *sedge; + + pedge = c_node_link_new(successor); + sedge = c_node_link_new(predecessor); + if (sedge == NULL || pedge == NULL) { + free(sedge); + free(pedge); + return -ENOMEM; + } + c_list_add_tail(pedge, &predecessor->successors); + c_list_add_tail(sedge, &successor->predecessors); + return 0; +} + +int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction) +{ + struct c_instruction *inst = calloc(1, sizeof(struct c_instruction)); + + if (inst == NULL) + return -ENOMEM; + memcpy(inst, instruction, sizeof(struct c_instruction)); + c_list_add(inst, &node->insts); + return 0; +} + +int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction) +{ + struct c_instruction *inst = calloc(1, sizeof(struct c_instruction)); + + if (inst == NULL) + return -ENOMEM; + memcpy(inst, instruction, sizeof(struct c_instruction)); + c_list_add_tail(inst, &node->insts); + return 0; +} + +struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor) +{ + struct c_node *node = calloc(1, sizeof(struct c_node)); + + if (node == NULL) + return NULL; + c_node_init(node); + if (c_node_cfg_link(predecessor, node)) { + free(node); + return NULL; + } + c_list_add_tail(node, &shader->nodes); + return node; +} + +int c_shader_init(struct c_shader *shader, unsigned type) +{ + unsigned i; + int r; + + shader->type = type; + for (i = 0; i < C_FILE_COUNT; i++) { + shader->files[i].nvectors = 0; + c_list_init(&shader->files[i].vectors); + } + c_list_init(&shader->nodes); + c_node_init(&shader->entry); + c_node_init(&shader->end); + shader->entry.opcode = C_OPCODE_ENTRY; + shader->end.opcode = C_OPCODE_END; + r = c_node_cfg_link(&shader->entry, &shader->end); + if (r) + return r; + return 0; +} + +struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid) +{ + struct c_vector *v = calloc(1, sizeof(struct c_vector)); + int i; + + if (v == NULL) { + return NULL; + } + for (i = 0; i < 4; i++) { + v->channel[i] = calloc(1, sizeof(struct c_channel)); + if (v->channel[i] == NULL) + goto out_err; + v->channel[i]->vindex = i; + v->channel[i]->vector = v; + } + v->file = file; + v->name = name; + v->sid = sid; + shader->files[v->file].nvectors++; + v->id = shader->nvectors++; + c_list_add_tail(v, &shader->files[v->file].vectors); + return v; +out_err: + for (i = 0; i < 4; i++) { + free(v->channel[i]); + } + free(v); + return NULL; +} + +static void c_node_remove_link(struct c_node_link *head, struct c_node *node) +{ + struct c_node_link *link, *tmp; + + c_list_for_each_safe(link, tmp, head) { + if (link->node == node) { + c_list_del(link); + free(link); + } + } +} + +static void c_node_destroy(struct c_node *node) +{ + struct c_instruction *i, *ni; + struct c_node_link *link, *tmp; + + c_list_for_each_safe(i, ni, &node->insts) { + c_list_del(i); + free(i); + } + if (node->parent) + c_node_remove_link(&node->parent->childs, node); + node->parent = NULL; + c_list_for_each_safe(link, tmp, &node->predecessors) { + c_node_remove_link(&link->node->successors, node); + c_list_del(link); + free(link); + } + c_list_for_each_safe(link, tmp, &node->successors) { + c_node_remove_link(&link->node->predecessors, node); + c_list_del(link); + free(link); + } + c_list_for_each_safe(link, tmp, &node->childs) { + link->node->parent = NULL; + c_list_del(link); + free(link); + } +} + +void c_shader_destroy(struct c_shader *shader) +{ + struct c_node *n, *nn; + struct c_vector *v, *nv; + unsigned i; + + for (i = 0; i < C_FILE_COUNT; i++) { + shader->files[i].nvectors = 0; + c_list_for_each_safe(v, nv, &shader->files[i].vectors) { + c_list_del(v); + free(v->channel[0]); + free(v->channel[1]); + free(v->channel[2]); + free(v->channel[3]); + free(v); + } + } + c_list_for_each_safe(n, nn, &shader->nodes) { + c_list_del(n); + c_node_destroy(n); + } + memset(shader, 0, sizeof(struct c_shader)); +} + +static void c_shader_dfs_without_rec(struct c_node *entry, struct c_node *node) +{ + struct c_node_link *link; + + if (entry == node || entry->visited) + return; + entry->visited = 1; + c_list_for_each(link, &entry->successors) { + c_shader_dfs_without_rec(link->node, node); + } +} + +static void c_shader_dfs_without(struct c_shader *shader, struct c_node *node) +{ + struct c_node *n; + + shader->entry.visited = 0; + shader->end.visited = 0; + c_list_for_each(n, &shader->nodes) { + n->visited = 0; + } + c_shader_dfs_without_rec(&shader->entry, node); +} + +static int c_shader_build_dominator_tree_rec(struct c_shader *shader, struct c_node *node) +{ + struct c_node_link *link, *nlink; + unsigned found = 0; + int r; + + if (node->done) + return 0; + node->done = 1; + c_list_for_each(link, &node->predecessors) { + /* if we remove this predecessor can we reach the current node ? */ + c_shader_dfs_without(shader, link->node); + if (node->visited == 0) { + /* we were unable to visit current node thus current + * predecessor is the immediate dominator of node, as + * their can be only one immediate dominator we break + */ + node->parent = link->node; + nlink = c_node_link_new(node); + if (nlink == NULL) + return -ENOMEM; + c_list_add_tail(nlink, &link->node->childs); + found = 1; + break; + } + } + /* this shouldn't happen there should at least be 1 denominator for each node */ + if (!found && node->opcode != C_OPCODE_ENTRY) { + fprintf(stderr, "invalid flow control graph node %p (%d) has no immediate dominator

", + node, node->opcode); + return -EINVAL; + } + c_list_for_each(link, &node->predecessors) { + r = c_shader_build_dominator_tree_rec(shader, link->node); + if (r) + return r; + } + return 0; +} + +int c_shader_build_dominator_tree(struct c_shader *shader) +{ + struct c_node *node; + c_list_for_each(node, &shader->nodes) { + node->done = 0; + } + return c_shader_build_dominator_tree_rec(shader, &shader->end); +}

new file mode 100644

index 00000000000..d3c13b519be

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler.h b/src/gallium/drivers/r600/r600_compiler.hnew file mode 100644index 00000000000..d3c13b519be--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler.h @@ -0,0 +1,329 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 R600_COMPILER_H +#define R600_COMPILER_H + +struct c_vector; + +/* operand are the basic source/destination of each operation */ +struct c_channel { + struct c_channel *next; + struct c_channel *prev; + unsigned vindex; /**< index in vector X,Y,Z,W (0,1,2,3) */ + unsigned value; /**< immediate value 32bits */ + struct c_vector *vector; /**< vector to which it belongs */ +}; + +/* in GPU world most of the time operand are grouped into vector + * of 4 component this structure is mostly and handler to group + * operand into a same vector + */ +struct c_vector { + struct c_vector *next; + struct c_vector *prev; + unsigned id; /**< vector uniq id */ + unsigned name; /**< semantic name */ + unsigned file; /**< operand file C_FILE_* */ + int sid; /**< semantic id */ + struct c_channel *channel[4]; /**< operands */ +}; + +#define c_list_init(e) do { (e)->next = e; (e)->prev = e; } while(0) +#define c_list_add(e, h) do { (e)->next = (h)->next; (e)->prev = h; (h)->next = e; (e)->next->prev = e; } while(0) +#define c_list_add_tail(e, h) do { (e)->next = h; (e)->prev = (h)->prev; (h)->prev = e; (e)->prev->next = e; } while(0) +#define c_list_del(e) do { (e)->next->prev = (e)->prev; (e)->prev->next = (e)->next; c_list_init(e); } while(0) +#define c_list_for_each(p, h) for (p = (h)->next; p != (h); p = p->next) +#define c_list_for_each_from(p, s, h) for (p = s; p != (h); p = p->next) +#define c_list_for_each_safe(p, n, h) for (p = (h)->next, n = p->next; p != (h); p = n, n = p->next) +#define c_list_empty(h) ((h)->next == h) + + +#define C_PROGRAM_TYPE_VS 0 +#define C_PROGRAM_TYPE_FS 1 +#define C_PROGRAM_TYPE_COUNT 2 + +#define C_NODE_FLAG_ALU 1 +#define C_NODE_FLAG_FETCH 2 + +#define C_SWIZZLE_X 0 +#define C_SWIZZLE_Y 1 +#define C_SWIZZLE_Z 2 +#define C_SWIZZLE_W 3 +#define C_SWIZZLE_0 4 +#define C_SWIZZLE_1 5 +#define C_SWIZZLE_D 6 /**< discard */ + +#define C_FILE_NULL 0 +#define C_FILE_CONSTANT 1 +#define C_FILE_INPUT 2 +#define C_FILE_OUTPUT 3 +#define C_FILE_TEMPORARY 4 +#define C_FILE_SAMPLER 5 +#define C_FILE_ADDRESS 6 +#define C_FILE_IMMEDIATE 7 +#define C_FILE_LOOP 8 +#define C_FILE_PREDICATE 9 +#define C_FILE_SYSTEM_VALUE 10 +#define C_FILE_RESOURCE 11 +#define C_FILE_COUNT 12 + +#define C_SEMANTIC_POSITION 0 +#define C_SEMANTIC_COLOR 1 +#define C_SEMANTIC_BCOLOR 2 /**< back-face color */ +#define C_SEMANTIC_FOG 3 +#define C_SEMANTIC_PSIZE 4 +#define C_SEMANTIC_GENERIC 5 +#define C_SEMANTIC_NORMAL 6 +#define C_SEMANTIC_FACE 7 +#define C_SEMANTIC_EDGEFLAG 8 +#define C_SEMANTIC_PRIMID 9 +#define C_SEMANTIC_INSTANCEID 10 +#define C_SEMANTIC_VERTEXID 11 +#define C_SEMANTIC_COUNT 12 /**< number of semantic values */ + +#define C_OPCODE_ARL 0 +#define C_OPCODE_MOV 1 +#define C_OPCODE_LIT 2 +#define C_OPCODE_RCP 3 +#define C_OPCODE_RSQ 4 +#define C_OPCODE_EXP 5 +#define C_OPCODE_LOG 6 +#define C_OPCODE_MUL 7 +#define C_OPCODE_ADD 8 +#define C_OPCODE_DP3 9 +#define C_OPCODE_DP4 10 +#define C_OPCODE_DST 11 +#define C_OPCODE_MIN 12 +#define C_OPCODE_MAX 13 +#define C_OPCODE_SLT 14 +#define C_OPCODE_SGE 15 +#define C_OPCODE_MAD 16 +#define C_OPCODE_SUB 17 +#define C_OPCODE_LRP 18 +#define C_OPCODE_CND 19 +/* gap */ +#define C_OPCODE_DP2A 21 +/* gap */ +#define C_OPCODE_FRC 24 +#define C_OPCODE_CLAMP 25 +#define C_OPCODE_FLR 26 +#define C_OPCODE_ROUND 27 +#define C_OPCODE_EX2 28 +#define C_OPCODE_LG2 29 +#define C_OPCODE_POW 30 +#define C_OPCODE_XPD 31 +/* gap */ +#define C_OPCODE_ABS 33 +#define C_OPCODE_RCC 34 +#define C_OPCODE_DPH 35 +#define C_OPCODE_COS 36 +#define C_OPCODE_DDX 37 +#define C_OPCODE_DDY 38 +#define C_OPCODE_KILP 39 /* predicated kill */ +#define C_OPCODE_PK2H 40 +#define C_OPCODE_PK2US 41 +#define C_OPCODE_PK4B 42 +#define C_OPCODE_PK4UB 43 +#define C_OPCODE_RFL 44 +#define C_OPCODE_SEQ 45 +#define C_OPCODE_SFL 46 +#define C_OPCODE_SGT 47 +#define C_OPCODE_SIN 48 +#define C_OPCODE_SLE 49 +#define C_OPCODE_SNE 50 +#define C_OPCODE_STR 51 +#define C_OPCODE_TEX 52 +#define C_OPCODE_TXD 53 +#define C_OPCODE_TXP 54 +#define C_OPCODE_UP2H 55 +#define C_OPCODE_UP2US 56 +#define C_OPCODE_UP4B 57 +#define C_OPCODE_UP4UB 58 +#define C_OPCODE_X2D 59 +#define C_OPCODE_ARA 60 +#define C_OPCODE_ARR 61 +#define C_OPCODE_BRA 62 +#define C_OPCODE_CAL 63 +#define C_OPCODE_RET 64 +#define C_OPCODE_SSG 65 /* SGN */ +#define C_OPCODE_CMP 66 +#define C_OPCODE_SCS 67 +#define C_OPCODE_TXB 68 +#define C_OPCODE_NRM 69 +#define C_OPCODE_DIV 70 +#define C_OPCODE_DP2 71 +#define C_OPCODE_TXL 72 +#define C_OPCODE_BRK 73 +#define C_OPCODE_IF 74 +#define C_OPCODE_BGNFOR 75 +#define C_OPCODE_REP 76 +#define C_OPCODE_ELSE 77 +#define C_OPCODE_ENDIF 78 +#define C_OPCODE_ENDFOR 79 +#define C_OPCODE_ENDREP 80 +#define C_OPCODE_PUSHA 81 +#define C_OPCODE_POPA 82 +#define C_OPCODE_CEIL 83 +#define C_OPCODE_I2F 84 +#define C_OPCODE_NOT 85 +#define C_OPCODE_TRUNC 86 +#define C_OPCODE_SHL 87 +/* gap */ +#define C_OPCODE_AND 89 +#define C_OPCODE_OR 90 +#define C_OPCODE_MOD 91 +#define C_OPCODE_XOR 92 +#define C_OPCODE_SAD 93 +#define C_OPCODE_TXF 94 +#define C_OPCODE_TXQ 95 +#define C_OPCODE_CONT 96 +#define C_OPCODE_EMIT 97 +#define C_OPCODE_ENDPRIM 98 +#define C_OPCODE_BGNLOOP 99 +#define C_OPCODE_BGNSUB 100 +#define C_OPCODE_ENDLOOP 101 +#define C_OPCODE_ENDSUB 102 +/* gap */ +#define C_OPCODE_NOP 107 +/* gap */ +#define C_OPCODE_NRM4 112 +#define C_OPCODE_CALLNZ 113 +#define C_OPCODE_IFC 114 +#define C_OPCODE_BREAKC 115 +#define C_OPCODE_KIL 116 /* conditional kill */ +#define C_OPCODE_END 117 /* aka HALT */ +/* gap */ +#define C_OPCODE_F2I 119 +#define C_OPCODE_IDIV 120 +#define C_OPCODE_IMAX 121 +#define C_OPCODE_IMIN 122 +#define C_OPCODE_INEG 123 +#define C_OPCODE_ISGE 124 +#define C_OPCODE_ISHR 125 +#define C_OPCODE_ISLT 126 +#define C_OPCODE_F2U 127 +#define C_OPCODE_U2F 128 +#define C_OPCODE_UADD 129 +#define C_OPCODE_UDIV 130 +#define C_OPCODE_UMAD 131 +#define C_OPCODE_UMAX 132 +#define C_OPCODE_UMIN 133 +#define C_OPCODE_UMOD 134 +#define C_OPCODE_UMUL 135 +#define C_OPCODE_USEQ 136 +#define C_OPCODE_USGE 137 +#define C_OPCODE_USHR 138 +#define C_OPCODE_USLT 139 +#define C_OPCODE_USNE 140 +#define C_OPCODE_SWITCH 141 +#define C_OPCODE_CASE 142 +#define C_OPCODE_DEFAULT 143 +#define C_OPCODE_ENDSWITCH 144 +#define C_OPCODE_VFETCH 145 +#define C_OPCODE_ENTRY 146 +#define C_OPCODE_LAST 147 + +#define C_OPERAND_FLAG_ABS (1 << 0) +#define C_OPERAND_FLAG_NEG (1 << 1) + +struct c_operand { + struct c_vector *vector; + unsigned swizzle[4]; + unsigned flag[4]; +}; + +struct c_instruction { + struct c_instruction *next, *prev; + unsigned opcode; + unsigned ninput; + struct c_operand input[3]; + struct c_operand output; + unsigned write_mask; + void *backend; +}; + +struct c_node; + +struct c_node_link { + struct c_node_link *next; + struct c_node_link *prev; + struct c_node *node; +}; + +/** + * struct c_node + * + * @next: all node are in a double linked list, this point to + * next node + * @next: all node are in a double linked list, this point to + * previous node + * @predecessors: list of all predecessor nodes in the flow graph + * @successors: list of all sucessor nodes in the flow graph + * @parent: parent node in the depth first walk tree + * @childs: child nodes in the depth first walk tree + */ +struct c_node { + struct c_node *next, *prev; + struct c_node_link predecessors; + struct c_node_link successors; + struct c_node *parent; + struct c_node_link childs; + struct c_instruction insts; + unsigned opcode; + unsigned visited; + unsigned done; + void *backend; +}; + +struct c_file { + unsigned nvectors; + struct c_vector vectors; +}; + +struct c_shader { + unsigned nvectors; + struct c_file files[C_FILE_COUNT]; + struct c_node nodes; + struct c_node entry; + struct c_node end; + unsigned type; +}; + +int c_shader_init(struct c_shader *shader, unsigned type); +void c_shader_destroy(struct c_shader *shader); +struct c_vector *c_shader_vector_new(struct c_shader *shader, unsigned file, unsigned name, int sid); +int c_shader_build_dominator_tree(struct c_shader *shader); +void c_shader_dump(struct c_shader *shader); + +void c_node_init(struct c_node *node); +int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction); +int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction); + +/* control flow graph functions */ +int c_node_cfg_link(struct c_node *predecessor, struct c_node *successor); +struct c_node *c_node_cfg_new_after(struct c_node *predecessor); +struct c_node *c_shader_cfg_new_node_after(struct c_shader *shader, struct c_node *predecessor); + +struct c_vector *c_vector_new(void); + +#endif

new file mode 100644

index 00000000000..9df6a38598e

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler_dump.c b/src/gallium/drivers/r600/r600_compiler_dump.cnew file mode 100644index 00000000000..9df6a38598e--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler_dump.c @@ -0,0 +1,270 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include "r600_compiler.h" + +static const char *c_file_swz[] = { + "x", + "y", + "z", + "w", + "0", + "1", + ".", +}; + +static const char *c_file_str[] = { + "NULL", + "CONSTANT", + "INPUT", + "OUTPUT", + "TEMPORARY", + "SAMPLER", + "ADDRESS", + "IMMEDIATE", + "LOOP", + "PREDICATE", + "SYSTEM_VALUE", +}; + +static const char *c_semantic_str[] = { + "POSITION", + "COLOR", + "BCOLOR", + "FOG", + "PSIZE", + "GENERIC", + "NORMAL", + "FACE", + "EDGEFLAG", + "PRIMID", + "INSTANCEID", +}; + +static const char *c_opcode_str[] = { + "ARL", + "MOV", + "LIT", + "RCP", + "RSQ", + "EXP", + "LOG", + "MUL", + "ADD", + "DP3", + "DP4", + "DST", + "MIN", + "MAX", + "SLT", + "SGE", + "MAD", + "SUB", + "LRP", + "CND", + "(INVALID)", + "DP2A", + "(INVALID)", + "(INVALID)", + "FRC", + "CLAMP", + "FLR", + "ROUND", + "EX2", + "LG2", + "POW", + "XPD", + "(INVALID)", + "ABS", + "RCC", + "DPH", + "COS", + "DDX", + "DDY", + "KILP", + "PK2H", + "PK2US", + "PK4B", + "PK4UB", + "RFL", + "SEQ", + "SFL", + "SGT", + "SIN", + "SLE", + "SNE", + "STR", + "TEX", + "TXD", + "TXP", + "UP2H", + "UP2US", + "UP4B", + "UP4UB", + "X2D", + "ARA", + "ARR", + "BRA", + "CAL", + "RET", + "SSG", + "CMP", + "SCS", + "TXB", + "NRM", + "DIV", + "DP2", + "TXL", + "BRK", + "IF", + "BGNFOR", + "REP", + "ELSE", + "ENDIF", + "ENDFOR", + "ENDREP", + "PUSHA", + "POPA", + "CEIL", + "I2F", + "NOT", + "TRUNC", + "SHL", + "(INVALID)", + "AND", + "OR", + "MOD", + "XOR", + "SAD", + "TXF", + "TXQ", + "CONT", + "EMIT", + "ENDPRIM", + "BGNLOOP", + "BGNSUB", + "ENDLOOP", + "ENDSUB", + "(INVALID)", + "(INVALID)", + "(INVALID)", + "(INVALID)", + "NOP", + "(INVALID)", + "(INVALID)", + "(INVALID)", + "(INVALID)", + "NRM4", + "CALLNZ", + "IFC", + "BREAKC", + "KIL", + "END", + "(INVALID)", + "F2I", + "IDIV", + "IMAX", + "IMIN", + "INEG", + "ISGE", + "ISHR", + "ISLT", + "F2U", + "U2F", + "UADD", + "UDIV", + "UMAD", + "UMAX", + "UMIN", + "UMOD", + "UMUL", + "USEQ", + "USGE", + "USHR", + "USLT", + "USNE", + "SWITCH", + "CASE", + "DEFAULT", + "ENDSWITCH", + "VFETCH", + "ENTRY", +}; + +static inline const char *c_get_name(const char *name[], unsigned i) +{ + return name[i]; +} + +static void pindent(unsigned indent) +{ + unsigned i; + for (i = 0; i < indent; i++) + fprintf(stderr, " "); +} + +static void c_node_dump(struct c_node *node, unsigned indent) +{ + struct c_instruction *i; + unsigned j; + + pindent(indent); fprintf(stderr, "# node %s

", c_get_name(c_opcode_str, node->opcode)); + c_list_for_each(i, &node->insts) { + pindent(indent); fprintf(stderr, "%s", c_get_name(c_opcode_str, i->opcode)); + fprintf(stderr, " %s[%d][%s%s%s%s]", + c_get_name(c_file_str, i->output.vector->file), + i->output.vector->id, + c_get_name(c_file_swz, i->output.swizzle[0]), + c_get_name(c_file_swz, i->output.swizzle[1]), + c_get_name(c_file_swz, i->output.swizzle[2]), + c_get_name(c_file_swz, i->output.swizzle[3])); + for (j = 0; j < i->ninput; j++) { + fprintf(stderr, " %s[%d][%s%s%s%s]", + c_get_name(c_file_str, i->input[j].vector->file), + i->input[j].vector->id, + c_get_name(c_file_swz, i->input[j].swizzle[0]), + c_get_name(c_file_swz, i->input[j].swizzle[1]), + c_get_name(c_file_swz, i->input[j].swizzle[2]), + c_get_name(c_file_swz, i->input[j].swizzle[3])); + } + fprintf(stderr, ";

"); + } +} + +static void c_shader_dump_rec(struct c_shader *shader, struct c_node *node, unsigned indent) +{ + struct c_node_link *link; + + c_node_dump(node, indent); + c_list_for_each(link, &node->childs) { + c_shader_dump_rec(shader, link->node, indent + 1); + } +} + +void c_shader_dump(struct c_shader *shader) +{ + c_shader_dump_rec(shader, &shader->entry, 0); +}

new file mode 100644

index 00000000000..bed2b72f247

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler_r600.c b/src/gallium/drivers/r600/r600_compiler_r600.cnew file mode 100644index 00000000000..bed2b72f247--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler_r600.c @@ -0,0 +1,763 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include <util/u_format.h> +#include "r600_context.h" +#include "r600_sq.h" + + +struct r600_shader_alu_translate { + unsigned copcode; + unsigned opcode; + unsigned is_op3; +}; + +static int r600_shader_alu_translate(struct r600_shader *rshader, + struct c_instruction *instruction); +struct r600_shader_alu_translate r600_alu_translate_list[C_OPCODE_LAST]; + +int r600_shader_insert_fetch(struct c_shader *shader) +{ + struct c_vector *vi, *vr, *v, *nv; + struct c_instruction instruction; + int r; + + if (shader->type != C_PROGRAM_TYPE_VS) + return 0; + vi = c_shader_vector_new(shader, C_FILE_INPUT, C_SEMANTIC_VERTEXID, -1); + if (vi == NULL) + return -ENOMEM; + c_list_for_each_safe(v, nv, &shader->files[C_FILE_INPUT].vectors) { + if (v == vi) + continue; + vr = c_shader_vector_new(shader, C_FILE_RESOURCE, C_SEMANTIC_GENERIC, -1); + if (vr == NULL) + return -ENOMEM; + memset(&instruction, 0, sizeof(struct c_instruction)); + instruction.opcode = C_OPCODE_VFETCH; + instruction.write_mask = 0xF; + instruction.ninput = 2; + instruction.output.vector = v; + instruction.input[0].vector = vi; + instruction.input[1].vector = vr; + instruction.output.swizzle[0] = C_SWIZZLE_X; + instruction.output.swizzle[1] = C_SWIZZLE_Y; + instruction.output.swizzle[2] = C_SWIZZLE_Z; + instruction.output.swizzle[3] = C_SWIZZLE_W; + r = c_node_add_new_instruction_head(&shader->entry, &instruction); + if (r) + return r; + c_list_del(v); + shader->files[C_FILE_INPUT].nvectors--; + c_list_add_tail(v, &shader->files[C_FILE_TEMPORARY].vectors); + shader->files[C_FILE_TEMPORARY].nvectors++; + v->file = C_FILE_TEMPORARY; + } + return 0; +} + +void r600_shader_cleanup(struct r600_shader *rshader) +{ + struct r600_shader_node *n, *nn; + struct r600_shader_vfetch *vf, *nvf; + struct r600_shader_alu *alu, *nalu; + int i; + + if (rshader == NULL) + return; + if (rshader->gpr) { + for (i = 0; i < rshader->nvector; i++) { + free(rshader->gpr[i]); + } + free(rshader->gpr); + rshader->gpr = NULL; + } + c_list_for_each_safe(n, nn, &rshader->nodes) { + c_list_del(n); + c_list_for_each_safe(vf, nvf, &n->vfetch) { + c_list_del(vf); + free(vf); + } + c_list_for_each_safe(alu, nalu, &n->alu) { + c_list_del(alu); + free(alu); + } + free(n); + } + free(rshader->bcode); + return; +} + +int r600_shader_vfetch_bytecode(struct r600_shader *rshader, + struct r600_shader_node *rnode, + struct r600_shader_vfetch *vfetch, + unsigned *cid) +{ + unsigned id = *cid; + + vfetch->cf_addr = id; + rshader->bcode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vfetch->sel[2]) | + S_SQ_VTX_WORD0_SRC_GPR(vfetch->sel[1]) | + S_SQ_VTX_WORD0_SRC_SEL_X(vfetch->chan[1]) | + S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(0x1F); + rshader->bcode[id++] = S_SQ_VTX_WORD1_DST_SEL_X(vfetch->dsel[0]) | + S_SQ_VTX_WORD1_DST_SEL_Y(vfetch->dsel[1]) | + S_SQ_VTX_WORD1_DST_SEL_Z(vfetch->dsel[2]) | + S_SQ_VTX_WORD1_DST_SEL_W(vfetch->dsel[3]) | + S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) | + S_SQ_VTX_WORD1_GPR_DST_GPR(vfetch->sel[0]); + rshader->bcode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1); + rshader->bcode[id++] = 0; + *cid = id; + return 0; +} + +int r600_shader_update(struct r600_shader *rshader, enum pipe_format *resource_format) +{ + struct r600_shader_node *rnode; + struct r600_shader_vfetch *vfetch; + unsigned i; + + memcpy(rshader->resource_format, resource_format, + rshader->nresource * sizeof(enum pipe_format)); + c_list_for_each(rnode, &rshader->nodes) { + c_list_for_each(vfetch, &rnode->vfetch) { + const struct util_format_description *desc; + i = vfetch->cf_addr + 1; + rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_X; + rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Y; + rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_Z; + rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_W; + desc = util_format_description(resource_format[vfetch->sel[2]]); + if (desc == NULL) { + fprintf(stderr, "%s unknown format %d

", __func__, resource_format[vfetch->sel[2]]); + continue; + } + /* WARNING so far TGSI swizzle match R600 ones */ + rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_X(desc->swizzle[0]); + rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Y(desc->swizzle[1]); + rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_Z(desc->swizzle[2]); + rshader->bcode[i] |= S_SQ_VTX_WORD1_DST_SEL_W(desc->swizzle[3]); + } + } + return 0; +} + +int r600_shader_register(struct r600_shader *rshader) +{ + struct c_vector *v, *nv; + unsigned tid, cid, rid, i; + + rshader->nvector = rshader->cshader.nvectors; + rshader->gpr = calloc(rshader->nvector, sizeof(void*)); + if (rshader->gpr == NULL) + return -ENOMEM; + tid = 0; + cid = 0; + rid = 0; + /* alloc input first */ + c_list_for_each(v, &rshader->cshader.files[C_FILE_INPUT].vectors) { + nv = c_vector_new(); + if (nv == NULL) { + return -ENOMEM; + } + memcpy(nv, v, sizeof(struct c_vector)); + nv->id = tid++; + rshader->gpr[v->id] = nv; + } + for (i = 0; i < C_FILE_COUNT; i++) { + if (i == C_FILE_INPUT || i == C_FILE_IMMEDIATE) + continue; + c_list_for_each(v, &rshader->cshader.files[i].vectors) { + switch (v->file) { + case C_FILE_OUTPUT: + case C_FILE_TEMPORARY: + nv = c_vector_new(); + if (nv == NULL) { + return -ENOMEM; + } + memcpy(nv, v, sizeof(struct c_vector)); + nv->id = tid++; + rshader->gpr[v->id] = nv; + break; + case C_FILE_CONSTANT: + nv = c_vector_new(); + if (nv == NULL) { + return -ENOMEM; + } + memcpy(nv, v, sizeof(struct c_vector)); + nv->id = (cid++) + 256; + rshader->gpr[v->id] = nv; + break; + case C_FILE_RESOURCE: + nv = c_vector_new(); + if (nv == NULL) { + return -ENOMEM; + } + memcpy(nv, v, sizeof(struct c_vector)); + nv->id = (rid++); + rshader->gpr[v->id] = nv; + break; + default: + fprintf(stderr, "%s:%d unsupported file %d

", __func__, __LINE__, v->file); + return -EINVAL; + } + } + } + rshader->ngpr = tid; + rshader->nconstant = cid; + rshader->nresource = rid; + return 0; +} + +int r600_shader_find_gpr(struct r600_shader *rshader, struct c_vector *v, + unsigned swizzle, unsigned *sel, unsigned *chan) +{ + struct c_vector *tmp; + + /* Values [0,127] correspond to GPR[0..127]. + * Values [256,511] correspond to cfile constants c[0..255]. + * Other special values are shown in the list below. + * 248 SQ_ALU_SRC_0: special constant 0.0. + * 249 SQ_ALU_SRC_1: special constant 1.0 float. + * 250 SQ_ALU_SRC_1_INT: special constant 1 integer. + * 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer. + * 252 SQ_ALU_SRC_0_5: special constant 0.5 float. + * 253 SQ_ALU_SRC_LITERAL: literal constant. + * 254 SQ_ALU_SRC_PV: previous vector result. + * 255 SQ_ALU_SRC_PS: previous scalar result. + */ + *sel = 248; + *chan = 0; + if (v == NULL) + return 0; + if (v->file == C_FILE_IMMEDIATE) { + *sel = 253; + } else { + tmp = rshader->gpr[v->id]; + if (tmp == NULL) { + fprintf(stderr, "%s %d unknown register

", __FILE__, __LINE__); + return -EINVAL; + } + *sel = tmp->id; + } + *chan = swizzle; + switch (swizzle) { + case C_SWIZZLE_X: + case C_SWIZZLE_Y: + case C_SWIZZLE_Z: + case C_SWIZZLE_W: + break; + case C_SWIZZLE_0: + *sel = 248; + *chan = 0; + break; + case C_SWIZZLE_1: + *sel = 249; + *chan = 0; + break; + default: + fprintf(stderr, "%s %d invalid swizzle %d

", __FILE__, __LINE__, swizzle); + return -EINVAL; + } + return 0; +} + +static int r600_shader_new_node(struct r600_shader *rshader, struct c_node *node) +{ + struct r600_shader_node *rnode; + rnode = CALLOC_STRUCT(r600_shader_node); + if (rnode == NULL) + return -ENOMEM; + rnode->node = node; + c_list_init(&rnode->vfetch); + c_list_init(&rnode->alu); + c_list_add_tail(rnode, &rshader->nodes); + rshader->cur_node = rnode; + return 0; +} + +static int r600_shader_new_alu(struct r600_shader *rshader, struct r600_shader_alu *alu) +{ + struct r600_shader_alu *nalu; + + nalu = CALLOC_STRUCT(r600_shader_alu); + if (nalu == NULL) + return -ENOMEM; + memcpy(nalu, alu, sizeof(struct r600_shader_alu)); + c_list_add_tail(nalu, &rshader->cur_node->alu); + return 0; +} + +static int r600_shader_add_vfetch(struct r600_shader *rshader, + struct c_instruction *instruction) +{ + struct r600_shader_vfetch *vfetch; + int r; + + if (instruction == NULL) + return 0; + if (instruction->opcode != C_OPCODE_VFETCH) + return 0; + if (!c_list_empty(&rshader->cur_node->alu)) { + r = r600_shader_new_node(rshader, rshader->cur_node->node); + if (r) + return r; + } + vfetch = calloc(1, sizeof(struct r600_shader_vfetch)); + if (vfetch == NULL) + return -ENOMEM; + r = r600_shader_find_gpr(rshader, instruction->output.vector, 0, &vfetch->sel[0], &vfetch->chan[0]); + if (r) + return r; + r = r600_shader_find_gpr(rshader, instruction->input[0].vector, 0, &vfetch->sel[1], &vfetch->chan[1]); + if (r) + return r; + r = r600_shader_find_gpr(rshader, instruction->input[1].vector, 0, &vfetch->sel[2], &vfetch->chan[2]); + if (r) + return r; + vfetch->dsel[0] = C_SWIZZLE_X; + vfetch->dsel[1] = C_SWIZZLE_Y; + vfetch->dsel[2] = C_SWIZZLE_Z; + vfetch->dsel[3] = C_SWIZZLE_W; + c_list_add_tail(vfetch, &rshader->cur_node->vfetch); + rshader->cur_node->nslot += 2; + return 0; +} + +static int r600_node_translate(struct r600_shader *rshader, struct c_node *node) +{ + struct c_instruction *instruction; + int r; + + r = r600_shader_new_node(rshader, node); + if (r) + return r; + c_list_for_each(instruction, &node->insts) { + switch (instruction->opcode) { + case C_OPCODE_VFETCH: + r = r600_shader_add_vfetch(rshader, instruction); + if (r) + return r; + break; + default: + r = r600_shader_alu_translate(rshader, instruction); + if (r) + return r; + break; + } + } + return 0; +} + +int r600_shader_translate_rec(struct r600_shader *rshader, struct c_node *node) +{ + struct c_node_link *link; + int r; + + if (node->opcode == C_OPCODE_END) + return 0; + r = r600_node_translate(rshader, node); + if (r) + return r; + c_list_for_each(link, &node->childs) { + r = r600_shader_translate_rec(rshader, link->node); + if (r) + return r; + } + return 0; +} + +static int r600_shader_alu_translate(struct r600_shader *rshader, + struct c_instruction *instruction) +{ + struct r600_shader_alu_translate *info = &r600_alu_translate_list[instruction->opcode]; + struct r600_shader_alu alu; + unsigned rmask; + int r, i, j, c; + + if (!c_list_empty(&rshader->cur_node->vfetch)) { + r = r600_shader_new_node(rshader, rshader->cur_node->node); + if (r) + return r; + } + memset(&alu, 0, sizeof(struct r600_shader_alu)); + for (i = 0, c = 0; i < 4; i++) { + if (!(instruction->write_mask) || instruction->output.swizzle[i] == C_SWIZZLE_D) + continue; + alu.alu[c].opcode = instruction->opcode; + alu.alu[c].inst = info->opcode; + alu.alu[c].is_op3 = info->is_op3; + rmask = ~((1 << (i + 1)) - 1); + r = r600_shader_find_gpr(rshader, instruction->output.vector, + instruction->output.swizzle[i], + &alu.alu[c].dst.sel, &alu.alu[c].dst.chan); + if (r) { + fprintf(stderr, "%s %d register failed

", __FILE__, __LINE__); + return r; + } + for (j = 0; j < instruction->ninput; j++) { + r = r600_shader_find_gpr(rshader, instruction->input[j].vector, + instruction->input[j].swizzle[i], + &alu.alu[c].src[j].sel, &alu.alu[c].src[j].chan); + if (r) { + fprintf(stderr, "%s %d register failed

", __FILE__, __LINE__); + return r; + } + if (instruction->input[j].vector->file == C_FILE_IMMEDIATE) { + alu.literal[0] = instruction->input[j].vector->channel[0]->value; + alu.literal[1] = instruction->input[j].vector->channel[1]->value; + alu.literal[2] = instruction->input[j].vector->channel[2]->value; + alu.literal[3] = instruction->input[j].vector->channel[3]->value; + if (alu.alu[c].src[j].chan > 1) { + alu.nliteral = 4; + } else { + alu.nliteral = 2; + } + } + } + c++; + } + alu.nalu = c; + alu.alu[c - 1].last = 1; + r = r600_shader_new_alu(rshader, &alu); + return r; +} + +void r600_shader_node_place(struct r600_shader *rshader) +{ + struct r600_shader_node *node, *nnode; + struct r600_shader_alu *alu, *nalu; + struct r600_shader_vfetch *vfetch, *nvfetch; + unsigned cf_id = 0, cf_addr = 0; + + rshader->ncf = 0; + rshader->nslot = 0; + c_list_for_each_safe(node, nnode, &rshader->nodes) { + c_list_for_each_safe(alu, nalu, &node->alu) { + node->nslot += alu->nalu; + node->nslot += alu->nliteral >> 1; + } + node->nfetch = 0; + c_list_for_each_safe(vfetch, nvfetch, &node->vfetch) { + node->nslot += 2; + node->nfetch += 1; + } + if (!c_list_empty(&node->vfetch)) { + /* fetch node need to be 16 bytes aligned*/ + cf_addr += 1; + cf_addr &= 0xFFFFFFFEUL; + } + node->cf_id = cf_id; + node->cf_addr = cf_addr; + cf_id += 2; + cf_addr += node->nslot * 2; + rshader->ncf++; + } + rshader->nslot = cf_addr; + c_list_for_each_safe(node, nnode, &rshader->nodes) { + node->cf_addr += cf_id * 2; + } + rshader->ncf += rshader->cshader.files[C_FILE_OUTPUT].nvectors; + rshader->ndw = rshader->ncf * 2 + rshader->nslot * 2; +} + +int r600_shader_legalize(struct r600_shader *rshader) +{ + struct r600_shader_node *node, *nnode; + struct r600_shader_alu *alu, *nalu; + unsigned i; + + c_list_for_each_safe(node, nnode, &rshader->nodes) { + c_list_for_each_safe(alu, nalu, &node->alu) { + for (i = 0; i < alu->nalu; i++) { + switch (alu->alu[i].opcode) { + case C_OPCODE_DP3: + if (alu->alu[i].last) { + /* force W component to be 0 */ + alu->alu[i].src[0].chan = alu->alu[i].src[1].chan = 0; + alu->alu[i].src[0].sel = alu->alu[i].src[1].sel = 248; + } + break; + case C_OPCODE_SUB: + alu->alu[i].src[1].neg ^= 1; + break; + case C_OPCODE_ABS: + alu->alu[i].src[0].abs |= 1; + break; + default: + break; + } + } + } + } + return 0; +} + +#if 0 +static int r600_shader_alu_translate_lit(struct r600_shader *rshader, + struct c_instruction *instruction, + struct r600_shader_alu_translate *info) +{ + struct r600_shader_alu alu; + int r; + + if (rshader->cur_node->nvfetch) { + r = r600_shader_new_node(rshader, rshader->cur_node->node); + if (r) + return r; + } + /* dst.z = log(src0.y) */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED; + alu.is_op3 = 0; + alu.last = 1; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[1]; + alu.component[0] = C_SWIZZLE_Z; + alu.component[1] = C_SWIZZLE_Y; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + /* dst.z = MUL_LIT(src0.w, dst.z, src0.x) */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT; + alu.is_op3 = 0; + alu.last = 1; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[1]; + alu.vector[2] = instruction->vectors[0]; + alu.vector[3] = instruction->vectors[1]; + alu.component[0] = C_SWIZZLE_Z; + alu.component[1] = C_SWIZZLE_W; + alu.component[2] = C_SWIZZLE_Z; + alu.component[3] = C_SWIZZLE_X; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + /* dst.z = exp(dst.z) */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE; + alu.is_op3 = 0; + alu.last = 1; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[0]; + alu.component[0] = C_SWIZZLE_Z; + alu.component[1] = C_SWIZZLE_Z; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + /* dst.x = 1 */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV; + alu.is_op3 = 0; + alu.last = 0; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[1]; + alu.component[0] = C_SWIZZLE_X; + alu.component[1] = C_SWIZZLE_1; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + /* dst.w = 1 */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV; + alu.is_op3 = 0; + alu.last = 0; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[1]; + alu.component[0] = C_SWIZZLE_W; + alu.component[1] = C_SWIZZLE_1; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + /* dst.y = max(src0.x, 0.0) */ + memset(&alu, 0, sizeof(struct r600_shader_alu)); + alu.opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX; + alu.is_op3 = 0; + alu.last = 1; + alu.vector[0] = instruction->vectors[0]; + alu.vector[1] = instruction->vectors[1]; + alu.vector[2] = instruction->vectors[1]; + alu.component[0] = C_SWIZZLE_Y; + alu.component[1] = C_SWIZZLE_X; + alu.component[2] = C_SWIZZLE_0; + r = r600_shader_new_alu(rshader, &alu); + if (r) + return r; + return 0; +} +#endif +struct r600_shader_alu_translate r600_alu_translate_list[C_OPCODE_LAST] = { + {C_OPCODE_ARL, 0, 0}, + {C_OPCODE_MOV, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, 0}, + {C_OPCODE_LIT, 0, 0}, + {C_OPCODE_RCP, 0, 0}, + {C_OPCODE_RSQ, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_FF, 0}, + {C_OPCODE_EXP, 0, 0}, + {C_OPCODE_LOG, 0, 0}, + {C_OPCODE_MUL, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL, 0}, + {C_OPCODE_ADD, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, 0}, + {C_OPCODE_DP3, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, 0}, + {C_OPCODE_DP4, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, 0}, + {C_OPCODE_DST, 0, 0}, + {C_OPCODE_MIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MIN, 0}, + {C_OPCODE_MAX, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX, 0}, + {C_OPCODE_SLT, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, 0}, + {C_OPCODE_SGE, 0, 0}, + {C_OPCODE_MAD, V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD, 1}, + {C_OPCODE_SUB, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD, 0}, + {C_OPCODE_LRP, 0, 0}, + {C_OPCODE_CND, 0, 0}, + {20, 0, 0}, + {C_OPCODE_DP2A, 0, 0}, + {22, 0, 0}, + {23, 0, 0}, + {C_OPCODE_FRC, 0, 0}, + {C_OPCODE_CLAMP, 0, 0}, + {C_OPCODE_FLR, 0, 0}, + {C_OPCODE_ROUND, 0, 0}, + {C_OPCODE_EX2, 0, 0}, + {C_OPCODE_LG2, 0, 0}, + {C_OPCODE_POW, 0, 0}, + {C_OPCODE_XPD, 0, 0}, + {32, 0, 0}, + {C_OPCODE_ABS, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV, 0}, + {C_OPCODE_RCC, 0, 0}, + {C_OPCODE_DPH, 0, 0}, + {C_OPCODE_COS, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS, 0}, + {C_OPCODE_DDX, 0, 0}, + {C_OPCODE_DDY, 0, 0}, + {C_OPCODE_KILP, 0, 0}, + {C_OPCODE_PK2H, 0, 0}, + {C_OPCODE_PK2US, 0, 0}, + {C_OPCODE_PK4B, 0, 0}, + {C_OPCODE_PK4UB, 0, 0}, + {C_OPCODE_RFL, 0, 0}, + {C_OPCODE_SEQ, 0, 0}, + {C_OPCODE_SFL, 0, 0}, + {C_OPCODE_SGT, 0, 0}, + {C_OPCODE_SIN, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN, 0}, + {C_OPCODE_SLE, 0, 0}, + {C_OPCODE_SNE, 0, 0}, + {C_OPCODE_STR, 0, 0}, + {C_OPCODE_TEX, 0, 0}, + {C_OPCODE_TXD, 0, 0}, + {C_OPCODE_TXP, 0, 0}, + {C_OPCODE_UP2H, 0, 0}, + {C_OPCODE_UP2US, 0, 0}, + {C_OPCODE_UP4B, 0, 0}, + {C_OPCODE_UP4UB, 0, 0}, + {C_OPCODE_X2D, 0, 0}, + {C_OPCODE_ARA, 0, 0}, + {C_OPCODE_ARR, 0, 0}, + {C_OPCODE_BRA, 0, 0}, + {C_OPCODE_CAL, 0, 0}, + {C_OPCODE_RET, 0, 0}, + {C_OPCODE_SSG, 0, 0}, + {C_OPCODE_CMP, 0, 0}, + {C_OPCODE_SCS, 0, 0}, + {C_OPCODE_TXB, 0, 0}, + {C_OPCODE_NRM, 0, 0}, + {C_OPCODE_DIV, 0, 0}, + {C_OPCODE_DP2, 0, 0}, + {C_OPCODE_TXL, 0, 0}, + {C_OPCODE_BRK, 0, 0}, + {C_OPCODE_IF, 0, 0}, + {C_OPCODE_BGNFOR, 0, 0}, + {C_OPCODE_REP, 0, 0}, + {C_OPCODE_ELSE, 0, 0}, + {C_OPCODE_ENDIF, 0, 0}, + {C_OPCODE_ENDFOR, 0, 0}, + {C_OPCODE_ENDREP, 0, 0}, + {C_OPCODE_PUSHA, 0, 0}, + {C_OPCODE_POPA, 0, 0}, + {C_OPCODE_CEIL, 0, 0}, + {C_OPCODE_I2F, 0, 0}, + {C_OPCODE_NOT, 0, 0}, + {C_OPCODE_TRUNC, 0, 0}, + {C_OPCODE_SHL, 0, 0}, + {88, 0, 0}, + {C_OPCODE_AND, 0, 0}, + {C_OPCODE_OR, 0, 0}, + {C_OPCODE_MOD, 0, 0}, + {C_OPCODE_XOR, 0, 0}, + {C_OPCODE_SAD, 0, 0}, + {C_OPCODE_TXF, 0, 0}, + {C_OPCODE_TXQ, 0, 0}, + {C_OPCODE_CONT, 0, 0}, + {C_OPCODE_EMIT, 0, 0}, + {C_OPCODE_ENDPRIM, 0, 0}, + {C_OPCODE_BGNLOOP, 0, 0}, + {C_OPCODE_BGNSUB, 0, 0}, + {C_OPCODE_ENDLOOP, 0, 0}, + {C_OPCODE_ENDSUB, 0, 0}, + {103, 0, 0}, + {104, 0, 0}, + {105, 0, 0}, + {106, 0, 0}, + {C_OPCODE_NOP, 0, 0}, + {108, 0, 0}, + {109, 0, 0}, + {110, 0, 0}, + {111, 0, 0}, + {C_OPCODE_NRM4, 0, 0}, + {C_OPCODE_CALLNZ, 0, 0}, + {C_OPCODE_IFC, 0, 0}, + {C_OPCODE_BREAKC, 0, 0}, + {C_OPCODE_KIL, 0, 0}, + {C_OPCODE_END, 0, 0}, + {118, 0, 0}, + {C_OPCODE_F2I, 0, 0}, + {C_OPCODE_IDIV, 0, 0}, + {C_OPCODE_IMAX, 0, 0}, + {C_OPCODE_IMIN, 0, 0}, + {C_OPCODE_INEG, 0, 0}, + {C_OPCODE_ISGE, 0, 0}, + {C_OPCODE_ISHR, 0, 0}, + {C_OPCODE_ISLT, 0, 0}, + {C_OPCODE_F2U, 0, 0}, + {C_OPCODE_U2F, 0, 0}, + {C_OPCODE_UADD, 0, 0}, + {C_OPCODE_UDIV, 0, 0}, + {C_OPCODE_UMAD, 0, 0}, + {C_OPCODE_UMAX, 0, 0}, + {C_OPCODE_UMIN, 0, 0}, + {C_OPCODE_UMOD, 0, 0}, + {C_OPCODE_UMUL, 0, 0}, + {C_OPCODE_USEQ, 0, 0}, + {C_OPCODE_USGE, 0, 0}, + {C_OPCODE_USHR, 0, 0}, + {C_OPCODE_USLT, 0, 0}, + {C_OPCODE_USNE, 0, 0}, + {C_OPCODE_SWITCH, 0, 0}, + {C_OPCODE_CASE, 0, 0}, + {C_OPCODE_DEFAULT, 0, 0}, + {C_OPCODE_ENDSWITCH, 0, 0}, + {C_OPCODE_VFETCH, 0, 0}, + {C_OPCODE_ENTRY, 0, 0}, +};

new file mode 100644

index 00000000000..2cc2951f944

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler_r700.c b/src/gallium/drivers/r600/r600_compiler_r700.cnew file mode 100644index 00000000000..2cc2951f944--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler_r700.c @@ -0,0 +1,213 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include "r600_context.h" +#include "r700_sq.h" + +static int r700_shader_cf_node_bytecode(struct r600_shader *rshader, + struct r600_shader_node *rnode, + unsigned *cid) +{ + unsigned id = *cid; + + if (rnode->nfetch) { + rshader->bcode[id++] = S_SQ_CF_WORD0_ADDR(rnode->cf_addr >> 1); + rshader->bcode[id++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX) | + S_SQ_CF_WORD1_COUNT(rnode->nfetch - 1); + } else { + rshader->bcode[id++] = S_SQ_CF_ALU_WORD0_ADDR(rnode->cf_addr >> 1); + rshader->bcode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU) | + S_SQ_CF_ALU_WORD1_BARRIER(1) | + S_SQ_CF_ALU_WORD1_COUNT(rnode->nslot - 1); + } + *cid = id; + return 0; +} + +static int r700_shader_cf_output_bytecode(struct r600_shader *rshader, + struct c_vector *v, + unsigned *cid, + unsigned end) +{ + unsigned gpr, chan; + unsigned id = *cid; + int r; + + r = r600_shader_find_gpr(rshader, v, 0, &gpr, &chan); + if (r) + return r; + rshader->bcode[id + 0] = S_SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR(gpr) | + S_SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE(3); + rshader->bcode[id + 1] = S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X(0) | + S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y(1) | + S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z(2) | + S_SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W(3) | + S_SQ_CF_ALLOC_EXPORT_WORD1_BARRIER(1) | + S_SQ_CF_ALLOC_EXPORT_WORD1_CF_INST(V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE) | + S_SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM(end); + switch (v->name) { + case C_SEMANTIC_POSITION: + rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(60) | + S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS); + break; + case C_SEMANTIC_COLOR: + if (rshader->cshader.type == C_PROGRAM_TYPE_VS) { + rshader->output[rshader->noutput].gpr = gpr; + rshader->output[rshader->noutput].sid = v->sid; + rshader->output[rshader->noutput].name = v->name; + rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) | + S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM); + } else { + rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(0) | + S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL); + } + break; + case C_SEMANTIC_GENERIC: + rshader->output[rshader->noutput].gpr = gpr; + rshader->output[rshader->noutput].sid = v->sid; + rshader->output[rshader->noutput].name = v->name; + rshader->bcode[id + 0] |= S_SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE(rshader->noutput++) | + S_SQ_CF_ALLOC_EXPORT_WORD0_TYPE(V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM); + break; + default: + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -EINVAL; + } + *cid = id + 2; + return 0; +} + +static int r700_shader_alu_bytecode(struct r600_shader *rshader, + struct r600_shader_node *rnode, + struct r600_shader_inst *alu, + unsigned *cid) +{ + unsigned id = *cid; + + /* don't replace gpr by pv or ps for destination register */ + if (alu->is_op3) { + rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) | + S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) | + S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) | + S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) | + S_SQ_ALU_WORD0_LAST(alu->last); + rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) | + S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) | + S_SQ_ALU_WORD1_OP3_SRC2_SEL(alu->src[2].sel) | + S_SQ_ALU_WORD1_OP3_SRC2_CHAN(alu->src[2].chan) | + S_SQ_ALU_WORD1_OP3_SRC2_NEG(alu->src[2].neg) | + S_SQ_ALU_WORD1_OP3_ALU_INST(alu->inst) | + S_SQ_ALU_WORD1_BANK_SWIZZLE(0); + } else { + rshader->bcode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) | + S_SQ_ALU_WORD0_SRC0_CHAN(alu->src[0].chan) | + S_SQ_ALU_WORD0_SRC0_NEG(alu->src[0].neg) | + S_SQ_ALU_WORD0_SRC1_SEL(alu->src[1].sel) | + S_SQ_ALU_WORD0_SRC1_CHAN(alu->src[1].chan) | + S_SQ_ALU_WORD0_SRC1_NEG(alu->src[1].neg) | + S_SQ_ALU_WORD0_LAST(alu->last); + rshader->bcode[id++] = S_SQ_ALU_WORD1_DST_GPR(alu->dst.sel) | + S_SQ_ALU_WORD1_DST_CHAN(alu->dst.chan) | + S_SQ_ALU_WORD1_OP2_SRC0_ABS(alu->src[0].abs) | + S_SQ_ALU_WORD1_OP2_SRC1_ABS(alu->src[1].abs) | + S_SQ_ALU_WORD1_OP2_WRITE_MASK(1) | + S_SQ_ALU_WORD1_OP2_ALU_INST(alu->inst) | + S_SQ_ALU_WORD1_BANK_SWIZZLE(0); + } + *cid = id; + return 0; +} + +int r700_shader_translate(struct r600_shader *rshader) +{ + struct c_shader *shader = &rshader->cshader; + struct r600_shader_node *rnode; + struct r600_shader_vfetch *vfetch; + struct r600_shader_alu *alu; + struct c_vector *v; + unsigned id, i, end; + int r; + + r = r600_shader_register(rshader); + if (r) { + fprintf(stderr, "%s %d register allocation failed

", __FILE__, __LINE__); + return r; + } + r = r600_shader_translate_rec(rshader, &shader->entry); + if (r) { + fprintf(stderr, "%s %d translation failed

", __FILE__, __LINE__); + return r; + } + r = r600_shader_legalize(rshader); + if (r) { + fprintf(stderr, "%s %d legalize failed

", __FILE__, __LINE__); + return r; + } + r600_shader_node_place(rshader); + rshader->bcode = malloc(rshader->ndw * 4); + if (rshader->bcode == NULL) + return -ENOMEM; + c_list_for_each(rnode, &rshader->nodes) { + id = rnode->cf_addr; + c_list_for_each(vfetch, &rnode->vfetch) { + r = r600_shader_vfetch_bytecode(rshader, rnode, vfetch, &id); + if (r) + return r; + } + c_list_for_each(alu, &rnode->alu) { + for (i = 0; i < alu->nalu; i++) { + r = r700_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id); + if (r) + return r; + } + for (i = 0; i < alu->nliteral; i++) { + rshader->bcode[id++] = alu->literal[i]; + } + } + } + id = 0; + c_list_for_each(rnode, &rshader->nodes) { + r = r700_shader_cf_node_bytecode(rshader, rnode, &id); + if (r) + return r; + } + c_list_for_each(v, &rshader->cshader.files[C_FILE_OUTPUT].vectors) { + end = 0; + if (v->next == &rshader->cshader.files[C_FILE_OUTPUT].vectors) + end = 1; + r = r700_shader_cf_output_bytecode(rshader, v, &id, end); + if (r) + return r; + } + c_list_for_each(v, &rshader->cshader.files[C_FILE_INPUT].vectors) { + rshader->input[rshader->ninput].gpr = rshader->ninput; + rshader->input[rshader->ninput].sid = v->sid; + rshader->input[rshader->ninput].name = v->name; + rshader->ninput++; + } + return 0; +}

new file mode 100644

index 00000000000..745f92272f8

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_compiler_tgsi.c b/src/gallium/drivers/r600/r600_compiler_tgsi.cnew file mode 100644index 00000000000..745f92272f8--- /dev/null+++ b/ src/gallium/drivers/r600/r600_compiler_tgsi.c @@ -0,0 +1,717 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include <tgsi/tgsi_parse.h> +#include <tgsi/tgsi_scan.h> +#include "r600_shader.h" +#include "r600_context.h" + +struct tgsi_shader { + struct c_vector **v[TGSI_FILE_COUNT]; + struct tgsi_shader_info info; + struct tgsi_parse_context parser; + const struct tgsi_token *tokens; + struct c_shader *shader; + struct c_node *node; +}; + +static unsigned tgsi_file_to_c_file(unsigned file); +static unsigned tgsi_sname_to_c_sname(unsigned sname); +static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode); + +static int tgsi_shader_init(struct tgsi_shader *ts, + const struct tgsi_token *tokens, + struct c_shader *shader) +{ + int i; + + ts->shader = shader; + ts->tokens = tokens; + tgsi_scan_shader(ts->tokens, &ts->info); + tgsi_parse_init(&ts->parser, ts->tokens); + /* initialize to NULL in case of error */ + for (i = 0; i < C_FILE_COUNT; i++) { + ts->v[i] = NULL; + } + for (i = 0; i < TGSI_FILE_COUNT; i++) { + if (ts->info.file_count[i] > 0) { + ts->v[i] = calloc(ts->info.file_count[i], sizeof(void*)); + if (ts->v[i] == NULL) { + fprintf(stderr, "%s:%d unsupported %d %d

", __func__, __LINE__, i, ts->info.file_count[i]); + return -ENOMEM; + } + } + } + return 0; +} + +static void tgsi_shader_destroy(struct tgsi_shader *ts) +{ + int i; + + for (i = 0; i < TGSI_FILE_COUNT; i++) { + free(ts->v[i]); + } + tgsi_parse_free(&ts->parser); +} + +static int ntransform_declaration(struct tgsi_shader *ts) +{ + struct tgsi_full_declaration *fd = &ts->parser.FullToken.FullDeclaration; + struct c_vector *v; + unsigned file; + unsigned name; + int sid; + int i; + + if (fd->Declaration.Dimension) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -EINVAL; + } + for (i = fd->Range.First ; i <= fd->Range.Last; i++) { + sid = i; + name = C_SEMANTIC_GENERIC; + file = tgsi_file_to_c_file(fd->Declaration.File); + if (file == TGSI_FILE_NULL) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -EINVAL; + } + if (fd->Declaration.Semantic) { + name = tgsi_sname_to_c_sname(fd->Semantic.Name); + sid = fd->Semantic.Index; + } + v = c_shader_vector_new(ts->shader, file, name, sid); + if (v == NULL) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -ENOMEM; + } + ts->v[fd->Declaration.File][i] = v; + } + return 0; +} + +static int ntransform_immediate(struct tgsi_shader *ts) +{ + struct tgsi_full_immediate *fd = &ts->parser.FullToken.FullImmediate; + struct c_vector *v; + unsigned file; + unsigned name; + + if (fd->Immediate.DataType != TGSI_IMM_FLOAT32) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -EINVAL; + } + name = C_SEMANTIC_GENERIC; + file = C_FILE_IMMEDIATE; + v = c_shader_vector_new(ts->shader, file, name, 0); + if (v == NULL) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return -ENOMEM; + } + v->channel[0]->value = fd->u[0].Uint; + v->channel[1]->value = fd->u[1].Uint; + v->channel[2]->value = fd->u[2].Uint; + v->channel[3]->value = fd->u[3].Uint; + ts->v[TGSI_FILE_IMMEDIATE][0] = v; + return 0; +} + +static int ntransform_instruction(struct tgsi_shader *ts) +{ + struct tgsi_full_instruction *fi = &ts->parser.FullToken.FullInstruction; + struct c_shader *shader = ts->shader; + struct c_instruction instruction; + unsigned opcode; + int i, r; + + if (fi->Instruction.NumDstRegs > 1) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + if (fi->Instruction.Saturate) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + if (fi->Instruction.Predicate) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + if (fi->Instruction.Label) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + if (fi->Instruction.Texture) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + for (i = 0; i < fi->Instruction.NumSrcRegs; i++) { + if (fi->Src[i].Register.Indirect || + fi->Src[i].Register.Dimension || + fi->Src[i].Register.Absolute) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + } + for (i = 0; i < fi->Instruction.NumDstRegs; i++) { + if (fi->Dst[i].Register.Indirect || fi->Dst[i].Register.Dimension) { + fprintf(stderr, "%s %d unsupported

", __func__, __LINE__); + return -EINVAL; + } + } + r = tgsi_opcode_to_c_opcode(fi->Instruction.Opcode, &opcode); + if (r) { + fprintf(stderr, "%s:%d unsupported

", __func__, __LINE__); + return r; + } + if (opcode == C_OPCODE_END) { + return c_node_cfg_link(ts->node, &shader->end); + } + /* FIXME add flow instruction handling */ + memset(&instruction, 0, sizeof(struct c_instruction)); + instruction.opcode = opcode; + instruction.ninput = fi->Instruction.NumSrcRegs; + instruction.write_mask = fi->Dst[0].Register.WriteMask; + for (i = 0; i < fi->Instruction.NumSrcRegs; i++) { + instruction.input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index]; + instruction.input[i].swizzle[0] = fi->Src[i].Register.SwizzleX; + instruction.input[i].swizzle[1] = fi->Src[i].Register.SwizzleY; + instruction.input[i].swizzle[2] = fi->Src[i].Register.SwizzleZ; + instruction.input[i].swizzle[3] = fi->Src[i].Register.SwizzleW; + } + instruction.output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index]; + instruction.output.swizzle[0] = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D; + instruction.output.swizzle[1] = (fi->Dst[0].Register.WriteMask & 0x2) ? C_SWIZZLE_Y : C_SWIZZLE_D; + instruction.output.swizzle[2] = (fi->Dst[0].Register.WriteMask & 0x4) ? C_SWIZZLE_Z : C_SWIZZLE_D; + instruction.output.swizzle[3] = (fi->Dst[0].Register.WriteMask & 0x8) ? C_SWIZZLE_W : C_SWIZZLE_D; + return c_node_add_new_instruction(ts->node, &instruction); +} + +int c_shader_from_tgsi(struct c_shader *shader, unsigned type, + const struct tgsi_token *tokens) +{ + struct tgsi_shader ts; + int r = 0; + + c_shader_init(shader, type); + r = tgsi_shader_init(&ts, tokens, shader); + if (r) + goto out_err; + ts.shader = shader; + ts.node = &shader->entry; + while (!tgsi_parse_end_of_tokens(&ts.parser)) { + tgsi_parse_token(&ts.parser); + switch (ts.parser.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_IMMEDIATE: + r = ntransform_immediate(&ts); + if (r) + goto out_err; + break; + case TGSI_TOKEN_TYPE_DECLARATION: + r = ntransform_declaration(&ts); + if (r) + goto out_err; + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + r = ntransform_instruction(&ts); + if (r) + goto out_err; + break; + default: + r = -EINVAL; + goto out_err; + } + } + tgsi_shader_destroy(&ts); + return 0; +out_err: + c_shader_destroy(shader); + tgsi_shader_destroy(&ts); + return r; +} + +static unsigned tgsi_file_to_c_file(unsigned file) +{ + switch (file) { + case TGSI_FILE_CONSTANT: + return C_FILE_CONSTANT; + case TGSI_FILE_INPUT: + return C_FILE_INPUT; + case TGSI_FILE_OUTPUT: + return C_FILE_OUTPUT; + case TGSI_FILE_TEMPORARY: + return C_FILE_TEMPORARY; + case TGSI_FILE_SAMPLER: + return C_FILE_SAMPLER; + case TGSI_FILE_ADDRESS: + return C_FILE_ADDRESS; + case TGSI_FILE_IMMEDIATE: + return C_FILE_IMMEDIATE; + case TGSI_FILE_LOOP: + return C_FILE_LOOP; + case TGSI_FILE_PREDICATE: + return C_FILE_PREDICATE; + case TGSI_FILE_SYSTEM_VALUE: + return C_FILE_SYSTEM_VALUE; + case TGSI_FILE_NULL: + return C_FILE_NULL; + default: + fprintf(stderr, "%s:%d unsupported file %d

", __func__, __LINE__, file); + return C_FILE_NULL; + } +} + +static unsigned tgsi_sname_to_c_sname(unsigned sname) +{ + switch (sname) { + case TGSI_SEMANTIC_POSITION: + return C_SEMANTIC_POSITION; + case TGSI_SEMANTIC_COLOR: + return C_SEMANTIC_COLOR; + case TGSI_SEMANTIC_BCOLOR: + return C_SEMANTIC_BCOLOR; + case TGSI_SEMANTIC_FOG: + return C_SEMANTIC_FOG; + case TGSI_SEMANTIC_PSIZE: + return C_SEMANTIC_PSIZE; + case TGSI_SEMANTIC_GENERIC: + return C_SEMANTIC_GENERIC; + case TGSI_SEMANTIC_NORMAL: + return C_SEMANTIC_NORMAL; + case TGSI_SEMANTIC_FACE: + return C_SEMANTIC_FACE; + case TGSI_SEMANTIC_EDGEFLAG: + return C_SEMANTIC_EDGEFLAG; + case TGSI_SEMANTIC_PRIMID: + return C_SEMANTIC_PRIMID; + case TGSI_SEMANTIC_INSTANCEID: + return C_SEMANTIC_INSTANCEID; + default: + return C_SEMANTIC_GENERIC; + } +} + +static int tgsi_opcode_to_c_opcode(unsigned opcode, unsigned *copcode) +{ + switch (opcode) { + case TGSI_OPCODE_MOV: + *copcode = C_OPCODE_MOV; + return 0; + case TGSI_OPCODE_MUL: + *copcode = C_OPCODE_MUL; + return 0; + case TGSI_OPCODE_MAD: + *copcode = C_OPCODE_MAD; + return 0; + case TGSI_OPCODE_END: + *copcode = C_OPCODE_END; + return 0; + case TGSI_OPCODE_ARL: + *copcode = C_OPCODE_ARL; + return 0; + case TGSI_OPCODE_LIT: + *copcode = C_OPCODE_LIT; + return 0; + case TGSI_OPCODE_RCP: + *copcode = C_OPCODE_RCP; + return 0; + case TGSI_OPCODE_RSQ: + *copcode = C_OPCODE_RSQ; + return 0; + case TGSI_OPCODE_EXP: + *copcode = C_OPCODE_EXP; + return 0; + case TGSI_OPCODE_LOG: + *copcode = C_OPCODE_LOG; + return 0; + case TGSI_OPCODE_ADD: + *copcode = C_OPCODE_ADD; + return 0; + case TGSI_OPCODE_DP3: + *copcode = C_OPCODE_DP3; + return 0; + case TGSI_OPCODE_DP4: + *copcode = C_OPCODE_DP4; + return 0; + case TGSI_OPCODE_DST: + *copcode = C_OPCODE_DST; + return 0; + case TGSI_OPCODE_MIN: + *copcode = C_OPCODE_MIN; + return 0; + case TGSI_OPCODE_MAX: + *copcode = C_OPCODE_MAX; + return 0; + case TGSI_OPCODE_SLT: + *copcode = C_OPCODE_SLT; + return 0; + case TGSI_OPCODE_SGE: + *copcode = C_OPCODE_SGE; + return 0; + case TGSI_OPCODE_SUB: + *copcode = C_OPCODE_SUB; + return 0; + case TGSI_OPCODE_LRP: + *copcode = C_OPCODE_LRP; + return 0; + case TGSI_OPCODE_CND: + *copcode = C_OPCODE_CND; + return 0; + case TGSI_OPCODE_DP2A: + *copcode = C_OPCODE_DP2A; + return 0; + case TGSI_OPCODE_FRC: + *copcode = C_OPCODE_FRC; + return 0; + case TGSI_OPCODE_CLAMP: + *copcode = C_OPCODE_CLAMP; + return 0; + case TGSI_OPCODE_FLR: + *copcode = C_OPCODE_FLR; + return 0; + case TGSI_OPCODE_ROUND: + *copcode = C_OPCODE_ROUND; + return 0; + case TGSI_OPCODE_EX2: + *copcode = C_OPCODE_EX2; + return 0; + case TGSI_OPCODE_LG2: + *copcode = C_OPCODE_LG2; + return 0; + case TGSI_OPCODE_POW: + *copcode = C_OPCODE_POW; + return 0; + case TGSI_OPCODE_XPD: + *copcode = C_OPCODE_XPD; + return 0; + case TGSI_OPCODE_ABS: + *copcode = C_OPCODE_ABS; + return 0; + case TGSI_OPCODE_RCC: + *copcode = C_OPCODE_RCC; + return 0; + case TGSI_OPCODE_DPH: + *copcode = C_OPCODE_DPH; + return 0; + case TGSI_OPCODE_COS: + *copcode = C_OPCODE_COS; + return 0; + case TGSI_OPCODE_DDX: + *copcode = C_OPCODE_DDX; + return 0; + case TGSI_OPCODE_DDY: + *copcode = C_OPCODE_DDY; + return 0; + case TGSI_OPCODE_KILP: + *copcode = C_OPCODE_KILP; + return 0; + case TGSI_OPCODE_PK2H: + *copcode = C_OPCODE_PK2H; + return 0; + case TGSI_OPCODE_PK2US: + *copcode = C_OPCODE_PK2US; + return 0; + case TGSI_OPCODE_PK4B: + *copcode = C_OPCODE_PK4B; + return 0; + case TGSI_OPCODE_PK4UB: + *copcode = C_OPCODE_PK4UB; + return 0; + case TGSI_OPCODE_RFL: + *copcode = C_OPCODE_RFL; + return 0; + case TGSI_OPCODE_SEQ: + *copcode = C_OPCODE_SEQ; + return 0; + case TGSI_OPCODE_SFL: + *copcode = C_OPCODE_SFL; + return 0; + case TGSI_OPCODE_SGT: + *copcode = C_OPCODE_SGT; + return 0; + case TGSI_OPCODE_SIN: + *copcode = C_OPCODE_SIN; + return 0; + case TGSI_OPCODE_SLE: + *copcode = C_OPCODE_SLE; + return 0; + case TGSI_OPCODE_SNE: + *copcode = C_OPCODE_SNE; + return 0; + case TGSI_OPCODE_STR: + *copcode = C_OPCODE_STR; + return 0; + case TGSI_OPCODE_TEX: + *copcode = C_OPCODE_TEX; + return 0; + case TGSI_OPCODE_TXD: + *copcode = C_OPCODE_TXD; + return 0; + case TGSI_OPCODE_TXP: + *copcode = C_OPCODE_TXP; + return 0; + case TGSI_OPCODE_UP2H: + *copcode = C_OPCODE_UP2H; + return 0; + case TGSI_OPCODE_UP2US: + *copcode = C_OPCODE_UP2US; + return 0; + case TGSI_OPCODE_UP4B: + *copcode = C_OPCODE_UP4B; + return 0; + case TGSI_OPCODE_UP4UB: + *copcode = C_OPCODE_UP4UB; + return 0; + case TGSI_OPCODE_X2D: + *copcode = C_OPCODE_X2D; + return 0; + case TGSI_OPCODE_ARA: + *copcode = C_OPCODE_ARA; + return 0; + case TGSI_OPCODE_ARR: + *copcode = C_OPCODE_ARR; + return 0; + case TGSI_OPCODE_BRA: + *copcode = C_OPCODE_BRA; + return 0; + case TGSI_OPCODE_CAL: + *copcode = C_OPCODE_CAL; + return 0; + case TGSI_OPCODE_RET: + *copcode = C_OPCODE_RET; + return 0; + case TGSI_OPCODE_SSG: + *copcode = C_OPCODE_SSG; + return 0; + case TGSI_OPCODE_CMP: + *copcode = C_OPCODE_CMP; + return 0; + case TGSI_OPCODE_SCS: + *copcode = C_OPCODE_SCS; + return 0; + case TGSI_OPCODE_TXB: + *copcode = C_OPCODE_TXB; + return 0; + case TGSI_OPCODE_NRM: + *copcode = C_OPCODE_NRM; + return 0; + case TGSI_OPCODE_DIV: + *copcode = C_OPCODE_DIV; + return 0; + case TGSI_OPCODE_DP2: + *copcode = C_OPCODE_DP2; + return 0; + case TGSI_OPCODE_TXL: + *copcode = C_OPCODE_TXL; + return 0; + case TGSI_OPCODE_BRK: + *copcode = C_OPCODE_BRK; + return 0; + case TGSI_OPCODE_IF: + *copcode = C_OPCODE_IF; + return 0; + case TGSI_OPCODE_BGNFOR: + *copcode = C_OPCODE_BGNFOR; + return 0; + case TGSI_OPCODE_REP: + *copcode = C_OPCODE_REP; + return 0; + case TGSI_OPCODE_ELSE: + *copcode = C_OPCODE_ELSE; + return 0; + case TGSI_OPCODE_ENDIF: + *copcode = C_OPCODE_ENDIF; + return 0; + case TGSI_OPCODE_ENDFOR: + *copcode = C_OPCODE_ENDFOR; + return 0; + case TGSI_OPCODE_ENDREP: + *copcode = C_OPCODE_ENDREP; + return 0; + case TGSI_OPCODE_PUSHA: + *copcode = C_OPCODE_PUSHA; + return 0; + case TGSI_OPCODE_POPA: + *copcode = C_OPCODE_POPA; + return 0; + case TGSI_OPCODE_CEIL: + *copcode = C_OPCODE_CEIL; + return 0; + case TGSI_OPCODE_I2F: + *copcode = C_OPCODE_I2F; + return 0; + case TGSI_OPCODE_NOT: + *copcode = C_OPCODE_NOT; + return 0; + case TGSI_OPCODE_TRUNC: + *copcode = C_OPCODE_TRUNC; + return 0; + case TGSI_OPCODE_SHL: + *copcode = C_OPCODE_SHL; + return 0; + case TGSI_OPCODE_AND: + *copcode = C_OPCODE_AND; + return 0; + case TGSI_OPCODE_OR: + *copcode = C_OPCODE_OR; + return 0; + case TGSI_OPCODE_MOD: + *copcode = C_OPCODE_MOD; + return 0; + case TGSI_OPCODE_XOR: + *copcode = C_OPCODE_XOR; + return 0; + case TGSI_OPCODE_SAD: + *copcode = C_OPCODE_SAD; + return 0; + case TGSI_OPCODE_TXF: + *copcode = C_OPCODE_TXF; + return 0; + case TGSI_OPCODE_TXQ: + *copcode = C_OPCODE_TXQ; + return 0; + case TGSI_OPCODE_CONT: + *copcode = C_OPCODE_CONT; + return 0; + case TGSI_OPCODE_EMIT: + *copcode = C_OPCODE_EMIT; + return 0; + case TGSI_OPCODE_ENDPRIM: + *copcode = C_OPCODE_ENDPRIM; + return 0; + case TGSI_OPCODE_BGNLOOP: + *copcode = C_OPCODE_BGNLOOP; + return 0; + case TGSI_OPCODE_BGNSUB: + *copcode = C_OPCODE_BGNSUB; + return 0; + case TGSI_OPCODE_ENDLOOP: + *copcode = C_OPCODE_ENDLOOP; + return 0; + case TGSI_OPCODE_ENDSUB: + *copcode = C_OPCODE_ENDSUB; + return 0; + case TGSI_OPCODE_NOP: + *copcode = C_OPCODE_NOP; + return 0; + case TGSI_OPCODE_NRM4: + *copcode = C_OPCODE_NRM4; + return 0; + case TGSI_OPCODE_CALLNZ: + *copcode = C_OPCODE_CALLNZ; + return 0; + case TGSI_OPCODE_IFC: + *copcode = C_OPCODE_IFC; + return 0; + case TGSI_OPCODE_BREAKC: + *copcode = C_OPCODE_BREAKC; + return 0; + case TGSI_OPCODE_KIL: + *copcode = C_OPCODE_KIL; + return 0; + case TGSI_OPCODE_F2I: + *copcode = C_OPCODE_F2I; + return 0; + case TGSI_OPCODE_IDIV: + *copcode = C_OPCODE_IDIV; + return 0; + case TGSI_OPCODE_IMAX: + *copcode = C_OPCODE_IMAX; + return 0; + case TGSI_OPCODE_IMIN: + *copcode = C_OPCODE_IMIN; + return 0; + case TGSI_OPCODE_INEG: + *copcode = C_OPCODE_INEG; + return 0; + case TGSI_OPCODE_ISGE: + *copcode = C_OPCODE_ISGE; + return 0; + case TGSI_OPCODE_ISHR: + *copcode = C_OPCODE_ISHR; + return 0; + case TGSI_OPCODE_ISLT: + *copcode = C_OPCODE_ISLT; + return 0; + case TGSI_OPCODE_F2U: + *copcode = C_OPCODE_F2U; + return 0; + case TGSI_OPCODE_U2F: + *copcode = C_OPCODE_U2F; + return 0; + case TGSI_OPCODE_UADD: + *copcode = C_OPCODE_UADD; + return 0; + case TGSI_OPCODE_UDIV: + *copcode = C_OPCODE_UDIV; + return 0; + case TGSI_OPCODE_UMAD: + *copcode = C_OPCODE_UMAD; + return 0; + case TGSI_OPCODE_UMAX: + *copcode = C_OPCODE_UMAX; + return 0; + case TGSI_OPCODE_UMIN: + *copcode = C_OPCODE_UMIN; + return 0; + case TGSI_OPCODE_UMOD: + *copcode = C_OPCODE_UMOD; + return 0; + case TGSI_OPCODE_UMUL: + *copcode = C_OPCODE_UMUL; + return 0; + case TGSI_OPCODE_USEQ: + *copcode = C_OPCODE_USEQ; + return 0; + case TGSI_OPCODE_USGE: + *copcode = C_OPCODE_USGE; + return 0; + case TGSI_OPCODE_USHR: + *copcode = C_OPCODE_USHR; + return 0; + case TGSI_OPCODE_USLT: + *copcode = C_OPCODE_USLT; + return 0; + case TGSI_OPCODE_USNE: + *copcode = C_OPCODE_USNE; + return 0; + case TGSI_OPCODE_SWITCH: + *copcode = C_OPCODE_SWITCH; + return 0; + case TGSI_OPCODE_CASE: + *copcode = C_OPCODE_CASE; + return 0; + case TGSI_OPCODE_DEFAULT: + *copcode = C_OPCODE_DEFAULT; + return 0; + case TGSI_OPCODE_ENDSWITCH: + *copcode = C_OPCODE_ENDSWITCH; + return 0; + default: + fprintf(stderr, "%s:%d unsupported opcode %d

", __func__, __LINE__, opcode); + return -EINVAL; + } +}

new file mode 100644

index 00000000000..faefdb4378e

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.cnew file mode 100644index 00000000000..faefdb4378e--- /dev/null+++ b/ src/gallium/drivers/r600/r600_context.c @@ -0,0 +1,167 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Authors: + * Jerome Glisse + * Corbin Simpson + */ +#include <stdio.h> +#include <util/u_inlines.h> +#include <util/u_format.h> +#include <util/u_memory.h> +#include <util/u_blitter.h> +#include "r600_screen.h" +#include "r600_texture.h" +#include "r600_context.h" + +static void r600_destroy_context(struct pipe_context *context) +{ + struct r600_context *rctx = (struct r600_context*)context; + + FREE(rctx); +} + +static unsigned int r600_is_texture_referenced(struct pipe_context *context, + struct pipe_texture *texture, + unsigned face, unsigned level) +{ + struct pipe_buffer *buffer = NULL; + + r600_get_texture_buffer(context->screen, texture, &buffer, NULL); + return context->is_buffer_referenced(context, buffer); +} + +static unsigned int r600_is_buffer_referenced(struct pipe_context *context, struct pipe_buffer *buffer) +{ + return 0; +} + +static void r600_flush(struct pipe_context *ctx, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct r600_context *rctx = (struct r600_context*)ctx; + struct r600_screen *rscreen = (struct r600_screen*)ctx->screen; +static int dc = 0; + + if (radeon_ctx_pm4(rctx->ctx)) + return; + if (dc) + return; + radeon_ctx_dump_bof(rctx->ctx, "gallium.bof"); + radeon_ctx_submit(rctx->ctx); + rctx->ctx = radeon_ctx_decref(rctx->ctx); + rctx->ctx = radeon_ctx(rscreen->rw); + dc++; +} + +struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv) +{ + struct r600_context *rctx = CALLOC_STRUCT(r600_context); + struct r600_screen* rscreen = r600_screen(screen); + + if (rctx == NULL) + return NULL; + rctx->context.winsys = rscreen->screen.winsys; + rctx->context.screen = screen; + rctx->context.priv = priv; + rctx->context.destroy = r600_destroy_context; + rctx->context.clear = r600_clear; + rctx->context.surface_copy = r600_surface_copy; + rctx->context.surface_fill = r600_surface_fill; + rctx->context.draw_arrays = r600_draw_arrays; + rctx->context.draw_elements = r600_draw_elements; + rctx->context.draw_range_elements = r600_draw_range_elements; + rctx->context.is_texture_referenced = r600_is_texture_referenced; + rctx->context.is_buffer_referenced = r600_is_buffer_referenced; + rctx->context.flush = r600_flush; + r600_init_query_functions(rctx); + r600_init_state_functions(rctx); +#if 0 + rctx->blitter = util_blitter_create(&rctx->context); + if (rctx->blitter == NULL) { + FREE(rctx); + return NULL; + } +#endif + + rctx->cb_cntl = radeon_state(rscreen->rw, R600_CB_CNTL_TYPE, R600_CB_CNTL); + rctx->cb_cntl->states[R600_CB_CNTL__CB_SHADER_MASK] = 0x0000000F; + rctx->cb_cntl->states[R600_CB_CNTL__CB_TARGET_MASK] = 0x0000000F; + rctx->cb_cntl->states[R600_CB_CNTL__CB_COLOR_CONTROL] = 0x00CC0000; + rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_CONFIG] = 0x00000000; + rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_MCTX] = 0x00000000; + rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX] = 0x00000000; + rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_CONTROL] = 0x01000000; + rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_SRC] = 0x00000000; + rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_DST] = 0x000000FF; + rctx->cb_cntl->states[R600_CB_CNTL__CB_CLRCMP_MSK] = 0xFFFFFFFF; + rctx->cb_cntl->states[R600_CB_CNTL__PA_SC_AA_MASK] = 0xFFFFFFFF; + radeon_state_pm4(rctx->cb_cntl); + + rctx->config = radeon_state(rscreen->rw, R600_CONFIG_TYPE, R600_CONFIG); + rctx->config->states[R600_CONFIG__SQ_CONFIG] = 0xE400000C; + rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_1] = 0x403800C0; + rctx->config->states[R600_CONFIG__SQ_GPR_RESOURCE_MGMT_2] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_THREAD_RESOURCE_MGMT] = 0x00003090; + rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_1] = 0x00800080; + rctx->config->states[R600_CONFIG__SQ_STACK_RESOURCE_MGMT_2] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_DYN_GPR_CNTL_PS_FLUSH_REQ] = 0x00004000; + rctx->config->states[R600_CONFIG__TA_CNTL_AUX] = 0x07000002; + rctx->config->states[R600_CONFIG__VC_ENHANCE] = 0x00000000; + rctx->config->states[R600_CONFIG__DB_DEBUG] = 0x00000000; + rctx->config->states[R600_CONFIG__DB_WATERMARKS] = 0x00420204; + rctx->config->states[R600_CONFIG__SX_MISC] = 0x00000000; + rctx->config->states[R600_CONFIG__SPI_THREAD_GROUPING] = 0x00000001; + rctx->config->states[R600_CONFIG__CB_SHADER_CONTROL] = 0x00000003; + rctx->config->states[R600_CONFIG__SQ_ESGS_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_GSVS_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_ESTMP_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_GSTMP_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_VSTMP_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_PSTMP_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_FBUF_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_REDUC_RING_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__SQ_GS_VERT_ITEMSIZE] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_OUTPUT_PATH_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_HOS_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_HOS_MAX_TESS_LEVEL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_HOS_MIN_TESS_LEVEL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_HOS_REUSE_DEPTH] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_PRIM_TYPE] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_FIRST_DECR] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_DECR] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_0_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_1_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_0_FMT_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GROUP_VECT_1_FMT_CNTL] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_GS_MODE] = 0x00000000; + rctx->config->states[R600_CONFIG__PA_SC_MODE_CNTL] = 0x00514000; + rctx->config->states[R600_CONFIG__VGT_STRMOUT_EN] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_REUSE_OFF] = 0x00000001; + rctx->config->states[R600_CONFIG__VGT_VTX_CNT_EN] = 0x00000000; + rctx->config->states[R600_CONFIG__VGT_STRMOUT_BUFFER_EN] = 0x00000000; + radeon_state_pm4(rctx->config); + + rctx->ctx = radeon_ctx(rscreen->rw); + rctx->draw = radeon_draw(rscreen->rw); + return &rctx->context; +}

new file mode 100644

index 00000000000..4646df3b56f

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.hnew file mode 100644index 00000000000..4646df3b56f--- /dev/null+++ b/ src/gallium/drivers/r600/r600_context.h @@ -0,0 +1,101 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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 R600_CONTEXT_H +#define R600_CONTEXT_H + +#include <pipe/p_state.h> +#include <pipe/p_context.h> +#include <tgsi/tgsi_scan.h> +#include <tgsi/tgsi_parse.h> +#include <tgsi/tgsi_util.h> +#include <util/u_blitter.h> +#include "radeon.h" +#include "r600_shader.h" + +struct r600_state; +typedef void (*r600_state_destroy_t)(struct r600_state *rstate); + +struct r600_state { + unsigned type; + struct r600_atom *atom; + void *state; + unsigned nbuffers; + struct pipe_buffer *buffer[256]; + unsigned nsurfaces; + struct pipe_surface *surface[256]; + r600_state_destroy_t destroy; +}; + +struct r600_pipe_shader { + unsigned type; + struct r600_shader shader; + struct radeon_bo *bo; + struct radeon_state *state; +}; + +struct r600_context { + struct pipe_context context; + struct radeon_ctx *ctx; + struct radeon_state *cb_cntl; + struct radeon_state *db; + struct radeon_state *config; + struct r600_pipe_shader *ps_shader; + struct r600_pipe_shader *vs_shader; + unsigned flat_shade; + unsigned nvertex_buffer; + unsigned nvertex_element; + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; + struct blitter_context *blitter; + struct pipe_stencil_ref stencil_ref; + struct pipe_framebuffer_state fb_state; + struct radeon_draw *draw; +}; + +void r600_draw_arrays(struct pipe_context *ctx, unsigned mode, + unsigned start, unsigned count); +void r600_draw_elements(struct pipe_context *ctx, + struct pipe_buffer *index_buffer, + unsigned index_size, unsigned mode, + unsigned start, unsigned count); +void r600_draw_range_elements(struct pipe_context *ctx, + struct pipe_buffer *index_buffer, + unsigned indexSize, unsigned minIndex, + unsigned maxIndex, unsigned mode, + unsigned start, unsigned count); + +void r600_state_destroy_common(struct r600_state *state); +struct r600_state *r600_state_new(r600_state_destroy_t destroy); +struct r600_state *r600_state_destroy(struct r600_state *state); + +void r600_init_state_functions(struct r600_context *rctx); +void r600_init_query_functions(struct r600_context* rctx); +struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv); + +void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader); +struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx, + unsigned type, + const struct tgsi_token *tokens); +int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader); + +#endif

new file mode 100644

index 00000000000..b9037963117

--- /dev/null

+++ b/ diff --git a/src/gallium/drivers/r600/r600_draw.c b/src/gallium/drivers/r600/r600_draw.cnew file mode 100644index 00000000000..b9037963117--- /dev/null+++ b/ src/gallium/drivers/r600/r600_draw.c @@ -0,0 +1,215 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Authors: + * Jerome Glisse + * Corbin Simpson + */ +#include <stdio.h> +#include <errno.h> +#include <pipe/p_screen.h> +#include <util/u_format.h> +#include <util/u_math.h> +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include "r600_screen.h" +#include "r600_context.h" +#include "r600d.h" + +struct r600_draw { + struct pipe_context *ctx; + struct radeon_state *draw; + struct radeon_state *vgt; + unsigned mode; + unsigned start; + unsigned count; + unsigned index_size; + struct pipe_buffer *index_buffer; +}; + +static int r600_draw_common(struct r600_draw *draw) +{ + struct r600_context *rctx = (struct r600_context*)draw->ctx; + struct r600_screen *rscreen = (struct r600_screen*)draw->ctx->screen; + struct radeon_state *vs_resource; + struct r600_pipe_buffer *rbuffer; + unsigned i, j, offset, format, prim; + u32 vgt_dma_index_type, vgt_draw_initiator; + int r; + + switch (draw->index_size) { + case 2: + vgt_draw_initiator = 0; + vgt_dma_index_type = 0; + break; + case 4: + vgt_draw_initiator = 0; + vgt_dma_index_type = 1; + break; + case 0: + vgt_draw_initiator = 2; + vgt_dma_index_type = 0; + break; + default: + fprintf(stderr, "%s %d unsupported index size %d

", __func__, __LINE__, draw->index_size); + return -EINVAL; + } + r = r600_conv_pipe_prim(draw->mode, &prim); + if (r) + return r; + /* rebuild vertex shader if input format changed */ + r = r600_pipe_shader_update(draw->ctx, rctx->vs_shader); + if (r) + return r; + r = r600_pipe_shader_update(draw->ctx, rctx->ps_shader); + if (r) + return r; + r = radeon_draw_set(rctx->draw, rctx->vs_shader->state); + if (r) + return r; + r = radeon_dra