1/************************************************************************** 2 * 3 * Copyright 2010 VMware, Inc. 4 * All rights reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * Texture sampling code generation 30 * @author Jose Fonseca <jfonseca@vmware.com> 31 */ 32 33#include "pipe/p_defines.h" 34#include "pipe/p_shader_tokens.h" 35#include "gallivm/lp_bld_const.h" 36#include "gallivm/lp_bld_debug.h" 37#include "gallivm/lp_bld_type.h" 38#include "gallivm/lp_bld_sample.h" 39#include "gallivm/lp_bld_tgsi.h" 40 41 42#include "util/u_debug.h" 43#include "util/u_memory.h" 44#include "util/u_pointer.h" 45#include "util/u_string.h" 46 47#include "draw_llvm.h" 48 49 50/** 51 * This provides the bridge between the sampler state store in 52 * lp_jit_context and lp_jit_texture and the sampler code 53 * generator. It provides the texture layout information required by 54 * the texture sampler code generator in terms of the state stored in 55 * lp_jit_context and lp_jit_texture in runtime. 56 */ 57struct draw_llvm_sampler_dynamic_state 58{ 59 struct lp_sampler_dynamic_state base; 60 61 const struct draw_sampler_static_state *static_state; 62}; 63 64 65/** 66 * This is the bridge between our sampler and the TGSI translator. 67 */ 68struct draw_llvm_sampler_soa 69{ 70 struct lp_build_sampler_soa base; 71 72 struct draw_llvm_sampler_dynamic_state dynamic_state; 73 74 unsigned nr_samplers; 75}; 76 77struct draw_llvm_image_dynamic_state 78{ 79 struct lp_sampler_dynamic_state base; 80 81 const struct draw_image_static_state *static_state; 82}; 83 84struct draw_llvm_image_soa 85{ 86 struct lp_build_image_soa base; 87 88 struct draw_llvm_image_dynamic_state dynamic_state; 89 90 unsigned nr_images; 91}; 92 93/** 94 * Fetch the specified member of the lp_jit_texture structure. 95 * \param emit_load if TRUE, emit the LLVM load instruction to actually 96 * fetch the field's value. Otherwise, just emit the 97 * GEP code to address the field. 98 * 99 * @sa http://llvm.org/docs/GetElementPtr.html 100 */ 101static LLVMValueRef 102draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base, 103 struct gallivm_state *gallivm, 104 LLVMValueRef context_ptr, 105 unsigned texture_unit, 106 LLVMValueRef texture_unit_offset, 107 unsigned member_index, 108 const char *member_name, 109 boolean emit_load) 110{ 111 LLVMBuilderRef builder = gallivm->builder; 112 LLVMValueRef indices[4]; 113 LLVMValueRef ptr; 114 LLVMValueRef res; 115 116 assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); 117 118 /* context[0] */ 119 indices[0] = lp_build_const_int32(gallivm, 0); 120 /* context[0].textures */ 121 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_TEXTURES); 122 /* context[0].textures[unit] */ 123 indices[2] = lp_build_const_int32(gallivm, texture_unit); 124 if (texture_unit_offset) { 125 indices[2] = LLVMBuildAdd(gallivm->builder, indices[2], texture_unit_offset, ""); 126 LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, LLVMIntULT, indices[2], lp_build_const_int32(gallivm, PIPE_MAX_SHADER_SAMPLER_VIEWS), ""); 127 indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2], lp_build_const_int32(gallivm, texture_unit), ""); 128 } 129 /* context[0].textures[unit].member */ 130 indices[3] = lp_build_const_int32(gallivm, member_index); 131 132 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); 133 134 if (emit_load) 135 res = LLVMBuildLoad(builder, ptr, ""); 136 else 137 res = ptr; 138 139 lp_build_name(res, "context.texture%u.%s", texture_unit, member_name); 140 141 return res; 142} 143 144 145/** 146 * Fetch the specified member of the lp_jit_sampler structure. 147 * \param emit_load if TRUE, emit the LLVM load instruction to actually 148 * fetch the field's value. Otherwise, just emit the 149 * GEP code to address the field. 150 * 151 * @sa http://llvm.org/docs/GetElementPtr.html 152 */ 153static LLVMValueRef 154draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base, 155 struct gallivm_state *gallivm, 156 LLVMValueRef context_ptr, 157 unsigned sampler_unit, 158 unsigned member_index, 159 const char *member_name, 160 boolean emit_load) 161{ 162 LLVMBuilderRef builder = gallivm->builder; 163 LLVMValueRef indices[4]; 164 LLVMValueRef ptr; 165 LLVMValueRef res; 166 167 assert(sampler_unit < PIPE_MAX_SAMPLERS); 168 169 /* context[0] */ 170 indices[0] = lp_build_const_int32(gallivm, 0); 171 /* context[0].samplers */ 172 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS); 173 /* context[0].samplers[unit] */ 174 indices[2] = lp_build_const_int32(gallivm, sampler_unit); 175 /* context[0].samplers[unit].member */ 176 indices[3] = lp_build_const_int32(gallivm, member_index); 177 178 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); 179 180 if (emit_load) 181 res = LLVMBuildLoad(builder, ptr, ""); 182 else 183 res = ptr; 184 185 lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name); 186 187 return res; 188} 189 190/** 191 * Fetch the specified member of the lp_jit_texture structure. 192 * \param emit_load if TRUE, emit the LLVM load instruction to actually 193 * fetch the field's value. Otherwise, just emit the 194 * GEP code to address the field. 195 * 196 * @sa http://llvm.org/docs/GetElementPtr.html 197 */ 198static LLVMValueRef 199draw_llvm_image_member(const struct lp_sampler_dynamic_state *base, 200 struct gallivm_state *gallivm, 201 LLVMValueRef context_ptr, 202 unsigned image_unit, 203 LLVMValueRef image_unit_offset, 204 unsigned member_index, 205 const char *member_name, 206 boolean emit_load) 207{ 208 LLVMBuilderRef builder = gallivm->builder; 209 LLVMValueRef indices[4]; 210 LLVMValueRef ptr; 211 LLVMValueRef res; 212 213 assert(image_unit < PIPE_MAX_SHADER_IMAGES); 214 215 /* context[0] */ 216 indices[0] = lp_build_const_int32(gallivm, 0); 217 /* context[0].textures */ 218 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_IMAGES); 219 /* context[0].textures[unit] */ 220 indices[2] = lp_build_const_int32(gallivm, image_unit); 221 if (image_unit_offset) { 222 indices[2] = LLVMBuildAdd(gallivm->builder, indices[2], image_unit_offset, ""); 223 LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, LLVMIntULT, indices[2], lp_build_const_int32(gallivm, PIPE_MAX_SHADER_IMAGES), ""); 224 indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2], lp_build_const_int32(gallivm, image_unit), ""); 225 } 226 /* context[0].textures[unit].member */ 227 indices[3] = lp_build_const_int32(gallivm, member_index); 228 229 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); 230 231 if (emit_load) 232 res = LLVMBuildLoad(builder, ptr, ""); 233 else 234 res = ptr; 235 236 lp_build_name(res, "context.image%u.%s", image_unit, member_name); 237 238 return res; 239} 240 241/** 242 * Helper macro to instantiate the functions that generate the code to 243 * fetch the members of lp_jit_texture to fulfill the sampler code 244 * generator requests. 245 * 246 * This complexity is the price we have to pay to keep the texture 247 * sampler code generator a reusable module without dependencies to 248 * llvmpipe internals. 249 */ 250#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ 251 static LLVMValueRef \ 252 draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ 253 struct gallivm_state *gallivm, \ 254 LLVMValueRef context_ptr, \ 255 unsigned texture_unit, \ 256 LLVMValueRef texture_unit_offset) \ 257 { \ 258 return draw_llvm_texture_member(base, gallivm, context_ptr, \ 259 texture_unit, texture_unit_offset, \ 260 _index, #_name, _emit_load ); \ 261 } 262 263 264DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE) 265DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE) 266DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE) 267DRAW_LLVM_TEXTURE_MEMBER(first_level,DRAW_JIT_TEXTURE_FIRST_LEVEL, TRUE) 268DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE) 269DRAW_LLVM_TEXTURE_MEMBER(base_ptr, DRAW_JIT_TEXTURE_BASE, TRUE) 270DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE) 271DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE) 272DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE) 273DRAW_LLVM_TEXTURE_MEMBER(num_samples, DRAW_JIT_TEXTURE_NUM_SAMPLES, TRUE) 274DRAW_LLVM_TEXTURE_MEMBER(sample_stride, DRAW_JIT_TEXTURE_SAMPLE_STRIDE, TRUE) 275 276#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \ 277 static LLVMValueRef \ 278 draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \ 279 struct gallivm_state *gallivm, \ 280 LLVMValueRef context_ptr, \ 281 unsigned sampler_unit) \ 282 { \ 283 return draw_llvm_sampler_member(base, gallivm, context_ptr, \ 284 sampler_unit, _index, #_name, _emit_load ); \ 285 } 286 287 288DRAW_LLVM_SAMPLER_MEMBER(min_lod, DRAW_JIT_SAMPLER_MIN_LOD, TRUE) 289DRAW_LLVM_SAMPLER_MEMBER(max_lod, DRAW_JIT_SAMPLER_MAX_LOD, TRUE) 290DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE) 291DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE) 292DRAW_LLVM_SAMPLER_MEMBER(max_aniso, DRAW_JIT_SAMPLER_MAX_ANISO, TRUE) 293 294#define DRAW_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \ 295 static LLVMValueRef \ 296 draw_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \ 297 struct gallivm_state *gallivm, \ 298 LLVMValueRef context_ptr, \ 299 unsigned image_unit, LLVMValueRef image_unit_offset) \ 300 { \ 301 return draw_llvm_image_member(base, gallivm, context_ptr, \ 302 image_unit, image_unit_offset, \ 303 _index, #_name, _emit_load ); \ 304 } 305 306 307DRAW_LLVM_IMAGE_MEMBER(width, DRAW_JIT_IMAGE_WIDTH, TRUE) 308DRAW_LLVM_IMAGE_MEMBER(height, DRAW_JIT_IMAGE_HEIGHT, TRUE) 309DRAW_LLVM_IMAGE_MEMBER(depth, DRAW_JIT_IMAGE_DEPTH, TRUE) 310DRAW_LLVM_IMAGE_MEMBER(base_ptr, DRAW_JIT_IMAGE_BASE, TRUE) 311DRAW_LLVM_IMAGE_MEMBER(row_stride, DRAW_JIT_IMAGE_ROW_STRIDE, TRUE) 312DRAW_LLVM_IMAGE_MEMBER(img_stride, DRAW_JIT_IMAGE_IMG_STRIDE, TRUE) 313DRAW_LLVM_IMAGE_MEMBER(num_samples, DRAW_JIT_IMAGE_NUM_SAMPLES, TRUE) 314DRAW_LLVM_IMAGE_MEMBER(sample_stride, DRAW_JIT_IMAGE_SAMPLE_STRIDE, TRUE) 315 316static void 317draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) 318{ 319 FREE(sampler); 320} 321 322 323/** 324 * Fetch filtered values from texture. 325 * The 'texel' parameter returns four vectors corresponding to R, G, B, A. 326 */ 327static void 328draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, 329 struct gallivm_state *gallivm, 330 const struct lp_sampler_params *params) 331{ 332 struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; 333 unsigned texture_index = params->texture_index; 334 unsigned sampler_index = params->sampler_index; 335 336 assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 337 assert(sampler_index < PIPE_MAX_SAMPLERS); 338 339 if (params->texture_index_offset) { 340 struct lp_build_sample_array_switch switch_info; 341 memset(&switch_info, 0, sizeof(switch_info)); 342 LLVMValueRef unit = LLVMBuildAdd(gallivm->builder, params->texture_index_offset, 343 lp_build_const_int32(gallivm, texture_index), ""); 344 lp_build_sample_array_init_soa(&switch_info, gallivm, params, unit, 345 0, sampler->nr_samplers); 346 347 for (unsigned i = 0; i < sampler->nr_samplers; i++) { 348 lp_build_sample_array_case_soa(&switch_info, i, 349 &sampler->dynamic_state.static_state[i].texture_state, 350 &sampler->dynamic_state.static_state[i].sampler_state, 351 &sampler->dynamic_state.base); 352 } 353 lp_build_sample_array_fini_soa(&switch_info); 354 } else { 355 lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state, 356 &sampler->dynamic_state.static_state[sampler_index].sampler_state, 357 &sampler->dynamic_state.base, 358 gallivm, params); 359 } 360} 361 362 363/** 364 * Fetch the texture size. 365 */ 366static void 367draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, 368 struct gallivm_state *gallivm, 369 const struct lp_sampler_size_query_params *params) 370{ 371 struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; 372 373 assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); 374 375 lp_build_size_query_soa(gallivm, 376 &sampler->dynamic_state.static_state[params->texture_unit].texture_state, 377 &sampler->dynamic_state.base, 378 params); 379} 380 381struct lp_build_sampler_soa * 382draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state, 383 unsigned nr_samplers) 384{ 385 struct draw_llvm_sampler_soa *sampler; 386 387 sampler = CALLOC_STRUCT(draw_llvm_sampler_soa); 388 if (!sampler) 389 return NULL; 390 391 sampler->base.destroy = draw_llvm_sampler_soa_destroy; 392 sampler->base.emit_tex_sample = draw_llvm_sampler_soa_emit_fetch_texel; 393 sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query; 394 sampler->dynamic_state.base.width = draw_llvm_texture_width; 395 sampler->dynamic_state.base.height = draw_llvm_texture_height; 396 sampler->dynamic_state.base.depth = draw_llvm_texture_depth; 397 sampler->dynamic_state.base.first_level = draw_llvm_texture_first_level; 398 sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level; 399 sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride; 400 sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride; 401 sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr; 402 sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets; 403 sampler->dynamic_state.base.num_samples = draw_llvm_texture_num_samples; 404 sampler->dynamic_state.base.sample_stride = draw_llvm_texture_sample_stride; 405 sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod; 406 sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod; 407 sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias; 408 sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color; 409 sampler->dynamic_state.base.max_aniso = draw_llvm_sampler_max_aniso; 410 sampler->dynamic_state.static_state = static_state; 411 412 sampler->nr_samplers = nr_samplers; 413 return &sampler->base; 414} 415 416static void 417draw_llvm_image_soa_emit_op(const struct lp_build_image_soa *base, 418 struct gallivm_state *gallivm, 419 const struct lp_img_params *params) 420{ 421 struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base; 422 unsigned image_index = params->image_index; 423 assert(image_index < PIPE_MAX_SHADER_IMAGES); 424 425 if (params->image_index_offset) { 426 struct lp_build_img_op_array_switch switch_info; 427 memset(&switch_info, 0, sizeof(switch_info)); 428 LLVMValueRef unit = LLVMBuildAdd(gallivm->builder, params->image_index_offset, 429 lp_build_const_int32(gallivm, image_index), ""); 430 lp_build_image_op_switch_soa(&switch_info, gallivm, params, 431 unit, 0, image->nr_images); 432 433 for (unsigned i = 0; i < image->nr_images; i++) { 434 lp_build_image_op_array_case(&switch_info, i, 435 &image->dynamic_state.static_state[i].image_state, 436 &image->dynamic_state.base); 437 } 438 lp_build_image_op_array_fini_soa(&switch_info); 439 return; 440 } 441 lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state, 442 &image->dynamic_state.base, 443 gallivm, params, params->outdata); 444} 445/** 446 * Fetch the texture size. 447 */ 448static void 449draw_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base, 450 struct gallivm_state *gallivm, 451 const struct lp_sampler_size_query_params *params) 452{ 453 struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base; 454 455 assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES); 456 457 lp_build_size_query_soa(gallivm, 458 &image->dynamic_state.static_state[params->texture_unit].image_state, 459 &image->dynamic_state.base, 460 params); 461} 462static void 463draw_llvm_image_soa_destroy(struct lp_build_image_soa *image) 464{ 465 FREE(image); 466} 467 468struct lp_build_image_soa * 469draw_llvm_image_soa_create(const struct draw_image_static_state *static_state, 470 unsigned nr_images) 471{ 472 struct draw_llvm_image_soa *image; 473 474 image = CALLOC_STRUCT(draw_llvm_image_soa); 475 if (!image) 476 return NULL; 477 478 image->base.destroy = draw_llvm_image_soa_destroy; 479 image->base.emit_op = draw_llvm_image_soa_emit_op; 480 image->base.emit_size_query = draw_llvm_image_soa_emit_size_query; 481 482 image->dynamic_state.base.width = draw_llvm_image_width; 483 image->dynamic_state.base.height = draw_llvm_image_height; 484 485 image->dynamic_state.base.depth = draw_llvm_image_depth; 486 image->dynamic_state.base.base_ptr = draw_llvm_image_base_ptr; 487 image->dynamic_state.base.row_stride = draw_llvm_image_row_stride; 488 image->dynamic_state.base.img_stride = draw_llvm_image_img_stride; 489 image->dynamic_state.base.num_samples = draw_llvm_image_num_samples; 490 image->dynamic_state.base.sample_stride = draw_llvm_image_sample_stride; 491 492 image->dynamic_state.static_state = static_state; 493 494 image->nr_images = nr_images; 495 return &image->base; 496} 497