Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
Conflicts: configs/linux-dri src/mesa/pipe/Makefile
This commit is contained in:
+1
-1
@@ -86,7 +86,7 @@ else
|
||||
endif
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu glut/beos
|
||||
SRC_DIRS = gallium mesa glu glut/beos
|
||||
GLU_DIRS = sgi
|
||||
DRIVER_DIRS = beos
|
||||
PROGRAM_DIRS = beos samples redbook demos tests
|
||||
|
||||
+1
-1
@@ -25,5 +25,5 @@ GLW_LIB_DEPS = -L/usr/X11R6/lib -lX11 -lXt $(TOP)/lib/GL.dylib
|
||||
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:
|
||||
SRC_DIRS = mesa glu glut/glx
|
||||
SRC_DIRS = gallium mesa glu glut/glx
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ GLW_LIB_DEPS = -L/usr/X11R6/lib -lX11 -lXt $(TOP)/lib/GL.dylib
|
||||
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:
|
||||
SRC_DIRS = mesa glu glut/glx
|
||||
SRC_DIRS = gallium mesa glu glut/glx
|
||||
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ GLW_SOURCES = GLwDrawA.c
|
||||
|
||||
# Directories to build
|
||||
LIB_DIR = lib
|
||||
SRC_DIRS = mesa glu glut/glx glw
|
||||
SRC_DIRS = gallium mesa glu glut/glx glw
|
||||
GLU_DIRS = sgi
|
||||
DRIVER_DIRS = x11 osmesa
|
||||
# Which subdirs under $(TOP)/progs/ to enter:
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -L/usr/X11R6/lib -lGL -lXt -lX11
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw
|
||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw
|
||||
DRIVER_DIRS = dri
|
||||
PROGRAM_DIRS =
|
||||
WINDOW_SYSTEM=dri
|
||||
|
||||
+4
-2
@@ -21,7 +21,7 @@ CFLAGS = $(OPT_FLAGS) -Wall -Winline -fPIC -m32 -mabi=altivec -maltivec -I. -I$(
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
# Omitting glw here:
|
||||
SRC_DIRS = mesa glu glut/glx
|
||||
SRC_DIRS = gallium mesa glu glut/glx
|
||||
|
||||
|
||||
MKDEP_OPTIONS = -fdepend -Y
|
||||
@@ -36,7 +36,9 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread \
|
||||
|
||||
SPU_CC = spu-gcc
|
||||
|
||||
SPU_CFLAGS = $(OPT_FLAGS) -W -Wall -Winline -Wmissing-prototypes -Wno-main -I. -I $(SDK)/spu/include -include spu_intrinsics.h -I $(TOP)/src/mesa/
|
||||
SPU_CFLAGS = $(OPT_FLAGS) -W -Wall -Winline -Wmissing-prototypes -Wno-main \
|
||||
-I. -I$(SDK)/spu/include -I$(TOP)/src/mesa/ $(INCLUDE_DIRS) \
|
||||
-include spu_intrinsics.h
|
||||
|
||||
SPU_LFLAGS = -L$(SDK)/spu/lib -Wl,-N -lmisc
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ ifeq ($(HAVE_X86), yes)
|
||||
endif
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu glut/directfb
|
||||
SRC_DIRS = gallium mesa glu glut/directfb
|
||||
GLU_DIRS = sgi
|
||||
DRIVER_DIRS = directfb
|
||||
PROGRAM_DIRS = demos directfb
|
||||
|
||||
+3
-3
@@ -54,10 +54,10 @@ USING_EGL=0
|
||||
|
||||
# Directories
|
||||
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
|
||||
else
|
||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw
|
||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw
|
||||
PROGRAM_DIRS =
|
||||
endif
|
||||
|
||||
@@ -66,4 +66,4 @@ WINDOW_SYSTEM=dri
|
||||
|
||||
# gamma are missing because they have not been converted to use the new
|
||||
# interface.
|
||||
DRI_DIRS = nouveau_winsys
|
||||
DRI_DIRS = intel
|
||||
|
||||
@@ -53,10 +53,10 @@ USING_EGL=0
|
||||
|
||||
# Directories
|
||||
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
|
||||
else
|
||||
SRC_DIRS = glx/x11 mesa glu glut/glx glw
|
||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw
|
||||
PROGRAM_DIRS =
|
||||
endif
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ CONFIG_NAME = linux-fbdev
|
||||
|
||||
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
|
||||
PROGRAM_DIRS = fbdev demos redbook samples
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ CXXFLAGS = -O3 -ansi -pedantic -fPIC -ffast-math -D_POSIX_SOURCE -D_POSIX_C_SOUR
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu
|
||||
SRC_DIRS = gallium mesa glu
|
||||
DRIVER_DIRS = osmesa
|
||||
PROGRAM_DIRS = osdemos
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ OSMESA_LIB_NAME = libOSMesa16.so
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu
|
||||
SRC_DIRS = gallium mesa glu
|
||||
DRIVER_DIRS = osmesa
|
||||
PROGRAM_DIRS =
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ OSMESA_LIB_NAME = libOSMesa16.a
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu
|
||||
SRC_DIRS = gallium mesa glu
|
||||
DRIVER_DIRS = osmesa
|
||||
PROGRAM_DIRS =
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ OSMESA_LIB_NAME = libOSMesa32.so
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = mesa glu
|
||||
SRC_DIRS = gallium mesa glu
|
||||
DRIVER_DIRS = osmesa
|
||||
PROGRAM_DIRS =
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ GLUT_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) -lm
|
||||
APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm -lpthread
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = glx/mini mesa glu glut/mini
|
||||
SRC_DIRS = glx/mini gallium mesa glu glut/mini
|
||||
DRIVER_DIRS = dri
|
||||
PROGRAM_DIRS = miniglx
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ SOURCES = \
|
||||
linestrip-stipple-wide.c \
|
||||
linestrip-stipple.c \
|
||||
linestrip.c \
|
||||
pgon-mode.c \
|
||||
point-clip.c \
|
||||
point-param.c \
|
||||
point-sprite.c \
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
SUBDIRS = auxiliary 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]`
|
||||
@@ -15,7 +15,10 @@ OBJECTS = $(C_SOURCES:.c=.o) \
|
||||
### Include directories
|
||||
INCLUDES = \
|
||||
-I. \
|
||||
-I$(TOP)/src/mesa/pipe \
|
||||
-I$(TOP)/src/gallium/include \
|
||||
-I$(TOP)/src/gallium/include/pipe \
|
||||
-I$(TOP)/src/gallium/auxiliary \
|
||||
-I$(TOP)/src/gallium/drivers \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/include \
|
||||
$(DRIVER_INCLUDES)
|
||||
@@ -38,7 +41,7 @@ INCLUDES = \
|
||||
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)
|
||||
|
||||
|
||||
@@ -2,16 +2,11 @@ TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
ifeq ($(CONFIG_NAME), linux-cell)
|
||||
CELL_DIR = cell
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NAME), linux-llvm)
|
||||
LLVM_DIR = llvm
|
||||
endif
|
||||
|
||||
SUBDIRS = softpipe i915simple i965simple nv30 nv40 nv50 failover pipebuffer \
|
||||
$(CELL_DIR) $(LLVM_DIR)
|
||||
SUBDIRS = pipebuffer $(LLVM_DIR)
|
||||
|
||||
|
||||
default: subdirs
|
||||
@@ -0,0 +1,2 @@
|
||||
default:
|
||||
cd ../../../mesa ; make
|
||||
@@ -459,7 +459,7 @@ static void clip_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void clip_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
|
||||
{
|
||||
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.point = clip_point;
|
||||
@@ -242,7 +242,7 @@ draw_convert_wide_lines(struct draw_context *draw, boolean enable)
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -260,7 +260,7 @@ void draw_alloc_tmps( struct draw_stage *stage, unsigned nr )
|
||||
}
|
||||
|
||||
|
||||
void draw_free_tmps( struct draw_stage *stage )
|
||||
void draw_free_temp_verts( struct draw_stage *stage )
|
||||
{
|
||||
if (stage->tmp) {
|
||||
FREE( stage->tmp[0] );
|
||||
@@ -123,7 +123,7 @@ static void cull_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void cull_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -176,7 +176,7 @@ static void flatshade_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void flatshade_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -159,7 +159,7 @@ static void offset_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void offset_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "pipe/tgsi/exec/tgsi_exec.h"
|
||||
#include "tgsi/exec/tgsi_exec.h"
|
||||
|
||||
|
||||
struct gallivm_prog;
|
||||
@@ -128,13 +128,25 @@ struct draw_stage
|
||||
* Private version of the compiled vertex_shader
|
||||
*/
|
||||
struct draw_vertex_shader {
|
||||
|
||||
/* This member will disappear shortly:
|
||||
*/
|
||||
const struct pipe_shader_state *state;
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
struct x86_function sse2_program;
|
||||
#endif
|
||||
#ifdef MESA_LLVM
|
||||
struct gallivm_prog *llvm_prog;
|
||||
#endif
|
||||
|
||||
void (*prepare)( struct draw_vertex_shader *shader,
|
||||
struct draw_context *draw );
|
||||
|
||||
/* Run the shader - this interface will get cleaned up in the
|
||||
* future:
|
||||
*/
|
||||
void (*run)( struct draw_vertex_shader *shader,
|
||||
struct draw_context *draw,
|
||||
const unsigned *elts,
|
||||
unsigned count,
|
||||
struct vertex_header *vOut[] );
|
||||
|
||||
|
||||
void (*delete)( struct draw_vertex_shader * );
|
||||
};
|
||||
|
||||
|
||||
@@ -176,7 +188,7 @@ struct draw_context
|
||||
struct pipe_viewport_state viewport;
|
||||
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
|
||||
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
|
||||
const struct draw_vertex_shader *vertex_shader;
|
||||
struct draw_vertex_shader *vertex_shader;
|
||||
|
||||
uint num_vs_outputs; /**< convenience, from vertex_shader */
|
||||
|
||||
@@ -201,6 +213,7 @@ struct draw_context
|
||||
|
||||
boolean convert_wide_points; /**< convert wide points to tris? */
|
||||
boolean convert_wide_lines; /**< convert side lines to tris? */
|
||||
boolean use_sse;
|
||||
|
||||
unsigned reduced_prim;
|
||||
|
||||
@@ -255,11 +268,10 @@ struct draw_context
|
||||
unsigned queue_nr;
|
||||
} pq;
|
||||
|
||||
int use_sse : 1;
|
||||
#ifdef MESA_LLVM
|
||||
struct gallivm_cpu_engine *engine;
|
||||
#endif
|
||||
|
||||
|
||||
/* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private.
|
||||
*/
|
||||
struct gallivm_cpu_engine *engine;
|
||||
void *driver_private;
|
||||
};
|
||||
|
||||
@@ -276,9 +288,9 @@ extern struct draw_stage *draw_wide_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 );
|
||||
|
||||
@@ -290,11 +302,7 @@ extern void draw_vertex_cache_invalidate( struct draw_context *draw );
|
||||
extern void draw_vertex_cache_unreference( struct draw_context *draw );
|
||||
extern void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw );
|
||||
|
||||
|
||||
extern void draw_vertex_shader_queue_flush( struct draw_context *draw );
|
||||
#ifdef MESA_LLVM
|
||||
extern void draw_vertex_shader_queue_flush_llvm( struct draw_context *draw );
|
||||
#endif
|
||||
|
||||
struct tgsi_exec_machine;
|
||||
|
||||
@@ -212,6 +212,7 @@ passthrough_tri(struct draw_stage *stage, struct prim_header *header)
|
||||
static void
|
||||
stipple_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -223,7 +224,7 @@ struct draw_stage *draw_stipple_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -176,7 +176,7 @@ static void twoside_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void twoside_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -165,6 +165,8 @@ static void unfilled_flush( struct draw_stage *stage,
|
||||
unsigned flags )
|
||||
{
|
||||
stage->next->flush( stage->next, flags );
|
||||
|
||||
stage->tri = unfilled_first_tri;
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +178,7 @@ static void unfilled_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void unfilled_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -188,7 +190,7 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -523,6 +523,9 @@ static void vbuf_destroy( struct draw_stage *stage )
|
||||
if(vbuf->vf)
|
||||
draw_vf_destroy( vbuf->vf );
|
||||
|
||||
if (vbuf->render)
|
||||
vbuf->render->destroy( vbuf->render );
|
||||
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/draw/draw_private.h"
|
||||
#include "pipe/draw/draw_vertex.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_vertex.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,12 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
#include "draw_vs.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run the vertex shader on all vertices in the vertex queue.
|
||||
* Called by the draw module when the vertx cache needs to be flushed.
|
||||
*/
|
||||
void
|
||||
draw_vertex_shader_queue_flush(struct draw_context *draw)
|
||||
{
|
||||
struct draw_vertex_shader *shader = draw->vertex_shader;
|
||||
unsigned i;
|
||||
|
||||
assert(draw->vs.queue_nr != 0);
|
||||
|
||||
/* XXX: do this on statechange:
|
||||
*/
|
||||
shader->prepare( shader, draw );
|
||||
|
||||
// fprintf(stderr, " q(%d) ", draw->vs.queue_nr );
|
||||
|
||||
/* run vertex shader on vertex cache entries, four per invokation */
|
||||
for (i = 0; i < draw->vs.queue_nr; i += 4) {
|
||||
struct vertex_header *dests[4];
|
||||
unsigned elts[4];
|
||||
int j, n = MIN2(4, draw->vs.queue_nr - i);
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
elts[j] = draw->vs.queue[i + j].elt;
|
||||
dests[j] = draw->vs.queue[i + j].dest;
|
||||
}
|
||||
|
||||
for ( ; j < 4; j++) {
|
||||
elts[j] = elts[0];
|
||||
dests[j] = dests[0];
|
||||
}
|
||||
|
||||
assert(n > 0);
|
||||
assert(n <= 4);
|
||||
|
||||
shader->run(shader, draw, elts, n, dests);
|
||||
}
|
||||
|
||||
draw->vs.queue_nr = 0;
|
||||
}
|
||||
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vertex_shader(struct draw_context *draw,
|
||||
const struct pipe_shader_state *shader)
|
||||
{
|
||||
struct draw_vertex_shader *vs;
|
||||
|
||||
vs = draw_create_vs_llvm( draw, shader );
|
||||
if (vs)
|
||||
return vs;
|
||||
|
||||
vs = draw_create_vs_sse( draw, shader );
|
||||
if (vs)
|
||||
return vs;
|
||||
|
||||
vs = draw_create_vs_exec( draw, shader );
|
||||
assert(vs);
|
||||
return vs;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
draw_bind_vertex_shader(struct draw_context *draw,
|
||||
struct draw_vertex_shader *dvs)
|
||||
{
|
||||
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
|
||||
|
||||
draw->vertex_shader = dvs;
|
||||
draw->num_vs_outputs = dvs->state->num_outputs;
|
||||
|
||||
tgsi_exec_machine_init(&draw->machine);
|
||||
|
||||
dvs->prepare( dvs, draw );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
draw_delete_vertex_shader(struct draw_context *draw,
|
||||
struct draw_vertex_shader *dvs)
|
||||
{
|
||||
dvs->delete( dvs );
|
||||
}
|
||||
@@ -370,7 +370,7 @@ void draw_vf_emit_vertex( struct draw_vertex_fetch *vf,
|
||||
unsigned 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].inputstride = 0; /* XXX: one-vertex-max ATM */
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003 Tungsten Graphics, inc.
|
||||
* Copyright 2008 Tungsten Graphics, inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -20,6 +20,17 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* Keith Whitwell <keithw@tungstengraphics.com>
|
||||
@@ -33,7 +44,7 @@
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "draw_vertex.h"
|
||||
#include "draw_private.h" // for vertex_header
|
||||
#include "draw_private.h" /* for vertex_header */
|
||||
|
||||
|
||||
enum draw_vf_attr_format {
|
||||
@@ -181,6 +192,7 @@ struct draw_vf_attr_type {
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
/** XXX this could be moved into draw_vf.c */
|
||||
struct draw_vf_fastpath {
|
||||
unsigned vertex_stride;
|
||||
unsigned attr_count;
|
||||
@@ -209,6 +221,7 @@ void
|
||||
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 {
|
||||
const char *name;
|
||||
draw_vf_insert_func insert[4];
|
||||
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#ifndef DRAW_VS_H
|
||||
#define DRAW_VS_H
|
||||
|
||||
struct draw_vertex_shader;
|
||||
struct draw_context;
|
||||
struct pipe_shader_state;
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_exec(struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ);
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_sse(struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ);
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_llvm(struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
#include "draw_vs.h"
|
||||
|
||||
|
||||
static INLINE unsigned
|
||||
compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
|
||||
{
|
||||
unsigned mask = 0;
|
||||
unsigned i;
|
||||
|
||||
/* Do the hardwired planes first:
|
||||
*/
|
||||
if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
|
||||
if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
|
||||
if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
|
||||
if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
|
||||
if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
|
||||
if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
|
||||
|
||||
/* Followed by any remaining ones:
|
||||
*/
|
||||
for (i = 6; i < nr; i++) {
|
||||
if (dot4(clip, plane[i]) < 0)
|
||||
mask |= (1<<i);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vs_exec_prepare( struct draw_vertex_shader *shader,
|
||||
struct draw_context *draw )
|
||||
{
|
||||
/* specify the vertex program to interpret/execute */
|
||||
tgsi_exec_machine_bind_shader(&draw->machine,
|
||||
shader->state->tokens,
|
||||
PIPE_MAX_SAMPLERS,
|
||||
NULL /*samplers*/ );
|
||||
|
||||
draw_update_vertex_fetch( draw );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transform vertices with the current vertex program/shader
|
||||
* Up to four vertices can be shaded at a time.
|
||||
* \param vbuffer the input vertex data
|
||||
* \param elts indexes of four input vertices
|
||||
* \param count number of vertices to shade [1..4]
|
||||
* \param vOut array of pointers to four output vertices
|
||||
*/
|
||||
static void
|
||||
vs_exec_run( struct draw_vertex_shader *shader,
|
||||
struct draw_context *draw,
|
||||
const unsigned *elts,
|
||||
unsigned count,
|
||||
struct vertex_header *vOut[] )
|
||||
{
|
||||
struct tgsi_exec_machine *machine = &draw->machine;
|
||||
unsigned int j;
|
||||
|
||||
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_ATTRIB_MAX);
|
||||
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_ATTRIB_MAX);
|
||||
const float *scale = draw->viewport.scale;
|
||||
const float *trans = draw->viewport.translate;
|
||||
|
||||
assert(count <= 4);
|
||||
assert(draw->vertex_shader->state->output_semantic_name[0]
|
||||
== TGSI_SEMANTIC_POSITION);
|
||||
|
||||
machine->Consts = (float (*)[4]) draw->user.constants;
|
||||
machine->Inputs = ALIGN16_ASSIGN(inputs);
|
||||
machine->Outputs = ALIGN16_ASSIGN(outputs);
|
||||
|
||||
draw->vertex_fetch.fetch_func( draw, machine, elts, count );
|
||||
|
||||
/* run interpreter */
|
||||
tgsi_exec_machine_run( machine );
|
||||
|
||||
|
||||
/* store machine results */
|
||||
for (j = 0; j < count; j++) {
|
||||
unsigned slot;
|
||||
float x, y, z, w;
|
||||
|
||||
/* Handle attr[0] (position) specially:
|
||||
*
|
||||
* XXX: Computing the clipmask should be done in the vertex
|
||||
* program as a set of DP4 instructions appended to the
|
||||
* user-provided code.
|
||||
*/
|
||||
x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
|
||||
y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
|
||||
z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
|
||||
w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
|
||||
|
||||
vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
|
||||
vOut[j]->edgeflag = 1;
|
||||
|
||||
/* divide by w */
|
||||
w = 1.0f / w;
|
||||
x *= w;
|
||||
y *= w;
|
||||
z *= w;
|
||||
|
||||
/* Viewport mapping */
|
||||
vOut[j]->data[0][0] = x * scale[0] + trans[0];
|
||||
vOut[j]->data[0][1] = y * scale[1] + trans[1];
|
||||
vOut[j]->data[0][2] = z * scale[2] + trans[2];
|
||||
vOut[j]->data[0][3] = w;
|
||||
|
||||
/* Remaining attributes are packed into sequential post-transform
|
||||
* vertex attrib slots.
|
||||
*/
|
||||
for (slot = 1; slot < draw->num_vs_outputs; slot++) {
|
||||
vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
|
||||
vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
|
||||
vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
|
||||
vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
|
||||
}
|
||||
} /* loop over vertices */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
vs_exec_delete( struct draw_vertex_shader *dvs )
|
||||
{
|
||||
FREE( dvs );
|
||||
}
|
||||
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_exec(struct draw_context *draw,
|
||||
const struct pipe_shader_state *state)
|
||||
{
|
||||
struct draw_vertex_shader *vs = CALLOC_STRUCT( draw_vertex_shader );
|
||||
|
||||
if (vs == NULL)
|
||||
return NULL;
|
||||
|
||||
vs->state = state;
|
||||
vs->prepare = vs_exec_prepare;
|
||||
vs->run = vs_exec_run;
|
||||
vs->delete = vs_exec_delete;
|
||||
|
||||
return vs;
|
||||
}
|
||||
+70
-157
@@ -27,23 +27,25 @@
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Zack Rusin
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
#include "pipe/tgsi/exec/tgsi_sse2.h"
|
||||
#endif
|
||||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
#include "draw_vs.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "pipe/llvm/gallivm.h"
|
||||
#ifdef MESA_LLVM
|
||||
|
||||
#include "llvm/gallivm.h"
|
||||
|
||||
#define DBG_VS 0
|
||||
struct draw_llvm_vertex_shader {
|
||||
struct draw_vertex_shader base;
|
||||
struct gallivm_prog *llvm_prog;
|
||||
};
|
||||
|
||||
|
||||
static INLINE unsigned
|
||||
@@ -72,11 +74,14 @@ compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
|
||||
}
|
||||
|
||||
|
||||
typedef void (XSTDCALL *codegen_function) (
|
||||
const struct tgsi_exec_vector *input,
|
||||
struct tgsi_exec_vector *output,
|
||||
float (*constant)[4],
|
||||
struct tgsi_exec_vector *temporary );
|
||||
|
||||
static void
|
||||
vs_llvm_prepare( struct draw_vertex_shader *base,
|
||||
struct draw_context *draw )
|
||||
{
|
||||
draw_update_vertex_fetch( draw );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -88,10 +93,15 @@ typedef void (XSTDCALL *codegen_function) (
|
||||
* \param vOut array of pointers to four output vertices
|
||||
*/
|
||||
static void
|
||||
run_vertex_program(struct draw_context *draw,
|
||||
unsigned elts[4], unsigned count,
|
||||
struct vertex_header *vOut[])
|
||||
vs_llvm_run( struct draw_vertex_shader *base,
|
||||
struct draw_context *draw,
|
||||
const unsigned *elts,
|
||||
unsigned count,
|
||||
struct vertex_header *vOut[] )
|
||||
{
|
||||
struct draw_llvm_vertex_shader *shader =
|
||||
(struct draw_llvm_vertex_shader *)base;
|
||||
|
||||
struct tgsi_exec_machine *machine = &draw->machine;
|
||||
unsigned int j;
|
||||
|
||||
@@ -100,6 +110,7 @@ run_vertex_program(struct draw_context *draw,
|
||||
const float *scale = draw->viewport.scale;
|
||||
const float *trans = draw->viewport.translate;
|
||||
|
||||
|
||||
assert(count <= 4);
|
||||
assert(draw->vertex_shader->state->output_semantic_name[0]
|
||||
== TGSI_SEMANTIC_POSITION);
|
||||
@@ -113,51 +124,17 @@ run_vertex_program(struct draw_context *draw,
|
||||
draw->vertex_fetch.fetch_func( draw, machine, elts, count );
|
||||
|
||||
/* run shader */
|
||||
#ifdef MESA_LLVM
|
||||
if (1) {
|
||||
struct gallivm_prog *prog = draw->vertex_shader->llvm_prog;
|
||||
gallivm_cpu_vs_exec(prog,
|
||||
gallivm_cpu_vs_exec(shader->llvm_prog,
|
||||
machine->Inputs,
|
||||
machine->Outputs,
|
||||
machine->Consts);
|
||||
} else
|
||||
#elif defined(__i386__) || defined(__386__)
|
||||
if (draw->use_sse) {
|
||||
/* SSE */
|
||||
/* cast away const */
|
||||
struct draw_vertex_shader *shader
|
||||
= (struct draw_vertex_shader *)draw->vertex_shader;
|
||||
codegen_function func
|
||||
= (codegen_function) x86_get_func( &shader->sse2_program );
|
||||
|
||||
if (func)
|
||||
func(
|
||||
machine->Inputs,
|
||||
machine->Outputs,
|
||||
machine->Consts,
|
||||
machine->Temps );
|
||||
else
|
||||
/* interpreter */
|
||||
tgsi_exec_machine_run( machine );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* interpreter */
|
||||
tgsi_exec_machine_run( machine );
|
||||
}
|
||||
machine->Consts,
|
||||
machine->Temps);
|
||||
|
||||
/* store machine results */
|
||||
for (j = 0; j < count; j++) {
|
||||
unsigned slot;
|
||||
float x, y, z, w;
|
||||
|
||||
/* Handle attr[0] (position) specially:
|
||||
*
|
||||
* XXX: Computing the clipmask should be done in the vertex
|
||||
* program as a set of DP4 instructions appended to the
|
||||
* user-provided code.
|
||||
*/
|
||||
x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
|
||||
y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
|
||||
z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
|
||||
@@ -178,13 +155,6 @@ run_vertex_program(struct draw_context *draw,
|
||||
vOut[j]->data[0][2] = z * scale[2] + trans[2];
|
||||
vOut[j]->data[0][3] = w;
|
||||
|
||||
#if DBG_VS
|
||||
debug_printf("output[%d]win: %f %f %f %f\n", j,
|
||||
vOut[j]->data[0][0],
|
||||
vOut[j]->data[0][1],
|
||||
vOut[j]->data[0][2],
|
||||
vOut[j]->data[0][3]);
|
||||
#endif
|
||||
/* Remaining attributes are packed into sequential post-transform
|
||||
* vertex attrib slots.
|
||||
*/
|
||||
@@ -193,132 +163,75 @@ run_vertex_program(struct draw_context *draw,
|
||||
vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
|
||||
vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
|
||||
vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
|
||||
#if DBG_VS
|
||||
debug_printf("output[%d][%d]: %f %f %f %f\n", j, slot,
|
||||
vOut[j]->data[slot][0],
|
||||
vOut[j]->data[slot][1],
|
||||
vOut[j]->data[slot][2],
|
||||
vOut[j]->data[slot][3]);
|
||||
#endif
|
||||
}
|
||||
} /* loop over vertices */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the vertex shader on all vertices in the vertex queue.
|
||||
* Called by the draw module when the vertx cache needs to be flushed.
|
||||
*/
|
||||
void
|
||||
draw_vertex_shader_queue_flush(struct draw_context *draw)
|
||||
static void
|
||||
vs_llvm_delete( struct draw_vertex_shader *base )
|
||||
{
|
||||
unsigned i;
|
||||
struct draw_llvm_vertex_shader *shader =
|
||||
(struct draw_llvm_vertex_shader *)base;
|
||||
|
||||
assert(draw->vs.queue_nr != 0);
|
||||
|
||||
/* XXX: do this on statechange:
|
||||
/* Do something to free compiled shader:
|
||||
*/
|
||||
draw_update_vertex_fetch( draw );
|
||||
|
||||
// fprintf(stderr, " q(%d) ", draw->vs.queue_nr );
|
||||
|
||||
/* run vertex shader on vertex cache entries, four per invokation */
|
||||
for (i = 0; i < draw->vs.queue_nr; i += 4) {
|
||||
struct vertex_header *dests[4];
|
||||
unsigned elts[4];
|
||||
int j, n = MIN2(4, draw->vs.queue_nr - i);
|
||||
|
||||
for (j = 0; j < n; j++) {
|
||||
elts[j] = draw->vs.queue[i + j].elt;
|
||||
dests[j] = draw->vs.queue[i + j].dest;
|
||||
}
|
||||
|
||||
for ( ; j < 4; j++) {
|
||||
elts[j] = elts[0];
|
||||
dests[j] = dests[0];
|
||||
}
|
||||
|
||||
assert(n > 0);
|
||||
assert(n <= 4);
|
||||
|
||||
run_vertex_program(draw, elts, n, dests);
|
||||
}
|
||||
|
||||
draw->vs.queue_nr = 0;
|
||||
FREE( shader );
|
||||
}
|
||||
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vertex_shader(struct draw_context *draw,
|
||||
const struct pipe_shader_state *shader)
|
||||
{
|
||||
struct draw_vertex_shader *vs;
|
||||
|
||||
vs = CALLOC_STRUCT( draw_vertex_shader );
|
||||
if (vs == NULL) {
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_llvm(struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct draw_llvm_vertex_shader *vs;
|
||||
|
||||
vs = CALLOC_STRUCT( draw_llvm_vertex_shader );
|
||||
if (vs == NULL)
|
||||
return NULL;
|
||||
|
||||
vs->base.state = templ;
|
||||
vs->base.prepare = vs_llvm_prepare;
|
||||
vs->base.run = vs_llvm_run;
|
||||
vs->base.delete = vs_llvm_delete;
|
||||
|
||||
{
|
||||
struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS);
|
||||
gallivm_ir_set_layout(ir, GALLIVM_SOA);
|
||||
gallivm_ir_set_components(ir, 4);
|
||||
gallivm_ir_fill_from_tgsi(ir, vs->base.state->tokens);
|
||||
vs->llvm_prog = gallivm_ir_compile(ir);
|
||||
gallivm_ir_delete(ir);
|
||||
}
|
||||
|
||||
vs->state = shader;
|
||||
|
||||
#ifdef MESA_LLVM
|
||||
struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS);
|
||||
gallivm_ir_set_layout(ir, GALLIVM_SOA);
|
||||
gallivm_ir_set_components(ir, 4);
|
||||
gallivm_ir_fill_from_tgsi(ir, shader->tokens);
|
||||
vs->llvm_prog = gallivm_ir_compile(ir);
|
||||
gallivm_ir_delete(ir);
|
||||
|
||||
draw->engine = gallivm_global_cpu_engine();
|
||||
|
||||
/* XXX: Why are there two versions of this? Shouldn't creating the
|
||||
* engine be a separate operation to compiling a shader?
|
||||
*/
|
||||
if (!draw->engine) {
|
||||
draw->engine = gallivm_cpu_engine_create(vs->llvm_prog);
|
||||
}
|
||||
else {
|
||||
gallivm_cpu_jit_compile(draw->engine, vs->llvm_prog);
|
||||
}
|
||||
#elif defined(__i386__) || defined(__386__)
|
||||
if (draw->use_sse) {
|
||||
/* cast-away const */
|
||||
struct pipe_shader_state *sh = (struct pipe_shader_state *) shader;
|
||||
|
||||
x86_init_func( &vs->sse2_program );
|
||||
if (!tgsi_emit_sse2( (struct tgsi_token *) sh->tokens,
|
||||
&vs->sse2_program )) {
|
||||
x86_release_func( (struct x86_function *) &vs->sse2_program );
|
||||
fprintf(stdout /*err*/,
|
||||
"tgsi_emit_sse2() failed, falling back to interpreter\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return vs;
|
||||
return &vs->base;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
draw_bind_vertex_shader(struct draw_context *draw,
|
||||
struct draw_vertex_shader *dvs)
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_llvm(struct draw_context *draw,
|
||||
const struct pipe_shader_state *shader)
|
||||
{
|
||||
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
|
||||
|
||||
draw->vertex_shader = dvs;
|
||||
draw->num_vs_outputs = dvs->state->num_outputs;
|
||||
|
||||
/* specify the vertex program to interpret/execute */
|
||||
tgsi_exec_machine_init(&draw->machine,
|
||||
draw->vertex_shader->state->tokens,
|
||||
PIPE_MAX_SAMPLERS,
|
||||
NULL /*samplers*/ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
draw_delete_vertex_shader(struct draw_context *draw,
|
||||
struct draw_vertex_shader *dvs)
|
||||
{
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
x86_release_func( (struct x86_function *) &dvs->sse2_program );
|
||||
#endif
|
||||
|
||||
FREE( dvs );
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "draw_vs.h"
|
||||
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "tgsi/exec/tgsi_sse2.h"
|
||||
|
||||
|
||||
typedef void (XSTDCALL *codegen_function) (
|
||||
const struct tgsi_exec_vector *input,
|
||||
struct tgsi_exec_vector *output,
|
||||
float (*constant)[4],
|
||||
struct tgsi_exec_vector *temporary );
|
||||
|
||||
|
||||
struct draw_sse_vertex_shader {
|
||||
struct draw_vertex_shader base;
|
||||
struct x86_function sse2_program;
|
||||
codegen_function func;
|
||||
};
|
||||
|
||||
|
||||
/* Should be part of the generated shader:
|
||||
*/
|
||||
static INLINE unsigned
|
||||
compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
|
||||
{
|
||||
unsigned mask = 0;
|
||||
unsigned i;
|
||||
|
||||
/* Do the hardwired planes first:
|
||||
*/
|
||||
if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
|
||||
if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
|
||||
if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
|
||||
if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
|
||||
if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
|
||||
if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
|
||||
|
||||
/* Followed by any remaining ones:
|
||||
*/
|
||||
for (i = 6; i < nr; i++) {
|
||||
if (dot4(clip, plane[i]) < 0)
|
||||
mask |= (1<<i);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vs_sse_prepare( struct draw_vertex_shader *base,
|
||||
struct draw_context *draw )
|
||||
{
|
||||
draw_update_vertex_fetch( draw );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform vertices with the current vertex program/shader
|
||||
* Up to four vertices can be shaded at a time.
|
||||
* \param vbuffer the input vertex data
|
||||
* \param elts indexes of four input vertices
|
||||
* \param count number of vertices to shade [1..4]
|
||||
* \param vOut array of pointers to four output vertices
|
||||
*/
|
||||
static void
|
||||
vs_sse_run( struct draw_vertex_shader *base,
|
||||
struct draw_context *draw,
|
||||
const unsigned *elts,
|
||||
unsigned count,
|
||||
struct vertex_header *vOut[] )
|
||||
{
|
||||
struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
|
||||
struct tgsi_exec_machine *machine = &draw->machine;
|
||||
unsigned int j;
|
||||
|
||||
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_ATTRIB_MAX);
|
||||
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_ATTRIB_MAX);
|
||||
const float *scale = draw->viewport.scale;
|
||||
const float *trans = draw->viewport.translate;
|
||||
|
||||
assert(count <= 4);
|
||||
assert(draw->vertex_shader->state->output_semantic_name[0]
|
||||
== TGSI_SEMANTIC_POSITION);
|
||||
|
||||
/* Consts does not require 16 byte alignment. */
|
||||
machine->Consts = (float (*)[4]) draw->user.constants;
|
||||
machine->Inputs = ALIGN16_ASSIGN(inputs);
|
||||
machine->Outputs = ALIGN16_ASSIGN(outputs);
|
||||
|
||||
|
||||
/* Fetch vertices. This may at some point be integrated into the
|
||||
* compiled shader -- that would require a reorganization where
|
||||
* multiple versions of the compiled shader might exist,
|
||||
* specialized for each fetch state.
|
||||
*/
|
||||
draw->vertex_fetch.fetch_func( draw, machine, elts, count );
|
||||
|
||||
|
||||
/* run compiled shader
|
||||
*/
|
||||
shader->func(
|
||||
machine->Inputs,
|
||||
machine->Outputs,
|
||||
machine->Consts,
|
||||
machine->Temps );
|
||||
|
||||
|
||||
/* XXX: Computing the clipmask and emitting results should be done
|
||||
* in the vertex program as a set of instructions appended to
|
||||
* the user-provided code.
|
||||
*/
|
||||
for (j = 0; j < count; j++) {
|
||||
unsigned slot;
|
||||
float x, y, z, w;
|
||||
|
||||
x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
|
||||
y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
|
||||
z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
|
||||
w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
|
||||
|
||||
vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
|
||||
vOut[j]->edgeflag = 1;
|
||||
|
||||
/* divide by w */
|
||||
w = 1.0f / w;
|
||||
x *= w;
|
||||
y *= w;
|
||||
z *= w;
|
||||
|
||||
/* Viewport mapping */
|
||||
vOut[j]->data[0][0] = x * scale[0] + trans[0];
|
||||
vOut[j]->data[0][1] = y * scale[1] + trans[1];
|
||||
vOut[j]->data[0][2] = z * scale[2] + trans[2];
|
||||
vOut[j]->data[0][3] = w;
|
||||
|
||||
/* Remaining attributes are packed into sequential post-transform
|
||||
* vertex attrib slots.
|
||||
*/
|
||||
for (slot = 1; slot < draw->num_vs_outputs; slot++) {
|
||||
vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
|
||||
vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
|
||||
vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
|
||||
vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
vs_sse_delete( struct draw_vertex_shader *base )
|
||||
{
|
||||
struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
|
||||
|
||||
x86_release_func( &shader->sse2_program );
|
||||
|
||||
FREE( shader );
|
||||
}
|
||||
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_sse(struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ)
|
||||
{
|
||||
struct draw_sse_vertex_shader *vs;
|
||||
|
||||
if (!draw->use_sse)
|
||||
return NULL;
|
||||
|
||||
vs = CALLOC_STRUCT( draw_sse_vertex_shader );
|
||||
if (vs == NULL)
|
||||
return NULL;
|
||||
|
||||
vs->base.state = templ;
|
||||
vs->base.prepare = vs_sse_prepare;
|
||||
vs->base.run = vs_sse_run;
|
||||
vs->base.delete = vs_sse_delete;
|
||||
|
||||
x86_init_func( &vs->sse2_program );
|
||||
|
||||
if (!tgsi_emit_sse2( (struct tgsi_token *) vs->base.state->tokens,
|
||||
&vs->sse2_program ))
|
||||
goto fail;
|
||||
|
||||
vs->func = (codegen_function) x86_get_func( &vs->sse2_program );
|
||||
|
||||
return &vs->base;
|
||||
|
||||
fail:
|
||||
fprintf(stderr, "tgsi_emit_sse2() failed, falling back to interpreter\n");
|
||||
|
||||
x86_release_func( &vs->sse2_program );
|
||||
|
||||
FREE(vs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vs_sse( struct draw_context *draw,
|
||||
const struct pipe_shader_state *templ )
|
||||
{
|
||||
return (void *) 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -175,7 +175,7 @@ static void wide_line_aa(struct draw_stage *stage,
|
||||
float *pos;
|
||||
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];
|
||||
const float len = sqrt(dx * dx + dy * dy);
|
||||
const float len = (float) sqrt(dx * dx + dy * dy);
|
||||
uint i;
|
||||
|
||||
dx = dx * half_width / len;
|
||||
@@ -400,7 +400,7 @@ static void wide_flush( struct draw_stage *stage, unsigned flags )
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
@@ -408,7 +408,7 @@ static void draw_reset_stipple_counter( struct draw_stage *stage )
|
||||
|
||||
static void wide_destroy( struct draw_stage *stage )
|
||||
{
|
||||
draw_free_tmps( stage );
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ struct draw_stage *draw_wide_stage( struct draw_context *draw )
|
||||
{
|
||||
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.next = NULL;
|
||||
@@ -425,7 +425,7 @@ struct draw_stage *draw_wide_stage( struct draw_context *draw )
|
||||
wide->stage.line = wide_first_line;
|
||||
wide->stage.tri = passthrough_tri;
|
||||
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;
|
||||
|
||||
return &wide->stage;
|
||||
@@ -15,7 +15,7 @@ GALLIVM_SOURCES = \
|
||||
storagesoa.cpp \
|
||||
instructionssoa.cpp
|
||||
|
||||
INC_SOURCES = gallivm_builtins.cpp llvm_base_shader.cpp
|
||||
INC_SOURCES = gallivm_builtins.cpp
|
||||
|
||||
CPP_SOURCES = \
|
||||
$(GALLIVM_SOURCES)
|
||||
@@ -30,7 +30,9 @@ OBJECTS = $(C_SOURCES:.c=.o) \
|
||||
### Include directories
|
||||
INCLUDES = \
|
||||
-I. \
|
||||
-I$(TOP)/src/mesa/pipe \
|
||||
-I$(TOP)/src/gallium/drivers
|
||||
-I$(TOP)/src/gallium/auxiliary \
|
||||
-I$(TOP)/src/gallium/include \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/include
|
||||
|
||||
@@ -65,8 +67,6 @@ depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(INC_SOURCES)
|
||||
gallivm_builtins.cpp: llvm_builtins.c
|
||||
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
|
||||
tags:
|
||||
@@ -77,7 +77,7 @@ tags:
|
||||
clean:
|
||||
-rm -f *.o */*.o *~ *.so *~ server/*.o
|
||||
-rm -f depend depend.bak
|
||||
-rm -f gallivm_builtins.cpp llvm_base_shader.cpp
|
||||
-rm -f gallivm_builtins.cpp
|
||||
|
||||
symlinks:
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
#include "pipe/p_context.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/CallingConv.h>
|
||||
@@ -289,9 +289,9 @@ void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
|
||||
tgsi_dump(tokens, 0);
|
||||
|
||||
|
||||
llvm::Module *irmod = tgsi_to_llvmir(ir, tokens);
|
||||
llvm::Module *mod = tgsi_to_llvmir(ir, tokens);
|
||||
|
||||
llvm::Module *mod = tgsi_to_llvm(ir, tokens);
|
||||
//llvm::Module *mod = tgsi_to_llvm(ir, tokens);
|
||||
ir->module = mod;
|
||||
gallivm_ir_dump(ir, 0);
|
||||
}
|
||||
@@ -318,6 +318,9 @@ struct gallivm_prog * gallivm_ir_compile(struct gallivm_ir *ir)
|
||||
passes.run(*mod);
|
||||
prog->module = mod;
|
||||
|
||||
std::cout << "After optimizations:"<<std::endl;
|
||||
mod->dump();
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ struct gallivm_cpu_engine *gallivm_global_cpu_engine();
|
||||
int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
|
||||
struct tgsi_exec_vector *inputs,
|
||||
struct tgsi_exec_vector *dests,
|
||||
float (*consts)[4]);
|
||||
float (*consts)[4],
|
||||
struct tgsi_exec_vector *temps);
|
||||
int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
|
||||
float x, float y,
|
||||
float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
|
||||
@@ -42,8 +42,8 @@
|
||||
#include "pipe/p_context.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/CallingConv.h>
|
||||
@@ -105,10 +105,10 @@ static inline llvm::Function *func_for_shader(struct gallivm_prog *prog)
|
||||
|
||||
switch (prog->type) {
|
||||
case GALLIVM_VS:
|
||||
func = mod->getFunction("run_vertex_shader");
|
||||
func = mod->getFunction("vs_shader");
|
||||
break;
|
||||
case GALLIVM_FS:
|
||||
func = mod->getFunction("run_fragment_shader");
|
||||
func = mod->getFunction("fs_shader");
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown shader type!");
|
||||
@@ -177,10 +177,7 @@ struct gallivm_cpu_engine * gallivm_global_cpu_engine()
|
||||
typedef void (*vertex_shader_runner)(void *ainputs,
|
||||
void *dests,
|
||||
float (*aconsts)[4],
|
||||
int num_vertices,
|
||||
int num_inputs,
|
||||
int num_attribs,
|
||||
int num_consts);
|
||||
void *temps);
|
||||
|
||||
|
||||
/*!
|
||||
@@ -191,12 +188,13 @@ typedef void (*vertex_shader_runner)(void *ainputs,
|
||||
int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
|
||||
struct tgsi_exec_vector *inputs,
|
||||
struct tgsi_exec_vector *dests,
|
||||
float (*consts)[4])
|
||||
float (*consts)[4],
|
||||
struct tgsi_exec_vector *temps)
|
||||
{
|
||||
vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
|
||||
assert(runner);
|
||||
/*FIXME*/
|
||||
runner(inputs, dests, consts, 4, 4, 4, prog->num_consts);
|
||||
runner(inputs, dests, consts, temps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef GALLIVM_P_H
|
||||
#define GALLIVM_P_H
|
||||
|
||||
#ifdef MESA_LLVM
|
||||
|
||||
#include "gallivm.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum gallivm_shader_type;
|
||||
enum gallivm_vector_layout;
|
||||
|
||||
struct gallivm_interpolate {
|
||||
int attrib;
|
||||
int chan;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct gallivm_ir {
|
||||
llvm::Module *module;
|
||||
int id;
|
||||
enum gallivm_shader_type type;
|
||||
enum gallivm_vector_layout layout;
|
||||
int num_components;
|
||||
int num_consts;
|
||||
|
||||
//FIXME: this might not be enough for some shaders
|
||||
struct gallivm_interpolate interpolators[32*4];
|
||||
int num_interp;
|
||||
};
|
||||
|
||||
struct gallivm_prog {
|
||||
llvm::Module *module;
|
||||
void *function;
|
||||
|
||||
int id;
|
||||
enum gallivm_shader_type type;
|
||||
|
||||
int num_consts;
|
||||
|
||||
//FIXME: this might not be enough for some shaders
|
||||
struct gallivm_interpolate interpolators[32*4];
|
||||
int num_interp;
|
||||
};
|
||||
|
||||
static INLINE void gallivm_swizzle_components(int swizzle,
|
||||
int *xc, int *yc,
|
||||
int *zc, int *wc)
|
||||
{
|
||||
int x = swizzle / 1000; swizzle -= x * 1000;
|
||||
int y = swizzle / 100; swizzle -= y * 100;
|
||||
int z = swizzle / 10; swizzle -= z * 10;
|
||||
int w = swizzle;
|
||||
|
||||
if (xc) *xc = x;
|
||||
if (yc) *yc = y;
|
||||
if (zc) *zc = z;
|
||||
if (wc) *wc = w;
|
||||
}
|
||||
|
||||
static INLINE boolean gallivm_is_swizzle(int swizzle)
|
||||
{
|
||||
const int NO_SWIZZLE = TGSI_SWIZZLE_X * 1000 + TGSI_SWIZZLE_Y * 100 +
|
||||
TGSI_SWIZZLE_Z * 10 + TGSI_SWIZZLE_W;
|
||||
return swizzle != NO_SWIZZLE;
|
||||
}
|
||||
|
||||
static INLINE int gallivm_x_swizzle(int swizzle)
|
||||
{
|
||||
int x;
|
||||
gallivm_swizzle_components(swizzle, &x, 0, 0, 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
static INLINE int gallivm_y_swizzle(int swizzle)
|
||||
{
|
||||
int y;
|
||||
gallivm_swizzle_components(swizzle, 0, &y, 0, 0);
|
||||
return y;
|
||||
}
|
||||
|
||||
static INLINE int gallivm_z_swizzle(int swizzle)
|
||||
{
|
||||
int z;
|
||||
gallivm_swizzle_components(swizzle, 0, 0, &z, 0);
|
||||
return z;
|
||||
}
|
||||
|
||||
static INLINE int gallivm_w_swizzle(int swizzle)
|
||||
{
|
||||
int w;
|
||||
gallivm_swizzle_components(swizzle, 0, 0, 0, &w);
|
||||
return w;
|
||||
}
|
||||
|
||||
#endif /* MESA_LLVM */
|
||||
|
||||
#if defined __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
#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;
|
||||
}
|
||||
@@ -28,6 +28,8 @@
|
||||
#ifndef INSTRUCTIONSSOA_H
|
||||
#define INSTRUCTIONSSOA_H
|
||||
|
||||
#include <llvm/Support/LLVMBuilder.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@@ -44,11 +46,28 @@ public:
|
||||
InstructionsSoa(llvm::Module *mod, llvm::Function *func,
|
||||
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,
|
||||
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,
|
||||
const std::vector<llvm::Value*> in2);
|
||||
void end();
|
||||
|
||||
std::vector<llvm::Value*> extractVector(llvm::Value *vector);
|
||||
private:
|
||||
const char * name(const char *prefix) const;
|
||||
llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
|
||||
llvm::Value *z, llvm::Value *w);
|
||||
private:
|
||||
llvm::LLVMFoldingBuilder m_builder;
|
||||
StorageSoa *m_storage;
|
||||
private:
|
||||
mutable int m_idx;
|
||||
mutable char m_name[32];
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
#include "gallivm_p.h"
|
||||
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include <llvm/BasicBlock.h>
|
||||
#include <llvm/Module.h>
|
||||
@@ -82,10 +84,10 @@ llvm::Constant *Storage::shuffleMask(int vec)
|
||||
if (origVec == 0) {
|
||||
const_vec = Constant::getNullValue(m_intVecType);
|
||||
} else {
|
||||
int x = vec / 1000; vec -= x * 1000;
|
||||
int y = vec / 100; vec -= y * 100;
|
||||
int z = vec / 10; vec -= z * 10;
|
||||
int w = vec;
|
||||
int x = gallivm_x_swizzle(vec);
|
||||
int y = gallivm_y_swizzle(vec);
|
||||
int z = gallivm_z_swizzle(vec);
|
||||
int w = gallivm_w_swizzle(vec);
|
||||
std::vector<Constant*> elems;
|
||||
elems.push_back(constantInt(x));
|
||||
elems.push_back(constantInt(y));
|
||||
@@ -0,0 +1,389 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef STORAGESOA_H
|
||||
#define STORAGESOA_H
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
class BasicBlock;
|
||||
class Constant;
|
||||
class ConstantInt;
|
||||
class GlobalVariable;
|
||||
class LoadInst;
|
||||
class Value;
|
||||
class VectorType;
|
||||
class Module;
|
||||
}
|
||||
|
||||
class StorageSoa
|
||||
{
|
||||
public:
|
||||
enum Argument {
|
||||
Input,
|
||||
Output,
|
||||
Temp,
|
||||
Const,
|
||||
Immediate,
|
||||
Address
|
||||
};
|
||||
public:
|
||||
StorageSoa(llvm::BasicBlock *block,
|
||||
llvm::Value *input,
|
||||
llvm::Value *output,
|
||||
llvm::Value *consts,
|
||||
llvm::Value *temps);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
void addImmediate(float *vec);
|
||||
void declareImmediates();
|
||||
|
||||
void addAddress(int idx);
|
||||
|
||||
llvm::Value * addrElement(int idx) const;
|
||||
|
||||
llvm::ConstantInt *constantInt(int) const;
|
||||
private:
|
||||
llvm::Value *elementPointer(llvm::Value *ptr, llvm::Value *indIdx,
|
||||
int channel) const;
|
||||
llvm::Value *element(llvm::Value *ptr, llvm::Value *idx,
|
||||
int channel) const;
|
||||
const char *name(const char *prefix) 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:
|
||||
llvm::BasicBlock *m_block;
|
||||
|
||||
llvm::Value *m_input;
|
||||
llvm::Value *m_output;
|
||||
llvm::Value *m_consts;
|
||||
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 char m_name[32];
|
||||
mutable int m_idx;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
#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>
|
||||
@@ -44,7 +44,38 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
#include "llvm_base_shader.cpp"
|
||||
|
||||
static inline FunctionType *vertexShaderFunctionType()
|
||||
{
|
||||
//Function takes three arguments,
|
||||
// the calling code has to make sure the types it will
|
||||
// pass are castable to the following:
|
||||
// [4 x <4 x float>] inputs,
|
||||
// [4 x <4 x float>] output,
|
||||
// [4 x [4 x float]] consts,
|
||||
// [4 x <4 x float>] temps
|
||||
|
||||
std::vector<const Type*> funcArgs;
|
||||
VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
|
||||
ArrayType *vectorArray = ArrayType::get(vectorType, 4);
|
||||
PointerType *vectorArrayPtr = PointerType::get(vectorArray, 0);
|
||||
|
||||
ArrayType *floatArray = ArrayType::get(Type::FloatTy, 4);
|
||||
ArrayType *constsArray = ArrayType::get(floatArray, 4);
|
||||
PointerType *constsArrayPtr = PointerType::get(constsArray, 0);
|
||||
|
||||
funcArgs.push_back(vectorArrayPtr);//inputs
|
||||
funcArgs.push_back(vectorArrayPtr);//output
|
||||
funcArgs.push_back(constsArrayPtr);//consts
|
||||
funcArgs.push_back(vectorArrayPtr);//temps
|
||||
|
||||
FunctionType *functionType = FunctionType::get(
|
||||
/*Result=*/Type::VoidTy,
|
||||
/*Params=*/funcArgs,
|
||||
/*isVarArg=*/false);
|
||||
|
||||
return functionType;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_interpolator(struct gallivm_ir *ir,
|
||||
@@ -117,10 +148,14 @@ translate_declaration(struct gallivm_ir *prog,
|
||||
static void
|
||||
translate_declarationir(struct gallivm_ir *,
|
||||
llvm::Module *,
|
||||
StorageSoa *,
|
||||
struct tgsi_full_declaration *,
|
||||
StorageSoa *storage,
|
||||
struct tgsi_full_declaration *decl,
|
||||
struct tgsi_full_declaration *)
|
||||
{
|
||||
if (decl->Declaration.File == TGSI_FILE_ADDRESS) {
|
||||
int idx = decl->u.DeclarationRange.First;
|
||||
storage->addAddress(idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -178,9 +213,8 @@ swizzleVector(llvm::Value *val, struct tgsi_full_src_register *src,
|
||||
Storage *storage)
|
||||
{
|
||||
int swizzle = swizzleInt(src);
|
||||
const int NO_SWIZZLE = TGSI_SWIZZLE_X * 1000 + TGSI_SWIZZLE_Y * 100 +
|
||||
TGSI_SWIZZLE_Z * 10 + TGSI_SWIZZLE_W;
|
||||
if (swizzle != NO_SWIZZLE) {
|
||||
|
||||
if (gallivm_is_swizzle(swizzle)) {
|
||||
/*fprintf(stderr, "XXXXXXXX swizzle = %d\n", swizzle);*/
|
||||
val = storage->shuffleVector(val, swizzle);
|
||||
}
|
||||
@@ -673,18 +707,22 @@ translate_instructionir(llvm::Module *module,
|
||||
|
||||
if (src->SrcRegister.Indirect) {
|
||||
indIdx = storage->addrElement(src->SrcRegisterInd.Index);
|
||||
indIdx = storage->extractIndex(indIdx);
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
val = storage->immediateElement(src->SrcRegister.Index, swizzle);
|
||||
val = storage->load(StorageSoa::Immediate,
|
||||
src->SrcRegister.Index, swizzle, indIdx);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File);
|
||||
return;
|
||||
@@ -696,6 +734,7 @@ translate_instructionir(llvm::Module *module,
|
||||
std::vector<llvm::Value*> out(4);
|
||||
switch (inst->Instruction.Opcode) {
|
||||
case TGSI_OPCODE_ARL: {
|
||||
out = instr->arl(inputs[0]);
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_MOV: {
|
||||
@@ -745,6 +784,7 @@ translate_instructionir(llvm::Module *module,
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_MAD: {
|
||||
out = instr->madd(inputs[0], inputs[1], inputs[2]);
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_SUB: {
|
||||
@@ -1028,11 +1068,14 @@ translate_instructionir(llvm::Module *module,
|
||||
struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
|
||||
|
||||
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) {
|
||||
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) {
|
||||
storage->storeAddress(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
|
||||
storage->store(StorageSoa::Address,
|
||||
dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: unsupported LLVM destination!");
|
||||
assert(!"wrong destination");
|
||||
@@ -1043,7 +1086,7 @@ translate_instructionir(llvm::Module *module,
|
||||
llvm::Module *
|
||||
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_full_instruction fi;
|
||||
struct tgsi_full_declaration fd;
|
||||
@@ -1107,29 +1150,32 @@ tgsi_to_llvm(struct gallivm_ir *ir, const struct tgsi_token *tokens)
|
||||
llvm::Module * tgsi_to_llvmir(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_full_instruction fi;
|
||||
struct tgsi_full_declaration fd;
|
||||
unsigned instno = 0;
|
||||
Function* shader = mod->getFunction("execute_shader");
|
||||
std::ostringstream stream;
|
||||
if (ir->type == GALLIVM_VS) {
|
||||
stream << "vs_shader";
|
||||
} else {
|
||||
stream << "fs_shader";
|
||||
}
|
||||
stream << ir->id;
|
||||
//stream << ir->id;
|
||||
std::string func_name = stream.str();
|
||||
shader->setName(func_name.c_str());
|
||||
Function *shader = llvm::cast<Function>(mod->getOrInsertFunction(
|
||||
func_name.c_str(),
|
||||
vertexShaderFunctionType()));
|
||||
|
||||
Function::arg_iterator args = shader->arg_begin();
|
||||
Value *input = args++;
|
||||
input->setName("input");
|
||||
input->setName("inputs");
|
||||
Value *output = args++;
|
||||
output->setName("output");
|
||||
output->setName("outputs");
|
||||
Value *consts = args++;
|
||||
consts->setName("consts");
|
||||
Value *temps = args++;
|
||||
temps->setName("temps");
|
||||
|
||||
BasicBlock *label_entry = new BasicBlock("entry", shader, 0);
|
||||
|
||||
@@ -1138,7 +1184,7 @@ llvm::Module * tgsi_to_llvmir(struct gallivm_ir *ir,
|
||||
fi = tgsi_default_full_instruction();
|
||||
fd = tgsi_default_full_declaration();
|
||||
|
||||
StorageSoa storage(label_entry, input, output, consts);
|
||||
StorageSoa storage(label_entry, input, output, consts, temps);
|
||||
InstructionsSoa instr(mod, shader, label_entry, &storage);
|
||||
|
||||
while(!tgsi_parse_end_of_tokens(&parse)) {
|
||||
@@ -1157,6 +1203,7 @@ llvm::Module * tgsi_to_llvmir(struct gallivm_ir *ir,
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION:
|
||||
storage.declareImmediates();
|
||||
translate_instructionir(mod, &storage, &instr,
|
||||
&parse.FullToken.FullInstruction,
|
||||
&fi, instno);
|
||||
@@ -17,7 +17,7 @@ C_SOURCES = \
|
||||
|
||||
ASM_SOURCES =
|
||||
|
||||
include ../Makefile.template
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
+2
-2
@@ -110,7 +110,7 @@ pb_malloc_buffer_create(size_t size,
|
||||
buf = CALLOC_STRUCT(malloc_buffer);
|
||||
if(!buf)
|
||||
return NULL;
|
||||
|
||||
|
||||
buf->base.base.refcount = 1;
|
||||
buf->base.base.alignment = desc->alignment;
|
||||
buf->base.base.usage = desc->usage;
|
||||
@@ -119,7 +119,7 @@ pb_malloc_buffer_create(size_t size,
|
||||
|
||||
buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment);
|
||||
if(!buf->data) {
|
||||
FREE(buf);
|
||||
align_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_util.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"
|
||||
|
||||
#define TILE_TOP_LEFT 0
|
||||
@@ -120,18 +120,41 @@
|
||||
|
||||
|
||||
|
||||
static void
|
||||
tgsi_exec_prepare( struct tgsi_exec_machine *mach )
|
||||
/**
|
||||
* Initialize machine state by expanding tokens to full instructions,
|
||||
* allocating temporary storage, setting up constants, etc.
|
||||
* After this, we can call tgsi_exec_machine_run() many times.
|
||||
*/
|
||||
void
|
||||
tgsi_exec_machine_bind_shader(
|
||||
struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_token *tokens,
|
||||
uint numSamplers,
|
||||
struct tgsi_sampler *samplers)
|
||||
{
|
||||
struct tgsi_exec_labels *labels = &mach->Labels;
|
||||
uint k;
|
||||
struct tgsi_parse_context parse;
|
||||
struct tgsi_exec_labels *labels = &mach->Labels;
|
||||
struct tgsi_full_instruction *instructions;
|
||||
struct tgsi_full_declaration *declarations;
|
||||
uint maxInstructions = 10, numInstructions = 0;
|
||||
uint maxDeclarations = 10, numDeclarations = 0;
|
||||
uint k;
|
||||
uint instno = 0;
|
||||
|
||||
#if 0
|
||||
tgsi_dump(tokens, 0);
|
||||
#endif
|
||||
|
||||
mach->Tokens = tokens;
|
||||
mach->Samplers = samplers;
|
||||
|
||||
k = tgsi_parse_init (&parse, mach->Tokens);
|
||||
if (k != TGSI_PARSE_OK) {
|
||||
debug_printf( "Problem parsing!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
mach->Processor = parse.FullHeader.Processor.Processor;
|
||||
mach->ImmLimit = 0;
|
||||
labels->count = 0;
|
||||
|
||||
@@ -141,11 +164,6 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
|
||||
instructions = (struct tgsi_full_instruction *)
|
||||
MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) );
|
||||
|
||||
k = tgsi_parse_init( &parse, mach->Tokens );
|
||||
if (k != TGSI_PARSE_OK) {
|
||||
debug_printf("Problem parsing!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while( !tgsi_parse_end_of_tokens( &parse ) ) {
|
||||
uint pointer = parse.Position;
|
||||
@@ -158,13 +176,13 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
|
||||
if (numDeclarations == maxDeclarations) {
|
||||
declarations = REALLOC(declarations,
|
||||
maxDeclarations
|
||||
* sizeof(struct tgsi_full_instruction),
|
||||
* sizeof(struct tgsi_full_declaration),
|
||||
(maxDeclarations + 10)
|
||||
* sizeof(struct tgsi_full_instruction));
|
||||
* sizeof(struct tgsi_full_declaration));
|
||||
maxDeclarations += 10;
|
||||
}
|
||||
memcpy(declarations + numDeclarations,
|
||||
&parse.FullToken.FullInstruction,
|
||||
&parse.FullToken.FullDeclaration,
|
||||
sizeof(declarations[0]));
|
||||
numDeclarations++;
|
||||
break;
|
||||
@@ -176,7 +194,8 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
|
||||
assert( mach->ImmLimit + size / 4 <= TGSI_EXEC_NUM_IMMEDIATES );
|
||||
|
||||
for( i = 0; i < size; i++ ) {
|
||||
mach->Imms[mach->ImmLimit + i / 4][i % 4] = parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
|
||||
mach->Imms[mach->ImmLimit + i / 4][i % 4] =
|
||||
parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
|
||||
}
|
||||
mach->ImmLimit += size / 4;
|
||||
}
|
||||
@@ -224,37 +243,11 @@ tgsi_exec_prepare( struct tgsi_exec_machine *mach )
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize machine state by expanding tokens to full instructions,
|
||||
* allocating temporary storage, setting up constants, etc.
|
||||
* After this, we can call tgsi_exec_machine_run() many times.
|
||||
*/
|
||||
void
|
||||
tgsi_exec_machine_init(
|
||||
struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_token *tokens,
|
||||
uint numSamplers,
|
||||
struct tgsi_sampler *samplers)
|
||||
struct tgsi_exec_machine *mach )
|
||||
{
|
||||
uint i, k;
|
||||
struct tgsi_parse_context parse;
|
||||
|
||||
#if 0
|
||||
tgsi_dump(tokens, 0);
|
||||
#endif
|
||||
|
||||
mach->Tokens = tokens;
|
||||
|
||||
mach->Samplers = samplers;
|
||||
|
||||
k = tgsi_parse_init (&parse, mach->Tokens);
|
||||
if (k != TGSI_PARSE_OK) {
|
||||
debug_printf( "Problem parsing!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
mach->Processor = parse.FullHeader.Processor.Processor;
|
||||
tgsi_parse_free (&parse);
|
||||
uint i;
|
||||
|
||||
mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps);
|
||||
mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS];
|
||||
@@ -270,8 +263,6 @@ tgsi_exec_machine_init(
|
||||
mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].f[i] = 128.0f;
|
||||
mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].f[i] = -128.0f;
|
||||
}
|
||||
|
||||
tgsi_exec_prepare( mach );
|
||||
}
|
||||
|
||||
|
||||
@@ -1346,9 +1337,12 @@ exec_tex(struct tgsi_exec_machine *mach,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate a constant-valued coefficient at the position of the
|
||||
* current quad.
|
||||
*/
|
||||
static void
|
||||
constant_interpolation(
|
||||
eval_constant_coef(
|
||||
struct tgsi_exec_machine *mach,
|
||||
unsigned attrib,
|
||||
unsigned chan )
|
||||
@@ -1360,8 +1354,12 @@ constant_interpolation(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a linear-valued coefficient at the position of the
|
||||
* current quad.
|
||||
*/
|
||||
static void
|
||||
linear_interpolation(
|
||||
eval_linear_coef(
|
||||
struct tgsi_exec_machine *mach,
|
||||
unsigned attrib,
|
||||
unsigned chan )
|
||||
@@ -1377,8 +1375,12 @@ linear_interpolation(
|
||||
mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a perspective-valued coefficient at the position of the
|
||||
* current quad.
|
||||
*/
|
||||
static void
|
||||
perspective_interpolation(
|
||||
eval_perspective_coef(
|
||||
struct tgsi_exec_machine *mach,
|
||||
unsigned attrib,
|
||||
unsigned chan )
|
||||
@@ -1397,7 +1399,7 @@ perspective_interpolation(
|
||||
}
|
||||
|
||||
|
||||
typedef void (* interpolation_func)(
|
||||
typedef void (* eval_coef_func)(
|
||||
struct tgsi_exec_machine *mach,
|
||||
unsigned attrib,
|
||||
unsigned chan );
|
||||
@@ -1410,7 +1412,7 @@ exec_declaration(
|
||||
if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
|
||||
if( decl->Declaration.File == TGSI_FILE_INPUT ) {
|
||||
unsigned first, last, mask;
|
||||
interpolation_func interp;
|
||||
eval_coef_func eval;
|
||||
|
||||
assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE );
|
||||
|
||||
@@ -1420,15 +1422,15 @@ exec_declaration(
|
||||
|
||||
switch( decl->Interpolation.Interpolate ) {
|
||||
case TGSI_INTERPOLATE_CONSTANT:
|
||||
interp = constant_interpolation;
|
||||
eval = eval_constant_coef;
|
||||
break;
|
||||
|
||||
case TGSI_INTERPOLATE_LINEAR:
|
||||
interp = linear_interpolation;
|
||||
eval = eval_linear_coef;
|
||||
break;
|
||||
|
||||
case TGSI_INTERPOLATE_PERSPECTIVE:
|
||||
interp = perspective_interpolation;
|
||||
eval = eval_perspective_coef;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1440,7 +1442,7 @@ exec_declaration(
|
||||
|
||||
for( i = first; i <= last; i++ ) {
|
||||
for( j = 0; j < NUM_CHANNELS; j++ ) {
|
||||
interp( mach, i, j );
|
||||
eval( mach, i, j );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1450,7 +1452,7 @@ exec_declaration(
|
||||
for( j = 0; j < NUM_CHANNELS; j++ ) {
|
||||
if( mask & (1 << j) ) {
|
||||
for( i = first; i <= last; i++ ) {
|
||||
interp( mach, i, j );
|
||||
eval( mach, i, j );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,12 +215,16 @@ struct tgsi_exec_machine
|
||||
struct tgsi_exec_labels Labels;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
tgsi_exec_machine_init(
|
||||
struct tgsi_exec_machine *mach );
|
||||
|
||||
|
||||
void
|
||||
tgsi_exec_machine_bind_shader(
|
||||
struct tgsi_exec_machine *mach,
|
||||
const struct tgsi_token *tokens,
|
||||
unsigned numSamplers,
|
||||
uint numSamplers,
|
||||
struct tgsi_sampler *samplers);
|
||||
|
||||
uint
|
||||
+128
-101
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "pipe/p_util.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_sse2.h"
|
||||
|
||||
@@ -44,6 +44,9 @@ static void
|
||||
_print_reg(
|
||||
struct x86_reg reg )
|
||||
{
|
||||
if (reg.mod != mod_REG)
|
||||
debug_printf( "[" );
|
||||
|
||||
switch( reg.file ) {
|
||||
case file_REG32:
|
||||
switch( reg.idx ) {
|
||||
@@ -83,6 +86,13 @@ _print_reg(
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg.mod == mod_DISP8 ||
|
||||
reg.mod == mod_DISP32)
|
||||
debug_printf("+%d", reg.disp);
|
||||
|
||||
if (reg.mod != mod_REG)
|
||||
debug_printf( "]" );
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -318,8 +328,11 @@ emit_call(
|
||||
struct x86_function *func,
|
||||
void (* addr)() )
|
||||
{
|
||||
struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX );
|
||||
|
||||
DUMP_I( "CALL", addr );
|
||||
x86_call( func, addr );
|
||||
x86_mov_reg_imm( func, ecx, (unsigned long) addr );
|
||||
x86_call( func, ecx );
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1426,7 +1439,7 @@ emit_cmp(
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
emit_instruction(
|
||||
struct x86_function *func,
|
||||
struct tgsi_full_instruction *inst )
|
||||
@@ -1537,11 +1550,11 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_EXP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_LOG:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_MUL:
|
||||
@@ -1696,24 +1709,24 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CND:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CND0:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DOT2ADD:
|
||||
/* TGSI_OPCODE_DP2A */
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_INDEX:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_NEGATE:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_FRAC:
|
||||
@@ -1726,7 +1739,7 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CLAMP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_FLOOR:
|
||||
@@ -1739,7 +1752,7 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ROUND:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_EXPBASE2:
|
||||
@@ -1814,7 +1827,7 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_MULTIPLYMATRIX:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ABS:
|
||||
@@ -1827,7 +1840,7 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_RCC:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DPH:
|
||||
@@ -1858,11 +1871,11 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DDX:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DDY:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_KIL:
|
||||
@@ -1870,35 +1883,35 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_PK2H:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_PK2US:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_PK4B:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_PK4UB:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_RFL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SEQ:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SFL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SGT:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SIN:
|
||||
@@ -1910,66 +1923,73 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SLE:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SNE:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_STR:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TEX:
|
||||
emit_tempf(
|
||||
func,
|
||||
0,
|
||||
TGSI_EXEC_TEMP_ONE_I,
|
||||
TGSI_EXEC_TEMP_ONE_C );
|
||||
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
|
||||
STORE( func, *inst, 0, 0, chan_index );
|
||||
if (0) {
|
||||
/* Disable dummy texture code:
|
||||
*/
|
||||
emit_tempf(
|
||||
func,
|
||||
0,
|
||||
TGSI_EXEC_TEMP_ONE_I,
|
||||
TGSI_EXEC_TEMP_ONE_C );
|
||||
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
|
||||
STORE( func, *inst, 0, 0, chan_index );
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXD:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_UP2H:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_UP2US:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_UP4B:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_UP4UB:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_X2D:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ARA:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ARR:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_BRA:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CAL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_RET:
|
||||
@@ -1982,7 +2002,7 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SSG:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CMP:
|
||||
@@ -2011,132 +2031,134 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXB:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_NRM:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DIV:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DP2:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_BRK:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_IF:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_LOOP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_REP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ELSE:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ENDIF:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ENDLOOP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ENDREP:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_PUSHA:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_POPA:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CEIL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_I2F:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_NOT:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TRUNC:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SHL:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SHR:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_AND:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_OR:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_MOD:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_XOR:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SAD:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXF:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXQ:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CONT:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_EMIT:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ENDPRIM:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2154,14 +2176,6 @@ emit_declaration(
|
||||
last = decl->u.DeclarationRange.Last;
|
||||
mask = decl->Declaration.UsageMask;
|
||||
|
||||
/* Do not touch WPOS.xy */
|
||||
if( first == 0 ) {
|
||||
mask &= ~TGSI_WRITEMASK_XY;
|
||||
if( mask == TGSI_WRITEMASK_NONE ) {
|
||||
first++;
|
||||
}
|
||||
}
|
||||
|
||||
for( i = first; i <= last; i++ ) {
|
||||
for( j = 0; j < NUM_CHANNELS; j++ ) {
|
||||
if( mask & (1 << j) ) {
|
||||
@@ -2172,9 +2186,9 @@ emit_declaration(
|
||||
break;
|
||||
|
||||
case TGSI_INTERPOLATE_LINEAR:
|
||||
emit_inputf( func, 0, 0, TGSI_SWIZZLE_X );
|
||||
emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
|
||||
emit_coef_dadx( func, 1, i, j );
|
||||
emit_inputf( func, 2, 0, TGSI_SWIZZLE_Y );
|
||||
emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
|
||||
emit_coef_dady( func, 3, i, j );
|
||||
emit_mul( func, 0, 1 ); /* x * dadx */
|
||||
emit_coef_a0( func, 4, i, j );
|
||||
@@ -2185,12 +2199,12 @@ emit_declaration(
|
||||
break;
|
||||
|
||||
case TGSI_INTERPOLATE_PERSPECTIVE:
|
||||
emit_inputf( func, 0, 0, TGSI_SWIZZLE_X );
|
||||
emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
|
||||
emit_coef_dadx( func, 1, i, j );
|
||||
emit_inputf( func, 2, 0, TGSI_SWIZZLE_Y );
|
||||
emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
|
||||
emit_coef_dady( func, 3, i, j );
|
||||
emit_mul( func, 0, 1 ); /* x * dadx */
|
||||
emit_inputf( func, 4, 0, TGSI_SWIZZLE_W );
|
||||
emit_tempf( func, 4, 0, TGSI_SWIZZLE_W );
|
||||
emit_coef_a0( func, 5, i, j );
|
||||
emit_rcp( func, 4, 4 ); /* 1.0 / w */
|
||||
emit_mul( func, 2, 3 ); /* y * dady */
|
||||
@@ -2202,6 +2216,7 @@ emit_declaration(
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2215,6 +2230,7 @@ tgsi_emit_sse2(
|
||||
struct x86_function *func )
|
||||
{
|
||||
struct tgsi_parse_context parse;
|
||||
unsigned ok = 1;
|
||||
|
||||
DUMP_START();
|
||||
|
||||
@@ -2239,7 +2255,7 @@ tgsi_emit_sse2(
|
||||
|
||||
tgsi_parse_init( &parse, tokens );
|
||||
|
||||
while( !tgsi_parse_end_of_tokens( &parse ) ) {
|
||||
while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
|
||||
tgsi_parse_token( &parse );
|
||||
|
||||
switch( parse.FullToken.Token.Type ) {
|
||||
@@ -2247,17 +2263,26 @@ tgsi_emit_sse2(
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION:
|
||||
emit_instruction(
|
||||
func,
|
||||
&parse.FullToken.FullInstruction );
|
||||
ok = emit_instruction(
|
||||
func,
|
||||
&parse.FullToken.FullInstruction );
|
||||
|
||||
if (!ok) {
|
||||
debug_printf("failed to translate tgsi opcode %d\n",
|
||||
parse.FullToken.FullInstruction.Instruction.Opcode );
|
||||
}
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE:
|
||||
/* XXX implement this */
|
||||
return 0;
|
||||
ok = 0;
|
||||
debug_printf("failed to emit immediate value\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2265,7 +2290,7 @@ tgsi_emit_sse2(
|
||||
|
||||
DUMP_END();
|
||||
|
||||
return 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2283,6 +2308,7 @@ tgsi_emit_sse2_fs(
|
||||
{
|
||||
struct tgsi_parse_context parse;
|
||||
boolean instruction_phase = FALSE;
|
||||
unsigned ok = 1;
|
||||
|
||||
DUMP_START();
|
||||
|
||||
@@ -2308,7 +2334,7 @@ tgsi_emit_sse2_fs(
|
||||
|
||||
tgsi_parse_init( &parse, tokens );
|
||||
|
||||
while( !tgsi_parse_end_of_tokens( &parse ) ) {
|
||||
while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
|
||||
tgsi_parse_token( &parse );
|
||||
|
||||
switch( parse.FullToken.Token.Type ) {
|
||||
@@ -2327,17 +2353,18 @@ tgsi_emit_sse2_fs(
|
||||
get_output_base(),
|
||||
get_argument( 1 ) );
|
||||
}
|
||||
emit_instruction(
|
||||
ok = emit_instruction(
|
||||
func,
|
||||
&parse.FullToken.FullInstruction );
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE:
|
||||
/* XXX implement this */
|
||||
assert(0);
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ok = 0;
|
||||
assert( 0 );
|
||||
}
|
||||
}
|
||||
@@ -2346,7 +2373,7 @@ tgsi_emit_sse2_fs(
|
||||
|
||||
DUMP_END();
|
||||
|
||||
return 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif /* i386 */
|
||||
@@ -0,0 +1,199 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user