1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc.
4bf215546Sopenharmony_ci * All rights reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/**
29bf215546Sopenharmony_ci * Texture sampling code generation
30bf215546Sopenharmony_ci *
31bf215546Sopenharmony_ci * This file is nothing more than ugly glue between three largely independent
32bf215546Sopenharmony_ci * entities:
33bf215546Sopenharmony_ci * - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa)
34bf215546Sopenharmony_ci * - texture sampling code generation (i.e., lp_build_sample_soa)
35bf215546Sopenharmony_ci * - LLVM pipe driver
36bf215546Sopenharmony_ci *
37bf215546Sopenharmony_ci * All interesting code is in the functions mentioned above. There is really
38bf215546Sopenharmony_ci * nothing to see here.
39bf215546Sopenharmony_ci *
40bf215546Sopenharmony_ci * @author Jose Fonseca <jfonseca@vmware.com>
41bf215546Sopenharmony_ci */
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#include "pipe/p_defines.h"
44bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
45bf215546Sopenharmony_ci#include "gallivm/lp_bld_debug.h"
46bf215546Sopenharmony_ci#include "gallivm/lp_bld_const.h"
47bf215546Sopenharmony_ci#include "gallivm/lp_bld_type.h"
48bf215546Sopenharmony_ci#include "gallivm/lp_bld_sample.h"
49bf215546Sopenharmony_ci#include "gallivm/lp_bld_tgsi.h"
50bf215546Sopenharmony_ci#include "lp_jit.h"
51bf215546Sopenharmony_ci#include "lp_tex_sample.h"
52bf215546Sopenharmony_ci#include "lp_state_fs.h"
53bf215546Sopenharmony_ci#include "lp_debug.h"
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci/**
57bf215546Sopenharmony_ci * This provides the bridge between the sampler state store in
58bf215546Sopenharmony_ci * lp_jit_context and lp_jit_texture and the sampler code
59bf215546Sopenharmony_ci * generator. It provides the texture layout information required by
60bf215546Sopenharmony_ci * the texture sampler code generator in terms of the state stored in
61bf215546Sopenharmony_ci * lp_jit_context and lp_jit_texture in runtime.
62bf215546Sopenharmony_ci */
63bf215546Sopenharmony_cistruct llvmpipe_sampler_dynamic_state
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci   struct lp_sampler_dynamic_state base;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   const struct lp_sampler_static_state *static_state;
68bf215546Sopenharmony_ci};
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci/**
72bf215546Sopenharmony_ci * This is the bridge between our sampler and the TGSI translator.
73bf215546Sopenharmony_ci */
74bf215546Sopenharmony_cistruct lp_llvm_sampler_soa
75bf215546Sopenharmony_ci{
76bf215546Sopenharmony_ci   struct lp_build_sampler_soa base;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   struct llvmpipe_sampler_dynamic_state dynamic_state;
79bf215546Sopenharmony_ci   unsigned nr_samplers;
80bf215546Sopenharmony_ci};
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_cistruct llvmpipe_image_dynamic_state
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci   struct lp_sampler_dynamic_state base;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   const struct lp_image_static_state *static_state;
88bf215546Sopenharmony_ci};
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci/**
92bf215546Sopenharmony_ci * This is the bridge between our images and the TGSI translator.
93bf215546Sopenharmony_ci */
94bf215546Sopenharmony_cistruct lp_llvm_image_soa
95bf215546Sopenharmony_ci{
96bf215546Sopenharmony_ci   struct lp_build_image_soa base;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   struct llvmpipe_image_dynamic_state dynamic_state;
99bf215546Sopenharmony_ci   unsigned nr_images;
100bf215546Sopenharmony_ci};
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci/**
104bf215546Sopenharmony_ci * Fetch the specified member of the lp_jit_texture structure.
105bf215546Sopenharmony_ci * \param emit_load  if TRUE, emit the LLVM load instruction to actually
106bf215546Sopenharmony_ci *                   fetch the field's value.  Otherwise, just emit the
107bf215546Sopenharmony_ci *                   GEP code to address the field.
108bf215546Sopenharmony_ci *
109bf215546Sopenharmony_ci * @sa http://llvm.org/docs/GetElementPtr.html
110bf215546Sopenharmony_ci */
111bf215546Sopenharmony_cistatic LLVMValueRef
112bf215546Sopenharmony_cilp_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
113bf215546Sopenharmony_ci                       struct gallivm_state *gallivm,
114bf215546Sopenharmony_ci                       LLVMValueRef context_ptr,
115bf215546Sopenharmony_ci                       unsigned texture_unit,
116bf215546Sopenharmony_ci                       LLVMValueRef texture_unit_offset,
117bf215546Sopenharmony_ci                       unsigned member_index,
118bf215546Sopenharmony_ci                       const char *member_name,
119bf215546Sopenharmony_ci                       boolean emit_load)
120bf215546Sopenharmony_ci{
121bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
122bf215546Sopenharmony_ci   LLVMValueRef indices[4];
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   /* context[0] */
127bf215546Sopenharmony_ci   indices[0] = lp_build_const_int32(gallivm, 0);
128bf215546Sopenharmony_ci   /* context[0].textures */
129bf215546Sopenharmony_ci   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_TEXTURES);
130bf215546Sopenharmony_ci   /* context[0].textures[unit] */
131bf215546Sopenharmony_ci   indices[2] = lp_build_const_int32(gallivm, texture_unit);
132bf215546Sopenharmony_ci   if (texture_unit_offset) {
133bf215546Sopenharmony_ci      indices[2] = LLVMBuildAdd(gallivm->builder, indices[2],
134bf215546Sopenharmony_ci                                texture_unit_offset, "");
135bf215546Sopenharmony_ci      LLVMValueRef cond =
136bf215546Sopenharmony_ci         LLVMBuildICmp(gallivm->builder, LLVMIntULT,
137bf215546Sopenharmony_ci                       indices[2],
138bf215546Sopenharmony_ci                       lp_build_const_int32(gallivm,
139bf215546Sopenharmony_ci                                            PIPE_MAX_SHADER_SAMPLER_VIEWS), "");
140bf215546Sopenharmony_ci      indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2],
141bf215546Sopenharmony_ci                                   lp_build_const_int32(gallivm,
142bf215546Sopenharmony_ci                                                        texture_unit), "");
143bf215546Sopenharmony_ci   }
144bf215546Sopenharmony_ci   /* context[0].textures[unit].member */
145bf215546Sopenharmony_ci   indices[3] = lp_build_const_int32(gallivm, member_index);
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   LLVMValueRef ptr =
148bf215546Sopenharmony_ci      LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   LLVMValueRef res = emit_load ? LLVMBuildLoad(builder, ptr, "") : ptr;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   return res;
155bf215546Sopenharmony_ci}
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci/**
159bf215546Sopenharmony_ci * Helper macro to instantiate the functions that generate the code to
160bf215546Sopenharmony_ci * fetch the members of lp_jit_texture to fulfill the sampler code
161bf215546Sopenharmony_ci * generator requests.
162bf215546Sopenharmony_ci *
163bf215546Sopenharmony_ci * This complexity is the price we have to pay to keep the texture
164bf215546Sopenharmony_ci * sampler code generator a reusable module without dependencies to
165bf215546Sopenharmony_ci * llvmpipe internals.
166bf215546Sopenharmony_ci */
167bf215546Sopenharmony_ci#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load)  \
168bf215546Sopenharmony_ci   static LLVMValueRef \
169bf215546Sopenharmony_ci   lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
170bf215546Sopenharmony_ci                            struct gallivm_state *gallivm, \
171bf215546Sopenharmony_ci                            LLVMValueRef context_ptr, \
172bf215546Sopenharmony_ci                            unsigned texture_unit,    \
173bf215546Sopenharmony_ci                            LLVMValueRef texture_unit_offset) \
174bf215546Sopenharmony_ci   { \
175bf215546Sopenharmony_ci      return lp_llvm_texture_member(base, gallivm, context_ptr, \
176bf215546Sopenharmony_ci                                    texture_unit, texture_unit_offset,  \
177bf215546Sopenharmony_ci                                    _index, #_name, _emit_load );       \
178bf215546Sopenharmony_ci   }
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(width,      LP_JIT_TEXTURE_WIDTH, TRUE)
182bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(height,     LP_JIT_TEXTURE_HEIGHT, TRUE)
183bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(depth,      LP_JIT_TEXTURE_DEPTH, TRUE)
184bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(first_level, LP_JIT_TEXTURE_FIRST_LEVEL, TRUE)
185bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE)
186bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(base_ptr,   LP_JIT_TEXTURE_BASE, TRUE)
187bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE)
188bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE)
189bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE)
190bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(num_samples, LP_JIT_TEXTURE_NUM_SAMPLES, TRUE)
191bf215546Sopenharmony_ciLP_LLVM_TEXTURE_MEMBER(sample_stride, LP_JIT_TEXTURE_SAMPLE_STRIDE, TRUE)
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci/**
195bf215546Sopenharmony_ci * Fetch the specified member of the lp_jit_sampler structure.
196bf215546Sopenharmony_ci * \param emit_load  if TRUE, emit the LLVM load instruction to actually
197bf215546Sopenharmony_ci *                   fetch the field's value.  Otherwise, just emit the
198bf215546Sopenharmony_ci *                   GEP code to address the field.
199bf215546Sopenharmony_ci *
200bf215546Sopenharmony_ci * @sa http://llvm.org/docs/GetElementPtr.html
201bf215546Sopenharmony_ci */
202bf215546Sopenharmony_cistatic LLVMValueRef
203bf215546Sopenharmony_cilp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
204bf215546Sopenharmony_ci                       struct gallivm_state *gallivm,
205bf215546Sopenharmony_ci                       LLVMValueRef context_ptr,
206bf215546Sopenharmony_ci                       unsigned sampler_unit,
207bf215546Sopenharmony_ci                       unsigned member_index,
208bf215546Sopenharmony_ci                       const char *member_name,
209bf215546Sopenharmony_ci                       boolean emit_load)
210bf215546Sopenharmony_ci{
211bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
212bf215546Sopenharmony_ci   LLVMValueRef indices[4];
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   assert(sampler_unit < PIPE_MAX_SAMPLERS);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   /* context[0] */
217bf215546Sopenharmony_ci   indices[0] = lp_build_const_int32(gallivm, 0);
218bf215546Sopenharmony_ci   /* context[0].samplers */
219bf215546Sopenharmony_ci   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS);
220bf215546Sopenharmony_ci   /* context[0].samplers[unit] */
221bf215546Sopenharmony_ci   indices[2] = lp_build_const_int32(gallivm, sampler_unit);
222bf215546Sopenharmony_ci   /* context[0].samplers[unit].member */
223bf215546Sopenharmony_ci   indices[3] = lp_build_const_int32(gallivm, member_index);
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   LLVMValueRef ptr =
226bf215546Sopenharmony_ci      LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   LLVMValueRef res = emit_load ? LLVMBuildLoad(builder, ptr, "") : ptr;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   return res;
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load)  \
237bf215546Sopenharmony_ci   static LLVMValueRef \
238bf215546Sopenharmony_ci   lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
239bf215546Sopenharmony_ci                            struct gallivm_state *gallivm, \
240bf215546Sopenharmony_ci                            LLVMValueRef context_ptr, \
241bf215546Sopenharmony_ci                            unsigned sampler_unit) \
242bf215546Sopenharmony_ci   { \
243bf215546Sopenharmony_ci      return lp_llvm_sampler_member(base, gallivm, context_ptr, \
244bf215546Sopenharmony_ci                                    sampler_unit, _index, #_name, _emit_load ); \
245bf215546Sopenharmony_ci   }
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ciLP_LLVM_SAMPLER_MEMBER(min_lod,    LP_JIT_SAMPLER_MIN_LOD, TRUE)
249bf215546Sopenharmony_ciLP_LLVM_SAMPLER_MEMBER(max_lod,    LP_JIT_SAMPLER_MAX_LOD, TRUE)
250bf215546Sopenharmony_ciLP_LLVM_SAMPLER_MEMBER(lod_bias,   LP_JIT_SAMPLER_LOD_BIAS, TRUE)
251bf215546Sopenharmony_ciLP_LLVM_SAMPLER_MEMBER(border_color, LP_JIT_SAMPLER_BORDER_COLOR, FALSE)
252bf215546Sopenharmony_ciLP_LLVM_SAMPLER_MEMBER(max_aniso, LP_JIT_SAMPLER_MAX_ANISO, TRUE)
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci/**
256bf215546Sopenharmony_ci * Fetch the specified member of the lp_jit_image structure.
257bf215546Sopenharmony_ci * \param emit_load  if TRUE, emit the LLVM load instruction to actually
258bf215546Sopenharmony_ci *                   fetch the field's value.  Otherwise, just emit the
259bf215546Sopenharmony_ci *                   GEP code to address the field.
260bf215546Sopenharmony_ci *
261bf215546Sopenharmony_ci * @sa http://llvm.org/docs/GetElementPtr.html
262bf215546Sopenharmony_ci */
263bf215546Sopenharmony_cistatic LLVMValueRef
264bf215546Sopenharmony_cilp_llvm_image_member(const struct lp_sampler_dynamic_state *base,
265bf215546Sopenharmony_ci                     struct gallivm_state *gallivm,
266bf215546Sopenharmony_ci                     LLVMValueRef context_ptr,
267bf215546Sopenharmony_ci                     unsigned image_unit,
268bf215546Sopenharmony_ci                     LLVMValueRef image_unit_offset,
269bf215546Sopenharmony_ci                     unsigned member_index,
270bf215546Sopenharmony_ci                     const char *member_name,
271bf215546Sopenharmony_ci                     boolean emit_load)
272bf215546Sopenharmony_ci{
273bf215546Sopenharmony_ci   LLVMBuilderRef builder = gallivm->builder;
274bf215546Sopenharmony_ci   LLVMValueRef indices[4];
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci   assert(image_unit < PIPE_MAX_SHADER_IMAGES);
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   /* context[0] */
279bf215546Sopenharmony_ci   indices[0] = lp_build_const_int32(gallivm, 0);
280bf215546Sopenharmony_ci   /* context[0].images */
281bf215546Sopenharmony_ci   indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_IMAGES);
282bf215546Sopenharmony_ci   /* context[0].images[unit] */
283bf215546Sopenharmony_ci   indices[2] = lp_build_const_int32(gallivm, image_unit);
284bf215546Sopenharmony_ci   if (image_unit_offset) {
285bf215546Sopenharmony_ci      indices[2] = LLVMBuildAdd(gallivm->builder, indices[2], image_unit_offset, "");
286bf215546Sopenharmony_ci      LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, LLVMIntULT, indices[2], lp_build_const_int32(gallivm, PIPE_MAX_SHADER_IMAGES), "");
287bf215546Sopenharmony_ci      indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2], lp_build_const_int32(gallivm, image_unit), "");
288bf215546Sopenharmony_ci   }
289bf215546Sopenharmony_ci   /* context[0].images[unit].member */
290bf215546Sopenharmony_ci   indices[3] = lp_build_const_int32(gallivm, member_index);
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   LLVMValueRef ptr =
293bf215546Sopenharmony_ci      LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci   LLVMValueRef res = emit_load ? LLVMBuildLoad(builder, ptr, "") : ptr;
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci   lp_build_name(res, "context.image%u.%s", image_unit, member_name);
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   return res;
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci/**
304bf215546Sopenharmony_ci * Helper macro to instantiate the functions that generate the code to
305bf215546Sopenharmony_ci * fetch the members of lp_jit_image to fulfill the sampler code
306bf215546Sopenharmony_ci * generator requests.
307bf215546Sopenharmony_ci *
308bf215546Sopenharmony_ci * This complexity is the price we have to pay to keep the image
309bf215546Sopenharmony_ci * sampler code generator a reusable module without dependencies to
310bf215546Sopenharmony_ci * llvmpipe internals.
311bf215546Sopenharmony_ci */
312bf215546Sopenharmony_ci#define LP_LLVM_IMAGE_MEMBER(_name, _index, _emit_load)  \
313bf215546Sopenharmony_ci   static LLVMValueRef \
314bf215546Sopenharmony_ci   lp_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \
315bf215546Sopenharmony_ci                          struct gallivm_state *gallivm,               \
316bf215546Sopenharmony_ci                          LLVMValueRef context_ptr,                     \
317bf215546Sopenharmony_ci                          unsigned image_unit, LLVMValueRef image_unit_offset) \
318bf215546Sopenharmony_ci   { \
319bf215546Sopenharmony_ci      return lp_llvm_image_member(base, gallivm, context_ptr, \
320bf215546Sopenharmony_ci                                  image_unit, image_unit_offset, \
321bf215546Sopenharmony_ci                                  _index, #_name, _emit_load );  \
322bf215546Sopenharmony_ci   }
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(width,      LP_JIT_IMAGE_WIDTH, TRUE)
326bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(height,     LP_JIT_IMAGE_HEIGHT, TRUE)
327bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(depth,      LP_JIT_IMAGE_DEPTH, TRUE)
328bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(base_ptr,   LP_JIT_IMAGE_BASE, TRUE)
329bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(row_stride, LP_JIT_IMAGE_ROW_STRIDE, TRUE)
330bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(img_stride, LP_JIT_IMAGE_IMG_STRIDE, TRUE)
331bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(num_samples, LP_JIT_IMAGE_NUM_SAMPLES, TRUE)
332bf215546Sopenharmony_ciLP_LLVM_IMAGE_MEMBER(sample_stride, LP_JIT_IMAGE_SAMPLE_STRIDE, TRUE)
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci#if LP_USE_TEXTURE_CACHE
336bf215546Sopenharmony_cistatic LLVMValueRef
337bf215546Sopenharmony_cilp_llvm_texture_cache_ptr(const struct lp_sampler_dynamic_state *base,
338bf215546Sopenharmony_ci                          struct gallivm_state *gallivm,
339bf215546Sopenharmony_ci                          LLVMValueRef thread_data_ptr,
340bf215546Sopenharmony_ci                          unsigned unit)
341bf215546Sopenharmony_ci{
342bf215546Sopenharmony_ci   /* We use the same cache for all units */
343bf215546Sopenharmony_ci   (void)unit;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   return lp_jit_thread_data_cache(gallivm, thread_data_ptr);
346bf215546Sopenharmony_ci}
347bf215546Sopenharmony_ci#endif
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_cistatic void
351bf215546Sopenharmony_cilp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   FREE(sampler);
354bf215546Sopenharmony_ci}
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci/**
358bf215546Sopenharmony_ci * Fetch filtered values from texture.
359bf215546Sopenharmony_ci * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
360bf215546Sopenharmony_ci */
361bf215546Sopenharmony_cistatic void
362bf215546Sopenharmony_cilp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
363bf215546Sopenharmony_ci                                     struct gallivm_state *gallivm,
364bf215546Sopenharmony_ci                                     const struct lp_sampler_params *params)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
367bf215546Sopenharmony_ci   const unsigned texture_index = params->texture_index;
368bf215546Sopenharmony_ci   const unsigned sampler_index = params->sampler_index;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   assert(sampler_index < PIPE_MAX_SAMPLERS);
371bf215546Sopenharmony_ci   assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci   if (LP_PERF & PERF_NO_TEX) {
374bf215546Sopenharmony_ci      lp_build_sample_nop(gallivm, params->type, params->coords, params->texel);
375bf215546Sopenharmony_ci      return;
376bf215546Sopenharmony_ci   }
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   if (params->texture_index_offset) {
379bf215546Sopenharmony_ci      LLVMValueRef unit =
380bf215546Sopenharmony_ci         LLVMBuildAdd(gallivm->builder, params->texture_index_offset,
381bf215546Sopenharmony_ci                      lp_build_const_int32(gallivm, texture_index), "");
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci      struct lp_build_sample_array_switch switch_info;
384bf215546Sopenharmony_ci      memset(&switch_info, 0, sizeof(switch_info));
385bf215546Sopenharmony_ci      lp_build_sample_array_init_soa(&switch_info, gallivm, params, unit,
386bf215546Sopenharmony_ci                                     0, sampler->nr_samplers);
387bf215546Sopenharmony_ci      // build the switch cases
388bf215546Sopenharmony_ci      for (unsigned i = 0; i < sampler->nr_samplers; i++) {
389bf215546Sopenharmony_ci         lp_build_sample_array_case_soa(&switch_info, i,
390bf215546Sopenharmony_ci                                        &sampler->dynamic_state.static_state[i].texture_state,
391bf215546Sopenharmony_ci                                        &sampler->dynamic_state.static_state[i].sampler_state,
392bf215546Sopenharmony_ci                                        &sampler->dynamic_state.base);
393bf215546Sopenharmony_ci      }
394bf215546Sopenharmony_ci      lp_build_sample_array_fini_soa(&switch_info);
395bf215546Sopenharmony_ci   } else {
396bf215546Sopenharmony_ci      lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
397bf215546Sopenharmony_ci                          &sampler->dynamic_state.static_state[sampler_index].sampler_state,
398bf215546Sopenharmony_ci                          &sampler->dynamic_state.base,
399bf215546Sopenharmony_ci                          gallivm, params);
400bf215546Sopenharmony_ci   }
401bf215546Sopenharmony_ci}
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci/**
405bf215546Sopenharmony_ci * Fetch the texture size.
406bf215546Sopenharmony_ci */
407bf215546Sopenharmony_cistatic void
408bf215546Sopenharmony_cilp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
409bf215546Sopenharmony_ci                                    struct gallivm_state *gallivm,
410bf215546Sopenharmony_ci                                    const struct lp_sampler_size_query_params *params)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   lp_build_size_query_soa(gallivm,
417bf215546Sopenharmony_ci                           &sampler->dynamic_state.static_state[params->texture_unit].texture_state,
418bf215546Sopenharmony_ci                           &sampler->dynamic_state.base,
419bf215546Sopenharmony_ci                           params);
420bf215546Sopenharmony_ci}
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_cistruct lp_build_sampler_soa *
424bf215546Sopenharmony_cilp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
425bf215546Sopenharmony_ci                           unsigned nr_samplers)
426bf215546Sopenharmony_ci{
427bf215546Sopenharmony_ci   assert(static_state);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   struct lp_llvm_sampler_soa *sampler = CALLOC_STRUCT(lp_llvm_sampler_soa);
430bf215546Sopenharmony_ci   if (!sampler)
431bf215546Sopenharmony_ci      return NULL;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   sampler->base.destroy = lp_llvm_sampler_soa_destroy;
434bf215546Sopenharmony_ci   sampler->base.emit_tex_sample = lp_llvm_sampler_soa_emit_fetch_texel;
435bf215546Sopenharmony_ci   sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query;
436bf215546Sopenharmony_ci   sampler->dynamic_state.base.width = lp_llvm_texture_width;
437bf215546Sopenharmony_ci   sampler->dynamic_state.base.height = lp_llvm_texture_height;
438bf215546Sopenharmony_ci   sampler->dynamic_state.base.depth = lp_llvm_texture_depth;
439bf215546Sopenharmony_ci   sampler->dynamic_state.base.first_level = lp_llvm_texture_first_level;
440bf215546Sopenharmony_ci   sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level;
441bf215546Sopenharmony_ci   sampler->dynamic_state.base.base_ptr = lp_llvm_texture_base_ptr;
442bf215546Sopenharmony_ci   sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride;
443bf215546Sopenharmony_ci   sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride;
444bf215546Sopenharmony_ci   sampler->dynamic_state.base.mip_offsets = lp_llvm_texture_mip_offsets;
445bf215546Sopenharmony_ci   sampler->dynamic_state.base.num_samples = lp_llvm_texture_num_samples;
446bf215546Sopenharmony_ci   sampler->dynamic_state.base.sample_stride = lp_llvm_texture_sample_stride;
447bf215546Sopenharmony_ci   sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod;
448bf215546Sopenharmony_ci   sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod;
449bf215546Sopenharmony_ci   sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias;
450bf215546Sopenharmony_ci   sampler->dynamic_state.base.border_color = lp_llvm_sampler_border_color;
451bf215546Sopenharmony_ci   sampler->dynamic_state.base.max_aniso = lp_llvm_sampler_max_aniso;
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci#if LP_USE_TEXTURE_CACHE
454bf215546Sopenharmony_ci   sampler->dynamic_state.base.cache_ptr = lp_llvm_texture_cache_ptr;
455bf215546Sopenharmony_ci#endif
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   sampler->dynamic_state.static_state = static_state;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   sampler->nr_samplers = nr_samplers;
460bf215546Sopenharmony_ci   return &sampler->base;
461bf215546Sopenharmony_ci}
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_cistatic void
465bf215546Sopenharmony_cilp_llvm_image_soa_destroy(struct lp_build_image_soa *image)
466bf215546Sopenharmony_ci{
467bf215546Sopenharmony_ci   FREE(image);
468bf215546Sopenharmony_ci}
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_cistatic void
472bf215546Sopenharmony_cilp_llvm_image_soa_emit_op(const struct lp_build_image_soa *base,
473bf215546Sopenharmony_ci                             struct gallivm_state *gallivm,
474bf215546Sopenharmony_ci                             const struct lp_img_params *params)
475bf215546Sopenharmony_ci{
476bf215546Sopenharmony_ci   struct lp_llvm_image_soa *image = (struct lp_llvm_image_soa *)base;
477bf215546Sopenharmony_ci   const unsigned image_index = params->image_index;
478bf215546Sopenharmony_ci   assert(image_index < PIPE_MAX_SHADER_IMAGES);
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   if (params->image_index_offset) {
481bf215546Sopenharmony_ci      struct lp_build_img_op_array_switch switch_info;
482bf215546Sopenharmony_ci      memset(&switch_info, 0, sizeof(switch_info));
483bf215546Sopenharmony_ci      LLVMValueRef unit = LLVMBuildAdd(gallivm->builder,
484bf215546Sopenharmony_ci                                       params->image_index_offset,
485bf215546Sopenharmony_ci                                       lp_build_const_int32(gallivm,
486bf215546Sopenharmony_ci                                                            image_index), "");
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci      lp_build_image_op_switch_soa(&switch_info, gallivm, params,
489bf215546Sopenharmony_ci                                   unit, 0, image->nr_images);
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci      for (unsigned i = 0; i < image->nr_images; i++) {
492bf215546Sopenharmony_ci         lp_build_image_op_array_case(&switch_info, i,
493bf215546Sopenharmony_ci                                      &image->dynamic_state.static_state[i].image_state,
494bf215546Sopenharmony_ci                                      &image->dynamic_state.base);
495bf215546Sopenharmony_ci      }
496bf215546Sopenharmony_ci      lp_build_image_op_array_fini_soa(&switch_info);
497bf215546Sopenharmony_ci   } else {
498bf215546Sopenharmony_ci      lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state,
499bf215546Sopenharmony_ci                          &image->dynamic_state.base,
500bf215546Sopenharmony_ci                          gallivm, params, params->outdata);
501bf215546Sopenharmony_ci   }
502bf215546Sopenharmony_ci}
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci
505bf215546Sopenharmony_ci/**
506bf215546Sopenharmony_ci * Fetch the texture size.
507bf215546Sopenharmony_ci */
508bf215546Sopenharmony_cistatic void
509bf215546Sopenharmony_cilp_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base,
510bf215546Sopenharmony_ci                                  struct gallivm_state *gallivm,
511bf215546Sopenharmony_ci                                  const struct lp_sampler_size_query_params *params)
512bf215546Sopenharmony_ci{
513bf215546Sopenharmony_ci   struct lp_llvm_image_soa *image = (struct lp_llvm_image_soa *)base;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES);
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci   lp_build_size_query_soa(gallivm,
518bf215546Sopenharmony_ci                           &image->dynamic_state.static_state[params->texture_unit].image_state,
519bf215546Sopenharmony_ci                           &image->dynamic_state.base,
520bf215546Sopenharmony_ci                           params);
521bf215546Sopenharmony_ci}
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_cistruct lp_build_image_soa *
525bf215546Sopenharmony_cilp_llvm_image_soa_create(const struct lp_image_static_state *static_state,
526bf215546Sopenharmony_ci                         unsigned nr_images)
527bf215546Sopenharmony_ci{
528bf215546Sopenharmony_ci   struct lp_llvm_image_soa *image = CALLOC_STRUCT(lp_llvm_image_soa);
529bf215546Sopenharmony_ci   if (!image)
530bf215546Sopenharmony_ci      return NULL;
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   image->base.destroy = lp_llvm_image_soa_destroy;
533bf215546Sopenharmony_ci   image->base.emit_op = lp_llvm_image_soa_emit_op;
534bf215546Sopenharmony_ci   image->base.emit_size_query = lp_llvm_image_soa_emit_size_query;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   image->dynamic_state.base.width = lp_llvm_image_width;
537bf215546Sopenharmony_ci   image->dynamic_state.base.height = lp_llvm_image_height;
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   image->dynamic_state.base.depth = lp_llvm_image_depth;
540bf215546Sopenharmony_ci   image->dynamic_state.base.base_ptr = lp_llvm_image_base_ptr;
541bf215546Sopenharmony_ci   image->dynamic_state.base.row_stride = lp_llvm_image_row_stride;
542bf215546Sopenharmony_ci   image->dynamic_state.base.img_stride = lp_llvm_image_img_stride;
543bf215546Sopenharmony_ci   image->dynamic_state.base.num_samples = lp_llvm_image_num_samples;
544bf215546Sopenharmony_ci   image->dynamic_state.base.sample_stride = lp_llvm_image_sample_stride;
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   image->dynamic_state.static_state = static_state;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   image->nr_images = nr_images;
549bf215546Sopenharmony_ci   return &image->base;
550bf215546Sopenharmony_ci}
551