From 6e176f33c506ac6ca6d908857343155a2e5dcc9b Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 4 Mar 2015 22:42:34 +0100 Subject: [PATCH] Geoshader support! --- Manual.md | 12 ++++++--- source/picasso.h | 1 + source/picasso_assembler.cpp | 51 ++++++++++++++++++++++++++++++++++-- source/picasso_frontend.cpp | 13 ++++----- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/Manual.md b/Manual.md index eef5b7f..65603cb 100644 --- a/Manual.md +++ b/Manual.md @@ -137,10 +137,10 @@ Reserves a new integer vector uniform to be preloaded with the specified constan ``` Allocates a new output register, wires it to a certain output property and creates an alias for it that points to the allocated register. The following property names are supported: -- `position` (or `pos`): In vertex shaders, this represents the position of the outputted vertex. +- `position` (or `pos`): Represents the position of the outputted vertex. - `normalquat` (or `nquat`): Under investigation. -- `color` (or `clr`): In vertex shaders, this represents the color of the outputted vertex. Its format is (R, G, B, xx) where R,G,B are values ranging from 0.0 to 1.0. The W component isn't used. -- `texcoord0` (or `tcoord0`): In vertex shaders, this represents the texture coordinate that is fed to the Texture Unit 0. The Z and W components are not used. +- `color` (or `clr`): Represents the color of the outputted vertex. Its format is (R, G, B, xx) where R,G,B are values ranging from 0.0 to 1.0. The W component isn't used. +- `texcoord0` (or `tcoord0`): Represents the texture coordinate that is fed to the Texture Unit 0. The Z and W components are not used. - `texcoord0w` (or `tcoord0w`): Under investigation. - `texcoord1` (or `tcoord1`): As `texcoord0`, but for the Texture Unit 1. - `texcoord2` (or `tcoord2`): As `texcoord0`, but for the Texture Unit 2. @@ -163,6 +163,8 @@ Syntax | Description --------------------------------- | ----------------------------------- `nop` | No operation. `end` | Signals the end of the program. +`emit` | (Geoshader-only) Emits a vertex configured by a prior `setemit`. +`setemit vtxId, emitFlags | (Geoshader-only) Configures a vertex for emission. The `emitFlags` parameter can be omitted. `add rDest, rSrc1, rSrc2` | `dp3 rDest, rSrc1, rSrc2` | `dp4 rDest, rSrc1, rSrc2` | @@ -217,3 +219,7 @@ Syntax | Description - `flag1`: It tests a single flag. - `flag1 && flag2`: It performs AND between the two flags. Optionally, a single `&` may be specified. - `flag1 || flag2`: It performs OR between the two flags. Optionally, a single `|` may be specified. +- `vtxId`: An integer ranging from 0 to 3 specifying the vertex ID used in geoshader vertex emission. +- `emitFlags`: A space delimited combination of the following words: + - `primitive` (or `prim`): Specifies that after emitting the vertex, a primitive should also be emitted. + - `inv` (or `invert`): Specifies that the order of the vertices in the emitted primitive is inverted. diff --git a/source/picasso.h b/source/picasso.h index 7dd87bf..689346a 100644 --- a/source/picasso.h +++ b/source/picasso.h @@ -61,6 +61,7 @@ enum typedef std::vector outputBufType; typedef outputBufType::iterator outputBufIter; +extern bool g_isGeoShader; extern outputBufType g_outputBuf; enum diff --git a/source/picasso_assembler.cpp b/source/picasso_assembler.cpp index c3bd621..a983d6a 100644 --- a/source/picasso_assembler.cpp +++ b/source/picasso_assembler.cpp @@ -7,6 +7,7 @@ static const char* curFile = NULL; static int curLine = -1; +bool g_isGeoShader = false; std::vector g_outputBuf; StackEntry g_stack[MAX_STACK]; @@ -561,9 +562,12 @@ static int parseReg(char* pos, int& outReg, int& outSw, int* idxType = NULL) switch (*pos) { case 'o': // Output registers - case 'v': // Input attributes if (outReg < 0x00 || outReg >= 0x08) - return throwError("invalid input/output register: %s(%d)\n", pos); + return throwError("invalid output register: %s(%d)\n", pos); + break; + case 'v': // Input attributes + if (outReg < 0x00 || outReg >= 0x0F) + return throwError("invalid input register: %s(%d)\n", pos); break; case 'r': // Temporary registers outReg += 0x10; @@ -805,6 +809,46 @@ DEF_COMMAND(formatmova) return 0; } +static inline int parseSetEmitFlags(char* flags, bool& isPrim, bool& isInv) +{ + isPrim = false; + isInv = false; + if (!flags) + return 0; + + mystrtok_pos = flags; + while (char* flag = mystrtok_spc(NULL)) + { + if (stricmp(flag, "prim")==0 || stricmp(flag, "primitive")==0) + isPrim = true; + else if (stricmp(flag, "inv")==0 || stricmp(flag, "invert")==0) + isInv = true; + else + throwError("unknown setemit flag: %s\n", flag); + + } + return 0; +} + +DEF_COMMAND(formatsetemit) +{ + NEXT_ARG(vtxIdStr); + NEXT_ARG_OPT(flagStr, NULL); + ENSURE_NO_MORE_ARGS(); + + ARG_TO_INT(vtxId, vtxIdStr, 0, 3); + bool isPrim, isInv; + safe_call(parseSetEmitFlags(flagStr, isPrim, isInv)); + +#ifdef DEBUG + printf("%s:%02X vtx%d, %s, %s\n", cmdName, opcode, vtxId, isPrim?"true":"false", isInv=?"true":"false"); +#endif + BUF.push_back(FMT_OPCODE(opcode) | ((u32)isInv<<22) | ((u32)isPrim<<23) | (vtxId<<24)); + g_isGeoShader = true; + + return 0; +} + DEF_COMMAND(formatcall) { NEXT_ARG(procName); @@ -967,6 +1011,7 @@ static const cmdTableType cmdTable[] = { DEC_COMMAND(NOP, format0), DEC_COMMAND(END, format0), + DEC_COMMAND(EMIT, format0), DEC_COMMAND(ADD, format1), DEC_COMMAND(DP3, format1), @@ -1009,6 +1054,8 @@ static const cmdTableType cmdTable[] = DEC_COMMAND(MADI, format5i), DEC_COMMAND(MAD, format5), + DEC_COMMAND(SETEMIT, formatsetemit), + { NULL, NULL }, }; diff --git a/source/picasso_frontend.cpp b/source/picasso_frontend.cpp index caa6d7e..83c6dc6 100644 --- a/source/picasso_frontend.cpp +++ b/source/picasso_frontend.cpp @@ -105,7 +105,7 @@ int main(int argc, char* argv[]) f.WriteWord(0x454C5644); // DVLE f.WriteHword(0); // padding? - f.WriteHword(0); // Vertex shader + f.WriteHword(g_isGeoShader ? 1 : 0); // Shader type f.WriteWord(mainIt->second.first); // offset to main f.WriteWord(mainIt->second.first+mainIt->second.second); // offset to end of main f.WriteWord(0); // ??? @@ -192,21 +192,22 @@ int main(int argc, char* argv[]) fprintf(f2, "// Generated by picasso\n"); fprintf(f2, "#pragma once\n"); + const char* prefix = g_isGeoShader ? "GSH" : "VSH"; for (int i = 0; i < g_uniformCount; i ++) { Uniform& u = g_uniformTable[i]; if (u.type == UTYPE_FVEC) - fprintf(f2, "#define SHADER_FVEC_%s 0x%02X\n", u.name, u.pos-0x20); + fprintf(f2, "#define %s_FVEC_%s 0x%02X\n", prefix, u.name, u.pos-0x20); else if (u.type == UTYPE_IVEC) - fprintf(f2, "#define SHADER_IVEC_%s 0x%02X\n", u.name, u.pos-0x80); + fprintf(f2, "#define %s_IVEC_%s 0x%02X\n", prefix, u.name, u.pos-0x80); else if (u.type == UTYPE_BOOL) { if (u.size == 1) - fprintf(f2, "#define SHADER_FLAG_%s BIT(%d)\n", u.name, u.pos-0x88); + fprintf(f2, "#define %s_FLAG_%s BIT(%d)\n", prefix, u.name, u.pos-0x88); else - fprintf(f2, "#define SHADER_FLAG_%s(_n) BIT(%d+(_n))\n", u.name, u.pos-0x88); + fprintf(f2, "#define %s_FLAG_%s(_n) BIT(%d+(_n))\n", prefix, u.name, u.pos-0x88); } - fprintf(f2, "#define SHADER_ULEN_%s %d\n", u.name, u.size); + fprintf(f2, "#define %s_ULEN_%s %d\n", prefix, u.name, u.size); } fclose(f2);