Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 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 
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
 */
57
struct 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
   LLVMValueRef context_ptr;
64
};
65
 
66
 
67
/**
68
 * This is the bridge between our sampler and the TGSI translator.
69
 */
70
struct draw_llvm_sampler_soa
71
{
72
   struct lp_build_sampler_soa base;
73
 
74
   struct draw_llvm_sampler_dynamic_state dynamic_state;
75
};
76
 
77
 
78
/**
79
 * Fetch the specified member of the lp_jit_texture structure.
80
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
81
 *                   fetch the field's value.  Otherwise, just emit the
82
 *                   GEP code to address the field.
83
 *
84
 * @sa http://llvm.org/docs/GetElementPtr.html
85
 */
86
static LLVMValueRef
87
draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
88
                         struct gallivm_state *gallivm,
89
                         unsigned texture_unit,
90
                         unsigned member_index,
91
                         const char *member_name,
92
                         boolean emit_load)
93
{
94
   LLVMBuilderRef builder = gallivm->builder;
95
   struct draw_llvm_sampler_dynamic_state *state =
96
      (struct draw_llvm_sampler_dynamic_state *)base;
97
   LLVMValueRef indices[4];
98
   LLVMValueRef ptr;
99
   LLVMValueRef res;
100
 
101
   debug_assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
102
 
103
   /* context[0] */
104
   indices[0] = lp_build_const_int32(gallivm, 0);
105
   /* context[0].textures */
106
   indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_TEXTURES);
107
   /* context[0].textures[unit] */
108
   indices[2] = lp_build_const_int32(gallivm, texture_unit);
109
   /* context[0].textures[unit].member */
110
   indices[3] = lp_build_const_int32(gallivm, member_index);
111
 
112
   ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
113
 
114
   if (emit_load)
115
      res = LLVMBuildLoad(builder, ptr, "");
116
   else
117
      res = ptr;
118
 
119
   lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
120
 
121
   return res;
122
}
123
 
124
 
125
/**
126
 * Fetch the specified member of the lp_jit_sampler structure.
127
 * \param emit_load  if TRUE, emit the LLVM load instruction to actually
128
 *                   fetch the field's value.  Otherwise, just emit the
129
 *                   GEP code to address the field.
130
 *
131
 * @sa http://llvm.org/docs/GetElementPtr.html
132
 */
133
static LLVMValueRef
134
draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
135
                         struct gallivm_state *gallivm,
136
                         unsigned sampler_unit,
137
                         unsigned member_index,
138
                         const char *member_name,
139
                         boolean emit_load)
140
{
141
   LLVMBuilderRef builder = gallivm->builder;
142
   struct draw_llvm_sampler_dynamic_state *state =
143
      (struct draw_llvm_sampler_dynamic_state *)base;
144
   LLVMValueRef indices[4];
145
   LLVMValueRef ptr;
146
   LLVMValueRef res;
147
 
148
   debug_assert(sampler_unit < PIPE_MAX_SAMPLERS);
149
 
150
   /* context[0] */
151
   indices[0] = lp_build_const_int32(gallivm, 0);
152
   /* context[0].samplers */
153
   indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS);
154
   /* context[0].samplers[unit] */
155
   indices[2] = lp_build_const_int32(gallivm, sampler_unit);
156
   /* context[0].samplers[unit].member */
157
   indices[3] = lp_build_const_int32(gallivm, member_index);
158
 
159
   ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
160
 
161
   if (emit_load)
162
      res = LLVMBuildLoad(builder, ptr, "");
163
   else
164
      res = ptr;
165
 
166
   lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
167
 
168
   return res;
169
}
170
 
171
 
172
/**
173
 * Helper macro to instantiate the functions that generate the code to
174
 * fetch the members of lp_jit_texture to fulfill the sampler code
175
 * generator requests.
176
 *
177
 * This complexity is the price we have to pay to keep the texture
178
 * sampler code generator a reusable module without dependencies to
179
 * llvmpipe internals.
180
 */
181
#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load)  \
182
   static LLVMValueRef \
183
   draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
184
                              struct gallivm_state *gallivm,               \
185
                              unsigned texture_unit)                       \
186
   { \
187
      return draw_llvm_texture_member(base, gallivm, texture_unit, _index, #_name, _emit_load ); \
188
   }
189
 
190
 
191
DRAW_LLVM_TEXTURE_MEMBER(width,      DRAW_JIT_TEXTURE_WIDTH, TRUE)
192
DRAW_LLVM_TEXTURE_MEMBER(height,     DRAW_JIT_TEXTURE_HEIGHT, TRUE)
193
DRAW_LLVM_TEXTURE_MEMBER(depth,      DRAW_JIT_TEXTURE_DEPTH, TRUE)
194
DRAW_LLVM_TEXTURE_MEMBER(first_level,DRAW_JIT_TEXTURE_FIRST_LEVEL, TRUE)
195
DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)
196
DRAW_LLVM_TEXTURE_MEMBER(base_ptr,   DRAW_JIT_TEXTURE_BASE, TRUE)
197
DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)
198
DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)
199
DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE)
200
 
201
 
202
#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
203
   static LLVMValueRef \
204
   draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
205
                              struct gallivm_state *gallivm,               \
206
                              unsigned sampler_unit)                       \
207
   { \
208
      return draw_llvm_sampler_member(base, gallivm, sampler_unit, _index, #_name, _emit_load ); \
209
   }
210
 
211
 
212
DRAW_LLVM_SAMPLER_MEMBER(min_lod,    DRAW_JIT_SAMPLER_MIN_LOD, TRUE)
213
DRAW_LLVM_SAMPLER_MEMBER(max_lod,    DRAW_JIT_SAMPLER_MAX_LOD, TRUE)
214
DRAW_LLVM_SAMPLER_MEMBER(lod_bias,   DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)
215
DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
216
 
217
 
218
static void
219
draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
220
{
221
   FREE(sampler);
222
}
223
 
224
 
225
/**
226
 * Fetch filtered values from texture.
227
 * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
228
 */
229
static void
230
draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
231
                                       struct gallivm_state *gallivm,
232
                                       struct lp_type type,
233
                                       boolean is_fetch,
234
                                       unsigned texture_index,
235
                                       unsigned sampler_index,
236
                                       const LLVMValueRef *coords,
237
                                       const LLVMValueRef *offsets,
238
                                       const struct lp_derivatives *derivs,
239
                                       LLVMValueRef lod_bias, /* optional */
240
                                       LLVMValueRef explicit_lod, /* optional */
241
                                       boolean scalar_lod,
242
                                       LLVMValueRef *texel)
243
{
244
   struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
245
 
246
   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
247
   assert(sampler_index < PIPE_MAX_SAMPLERS);
248
 
249
   lp_build_sample_soa(gallivm,
250
                       &sampler->dynamic_state.static_state[texture_index].texture_state,
251
                       &sampler->dynamic_state.static_state[sampler_index].sampler_state,
252
                       &sampler->dynamic_state.base,
253
                       type,
254
                       is_fetch,
255
                       texture_index,
256
                       sampler_index,
257
                       coords,
258
                       offsets,
259
                       derivs,
260
                       lod_bias, explicit_lod, scalar_lod,
261
                       texel);
262
}
263
 
264
 
265
/**
266
 * Fetch the texture size.
267
 */
268
static void
269
draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
270
                                      struct gallivm_state *gallivm,
271
                                      struct lp_type type,
272
                                      unsigned texture_unit,
273
                                      boolean need_nr_mips,
274
                                      LLVMValueRef explicit_lod, /* optional */
275
                                      LLVMValueRef *sizes_out)
276
{
277
   struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
278
 
279
   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
280
 
281
   lp_build_size_query_soa(gallivm,
282
                           &sampler->dynamic_state.static_state[texture_unit].texture_state,
283
                           &sampler->dynamic_state.base,
284
                           type,
285
                           texture_unit,
286
                           need_nr_mips,
287
                           explicit_lod,
288
                           sizes_out);
289
}
290
 
291
struct lp_build_sampler_soa *
292
draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
293
                             LLVMValueRef context_ptr)
294
{
295
   struct draw_llvm_sampler_soa *sampler;
296
 
297
   sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);
298
   if(!sampler)
299
      return NULL;
300
 
301
   sampler->base.destroy = draw_llvm_sampler_soa_destroy;
302
   sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
303
   sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;
304
   sampler->dynamic_state.base.width = draw_llvm_texture_width;
305
   sampler->dynamic_state.base.height = draw_llvm_texture_height;
306
   sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
307
   sampler->dynamic_state.base.first_level = draw_llvm_texture_first_level;
308
   sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;
309
   sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;
310
   sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
311
   sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr;
312
   sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets;
313
   sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;
314
   sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;
315
   sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;
316
   sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;
317
   sampler->dynamic_state.static_state = static_state;
318
   sampler->dynamic_state.context_ptr = context_ptr;
319
 
320
   return &sampler->base;
321
}
322