Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_llvm_sample.c
4565 views
/**************************************************************************1*2* Copyright 2010 VMware, Inc.3* All rights reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* Texture sampling code generation29* @author Jose Fonseca <[email protected]>30*/3132#include "pipe/p_defines.h"33#include "pipe/p_shader_tokens.h"34#include "gallivm/lp_bld_const.h"35#include "gallivm/lp_bld_debug.h"36#include "gallivm/lp_bld_type.h"37#include "gallivm/lp_bld_sample.h"38#include "gallivm/lp_bld_tgsi.h"394041#include "util/u_debug.h"42#include "util/u_memory.h"43#include "util/u_pointer.h"44#include "util/u_string.h"4546#include "draw_llvm.h"474849/**50* This provides the bridge between the sampler state store in51* lp_jit_context and lp_jit_texture and the sampler code52* generator. It provides the texture layout information required by53* the texture sampler code generator in terms of the state stored in54* lp_jit_context and lp_jit_texture in runtime.55*/56struct draw_llvm_sampler_dynamic_state57{58struct lp_sampler_dynamic_state base;5960const struct draw_sampler_static_state *static_state;61};626364/**65* This is the bridge between our sampler and the TGSI translator.66*/67struct draw_llvm_sampler_soa68{69struct lp_build_sampler_soa base;7071struct draw_llvm_sampler_dynamic_state dynamic_state;7273unsigned nr_samplers;74};7576struct draw_llvm_image_dynamic_state77{78struct lp_sampler_dynamic_state base;7980const struct draw_image_static_state *static_state;81};8283struct draw_llvm_image_soa84{85struct lp_build_image_soa base;8687struct draw_llvm_image_dynamic_state dynamic_state;8889unsigned nr_images;90};9192/**93* Fetch the specified member of the lp_jit_texture structure.94* \param emit_load if TRUE, emit the LLVM load instruction to actually95* fetch the field's value. Otherwise, just emit the96* GEP code to address the field.97*98* @sa http://llvm.org/docs/GetElementPtr.html99*/100static LLVMValueRef101draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,102struct gallivm_state *gallivm,103LLVMValueRef context_ptr,104unsigned texture_unit,105LLVMValueRef texture_unit_offset,106unsigned member_index,107const char *member_name,108boolean emit_load)109{110LLVMBuilderRef builder = gallivm->builder;111LLVMValueRef indices[4];112LLVMValueRef ptr;113LLVMValueRef res;114115debug_assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);116117/* context[0] */118indices[0] = lp_build_const_int32(gallivm, 0);119/* context[0].textures */120indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_TEXTURES);121/* context[0].textures[unit] */122indices[2] = lp_build_const_int32(gallivm, texture_unit);123if (texture_unit_offset) {124indices[2] = LLVMBuildAdd(gallivm->builder, indices[2], texture_unit_offset, "");125LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, LLVMIntULT, indices[2], lp_build_const_int32(gallivm, PIPE_MAX_SHADER_SAMPLER_VIEWS), "");126indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2], lp_build_const_int32(gallivm, texture_unit), "");127}128/* context[0].textures[unit].member */129indices[3] = lp_build_const_int32(gallivm, member_index);130131ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");132133if (emit_load)134res = LLVMBuildLoad(builder, ptr, "");135else136res = ptr;137138lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);139140return res;141}142143144/**145* Fetch the specified member of the lp_jit_sampler structure.146* \param emit_load if TRUE, emit the LLVM load instruction to actually147* fetch the field's value. Otherwise, just emit the148* GEP code to address the field.149*150* @sa http://llvm.org/docs/GetElementPtr.html151*/152static LLVMValueRef153draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,154struct gallivm_state *gallivm,155LLVMValueRef context_ptr,156unsigned sampler_unit,157unsigned member_index,158const char *member_name,159boolean emit_load)160{161LLVMBuilderRef builder = gallivm->builder;162LLVMValueRef indices[4];163LLVMValueRef ptr;164LLVMValueRef res;165166debug_assert(sampler_unit < PIPE_MAX_SAMPLERS);167168/* context[0] */169indices[0] = lp_build_const_int32(gallivm, 0);170/* context[0].samplers */171indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS);172/* context[0].samplers[unit] */173indices[2] = lp_build_const_int32(gallivm, sampler_unit);174/* context[0].samplers[unit].member */175indices[3] = lp_build_const_int32(gallivm, member_index);176177ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");178179if (emit_load)180res = LLVMBuildLoad(builder, ptr, "");181else182res = ptr;183184lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);185186return res;187}188189/**190* Fetch the specified member of the lp_jit_texture structure.191* \param emit_load if TRUE, emit the LLVM load instruction to actually192* fetch the field's value. Otherwise, just emit the193* GEP code to address the field.194*195* @sa http://llvm.org/docs/GetElementPtr.html196*/197static LLVMValueRef198draw_llvm_image_member(const struct lp_sampler_dynamic_state *base,199struct gallivm_state *gallivm,200LLVMValueRef context_ptr,201unsigned image_unit,202LLVMValueRef image_unit_offset,203unsigned member_index,204const char *member_name,205boolean emit_load)206{207LLVMBuilderRef builder = gallivm->builder;208LLVMValueRef indices[4];209LLVMValueRef ptr;210LLVMValueRef res;211212debug_assert(image_unit < PIPE_MAX_SHADER_IMAGES);213214/* context[0] */215indices[0] = lp_build_const_int32(gallivm, 0);216/* context[0].textures */217indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_IMAGES);218/* context[0].textures[unit] */219indices[2] = lp_build_const_int32(gallivm, image_unit);220if (image_unit_offset) {221indices[2] = LLVMBuildAdd(gallivm->builder, indices[2], image_unit_offset, "");222LLVMValueRef cond = LLVMBuildICmp(gallivm->builder, LLVMIntULT, indices[2], lp_build_const_int32(gallivm, PIPE_MAX_SHADER_IMAGES), "");223indices[2] = LLVMBuildSelect(gallivm->builder, cond, indices[2], lp_build_const_int32(gallivm, image_unit), "");224}225/* context[0].textures[unit].member */226indices[3] = lp_build_const_int32(gallivm, member_index);227228ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");229230if (emit_load)231res = LLVMBuildLoad(builder, ptr, "");232else233res = ptr;234235lp_build_name(res, "context.image%u.%s", image_unit, member_name);236237return res;238}239240/**241* Helper macro to instantiate the functions that generate the code to242* fetch the members of lp_jit_texture to fulfill the sampler code243* generator requests.244*245* This complexity is the price we have to pay to keep the texture246* sampler code generator a reusable module without dependencies to247* llvmpipe internals.248*/249#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \250static LLVMValueRef \251draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \252struct gallivm_state *gallivm, \253LLVMValueRef context_ptr, \254unsigned texture_unit, \255LLVMValueRef texture_unit_offset) \256{ \257return draw_llvm_texture_member(base, gallivm, context_ptr, \258texture_unit, texture_unit_offset, \259_index, #_name, _emit_load ); \260}261262263DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE)264DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE)265DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE)266DRAW_LLVM_TEXTURE_MEMBER(first_level,DRAW_JIT_TEXTURE_FIRST_LEVEL, TRUE)267DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)268DRAW_LLVM_TEXTURE_MEMBER(base_ptr, DRAW_JIT_TEXTURE_BASE, TRUE)269DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)270DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)271DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE)272DRAW_LLVM_TEXTURE_MEMBER(num_samples, DRAW_JIT_TEXTURE_NUM_SAMPLES, TRUE)273DRAW_LLVM_TEXTURE_MEMBER(sample_stride, DRAW_JIT_TEXTURE_SAMPLE_STRIDE, TRUE)274275#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \276static LLVMValueRef \277draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \278struct gallivm_state *gallivm, \279LLVMValueRef context_ptr, \280unsigned sampler_unit) \281{ \282return draw_llvm_sampler_member(base, gallivm, context_ptr, \283sampler_unit, _index, #_name, _emit_load ); \284}285286287DRAW_LLVM_SAMPLER_MEMBER(min_lod, DRAW_JIT_SAMPLER_MIN_LOD, TRUE)288DRAW_LLVM_SAMPLER_MEMBER(max_lod, DRAW_JIT_SAMPLER_MAX_LOD, TRUE)289DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)290DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)291292#define DRAW_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \293static LLVMValueRef \294draw_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \295struct gallivm_state *gallivm, \296LLVMValueRef context_ptr, \297unsigned image_unit, LLVMValueRef image_unit_offset) \298{ \299return draw_llvm_image_member(base, gallivm, context_ptr, \300image_unit, image_unit_offset, \301_index, #_name, _emit_load ); \302}303304305DRAW_LLVM_IMAGE_MEMBER(width, DRAW_JIT_IMAGE_WIDTH, TRUE)306DRAW_LLVM_IMAGE_MEMBER(height, DRAW_JIT_IMAGE_HEIGHT, TRUE)307DRAW_LLVM_IMAGE_MEMBER(depth, DRAW_JIT_IMAGE_DEPTH, TRUE)308DRAW_LLVM_IMAGE_MEMBER(base_ptr, DRAW_JIT_IMAGE_BASE, TRUE)309DRAW_LLVM_IMAGE_MEMBER(row_stride, DRAW_JIT_IMAGE_ROW_STRIDE, TRUE)310DRAW_LLVM_IMAGE_MEMBER(img_stride, DRAW_JIT_IMAGE_IMG_STRIDE, TRUE)311DRAW_LLVM_IMAGE_MEMBER(num_samples, DRAW_JIT_IMAGE_NUM_SAMPLES, TRUE)312DRAW_LLVM_IMAGE_MEMBER(sample_stride, DRAW_JIT_IMAGE_SAMPLE_STRIDE, TRUE)313314static void315draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)316{317FREE(sampler);318}319320321/**322* Fetch filtered values from texture.323* The 'texel' parameter returns four vectors corresponding to R, G, B, A.324*/325static void326draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,327struct gallivm_state *gallivm,328const struct lp_sampler_params *params)329{330struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;331unsigned texture_index = params->texture_index;332unsigned sampler_index = params->sampler_index;333334assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);335assert(sampler_index < PIPE_MAX_SAMPLERS);336337if (params->texture_index_offset) {338struct lp_build_sample_array_switch switch_info;339memset(&switch_info, 0, sizeof(switch_info));340LLVMValueRef unit = LLVMBuildAdd(gallivm->builder, params->texture_index_offset,341lp_build_const_int32(gallivm, texture_index), "");342lp_build_sample_array_init_soa(&switch_info, gallivm, params, unit,3430, sampler->nr_samplers);344345for (unsigned i = 0; i < sampler->nr_samplers; i++) {346lp_build_sample_array_case_soa(&switch_info, i,347&sampler->dynamic_state.static_state[i].texture_state,348&sampler->dynamic_state.static_state[i].sampler_state,349&sampler->dynamic_state.base);350}351lp_build_sample_array_fini_soa(&switch_info);352} else {353lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,354&sampler->dynamic_state.static_state[sampler_index].sampler_state,355&sampler->dynamic_state.base,356gallivm, params);357}358}359360361/**362* Fetch the texture size.363*/364static void365draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,366struct gallivm_state *gallivm,367const struct lp_sampler_size_query_params *params)368{369struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;370371assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);372373lp_build_size_query_soa(gallivm,374&sampler->dynamic_state.static_state[params->texture_unit].texture_state,375&sampler->dynamic_state.base,376params);377}378379struct lp_build_sampler_soa *380draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,381unsigned nr_samplers)382{383struct draw_llvm_sampler_soa *sampler;384385sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);386if (!sampler)387return NULL;388389sampler->base.destroy = draw_llvm_sampler_soa_destroy;390sampler->base.emit_tex_sample = draw_llvm_sampler_soa_emit_fetch_texel;391sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;392sampler->dynamic_state.base.width = draw_llvm_texture_width;393sampler->dynamic_state.base.height = draw_llvm_texture_height;394sampler->dynamic_state.base.depth = draw_llvm_texture_depth;395sampler->dynamic_state.base.first_level = draw_llvm_texture_first_level;396sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;397sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;398sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;399sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr;400sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets;401sampler->dynamic_state.base.num_samples = draw_llvm_texture_num_samples;402sampler->dynamic_state.base.sample_stride = draw_llvm_texture_sample_stride;403sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;404sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;405sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;406sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;407sampler->dynamic_state.static_state = static_state;408409sampler->nr_samplers = nr_samplers;410return &sampler->base;411}412413static void414draw_llvm_image_soa_emit_op(const struct lp_build_image_soa *base,415struct gallivm_state *gallivm,416const struct lp_img_params *params)417{418struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;419unsigned image_index = params->image_index;420assert(image_index < PIPE_MAX_SHADER_IMAGES);421422if (params->image_index_offset) {423struct lp_build_img_op_array_switch switch_info;424memset(&switch_info, 0, sizeof(switch_info));425LLVMValueRef unit = LLVMBuildAdd(gallivm->builder, params->image_index_offset,426lp_build_const_int32(gallivm, image_index), "");427lp_build_image_op_switch_soa(&switch_info, gallivm, params,428unit, 0, image->nr_images);429430for (unsigned i = 0; i < image->nr_images; i++) {431lp_build_image_op_array_case(&switch_info, i,432&image->dynamic_state.static_state[i].image_state,433&image->dynamic_state.base);434}435lp_build_image_op_array_fini_soa(&switch_info);436return;437}438lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state,439&image->dynamic_state.base,440gallivm, params, params->outdata);441}442/**443* Fetch the texture size.444*/445static void446draw_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base,447struct gallivm_state *gallivm,448const struct lp_sampler_size_query_params *params)449{450struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;451452assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES);453454lp_build_size_query_soa(gallivm,455&image->dynamic_state.static_state[params->texture_unit].image_state,456&image->dynamic_state.base,457params);458}459static void460draw_llvm_image_soa_destroy(struct lp_build_image_soa *image)461{462FREE(image);463}464465struct lp_build_image_soa *466draw_llvm_image_soa_create(const struct draw_image_static_state *static_state,467unsigned nr_images)468{469struct draw_llvm_image_soa *image;470471image = CALLOC_STRUCT(draw_llvm_image_soa);472if (!image)473return NULL;474475image->base.destroy = draw_llvm_image_soa_destroy;476image->base.emit_op = draw_llvm_image_soa_emit_op;477image->base.emit_size_query = draw_llvm_image_soa_emit_size_query;478479image->dynamic_state.base.width = draw_llvm_image_width;480image->dynamic_state.base.height = draw_llvm_image_height;481482image->dynamic_state.base.depth = draw_llvm_image_depth;483image->dynamic_state.base.base_ptr = draw_llvm_image_base_ptr;484image->dynamic_state.base.row_stride = draw_llvm_image_row_stride;485image->dynamic_state.base.img_stride = draw_llvm_image_img_stride;486image->dynamic_state.base.num_samples = draw_llvm_image_num_samples;487image->dynamic_state.base.sample_stride = draw_llvm_image_sample_stride;488489image->dynamic_state.static_state = static_state;490491image->nr_images = nr_images;492return &image->base;493}494495496