Conflicts: src/gallium/drivers/softpipe/sp_quad_fs.c src/gallium/drivers/softpipe/sp_state.h src/gallium/drivers/softpipe/sp_state_fs.ctags/mesa_20090313
endif | endif | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu glut/beos | |||||
SRC_DIRS = gallium mesa glu glut/beos | |||||
GLU_DIRS = sgi | GLU_DIRS = sgi | ||||
DRIVER_DIRS = beos | DRIVER_DIRS = beos | ||||
PROGRAM_DIRS = beos samples redbook demos tests | PROGRAM_DIRS = beos samples redbook demos tests |
APP_LIB_DEPS = -L$(TOP)/lib -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm | APP_LIB_DEPS = -L$(TOP)/lib -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm | ||||
# omit glw lib for now: | # omit glw lib for now: | ||||
SRC_DIRS = mesa glu glut/glx | |||||
SRC_DIRS = gallium mesa glu glut/glx | |||||
APP_LIB_DEPS = -L$(TOP)/lib -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm | APP_LIB_DEPS = -L$(TOP)/lib -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm | ||||
# omit glw lib for now: | # omit glw lib for now: | ||||
SRC_DIRS = mesa glu glut/glx | |||||
SRC_DIRS = gallium mesa glu glut/glx | |||||
# Directories to build | # Directories to build | ||||
LIB_DIR = lib | LIB_DIR = lib | ||||
SRC_DIRS = mesa glu glut/glx glw | |||||
SRC_DIRS = gallium mesa glu glut/glx glw | |||||
GLU_DIRS = sgi | GLU_DIRS = sgi | ||||
DRIVER_DIRS = x11 osmesa | DRIVER_DIRS = x11 osmesa | ||||
# Which subdirs under $(TOP)/progs/ to enter: | # Which subdirs under $(TOP)/progs/ to enter: |
# Directories | # Directories | ||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw | |||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw | |||||
DRIVER_DIRS = dri | DRIVER_DIRS = dri | ||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
WINDOW_SYSTEM=dri | WINDOW_SYSTEM=dri |
CXXFLAGS = $(CFLAGS) | CXXFLAGS = $(CFLAGS) | ||||
# Omitting glw here: | # Omitting glw here: | ||||
SRC_DIRS = mesa glu glut/glx | |||||
SRC_DIRS = gallium mesa glu glut/glx | |||||
MKDEP_OPTIONS = -fdepend -Y | MKDEP_OPTIONS = -fdepend -Y |
endif | endif | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu glut/directfb | |||||
SRC_DIRS = gallium mesa glu glut/directfb | |||||
GLU_DIRS = sgi | GLU_DIRS = sgi | ||||
DRIVER_DIRS = directfb | DRIVER_DIRS = directfb | ||||
PROGRAM_DIRS = demos directfb | PROGRAM_DIRS = demos directfb |
# Directories | # Directories | ||||
ifeq ($(USING_EGL), 1) | ifeq ($(USING_EGL), 1) | ||||
SRC_DIRS = egl glx/x11 mesa glu glut/glx glw | |||||
SRC_DIRS = egl glx/x11 gallium mesa glu glut/glx glw | |||||
PROGRAM_DIRS = egl | PROGRAM_DIRS = egl | ||||
else | else | ||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw | |||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw | |||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
endif | endif | ||||
# gamma are missing because they have not been converted to use the new | # gamma are missing because they have not been converted to use the new | ||||
# interface. | # interface. | ||||
DRI_DIRS = intel_winsys | |||||
DRI_DIRS = intel |
# Directories | # Directories | ||||
ifeq ($(USING_EGL), 1) | ifeq ($(USING_EGL), 1) | ||||
SRC_DIRS = egl glx/x11 mesa glu glut/glx glw | |||||
SRC_DIRS = egl glx/x11 gallium mesa glu glut/glx glw | |||||
PROGRAM_DIRS = egl | PROGRAM_DIRS = egl | ||||
else | else | ||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw | |||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw | |||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
endif | endif | ||||
CFLAGS = -O3 -ffast-math -ansi -pedantic -fPIC -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_BSD_SOURCE -DPTHREADS -DUSE_GLFBDEV_DRIVER | CFLAGS = -O3 -ffast-math -ansi -pedantic -fPIC -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_BSD_SOURCE -DPTHREADS -DUSE_GLFBDEV_DRIVER | ||||
SRC_DIRS = mesa glu glut/fbdev | |||||
SRC_DIRS = gallium mesa glu glut/fbdev | |||||
DRIVER_DIRS = fbdev osmesa | DRIVER_DIRS = fbdev osmesa | ||||
PROGRAM_DIRS = fbdev demos redbook samples | PROGRAM_DIRS = fbdev demos redbook samples | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu | |||||
SRC_DIRS = gallium mesa glu | |||||
DRIVER_DIRS = osmesa | DRIVER_DIRS = osmesa | ||||
PROGRAM_DIRS = osdemos | PROGRAM_DIRS = osdemos | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu | |||||
SRC_DIRS = gallium mesa glu | |||||
DRIVER_DIRS = osmesa | DRIVER_DIRS = osmesa | ||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu | |||||
SRC_DIRS = gallium mesa glu | |||||
DRIVER_DIRS = osmesa | DRIVER_DIRS = osmesa | ||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
# Directories | # Directories | ||||
SRC_DIRS = mesa glu | |||||
SRC_DIRS = gallium mesa glu | |||||
DRIVER_DIRS = osmesa | DRIVER_DIRS = osmesa | ||||
PROGRAM_DIRS = | PROGRAM_DIRS = | ||||
APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm -lpthread | APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm -lpthread | ||||
# Directories | # Directories | ||||
SRC_DIRS = glx/mini mesa glu glut/mini | |||||
SRC_DIRS = glx/mini gallium mesa glu glut/mini | |||||
DRIVER_DIRS = dri | DRIVER_DIRS = dri | ||||
PROGRAM_DIRS = miniglx | PROGRAM_DIRS = miniglx | ||||
linestrip-stipple-wide.c \ | linestrip-stipple-wide.c \ | ||||
linestrip-stipple.c \ | linestrip-stipple.c \ | ||||
linestrip.c \ | linestrip.c \ | ||||
pgon-mode.c \ | |||||
point-clip.c \ | point-clip.c \ | ||||
point-param.c \ | point-param.c \ | ||||
point-sprite.c \ | point-sprite.c \ |
/** | |||||
* Test glPolygonMode. | |||||
* A tri-strip w/ two tris is drawn so that the first tri is front-facing | |||||
* but the second tri is back-facing. | |||||
* Set glPolygonMode differently for the front/back faces | |||||
* | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <math.h> | |||||
#include <GL/glut.h> | |||||
static int Win; | |||||
static GLfloat Zrot = 0; | |||||
static GLboolean FrontFillBackUnfilled = GL_TRUE; | |||||
static GLboolean Lines = GL_TRUE; | |||||
static void | |||||
Draw(void) | |||||
{ | |||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||||
if (FrontFillBackUnfilled) { | |||||
if (Lines) { | |||||
printf("FrontMode = FILL, BackMode = LINE\n"); | |||||
glPolygonMode(GL_BACK, GL_LINE); | |||||
} | |||||
else { | |||||
printf("FrontMode = FILL, BackMode = POINT\n"); | |||||
glPolygonMode(GL_BACK, GL_POINT); | |||||
} | |||||
glPolygonMode(GL_FRONT, GL_FILL); | |||||
} | |||||
else { | |||||
if (Lines) { | |||||
printf("FrontMode = LINE, BackMode = FILL\n"); | |||||
glPolygonMode(GL_FRONT, GL_LINE); | |||||
} | |||||
else { | |||||
printf("FrontMode = POINT, BackMode = FILL\n"); | |||||
glPolygonMode(GL_FRONT, GL_POINT); | |||||
} | |||||
glPolygonMode(GL_BACK, GL_FILL); | |||||
} | |||||
glPushMatrix(); | |||||
glRotatef(Zrot, 0, 0, 1); | |||||
glBegin(GL_TRIANGLE_STRIP); | |||||
glVertex2f(-1, 0); | |||||
glVertex2f( 1, 0); | |||||
glVertex2f(0, 1); | |||||
glVertex2f(0, -1); | |||||
glEnd(); | |||||
glPopMatrix(); | |||||
glutSwapBuffers(); | |||||
} | |||||
static void | |||||
Reshape(int width, int height) | |||||
{ | |||||
glViewport(0, 0, width, height); | |||||
glMatrixMode(GL_PROJECTION); | |||||
glLoadIdentity(); | |||||
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); | |||||
glMatrixMode(GL_MODELVIEW); | |||||
glLoadIdentity(); | |||||
glTranslatef(0.0, 0.0, -15.0); | |||||
} | |||||
static void | |||||
Key(unsigned char key, int x, int y) | |||||
{ | |||||
const GLfloat step = 3.0; | |||||
(void) x; | |||||
(void) y; | |||||
switch (key) { | |||||
case 'p': | |||||
FrontFillBackUnfilled = !FrontFillBackUnfilled; | |||||
break; | |||||
case 'l': | |||||
Lines = !Lines; | |||||
break; | |||||
case 'z': | |||||
Zrot -= step; | |||||
break; | |||||
case 'Z': | |||||
Zrot += step; | |||||
break; | |||||
case 27: | |||||
glutDestroyWindow(Win); | |||||
exit(0); | |||||
break; | |||||
} | |||||
glutPostRedisplay(); | |||||
} | |||||
static void | |||||
Init(void) | |||||
{ | |||||
printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER)); | |||||
glLineWidth(3.0); | |||||
glPointSize(3.0); | |||||
glColor4f(1, 1, 1, 0.8); | |||||
glEnable(GL_BLEND); | |||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||||
printf("Press 'p' to toggle polygon mode\n"); | |||||
} | |||||
int | |||||
main(int argc, char *argv[]) | |||||
{ | |||||
glutInit(&argc, argv); | |||||
glutInitWindowPosition(0, 0); | |||||
glutInitWindowSize(400, 400); | |||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); | |||||
Win = glutCreateWindow(argv[0]); | |||||
glutReshapeFunc(Reshape); | |||||
glutKeyboardFunc(Key); | |||||
glutDisplayFunc(Draw); | |||||
Init(); | |||||
glutMainLoop(); | |||||
return 0; | |||||
} |
TOP = ../.. | |||||
include $(TOP)/configs/current | |||||
SUBDIRS = aux drivers | |||||
default: subdirs | |||||
subdirs: | |||||
@for dir in $(SUBDIRS) ; do \ | |||||
if [ -d $$dir ] ; then \ | |||||
(cd $$dir && $(MAKE)) || exit 1 ; \ | |||||
fi \ | |||||
done | |||||
clean: | |||||
rm -f `find . -name \*.[oa]` |
### Include directories | ### Include directories | ||||
INCLUDES = \ | INCLUDES = \ | ||||
-I. \ | -I. \ | ||||
-I$(TOP)/src/mesa/pipe \ | |||||
-I$(TOP)/src/gallium/include \ | |||||
-I$(TOP)/src/gallium/include/pipe \ | |||||
-I$(TOP)/src/gallium/aux \ | |||||
-I$(TOP)/src/gallium/drivers \ | |||||
-I$(TOP)/src/mesa \ | -I$(TOP)/src/mesa \ | ||||
-I$(TOP)/include \ | -I$(TOP)/include \ | ||||
$(DRIVER_INCLUDES) | $(DRIVER_INCLUDES) | ||||
default: depend symlinks $(LIBNAME) | default: depend symlinks $(LIBNAME) | ||||
$(LIBNAME): $(OBJECTS) Makefile $(TOP)/src/mesa/pipe/Makefile.template | |||||
$(LIBNAME): $(OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template | |||||
$(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS) | $(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS) | ||||
TOP = ../../.. | |||||
include $(TOP)/configs/current | |||||
ifeq ($(CONFIG_NAME), linux-llvm) | |||||
LLVM_DIR = llvm | |||||
endif | |||||
SUBDIRS = pipebuffer $(LLVM_DIR) | |||||
default: subdirs | |||||
subdirs: | |||||
@for dir in $(SUBDIRS) ; do \ | |||||
if [ -d $$dir ] ; then \ | |||||
(cd $$dir && $(MAKE)) || exit 1 ; \ | |||||
fi \ | |||||
done | |||||
clean: | |||||
rm -f `find . -name \*.[oa]` |
static void clip_destroy( struct draw_stage *stage ) | static void clip_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct clipper *clipper = CALLOC_STRUCT(clipper); | struct clipper *clipper = CALLOC_STRUCT(clipper); | ||||
draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES+1 ); | |||||
draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 ); | |||||
clipper->stage.draw = draw; | clipper->stage.draw = draw; | ||||
clipper->stage.point = clip_point; | clipper->stage.point = clip_point; |
/** | /** | ||||
* Allocate space for temporary post-transform vertices, such as for clipping. | * Allocate space for temporary post-transform vertices, such as for clipping. | ||||
*/ | */ | ||||
void draw_alloc_tmps( struct draw_stage *stage, unsigned nr ) | |||||
void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr ) | |||||
{ | { | ||||
assert(!stage->tmp); | assert(!stage->tmp); | ||||
} | } | ||||
void draw_free_tmps( struct draw_stage *stage ) | |||||
void draw_free_temp_verts( struct draw_stage *stage ) | |||||
{ | { | ||||
if (stage->tmp) { | if (stage->tmp) { | ||||
FREE( stage->tmp[0] ); | FREE( stage->tmp[0] ); |
static void cull_destroy( struct draw_stage *stage ) | static void cull_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct cull_stage *cull = CALLOC_STRUCT(cull_stage); | struct cull_stage *cull = CALLOC_STRUCT(cull_stage); | ||||
draw_alloc_tmps( &cull->stage, 0 ); | |||||
draw_alloc_temp_verts( &cull->stage, 0 ); | |||||
cull->stage.draw = draw; | cull->stage.draw = draw; | ||||
cull->stage.next = NULL; | cull->stage.next = NULL; |
static void flatshade_destroy( struct draw_stage *stage ) | static void flatshade_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage); | struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage); | ||||
draw_alloc_tmps( &flatshade->stage, 2 ); | |||||
draw_alloc_temp_verts( &flatshade->stage, 2 ); | |||||
flatshade->stage.draw = draw; | flatshade->stage.draw = draw; | ||||
flatshade->stage.next = NULL; | flatshade->stage.next = NULL; |
static void offset_destroy( struct draw_stage *stage ) | static void offset_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct offset_stage *offset = CALLOC_STRUCT(offset_stage); | struct offset_stage *offset = CALLOC_STRUCT(offset_stage); | ||||
draw_alloc_tmps( &offset->stage, 3 ); | |||||
draw_alloc_temp_verts( &offset->stage, 3 ); | |||||
offset->stage.draw = draw; | offset->stage.draw = draw; | ||||
offset->stage.next = NULL; | offset->stage.next = NULL; |
#include "pipe/p_defines.h" | #include "pipe/p_defines.h" | ||||
#include "x86/rtasm/x86sse.h" | #include "x86/rtasm/x86sse.h" | ||||
#include "pipe/tgsi/exec/tgsi_exec.h" | |||||
#include "tgsi/exec/tgsi_exec.h" | |||||
struct gallivm_prog; | struct gallivm_prog; | ||||
extern struct draw_stage *draw_validate_stage( struct draw_context *context ); | extern struct draw_stage *draw_validate_stage( struct draw_context *context ); | ||||
extern void draw_free_tmps( struct draw_stage *stage ); | |||||
extern void draw_reset_tmps( struct draw_stage *stage ); | |||||
extern void draw_alloc_tmps( struct draw_stage *stage, unsigned nr ); | |||||
extern void draw_free_temp_verts( struct draw_stage *stage ); | |||||
extern void draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr ); | |||||
extern void draw_reset_vertex_ids( struct draw_context *draw ); | extern void draw_reset_vertex_ids( struct draw_context *draw ); | ||||
static void | static void | ||||
stipple_destroy( struct draw_stage *stage ) | stipple_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage); | struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage); | ||||
draw_alloc_tmps( &stipple->stage, 2 ); | |||||
draw_alloc_temp_verts( &stipple->stage, 2 ); | |||||
stipple->stage.draw = draw; | stipple->stage.draw = draw; | ||||
stipple->stage.next = NULL; | stipple->stage.next = NULL; |
static void twoside_destroy( struct draw_stage *stage ) | static void twoside_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage); | struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage); | ||||
draw_alloc_tmps( &twoside->stage, 3 ); | |||||
draw_alloc_temp_verts( &twoside->stage, 3 ); | |||||
twoside->stage.draw = draw; | twoside->stage.draw = draw; | ||||
twoside->stage.next = NULL; | twoside->stage.next = NULL; |
unsigned flags ) | unsigned flags ) | ||||
{ | { | ||||
stage->next->flush( stage->next, flags ); | stage->next->flush( stage->next, flags ); | ||||
stage->tri = unfilled_first_tri; | |||||
} | } | ||||
static void unfilled_destroy( struct draw_stage *stage ) | static void unfilled_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage); | struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage); | ||||
draw_alloc_tmps( &unfilled->stage, 0 ); | |||||
draw_alloc_temp_verts( &unfilled->stage, 0 ); | |||||
unfilled->stage.draw = draw; | unfilled->stage.draw = draw; | ||||
unfilled->stage.next = NULL; | unfilled->stage.next = NULL; |
if(vbuf->vf) | if(vbuf->vf) | ||||
draw_vf_destroy( vbuf->vf ); | draw_vf_destroy( vbuf->vf ); | ||||
if (vbuf->render) | |||||
vbuf->render->destroy( vbuf->render ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
*/ | */ | ||||
#include "pipe/draw/draw_private.h" | |||||
#include "pipe/draw/draw_vertex.h" | |||||
#include "draw/draw_private.h" | |||||
#include "draw/draw_vertex.h" | |||||
/** | /** |
* | * | ||||
**************************************************************************/ | **************************************************************************/ | ||||
/* Author: | |||||
/** | |||||
* Post-transform vertex format info. The vertex_info struct is used by | |||||
* the draw_vbuf code to emit hardware-specific vertex layouts into hw | |||||
* vertex buffers. | |||||
* | |||||
* Author: | |||||
* Brian Paul | * Brian Paul | ||||
*/ | */ | ||||
#include "pipe/p_util.h" | #include "pipe/p_util.h" | ||||
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#if defined(__i386__) || defined(__386__) | #if defined(__i386__) || defined(__386__) | ||||
#include "pipe/tgsi/exec/tgsi_sse2.h" | |||||
#include "tgsi/exec/tgsi_sse2.h" | |||||
#endif | #endif | ||||
#include "draw_private.h" | #include "draw_private.h" | ||||
#include "draw_context.h" | #include "draw_context.h" | ||||
#include "x86/rtasm/x86sse.h" | #include "x86/rtasm/x86sse.h" | ||||
#include "pipe/llvm/gallivm.h" | |||||
#include "llvm/gallivm.h" | |||||
#define DBG_VS 0 | #define DBG_VS 0 |
unsigned j; | unsigned j; | ||||
for (j = 0; j < vf->attr_count; j++) { | for (j = 0; j < vf->attr_count; j++) { | ||||
if(!a[j].isconst) { | |||||
if (!a[j].isconst) { | |||||
a[j].inputptr = (uint8_t *)&vertex->data[a[j].attrib][0]; | a[j].inputptr = (uint8_t *)&vertex->data[a[j].attrib][0]; | ||||
a[j].inputstride = 0; /* XXX: one-vertex-max ATM */ | a[j].inputstride = 0; /* XXX: one-vertex-max ATM */ | ||||
} | } |
/* | /* | ||||
* Copyright 2003 Tungsten Graphics, inc. | |||||
* Copyright 2008 Tungsten Graphics, inc. | |||||
* All Rights Reserved. | * All Rights Reserved. | ||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a | * Permission is hereby granted, free of charge, to any person obtaining a | ||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | * 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 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
*/ | |||||
/** | |||||
* Vertex fetch/store/convert code. This functionality is used in two places: | |||||
* 1. Vertex fetch/convert - to grab vertex data from incoming vertex | |||||
* arrays and convert to format needed by vertex shaders. | |||||
* 2. Vertex store/emit - to convert simple float[][4] vertex attributes | |||||
* (which is the organization used throughout the draw/prim pipeline) to | |||||
* hardware-specific formats and emit into hardware vertex buffers. | |||||
* | |||||
* | * | ||||
* Authors: | * Authors: | ||||
* Keith Whitwell <keithw@tungstengraphics.com> | * Keith Whitwell <keithw@tungstengraphics.com> | ||||
#include "pipe/p_state.h" | #include "pipe/p_state.h" | ||||
#include "draw_vertex.h" | #include "draw_vertex.h" | ||||
#include "draw_private.h" // for vertex_header | |||||
#include "draw_private.h" /* for vertex_header */ | |||||
enum draw_vf_attr_format { | enum draw_vf_attr_format { | ||||
unsigned offset; | unsigned offset; | ||||
}; | }; | ||||
/** XXX this could be moved into draw_vf.c */ | |||||
struct draw_vf_fastpath { | struct draw_vf_fastpath { | ||||
unsigned vertex_stride; | unsigned vertex_stride; | ||||
unsigned attr_count; | unsigned attr_count; | ||||
draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf ); | draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf ); | ||||
/** XXX this type and function could probably be moved into draw_vf.c */ | |||||
struct draw_vf_format_info { | struct draw_vf_format_info { | ||||
const char *name; | const char *name; | ||||
draw_vf_insert_func insert[4]; | draw_vf_insert_func insert[4]; |
float *pos; | float *pos; | ||||
float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0]; | float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0]; | ||||
float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1]; | float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1]; | ||||
const float len = sqrt(dx * dx + dy * dy); | |||||
const float len = (float) sqrt(dx * dx + dy * dy); | |||||
uint i; | uint i; | ||||
dx = dx * half_width / len; | dx = dx * half_width / len; | ||||
} | } | ||||
static void draw_reset_stipple_counter( struct draw_stage *stage ) | |||||
static void wide_reset_stipple_counter( struct draw_stage *stage ) | |||||
{ | { | ||||
stage->next->reset_stipple_counter( stage->next ); | stage->next->reset_stipple_counter( stage->next ); | ||||
} | } | ||||
static void wide_destroy( struct draw_stage *stage ) | static void wide_destroy( struct draw_stage *stage ) | ||||
{ | { | ||||
draw_free_tmps( stage ); | |||||
draw_free_temp_verts( stage ); | |||||
FREE( stage ); | FREE( stage ); | ||||
} | } | ||||
{ | { | ||||
struct wide_stage *wide = CALLOC_STRUCT(wide_stage); | struct wide_stage *wide = CALLOC_STRUCT(wide_stage); | ||||
draw_alloc_tmps( &wide->stage, 4 ); | |||||
draw_alloc_temp_verts( &wide->stage, 4 ); | |||||
wide->stage.draw = draw; | wide->stage.draw = draw; | ||||
wide->stage.next = NULL; | wide->stage.next = NULL; | ||||
wide->stage.line = wide_first_line; | wide->stage.line = wide_first_line; | ||||
wide->stage.tri = passthrough_tri; | wide->stage.tri = passthrough_tri; | ||||
wide->stage.flush = wide_flush; | wide->stage.flush = wide_flush; | ||||
wide->stage.reset_stipple_counter = draw_reset_stipple_counter; | |||||
wide->stage.reset_stipple_counter = wide_reset_stipple_counter; | |||||
wide->stage.destroy = wide_destroy; | wide->stage.destroy = wide_destroy; | ||||
return &wide->stage; | return &wide->stage; |
storagesoa.cpp \ | storagesoa.cpp \ | ||||
instructionssoa.cpp | instructionssoa.cpp | ||||
INC_SOURCES = gallivm_builtins.cpp llvm_base_shader.cpp | |||||
INC_SOURCES = gallivm_builtins.cpp | |||||
CPP_SOURCES = \ | CPP_SOURCES = \ | ||||
$(GALLIVM_SOURCES) | $(GALLIVM_SOURCES) | ||||
### Include directories | ### Include directories | ||||
INCLUDES = \ | INCLUDES = \ | ||||
-I. \ | -I. \ | ||||
-I$(TOP)/src/mesa/pipe \ | |||||
-I$(TOP)/src/gallium/drivers | |||||
-I$(TOP)/src/gallium/aux \ | |||||
-I$(TOP)/src/gallium/include \ | |||||
-I$(TOP)/src/mesa \ | -I$(TOP)/src/mesa \ | ||||
-I$(TOP)/include | -I$(TOP)/include | ||||
gallivm_builtins.cpp: llvm_builtins.c | gallivm_builtins.cpp: llvm_builtins.c | ||||
clang --emit-llvm $< |llvm-as|opt -std-compile-opts|llvm2cpp -gen-contents -o=$@ -f -for=shader -funcname=createGallivmBuiltins | clang --emit-llvm $< |llvm-as|opt -std-compile-opts|llvm2cpp -gen-contents -o=$@ -f -for=shader -funcname=createGallivmBuiltins | ||||
llvm_base_shader.cpp: llvm_entry.c | |||||
clang --emit-llvm $< |llvm-as |opt -std-compile-opts |llvm2cpp -for=Shader -gen-module -o=$@ -f -funcname=createBaseShader | |||||
# Emacs tags | # Emacs tags | ||||
tags: | tags: | ||||
clean: | clean: | ||||
-rm -f *.o */*.o *~ *.so *~ server/*.o | -rm -f *.o */*.o *~ *.so *~ server/*.o | ||||
-rm -f depend depend.bak | -rm -f depend depend.bak | ||||
-rm -f gallivm_builtins.cpp llvm_base_shader.cpp | |||||
-rm -f gallivm_builtins.cpp | |||||
symlinks: | symlinks: | ||||
#include "pipe/p_context.h" | #include "pipe/p_context.h" | ||||
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#include "pipe/tgsi/exec/tgsi_exec.h" | |||||
#include "pipe/tgsi/util/tgsi_dump.h" | |||||
#include "tgsi/exec/tgsi_exec.h" | |||||
#include "tgsi/util/tgsi_dump.h" | |||||
#include <llvm/Module.h> | #include <llvm/Module.h> | ||||
#include <llvm/CallingConv.h> | #include <llvm/CallingConv.h> |
#include "pipe/p_context.h" | #include "pipe/p_context.h" | ||||
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#include "pipe/tgsi/exec/tgsi_exec.h" | |||||
#include "pipe/tgsi/util/tgsi_dump.h" | |||||
#include "tgsi/exec/tgsi_exec.h" | |||||
#include "tgsi/util/tgsi_dump.h" | |||||
#include <llvm/Module.h> | #include <llvm/Module.h> | ||||
#include <llvm/CallingConv.h> | #include <llvm/CallingConv.h> |
#include "instructionssoa.h" | |||||
#include "storagesoa.h" | |||||
#include <llvm/Constants.h> | |||||
using namespace llvm; | |||||
InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func, | |||||
llvm::BasicBlock *block, StorageSoa *storage) | |||||
: m_builder(block), | |||||
m_storage(storage), | |||||
m_idx(0) | |||||
{ | |||||
} | |||||
const char * InstructionsSoa::name(const char *prefix) const | |||||
{ | |||||
++m_idx; | |||||
snprintf(m_name, 32, "%s%d", prefix, m_idx); | |||||
return m_name; | |||||
} | |||||
llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y, | |||||
llvm::Value *z, llvm::Value *w) | |||||
{ | |||||
VectorType *vectorType = VectorType::get(Type::FloatTy, 4); | |||||
Constant *constVector = Constant::getNullValue(vectorType); | |||||
Value *res = m_builder.CreateInsertElement(constVector, x, | |||||
m_storage->constantInt(0), | |||||
name("vecx")); | |||||
res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1), | |||||
name("vecxy")); | |||||
res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2), | |||||
name("vecxyz")); | |||||
if (w) | |||||
res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3), | |||||
name("vecxyzw")); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> InstructionsSoa::arl(const std::vector<llvm::Value*> in) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
//Extract x's | |||||
llvm::Value *x1 = m_builder.CreateExtractElement(in[0], | |||||
m_storage->constantInt(0), | |||||
name("extractX")); | |||||
//cast it to an unsigned int | |||||
x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast")); | |||||
res[0] = x1;//vectorFromVals(x1, x2, x3, x4); | |||||
//only x is valid. the others shouldn't be necessary | |||||
/* | |||||
res[1] = Constant::getNullValue(m_floatVecType); | |||||
res[2] = Constant::getNullValue(m_floatVecType); | |||||
res[3] = Constant::getNullValue(m_floatVecType); | |||||
*/ | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> InstructionsSoa::add(const std::vector<llvm::Value*> in1, | |||||
const std::vector<llvm::Value*> in2) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx")); | |||||
res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy")); | |||||
res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz")); | |||||
res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw")); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> in1, | |||||
const std::vector<llvm::Value*> in2) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx")); | |||||
res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly")); | |||||
res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz")); | |||||
res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw")); | |||||
return res; | |||||
} | |||||
void InstructionsSoa::end() | |||||
{ | |||||
m_builder.CreateRetVoid(); | |||||
} | |||||
std::vector<llvm::Value*> InstructionsSoa::madd(const std::vector<llvm::Value*> in1, | |||||
const std::vector<llvm::Value*> in2, | |||||
const std::vector<llvm::Value*> in3) | |||||
{ | |||||
std::vector<llvm::Value*> res = mul(in1, in2); | |||||
return add(res, in3); | |||||
} | |||||
std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = m_builder.CreateExtractElement(vector, | |||||
m_storage->constantInt(0), | |||||
name("extract1X")); | |||||
res[1] = m_builder.CreateExtractElement(vector, | |||||
m_storage->constantInt(1), | |||||
name("extract2X")); | |||||
res[2] = m_builder.CreateExtractElement(vector, | |||||
m_storage->constantInt(2), | |||||
name("extract3X")); | |||||
res[3] = m_builder.CreateExtractElement(vector, | |||||
m_storage->constantInt(3), | |||||
name("extract4X")); | |||||
return res; | |||||
} |
InstructionsSoa(llvm::Module *mod, llvm::Function *func, | InstructionsSoa(llvm::Module *mod, llvm::Function *func, | ||||
llvm::BasicBlock *block, StorageSoa *storage); | llvm::BasicBlock *block, StorageSoa *storage); | ||||
std::vector<llvm::Value*> arl(const std::vector<llvm::Value*> in); | |||||
std::vector<llvm::Value*> add(const std::vector<llvm::Value*> in1, | std::vector<llvm::Value*> add(const std::vector<llvm::Value*> in1, | ||||
const std::vector<llvm::Value*> in2); | const std::vector<llvm::Value*> in2); | ||||
std::vector<llvm::Value*> madd(const std::vector<llvm::Value*> in1, | |||||
const std::vector<llvm::Value*> in2, | |||||
const std::vector<llvm::Value*> in3); | |||||
std::vector<llvm::Value*> mul(const std::vector<llvm::Value*> in1, | std::vector<llvm::Value*> mul(const std::vector<llvm::Value*> in1, | ||||
const std::vector<llvm::Value*> in2); | const std::vector<llvm::Value*> in2); | ||||
void end(); | void end(); | ||||
std::vector<llvm::Value*> extractVector(llvm::Value *vector); | |||||
private: | private: | ||||
const char * name(const char *prefix) const; | const char * name(const char *prefix) const; | ||||
llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y, | |||||
llvm::Value *z, llvm::Value *w); | |||||
private: | private: | ||||
llvm::LLVMFoldingBuilder m_builder; | llvm::LLVMFoldingBuilder m_builder; | ||||
StorageSoa *m_storage; | |||||
private: | private: | ||||
mutable int m_idx; | mutable int m_idx; | ||||
mutable char m_name[32]; | mutable char m_name[32]; |
/************************************************************************** | |||||
* | |||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. | |||||
* 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 TUNGSTEN GRAPHICS 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. | |||||
* | |||||
**************************************************************************/ | |||||
#include "storagesoa.h" | |||||
#include "gallivm_p.h" | |||||
#include "pipe/p_shader_tokens.h" | |||||
#include "pipe/p_debug.h" | |||||
#include <llvm/BasicBlock.h> | |||||
#include <llvm/Module.h> | |||||
#include <llvm/Value.h> | |||||
#include <llvm/CallingConv.h> | |||||
#include <llvm/Constants.h> | |||||
#include <llvm/DerivedTypes.h> | |||||
#include <llvm/InstrTypes.h> | |||||
#include <llvm/Instructions.h> | |||||
using namespace llvm; | |||||
StorageSoa::StorageSoa(llvm::BasicBlock *block, | |||||
llvm::Value *input, | |||||
llvm::Value *output, | |||||
llvm::Value *consts, | |||||
llvm::Value *temps) | |||||
: m_block(block), | |||||
m_input(input), | |||||
m_output(output), | |||||
m_consts(consts), | |||||
m_temps(temps), | |||||
m_immediates(0), | |||||
m_idx(0) | |||||
{ | |||||
} | |||||
void StorageSoa::addImmediate(float *vec) | |||||
{ | |||||
std::vector<float> vals(4); | |||||
vals[0] = vec[0]; | |||||
vals[1] = vec[1]; | |||||
vals[2] = vec[2]; | |||||
vals[3] = vec[3]; | |||||
m_immediatesToFlush.push_back(vals); | |||||
} | |||||
void StorageSoa::declareImmediates() | |||||
{ | |||||
if (m_immediatesToFlush.empty()) | |||||
return; | |||||
VectorType *vectorType = VectorType::get(Type::FloatTy, 4); | |||||
ArrayType *vectorChannels = ArrayType::get(vectorType, 4); | |||||
ArrayType *arrayType = ArrayType::get(vectorChannels, m_immediatesToFlush.size()); | |||||
m_immediates = new GlobalVariable( | |||||
/*Type=*/arrayType, | |||||
/*isConstant=*/false, | |||||
/*Linkage=*/GlobalValue::ExternalLinkage, | |||||
/*Initializer=*/0, // has initializer, specified below | |||||
/*Name=*/name("immediates"), | |||||
currentModule()); | |||||
std::vector<Constant*> arrayVals; | |||||
for (unsigned int i = 0; i < m_immediatesToFlush.size(); ++i) { | |||||
std::vector<float> vec = m_immediatesToFlush[i]; | |||||
std::vector<float> vals(4); | |||||
std::vector<Constant*> channelArray; | |||||
vals[0] = vec[0]; vals[1] = vec[0]; vals[2] = vec[0]; vals[3] = vec[0]; | |||||
llvm::Constant *xChannel = createConstGlobalVector(vals); | |||||
vals[0] = vec[1]; vals[1] = vec[1]; vals[2] = vec[1]; vals[3] = vec[1]; | |||||
llvm::Constant *yChannel = createConstGlobalVector(vals); | |||||
vals[0] = vec[2]; vals[1] = vec[2]; vals[2] = vec[2]; vals[3] = vec[2]; | |||||
llvm::Constant *zChannel = createConstGlobalVector(vals); | |||||
vals[0] = vec[3]; vals[1] = vec[3]; vals[2] = vec[3]; vals[3] = vec[3]; | |||||
llvm::Constant *wChannel = createConstGlobalVector(vals); | |||||
channelArray.push_back(xChannel); | |||||
channelArray.push_back(yChannel); | |||||
channelArray.push_back(zChannel); | |||||
channelArray.push_back(wChannel); | |||||
Constant *constChannels = ConstantArray::get(vectorChannels, | |||||
channelArray); | |||||
arrayVals.push_back(constChannels); | |||||
} | |||||
Constant *constArray = ConstantArray::get(arrayType, arrayVals); | |||||
m_immediates->setInitializer(constArray); | |||||
m_immediatesToFlush.clear(); | |||||
} | |||||
llvm::Value *StorageSoa::addrElement(int idx) const | |||||
{ | |||||
std::map<int, llvm::Value*>::const_iterator itr = m_addresses.find(idx); | |||||
if (itr == m_addresses.end()) { | |||||
debug_printf("Trying to access invalid shader 'address'\n"); | |||||
return 0; | |||||
} | |||||
llvm::Value * res = (*itr).second; | |||||
res = new LoadInst(res, name("addr"), false, m_block); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::inputElement(llvm::Value *idx) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = element(m_input, idx, 0); | |||||
res[1] = element(m_input, idx, 1); | |||||
res[2] = element(m_input, idx, 2); | |||||
res[3] = element(m_input, idx, 3); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::constElement(llvm::Value *idx) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
llvm::Value *xChannel, *yChannel, *zChannel, *wChannel; | |||||
xChannel = elementPointer(m_consts, idx, 0); | |||||
yChannel = elementPointer(m_consts, idx, 1); | |||||
zChannel = elementPointer(m_consts, idx, 2); | |||||
wChannel = elementPointer(m_consts, idx, 3); | |||||
res[0] = alignedArrayLoad(xChannel); | |||||
res[1] = alignedArrayLoad(yChannel); | |||||
res[2] = alignedArrayLoad(zChannel); | |||||
res[3] = alignedArrayLoad(wChannel); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::outputElement(llvm::Value *idx) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = element(m_output, idx, 0); | |||||
res[1] = element(m_output, idx, 1); | |||||
res[2] = element(m_output, idx, 2); | |||||
res[3] = element(m_output, idx, 3); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::tempElement(llvm::Value *idx) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = element(m_temps, idx, 0); | |||||
res[1] = element(m_temps, idx, 1); | |||||
res[2] = element(m_temps, idx, 2); | |||||
res[3] = element(m_temps, idx, 3); | |||||
return res; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::immediateElement(llvm::Value *idx) | |||||
{ | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = element(m_immediates, idx, 0); | |||||
res[1] = element(m_immediates, idx, 1); | |||||
res[2] = element(m_immediates, idx, 2); | |||||
res[3] = element(m_immediates, idx, 3); | |||||
return res; | |||||
} | |||||
llvm::Value * StorageSoa::elementPointer(llvm::Value *ptr, llvm::Value *index, | |||||
int channel) const | |||||
{ | |||||
std::vector<Value*> indices; | |||||
if (m_immediates == ptr) | |||||
indices.push_back(constantInt(0)); | |||||
indices.push_back(index); | |||||
indices.push_back(constantInt(channel)); | |||||
GetElementPtrInst *getElem = new GetElementPtrInst(ptr, | |||||
indices.begin(), | |||||
indices.end(), | |||||
name("ptr"), | |||||
m_block); | |||||
return getElem; | |||||
} | |||||
llvm::Value * StorageSoa::element(llvm::Value *ptr, llvm::Value *index, | |||||
int channel) const | |||||
{ | |||||
llvm::Value *res = elementPointer(ptr, index, channel); | |||||
LoadInst *load = new LoadInst(res, name("element"), false, m_block); | |||||
//load->setAlignment(8); | |||||
return load; | |||||
} | |||||
const char * StorageSoa::name(const char *prefix) const | |||||
{ | |||||
++m_idx; | |||||
snprintf(m_name, 32, "%s%d", prefix, m_idx); | |||||
return m_name; | |||||
} | |||||
llvm::ConstantInt * StorageSoa::constantInt(int idx) const | |||||
{ | |||||
if (m_constInts.find(idx) != m_constInts.end()) { | |||||
return m_constInts[idx]; | |||||
} | |||||
ConstantInt *constInt = ConstantInt::get(APInt(32, idx)); | |||||
m_constInts[idx] = constInt; | |||||
return constInt; | |||||
} | |||||
llvm::Value *StorageSoa::alignedArrayLoad(llvm::Value *val) | |||||
{ | |||||
VectorType *vectorType = VectorType::get(Type::FloatTy, 4); | |||||
PointerType *vectorPtr = PointerType::get(vectorType, 0); | |||||
CastInst *cast = new BitCastInst(val, vectorPtr, name("toVector"), m_block); | |||||
LoadInst *load = new LoadInst(cast, name("alignLoad"), false, m_block); | |||||
load->setAlignment(8); | |||||
return load; | |||||
} | |||||
llvm::Module * StorageSoa::currentModule() const | |||||
{ | |||||
if (!m_block || !m_block->getParent()) | |||||
return 0; | |||||
return m_block->getParent()->getParent(); | |||||
} | |||||
llvm::Constant * StorageSoa::createConstGlobalVector(const std::vector<float> &vec) | |||||
{ | |||||
VectorType *vectorType = VectorType::get(Type::FloatTy, 4); | |||||
std::vector<Constant*> immValues; | |||||
ConstantFP *constx = ConstantFP::get(Type::FloatTy, APFloat(vec[0])); | |||||
ConstantFP *consty = ConstantFP::get(Type::FloatTy, APFloat(vec[1])); | |||||
ConstantFP *constz = ConstantFP::get(Type::FloatTy, APFloat(vec[2])); | |||||
ConstantFP *constw = ConstantFP::get(Type::FloatTy, APFloat(vec[3])); | |||||
immValues.push_back(constx); | |||||
immValues.push_back(consty); | |||||
immValues.push_back(constz); | |||||
immValues.push_back(constw); | |||||
Constant *constVector = ConstantVector::get(vectorType, immValues); | |||||
return constVector; | |||||
} | |||||
std::vector<llvm::Value*> StorageSoa::load(Argument type, int idx, int swizzle, | |||||
llvm::Value *indIdx) | |||||
{ | |||||
std::vector<llvm::Value*> val(4); | |||||
//if we have an indirect index, always use that | |||||
// if not use the integer offset to create one | |||||
llvm::Value *realIndex = 0; | |||||
if (indIdx) | |||||
realIndex = indIdx; | |||||
else | |||||
realIndex = constantInt(idx); | |||||
debug_printf("XXXXXXXXX realIdx = %p, indIdx = %p\n", realIndex, indIdx); | |||||
switch(type) { | |||||
case Input: | |||||
val = inputElement(realIndex); | |||||
break; | |||||
case Output: | |||||
val = outputElement(realIndex); | |||||
break; | |||||
case Temp: | |||||
val = tempElement(realIndex); | |||||
break; | |||||
case Const: | |||||
val = constElement(realIndex); | |||||
break; | |||||
case Immediate: | |||||
val = immediateElement(realIndex); | |||||
break; | |||||
case Address: | |||||
debug_printf("Address not handled in the load phase!\n"); | |||||
assert(0); | |||||
break; | |||||
} | |||||
if (!gallivm_is_swizzle(swizzle)) | |||||
return val; | |||||
std::vector<llvm::Value*> res(4); | |||||
res[0] = val[gallivm_x_swizzle(swizzle)]; | |||||
res[1] = val[gallivm_y_swizzle(swizzle)]; | |||||
res[2] = val[gallivm_z_swizzle(swizzle)]; | |||||
res[3] = val[gallivm_w_swizzle(swizzle)]; | |||||
return res; | |||||
} | |||||
void StorageSoa::store(Argument type, int idx, const std::vector<llvm::Value*> &val, | |||||
int mask) | |||||
{ | |||||
llvm::Value *out = 0; | |||||
switch(type) { | |||||
case Output: | |||||
out = m_output; | |||||
break; | |||||
case Temp: | |||||
out = m_temps; | |||||
break; | |||||
case Input: | |||||
out = m_input; | |||||
break; | |||||
case Address: { | |||||
llvm::Value *addr = m_addresses[idx]; | |||||
if (!addr) { | |||||
addAddress(idx); | |||||
addr = m_addresses[idx]; | |||||
assert(addr); | |||||
} | |||||
new StoreInst(val[0], addr, false, m_block); | |||||
return; | |||||
break; | |||||
} | |||||
default: | |||||
debug_printf("Can't save output of this type: %d !\n", type); | |||||
assert(0); | |||||
break; | |||||
} | |||||
llvm::Value *realIndex = constantInt(idx); | |||||
if ((mask & TGSI_WRITEMASK_X)) { | |||||
llvm::Value *xChannel = elementPointer(out, realIndex, 0); | |||||
new StoreInst(val[0], xChannel, false, m_block); | |||||
} | |||||
if ((mask & TGSI_WRITEMASK_Y)) { | |||||
llvm::Value *yChannel = elementPointer(out, realIndex, 1); | |||||
new StoreInst(val[1], yChannel, false, m_block); | |||||
} | |||||
if ((mask & TGSI_WRITEMASK_Z)) { | |||||
llvm::Value *zChannel = elementPointer(out, realIndex, 2); | |||||
new StoreInst(val[2], zChannel, false, m_block); | |||||
} | |||||
if ((mask & TGSI_WRITEMASK_W)) { | |||||
llvm::Value *wChannel = elementPointer(out, realIndex, 3); | |||||
new StoreInst(val[3], wChannel, false, m_block); | |||||
} | |||||
} | |||||
void StorageSoa::addAddress(int idx) | |||||
{ | |||||
GlobalVariable *val = new GlobalVariable( | |||||
/*Type=*/IntegerType::get(32), | |||||
/*isConstant=*/false, | |||||
/*Linkage=*/GlobalValue::ExternalLinkage, | |||||
/*Initializer=*/0, // has initializer, specified below | |||||
/*Name=*/name("address"), | |||||
currentModule()); | |||||
val->setInitializer(Constant::getNullValue(IntegerType::get(32))); | |||||
debug_printf("adding to %d\n", idx); | |||||
m_addresses[idx] = val; | |||||
} |
#define STORAGESOA_H | #define STORAGESOA_H | ||||
#include <vector> | #include <vector> | ||||
#include <list> | |||||
#include <map> | #include <map> | ||||
namespace llvm { | namespace llvm { | ||||
class BasicBlock; | class BasicBlock; | ||||
class Constant; | class Constant; | ||||
class ConstantInt; | class ConstantInt; | ||||
class GlobalVariable; | |||||
class LoadInst; | class LoadInst; | ||||
class Value; | class Value; | ||||
class VectorType; | class VectorType; | ||||
class Module; | |||||
} | } | ||||
class StorageSoa | class StorageSoa | ||||
{ | { | ||||
public: | |||||
enum Argument { | |||||
Input, | |||||
Output, | |||||
Temp, | |||||
Const, | |||||
Immediate, | |||||
Address | |||||
}; | |||||
public: | public: | ||||
StorageSoa(llvm::BasicBlock *block, | StorageSoa(llvm::BasicBlock *block, | ||||
llvm::Value *input, | llvm::Value *input, | ||||
llvm::Value *consts, | llvm::Value *consts, | ||||
llvm::Value *temps); | llvm::Value *temps); | ||||
void addImmediate(float *vec); | |||||
llvm::Value * addrElement(int idx) const; | |||||
std::vector<llvm::Value*> load(Argument type, int idx, int swizzle, | |||||
llvm::Value *indIdx =0); | |||||
void store(Argument type, int idx, const std::vector<llvm::Value*> &val, | |||||
int mask); | |||||
std::vector<llvm::Value*> inputElement(int idx, int swizzle, llvm::Value *indIdx =0); | |||||
std::vector<llvm::Value*> constElement(int idx, int swizzle, llvm::Value *indIdx =0); | |||||
std::vector<llvm::Value*> outputElement(int idx, int swizzle, llvm::Value *indIdx =0); | |||||
std::vector<llvm::Value*> tempElement(int idx, int swizzle, llvm::Value *indIdx =0); | |||||
std::vector<llvm::Value*> immediateElement(int idx, int swizzle); | |||||
void addImmediate(float *vec); | |||||
void declareImmediates(); | |||||
void addAddress(int idx); | |||||
llvm::Value *extractIndex(llvm::Value *vec); | |||||
llvm::Value * addrElement(int idx) const; | |||||
void storeOutput(int dstIdx, const std::vector<llvm::Value*> &val, | |||||
int mask); | |||||
void storeTemp(int idx, const std::vector<llvm::Value*> &val, | |||||
int mask); | |||||
void storeAddress(int idx, const std::vector<llvm::Value*> &val, | |||||
int mask); | |||||
llvm::ConstantInt *constantInt(int) const; | |||||
private: | private: | ||||
llvm::Value *elementPointer(llvm::Value *ptr, int index, | |||||
llvm::Value *elementPointer(llvm::Value *ptr, llvm::Value *indIdx, | |||||
int channel) const; | int channel) const; | ||||
llvm::Value *element(llvm::Value *ptr, int index, | |||||
llvm::Value *element(llvm::Value *ptr, llvm::Value *idx, | |||||
int channel) const; | int channel) const; | ||||
const char *name(const char *prefix) const; | const char *name(const char *prefix) const; | ||||
llvm::ConstantInt *constantInt(int) const; | |||||
llvm::Value *alignedArrayLoad(llvm::Value *val); | |||||
llvm::Module *currentModule() const; | |||||
llvm::Constant *createConstGlobalVector(const std::vector<float> &vec); | |||||
std::vector<llvm::Value*> inputElement(llvm::Value *indIdx); | |||||
std::vector<llvm::Value*> constElement(llvm::Value *indIdx); | |||||
std::vector<llvm::Value*> outputElement(llvm::Value *indIdx); | |||||
std::vector<llvm::Value*> tempElement(llvm::Value *indIdx); | |||||
std::vector<llvm::Value*> immediateElement(llvm::Value *indIdx); | |||||
private: | private: | ||||
llvm::BasicBlock *m_block; | llvm::BasicBlock *m_block; | ||||
llvm::Value *m_output; | llvm::Value *m_output; | ||||
llvm::Value *m_consts; | llvm::Value *m_consts; | ||||
llvm::Value *m_temps; | llvm::Value *m_temps; | ||||
llvm::GlobalVariable *m_immediates; | |||||
std::map<int, llvm::Value*> m_addresses; | |||||
std::vector<std::vector<float> > m_immediatesToFlush; | |||||
mutable std::map<int, llvm::ConstantInt*> m_constInts; | mutable std::map<int, llvm::ConstantInt*> m_constInts; | ||||
mutable char m_name[32]; | mutable char m_name[32]; |
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#include "pipe/tgsi/util/tgsi_parse.h" | |||||
#include "pipe/tgsi/exec/tgsi_exec.h" | |||||
#include "pipe/tgsi/util/tgsi_util.h" | |||||
#include "pipe/tgsi/util/tgsi_build.h" | |||||
#include "pipe/tgsi/util/tgsi_dump.h" | |||||
#include "tgsi/util/tgsi_parse.h" | |||||
#include "tgsi/exec/tgsi_exec.h" | |||||
#include "tgsi/util/tgsi_util.h" | |||||
#include "tgsi/util/tgsi_build.h" | |||||
#include "tgsi/util/tgsi_dump.h" | |||||
#include <llvm/Module.h> | #include <llvm/Module.h> | ||||
#include <iostream> | #include <iostream> | ||||
using namespace llvm; | using namespace llvm; | ||||
#include "llvm_base_shader.cpp" | |||||
static inline FunctionType *vertexShaderFunctionType() | static inline FunctionType *vertexShaderFunctionType() | ||||
{ | { | ||||
static void | static void | ||||
translate_declarationir(struct gallivm_ir *, | translate_declarationir(struct gallivm_ir *, | ||||
llvm::Module *, | llvm::Module *, | ||||
StorageSoa *, | |||||
struct tgsi_full_declaration *, | |||||
StorageSoa *storage, | |||||
struct tgsi_full_declaration *decl, | |||||
struct tgsi_full_declaration *) | struct tgsi_full_declaration *) | ||||
{ | { | ||||
if (decl->Declaration.File == TGSI_FILE_ADDRESS) { | |||||
int idx = decl->u.DeclarationRange.First; | |||||
storage->addAddress(idx); | |||||
} | |||||
} | } | ||||
static void | static void | ||||
if (src->SrcRegister.Indirect) { | if (src->SrcRegister.Indirect) { | ||||
indIdx = storage->addrElement(src->SrcRegisterInd.Index); | indIdx = storage->addrElement(src->SrcRegisterInd.Index); | ||||
indIdx = storage->extractIndex(indIdx); | |||||
} | } | ||||
if (src->SrcRegister.File == TGSI_FILE_CONSTANT) { | if (src->SrcRegister.File == TGSI_FILE_CONSTANT) { | ||||
val = storage->constElement(src->SrcRegister.Index, swizzle, indIdx); | |||||
val = storage->load(StorageSoa::Const, | |||||
src->SrcRegister.Index, swizzle, indIdx); | |||||
} else if (src->SrcRegister.File == TGSI_FILE_INPUT) { | } else if (src->SrcRegister.File == TGSI_FILE_INPUT) { | ||||
val = storage->inputElement(src->SrcRegister.Index, swizzle, indIdx); | |||||
val = storage->load(StorageSoa::Input, | |||||
src->SrcRegister.Index, swizzle, indIdx); | |||||
} else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) { | } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) { | ||||
val = storage->tempElement(src->SrcRegister.Index, swizzle); | |||||
val = storage->load(StorageSoa::Temp, | |||||
src->SrcRegister.Index, swizzle, indIdx); | |||||
} else if (src->SrcRegister.File == TGSI_FILE_OUTPUT) { | } else if (src->SrcRegister.File == TGSI_FILE_OUTPUT) { | ||||
val = storage->outputElement(src->SrcRegister.Index, swizzle, indIdx); | |||||
val = storage->load(StorageSoa::Output, | |||||
src->SrcRegister.Index, swizzle, indIdx); | |||||
} else if (src->SrcRegister.File == TGSI_FILE_IMMEDIATE) { | } else if (src->SrcRegister.File == TGSI_FILE_IMMEDIATE) { | ||||
val = storage->immediateElement(src->SrcRegister.Index, swizzle); | |||||
val = storage->load(StorageSoa::Immediate, | |||||
src->SrcRegister.Index, swizzle, indIdx); | |||||
} else { | } else { | ||||
fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File); | fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File); | ||||
return; | return; | ||||
std::vector<llvm::Value*> out(4); | std::vector<llvm::Value*> out(4); | ||||
switch (inst->Instruction.Opcode) { | switch (inst->Instruction.Opcode) { | ||||
case TGSI_OPCODE_ARL: { | case TGSI_OPCODE_ARL: { | ||||
out = instr->arl(inputs[0]); | |||||
} | } | ||||
break; | break; | ||||
case TGSI_OPCODE_MOV: { | case TGSI_OPCODE_MOV: { | ||||
} | } | ||||
break; | break; | ||||
case TGSI_OPCODE_MAD: { | case TGSI_OPCODE_MAD: { | ||||
out = instr->madd(inputs[0], inputs[1], inputs[2]); | |||||
} | } | ||||
break; | break; | ||||
case TGSI_OPCODE_SUB: { | case TGSI_OPCODE_SUB: { | ||||
struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; | struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; | ||||
if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { | if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { | ||||
storage->storeOutput(dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
storage->store(StorageSoa::Output, | |||||
dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
} else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) { | } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) { | ||||
storage->storeTemp(dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
storage->store(StorageSoa::Temp, | |||||
dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
} else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) { | } else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) { | ||||
storage->storeAddress(dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
storage->store(StorageSoa::Address, | |||||
dst->DstRegister.Index, out, dst->DstRegister.WriteMask); | |||||
} else { | } else { | ||||
fprintf(stderr, "ERROR: unsupported LLVM destination!"); | fprintf(stderr, "ERROR: unsupported LLVM destination!"); | ||||
assert(!"wrong destination"); | assert(!"wrong destination"); | ||||
llvm::Module * | llvm::Module * | ||||
tgsi_to_llvm(struct gallivm_ir *ir, const struct tgsi_token *tokens) | tgsi_to_llvm(struct gallivm_ir *ir, const struct tgsi_token *tokens) | ||||
{ | { | ||||
llvm::Module *mod = createBaseShader(); | |||||
llvm::Module *mod = new Module("shader"); | |||||
struct tgsi_parse_context parse; | struct tgsi_parse_context parse; | ||||
struct tgsi_full_instruction fi; | struct tgsi_full_instruction fi; | ||||
struct tgsi_full_declaration fd; | struct tgsi_full_declaration fd; | ||||
break; | break; | ||||
case TGSI_TOKEN_TYPE_INSTRUCTION: | case TGSI_TOKEN_TYPE_INSTRUCTION: | ||||
storage.declareImmediates(); | |||||
translate_instructionir(mod, &storage, &instr, | translate_instructionir(mod, &storage, &instr, | ||||
&parse.FullToken.FullInstruction, | &parse.FullToken.FullInstruction, | ||||
&fi, instno); | &fi, instno); |
ASM_SOURCES = | ASM_SOURCES = | ||||
include ../Makefile.template | |||||
include ../../Makefile.template | |||||
symlinks: | symlinks: | ||||
buf = CALLOC_STRUCT(malloc_buffer); | buf = CALLOC_STRUCT(malloc_buffer); | ||||
if(!buf) | if(!buf) | ||||
return NULL; | return NULL; | ||||
buf->base.base.refcount = 1; | buf->base.base.refcount = 1; | ||||
buf->base.base.alignment = desc->alignment; | buf->base.base.alignment = desc->alignment; | ||||
buf->base.base.usage = desc->usage; | buf->base.base.usage = desc->usage; | ||||
buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment); | buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment); | ||||
if(!buf->data) { | if(!buf->data) { | ||||
FREE(buf); | |||||
align_free(buf); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
#include "pipe/p_state.h" | #include "pipe/p_state.h" | ||||
#include "pipe/p_util.h" | #include "pipe/p_util.h" | ||||
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#include "pipe/tgsi/util/tgsi_parse.h" | |||||
#include "pipe/tgsi/util/tgsi_util.h" | |||||
#include "tgsi/util/tgsi_parse.h" | |||||
#include "tgsi/util/tgsi_util.h" | |||||
#include "tgsi_exec.h" | #include "tgsi_exec.h" | ||||
#define TILE_TOP_LEFT 0 | #define TILE_TOP_LEFT 0 | ||||
if (numDeclarations == maxDeclarations) { | if (numDeclarations == maxDeclarations) { | ||||
declarations = REALLOC(declarations, | declarations = REALLOC(declarations, | ||||
maxDeclarations | maxDeclarations | ||||
* sizeof(struct tgsi_full_instruction), | |||||
* sizeof(struct tgsi_full_declaration), | |||||
(maxDeclarations + 10) | (maxDeclarations + 10) | ||||
* sizeof(struct tgsi_full_instruction)); | |||||
* sizeof(struct tgsi_full_declaration)); | |||||
maxDeclarations += 10; | maxDeclarations += 10; | ||||
} | } | ||||
memcpy(declarations + numDeclarations, | memcpy(declarations + numDeclarations, | ||||
&parse.FullToken.FullInstruction, | |||||
&parse.FullToken.FullDeclaration, | |||||
sizeof(declarations[0])); | sizeof(declarations[0])); | ||||
numDeclarations++; | numDeclarations++; | ||||
break; | break; | ||||
} | } | ||||
/** | |||||
* Evaluate a constant-valued coefficient at the position of the | |||||
* current quad. | |||||
*/ | |||||
static void | static void | ||||
constant_interpolation( | |||||
eval_constant_coef( | |||||
struct tgsi_exec_machine *mach, | struct tgsi_exec_machine *mach, | ||||
unsigned attrib, | unsigned attrib, | ||||
unsigned chan ) | unsigned chan ) | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Evaluate a linear-valued coefficient at the position of the | |||||
* current quad. | |||||
*/ | |||||
static void | static void | ||||
linear_interpolation( | |||||
eval_linear_coef( | |||||
struct tgsi_exec_machine *mach, | struct tgsi_exec_machine *mach, | ||||
unsigned attrib, | unsigned attrib, | ||||
unsigned chan ) | unsigned chan ) | ||||
mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady; | mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady; | ||||
} | } | ||||
/** | |||||
* Evaluate a perspective-valued coefficient at the position of the | |||||
* current quad. | |||||
*/ | |||||
static void | static void | ||||
perspective_interpolation( | |||||
eval_perspective_coef( | |||||
struct tgsi_exec_machine *mach, | struct tgsi_exec_machine *mach, | ||||
unsigned attrib, | unsigned attrib, | ||||
unsigned chan ) | unsigned chan ) | ||||
} | } | ||||
typedef void (* interpolation_func)( | |||||
typedef void (* eval_coef_func)( | |||||
struct tgsi_exec_machine *mach, | struct tgsi_exec_machine *mach, | ||||
unsigned attrib, | unsigned attrib, | ||||
unsigned chan ); | unsigned chan ); | ||||
if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) { | if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) { | ||||
if( decl->Declaration.File == TGSI_FILE_INPUT ) { | if( decl->Declaration.File == TGSI_FILE_INPUT ) { | ||||
unsigned first, last, mask; | unsigned first, last, mask; | ||||
interpolation_func interp; | |||||
eval_coef_func eval; | |||||
assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); | assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); | ||||
switch( decl->Interpolation.Interpolate ) { | switch( decl->Interpolation.Interpolate ) { | ||||
case TGSI_INTERPOLATE_CONSTANT: | case TGSI_INTERPOLATE_CONSTANT: | ||||
interp = constant_interpolation; | |||||
eval = eval_constant_coef; | |||||
break; | break; | ||||
case TGSI_INTERPOLATE_LINEAR: | case TGSI_INTERPOLATE_LINEAR: | ||||
interp = linear_interpolation; | |||||
eval = eval_linear_coef; | |||||
break; | break; | ||||
case TGSI_INTERPOLATE_PERSPECTIVE: | case TGSI_INTERPOLATE_PERSPECTIVE: | ||||
interp = perspective_interpolation; | |||||
eval = eval_perspective_coef; | |||||
break; | break; | ||||
default: | default: | ||||
for( i = first; i <= last; i++ ) { | for( i = first; i <= last; i++ ) { | ||||
for( j = 0; j < NUM_CHANNELS; j++ ) { | for( j = 0; j < NUM_CHANNELS; j++ ) { | ||||
interp( mach, i, j ); | |||||
eval( mach, i, j ); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
for( j = 0; j < NUM_CHANNELS; j++ ) { | for( j = 0; j < NUM_CHANNELS; j++ ) { | ||||
if( mask & (1 << j) ) { | if( mask & (1 << j) ) { | ||||
for( i = first; i <= last; i++ ) { | for( i = first; i <= last; i++ ) { | ||||
interp( mach, i, j ); | |||||
eval( mach, i, j ); | |||||
} | } | ||||
} | } | ||||
} | } |
#include "pipe/p_util.h" | #include "pipe/p_util.h" | ||||
#include "pipe/p_shader_tokens.h" | #include "pipe/p_shader_tokens.h" | ||||
#include "pipe/tgsi/util/tgsi_parse.h" | |||||
#include "pipe/tgsi/util/tgsi_util.h" | |||||
#include "tgsi/util/tgsi_parse.h" | |||||
#include "tgsi/util/tgsi_util.h" | |||||
#include "tgsi_exec.h" | #include "tgsi_exec.h" | ||||
#include "tgsi_sse2.h" | #include "tgsi_sse2.h" | ||||
/************************************************************************** | |||||
* | |||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. | |||||
* 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 TUNGSTEN GRAPHICS 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. | |||||
* | |||||
**************************************************************************/ | |||||
/** | |||||
* TGSI program transformation utility. | |||||
* | |||||
* Authors: Brian Paul | |||||
*/ | |||||
#include "tgsi_transform.h" | |||||
static void | |||||
emit_instruction(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_instruction *inst) | |||||
{ | |||||
uint ti = ctx->ti; | |||||
ti += tgsi_build_full_instruction(inst, | |||||
ctx->tokens_out + ti, | |||||
ctx->header, | |||||
ctx->max_tokens_out - ti); | |||||
ctx->ti = ti; | |||||
} | |||||
static void | |||||
emit_declaration(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_declaration *decl) | |||||
{ | |||||
uint ti = ctx->ti; | |||||
ti += tgsi_build_full_declaration(decl, | |||||
ctx->tokens_out + ti, | |||||
ctx->header, | |||||
ctx->max_tokens_out - ti); | |||||
ctx->ti = ti; | |||||
} | |||||
static void | |||||
emit_immediate(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_immediate *imm) | |||||
{ | |||||
uint ti = ctx->ti; | |||||
ti += tgsi_build_full_immediate(imm, | |||||
ctx->tokens_out + ti, | |||||
ctx->header, | |||||
ctx->max_tokens_out - ti); | |||||
ctx->ti = ti; | |||||
} | |||||
/** | |||||
* Apply user-defined transformations to the input shader to produce | |||||
* the output shader. | |||||
* For example, a register search-and-replace operation could be applied | |||||
* by defining a transform_instruction() callback that examined and changed | |||||
* the instruction src/dest regs. | |||||
* | |||||
* \return number of tokens emitted | |||||
*/ | |||||
int | |||||
tgsi_transform_shader(const struct tgsi_token *tokens_in, | |||||
struct tgsi_token *tokens_out, | |||||
uint max_tokens_out, | |||||
struct tgsi_transform_context *ctx) | |||||
{ | |||||
uint procType; | |||||
/* input shader */ | |||||
struct tgsi_parse_context parse; | |||||
/* output shader */ | |||||
struct tgsi_processor *processor; | |||||
/** | |||||
** callback context init | |||||
**/ | |||||
ctx->emit_instruction = emit_instruction; | |||||
ctx->emit_declaration = emit_declaration; | |||||
ctx->emit_immediate = emit_immediate; | |||||
ctx->tokens_out = tokens_out; | |||||
ctx->max_tokens_out = max_tokens_out; | |||||
/** | |||||
** Setup to begin parsing input shader | |||||
**/ | |||||
if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) { | |||||
debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n"); | |||||
return -1; | |||||
} | |||||
procType = parse.FullHeader.Processor.Processor; | |||||
assert(procType == TGSI_PROCESSOR_FRAGMENT || | |||||
procType == TGSI_PROCESSOR_VERTEX || | |||||
procType == TGSI_PROCESSOR_GEOMETRY); | |||||
/** | |||||
** Setup output shader | |||||
**/ | |||||
*(struct tgsi_version *) &tokens_out[0] = tgsi_build_version(); | |||||
ctx->header = (struct tgsi_header *) (tokens_out + 1); | |||||
*ctx->header = tgsi_build_header(); | |||||
processor = (struct tgsi_processor *) (tokens_out + 2); | |||||
*processor = tgsi_build_processor( procType, ctx->header ); | |||||
ctx->ti = 3; | |||||
/** | |||||
** Loop over incoming program tokens/instructions | |||||
*/ | |||||
while( !tgsi_parse_end_of_tokens( &parse ) ) { | |||||
tgsi_parse_token( &parse ); | |||||
switch( parse.FullToken.Token.Type ) { | |||||
case TGSI_TOKEN_TYPE_INSTRUCTION: | |||||
{ | |||||
struct tgsi_full_instruction *fullinst | |||||
= &parse.FullToken.FullInstruction; | |||||
if (ctx->transform_instruction) | |||||
ctx->transform_instruction(ctx, fullinst); | |||||
else | |||||
ctx->emit_instruction(ctx, fullinst); | |||||
} | |||||
break; | |||||
case TGSI_TOKEN_TYPE_DECLARATION: | |||||
{ | |||||
struct tgsi_full_declaration *fulldecl | |||||
= &parse.FullToken.FullDeclaration; | |||||
if (ctx->transform_declaration) | |||||
ctx->transform_declaration(ctx, fulldecl); | |||||
else | |||||
ctx->emit_declaration(ctx, fulldecl); | |||||
} | |||||
break; | |||||
case TGSI_TOKEN_TYPE_IMMEDIATE: | |||||
{ | |||||
struct tgsi_full_immediate *fullimm | |||||
= &parse.FullToken.FullImmediate; | |||||
if (ctx->transform_immediate) | |||||
ctx->transform_immediate(ctx, fullimm); | |||||
else | |||||
ctx->emit_immediate(ctx, fullimm); | |||||
} | |||||
break; | |||||
default: | |||||
assert( 0 ); | |||||
} | |||||
} | |||||
if (ctx->epilog) { | |||||
ctx->epilog(ctx); | |||||
} | |||||
tgsi_parse_free (&parse); | |||||
return ctx->ti; | |||||
} |
/************************************************************************** | |||||
* | |||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. | |||||
* 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 TUNGSTEN GRAPHICS 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. | |||||
* | |||||
**************************************************************************/ | |||||
#ifndef TGSI_TRANSFORM_H | |||||
#define TGSI_TRANSFORM_H | |||||
#include "pipe/p_util.h" | |||||
#include "pipe/p_shader_tokens.h" | |||||
#include "tgsi/util/tgsi_parse.h" | |||||
#include "tgsi/util/tgsi_build.h" | |||||
/** | |||||
* Subclass this to add caller-specific data | |||||
*/ | |||||
struct tgsi_transform_context | |||||
{ | |||||
/**** PUBLIC ***/ | |||||
/** | |||||
* User-defined callbacks invoked per instruction. | |||||
*/ | |||||
void (*transform_instruction)(struct tgsi_transform_context *ctx, | |||||
struct tgsi_full_instruction *inst); | |||||
void (*transform_declaration)(struct tgsi_transform_context *ctx, | |||||
struct tgsi_full_declaration *decl); | |||||
void (*transform_immediate)(struct tgsi_transform_context *ctx, | |||||
struct tgsi_full_immediate *imm); | |||||
/** | |||||
* Called at end of input program to allow caller to append extra | |||||
* instructions. Return number of tokens emitted. | |||||
*/ | |||||
void (*epilog)(struct tgsi_transform_context *ctx); | |||||
/*** PRIVATE ***/ | |||||
/** | |||||
* These are setup by tgsi_transform_shader() and cannot be overridden. | |||||
* Meant to be called from in the above user callback functions. | |||||
*/ | |||||
void (*emit_instruction)(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_instruction *inst); | |||||
void (*emit_declaration)(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_declaration *decl); | |||||
void (*emit_immediate)(struct tgsi_transform_context *ctx, | |||||
const struct tgsi_full_immediate *imm); | |||||
struct tgsi_header *header; | |||||
uint max_tokens_out; | |||||
struct tgsi_token *tokens_out; | |||||
uint ti; | |||||
}; | |||||
extern int | |||||
tgsi_transform_shader(const struct tgsi_token *tokens_in, | |||||
struct tgsi_token *tokens_out, | |||||
uint max_tokens_out, | |||||
struct tgsi_transform_context *ctx); | |||||
#endif /* TGSI_TRANSFORM_H */ |