Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 <jfonseca@vmware.com>
  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.  
  323.