Path: blob/21.2-virgl/src/gallium/drivers/swr/swr_tex_sample.cpp
4570 views
/**************************************************************************1*2* Copyright 2009 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* Largely a copy of llvmpipe's lp_tex_sample.c29*/3031/**32* Texture sampling code generation33*34* This file is nothing more than ugly glue between three largely independent35* entities:36* - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa)37* - texture sampling code generation (i.e., lp_build_sample_soa)38* - SWR driver39*40* All interesting code is in the functions mentioned above. There is really41* nothing to see here.42*43* @author Jose Fonseca <[email protected]>44*/4546#include "state.h"47#include "JitManager.h"48#include "gen_state_llvm.h"4950#include "pipe/p_defines.h"51#include "pipe/p_shader_tokens.h"52#include "gallivm/lp_bld_debug.h"53#include "gallivm/lp_bld_const.h"54#include "gallivm/lp_bld_type.h"55#include "gallivm/lp_bld_sample.h"56#include "gallivm/lp_bld_tgsi.h"57#include "util/u_memory.h"5859#include "swr_tex_sample.h"60#include "gen_surf_state_llvm.h"61#include "gen_swr_context_llvm.h"6263using namespace SwrJit;6465/**66* This provides the bridge between the sampler state store in67* lp_jit_context and lp_jit_texture and the sampler code68* generator. It provides the texture layout information required by69* the texture sampler code generator in terms of the state stored in70* lp_jit_context and lp_jit_texture in runtime.71*/72struct swr_sampler_dynamic_state {73struct lp_sampler_dynamic_state base;7475const struct swr_sampler_static_state *static_state;7677enum pipe_shader_type shader_type;78};798081/**82* This is the bridge between our sampler and the TGSI translator.83*/84struct swr_sampler_soa {85struct lp_build_sampler_soa base;8687struct swr_sampler_dynamic_state dynamic_state;88};899091/**92* Fetch the specified member of the lp_jit_texture structure.93* \param emit_load if TRUE, emit the LLVM load instruction to actually94* fetch the field's value. Otherwise, just emit the95* GEP code to address the field.96*97* @sa http://llvm.org/docs/GetElementPtr.html98*/99static LLVMValueRef100swr_texture_member(const struct lp_sampler_dynamic_state *base,101struct gallivm_state *gallivm,102LLVMValueRef context_ptr,103unsigned texture_unit,104unsigned member_index,105const char *member_name,106boolean emit_load)107{108LLVMBuilderRef builder = gallivm->builder;109LLVMValueRef indices[4];110LLVMValueRef ptr;111LLVMValueRef res;112113assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);114115/* context[0] */116indices[0] = lp_build_const_int32(gallivm, 0);117/* context[0].textures */118auto dynamic = (const struct swr_sampler_dynamic_state *)base;119switch (dynamic->shader_type) {120case PIPE_SHADER_FRAGMENT:121indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesFS);122break;123case PIPE_SHADER_VERTEX:124indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesVS);125break;126case PIPE_SHADER_GEOMETRY:127indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesGS);128break;129case PIPE_SHADER_TESS_CTRL:130indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesTCS);131break;132case PIPE_SHADER_TESS_EVAL:133indices[1] = lp_build_const_int32(gallivm, swr_draw_context_texturesTES);134break;135default:136assert(0 && "unsupported shader type");137break;138}139/* context[0].textures[unit] */140indices[2] = lp_build_const_int32(gallivm, texture_unit);141/* context[0].textures[unit].member */142indices[3] = lp_build_const_int32(gallivm, member_index);143144ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");145146if (emit_load)147res = LLVMBuildLoad(builder, ptr, "");148else149res = ptr;150151lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);152153return res;154}155156157/**158* Helper macro to instantiate the functions that generate the code to159* fetch the members of lp_jit_texture to fulfill the sampler code160* generator requests.161*162* This complexity is the price we have to pay to keep the texture163* sampler code generator a reusable module without dependencies to164* swr internals.165*/166#define SWR_TEXTURE_MEMBER(_name, _emit_load) \167static LLVMValueRef swr_texture_##_name( \168const struct lp_sampler_dynamic_state *base, \169struct gallivm_state *gallivm, \170LLVMValueRef context_ptr, \171unsigned texture_unit, \172LLVMValueRef texture_unit_offset) \173{ \174return swr_texture_member(base, \175gallivm, \176context_ptr, \177texture_unit, \178swr_jit_texture_##_name, \179#_name, \180_emit_load); \181}182183184SWR_TEXTURE_MEMBER(width, TRUE)185SWR_TEXTURE_MEMBER(height, TRUE)186SWR_TEXTURE_MEMBER(depth, TRUE)187SWR_TEXTURE_MEMBER(first_level, TRUE)188SWR_TEXTURE_MEMBER(last_level, TRUE)189SWR_TEXTURE_MEMBER(base_ptr, TRUE)190SWR_TEXTURE_MEMBER(num_samples, TRUE)191SWR_TEXTURE_MEMBER(sample_stride, TRUE)192SWR_TEXTURE_MEMBER(row_stride, FALSE)193SWR_TEXTURE_MEMBER(img_stride, FALSE)194SWR_TEXTURE_MEMBER(mip_offsets, FALSE)195196197/**198* Fetch the specified member of the lp_jit_sampler structure.199* \param emit_load if TRUE, emit the LLVM load instruction to actually200* fetch the field's value. Otherwise, just emit the201* GEP code to address the field.202*203* @sa http://llvm.org/docs/GetElementPtr.html204*/205static LLVMValueRef206swr_sampler_member(const struct lp_sampler_dynamic_state *base,207struct gallivm_state *gallivm,208LLVMValueRef context_ptr,209unsigned sampler_unit,210unsigned member_index,211const char *member_name,212boolean emit_load)213{214LLVMBuilderRef builder = gallivm->builder;215LLVMValueRef indices[4];216LLVMValueRef ptr;217LLVMValueRef res;218219assert(sampler_unit < PIPE_MAX_SAMPLERS);220221/* context[0] */222indices[0] = lp_build_const_int32(gallivm, 0);223/* context[0].samplers */224auto dynamic = (const struct swr_sampler_dynamic_state *)base;225switch (dynamic->shader_type) {226case PIPE_SHADER_FRAGMENT:227indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersFS);228break;229case PIPE_SHADER_VERTEX:230indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersVS);231break;232case PIPE_SHADER_GEOMETRY:233indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersGS);234break;235case PIPE_SHADER_TESS_CTRL:236indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersTCS);237break;238case PIPE_SHADER_TESS_EVAL:239indices[1] = lp_build_const_int32(gallivm, swr_draw_context_samplersTES);240break;241default:242assert(0 && "unsupported shader type");243break;244}245/* context[0].samplers[unit] */246indices[2] = lp_build_const_int32(gallivm, sampler_unit);247/* context[0].samplers[unit].member */248indices[3] = lp_build_const_int32(gallivm, member_index);249250ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");251252if (emit_load)253res = LLVMBuildLoad(builder, ptr, "");254else255res = ptr;256257lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);258259return res;260}261262263#define SWR_SAMPLER_MEMBER(_name, _emit_load) \264static LLVMValueRef swr_sampler_##_name( \265const struct lp_sampler_dynamic_state *base, \266struct gallivm_state *gallivm, \267LLVMValueRef context_ptr, \268unsigned sampler_unit) \269{ \270return swr_sampler_member(base, \271gallivm, \272context_ptr, \273sampler_unit, \274swr_jit_sampler_##_name, \275#_name, \276_emit_load); \277}278279280SWR_SAMPLER_MEMBER(min_lod, TRUE)281SWR_SAMPLER_MEMBER(max_lod, TRUE)282SWR_SAMPLER_MEMBER(lod_bias, TRUE)283SWR_SAMPLER_MEMBER(border_color, FALSE)284285286static void287swr_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)288{289FREE(sampler);290}291292293/**294* Fetch filtered values from texture.295* The 'texel' parameter returns four vectors corresponding to R, G, B, A.296*/297static void298swr_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,299struct gallivm_state *gallivm,300const struct lp_sampler_params *params)301{302struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base;303unsigned texture_index = params->texture_index;304unsigned sampler_index = params->sampler_index;305306assert(sampler_index < PIPE_MAX_SAMPLERS);307assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);308309#if 0310lp_build_sample_nop(gallivm, params->type, params->coords, params->texel);311#else312lp_build_sample_soa(313&sampler->dynamic_state.static_state[texture_index].texture_state,314&sampler->dynamic_state.static_state[sampler_index].sampler_state,315&sampler->dynamic_state.base,316gallivm,317params);318#endif319}320321/**322* Fetch the texture size.323*/324static void325swr_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,326struct gallivm_state *gallivm,327const struct lp_sampler_size_query_params *params)328{329struct swr_sampler_soa *sampler = (struct swr_sampler_soa *)base;330331assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);332333lp_build_size_query_soa(334gallivm,335&sampler->dynamic_state.static_state[params->texture_unit].texture_state,336&sampler->dynamic_state.base,337params);338}339340341struct lp_build_sampler_soa *342swr_sampler_soa_create(const struct swr_sampler_static_state *static_state,343enum pipe_shader_type shader_type)344{345struct swr_sampler_soa *sampler;346347sampler = CALLOC_STRUCT(swr_sampler_soa);348if (!sampler)349return NULL;350351sampler->base.destroy = swr_sampler_soa_destroy;352sampler->base.emit_tex_sample = swr_sampler_soa_emit_fetch_texel;353sampler->base.emit_size_query = swr_sampler_soa_emit_size_query;354sampler->dynamic_state.base.width = swr_texture_width;355sampler->dynamic_state.base.height = swr_texture_height;356sampler->dynamic_state.base.depth = swr_texture_depth;357sampler->dynamic_state.base.first_level = swr_texture_first_level;358sampler->dynamic_state.base.last_level = swr_texture_last_level;359sampler->dynamic_state.base.base_ptr = swr_texture_base_ptr;360sampler->dynamic_state.base.row_stride = swr_texture_row_stride;361sampler->dynamic_state.base.img_stride = swr_texture_img_stride;362sampler->dynamic_state.base.mip_offsets = swr_texture_mip_offsets;363sampler->dynamic_state.base.num_samples = swr_texture_num_samples;364sampler->dynamic_state.base.sample_stride = swr_texture_sample_stride;365sampler->dynamic_state.base.min_lod = swr_sampler_min_lod;366sampler->dynamic_state.base.max_lod = swr_sampler_max_lod;367sampler->dynamic_state.base.lod_bias = swr_sampler_lod_bias;368sampler->dynamic_state.base.border_color = swr_sampler_border_color;369370sampler->dynamic_state.static_state = static_state;371372sampler->dynamic_state.shader_type = shader_type;373374return &sampler->base;375}376377378