Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 1 | |
Christian König | ce40e47 | 2012-08-02 12:14:59 +0200 | [diff] [blame] | 2 | /* |
| 3 | * Copyright 2012 Advanced Micro Devices, Inc. |
| 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | * copy of this software and associated documentation files (the "Software"), |
| 7 | * to deal in the Software without restriction, including without limitation |
| 8 | * on the rights to use, copy, modify, merge, publish, distribute, sub |
| 9 | * license, and/or sell copies of the Software, and to permit persons to whom |
| 10 | * the Software is furnished to do so, subject to the following conditions: |
| 11 | * |
| 12 | * The above copyright notice and this permission notice (including the next |
| 13 | * paragraph) shall be included in all copies or substantial portions of the |
| 14 | * Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
| 20 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| 21 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| 22 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 23 | * |
| 24 | * Authors: |
| 25 | * Tom Stellard <thomas.stellard@amd.com> |
| 26 | * Michel Dänzer <michel.daenzer@amd.com> |
| 27 | * Christian König <christian.koenig@amd.com> |
| 28 | */ |
| 29 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 30 | #include "gallivm/lp_bld_tgsi_action.h" |
| 31 | #include "gallivm/lp_bld_const.h" |
Michel Dänzer | c2bae6b | 2012-08-02 17:19:22 +0200 | [diff] [blame] | 32 | #include "gallivm/lp_bld_gather.h" |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 33 | #include "gallivm/lp_bld_intr.h" |
| 34 | #include "gallivm/lp_bld_tgsi.h" |
| 35 | #include "radeon_llvm.h" |
Tom Stellard | 509ddb0 | 2012-04-16 17:48:44 -0400 | [diff] [blame] | 36 | #include "radeon_llvm_emit.h" |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 37 | #include "tgsi/tgsi_info.h" |
| 38 | #include "tgsi/tgsi_parse.h" |
| 39 | #include "tgsi/tgsi_scan.h" |
| 40 | #include "tgsi/tgsi_dump.h" |
| 41 | |
| 42 | #include "radeonsi_pipe.h" |
| 43 | #include "radeonsi_shader.h" |
Christian König | f67fae0 | 2012-07-17 23:43:00 +0200 | [diff] [blame] | 44 | #include "si_state.h" |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 45 | #include "sid.h" |
| 46 | |
| 47 | #include <assert.h> |
| 48 | #include <errno.h> |
| 49 | #include <stdio.h> |
| 50 | |
| 51 | /* |
| 52 | static ps_remap_inputs( |
| 53 | struct tgsi_llvm_context * tl_ctx, |
| 54 | unsigned tgsi_index, |
| 55 | unsigned tgsi_chan) |
| 56 | { |
| 57 | : |
| 58 | } |
| 59 | |
| 60 | struct si_input |
| 61 | { |
| 62 | struct list_head head; |
| 63 | unsigned tgsi_index; |
| 64 | unsigned tgsi_chan; |
| 65 | unsigned order; |
| 66 | }; |
| 67 | */ |
| 68 | |
| 69 | |
| 70 | struct si_shader_context |
| 71 | { |
| 72 | struct radeon_llvm_context radeon_bld; |
| 73 | struct r600_context *rctx; |
| 74 | struct tgsi_parse_context parse; |
| 75 | struct tgsi_token * tokens; |
| 76 | struct si_pipe_shader *shader; |
| 77 | unsigned type; /* TGSI_PROCESSOR_* specifies the type of shader. */ |
| 78 | /* unsigned num_inputs; */ |
| 79 | /* struct list_head inputs; */ |
| 80 | /* unsigned * input_mappings *//* From TGSI to SI hw */ |
| 81 | /* struct tgsi_shader_info info;*/ |
| 82 | }; |
| 83 | |
| 84 | static struct si_shader_context * si_shader_context( |
| 85 | struct lp_build_tgsi_context * bld_base) |
| 86 | { |
| 87 | return (struct si_shader_context *)bld_base; |
| 88 | } |
| 89 | |
| 90 | |
| 91 | #define PERSPECTIVE_BASE 0 |
| 92 | #define LINEAR_BASE 9 |
| 93 | |
| 94 | #define SAMPLE_OFFSET 0 |
| 95 | #define CENTER_OFFSET 2 |
| 96 | #define CENTROID_OFSET 4 |
| 97 | |
| 98 | #define USE_SGPR_MAX_SUFFIX_LEN 5 |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 99 | #define CONST_ADDR_SPACE 2 |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 100 | #define USER_SGPR_ADDR_SPACE 8 |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 101 | |
| 102 | enum sgpr_type { |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 103 | SGPR_CONST_PTR_F32, |
| 104 | SGPR_CONST_PTR_V4I32, |
| 105 | SGPR_CONST_PTR_V8I32, |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 106 | SGPR_I32, |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 107 | SGPR_I64 |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 108 | }; |
| 109 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 110 | /** |
| 111 | * Build an LLVM bytecode indexed load using LLVMBuildGEP + LLVMBuildLoad |
| 112 | * |
| 113 | * @param offset The offset parameter specifies the number of |
| 114 | * elements to offset, not the number of bytes or dwords. An element is the |
| 115 | * the type pointed to by the base_ptr parameter (e.g. int is the element of |
| 116 | * an int* pointer) |
| 117 | * |
| 118 | * When LLVM lowers the load instruction, it will convert the element offset |
| 119 | * into a dword offset automatically. |
| 120 | * |
| 121 | */ |
| 122 | static LLVMValueRef build_indexed_load( |
| 123 | struct gallivm_state * gallivm, |
| 124 | LLVMValueRef base_ptr, |
| 125 | LLVMValueRef offset) |
| 126 | { |
| 127 | LLVMValueRef computed_ptr = LLVMBuildGEP( |
| 128 | gallivm->builder, base_ptr, &offset, 1, ""); |
| 129 | |
| 130 | return LLVMBuildLoad(gallivm->builder, computed_ptr, ""); |
| 131 | } |
| 132 | |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 133 | /** |
| 134 | * Load a value stored in one of the user SGPRs |
| 135 | * |
| 136 | * @param sgpr This is the sgpr to load the value from. If you need to load a |
| 137 | * value that is stored in consecutive SGPR registers (e.g. a 64-bit pointer), |
| 138 | * then you should pass the index of the first SGPR that holds the value. For |
| 139 | * example, if you want to load a pointer that is stored in SGPRs 2 and 3, then |
| 140 | * use pass 2 for the sgpr parameter. |
| 141 | * |
| 142 | * The value of the sgpr parameter must also be aligned to the width of the type |
| 143 | * being loaded, so that the sgpr parameter is divisible by the dword width of the |
| 144 | * type. For example, if the value being loaded is two dwords wide, then the sgpr |
| 145 | * parameter must be divisible by two. |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 146 | */ |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 147 | static LLVMValueRef use_sgpr( |
| 148 | struct gallivm_state * gallivm, |
| 149 | enum sgpr_type type, |
| 150 | unsigned sgpr) |
| 151 | { |
| 152 | LLVMValueRef sgpr_index; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 153 | LLVMTypeRef ret_type; |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 154 | LLVMValueRef ptr; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 155 | |
| 156 | sgpr_index = lp_build_const_int32(gallivm, sgpr); |
| 157 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 158 | switch (type) { |
| 159 | case SGPR_CONST_PTR_F32: |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 160 | assert(sgpr % 2 == 0); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 161 | ret_type = LLVMFloatTypeInContext(gallivm->context); |
| 162 | ret_type = LLVMPointerType(ret_type, CONST_ADDR_SPACE); |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 163 | break; |
| 164 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 165 | case SGPR_I32: |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 166 | ret_type = LLVMInt32TypeInContext(gallivm->context); |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 167 | break; |
| 168 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 169 | case SGPR_I64: |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 170 | assert(sgpr % 2 == 0); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 171 | ret_type= LLVMInt64TypeInContext(gallivm->context); |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 172 | break; |
| 173 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 174 | case SGPR_CONST_PTR_V4I32: |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 175 | assert(sgpr % 2 == 0); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 176 | ret_type = LLVMInt32TypeInContext(gallivm->context); |
| 177 | ret_type = LLVMVectorType(ret_type, 4); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 178 | ret_type = LLVMPointerType(ret_type, CONST_ADDR_SPACE); |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 179 | break; |
| 180 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 181 | case SGPR_CONST_PTR_V8I32: |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 182 | assert(sgpr % 2 == 0); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 183 | ret_type = LLVMInt32TypeInContext(gallivm->context); |
| 184 | ret_type = LLVMVectorType(ret_type, 8); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 185 | ret_type = LLVMPointerType(ret_type, CONST_ADDR_SPACE); |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 186 | break; |
| 187 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 188 | default: |
| 189 | assert(!"Unsupported SGPR type in use_sgpr()"); |
| 190 | return NULL; |
| 191 | } |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 192 | |
| 193 | ret_type = LLVMPointerType(ret_type, USER_SGPR_ADDR_SPACE); |
| 194 | ptr = LLVMBuildIntToPtr(gallivm->builder, sgpr_index, ret_type, ""); |
| 195 | return LLVMBuildLoad(gallivm->builder, ptr, ""); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | static void declare_input_vs( |
| 199 | struct si_shader_context * si_shader_ctx, |
| 200 | unsigned input_index, |
| 201 | const struct tgsi_full_declaration *decl) |
| 202 | { |
| 203 | LLVMValueRef t_list_ptr; |
| 204 | LLVMValueRef t_offset; |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 205 | LLVMValueRef t_list; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 206 | LLVMValueRef attribute_offset; |
| 207 | LLVMValueRef buffer_index_reg; |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 208 | LLVMValueRef args[3]; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 209 | LLVMTypeRef vec4_type; |
| 210 | LLVMValueRef input; |
| 211 | struct lp_build_context * uint = &si_shader_ctx->radeon_bld.soa.bld_base.uint_bld; |
| 212 | struct lp_build_context * base = &si_shader_ctx->radeon_bld.soa.bld_base.base; |
| 213 | struct r600_context *rctx = si_shader_ctx->rctx; |
Christian König | b15e3ae | 2012-07-25 11:22:59 +0200 | [diff] [blame] | 214 | //struct pipe_vertex_element *velem = &rctx->vertex_elements->elements[input_index]; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 215 | unsigned chan; |
| 216 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 217 | /* Load the T list */ |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 218 | /* XXX: Communicate with the rest of the driver about which SGPR the T# |
Michel Dänzer | 9918fbd | 2012-04-19 11:41:48 +0200 | [diff] [blame] | 219 | * list pointer is going to be stored in. Hard code to SGPR[6:7] for |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 220 | * now */ |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 221 | t_list_ptr = use_sgpr(base->gallivm, SGPR_CONST_PTR_V4I32, 6); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 222 | |
Christian König | b15e3ae | 2012-07-25 11:22:59 +0200 | [diff] [blame] | 223 | t_offset = lp_build_const_int32(base->gallivm, input_index); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 224 | |
| 225 | t_list = build_indexed_load(base->gallivm, t_list_ptr, t_offset); |
| 226 | |
| 227 | /* Build the attribute offset */ |
Christian König | b15e3ae | 2012-07-25 11:22:59 +0200 | [diff] [blame] | 228 | attribute_offset = lp_build_const_int32(base->gallivm, 0); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 229 | |
| 230 | /* Load the buffer index is always, which is always stored in VGPR0 |
| 231 | * for Vertex Shaders */ |
Tom Stellard | 40c41fe | 2012-07-25 19:17:16 +0000 | [diff] [blame] | 232 | buffer_index_reg = build_intrinsic(base->gallivm->builder, |
| 233 | "llvm.SI.vs.load.buffer.index", uint->elem_type, NULL, 0, |
| 234 | LLVMReadNoneAttribute); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 235 | |
| 236 | vec4_type = LLVMVectorType(base->elem_type, 4); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 237 | args[0] = t_list; |
| 238 | args[1] = attribute_offset; |
| 239 | args[2] = buffer_index_reg; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 240 | input = lp_build_intrinsic(base->gallivm->builder, |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 241 | "llvm.SI.vs.load.input", vec4_type, args, 3); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 242 | |
| 243 | /* Break up the vec4 into individual components */ |
| 244 | for (chan = 0; chan < 4; chan++) { |
| 245 | LLVMValueRef llvm_chan = lp_build_const_int32(base->gallivm, chan); |
| 246 | /* XXX: Use a helper function for this. There is one in |
| 247 | * tgsi_llvm.c. */ |
| 248 | si_shader_ctx->radeon_bld.inputs[radeon_llvm_reg_index_soa(input_index, chan)] = |
| 249 | LLVMBuildExtractElement(base->gallivm->builder, |
| 250 | input, llvm_chan, ""); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | static void declare_input_fs( |
| 255 | struct si_shader_context * si_shader_ctx, |
| 256 | unsigned input_index, |
| 257 | const struct tgsi_full_declaration *decl) |
| 258 | { |
| 259 | const char * intr_name; |
| 260 | unsigned chan; |
| 261 | struct lp_build_context * base = |
| 262 | &si_shader_ctx->radeon_bld.soa.bld_base.base; |
| 263 | struct gallivm_state * gallivm = base->gallivm; |
| 264 | |
| 265 | /* This value is: |
| 266 | * [15:0] NewPrimMask (Bit mask for each quad. It is set it the |
| 267 | * quad begins a new primitive. Bit 0 always needs |
| 268 | * to be unset) |
| 269 | * [32:16] ParamOffset |
| 270 | * |
| 271 | */ |
Michel Dänzer | 9918fbd | 2012-04-19 11:41:48 +0200 | [diff] [blame] | 272 | /* XXX: This register number must be identical to the S_00B02C_USER_SGPR |
| 273 | * register field value |
| 274 | */ |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 275 | LLVMValueRef params = use_sgpr(base->gallivm, SGPR_I32, 6); |
| 276 | |
| 277 | |
| 278 | /* XXX: Is this the input_index? */ |
| 279 | LLVMValueRef attr_number = lp_build_const_int32(gallivm, input_index); |
| 280 | |
| 281 | /* XXX: Handle all possible interpolation modes */ |
Francisco Jerez | 1279923 | 2012-04-30 18:27:52 +0200 | [diff] [blame] | 282 | switch (decl->Interp.Interpolate) { |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 283 | case TGSI_INTERPOLATE_COLOR: |
Michel Dänzer | 90c6eac | 2012-06-08 17:15:21 +0200 | [diff] [blame] | 284 | /* XXX: Flat shading hangs the GPU */ |
Christian König | f67fae0 | 2012-07-17 23:43:00 +0200 | [diff] [blame] | 285 | if (si_shader_ctx->rctx->queued.named.rasterizer->flatshade) { |
Michel Dänzer | 90c6eac | 2012-06-08 17:15:21 +0200 | [diff] [blame] | 286 | #if 0 |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 287 | intr_name = "llvm.SI.fs.interp.constant"; |
Michel Dänzer | 90c6eac | 2012-06-08 17:15:21 +0200 | [diff] [blame] | 288 | #else |
| 289 | intr_name = "llvm.SI.fs.interp.linear.center"; |
| 290 | #endif |
Michel Dänzer | 1deb2be | 2012-05-14 16:26:19 +0200 | [diff] [blame] | 291 | } else { |
| 292 | if (decl->Interp.Centroid) |
| 293 | intr_name = "llvm.SI.fs.interp.persp.centroid"; |
| 294 | else |
| 295 | intr_name = "llvm.SI.fs.interp.persp.center"; |
| 296 | } |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 297 | break; |
| 298 | case TGSI_INTERPOLATE_CONSTANT: |
Michel Dänzer | 90c6eac | 2012-06-08 17:15:21 +0200 | [diff] [blame] | 299 | /* XXX: Flat shading hangs the GPU */ |
| 300 | #if 0 |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 301 | intr_name = "llvm.SI.fs.interp.constant"; |
| 302 | break; |
Michel Dänzer | 90c6eac | 2012-06-08 17:15:21 +0200 | [diff] [blame] | 303 | #endif |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 304 | case TGSI_INTERPOLATE_LINEAR: |
Michel Dänzer | 1deb2be | 2012-05-14 16:26:19 +0200 | [diff] [blame] | 305 | if (decl->Interp.Centroid) |
| 306 | intr_name = "llvm.SI.fs.interp.linear.centroid"; |
| 307 | else |
| 308 | intr_name = "llvm.SI.fs.interp.linear.center"; |
| 309 | break; |
| 310 | case TGSI_INTERPOLATE_PERSPECTIVE: |
| 311 | if (decl->Interp.Centroid) |
| 312 | intr_name = "llvm.SI.fs.interp.persp.centroid"; |
| 313 | else |
| 314 | intr_name = "llvm.SI.fs.interp.persp.center"; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 315 | break; |
| 316 | default: |
| 317 | fprintf(stderr, "Warning: Unhandled interpolation mode.\n"); |
| 318 | return; |
| 319 | } |
| 320 | |
| 321 | /* XXX: Could there be more than TGSI_NUM_CHANNELS (4) ? */ |
| 322 | for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) { |
| 323 | LLVMValueRef args[3]; |
| 324 | LLVMValueRef llvm_chan = lp_build_const_int32(gallivm, chan); |
| 325 | unsigned soa_index = radeon_llvm_reg_index_soa(input_index, chan); |
| 326 | LLVMTypeRef input_type = LLVMFloatTypeInContext(gallivm->context); |
| 327 | args[0] = llvm_chan; |
| 328 | args[1] = attr_number; |
| 329 | args[2] = params; |
| 330 | si_shader_ctx->radeon_bld.inputs[soa_index] = |
| 331 | lp_build_intrinsic(gallivm->builder, intr_name, |
| 332 | input_type, args, 3); |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | static void declare_input( |
| 337 | struct radeon_llvm_context * radeon_bld, |
| 338 | unsigned input_index, |
| 339 | const struct tgsi_full_declaration *decl) |
| 340 | { |
| 341 | struct si_shader_context * si_shader_ctx = |
| 342 | si_shader_context(&radeon_bld->soa.bld_base); |
| 343 | if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) { |
| 344 | declare_input_vs(si_shader_ctx, input_index, decl); |
| 345 | } else if (si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT) { |
| 346 | declare_input_fs(si_shader_ctx, input_index, decl); |
| 347 | } else { |
| 348 | fprintf(stderr, "Warning: Unsupported shader type,\n"); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | static LLVMValueRef fetch_constant( |
| 353 | struct lp_build_tgsi_context * bld_base, |
| 354 | const struct tgsi_full_src_register *reg, |
| 355 | enum tgsi_opcode_type type, |
| 356 | unsigned swizzle) |
| 357 | { |
| 358 | struct lp_build_context * base = &bld_base->base; |
| 359 | |
| 360 | LLVMValueRef const_ptr; |
| 361 | LLVMValueRef offset; |
Tom Stellard | 022b543 | 2012-07-25 08:23:52 -0400 | [diff] [blame] | 362 | LLVMValueRef load; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 363 | |
| 364 | /* XXX: Assume the pointer to the constant buffer is being stored in |
Michel Dänzer | 9918fbd | 2012-04-19 11:41:48 +0200 | [diff] [blame] | 365 | * SGPR[0:1] */ |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 366 | const_ptr = use_sgpr(base->gallivm, SGPR_CONST_PTR_F32, 0); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 367 | |
| 368 | /* XXX: This assumes that the constant buffer is not packed, so |
| 369 | * CONST[0].x will have an offset of 0 and CONST[1].x will have an |
| 370 | * offset of 4. */ |
| 371 | offset = lp_build_const_int32(base->gallivm, |
| 372 | (reg->Register.Index * 4) + swizzle); |
| 373 | |
Tom Stellard | 022b543 | 2012-07-25 08:23:52 -0400 | [diff] [blame] | 374 | load = build_indexed_load(base->gallivm, const_ptr, offset); |
| 375 | return bitcast(bld_base, type, load); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 376 | } |
| 377 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 378 | /* XXX: This is partially implemented for VS only at this point. It is not complete */ |
| 379 | static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) |
| 380 | { |
| 381 | struct si_shader_context * si_shader_ctx = si_shader_context(bld_base); |
Christian König | 3c09f11 | 2012-07-18 17:39:15 +0200 | [diff] [blame] | 382 | struct si_shader * shader = &si_shader_ctx->shader->shader; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 383 | struct lp_build_context * base = &bld_base->base; |
| 384 | struct lp_build_context * uint = |
| 385 | &si_shader_ctx->radeon_bld.soa.bld_base.uint_bld; |
| 386 | struct tgsi_parse_context *parse = &si_shader_ctx->parse; |
| 387 | LLVMValueRef last_args[9] = { 0 }; |
Christian König | 3508815 | 2012-08-01 22:35:24 +0200 | [diff] [blame] | 388 | unsigned color_count = 0; |
| 389 | unsigned param_count = 0; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 390 | |
| 391 | while (!tgsi_parse_end_of_tokens(parse)) { |
| 392 | /* XXX: component_bits controls which components of the output |
| 393 | * registers actually get exported. (e.g bit 0 means export |
| 394 | * X component, bit 1 means export Y component, etc.) I'm |
| 395 | * hard coding this to 0xf for now. In the future, we might |
| 396 | * want to do something else. */ |
| 397 | unsigned component_bits = 0xf; |
| 398 | unsigned chan; |
| 399 | struct tgsi_full_declaration *d = |
| 400 | &parse->FullToken.FullDeclaration; |
| 401 | LLVMValueRef args[9]; |
| 402 | unsigned target; |
| 403 | unsigned index; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 404 | int i; |
| 405 | |
| 406 | tgsi_parse_token(parse); |
| 407 | if (parse->FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) |
| 408 | continue; |
| 409 | |
| 410 | switch (d->Declaration.File) { |
| 411 | case TGSI_FILE_INPUT: |
| 412 | i = shader->ninput++; |
| 413 | shader->input[i].name = d->Semantic.Name; |
| 414 | shader->input[i].sid = d->Semantic.Index; |
Francisco Jerez | 1279923 | 2012-04-30 18:27:52 +0200 | [diff] [blame] | 415 | shader->input[i].interpolate = d->Interp.Interpolate; |
| 416 | shader->input[i].centroid = d->Interp.Centroid; |
Christian König | 3508815 | 2012-08-01 22:35:24 +0200 | [diff] [blame] | 417 | continue; |
| 418 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 419 | case TGSI_FILE_OUTPUT: |
| 420 | i = shader->noutput++; |
| 421 | shader->output[i].name = d->Semantic.Name; |
| 422 | shader->output[i].sid = d->Semantic.Index; |
Francisco Jerez | 1279923 | 2012-04-30 18:27:52 +0200 | [diff] [blame] | 423 | shader->output[i].interpolate = d->Interp.Interpolate; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 424 | break; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 425 | |
Christian König | 3508815 | 2012-08-01 22:35:24 +0200 | [diff] [blame] | 426 | default: |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 427 | continue; |
Christian König | 3508815 | 2012-08-01 22:35:24 +0200 | [diff] [blame] | 428 | } |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 429 | |
| 430 | for (index = d->Range.First; index <= d->Range.Last; index++) { |
| 431 | for (chan = 0; chan < 4; chan++ ) { |
| 432 | LLVMValueRef out_ptr = |
| 433 | si_shader_ctx->radeon_bld.soa.outputs |
| 434 | [index][chan]; |
| 435 | /* +5 because the first output value will be |
| 436 | * the 6th argument to the intrinsic. */ |
| 437 | args[chan + 5]= LLVMBuildLoad( |
| 438 | base->gallivm->builder, out_ptr, ""); |
| 439 | } |
| 440 | |
| 441 | /* XXX: We probably need to keep track of the output |
| 442 | * values, so we know what we are passing to the next |
| 443 | * stage. */ |
| 444 | |
| 445 | /* Select the correct target */ |
| 446 | switch(d->Semantic.Name) { |
| 447 | case TGSI_SEMANTIC_POSITION: |
| 448 | target = V_008DFC_SQ_EXP_POS; |
| 449 | break; |
| 450 | case TGSI_SEMANTIC_COLOR: |
| 451 | if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX) { |
| 452 | target = V_008DFC_SQ_EXP_PARAM + param_count; |
Michel Dänzer | dd9d619 | 2012-05-18 15:01:10 +0200 | [diff] [blame] | 453 | shader->output[i].param_offset = param_count; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 454 | param_count++; |
| 455 | } else { |
| 456 | target = V_008DFC_SQ_EXP_MRT + color_count; |
| 457 | color_count++; |
| 458 | } |
| 459 | break; |
| 460 | case TGSI_SEMANTIC_GENERIC: |
| 461 | target = V_008DFC_SQ_EXP_PARAM + param_count; |
Michel Dänzer | dd9d619 | 2012-05-18 15:01:10 +0200 | [diff] [blame] | 462 | shader->output[i].param_offset = param_count; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 463 | param_count++; |
| 464 | break; |
| 465 | default: |
| 466 | target = 0; |
| 467 | fprintf(stderr, |
| 468 | "Warning: SI unhandled output type:%d\n", |
| 469 | d->Semantic.Name); |
| 470 | } |
| 471 | |
| 472 | /* Specify which components to enable */ |
| 473 | args[0] = lp_build_const_int32(base->gallivm, |
| 474 | component_bits); |
| 475 | |
| 476 | /* Specify whether the EXEC mask represents the valid mask */ |
| 477 | args[1] = lp_build_const_int32(base->gallivm, 0); |
| 478 | |
| 479 | /* Specify whether this is the last export */ |
| 480 | args[2] = lp_build_const_int32(base->gallivm, 0); |
| 481 | |
| 482 | /* Specify the target we are exporting */ |
| 483 | args[3] = lp_build_const_int32(base->gallivm, target); |
| 484 | |
| 485 | /* Set COMPR flag to zero to export data as 32-bit */ |
| 486 | args[4] = uint->zero; |
| 487 | |
| 488 | if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX ? |
| 489 | (d->Semantic.Name == TGSI_SEMANTIC_POSITION) : |
| 490 | (d->Semantic.Name == TGSI_SEMANTIC_COLOR)) { |
| 491 | if (last_args[0]) { |
| 492 | lp_build_intrinsic(base->gallivm->builder, |
| 493 | "llvm.SI.export", |
| 494 | LLVMVoidTypeInContext(base->gallivm->context), |
| 495 | last_args, 9); |
| 496 | } |
| 497 | |
| 498 | memcpy(last_args, args, sizeof(args)); |
| 499 | } else { |
| 500 | lp_build_intrinsic(base->gallivm->builder, |
| 501 | "llvm.SI.export", |
| 502 | LLVMVoidTypeInContext(base->gallivm->context), |
| 503 | args, 9); |
| 504 | } |
| 505 | |
| 506 | } |
| 507 | } |
| 508 | |
Christian König | f18fd25 | 2012-07-25 21:58:46 +0200 | [diff] [blame] | 509 | if (!last_args[0]) { |
| 510 | assert(si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT); |
| 511 | |
| 512 | /* Specify which components to enable */ |
| 513 | last_args[0] = lp_build_const_int32(base->gallivm, 0x0); |
| 514 | |
| 515 | /* Specify the target we are exporting */ |
| 516 | last_args[3] = lp_build_const_int32(base->gallivm, V_008DFC_SQ_EXP_MRT); |
| 517 | |
| 518 | /* Set COMPR flag to zero to export data as 32-bit */ |
| 519 | last_args[4] = uint->zero; |
| 520 | |
| 521 | /* dummy bits */ |
| 522 | last_args[5]= uint->zero; |
| 523 | last_args[6]= uint->zero; |
| 524 | last_args[7]= uint->zero; |
| 525 | last_args[8]= uint->zero; |
| 526 | } |
| 527 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 528 | /* Specify whether the EXEC mask represents the valid mask */ |
| 529 | last_args[1] = lp_build_const_int32(base->gallivm, |
| 530 | si_shader_ctx->type == TGSI_PROCESSOR_FRAGMENT); |
| 531 | |
| 532 | /* Specify that this is the last export */ |
| 533 | last_args[2] = lp_build_const_int32(base->gallivm, 1); |
| 534 | |
| 535 | lp_build_intrinsic(base->gallivm->builder, |
| 536 | "llvm.SI.export", |
| 537 | LLVMVoidTypeInContext(base->gallivm->context), |
| 538 | last_args, 9); |
| 539 | |
| 540 | /* XXX: Look up what this function does */ |
| 541 | /* ctx->shader->output[i].spi_sid = r600_spi_sid(&ctx->shader->output[i]);*/ |
| 542 | } |
| 543 | |
| 544 | static void tex_fetch_args( |
| 545 | struct lp_build_tgsi_context * bld_base, |
| 546 | struct lp_build_emit_data * emit_data) |
| 547 | { |
Michel Dänzer | c2bae6b | 2012-08-02 17:19:22 +0200 | [diff] [blame] | 548 | const struct tgsi_full_instruction * inst = emit_data->inst; |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 549 | LLVMValueRef ptr; |
| 550 | LLVMValueRef offset; |
| 551 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 552 | /* WriteMask */ |
Christian König | 250b7fd | 2012-08-01 23:18:14 +0200 | [diff] [blame] | 553 | /* XXX: should be optimized using emit_data->inst->Dst[0].Register.WriteMask*/ |
| 554 | emit_data->args[0] = lp_build_const_int32(bld_base->base.gallivm, 0xf); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 555 | |
| 556 | /* Coordinates */ |
| 557 | /* XXX: Not all sample instructions need 4 address arguments. */ |
Michel Dänzer | c2bae6b | 2012-08-02 17:19:22 +0200 | [diff] [blame] | 558 | if (inst->Instruction.Opcode == TGSI_OPCODE_TXP) { |
| 559 | LLVMValueRef src_w; |
| 560 | unsigned chan; |
| 561 | LLVMValueRef coords[4]; |
| 562 | |
| 563 | emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4); |
| 564 | src_w = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_W); |
| 565 | |
| 566 | for (chan = 0; chan < 3; chan++ ) { |
| 567 | LLVMValueRef arg = lp_build_emit_fetch(bld_base, |
| 568 | emit_data->inst, 0, chan); |
| 569 | coords[chan] = lp_build_emit_llvm_binary(bld_base, |
| 570 | TGSI_OPCODE_DIV, |
| 571 | arg, src_w); |
| 572 | } |
| 573 | coords[3] = bld_base->base.one; |
| 574 | emit_data->args[1] = lp_build_gather_values(bld_base->base.gallivm, |
| 575 | coords, 4); |
| 576 | } else |
| 577 | emit_data->args[1] = lp_build_emit_fetch(bld_base, emit_data->inst, |
| 578 | 0, LP_CHAN_ALL); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 579 | |
| 580 | /* Resource */ |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 581 | ptr = use_sgpr(bld_base->base.gallivm, SGPR_CONST_PTR_V8I32, 4); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 582 | offset = lp_build_const_int32(bld_base->base.gallivm, |
Christian König | 92b96a8 | 2012-08-01 15:20:07 +0200 | [diff] [blame] | 583 | emit_data->inst->Src[1].Register.Index); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 584 | emit_data->args[2] = build_indexed_load(bld_base->base.gallivm, |
| 585 | ptr, offset); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 586 | |
| 587 | /* Sampler */ |
Tom Stellard | 89ece08 | 2012-05-29 11:36:29 -0400 | [diff] [blame] | 588 | ptr = use_sgpr(bld_base->base.gallivm, SGPR_CONST_PTR_V4I32, 2); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 589 | offset = lp_build_const_int32(bld_base->base.gallivm, |
Christian König | 92b96a8 | 2012-08-01 15:20:07 +0200 | [diff] [blame] | 590 | emit_data->inst->Src[1].Register.Index); |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 591 | emit_data->args[3] = build_indexed_load(bld_base->base.gallivm, |
| 592 | ptr, offset); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 593 | |
| 594 | /* Dimensions */ |
| 595 | /* XXX: We might want to pass this information to the shader at some. */ |
| 596 | /* emit_data->args[4] = lp_build_const_int32(bld_base->base.gallivm, |
| 597 | emit_data->inst->Texture.Texture); |
| 598 | */ |
| 599 | |
Tom Stellard | 467f516 | 2012-05-16 15:15:35 -0400 | [diff] [blame] | 600 | emit_data->arg_count = 4; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 601 | /* XXX: To optimize, we could use a float or v2f32, if the last bits of |
| 602 | * the writemask are clear */ |
| 603 | emit_data->dst_type = LLVMVectorType( |
| 604 | LLVMFloatTypeInContext(bld_base->base.gallivm->context), |
| 605 | 4); |
| 606 | } |
| 607 | |
| 608 | static const struct lp_build_tgsi_action tex_action = { |
| 609 | .fetch_args = tex_fetch_args, |
| 610 | .emit = lp_build_tgsi_intrinsic, |
| 611 | .intr_name = "llvm.SI.sample" |
| 612 | }; |
| 613 | |
| 614 | |
| 615 | int si_pipe_shader_create( |
| 616 | struct pipe_context *ctx, |
| 617 | struct si_pipe_shader *shader) |
| 618 | { |
| 619 | struct r600_context *rctx = (struct r600_context*)ctx; |
| 620 | struct si_shader_context si_shader_ctx; |
| 621 | struct tgsi_shader_info shader_info; |
| 622 | struct lp_build_tgsi_context * bld_base; |
| 623 | LLVMModuleRef mod; |
| 624 | unsigned char * inst_bytes; |
| 625 | unsigned inst_byte_count; |
| 626 | unsigned i; |
Christian König | d51b9b7 | 2012-07-24 18:50:49 +0200 | [diff] [blame] | 627 | uint32_t *ptr; |
Michel Dänzer | 4c4ef9c | 2012-06-07 19:30:47 +0200 | [diff] [blame] | 628 | bool dump; |
| 629 | |
| 630 | dump = debug_get_bool_option("RADEON_DUMP_SHADERS", FALSE); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 631 | |
Tom Stellard | a5ac8ee | 2012-08-02 13:21:30 -0400 | [diff] [blame] | 632 | memset(&si_shader_ctx.radeon_bld, 0, sizeof(si_shader_ctx.radeon_bld)); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 633 | radeon_llvm_context_init(&si_shader_ctx.radeon_bld); |
| 634 | bld_base = &si_shader_ctx.radeon_bld.soa.bld_base; |
| 635 | |
| 636 | tgsi_scan_shader(shader->tokens, &shader_info); |
| 637 | bld_base->info = &shader_info; |
| 638 | bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = fetch_constant; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 639 | bld_base->emit_epilogue = si_llvm_emit_epilogue; |
| 640 | |
| 641 | bld_base->op_actions[TGSI_OPCODE_TEX] = tex_action; |
Michel Dänzer | c2bae6b | 2012-08-02 17:19:22 +0200 | [diff] [blame] | 642 | bld_base->op_actions[TGSI_OPCODE_TXP] = tex_action; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 643 | |
| 644 | si_shader_ctx.radeon_bld.load_input = declare_input; |
| 645 | si_shader_ctx.tokens = shader->tokens; |
| 646 | tgsi_parse_init(&si_shader_ctx.parse, si_shader_ctx.tokens); |
| 647 | si_shader_ctx.shader = shader; |
| 648 | si_shader_ctx.type = si_shader_ctx.parse.FullHeader.Processor.Processor; |
| 649 | si_shader_ctx.rctx = rctx; |
| 650 | |
Christian König | 835098a | 2012-07-17 21:28:10 +0200 | [diff] [blame] | 651 | shader->shader.nr_cbufs = rctx->framebuffer.nr_cbufs; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 652 | |
Tom Stellard | 185fc9a | 2012-07-12 10:40:47 -0400 | [diff] [blame] | 653 | /* Dump TGSI code before doing TGSI->LLVM conversion in case the |
| 654 | * conversion fails. */ |
| 655 | if (dump) { |
| 656 | tgsi_dump(shader->tokens, 0); |
| 657 | } |
| 658 | |
Michel Dänzer | 82cd9c0 | 2012-08-08 15:35:42 +0200 | [diff] [blame] | 659 | if (!lp_build_tgsi_llvm(bld_base, shader->tokens)) { |
| 660 | fprintf(stderr, "Failed to translate shader from TGSI to LLVM\n"); |
| 661 | return -EINVAL; |
| 662 | } |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 663 | |
| 664 | radeon_llvm_finalize_module(&si_shader_ctx.radeon_bld); |
| 665 | |
| 666 | mod = bld_base->base.gallivm->module; |
Michel Dänzer | 4c4ef9c | 2012-06-07 19:30:47 +0200 | [diff] [blame] | 667 | if (dump) { |
Michel Dänzer | 4c4ef9c | 2012-06-07 19:30:47 +0200 | [diff] [blame] | 668 | LLVMDumpModule(mod); |
| 669 | } |
| 670 | radeon_llvm_compile(mod, &inst_bytes, &inst_byte_count, "SI", dump); |
| 671 | if (dump) { |
| 672 | fprintf(stderr, "SI CODE:\n"); |
| 673 | for (i = 0; i < inst_byte_count; i+=4 ) { |
| 674 | fprintf(stderr, "%02x%02x%02x%02x\n", inst_bytes[i + 3], |
| 675 | inst_bytes[i + 2], inst_bytes[i + 1], |
| 676 | inst_bytes[i]); |
| 677 | } |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 678 | } |
| 679 | |
| 680 | shader->num_sgprs = util_le32_to_cpu(*(uint32_t*)inst_bytes); |
| 681 | shader->num_vgprs = util_le32_to_cpu(*(uint32_t*)(inst_bytes + 4)); |
| 682 | shader->spi_ps_input_ena = util_le32_to_cpu(*(uint32_t*)(inst_bytes + 8)); |
| 683 | |
Michel Dänzer | 4b64fa2 | 2012-08-15 18:22:46 +0200 | [diff] [blame^] | 684 | radeon_llvm_dispose(&si_shader_ctx.radeon_bld); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 685 | tgsi_parse_free(&si_shader_ctx.parse); |
| 686 | |
| 687 | /* copy new shader */ |
Christian König | d51b9b7 | 2012-07-24 18:50:49 +0200 | [diff] [blame] | 688 | si_resource_reference(&shader->bo, NULL); |
| 689 | shader->bo = si_resource_create_custom(ctx->screen, PIPE_USAGE_IMMUTABLE, |
| 690 | inst_byte_count - 12); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 691 | if (shader->bo == NULL) { |
Christian König | d51b9b7 | 2012-07-24 18:50:49 +0200 | [diff] [blame] | 692 | return -ENOMEM; |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 693 | } |
| 694 | |
Christian König | d51b9b7 | 2012-07-24 18:50:49 +0200 | [diff] [blame] | 695 | ptr = (uint32_t*)rctx->ws->buffer_map(shader->bo->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE); |
| 696 | if (0 /*R600_BIG_ENDIAN*/) { |
| 697 | for (i = 0; i < (inst_byte_count-12)/4; ++i) { |
| 698 | ptr[i] = util_bswap32(*(uint32_t*)(inst_bytes+12 + i*4)); |
| 699 | } |
| 700 | } else { |
| 701 | memcpy(ptr, inst_bytes + 12, inst_byte_count - 12); |
| 702 | } |
| 703 | rctx->ws->buffer_unmap(shader->bo->cs_buf); |
| 704 | |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 705 | free(inst_bytes); |
| 706 | |
| 707 | return 0; |
| 708 | } |
| 709 | |
| 710 | void si_pipe_shader_destroy(struct pipe_context *ctx, struct si_pipe_shader *shader) |
| 711 | { |
Christian König | fe41287 | 2012-07-24 18:47:19 +0200 | [diff] [blame] | 712 | si_resource_reference(&shader->bo, NULL); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 713 | |
Christian König | 3c09f11 | 2012-07-18 17:39:15 +0200 | [diff] [blame] | 714 | memset(&shader->shader,0,sizeof(struct si_shader)); |
Tom Stellard | a75c616 | 2012-01-06 17:38:37 -0500 | [diff] [blame] | 715 | } |