mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-08 23:40:12 +01:00
draw: implement vertex texture sampling using llvm
This commit is contained in:
parent
ce929d8210
commit
01eebfe1b6
15 changed files with 516 additions and 32 deletions
|
|
@ -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_STRIDE);
|
||||
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_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
|
||||
|
|
|
|||
216
src/gallium/auxiliary/draw/draw_llvm_sample.c
Normal file
216
src/gallium/auxiliary/draw/draw_llvm_sample.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue