r600_shader.c revision 8556b77c56f3f1f0e75ce46d6b5c0d84c7b4eabd
1/* 2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Jerome Glisse 25 */ 26#include <stdio.h> 27#include <errno.h> 28#include <util/u_inlines.h> 29#include <util/u_format.h> 30#include <util/u_memory.h> 31#include <tgsi/tgsi_dump.h> 32#include "r600_screen.h" 33#include "r600_context.h" 34#include "r600d.h" 35 36static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *rpshader) 37{ 38 struct r600_screen *rscreen = r600_screen(ctx->screen); 39 struct r600_shader *rshader = &rpshader->shader; 40 struct radeon_state *state; 41 unsigned i, tmp; 42 43 rpshader->state = radeon_state_decref(rpshader->state); 44 state = radeon_state(rscreen->rw, R600_VS_SHADER_TYPE, R600_VS_SHADER); 45 if (state == NULL) 46 return -ENOMEM; 47 for (i = 0; i < rshader->noutput; i += 4) { 48 tmp = rshader->output[i].sid; 49 tmp |= rshader->output[i + 1].sid << 8; 50 tmp |= rshader->output[i + 2].sid << 16; 51 tmp |= rshader->output[i + 3].sid << 24; 52 state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i / 4] = tmp; 53 } 54 state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 1); 55 state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->ngpr); 56 rpshader->state = state; 57 rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo); 58 rpshader->state->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo); 59 rpshader->state->nbo = 2; 60 rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT; 61 return radeon_state_pm4(state); 62} 63 64static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *rpshader) 65{ 66 struct r600_screen *rscreen = r600_screen(ctx->screen); 67 struct r600_shader *rshader = &rpshader->shader; 68 struct radeon_state *state; 69 unsigned i, tmp; 70 71 rpshader->state = radeon_state_decref(rpshader->state); 72 state = radeon_state(rscreen->rw, R600_PS_SHADER_TYPE, R600_PS_SHADER); 73 if (state == NULL) 74 return -ENOMEM; 75 for (i = 0; i < rshader->ninput; i++) { 76 tmp = S_028644_SEMANTIC(rshader->input[i].sid); 77 tmp |= S_028644_SEL_CENTROID(1); 78 tmp |= S_028644_FLAT_SHADE(rshader->flat_shade); 79 state->states[R600_PS_SHADER__SPI_PS_INPUT_CNTL_0 + i] = tmp; 80 } 81 state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = S_0286CC_NUM_INTERP(rshader->ninput) | 82 S_0286CC_PERSP_GRADIENT_ENA(1); 83 state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_1] = 0x00000000; 84 state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->ngpr); 85 state->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = 0x00000002; 86 rpshader->state = state; 87 rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo); 88 rpshader->state->nbo = 1; 89 rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT; 90 return radeon_state_pm4(state); 91} 92 93static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *rpshader) 94{ 95 struct r600_screen *rscreen = r600_screen(ctx->screen); 96 struct r600_context *rctx = r600_context(ctx); 97 struct r600_shader *rshader = &rpshader->shader; 98 int r; 99 100 /* copy new shader */ 101 radeon_bo_decref(rscreen->rw, rpshader->bo); 102 rpshader->bo = NULL; 103 rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->ndw * 4, 104 4096, NULL); 105 if (rpshader->bo == NULL) { 106 return -ENOMEM; 107 } 108 radeon_bo_map(rscreen->rw, rpshader->bo); 109 memcpy(rpshader->bo->data, rshader->bcode, rshader->ndw * 4); 110 radeon_bo_unmap(rscreen->rw, rpshader->bo); 111 /* build state */ 112 rshader->flat_shade = rctx->flat_shade; 113 switch (rpshader->type) { 114 case C_PROGRAM_TYPE_VS: 115 r = r600_pipe_shader_vs(ctx, rpshader); 116 break; 117 case C_PROGRAM_TYPE_FS: 118 r = r600_pipe_shader_ps(ctx, rpshader); 119 break; 120 default: 121 r = -EINVAL; 122 break; 123 } 124 return r; 125} 126 127struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx, unsigned type, const struct tgsi_token *tokens) 128{ 129 struct r600_pipe_shader *rpshader = CALLOC_STRUCT(r600_pipe_shader); 130 struct r600_shader *rshader = &rpshader->shader; 131 int r; 132 133 if (rpshader == NULL) 134 return NULL; 135 rpshader->type = type; 136 LIST_INITHEAD(&rshader->nodes); 137 fprintf(stderr, "<<\n"); 138 tgsi_dump(tokens, 0); 139 fprintf(stderr, "--------------------------------------------------------------\n"); 140 r = c_shader_from_tgsi(&rshader->cshader, type, tokens); 141 if (r) { 142 r600_pipe_shader_destroy(ctx, rpshader); 143 fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__); 144 return NULL; 145 } 146 r = r600_shader_insert_fetch(&rshader->cshader); 147 if (r) { 148 r600_pipe_shader_destroy(ctx, rpshader); 149 fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__); 150 return NULL; 151 } 152 r = c_shader_build_dominator_tree(&rshader->cshader); 153 if (r) { 154 r600_pipe_shader_destroy(ctx, rpshader); 155 fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__); 156 return NULL; 157 } 158 c_shader_dump(&rshader->cshader); 159 r = r600_cshader_legalize(&rshader->cshader); 160 if (r) { 161 r600_pipe_shader_destroy(ctx, rpshader); 162 fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__); 163 return NULL; 164 } 165 r = r700_shader_translate(rshader); 166 if (r) { 167 r600_pipe_shader_destroy(ctx, rpshader); 168 fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__); 169 return NULL; 170 } 171#if 1 172#if 0 173 fprintf(stderr, "--------------------------------------------------------------\n"); 174 for (int i = 0; i < rshader->ndw; i++) { 175 fprintf(stderr, "0x%08X\n", rshader->bcode[i]); 176 } 177#endif 178 fprintf(stderr, ">>\n\n"); 179#endif 180 return rpshader; 181} 182 183void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader) 184{ 185 struct r600_screen *rscreen = r600_screen(ctx->screen); 186 187 if (rpshader == NULL) 188 return; 189 radeon_bo_decref(rscreen->rw, rpshader->bo); 190 rpshader->bo = NULL; 191 r600_shader_cleanup(&rpshader->shader); 192 FREE(rpshader); 193} 194 195int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader) 196{ 197 struct r600_context *rctx = r600_context(ctx); 198 struct r600_shader *rshader; 199 enum pipe_format resource_format[160]; 200 unsigned i, nresources = 0; 201 int r; 202 203 if (rpshader == NULL) 204 return -EINVAL; 205 rshader = &rpshader->shader; 206 switch (rpshader->type) { 207 case C_PROGRAM_TYPE_VS: 208 for (i = 0; i < rctx->vertex_elements->count; i++) { 209 resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format; 210 } 211 break; 212 default: 213 break; 214 } 215 /* there should be enough input */ 216 if (nresources < rshader->nresource) 217 return -EINVAL; 218 /* FIXME compare resources */ 219 r = r600_shader_update(rshader, resource_format); 220 if (r) 221 return r; 222 return r600_pipe_shader(ctx, rpshader); 223} 224