1/************************************************************************** 2 * 3 * Copyright 2009 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 * Largely a copy of llvmpipe's lp_tex_sample.c 30 */ 31 32/** 33 * Texture sampling code generation 34 * 35 * This file is nothing more than ugly glue between three largely independent 36 * entities: 37 * - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa) 38 * - texture sampling code generation (i.e., lp_build_sample_soa) 39 * - SWR driver 40 * 41 * All interesting code is in the functions mentioned above. There is really 42 * nothing to see here. 43 * 44 * @author Jose Fonseca <jfonseca@vmware.com> 45 */ 46 47#include "state.h" 48#include "JitManager.h" 49#include "state_llvm.h" 50 51#include "pipe/p_defines.h" 52#include "pipe/p_shader_tokens.h" 53#include "gallivm/lp_bld_debug.h" 54#include "gallivm/lp_bld_const.h" 55#include "gallivm/lp_bld_type.h" 56#include "gallivm/lp_bld_sample.h" 57#include "gallivm/lp_bld_tgsi.h" 58#include "util/u_memory.h" 59 60#include "swr_tex_sample.h" 61#include "swr_context_llvm.h" 62 63using namespace SwrJit; 64 65/** 66 * This provides the bridge between the sampler state store in 67 * lp_jit_context and lp_jit_texture and the sampler code 68 * generator. It provides the texture layout information required by 69 * the texture sampler code generator in terms of the state stored in 70 * lp_jit_context and lp_jit_texture in runtime. 71 */ 72struct swr_sampler_dynamic_state { 73 struct lp_sampler_dynamic_state base; 74 75 const struct swr_sampler_static_state *static_state; 76 77 unsigned shader_type; 78}; 79 80 81/** 82 * This is the bridge between our sampler and the TGSI translator. 83 */ 84struct swr_sampler_soa { 85 struct lp_build_sampler_soa base; 86 87 struct swr_sampler_dynamic_state dynamic_state; 88}; 89 90 91/** 92 * Fetch the specified member of the lp_jit_texture structure. 93 * \param emit_load if TRUE, emit the LLVM load instruction to actually 94 * fetch the field's value. Otherwise, just emit the 95 * GEP code to address the field. 96 * 97 * @sa http://llvm.org/docs/GetElementPtr.html 98 */ 99static LLVMValueRef 100swr_texture_member(const struct lp_sampler_dynamic_state *base, 101 struct gallivm_state *gallivm, 102 LLVMValueRef context_ptr, 103 unsigned texture_unit, 104 unsigned member_index, 105 const char *member_name, 106 boolean emit_load) 107{ 108 LLVMBuilderRef builder = gallivm->builder; 109 LLVMValueRef indices[4]; 110 LLVMValueRef ptr; 111 LLVMValueRef res; 112 113 assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); 114 115 /* context[0] */ 116 indices[0] = lp_build_const_int32(gallivm, 0); 117 /* context[0].textures */ 118 auto dynamic = (const struct swr_sampler_dynamic_state *)base; 119 switch (dynamic->shader_type) { 120 case PIPE_SHADER_FRAGMENT: 121 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesFS); 122 break; 123 case PIPE_SHADER_VERTEX: 124 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesVS); 125 break; 126 default: 127 assert(0 && "unsupported shader type"); 128 break; 129 } 130 /* context[0].textures[unit] */ 131 indices[2] = lp_build_const_int32(gallivm, texture_unit); 132 /* context[0].textures[unit].member */ 133 indices[3] = lp_build_const_int32(gallivm, member_index); 134 135 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); 136 137 if (emit_load) 138 res = LLVMBuildLoad(builder, ptr, ""); 139 else 140 res = ptr; 141 142 lp_build_name(res, "context.texture%u.%s", texture_unit, member_name); 143 144 return res; 145} 146 147 148/** 149 * Helper macro to instantiate the functions that generate the code to 150 * fetch the members of lp_jit_texture to fulfill the sampler code 151 * generator requests. 152 * 153 * This complexity is the price we have to pay to keep the texture 154 * sampler code generator a reusable module without dependencies to 155 * swr internals. 156 */ 157#define SWR_TEXTURE_MEMBER(_name, _emit_load) \ 158 static LLVMValueRef swr_texture_##_name( \ 159 const struct lp_sampler_dynamic_state *base, \ 160 struct gallivm_state *gallivm, \ 161 LLVMValueRef context_ptr, \ 162 unsigned texture_unit) \ 163 { \ 164 return swr_texture_member(base, \ 165 gallivm, \ 166 context_ptr, \ 167 texture_unit, \ 168 swr_jit_texture_##_name, \ 169 #_name, \ 170 _emit_load); \ 171 } 172 173 174SWR_TEXTURE_MEMBER(width, TRUE) 175SWR_TEXTURE_MEMBER(height, TRUE) 176SWR_TEXTURE_MEMBER(depth, TRUE) 177SWR_TEXTURE_MEMBER(first_level, TRUE) 178SWR_TEXTURE_MEMBER(last_level, TRUE) 179SWR_TEXTURE_MEMBER(base_ptr, TRUE) 180SWR_TEXTURE_MEMBER(row_stride, FALSE) 181SWR_TEXTURE_MEMBER(img_stride, FALSE) 182SWR_TEXTURE_MEMBER(mip_offsets, FALSE) 183 184 185/** 186 * Fetch the specified member of the lp_jit_sampler structure. 187 * \param emit_load if TRUE, emit the LLVM load instruction to actually 188 * fetch the field's value. Otherwise, just emit the 189 * GEP code to address the field. 190 * 191 * @sa http://llvm.org/docs/GetElementPtr.html 192 */ 193static LLVMValueRef 194swr_sampler_member(const struct lp_sampler_dynamic_state *base, 195 struct gallivm_state *gallivm, 196 LLVMValueRef context_ptr, 197 unsigned sampler_unit, 198 unsigned member_index, 199 const char *member_name, 200 boolean emit_load) 201{ 202 LLVMBuilderRef builder = gallivm->builder; 203 LLVMValueRef indices[4]; 204 LLVMValueRef ptr; 205 LLVMValueRef res; 206 207 assert(sampler_unit < PIPE_MAX_SAMPLERS); 208 209 /* context[0] */ 210 indices[0] = lp_build_const_int32(gallivm, 0); 211 /* context[0].samplers */ 212 auto dynamic = (const struct swr_sampler_dynamic_state *)base; 213 switch (dynamic->shader_type) { 214 case PIPE_SHADER_FRAGMENT: 215 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersFS); 216 break; 217 case PIPE_SHADER_VERTEX: 218 indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersVS); 219 break; 220 default: 221 assert(0 && "unsupported shader type"); 222 break; 223 } 224 /* context[0].samplers[unit] */ 225 indices[2] = lp_build_const_int32(gallivm, sampler_unit); 226 /* context[0].samplers[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.sampler%u.%s", sampler_unit, member_name); 237 238 return res; 239} 240 241 242#define SWR_SAMPLER_MEMBER(_name, _emit_load) \ 243 static LLVMValueRef swr_sampler_##_name( \ 244 const struct lp_sampler_dynamic_state *base, \ 245 struct gallivm_state *gallivm, \ 246 LLVMValueRef context_ptr, \ 247 unsigned sampler_unit) \ 248 { \ 249 return swr_sampler_member(base, \ 250 gallivm, \ 251 context_ptr, \ 252 sampler_unit, \ 253 swr_jit_sampler_##_name, \ 254 #_name, \ 255 _emit_load); \ 256 } 257 258 259SWR_SAMPLER_MEMBER(min_lod, TRUE) 260SWR_SAMPLER_MEMBER(max_lod, TRUE) 261SWR_SAMPLER_MEMBER(lod_bias, TRUE) 262SWR_SAMPLER_MEMBER(border_color, FALSE) 263 264 265static void 266swr_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) 267{ 268 FREE(sampler); 269} 270 271 272/** 273 * Fetch filtered values from texture. 274 * The 'texel' parameter returns four vectors corresponding to R, G, B, A. 275 */ 276static void 277swr_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, 278 struct gallivm_state *gallivm, 279 const struct lp_sampler_params *params) 280{ 281 struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base; 282 unsigned texture_index = params->texture_index; 283 unsigned sampler_index = params->sampler_index; 284 285 assert(sampler_index < PIPE_MAX_SAMPLERS); 286 assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 287 288#if 0 289 lp_build_sample_nop(gallivm, params->type, params->coords, params->texel); 290#else 291 lp_build_sample_soa( 292 &sampler->dynamic_state.static_state[texture_index].texture_state, 293 &sampler->dynamic_state.static_state[sampler_index].sampler_state, 294 &sampler->dynamic_state.base, 295 gallivm, 296 params); 297#endif 298} 299 300/** 301 * Fetch the texture size. 302 */ 303static void 304swr_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, 305 struct gallivm_state *gallivm, 306 const struct lp_sampler_size_query_params *params) 307{ 308 struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base; 309 310 assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); 311 312 lp_build_size_query_soa( 313 gallivm, 314 &sampler->dynamic_state.static_state[params->texture_unit].texture_state, 315 &sampler->dynamic_state.base, 316 params); 317} 318 319 320struct lp_build_sampler_soa * 321swr_sampler_soa_create(const struct swr_sampler_static_state *static_state, 322 unsigned shader_type) 323{ 324 struct swr_sampler_soa *sampler; 325 326 sampler = CALLOC_STRUCT(swr_sampler_soa); 327 if (!sampler) 328 return NULL; 329 330 sampler->base.destroy = swr_sampler_soa_destroy; 331 sampler->base.emit_tex_sample = swr_sampler_soa_emit_fetch_texel; 332 sampler->base.emit_size_query = swr_sampler_soa_emit_size_query; 333 sampler->dynamic_state.base.width = swr_texture_width; 334 sampler->dynamic_state.base.height = swr_texture_height; 335 sampler->dynamic_state.base.depth = swr_texture_depth; 336 sampler->dynamic_state.base.first_level = swr_texture_first_level; 337 sampler->dynamic_state.base.last_level = swr_texture_last_level; 338 sampler->dynamic_state.base.base_ptr = swr_texture_base_ptr; 339 sampler->dynamic_state.base.row_stride = swr_texture_row_stride; 340 sampler->dynamic_state.base.img_stride = swr_texture_img_stride; 341 sampler->dynamic_state.base.mip_offsets = swr_texture_mip_offsets; 342 sampler->dynamic_state.base.min_lod = swr_sampler_min_lod; 343 sampler->dynamic_state.base.max_lod = swr_sampler_max_lod; 344 sampler->dynamic_state.base.lod_bias = swr_sampler_lod_bias; 345 sampler->dynamic_state.base.border_color = swr_sampler_border_color; 346 347 sampler->dynamic_state.static_state = static_state; 348 349 sampler->dynamic_state.shader_type = shader_type; 350 351 return &sampler->base; 352} 353