mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 00:49:04 +02:00
llvmpipe: Code generate alpha testing and append to generated fragment shader.
This commit is contained in:
parent
b5e397c369
commit
9ae47069b4
9 changed files with 278 additions and 146 deletions
|
|
@ -4,6 +4,7 @@ include $(TOP)/configs/current
|
|||
LIBNAME = llvmpipe
|
||||
|
||||
C_SOURCES = \
|
||||
lp_bld_alpha.c \
|
||||
lp_bld_arit.c \
|
||||
lp_bld_blend_aos.c \
|
||||
lp_bld_blend_soa.c \
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ env.ParseConfig('llvm-config --cppflags')
|
|||
llvmpipe = env.ConvenienceLibrary(
|
||||
target = 'llvmpipe',
|
||||
source = [
|
||||
'lp_bld_alpha.c',
|
||||
'lp_bld_arit.c',
|
||||
'lp_bld_blend_aos.c',
|
||||
'lp_bld_blend_soa.c',
|
||||
|
|
|
|||
68
src/gallium/drivers/llvmpipe/lp_bld_alpha.c
Normal file
68
src/gallium/drivers/llvmpipe/lp_bld_alpha.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Alpha testing to LLVM IR translation.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_const.h"
|
||||
#include "lp_bld_arit.h"
|
||||
#include "lp_bld_logic.h"
|
||||
#include "lp_bld_debug.h"
|
||||
#include "lp_bld_alpha.h"
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_alpha_test(LLVMBuilderRef builder,
|
||||
const struct pipe_alpha_state *state,
|
||||
union lp_type type,
|
||||
LLVMValueRef alpha,
|
||||
LLVMValueRef mask)
|
||||
{
|
||||
struct lp_build_context bld;
|
||||
|
||||
lp_build_context_init(&bld, builder, type);
|
||||
|
||||
if(state->enabled) {
|
||||
LLVMValueRef ref = lp_build_const_uni(type, state->ref_value);
|
||||
LLVMValueRef test = lp_build_cmp(&bld, state->func, alpha, ref);
|
||||
|
||||
lp_build_name(test, "alpha_mask");
|
||||
|
||||
if(mask)
|
||||
mask = LLVMBuildAnd(builder, mask, test, "");
|
||||
else
|
||||
mask = test;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
52
src/gallium/drivers/llvmpipe/lp_bld_alpha.h
Normal file
52
src/gallium/drivers/llvmpipe/lp_bld_alpha.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Alpha testing to LLVM IR translation.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef LP_BLD_ALPHA_H
|
||||
#define LP_BLD_ALPHA_H
|
||||
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
struct pipe_alpha_state;
|
||||
union lp_type;
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_alpha_test(LLVMBuilderRef builder,
|
||||
const struct pipe_alpha_state *state,
|
||||
union lp_type type,
|
||||
LLVMValueRef alpha,
|
||||
LLVMValueRef mask);
|
||||
|
||||
|
||||
#endif /* !LP_BLD_ALPHA_H */
|
||||
|
|
@ -564,75 +564,6 @@ depth_stencil_test_quad(struct quad_stage *qs,
|
|||
}
|
||||
|
||||
|
||||
#define ALPHATEST( FUNC, COMP ) \
|
||||
static int \
|
||||
alpha_test_quads_##FUNC( struct quad_stage *qs, \
|
||||
struct quad_header *quads[], \
|
||||
unsigned nr ) \
|
||||
{ \
|
||||
const float ref = qs->llvmpipe->depth_stencil->alpha.ref_value; \
|
||||
const uint cbuf = 0; /* only output[0].alpha is tested */ \
|
||||
unsigned pass_nr = 0; \
|
||||
unsigned i; \
|
||||
\
|
||||
for (i = 0; i < nr; i++) { \
|
||||
const float *aaaa = quads[i]->output.color[cbuf][3]; \
|
||||
unsigned passMask = 0; \
|
||||
\
|
||||
if (!quads[i]->inout.mask) \
|
||||
continue; \
|
||||
\
|
||||
if (aaaa[0] COMP ref) passMask |= (1 << 0); \
|
||||
if (aaaa[1] COMP ref) passMask |= (1 << 1); \
|
||||
if (aaaa[2] COMP ref) passMask |= (1 << 2); \
|
||||
if (aaaa[3] COMP ref) passMask |= (1 << 3); \
|
||||
\
|
||||
quads[i]->inout.mask &= passMask; \
|
||||
\
|
||||
if (quads[i]->inout.mask) \
|
||||
++pass_nr; \
|
||||
} \
|
||||
\
|
||||
return pass_nr; \
|
||||
}
|
||||
|
||||
|
||||
ALPHATEST( LESS, < )
|
||||
ALPHATEST( EQUAL, == )
|
||||
ALPHATEST( LEQUAL, <= )
|
||||
ALPHATEST( GREATER, > )
|
||||
ALPHATEST( NOTEQUAL, != )
|
||||
ALPHATEST( GEQUAL, >= )
|
||||
|
||||
|
||||
/* XXX: Incorporate into shader using KILP.
|
||||
*/
|
||||
static int
|
||||
alpha_test_quads(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
switch (qs->llvmpipe->depth_stencil->alpha.func) {
|
||||
case PIPE_FUNC_LESS:
|
||||
return alpha_test_quads_LESS( qs, quads, nr );
|
||||
case PIPE_FUNC_EQUAL:
|
||||
return alpha_test_quads_EQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
return alpha_test_quads_LEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_GREATER:
|
||||
return alpha_test_quads_GREATER( qs, quads, nr );
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
return alpha_test_quads_NOTEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
return alpha_test_quads_GEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
return nr;
|
||||
case PIPE_FUNC_NEVER:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned mask_count[0x8] =
|
||||
{
|
||||
|
|
@ -659,10 +590,6 @@ depth_test_quads_fallback(struct quad_stage *qs,
|
|||
struct depth_data data;
|
||||
|
||||
|
||||
if (qs->llvmpipe->depth_stencil->alpha.enabled) {
|
||||
alpha_test_quads(qs, quads, nr);
|
||||
}
|
||||
|
||||
if (qs->llvmpipe->framebuffer.zsbuf &&
|
||||
(qs->llvmpipe->depth_stencil->depth.enabled ||
|
||||
qs->llvmpipe->depth_stencil->stencil[0].enabled)) {
|
||||
|
|
@ -801,8 +728,6 @@ choose_depth_test(struct quad_stage *qs,
|
|||
{
|
||||
boolean interp_depth = !qs->llvmpipe->fs->info.writes_z;
|
||||
|
||||
boolean alpha = qs->llvmpipe->depth_stencil->alpha.enabled;
|
||||
|
||||
boolean depth = (qs->llvmpipe->framebuffer.zsbuf &&
|
||||
qs->llvmpipe->depth_stencil->depth.enabled);
|
||||
|
||||
|
|
@ -815,13 +740,11 @@ choose_depth_test(struct quad_stage *qs,
|
|||
|
||||
qs->run = depth_test_quads_fallback;
|
||||
|
||||
if (!alpha &&
|
||||
!depth &&
|
||||
if (!depth &&
|
||||
!stencil) {
|
||||
qs->run = depth_noop;
|
||||
}
|
||||
else if (!alpha &&
|
||||
interp_depth &&
|
||||
else if (interp_depth &&
|
||||
depth &&
|
||||
depthfunc == PIPE_FUNC_LESS &&
|
||||
depthwrite &&
|
||||
|
|
|
|||
|
|
@ -76,10 +76,15 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
{
|
||||
struct quad_shade_stage *qss = quad_shade_stage( qs );
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
struct lp_fragment_shader *fs = llvmpipe->fs;
|
||||
void *constants;
|
||||
struct tgsi_sampler **samplers;
|
||||
unsigned chan_index;
|
||||
|
||||
assert(fs->current);
|
||||
if(!fs->current)
|
||||
return FALSE;
|
||||
|
||||
constants = llvmpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
|
||||
samplers = (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list;
|
||||
|
||||
|
|
@ -87,16 +92,16 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
qss->mask[chan_index] = ~0;
|
||||
|
||||
/* run shader */
|
||||
llvmpipe->fs->jit_function( quad->input.x0,
|
||||
quad->input.y0,
|
||||
quad->coef->a0,
|
||||
quad->coef->dadx,
|
||||
quad->coef->dady,
|
||||
constants,
|
||||
qss->mask,
|
||||
quad->output.color,
|
||||
quad->output.depth,
|
||||
samplers);
|
||||
fs->current->jit_function( quad->input.x0,
|
||||
quad->input.y0,
|
||||
quad->coef->a0,
|
||||
quad->coef->dadx,
|
||||
quad->coef->dady,
|
||||
constants,
|
||||
qss->mask,
|
||||
quad->output.color,
|
||||
quad->output.depth,
|
||||
samplers);
|
||||
|
||||
for (chan_index = 0; chan_index < NUM_CHANNELS; ++chan_index)
|
||||
if(!qss->mask[chan_index])
|
||||
|
|
|
|||
|
|
@ -70,6 +70,28 @@ typedef void
|
|||
void *depth,
|
||||
struct tgsi_sampler **samplers);
|
||||
|
||||
|
||||
struct lp_fragment_shader;
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state (though it doesn't really need to be).
|
||||
*
|
||||
* This is starting to look an awful lot like a quad pipeline stage...
|
||||
*/
|
||||
struct lp_fragment_shader_variant
|
||||
{
|
||||
struct lp_fragment_shader *shader;
|
||||
struct pipe_alpha_state alpha;
|
||||
|
||||
LLVMValueRef function;
|
||||
|
||||
lp_shader_fs_func jit_function;
|
||||
|
||||
struct lp_fragment_shader_variant *next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state (though it doesn't really need to be).
|
||||
*
|
||||
|
|
@ -83,9 +105,9 @@ struct lp_fragment_shader
|
|||
|
||||
struct llvmpipe_screen *screen;
|
||||
|
||||
LLVMValueRef function;
|
||||
struct lp_fragment_shader_variant *variants;
|
||||
|
||||
lp_shader_fs_func jit_function;
|
||||
struct lp_fragment_shader_variant *current;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -183,6 +205,7 @@ void llvmpipe_set_vertex_buffers(struct pipe_context *,
|
|||
unsigned count,
|
||||
const struct pipe_vertex_buffer *);
|
||||
|
||||
void llvmpipe_update_fs(struct llvmpipe_context *lp);
|
||||
|
||||
void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe );
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,11 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
|||
LP_NEW_FRAMEBUFFER))
|
||||
compute_cliprect(llvmpipe);
|
||||
|
||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA))
|
||||
llvmpipe_update_fs( llvmpipe );
|
||||
|
||||
|
||||
if (llvmpipe->dirty & (LP_NEW_BLEND |
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA |
|
||||
LP_NEW_FRAMEBUFFER |
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_debug_dump.h"
|
||||
#include "pipe/internal/p_winsys_screen.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "draw/draw_context.h"
|
||||
|
|
@ -36,6 +37,7 @@
|
|||
#include "tgsi/tgsi_parse.h"
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_tgsi.h"
|
||||
#include "lp_bld_alpha.h"
|
||||
#include "lp_bld_swizzle.h"
|
||||
#include "lp_bld_debug.h"
|
||||
#include "lp_screen.h"
|
||||
|
|
@ -103,10 +105,12 @@ setup_pos_vector(LLVMBuilderRef builder,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
static struct lp_fragment_shader_variant *
|
||||
shader_generate(struct llvmpipe_screen *screen,
|
||||
struct lp_fragment_shader *shader)
|
||||
struct lp_fragment_shader *shader,
|
||||
const struct pipe_alpha_state *alpha)
|
||||
{
|
||||
struct lp_fragment_shader_variant *variant;
|
||||
const struct tgsi_token *tokens = shader->base.tokens;
|
||||
union lp_type type;
|
||||
LLVMTypeRef elem_type;
|
||||
|
|
@ -129,10 +133,25 @@ shader_generate(struct llvmpipe_screen *screen,
|
|||
LLVMValueRef pos[NUM_CHANNELS];
|
||||
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
|
||||
LLVMValueRef mask;
|
||||
LLVMValueRef fetch_texel;
|
||||
unsigned i;
|
||||
unsigned attrib;
|
||||
unsigned chan;
|
||||
|
||||
#ifdef DEBUG
|
||||
tgsi_dump(shader->base.tokens, 0);
|
||||
debug_printf("alpha.enabled = %u\n", alpha->enabled);
|
||||
debug_printf("alpha.func = %s\n", debug_dump_func(alpha->func, TRUE));
|
||||
debug_printf("alpha.ref_value = %f\n", alpha->ref_value);
|
||||
#endif
|
||||
|
||||
variant = CALLOC_STRUCT(lp_fragment_shader_variant);
|
||||
if(!variant)
|
||||
return NULL;
|
||||
|
||||
variant->shader = shader;
|
||||
memcpy(&variant->alpha, alpha, sizeof *alpha);
|
||||
|
||||
type.value = 0;
|
||||
type.floating = TRUE; /* floating point values */
|
||||
type.sign = TRUE; /* values are signed */
|
||||
|
|
@ -157,22 +176,22 @@ shader_generate(struct llvmpipe_screen *screen,
|
|||
|
||||
func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
|
||||
|
||||
shader->function = LLVMAddFunction(screen->module, "shader", func_type);
|
||||
LLVMSetFunctionCallConv(shader->function, LLVMCCallConv);
|
||||
variant->function = LLVMAddFunction(screen->module, "shader", func_type);
|
||||
LLVMSetFunctionCallConv(variant->function, LLVMCCallConv);
|
||||
for(i = 0; i < Elements(arg_types); ++i)
|
||||
if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
|
||||
LLVMAddAttribute(LLVMGetParam(shader->function, i), LLVMNoAliasAttribute);
|
||||
LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute);
|
||||
|
||||
x = LLVMGetParam(shader->function, 0);
|
||||
y = LLVMGetParam(shader->function, 1);
|
||||
a0_ptr = LLVMGetParam(shader->function, 2);
|
||||
dadx_ptr = LLVMGetParam(shader->function, 3);
|
||||
dady_ptr = LLVMGetParam(shader->function, 4);
|
||||
consts_ptr = LLVMGetParam(shader->function, 5);
|
||||
mask_ptr = LLVMGetParam(shader->function, 6);
|
||||
color_ptr = LLVMGetParam(shader->function, 7);
|
||||
depth_ptr = LLVMGetParam(shader->function, 8);
|
||||
samplers_ptr = LLVMGetParam(shader->function, 9);
|
||||
x = LLVMGetParam(variant->function, 0);
|
||||
y = LLVMGetParam(variant->function, 1);
|
||||
a0_ptr = LLVMGetParam(variant->function, 2);
|
||||
dadx_ptr = LLVMGetParam(variant->function, 3);
|
||||
dady_ptr = LLVMGetParam(variant->function, 4);
|
||||
consts_ptr = LLVMGetParam(variant->function, 5);
|
||||
mask_ptr = LLVMGetParam(variant->function, 6);
|
||||
color_ptr = LLVMGetParam(variant->function, 7);
|
||||
depth_ptr = LLVMGetParam(variant->function, 8);
|
||||
samplers_ptr = LLVMGetParam(variant->function, 9);
|
||||
|
||||
lp_build_name(x, "x");
|
||||
lp_build_name(y, "y");
|
||||
|
|
@ -185,7 +204,7 @@ shader_generate(struct llvmpipe_screen *screen,
|
|||
lp_build_name(depth_ptr, "depth");
|
||||
lp_build_name(samplers_ptr, "samplers");
|
||||
|
||||
block = LLVMAppendBasicBlock(shader->function, "entry");
|
||||
block = LLVMAppendBasicBlock(variant->function, "entry");
|
||||
builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, block);
|
||||
|
||||
|
|
@ -210,6 +229,12 @@ shader_generate(struct llvmpipe_screen *screen,
|
|||
LLVMValueRef output_ptr = LLVMBuildGEP(builder, color_ptr, &index, 1, "");
|
||||
lp_build_name(outputs[attrib][chan], "color%u.%c", attrib, "rgba"[chan]);
|
||||
LLVMBuildStore(builder, outputs[attrib][chan], output_ptr);
|
||||
|
||||
/* Alpha test */
|
||||
/* XXX: should the alpha reference value be passed separately? */
|
||||
if(cbuf == 0 && chan == 3)
|
||||
mask = lp_build_alpha_test(builder, alpha, type, outputs[attrib][chan], mask);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -228,44 +253,16 @@ shader_generate(struct llvmpipe_screen *screen,
|
|||
LLVMBuildRetVoid(builder);;
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
llvmpipe_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
|
||||
struct lp_fragment_shader *shader;
|
||||
LLVMValueRef fetch_texel;
|
||||
|
||||
shader = CALLOC_STRUCT(lp_fragment_shader);
|
||||
if (!shader)
|
||||
return NULL;
|
||||
|
||||
/* get/save the summary info for this shader */
|
||||
tgsi_scan_shader(templ->tokens, &shader->info);
|
||||
|
||||
/* we need to keep a local copy of the tokens */
|
||||
shader->base.tokens = tgsi_dup_tokens(templ->tokens);
|
||||
|
||||
shader->screen = screen;
|
||||
LLVMRunFunctionPassManager(screen->pass, variant->function);
|
||||
|
||||
#ifdef DEBUG
|
||||
tgsi_dump(templ->tokens, 0);
|
||||
#endif
|
||||
|
||||
shader_generate(screen, shader);
|
||||
|
||||
LLVMRunFunctionPassManager(screen->pass, shader->function);
|
||||
|
||||
#ifdef DEBUG
|
||||
LLVMDumpValue(shader->function);
|
||||
LLVMDumpValue(variant->function);
|
||||
debug_printf("\n");
|
||||
#endif
|
||||
|
||||
if(LLVMVerifyFunction(shader->function, LLVMPrintMessageAction)) {
|
||||
LLVMDumpValue(shader->function);
|
||||
if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) {
|
||||
LLVMDumpValue(variant->function);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
|
@ -278,12 +275,38 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
|
|||
}
|
||||
}
|
||||
|
||||
shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function);
|
||||
variant->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, variant->function);
|
||||
|
||||
#ifdef DEBUG
|
||||
lp_disassemble(shader->jit_function);
|
||||
lp_disassemble(variant->jit_function);
|
||||
#endif
|
||||
|
||||
variant->next = shader->variants;
|
||||
shader->variants = variant;
|
||||
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
llvmpipe_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
|
||||
struct lp_fragment_shader *shader;
|
||||
|
||||
shader = CALLOC_STRUCT(lp_fragment_shader);
|
||||
if (!shader)
|
||||
return NULL;
|
||||
|
||||
/* get/save the summary info for this shader */
|
||||
tgsi_scan_shader(templ->tokens, &shader->info);
|
||||
|
||||
/* we need to keep a local copy of the tokens */
|
||||
shader->base.tokens = tgsi_dup_tokens(templ->tokens);
|
||||
|
||||
shader->screen = screen;
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
@ -303,14 +326,24 @@ void
|
|||
llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct lp_fragment_shader *shader = fs;
|
||||
struct lp_fragment_shader_variant *variant;
|
||||
struct llvmpipe_screen *screen = shader->screen;
|
||||
|
||||
assert(fs != llvmpipe_context(pipe)->fs);
|
||||
|
||||
if(shader->function) {
|
||||
if(shader->jit_function)
|
||||
LLVMFreeMachineCodeForFunction(screen->engine, shader->function);
|
||||
LLVMDeleteFunction(shader->function);
|
||||
|
||||
variant = shader->variants;
|
||||
while(variant) {
|
||||
struct lp_fragment_shader_variant *next = variant->next;
|
||||
|
||||
if(variant->function) {
|
||||
if(variant->jit_function)
|
||||
LLVMFreeMachineCodeForFunction(screen->engine, variant->function);
|
||||
LLVMDeleteFunction(variant->function);
|
||||
}
|
||||
|
||||
FREE(variant);
|
||||
|
||||
variant = next;
|
||||
}
|
||||
|
||||
FREE((void *) shader->base.tokens);
|
||||
|
|
@ -395,3 +428,24 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
|
|||
|
||||
llvmpipe->dirty |= LP_NEW_CONSTANTS;
|
||||
}
|
||||
|
||||
|
||||
void llvmpipe_update_fs(struct llvmpipe_context *lp)
|
||||
{
|
||||
struct lp_fragment_shader *shader = lp->fs;
|
||||
const struct pipe_alpha_state *alpha = &lp->depth_stencil->alpha;
|
||||
struct lp_fragment_shader_variant *variant;
|
||||
|
||||
variant = shader->variants;
|
||||
while(variant) {
|
||||
if(memcmp(&variant->alpha, alpha, sizeof *alpha) == 0)
|
||||
break;
|
||||
|
||||
variant = variant->next;
|
||||
}
|
||||
|
||||
if(!variant)
|
||||
variant = shader_generate(shader->screen, shader, alpha);
|
||||
|
||||
shader->current = variant;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue