Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 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
 * Texture sampling code generation
30
 *
31
 * This file is nothing more than ugly glue between three largely independent
32
 * entities:
33
 * - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa)
34
 * - texture sampling code generation (i.e., lp_build_sample_soa)
35
 * - LLVM pipe driver
36
 *
37
 * All interesting code is in the functions mentioned above. There is really
38
 * nothing to see here.
39
 *
40
 * @author Jose Fonseca 
41
 */
42
 
43
#include "pipe/p_defines.h"
44
#include "pipe/p_shader_tokens.h"
45
#include "gallivm/lp_bld_debug.h"
46
#include "gallivm/lp_bld_const.h"
47
#include "gallivm/lp_bld_type.h"
48
#include "gallivm/lp_bld_sample.h"
49
#include "gallivm/lp_bld_tgsi.h"
50
#include "lp_jit.h"
51
#include "lp_tex_sample.h"
52
#include "lp_state_fs.h"
53
#include "lp_debug.h"
54
 
55
 
56
/**
57
 * This provides the bridge between the sampler state store in
58
 * lp_jit_context and lp_jit_texture and the sampler code
59
 * generator. It provides the texture layout information required by
60
 * the texture sampler code generator in terms of the state stored in
61
 * lp_jit_context and lp_jit_texture in runtime.
62
 */
63
struct llvmpipe_sampler_dynamic_state
64
{
65
   struct lp_sampler_dynamic_state base;
66
 
67
   const struct lp_sampler_static_state *static_state;
68
 
69
   LLVMValueRef context_ptr;
70
};
71
 
72
 
73
/**
74
 * This is the bridge between our sampler and the TGSI translator.
75
 */
76
struct lp_llvm_sampler_soa
77
{
78
   struct lp_build_sampler_soa base;
79
 
80
   struct llvmpipe_sampler_dynamic_state dynamic_state;
81
};
82
 
83
 
84
/**
85
 * Fetch the specified member of the lp_jit_texture structure.
86
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
87
 *                   fetch the field's value.  Otherwise, just emit the
88
 *                   GEP code to address the field.
89
 *
90
 * @sa http://llvm.org/docs/GetElementPtr.html
91
 */
92
static LLVMValueRef
93
lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
94
                       struct gallivm_state *gallivm,
95
                       unsigned texture_unit,
96
                       unsigned member_index,
97
                       const char *member_name,
98
                       boolean emit_load)
99
{
100
   struct llvmpipe_sampler_dynamic_state *state =
101
      (struct llvmpipe_sampler_dynamic_state *)base;
102
   LLVMBuilderRef builder = gallivm->builder;
103
   LLVMValueRef indices[4];
104
   LLVMValueRef ptr;
105
   LLVMValueRef res;
106
 
107
   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
108
 
109
   /* context[0] */
110
   indices[0] = lp_build_const_int32(gallivm, 0);
111
   /* context[0].textures */
112
   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_TEXTURES);
113
   /* context[0].textures[unit] */
114
   indices[2] = lp_build_const_int32(gallivm, texture_unit);
115
   /* context[0].textures[unit].member */
116
   indices[3] = lp_build_const_int32(gallivm, member_index);
117
 
118
   ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
119
 
120
   if (emit_load)
121
      res = LLVMBuildLoad(builder, ptr, "");
122
   else
123
      res = ptr;
124
 
125
   lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
126
 
127
   return res;
128
}
129
 
130
 
131
/**
132
 * Helper macro to instantiate the functions that generate the code to
133
 * fetch the members of lp_jit_texture to fulfill the sampler code
134
 * generator requests.
135
 *
136
 * This complexity is the price we have to pay to keep the texture
137
 * sampler code generator a reusable module without dependencies to
138
 * llvmpipe internals.
139
 */
140
#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load)  \
141
   static LLVMValueRef \
142
   lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
143
                            struct gallivm_state *gallivm, \
144
                            unsigned texture_unit) \
145
   { \
146
      return lp_llvm_texture_member(base, gallivm, texture_unit, _index, #_name, _emit_load ); \
147
   }
148
 
149
 
150
LP_LLVM_TEXTURE_MEMBER(width,      LP_JIT_TEXTURE_WIDTH, TRUE)
151
LP_LLVM_TEXTURE_MEMBER(height,     LP_JIT_TEXTURE_HEIGHT, TRUE)
152
LP_LLVM_TEXTURE_MEMBER(depth,      LP_JIT_TEXTURE_DEPTH, TRUE)
153
LP_LLVM_TEXTURE_MEMBER(first_level, LP_JIT_TEXTURE_FIRST_LEVEL, TRUE)
154
LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE)
155
LP_LLVM_TEXTURE_MEMBER(base_ptr,   LP_JIT_TEXTURE_BASE, TRUE)
156
LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE)
157
LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE)
158
LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE)
159
 
160
 
161
/**
162
 * Fetch the specified member of the lp_jit_sampler structure.
163
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
164
 *                   fetch the field's value.  Otherwise, just emit the
165
 *                   GEP code to address the field.
166
 *
167
 * @sa http://llvm.org/docs/GetElementPtr.html
168
 */
169
static LLVMValueRef
170
lp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
171
                       struct gallivm_state *gallivm,
172
                       unsigned sampler_unit,
173
                       unsigned member_index,
174
                       const char *member_name,
175
                       boolean emit_load)
176
{
177
   struct llvmpipe_sampler_dynamic_state *state =
178
      (struct llvmpipe_sampler_dynamic_state *)base;
179
   LLVMBuilderRef builder = gallivm->builder;
180
   LLVMValueRef indices[4];
181
   LLVMValueRef ptr;
182
   LLVMValueRef res;
183
 
184
   assert(sampler_unit < PIPE_MAX_SAMPLERS);
185
 
186
   /* context[0] */
187
   indices[0] = lp_build_const_int32(gallivm, 0);
188
   /* context[0].samplers */
189
   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS);
190
   /* context[0].samplers[unit] */
191
   indices[2] = lp_build_const_int32(gallivm, sampler_unit);
192
   /* context[0].samplers[unit].member */
193
   indices[3] = lp_build_const_int32(gallivm, member_index);
194
 
195
   ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
196
 
197
   if (emit_load)
198
      res = LLVMBuildLoad(builder, ptr, "");
199
   else
200
      res = ptr;
201
 
202
   lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
203
 
204
   return res;
205
}
206
 
207
 
208
#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
209
   static LLVMValueRef \
210
   lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
211
                            struct gallivm_state *gallivm, \
212
                            unsigned sampler_unit) \
213
   { \
214
      return lp_llvm_sampler_member(base, gallivm, sampler_unit, _index, #_name, _emit_load ); \
215
   }
216
 
217
 
218
LP_LLVM_SAMPLER_MEMBER(min_lod,    LP_JIT_SAMPLER_MIN_LOD, TRUE)
219
LP_LLVM_SAMPLER_MEMBER(max_lod,    LP_JIT_SAMPLER_MAX_LOD, TRUE)
220
LP_LLVM_SAMPLER_MEMBER(lod_bias,   LP_JIT_SAMPLER_LOD_BIAS, TRUE)
221
LP_LLVM_SAMPLER_MEMBER(border_color, LP_JIT_SAMPLER_BORDER_COLOR, FALSE)
222
 
223
 
224
static void
225
lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
226
{
227
   FREE(sampler);
228
}
229
 
230
 
231
/**
232
 * Fetch filtered values from texture.
233
 * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
234
 */
235
static void
236
lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
237
                                     struct gallivm_state *gallivm,
238
                                     struct lp_type type,
239
                                     boolean is_fetch,
240
                                     unsigned texture_index,
241
                                     unsigned sampler_index,
242
                                     const LLVMValueRef *coords,
243
                                     const LLVMValueRef *offsets,
244
                                     const struct lp_derivatives *derivs,
245
                                     LLVMValueRef lod_bias, /* optional */
246
                                     LLVMValueRef explicit_lod, /* optional */
247
                                     boolean scalar_lod,
248
                                     LLVMValueRef *texel)
249
{
250
   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
251
 
252
   assert(sampler_index < PIPE_MAX_SAMPLERS);
253
   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
254
 
255
   if (LP_PERF & PERF_NO_TEX) {
256
      lp_build_sample_nop(gallivm, type, coords, texel);
257
      return;
258
   }
259
 
260
   lp_build_sample_soa(gallivm,
261
                       &sampler->dynamic_state.static_state[texture_index].texture_state,
262
                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
263
                       &sampler->dynamic_state.base,
264
                       type,
265
                       is_fetch,
266
                       texture_index,
267
                       sampler_index,
268
                       coords,
269
                       offsets,
270
                       derivs,
271
                       lod_bias, explicit_lod, scalar_lod,
272
                       texel);
273
}
274
 
275
/**
276
 * Fetch the texture size.
277
 */
278
static void
279
lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
280
                                    struct gallivm_state *gallivm,
281
                                    struct lp_type type,
282
                                    unsigned texture_unit,
283
                                    boolean need_nr_mips,
284
                                    LLVMValueRef explicit_lod, /* optional */
285
                                    LLVMValueRef *sizes_out)
286
{
287
   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
288
 
289
   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
290
 
291
   lp_build_size_query_soa(gallivm,
292
                           &sampler->dynamic_state.static_state[texture_unit].texture_state,
293
                           &sampler->dynamic_state.base,
294
                           type,
295
                           texture_unit,
296
                           need_nr_mips,
297
                           explicit_lod,
298
                           sizes_out);
299
}
300
 
301
 
302
struct lp_build_sampler_soa *
303
lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
304
                           LLVMValueRef context_ptr)
305
{
306
   struct lp_llvm_sampler_soa *sampler;
307
 
308
   sampler = CALLOC_STRUCT(lp_llvm_sampler_soa);
309
   if(!sampler)
310
      return NULL;
311
 
312
   sampler->base.destroy = lp_llvm_sampler_soa_destroy;
313
   sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel;
314
   sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query;
315
   sampler->dynamic_state.base.width = lp_llvm_texture_width;
316
   sampler->dynamic_state.base.height = lp_llvm_texture_height;
317
   sampler->dynamic_state.base.depth = lp_llvm_texture_depth;
318
   sampler->dynamic_state.base.first_level = lp_llvm_texture_first_level;
319
   sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level;
320
   sampler->dynamic_state.base.base_ptr = lp_llvm_texture_base_ptr;
321
   sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride;
322
   sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride;
323
   sampler->dynamic_state.base.mip_offsets = lp_llvm_texture_mip_offsets;
324
   sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod;
325
   sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod;
326
   sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias;
327
   sampler->dynamic_state.base.border_color = lp_llvm_sampler_border_color;
328
 
329
   sampler->dynamic_state.static_state = static_state;
330
   sampler->dynamic_state.context_ptr = context_ptr;
331
 
332
   return &sampler->base;
333
}
334