From a83c07d09cbb935c1ed94eb0c08f6dbc1f75d272 Mon Sep 17 00:00:00 2001 From: ElSemi Date: Tue, 23 Nov 2010 15:29:41 +0100 Subject: [PATCH] Added some missing files in previous commit (why? :S ) --- psl1ght/tools/vpcomp/Makefile | 42 +++++ psl1ght/tools/vpcomp/README.txt | 24 +++ psl1ght/tools/vpcomp/main.cpp | 284 +++++++++++++++++++++++++++++ psl1ght/tools/vpcomp/microcode.cpp | 181 ++++++++++++++++++ psl1ght/tools/vpcomp/microcode.h | 16 ++ 5 files changed, 547 insertions(+) create mode 100644 psl1ght/tools/vpcomp/Makefile create mode 100644 psl1ght/tools/vpcomp/README.txt create mode 100644 psl1ght/tools/vpcomp/main.cpp create mode 100644 psl1ght/tools/vpcomp/microcode.cpp create mode 100644 psl1ght/tools/vpcomp/microcode.h diff --git a/psl1ght/tools/vpcomp/Makefile b/psl1ght/tools/vpcomp/Makefile new file mode 100644 index 00000000..1679ca8d --- /dev/null +++ b/psl1ght/tools/vpcomp/Makefile @@ -0,0 +1,42 @@ +CFLAGS += -Wall -Os -g -pipe -I../../include +LDFLAGS += -lstdc++ + +CC = $(PREFIX)gcc +STRIP = $(PREFIX)strip + +BIN = vpcomp$(BIN_EXT) + +OBJS = main.o microcode.o parameters.o vpasm.o + +all: $(BIN) + +clean: + @rm -f *.o core core.* $(BIN) + +strip: all + $(STRIP) $(BIN) + +install: strip + install -m 755 $(BIN) $(DEVKITPPC)/bin + +$(BIN): $(OBJS) + $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.cpp + $(CC) $(CFLAGS) -c $< -o $@ + + +osx: + $(MAKE) clean + PREFIX=/opt/toolchains/powerpc-apple-darwin8-10.2/bin/ppc-apple-darwin8- CFLAGS=-fabi-version=1 $(MAKE) strip + cp $(BIN) $(BIN)_ppc + $(MAKE) clean + PREFIX=/opt/toolchains/i686-apple-darwin9-10.4/bin/i686-apple-darwin9- $(MAKE) strip + cp $(BIN) $(BIN)_intel + $(MAKE) clean + /opt/toolchains/i686-apple-darwin9-10.4/bin/i686-apple-darwin9-lipo -create $(BIN)_ppc $(BIN)_intel -output $(BIN) + rm $(BIN)_ppc $(BIN)_intel + diff --git a/psl1ght/tools/vpcomp/README.txt b/psl1ght/tools/vpcomp/README.txt new file mode 100644 index 00000000..5aca5aee --- /dev/null +++ b/psl1ght/tools/vpcomp/README.txt @@ -0,0 +1,24 @@ +Vertex program compiler for libreality + +Preliminary version. It should compile most simple programs + +Supported: +All scalar and vector opcodes +Branches +Calls (untested) +Parameter passing in constants + +Unsupported: +Texture lookup +Address register access (ARL,ARR) +Indirect constant register access +Program relocation (jump & constants relocations) + +The assembler parser is quite simplistic, so it might fail to properly compiled +some valid assembler files. + +It requires NVidia CG.dll in the same directory (or in path) in order to +compile .cg programs into .rvp (reality vertex program) files. +(Download NVidia CG toolkit from their webpage to get the .dll) + +Only the windows version of the toolkit is currently supported. diff --git a/psl1ght/tools/vpcomp/main.cpp b/psl1ght/tools/vpcomp/main.cpp new file mode 100644 index 00000000..f92d567e --- /dev/null +++ b/psl1ght/tools/vpcomp/main.cpp @@ -0,0 +1,284 @@ +#include "stdio.h" +#include "malloc.h" +#include "windows.h" + +#include "vpasm.h" +#include "microcode.h" +#include "parameters.h" + +struct _Options +{ + const char *SourceFile; + const char *DestFile; + const char *Entry; + char GenerateAssembler; + char Compile; + char Strip; +} Options= +{ + NULL, + NULL, + "main", + 0, + 1, + 0, +}; + +#define SWAP16(v) ((v)>>8)|((v)<<8) +#define SWAP32(v) ((v)>>24)|((v)<<24)|(((v)&0xFF00)<<8)|(((v)&0xFF0000)>>8) + +typedef void*(*_cgCreateContext)(); +typedef void(*_cgDestroyContext)(void *context); +typedef void*(*_cgCreateProgramFromFile)(void* context, int program_type, const char *program, int profile, const char *entry, const char **args); +typedef const char*(*_cgGetProgramString)(void *program,int pname); +typedef const char *(*_cgGetLastListing)(void *context); + +_cgCreateContext cgCreateContext=NULL; +_cgDestroyContext cgDestroyContext=NULL; +_cgCreateProgramFromFile cgCreateProgramFromFile=NULL; +_cgGetProgramString cgGetProgramString=NULL; +_cgGetLastListing cgGetLastListing=NULL; + +void InitCompiler() +{ + HMODULE libcgc=LoadLibrary("cg.dll"); + if(libcgc==NULL) + return; + cgCreateContext=(_cgCreateContext)GetProcAddress(libcgc,"cgCreateContext"); + cgDestroyContext=(_cgDestroyContext)GetProcAddress(libcgc,"cgDestroyContext"); + cgCreateProgramFromFile=(_cgCreateProgramFromFile)GetProcAddress(libcgc,"cgCreateProgramFromFile"); + cgGetProgramString=(_cgGetProgramString)GetProcAddress(libcgc,"cgGetProgramString"); + cgGetLastListing=(_cgGetLastListing)GetProcAddress(libcgc,"cgGetLastListing"); + +} + +void ShowUsage() +{ + printf("vpcomp [options] input output\n"); + printf("\t-a Assemble (do not compile, input an assembly listing instead of .cg\n"); + printf("\t-k Generate intermediate assembler file (.vsa)\n"); + printf("\t-e Entry function (default main)\n"); + printf("\t-s Generate stripped file (no variable names)\n"); + exit(-2); +} + +void ReadOptions(_Options *options,int argc,char **argv) +{ + int i; + + for(i=1;iCompile=0; break; + case 'k': options->GenerateAssembler=1; break; + case 'e': options->Entry=argv[i+1]; ++i; break; + case 's': options->Strip=1; break; + case 'h': ShowUsage(); break; + } + } + else + break; + } + if(i+2!=argc) + ShowUsage(); + options->SourceFile=argv[i]; + options->DestFile=argv[i+1]; +} + +static void fatal(const char *error) +{ + printf("%s\n",error); + exit(-1); +} + + +int main(int argc,char **argv) +{ + char *prg; + _Instruction *insts; + int nInsts; + + ReadOptions(&Options,argc,argv); + + if(Options.Compile) + { + printf("Compiling...\n"); + InitCompiler(); + + if(cgCreateContext==NULL) + { + fatal("Compiling requires NVidia CG.dll"); + } + + void *context=cgCreateContext(); + void *program=cgCreateProgramFromFile(context,4112/*CG_SOURCE*/,Options.SourceFile,/*6148*//*VP30*/7001/*VP40*/,Options.Entry,NULL); + if(program==NULL) + { + const char *error=cgGetLastListing(context); + printf("%s\n",error); + fatal("Error compiling shader"); + } + prg=(char*)cgGetProgramString(program,4106/*CG_COMPILED_PROGRAM*/); + + if(Options.GenerateAssembler) + { + char aux[256]; + strcpy(aux,Options.SourceFile); + strcat(aux,".vsa"); + FILE *f=fopen(aux,"wt"); + fwrite(prg,strlen(prg),1,f); + fclose(f); + } + } + else + { + FILE *f=fopen(Options.SourceFile,"rb"); + if(f==NULL) + fatal("Can't open input file"); + fseek(f,0,SEEK_END); + int sz=ftell(f); + fseek(f,0,SEEK_SET); + prg=(char*)malloc(sz); + fread(prg,sz,1,f); + fclose(f); + } + + printf("Assembling...\n"); + insts=ParseAsm(prg,&nInsts); + + printf("Generating microcode...\n"); + + _Microcode *ucode; + + ucode=GenerateMicrocode(insts,nInsts); + + printf("Scanning attribute & params\n"); + + list<_Parameter> parameters = ScanParameters(prg); + + //allocate a 2MB buffer for the generated vertex program + unsigned char *vertexprogram = (unsigned char*)malloc(2*1024*1024); + unsigned int lastoffset=0; + realityVertexProgram *vp=(realityVertexProgram *) vertexprogram; + + unsigned short magic = ('V'<<8)|'P'; + vp->Magic=SWAP16(magic); + vp->InputMask=SWAP32(ucode->InputMask); + vp->OutputMask=SWAP32(ucode->OutputMask); + + lastoffset=sizeof(realityVertexProgram); + + while(lastoffset&3) //align + { + vertexprogram[lastoffset]=0; + ++lastoffset; + } + + //attributes + realityVertexProgramAttribute *attributes = (realityVertexProgramAttribute*)(vertexprogram+lastoffset); + int n=0; + + vp->AttributesOffset=SWAP32(lastoffset); + + for(list<_Parameter>::iterator i=parameters.begin();i!=parameters.end();++i) + { + if(!i->IsConstant) + { + i->User=lastoffset+n*sizeof(realityVertexProgramAttribute); + attributes[n].Index=SWAP32(i->Index); + attributes[n].NameOffset=SWAP32(0); //will patch it later + ++n; + } + } + vp->NumAttributes=SWAP16(n); + lastoffset+=n*sizeof(realityVertexProgramAttribute); + + while(lastoffset&3) //align + { + vertexprogram[lastoffset]=0; + ++lastoffset; + } + + realityVertexProgramConstant *constants = (realityVertexProgramConstant*)(vertexprogram+lastoffset); + n=0; + + vp->ConstantsOffset=SWAP32(lastoffset); + + for(list<_Parameter>::iterator i=parameters.begin();i!=parameters.end();++i) + { + if(i->IsConstant) + { + i->User=lastoffset+n*sizeof(realityVertexProgramConstant); + constants[n].Index=SWAP32(i->Index); + constants[n].Type=i->Type; + constants[n].Internal=i->IsInternal; + constants[n].Values[0].f=i->Values[0]; + constants[n].Values[0].u=SWAP32(constants[n].Values[0].u); + constants[n].Values[1].f=i->Values[1]; + constants[n].Values[1].u=SWAP32(constants[n].Values[1].u); + constants[n].Values[2].f=i->Values[2]; + constants[n].Values[2].u=SWAP32(constants[n].Values[2].u); + constants[n].Values[3].f=i->Values[3]; + constants[n].Values[3].u=SWAP32(constants[n].Values[3].u); + + constants[n].NameOffset=SWAP32(0); //will patch it later + ++n; + } + } + vp->NumConstants=SWAP16(n); + lastoffset+=n*sizeof(realityVertexProgramConstant); + + if(!Options.Strip) + { + while(lastoffset&3) //align + { + vertexprogram[lastoffset]=0; + ++lastoffset; + } + + //Now the string table + for(list<_Parameter>::iterator i=parameters.begin();i!=parameters.end();++i) + { + if(!i->Name.empty() && !i->IsInternal) + { + const char *str=i->Name.c_str(); + int offset=lastoffset; + while(*str) + { + vertexprogram[lastoffset++]=*str++; + } + vertexprogram[lastoffset++]=0; + //now patch the offset (first dword) + *((unsigned int *) (vertexprogram+i->User))=SWAP32(offset); + } + } + } + + //now the microcode + while(lastoffset&15) //align + { + vertexprogram[lastoffset]=0; + ++lastoffset; + } + + vp->UCodeOffset=SWAP32(lastoffset); + vp->NumInsts=SWAP16(nInsts); + + unsigned int *dstcodeptr = (unsigned int*)(vertexprogram+lastoffset); + unsigned int *srccodeptr = ucode->ucode; + + for(int i=0;itype) + { + case NVFXSR_IMM: + val|=NV40_VP_SRC_REG_TYPE_INPUT<index<<8; + return val; + break; + case NVFXSR_TEMP: + val|=NV40_VP_SRC_REG_TYPE_TEMP<index<index<index; + break; + case NVFXSR_CONST: + val|=NV40_VP_SRC_REG_TYPE_CONST<index<neg) + val|=NV40_VP_SRC_NEGATE; + if(reg->abs) + { + switch(src) + { + case 0: words[0]|=NV40_VP_INST_SRC0_ABS; break; + case 1: words[0]|=NV40_VP_INST_SRC1_ABS; break; + case 2: words[0]|=NV40_VP_INST_SRC2_ABS; break; + } + } + val|=reg->swizzle[0]<swizzle[1]<swizzle[2]<swizzle[3]<unit==NVFX_VP_INST_SLOT_SCA) + { + if(inst->op==NVFX_VP_INST_SCA_OP_BRA || inst->op==NVFX_VP_INST_SCA_OP_CAL || inst->op==NVFX_VP_INST_SCA_OP_RET) + { + words[1]|=inst->op<dstMask<op<dstMask<op<dstMask<updateCC) + words[0]|=NV40_VP_INST_COND_UPDATE_ENABLE; + + if(inst->testCC) + words[0]|=NV40_VP_INST_COND_TEST_ENABLE; + words[0]|=inst->condition<condSwizzle[0]<condSwizzle[1]<condSwizzle[2]<condSwizzle[3]<saturate) + words[0]|=NV40_VP_INST_SATURATE; + + switch(inst->dstType) + { + case NVFXSR_NONE: + words[3]|=NV40_VP_INST_DEST_MASK; + if(inst->unit==NVFX_VP_INST_SLOT_SCA) + words[3]|=NV40_VP_INST_SCA_DEST_TEMP_MASK; + else + words[0]|=NV40_VP_INST_VEC_DEST_TEMP_MASK; + break; + case NVFXSR_TEMP: + words[3]|=NV40_VP_INST_DEST_MASK; + if(inst->unit==NVFX_VP_INST_SLOT_SCA) + words[3]|=inst->dstIndex<dstIndex<dstIndex<unit==NVFX_VP_INST_SLOT_SCA) + { + words[3]|=NV40_VP_INST_SCA_RESULT; + words[3]|=NV40_VP_INST_SCA_DEST_TEMP_MASK; + } + else + { + words[0]|=NV40_VP_INST_VEC_RESULT; + words[0]|=NV40_VP_INST_VEC_DEST_TEMP_MASK; + } + if(inst->dstIndex<7) + UsedOutputs|=1<dstIndex; + else + UsedOutputs|=1<<(inst->dstIndex+7); + break; + } + + tmp=build_src(0,inst->src+0,words,&UsedAttribs); + words[1]|=((tmp&NV40_VP_SRC0_HIGH_MASK)>>NV40_VP_SRC0_HIGH_SHIFT)<src+1,words,&UsedAttribs); + words[2]|=tmp<src+2,words,&UsedAttribs); + words[2]|=((tmp&NV40_VP_SRC2_HIGH_MASK)>>NV40_VP_SRC2_HIGH_SHIFT)<unit!=NVFX_VP_INST_SLOT_SCA) //?? it's reversed + words[3]|=NV40_VP_INST_SCA_RESULT; //?? + + if(i==nInsts-1) + words[3]|=1; //END + + + } + printf("%d instructions\n",nInsts); + printf("Attribute mask %x\n",UsedAttribs); + printf("Output mask %x\n",UsedOutputs); + + microcode.ucode=ucode; + microcode.InputMask=UsedAttribs; + microcode.OutputMask=UsedOutputs; + + return µcode; +} \ No newline at end of file diff --git a/psl1ght/tools/vpcomp/microcode.h b/psl1ght/tools/vpcomp/microcode.h new file mode 100644 index 00000000..7b4d9a51 --- /dev/null +++ b/psl1ght/tools/vpcomp/microcode.h @@ -0,0 +1,16 @@ +#ifndef UCODE_H +#define UCODE_H + + +#include "vpasm.h" + +struct _Microcode +{ + unsigned int *ucode; + unsigned int InputMask; + unsigned int OutputMask; +}; + +_Microcode *GenerateMicrocode(_Instruction *instructions,int nInst); + +#endif