@@ -171,7 +171,8 @@ GALLIVM_SOURCES = \ | |||
draw/draw_llvm.c \ | |||
draw/draw_vs_llvm.c \ | |||
draw/draw_pt_fetch_shade_pipeline_llvm.c \ | |||
draw/draw_llvm_translate.c | |||
draw/draw_llvm_translate.c \ | |||
draw/draw_llvm_sample.c | |||
GALLIVM_CPP_SOURCES = \ | |||
gallivm/lp_bld_misc.cpp |
@@ -221,7 +221,8 @@ if env['llvm']: | |||
'draw/draw_llvm.c', | |||
'draw/draw_pt_fetch_shade_pipeline_llvm.c', | |||
'draw/draw_llvm_translate.c', | |||
'draw/draw_vs_llvm.c' | |||
'draw/draw_vs_llvm.c', | |||
'draw/draw_llvm_sample.c' | |||
] | |||
gallium = env.ConvenienceLibrary( |
@@ -40,6 +40,7 @@ | |||
#if HAVE_LLVM | |||
#include "gallivm/lp_bld_init.h" | |||
#include "draw_llvm.h" | |||
#endif | |||
struct draw_context *draw_create( struct pipe_context *pipe ) | |||
@@ -52,6 +53,7 @@ struct draw_context *draw_create( struct pipe_context *pipe ) | |||
lp_build_init(); | |||
assert(lp_build_engine); | |||
draw->engine = lp_build_engine; | |||
draw->llvm = draw_llvm_create(draw); | |||
#endif | |||
if (!draw_init(draw)) | |||
@@ -132,6 +134,9 @@ void draw_destroy( struct draw_context *draw ) | |||
draw_pt_destroy( draw ); | |||
draw_vs_destroy( draw ); | |||
draw_gs_destroy( draw ); | |||
#ifdef HAVE_LLVM | |||
draw_llvm_destroy( draw->llvm ); | |||
#endif | |||
FREE( draw ); | |||
} | |||
@@ -601,3 +606,54 @@ draw_set_so_state(struct draw_context *draw, | |||
state, | |||
sizeof(struct pipe_stream_output_state)); | |||
} | |||
void | |||
draw_set_sampler_views(struct draw_context *draw, | |||
struct pipe_sampler_view **views, | |||
unsigned num) | |||
{ | |||
unsigned i; | |||
debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS); | |||
for (i = 0; i < num; ++i) | |||
draw->sampler_views[i] = views[i]; | |||
for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) | |||
draw->sampler_views[i] = NULL; | |||
draw->num_sampler_views = num; | |||
} | |||
void | |||
draw_set_samplers(struct draw_context *draw, | |||
struct pipe_sampler_state **samplers, | |||
unsigned num) | |||
{ | |||
unsigned i; | |||
debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS); | |||
for (i = 0; i < num; ++i) | |||
draw->samplers[i] = samplers[i]; | |||
for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) | |||
draw->samplers[i] = NULL; | |||
draw->num_samplers = num; | |||
} | |||
void | |||
draw_set_mapped_texture(struct draw_context *draw, | |||
unsigned sampler_idx, | |||
uint32_t width, uint32_t height, uint32_t depth, | |||
uint32_t last_level, | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]) | |||
{ | |||
#ifdef HAVE_LLVM | |||
draw_llvm_set_mapped_texture(draw, | |||
sampler_idx, | |||
width, height, depth, last_level, | |||
row_stride, img_stride, data); | |||
#endif | |||
} |
@@ -47,6 +47,7 @@ struct draw_vertex_shader; | |||
struct draw_geometry_shader; | |||
struct tgsi_sampler; | |||
#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */ | |||
struct draw_context *draw_create( struct pipe_context *pipe ); | |||
@@ -101,6 +102,23 @@ draw_texture_samplers(struct draw_context *draw, | |||
uint num_samplers, | |||
struct tgsi_sampler **samplers); | |||
void | |||
draw_set_sampler_views(struct draw_context *draw, | |||
struct pipe_sampler_view **views, | |||
unsigned num); | |||
void | |||
draw_set_samplers(struct draw_context *draw, | |||
struct pipe_sampler_state **samplers, | |||
unsigned num); | |||
void | |||
draw_set_mapped_texture(struct draw_context *draw, | |||
unsigned sampler_idx, | |||
uint32_t width, uint32_t height, uint32_t depth, | |||
uint32_t last_level, | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]); | |||
/* |
@@ -42,14 +42,13 @@ | |||
#include "tgsi/tgsi_dump.h" | |||
#include "util/u_cpu_detect.h" | |||
#include "util/u_string.h" | |||
#include "util/u_pointer.h" | |||
#include "util/u_string.h" | |||
#include <llvm-c/Transforms/Scalar.h> | |||
#define DEBUG_STORE 0 | |||
/* generates the draw jit function */ | |||
static void | |||
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var); | |||
@@ -63,12 +62,19 @@ init_globals(struct draw_llvm *llvm) | |||
/* struct draw_jit_texture */ | |||
{ | |||
LLVMTypeRef elem_types[4]; | |||
LLVMTypeRef elem_types[DRAW_JIT_TEXTURE_NUM_FIELDS]; | |||
elem_types[DRAW_JIT_TEXTURE_WIDTH] = LLVMInt32Type(); | |||
elem_types[DRAW_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); | |||
elem_types[DRAW_JIT_TEXTURE_STRIDE] = LLVMInt32Type(); | |||
elem_types[DRAW_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0); | |||
elem_types[DRAW_JIT_TEXTURE_DEPTH] = LLVMInt32Type(); | |||
elem_types[DRAW_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); | |||
elem_types[DRAW_JIT_TEXTURE_ROW_STRIDE] = | |||
LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS); | |||
elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] = | |||
LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS); | |||
elem_types[DRAW_JIT_TEXTURE_DATA] = | |||
LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), | |||
DRAW_MAX_TEXTURE_LEVELS); | |||
texture_type = LLVMStructType(elem_types, Elements(elem_types), 0); | |||
@@ -78,9 +84,18 @@ init_globals(struct draw_llvm *llvm) | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, height, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_HEIGHT); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, stride, | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, depth, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_DEPTH); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, last_level, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_LAST_LEVEL); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, row_stride, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_STRIDE); | |||
DRAW_JIT_TEXTURE_ROW_STRIDE); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, img_stride, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_IMG_STRIDE); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, data, | |||
llvm->target, texture_type, | |||
DRAW_JIT_TEXTURE_DATA); | |||
@@ -98,7 +113,8 @@ init_globals(struct draw_llvm *llvm) | |||
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */ | |||
elem_types[1] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */ | |||
elem_types[2] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */ | |||
elem_types[2] = LLVMArrayType(texture_type, | |||
PIPE_MAX_VERTEX_SAMPLERS); /* textures */ | |||
context_type = LLVMStructType(elem_types, Elements(elem_types), 0); | |||
@@ -108,7 +124,7 @@ init_globals(struct draw_llvm *llvm) | |||
llvm->target, context_type, 1); | |||
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures, | |||
llvm->target, context_type, | |||
DRAW_JIT_CONTEXT_TEXTURES_INDEX); | |||
DRAW_JIT_CTX_TEXTURES); | |||
LP_CHECK_STRUCT_SIZE(struct draw_jit_context, | |||
llvm->target, context_type); | |||
@@ -290,7 +306,8 @@ generate_vs(struct draw_llvm *llvm, | |||
LLVMBuilderRef builder, | |||
LLVMValueRef (*outputs)[NUM_CHANNELS], | |||
const LLVMValueRef (*inputs)[NUM_CHANNELS], | |||
LLVMValueRef context_ptr) | |||
LLVMValueRef context_ptr, | |||
struct lp_build_sampler_soa *sampler) | |||
{ | |||
const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens; | |||
struct lp_type vs_type; | |||
@@ -318,7 +335,7 @@ generate_vs(struct draw_llvm *llvm, | |||
NULL /*pos*/, | |||
inputs, | |||
outputs, | |||
NULL/*sampler*/, | |||
sampler, | |||
&llvm->draw->vs.vertex_shader->info); | |||
} | |||
@@ -641,6 +658,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) | |||
const int max_vertices = 4; | |||
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; | |||
void *code; | |||
struct lp_build_sampler_soa *sampler = 0; | |||
arg_types[0] = llvm->context_ptr_type; /* context */ | |||
arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */ | |||
@@ -688,6 +706,10 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) | |||
step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0); | |||
/* code generated texture sampling */ | |||
sampler = draw_llvm_sampler_soa_create(variant->key.sampler, | |||
context_ptr); | |||
#if DEBUG_STORE | |||
lp_build_printf(builder, "start = %d, end = %d, step = %d\n", | |||
start, end, step); | |||
@@ -729,7 +751,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) | |||
builder, | |||
outputs, | |||
ptr_aos, | |||
context_ptr); | |||
context_ptr, | |||
sampler); | |||
convert_to_aos(builder, io, outputs, | |||
draw->vs.vertex_shader->info.num_outputs, | |||
@@ -737,6 +760,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) | |||
} | |||
lp_build_loop_end_cond(builder, end, step, LLVMIntUGE, &lp_loop); | |||
sampler->destroy(sampler); | |||
LLVMBuildRetVoid(builder); | |||
LLVMDisposeBuilder(builder); | |||
@@ -787,6 +812,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian | |||
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; | |||
LLVMValueRef fetch_max; | |||
void *code; | |||
struct lp_build_sampler_soa *sampler = 0; | |||
arg_types[0] = llvm->context_ptr_type; /* context */ | |||
arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */ | |||
@@ -833,6 +859,10 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian | |||
step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0); | |||
/* code generated texture sampling */ | |||
sampler = draw_llvm_sampler_soa_create(variant->key.sampler, | |||
context_ptr); | |||
fetch_max = LLVMBuildSub(builder, fetch_count, | |||
LLVMConstInt(LLVMInt32Type(), 1, 0), | |||
"fetch_max"); | |||
@@ -884,7 +914,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian | |||
builder, | |||
outputs, | |||
ptr_aos, | |||
context_ptr); | |||
context_ptr, | |||
sampler); | |||
convert_to_aos(builder, io, outputs, | |||
draw->vs.vertex_shader->info.num_outputs, | |||
@@ -892,6 +923,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian | |||
} | |||
lp_build_loop_end_cond(builder, fetch_count, step, LLVMIntUGE, &lp_loop); | |||
sampler->destroy(sampler); | |||
LLVMBuildRetVoid(builder); | |||
LLVMDisposeBuilder(builder); | |||
@@ -925,6 +958,8 @@ void | |||
draw_llvm_make_variant_key(struct draw_llvm *llvm, | |||
struct draw_llvm_variant_key *key) | |||
{ | |||
unsigned i; | |||
memset(key, 0, sizeof(struct draw_llvm_variant_key)); | |||
key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements; | |||
@@ -936,6 +971,43 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, | |||
memcpy(&key->vs, | |||
&llvm->draw->vs.vertex_shader->state, | |||
sizeof(struct pipe_shader_state)); | |||
for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) { | |||
struct draw_vertex_shader *shader = llvm->draw->vs.vertex_shader; | |||
if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) | |||
lp_sampler_static_state(&key->sampler[i], | |||
llvm->draw->sampler_views[i], | |||
llvm->draw->samplers[i]); | |||
} | |||
} | |||
void | |||
draw_llvm_set_mapped_texture(struct draw_context *draw, | |||
unsigned sampler_idx, | |||
uint32_t width, uint32_t height, uint32_t depth, | |||
uint32_t last_level, | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]) | |||
{ | |||
unsigned j; | |||
struct draw_jit_texture *jit_tex; | |||
assert(sampler_idx <= PIPE_MAX_VERTEX_SAMPLERS); | |||
jit_tex = &draw->llvm->jit_context.textures[sampler_idx]; | |||
jit_tex->width = width; | |||
jit_tex->height = height; | |||
jit_tex->depth = depth; | |||
jit_tex->last_level = last_level; | |||
for (j = 0; j <= last_level; j++) { | |||
jit_tex->data[j] = data[j]; | |||
jit_tex->row_stride[j] = row_stride[j]; | |||
jit_tex->img_stride[j] = img_stride[j]; | |||
} | |||
} | |||
void |
@@ -25,12 +25,13 @@ | |||
* | |||
**************************************************************************/ | |||
#ifndef HAVE_LLVM_H | |||
#define HAVE_LLVM_H | |||
#ifndef DRAW_LLVM_H | |||
#define DRAW_LLVM_H | |||
#include "draw/draw_private.h" | |||
#include "draw/draw_vs.h" | |||
#include "gallivm/lp_bld_sample.h" | |||
#include "pipe/p_context.h" | |||
#include "util/u_simple_list.h" | |||
@@ -40,6 +41,8 @@ | |||
#include <llvm-c/Target.h> | |||
#include <llvm-c/ExecutionEngine.h> | |||
#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */ | |||
struct draw_llvm; | |||
struct llvm_vertex_shader; | |||
@@ -47,15 +50,22 @@ struct draw_jit_texture | |||
{ | |||
uint32_t width; | |||
uint32_t height; | |||
uint32_t stride; | |||
const void *data; | |||
uint32_t depth; | |||
uint32_t last_level; | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS]; | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS]; | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]; | |||
}; | |||
enum { | |||
DRAW_JIT_TEXTURE_WIDTH = 0, | |||
DRAW_JIT_TEXTURE_HEIGHT, | |||
DRAW_JIT_TEXTURE_STRIDE, | |||
DRAW_JIT_TEXTURE_DATA | |||
DRAW_JIT_TEXTURE_DEPTH, | |||
DRAW_JIT_TEXTURE_LAST_LEVEL, | |||
DRAW_JIT_TEXTURE_ROW_STRIDE, | |||
DRAW_JIT_TEXTURE_IMG_STRIDE, | |||
DRAW_JIT_TEXTURE_DATA, | |||
DRAW_JIT_TEXTURE_NUM_FIELDS /* number of fields above */ | |||
}; | |||
enum { | |||
@@ -81,7 +91,7 @@ struct draw_jit_context | |||
const float *gs_constants; | |||
struct draw_jit_texture textures[PIPE_MAX_SAMPLERS]; | |||
struct draw_jit_texture textures[PIPE_MAX_VERTEX_SAMPLERS]; | |||
}; | |||
@@ -91,10 +101,10 @@ struct draw_jit_context | |||
#define draw_jit_context_gs_constants(_builder, _ptr) \ | |||
lp_build_struct_get(_builder, _ptr, 1, "gs_constants") | |||
#define DRAW_JIT_CONTEXT_TEXTURES_INDEX 2 | |||
#define DRAW_JIT_CTX_TEXTURES 2 | |||
#define draw_jit_context_textures(_builder, _ptr) \ | |||
lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CONTEXT_TEXTURES_INDEX, "textures") | |||
lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CTX_TEXTURES, "textures") | |||
@@ -142,6 +152,7 @@ struct draw_llvm_variant_key | |||
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; | |||
unsigned nr_vertex_elements; | |||
struct pipe_shader_state vs; | |||
struct lp_sampler_static_state sampler[PIPE_MAX_VERTEX_SAMPLERS]; | |||
}; | |||
struct draw_llvm_variant_list_item | |||
@@ -221,4 +232,17 @@ draw_llvm_translate_from(LLVMBuilderRef builder, | |||
LLVMValueRef vbuffer, | |||
enum pipe_format from_format); | |||
struct lp_build_sampler_soa * | |||
draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, | |||
LLVMValueRef context_ptr); | |||
void | |||
draw_llvm_set_mapped_texture(struct draw_context *draw, | |||
unsigned sampler_idx, | |||
uint32_t width, uint32_t height, uint32_t depth, | |||
uint32_t last_level, | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS], | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]); | |||
#endif |
@@ -0,0 +1,216 @@ | |||
/************************************************************************** | |||
* | |||
* Copyright 2010 VMware, Inc. | |||
* All rights reserved. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sub license, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* The above copyright notice and this permission notice (including the | |||
* next paragraph) shall be included in all copies or substantial portions | |||
* of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | |||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR | |||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
* | |||
**************************************************************************/ | |||
/** | |||
* Texture sampling code generation | |||
* @author Jose Fonseca <jfonseca@vmware.com> | |||
*/ | |||
#include "pipe/p_defines.h" | |||
#include "pipe/p_shader_tokens.h" | |||
#include "gallivm/lp_bld_debug.h" | |||
#include "gallivm/lp_bld_type.h" | |||
#include "gallivm/lp_bld_sample.h" | |||
#include "gallivm/lp_bld_tgsi.h" | |||
#include "util/u_cpu_detect.h" | |||
#include "util/u_debug.h" | |||
#include "util/u_memory.h" | |||
#include "util/u_pointer.h" | |||
#include "util/u_string.h" | |||
#include "draw_llvm.h" | |||
/** | |||
* This provides the bridge between the sampler state store in | |||
* lp_jit_context and lp_jit_texture and the sampler code | |||
* generator. It provides the texture layout information required by | |||
* the texture sampler code generator in terms of the state stored in | |||
* lp_jit_context and lp_jit_texture in runtime. | |||
*/ | |||
struct draw_llvm_sampler_dynamic_state | |||
{ | |||
struct lp_sampler_dynamic_state base; | |||
const struct lp_sampler_static_state *static_state; | |||
LLVMValueRef context_ptr; | |||
}; | |||
/** | |||
* This is the bridge between our sampler and the TGSI translator. | |||
*/ | |||
struct draw_llvm_sampler_soa | |||
{ | |||
struct lp_build_sampler_soa base; | |||
struct draw_llvm_sampler_dynamic_state dynamic_state; | |||
}; | |||
/** | |||
* Fetch the specified member of the lp_jit_texture structure. | |||
* \param emit_load if TRUE, emit the LLVM load instruction to actually | |||
* fetch the field's value. Otherwise, just emit the | |||
* GEP code to address the field. | |||
* | |||
* @sa http://llvm.org/docs/GetElementPtr.html | |||
*/ | |||
static LLVMValueRef | |||
draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base, | |||
LLVMBuilderRef builder, | |||
unsigned unit, | |||
unsigned member_index, | |||
const char *member_name, | |||
boolean emit_load) | |||
{ | |||
struct draw_llvm_sampler_dynamic_state *state = | |||
(struct draw_llvm_sampler_dynamic_state *)base; | |||
LLVMValueRef indices[4]; | |||
LLVMValueRef ptr; | |||
LLVMValueRef res; | |||
debug_assert(unit < PIPE_MAX_VERTEX_SAMPLERS); | |||
/* context[0] */ | |||
indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); | |||
/* context[0].textures */ | |||
indices[1] = LLVMConstInt(LLVMInt32Type(), DRAW_JIT_CTX_TEXTURES, 0); | |||
/* context[0].textures[unit] */ | |||
indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0); | |||
/* context[0].textures[unit].member */ | |||
indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0); | |||
ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); | |||
if (emit_load) | |||
res = LLVMBuildLoad(builder, ptr, ""); | |||
else | |||
res = ptr; | |||
lp_build_name(res, "context.texture%u.%s", unit, member_name); | |||
return res; | |||
} | |||
/** | |||
* Helper macro to instantiate the functions that generate the code to | |||
* fetch the members of lp_jit_texture to fulfill the sampler code | |||
* generator requests. | |||
* | |||
* This complexity is the price we have to pay to keep the texture | |||
* sampler code generator a reusable module without dependencies to | |||
* llvmpipe internals. | |||
*/ | |||
#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ | |||
static LLVMValueRef \ | |||
draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ | |||
LLVMBuilderRef builder, \ | |||
unsigned unit) \ | |||
{ \ | |||
return draw_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \ | |||
} | |||
DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE) | |||
DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE) | |||
DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE) | |||
DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE) | |||
DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE) | |||
DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE) | |||
DRAW_LLVM_TEXTURE_MEMBER(data_ptr, DRAW_JIT_TEXTURE_DATA, FALSE) | |||
static void | |||
draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) | |||
{ | |||
FREE(sampler); | |||
} | |||
/** | |||
* Fetch filtered values from texture. | |||
* The 'texel' parameter returns four vectors corresponding to R, G, B, A. | |||
*/ | |||
static void | |||
draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, | |||
LLVMBuilderRef builder, | |||
struct lp_type type, | |||
unsigned unit, | |||
unsigned num_coords, | |||
const LLVMValueRef *coords, | |||
const LLVMValueRef *ddx, | |||
const LLVMValueRef *ddy, | |||
LLVMValueRef lod_bias, /* optional */ | |||
LLVMValueRef explicit_lod, /* optional */ | |||
LLVMValueRef *texel) | |||
{ | |||
struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; | |||
assert(unit < PIPE_MAX_VERTEX_SAMPLERS); | |||
lp_build_sample_soa(builder, | |||
&sampler->dynamic_state.static_state[unit], | |||
&sampler->dynamic_state.base, | |||
type, | |||
unit, | |||
num_coords, coords, | |||
ddx, ddy, | |||
lod_bias, explicit_lod, | |||
texel); | |||
} | |||
struct lp_build_sampler_soa * | |||
draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, | |||
LLVMValueRef context_ptr) | |||
{ | |||
struct draw_llvm_sampler_soa *sampler; | |||
sampler = CALLOC_STRUCT(draw_llvm_sampler_soa); | |||
if(!sampler) | |||
return NULL; | |||
sampler->base.destroy = draw_llvm_sampler_soa_destroy; | |||
sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel; | |||
sampler->dynamic_state.base.width = draw_llvm_texture_width; | |||
sampler->dynamic_state.base.height = draw_llvm_texture_height; | |||
sampler->dynamic_state.base.depth = draw_llvm_texture_depth; | |||
sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level; | |||
sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride; | |||
sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride; | |||
sampler->dynamic_state.base.data_ptr = draw_llvm_texture_data_ptr; | |||
sampler->dynamic_state.static_state = static_state; | |||
sampler->dynamic_state.context_ptr = context_ptr; | |||
return &sampler->base; | |||
} | |||
@@ -48,6 +48,7 @@ | |||
#ifdef HAVE_LLVM | |||
#include <llvm-c/ExecutionEngine.h> | |||
struct draw_llvm; | |||
#endif | |||
@@ -262,9 +263,15 @@ struct draw_context | |||
unsigned instance_id; | |||
#ifdef HAVE_LLVM | |||
struct draw_llvm *llvm; | |||
LLVMExecutionEngineRef engine; | |||
#endif | |||
struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; | |||
unsigned num_sampler_views; | |||
const struct pipe_sampler_state *samplers[PIPE_MAX_VERTEX_SAMPLERS]; | |||
unsigned num_samplers; | |||
void *driver_private; | |||
}; | |||
@@ -392,9 +392,6 @@ static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle ) | |||
if (fpme->post_vs) | |||
draw_pt_post_vs_destroy( fpme->post_vs ); | |||
if (fpme->llvm) | |||
draw_llvm_destroy( fpme->llvm ); | |||
FREE(middle); | |||
} | |||
@@ -436,7 +433,7 @@ draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw) | |||
if (!fpme->so_emit) | |||
goto fail; | |||
fpme->llvm = draw_llvm_create(draw); | |||
fpme->llvm = draw->llvm; | |||
if (!fpme->llvm) | |||
goto fail; | |||
@@ -86,7 +86,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) | |||
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: | |||
return PIPE_MAX_SAMPLERS; | |||
case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: | |||
return 0; | |||
return PIPE_MAX_VERTEX_SAMPLERS; | |||
case PIPE_CAP_MAX_COMBINED_SAMPLERS: | |||
return PIPE_MAX_SAMPLERS + PIPE_MAX_VERTEX_SAMPLERS; | |||
case PIPE_CAP_NPOT_TEXTURES: |
@@ -641,7 +641,6 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, | |||
/* | |||
* XXX: Where should this be unmapped? | |||
*/ | |||
struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); | |||
struct sw_winsys *winsys = screen->winsys; | |||
jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, | |||
@@ -657,6 +656,75 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, | |||
} | |||
/** | |||
* Called during state validation when LP_NEW_SAMPLER_VIEW is set. | |||
*/ | |||
void | |||
lp_setup_set_vertex_sampler_views(struct lp_setup_context *setup, | |||
unsigned num, | |||
struct pipe_sampler_view **views) | |||
{ | |||
unsigned i; | |||
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS]; | |||
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS]; | |||
const void *data[DRAW_MAX_TEXTURE_LEVELS]; | |||
struct lp_scene *scene; | |||
struct llvmpipe_context *lp; | |||
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); | |||
assert(num <= PIPE_MAX_VERTEX_SAMPLERS); | |||
scene = lp_setup_get_current_scene(setup); | |||
lp = llvmpipe_context(scene->pipe); | |||
for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { | |||
struct pipe_sampler_view *view = i < num ? views[i] : NULL; | |||
if (view) { | |||
struct pipe_resource *tex = view->texture; | |||
struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); | |||
/* We're referencing the texture's internal data, so save a | |||
* reference to it. | |||
*/ | |||
pipe_resource_reference(&setup->vs.current_tex[i], tex); | |||
if (!lp_tex->dt) { | |||
/* regular texture - setup array of mipmap level pointers */ | |||
int j; | |||
for (j = 0; j <= tex->last_level; j++) { | |||
data[j] = | |||
llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, | |||
LP_TEX_LAYOUT_LINEAR); | |||
row_stride[j] = lp_tex->row_stride[j]; | |||
img_stride[j] = lp_tex->img_stride[j]; | |||
} | |||
} | |||
else { | |||
/* display target texture/surface */ | |||
/* | |||
* XXX: Where should this be unmapped? | |||
*/ | |||
struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); | |||
struct sw_winsys *winsys = screen->winsys; | |||
data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, | |||
PIPE_TRANSFER_READ); | |||
row_stride[0] = lp_tex->row_stride[0]; | |||
img_stride[0] = lp_tex->img_stride[0]; | |||
assert(data[0]); | |||
} | |||
draw_set_mapped_texture(lp->draw, | |||
i, | |||
tex->width0, tex->height0, tex->depth0, | |||
tex->last_level, | |||
row_stride, img_stride, data); | |||
} | |||
} | |||
} | |||
/** | |||
* Is the given texture referenced by any scene? | |||
* Note: we have to check all scenes including any scenes currently | |||
@@ -850,6 +918,9 @@ lp_setup_destroy( struct lp_setup_context *setup ) | |||
util_unreference_framebuffer_state(&setup->fb); | |||
for (i = 0; i < Elements(setup->vs.current_tex); i++) { | |||
pipe_resource_reference(&setup->vs.current_tex[i], NULL); | |||
} | |||
for (i = 0; i < Elements(setup->fs.current_tex); i++) { | |||
pipe_resource_reference(&setup->fs.current_tex[i], NULL); | |||
} |
@@ -133,6 +133,11 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, | |||
unsigned num, | |||
struct pipe_sampler_view **views); | |||
void | |||
lp_setup_set_vertex_sampler_views(struct lp_setup_context *setup, | |||
unsigned num, | |||
struct pipe_sampler_view **views); | |||
unsigned | |||
lp_setup_is_resource_referenced( const struct lp_setup_context *setup, | |||
const struct pipe_resource *texture ); |
@@ -116,6 +116,10 @@ struct lp_setup_context | |||
struct pipe_resource *current_tex[PIPE_MAX_SAMPLERS]; | |||
} fs; | |||
struct { | |||
struct pipe_resource *current_tex[PIPE_MAX_VERTEX_SAMPLERS]; | |||
} vs; | |||
/** fragment shader constants */ | |||
struct { | |||
struct pipe_resource *current; |
@@ -188,10 +188,14 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) | |||
lp_setup_set_fs_constants(llvmpipe->setup, | |||
llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]); | |||
if (llvmpipe->dirty & LP_NEW_SAMPLER_VIEW) | |||
lp_setup_set_fragment_sampler_views(llvmpipe->setup, | |||
if (llvmpipe->dirty & LP_NEW_SAMPLER_VIEW) { | |||
lp_setup_set_fragment_sampler_views(llvmpipe->setup, | |||
llvmpipe->num_fragment_sampler_views, | |||
llvmpipe->fragment_sampler_views); | |||
lp_setup_set_vertex_sampler_views(llvmpipe->setup, | |||
llvmpipe->num_vertex_sampler_views, | |||
llvmpipe->vertex_sampler_views); | |||
} | |||
llvmpipe->dirty = 0; | |||
} |
@@ -100,6 +100,10 @@ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe, | |||
llvmpipe->num_vertex_samplers = num_samplers; | |||
draw_set_samplers(llvmpipe->draw, | |||
llvmpipe->vertex_samplers, | |||
llvmpipe->num_vertex_samplers); | |||
llvmpipe->dirty |= LP_NEW_SAMPLER; | |||
} | |||
@@ -166,6 +170,10 @@ llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe, | |||
llvmpipe->num_vertex_sampler_views = num; | |||
draw_set_sampler_views(llvmpipe->draw, | |||
llvmpipe->vertex_sampler_views, | |||
llvmpipe->num_vertex_sampler_views); | |||
llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; | |||
} | |||