Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 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
 
70
 
71
/**
72
 * This is the bridge between our sampler and the TGSI translator.
73
 */
74
struct lp_llvm_sampler_soa
75
{
76
   struct lp_build_sampler_soa base;
77
 
78
   struct llvmpipe_sampler_dynamic_state dynamic_state;
79
};
80
 
81
 
82
/**
83
 * Fetch the specified member of the lp_jit_texture structure.
84
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
85
 *                   fetch the field's value.  Otherwise, just emit the
86
 *                   GEP code to address the field.
87
 *
88
 * @sa http://llvm.org/docs/GetElementPtr.html
89
 */
90
static LLVMValueRef
91
lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
92
                       struct gallivm_state *gallivm,
93
                       LLVMValueRef context_ptr,
94
                       unsigned texture_unit,
95
                       unsigned member_index,
96
                       const char *member_name,
97
                       boolean emit_load)
98
{
99
   LLVMBuilderRef builder = gallivm->builder;
100
   LLVMValueRef indices[4];
101
   LLVMValueRef ptr;
102
   LLVMValueRef res;
103
 
104
   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
105
 
106
   /* context[0] */
107
   indices[0] = lp_build_const_int32(gallivm, 0);
108
   /* context[0].textures */
109
   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_TEXTURES);
110
   /* context[0].textures[unit] */
111
   indices[2] = lp_build_const_int32(gallivm, texture_unit);
112
   /* context[0].textures[unit].member */
113
   indices[3] = lp_build_const_int32(gallivm, member_index);
114
 
115
   ptr = LLVMBuildGEP(builder, context_ptr, indices, Elements(indices), "");
116
 
117
   if (emit_load)
118
      res = LLVMBuildLoad(builder, ptr, "");
119
   else
120
      res = ptr;
121
 
122
   lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
123
 
124
   return res;
125
}
126
 
127
 
128
/**
129
 * Helper macro to instantiate the functions that generate the code to
130
 * fetch the members of lp_jit_texture to fulfill the sampler code
131
 * generator requests.
132
 *
133
 * This complexity is the price we have to pay to keep the texture
134
 * sampler code generator a reusable module without dependencies to
135
 * llvmpipe internals.
136
 */
137
#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load)  \
138
   static LLVMValueRef \
139
   lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
140
                            struct gallivm_state *gallivm, \
141
                            LLVMValueRef context_ptr, \
142
                            unsigned texture_unit) \
143
   { \
144
      return lp_llvm_texture_member(base, gallivm, context_ptr, \
145
                                    texture_unit, _index, #_name, _emit_load ); \
146
   }
147
 
148
 
149
LP_LLVM_TEXTURE_MEMBER(width,      LP_JIT_TEXTURE_WIDTH, TRUE)
150
LP_LLVM_TEXTURE_MEMBER(height,     LP_JIT_TEXTURE_HEIGHT, TRUE)
151
LP_LLVM_TEXTURE_MEMBER(depth,      LP_JIT_TEXTURE_DEPTH, TRUE)
152
LP_LLVM_TEXTURE_MEMBER(first_level, LP_JIT_TEXTURE_FIRST_LEVEL, TRUE)
153
LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE)
154
LP_LLVM_TEXTURE_MEMBER(base_ptr,   LP_JIT_TEXTURE_BASE, TRUE)
155
LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE)
156
LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE)
157
LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE)
158
 
159
 
160
/**
161
 * Fetch the specified member of the lp_jit_sampler structure.
162
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
163
 *                   fetch the field's value.  Otherwise, just emit the
164
 *                   GEP code to address the field.
165
 *
166
 * @sa http://llvm.org/docs/GetElementPtr.html
167
 */
168
static LLVMValueRef
169
lp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
170
                       struct gallivm_state *gallivm,
171
                       LLVMValueRef context_ptr,
172
                       unsigned sampler_unit,
173
                       unsigned member_index,
174
                       const char *member_name,
175
                       boolean emit_load)
176
{
177
   LLVMBuilderRef builder = gallivm->builder;
178
   LLVMValueRef indices[4];
179
   LLVMValueRef ptr;
180
   LLVMValueRef res;
181
 
182
   assert(sampler_unit < PIPE_MAX_SAMPLERS);
183
 
184
   /* context[0] */
185
   indices[0] = lp_build_const_int32(gallivm, 0);
186
   /* context[0].samplers */
187
   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS);
188
   /* context[0].samplers[unit] */
189
   indices[2] = lp_build_const_int32(gallivm, sampler_unit);
190
   /* context[0].samplers[unit].member */
191
   indices[3] = lp_build_const_int32(gallivm, member_index);
192
 
193
   ptr = LLVMBuildGEP(builder, context_ptr, indices, Elements(indices), "");
194
 
195
   if (emit_load)
196
      res = LLVMBuildLoad(builder, ptr, "");
197
   else
198
      res = ptr;
199
 
200
   lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
201
 
202
   return res;
203
}
204
 
205
 
206
#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
207
   static LLVMValueRef \
208
   lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
209
                            struct gallivm_state *gallivm, \
210
                            LLVMValueRef context_ptr, \
211
                            unsigned sampler_unit) \
212
   { \
213
      return lp_llvm_sampler_member(base, gallivm, context_ptr, \
214
                                    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
                                     const struct lp_sampler_params *params)
239
{
240
   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
241
   unsigned texture_index = params->texture_index;
242
   unsigned sampler_index = params->sampler_index;
243
 
244
   assert(sampler_index < PIPE_MAX_SAMPLERS);
245
   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
246
 
247
   if (LP_PERF & PERF_NO_TEX) {
248
      lp_build_sample_nop(gallivm, params->type, params->coords, params->texel);
249
      return;
250
   }
251
 
252
   lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
253
                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
254
                       &sampler->dynamic_state.base,
255
                       gallivm, params);
256
}
257
 
258
/**
259
 * Fetch the texture size.
260
 */
261
static void
262
lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
263
                                    struct gallivm_state *gallivm,
264
                                    struct lp_type type,
265
                                    unsigned texture_unit,
266
                                    unsigned target,
267
                                    LLVMValueRef context_ptr,
268
                                    boolean is_sviewinfo,
269
                                    enum lp_sampler_lod_property lod_property,
270
                                    LLVMValueRef explicit_lod, /* optional */
271
                                    LLVMValueRef *sizes_out)
272
{
273
   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
274
 
275
   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
276
 
277
   lp_build_size_query_soa(gallivm,
278
                           &sampler->dynamic_state.static_state[texture_unit].texture_state,
279
                           &sampler->dynamic_state.base,
280
                           type,
281
                           texture_unit,
282
                           target,
283
                           context_ptr,
284
                           is_sviewinfo,
285
                           lod_property,
286
                           explicit_lod,
287
                           sizes_out);
288
}
289
 
290
 
291
struct lp_build_sampler_soa *
292
lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state)
293
{
294
   struct lp_llvm_sampler_soa *sampler;
295
 
296
   sampler = CALLOC_STRUCT(lp_llvm_sampler_soa);
297
   if(!sampler)
298
      return NULL;
299
 
300
   sampler->base.destroy = lp_llvm_sampler_soa_destroy;
301
   sampler->base.emit_tex_sample = lp_llvm_sampler_soa_emit_fetch_texel;
302
   sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query;
303
   sampler->dynamic_state.base.width = lp_llvm_texture_width;
304
   sampler->dynamic_state.base.height = lp_llvm_texture_height;
305
   sampler->dynamic_state.base.depth = lp_llvm_texture_depth;
306
   sampler->dynamic_state.base.first_level = lp_llvm_texture_first_level;
307
   sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level;
308
   sampler->dynamic_state.base.base_ptr = lp_llvm_texture_base_ptr;
309
   sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride;
310
   sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride;
311
   sampler->dynamic_state.base.mip_offsets = lp_llvm_texture_mip_offsets;
312
   sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod;
313
   sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod;
314
   sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias;
315
   sampler->dynamic_state.base.border_color = lp_llvm_sampler_border_color;
316
 
317
   sampler->dynamic_state.static_state = static_state;
318
 
319
   return &sampler->base;
320
}
321