From 8ff5c497e783111ec503a98003df78edfd3c3694 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Wed, 13 Sep 2017 20:57:33 +0100 Subject: [PATCH] Started back-porting Dxbx pixel shaders --- src/CxbxKrnl/EmuD3D8/PixelShader.h | 242 ++++++++++++++++++++++++++++- 1 file changed, 237 insertions(+), 5 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8/PixelShader.h b/src/CxbxKrnl/EmuD3D8/PixelShader.h index 550742465..3278ad38d 100644 --- a/src/CxbxKrnl/EmuD3D8/PixelShader.h +++ b/src/CxbxKrnl/EmuD3D8/PixelShader.h @@ -1,8 +1,8 @@ // ****************************************************************** // * // * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' +// * ,;;;"````" `;;;, .,;; ;;;"";;" `;;;, .,;; +// * [[[ "[[,,[[" [[[__[[\. "[[,,[[" // * $$$ Y$$$P $$""""Y$$ Y$$$P // * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, // * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, @@ -34,6 +34,8 @@ #ifndef PIXELSHADER_H #define PIXELSHADER_H +#pragma once + #include "Cxbx.h" /*---------------------------------------------------------------------------*/ @@ -413,10 +415,240 @@ enum PS_GLOBALFLAGS // change PS_TEXTUREMODES_PROJECT3D to PS_TEXTUREMODES_PROJECT2D // change PS_TEXTUREMODES_CUBEMAP to PS_TEXTUREMODES_PROJECT2D - PS_GLOBALFLAGS_NO_TEXMODE_ADJUST= 0x0000L, // don't adjust texture modes + PS_GLOBALFLAGS_NO_TEXMODE_ADJUST= 0x0000L, // don"t adjust texture modes PS_GLOBALFLAGS_TEXMODE_ADJUST= 0x0001L, // adjust texture modes according to set texture }; +#if 0 // Dxbx translation + +enum PSH_OPCODE +{ + PO_COMMENT, + PO_PS, + PO_DEF, +#ifdef CXBX_USE_PS_2_0 + PO_DCL, +#endif + PO_TEX, + PO_TEXBEM, + PO_TEXBEML, + PO_TEXBRDF, // Xbox ext. + PO_TEXCOORD, + PO_TEXKILL, + PO_TEXDP3, // Note : ps.1.3 only + PO_TEXDP3TEX, // Note : ps.1.3 only + PO_TEXM3X2TEX, + PO_TEXM3X2DEPTH, // Note : requires ps.1.3 and a preceding texm3x2pad + PO_TEXM3X3DIFF, // Xbox ext. + PO_TEXM3X3VSPEC, + PO_TEXM3X3TEX, // Note : Uses a cube texture + PO_TEXREG2AR, + PO_TEXREG2GB, + PO_TEXM3X2PAD, // Note : Must be combined with texm3x2tex or texm3x2depth + PO_TEXM3X3PAD, + PO_TEXM3X3SPEC, // NOTE : NEEDS 3 ARGUMENTS! + // Direct3D8 arithmetic instructions : + PO_ADD, + PO_CMP, + PO_CND, + PO_DP3, // dp3 d, s1,s2 : d=s0 dot s1 (replicated to all channels, .rgb=color only, .a=color+alpha) + PO_DP4, // dp3 d, s1,s2 : d.r=d.g=d.b=d.a=(s1.r*s2.r)+(s1.g*s2.g)+(s1.b*s2.b)+(s1.a*s2.a) + PO_LRP, + PO_MAD, + PO_MOV, + PO_MUL, + PO_NOP, + PO_SUB, + // Xbox1 opcodes : + PO_XMMA, + PO_XMMC, + PO_XDM, + PO_XDD, + PO_XFC +}; + +const struct { char *mn; int _Out; int _In; char *note; } PSH_OPCODE_DEFS[/*PSH_OPCODE*/] = { + // Pixel shader header opcodes (must be specified in this order) : + {/* PO_COMMENT */ /*mn:*/";", /*_Out: */ 0, /*_In: */ 0, /*note:*/""}, // + {/* PO_PS */ /*mn:*/"ps", /*_Out: */ 0, /*_In: */ 0, /*note:*/""}, // Must occur once, Xbox needs an x prefix {xps}, Native needs a 1.3 suffix {ps.1.3} + {/* PO_DEF */ /*mn:*/"def", /*_Out: */ 1, /*_In: */ 4, /*note:*/""}, // Output must be a PARAM_C, arguments must be 4 floats [0.00f .. 1.00f] +#ifdef CXBX_USE_PS_2_0 + {/* PO_DCL */ /*mn:*/"dcl", /*_Out: */ 1, /*_In: */ 0, /*note:*/""}, +#endif + {/* PO_TEX */ /*mn:*/"tex", /*_Out: */ 1, /*_In: */ 0, /*note:*/""}, + {/* PO_TEXBEM */ /*mn:*/"texbem", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXBEML */ /*mn:*/"texbeml", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXBRDF */ /*mn:*/"texbrdf", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, // /*note: */ Not supported by Direct3D8 ? + {/* PO_TEXCOORD */ /*mn:*/"texcoord", /*_Out: */ 1, /*_In: */ 0, /*note:*/""}, + {/* PO_TEXKILL */ /*mn:*/"texkill", /*_Out: */ 1, /*_In: */ 0, /*note:*/""}, + {/* PO_TEXDP3 */ /*mn:*/"texdp3", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXDP3TEX */ /*mn:*/"texdp3tex", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X2TEX */ /*mn:*/"texm3x2tex", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X2DEPTH */ /*mn:*/"texm3x2depth", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, // /*note: */ requires ps.1.3 and a preceding texm3x2pad + {/* PO_TEXM3X3DIFF */ /*mn:*/"texm3x3diff", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, // /*note: */ Not supported by Direct3D8 ? + {/* PO_TEXM3X3VSPEC */ /*mn:*/"texm3x3vspec", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X3TEX */ /*mn:*/"texm3x3tex", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, // /*note: */ Uses a cube texture + {/* PO_TEXREG2AR */ /*mn:*/"texreg2ar", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXREG2GB */ /*mn:*/"texreg2gb", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X2PAD */ /*mn:*/"texm3x2pad", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X3PAD */ /*mn:*/"texm3x3pad", /*_Out: */ 1, /*_In: */ 1, /*note:*/""}, + {/* PO_TEXM3X3SPEC */ /*mn:*/"texm3x3spec", /*_Out: */ 1, /*_In: */ 2, /*note:*/""}, + // Arithmetic opcodes : + {/* PO_ADD */ /*mn:*/"add", /*_Out: */ 1, /*_In: */ 2, /*note:*/"d0=s0+s1"}, + {/* PO_CMP */ /*mn:*/"cmp", /*_Out: */ 1, /*_In: */ 3, /*note:*/"d0={s0>=0?s1:s2}"}, + {/* PO_CND */ /*mn:*/"cnd", /*_Out: */ 1, /*_In: */ 3, /*note:*/"d1={s0.a>0.5?s1:s2}"}, // 1st input must be "r0.a" + {/* PO_DP3 */ /*mn:*/"dp3", /*_Out: */ 1, /*_In: */ 2, /*note:*/"d0=s0 dot3 s1"}, + {/* PO_DP4 */ /*mn:*/"dp4", /*_Out: */ 1, /*_In: */ 2, /*note:*/"d0=s0 dot4 s1"}, + {/* PO_LRP */ /*mn:*/"lrp", /*_Out: */ 1, /*_In: */ 3, /*note:*/"d0=s0*s1+{1-s0}*s2=s0*{s1-s2}+s2"}, + {/* PO_MAD */ /*mn:*/"mad", /*_Out: */ 1, /*_In: */ 3, /*note:*/"d0=s0*s1+s2"}, + {/* PO_MOV */ /*mn:*/"mov", /*_Out: */ 1, /*_In: */ 1, /*note:*/"d0=s0"}, + {/* PO_MUL */ /*mn:*/"mul", /*_Out: */ 1, /*_In: */ 2, /*note:*/"d0=s0*s1"}, + {/* PO_NOP */ /*mn:*/"nop", /*_Out: */ 0, /*_In: */ 0, /*note:*/""}, + {/* PO_SUB */ /*mn:*/"sub", /*_Out: */ 1, /*_In: */ 2, /*note:*/"d0=s0-s1"}, + // Xbox-only {NV2A} opcodes : + {/* PO_XMMA */ /*mn:*/"xmma", /*_Out: */ 3, /*_In: */ 4, /*note:*/"d0=s0*s1, d1=s2*s3, d2={s0*s1}+{s2*s3}"}, + {/* PO_XMMC */ /*mn:*/"xmmc", /*_Out: */ 3, /*_In: */ 4, /*note:*/"d0=s0*s1, d1=s2*s3, d2={r0.a>0.5}?{s0*s1}:{s2*s3}"}, + {/* PO_XDM */ /*mn:*/"xdm", /*_Out: */ 2, /*_In: */ 4, /*note:*/"d0=s0 dot s1, d1=s2*s3"}, + {/* PO_XDD */ /*mn:*/"xdd", /*_Out: */ 2, /*_In: */ 4, /*note:*/"d0=s0 dot s1, d1=s2 dot s3"}, + {/* PO_XFC */ /*mn:*/"xfc", /*_Out: */ 0, /*_In: */ 7, /*note:*/"r0.rgb=s0*s1+{1-s0}*s2+s3, r0.a=s6.a, prod=s4*s5, sum=r0+v1"} +}; + +enum PSH_ARGUMENT_TYPE +{ + PARAM_VALUE, // Xbox only; Numberic constants used in Xbox-only opcodes + PARAM_DISCARD, // Xbox only; + PARAM_FOG, // Final combiner only; Read-only register fog register + PARAM_V1R0_SUM, // Final combiner only; Read-only register that contains the result of V1+R0 + PARAM_EF_PROD, // Final combiner only; Read-only register that contains the result of final combiner parameters E * F + PARAM_R, // Temporary registers (unassigned except r0.a, which on NV2A is initially set to t0.a) + PARAM_T, // Textures + PARAM_V, // Vertex colors + PARAM_C // Constant registers, set by def opcodes or SetPixelShaderConstant +}; + +const char *PSH_ARGUMENT_TYPE_Str[/*PSH_ARGUMENT_TYPE*/] = { + // Prefix # r/w Input? Output? Note + "", // * r No No Used for numeric constants like -1, 0, 1 + "discard", // * w No Yes Only for xbox opcodes (native opcodes have single output - discards must be removed) + "fog", // 1 r Yes No Only for final combiner parameter + "sum", // 1 r Yes No Only for final combiner parameter + "prod", // 1 r Yes No Only for final combiner parameter + "r", // 2 r/w Yes Yes We fake a few extra registers and resolve them in FixupPixelShader + "t", // 4 r/w Yes Yes D3D9 cannot write to these! + "v", // 2 r Yes Yes + "c" // 16 r Yes No Xbox has 8*c0,c1=16, while PC D3D8 has only 8, we try to reduce that in FixupPixelShader +}; + +const +int FakeRegNr_Sum = 2; +int FakeRegNr_Prod = 3; +int FakeRegNr_Xmm1 = 4; +int FakeRegNr_Xmm2 = 5; + +// TODO : Translate From Dxbx : +//const +//int XFC_COMBINERSTAGENR = X_PSH_COMBINECOUNT; // Always call XFC "stage 9", 1 after the 8th combiner + +int PSH_XBOX_MAX_C_REGISTER_COUNT = 16; +int PSH_XBOX_MAX_R_REGISTER_COUNT = 2; +int PSH_XBOX_MAX_T_REGISTER_COUNT = 4; +int PSH_XBOX_MAX_V_REGISTER_COUNT = 2; +// Extra constants to support features not present in Native D3D : +int PSH_XBOX_CONSTANT_FOG = PSH_XBOX_MAX_C_REGISTER_COUNT; // = 16 +int PSH_XBOX_CONSTANT_FC0 = PSH_XBOX_CONSTANT_FOG + 1; // = 17 +int PSH_XBOX_CONSTANT_FC1 = PSH_XBOX_CONSTANT_FC0 + 1; // = 18 +int PSH_XBOX_CONSTANT_MAX = PSH_XBOX_CONSTANT_FC1 + 1; // = 19 + +#ifdef CXBX_USE_PS_3_0 +int PSH_PC_MAX_C_REGISTER_COUNT = 224; // ps 3.0 +int PSH_PC_MAX_R_REGISTER_COUNT = 32; // ps 3.0 +int PSH_PC_MAX_S_REGISTER_COUNT = 16; // ps 3.0 +int PSH_PC_MAX_V_REGISTER_COUNT = 10; // ps 3.0 +int PSH_PC_MAX_REGISTER_COUNT = 224; +#else +#ifdef CXBX_USE_PS_2_0 +int PSH_PC_MAX_C_REGISTER_COUNT = 32; // ps 2.0 +int PSH_PC_MAX_R_REGISTER_COUNT = 12; // ps 2.0 +int PSH_PC_MAX_S_REGISTER_COUNT = 16; // ps 2.0 +int PSH_PC_MAX_T_REGISTER_COUNT = 8; // ps 2.0 +int PSH_PC_MAX_V_REGISTER_COUNT = 2; // ps 2.0 +int PSH_PC_MAX_REGISTER_COUNT = 32; +#else // CXBX_USE_PS_1_3 +int PSH_PC_MAX_C_REGISTER_COUNT = 8; // ps 1.3 +int PSH_PC_MAX_R_REGISTER_COUNT = 2; // ps 1.3 +int PSH_PC_MAX_T_REGISTER_COUNT = 4; // ps 1.3 +int PSH_PC_MAX_V_REGISTER_COUNT = 2; // ps 1.3 +int PSH_PC_MAX_REGISTER_COUNT = 8; +#endif +#endif + +enum PSH_INST_MODIFIER { + INSMOD_NONE, // y = x + INSMOD_BIAS, // y = x - 0.5 // Xbox only : TODO : Fixup occurrances! + INSMOD_X2, // y = x * 2 + INSMOD_BX2, // y = (x - 0.5) * 2 // Xbox only : TODO : Fixup occurrances! + INSMOD_X4, // y = x * 4 + INSMOD_D2, // y = x * 0.5 + INSMOD_SAT // Xbox doesn"t support this, but has ARGMOD_SATURATE instead +}; + +const char *PSH_INST_MODIFIER_Str[/*PSH_INST_MODIFIER*/] = { + "", + "_bias", + "_x2", + "_bx2", + "_x4", + "_d2", + "_sat" +}; + +// Four argument modifiers (applied in this order) : +// 1: Inversion (invert or negate : "1-" or "-") +// 2: Apply bias ("_bias") +// 3: Apply scale ("_x2", "_bx2", "_x4", or "_d2") +// 4: Apply clamp ("_sat") +enum PSH_ARG_MODIFIER { + ARGMOD_IDENTITY, // y = x + + ARGMOD_INVERT, // y = 1-x -> 0..1 > 1..0 + ARGMOD_NEGATE, // y = -x -> 0..1 > 0..-1 + + ARGMOD_BIAS, // y = x-0.5 -> 0..1 > -0.5..0.5 + + ARGMOD_SCALE_X2, // y = x*2 -> 0..1 > 0..2 + ARGMOD_SCALE_BX2, // y = (x*2)-1 -> 0..1 > -1..1 + ARGMOD_SCALE_X4, // y = x*4 -> 0..1 > 0..4 + ARGMOD_SCALE_D2, // y = x/2 -> 0..1 > 0..0.5 + + ARGMOD_SATURATE, // Xbox - not available in PS1.3 (can be done on output instead) + + ARGMOD_ALPHA_REPLICATE, + ARGMOD_BLUE_REPLICATE // PS1.1-PS1.3 only allow this if destination writemask = .a +}; +// TODO : Translate From Dxbx : +// PSH_ARG_MODIFIERs = set of PSH_ARG_MODIFIER; + +const char *PSH_ARG_MODIFIER_Str[/*PSH_ARG_MODIFIER*/] = { + "%s", + + "1-%s", + "-%s", + + "%s_bias", + + "%s_x2", + "%s_bx2", + "%s_x4", + "%s_d2", + + "%s_sat", + + "%s", // .a is added via Mask + "%s" // .b idem +}; + +#endif // 0 Dxbx translation + // dump pixel shader definition to file void DumpPixelShaderDefToFile( X_D3DPIXELSHADERDEF* pPSDef, const char* pszCode ); // print relevant contents to the debug console @@ -425,7 +657,7 @@ void PrintPixelShaderDefContents( X_D3DPIXELSHADERDEF* pDSDef ); HRESULT EmuRecompilePshDef( X_D3DPIXELSHADERDEF* pPSDef, LPD3DXBUFFER* ppRecompiled ); /* - * Kingofc's pixel shader functions + * Kingofc"s pixel shader functions */ // Pixel Shader Stuff HRESULT CreatePixelShaderFunction(X_D3DPIXELSHADERDEF *pPSD, LPD3DXBUFFER* ppRecompiled); @@ -441,4 +673,4 @@ inline void null_func_psh(...) { } #define DbgPshPrintf XTL::null_func_psh #endif -#endif \ No newline at end of file +#endif // PIXELSHADER_H \ No newline at end of file