From 33293df1430a875aaa8a2c4428e327a7c3cb7fc2 Mon Sep 17 00:00:00 2001 From: Ivan Gyurdiev <ivg231@gmail.com> Date: Mon, 10 Jul 2006 04:35:15 -0600 Subject: [PATCH] wined3d: More flow control instructions. - Implement call, callnz, label, and ret - Implement support for NOT modifier --- dlls/wined3d/baseshader.c | 12 ++++++++++-- dlls/wined3d/glsl_shader.c | 32 ++++++++++++++++++++++++++++++++ dlls/wined3d/pixelshader.c | 22 ++++++++++++++++++---- dlls/wined3d/vertexshader.c | 12 ++++++++---- dlls/wined3d/wined3d_private.h | 9 +++++++++ 5 files changed, 77 insertions(+), 10 deletions(-) diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 1275dd55ad8..b3823c2ec52 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -277,7 +277,14 @@ HRESULT shader_get_registers_used( D3DSIO_REP == curOpcode->opcode) { reg_maps->loop = 1; pToken += curOpcode->num_params; - + + /* For subroutine prototypes */ + } else if (D3DSIO_LABEL == curOpcode->opcode) { + + DWORD snum = *pToken & D3DSP_REGNUM_MASK; + reg_maps->labels[snum] = 1; + pToken += curOpcode->num_params; + /* Set texture, address, temporary registers */ } else { int i, limit; @@ -683,7 +690,8 @@ void shader_generate_main( D3DSIO_NOP == curOpcode->opcode || D3DSIO_DEF == curOpcode->opcode || D3DSIO_DEFI == curOpcode->opcode || - D3DSIO_DEFB == curOpcode->opcode) { + D3DSIO_DEFB == curOpcode->opcode || + D3DSIO_RET == curOpcode->opcode) { pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index bd91f105475..223a8e01376 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -331,6 +331,12 @@ void shader_generate_glsl_declarations( char pshader = shader_is_pshader_version(This->baseShader.hex_version); char prefix = pshader ? 'P' : 'V'; + /* Prototype the subroutines */ + for (i = 0; i < This->baseShader.limits.label; i++) { + if (reg_maps->labels[i]) + shader_addline(buffer, "void subroutine%lu();\n", i); + } + /* Declare the constants (aka uniforms) */ if (This->baseShader.limits.constant_float > 0) shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, This->baseShader.limits.constant_float); @@ -495,6 +501,9 @@ static void shader_glsl_gen_modifier ( case D3DSPSM_NEG: sprintf(out_str, "-%s%s", in_reg, in_regswizzle); break; + case D3DSPSM_NOT: + sprintf(out_str, "!%s%s", in_reg, in_regswizzle); + break; case D3DSPSM_BIAS: sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); break; @@ -1238,6 +1247,29 @@ void shader_glsl_breakc(SHADER_OPCODE_ARG* arg) { src0_str, shader_get_comp_op(arg->opcode_token), src1_str); } +void shader_glsl_label(SHADER_OPCODE_ARG* arg) { + + DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK; + shader_addline(arg->buffer, "}\n"); + shader_addline(arg->buffer, "void subroutine%lu () {\n", snum); +} + +void shader_glsl_call(SHADER_OPCODE_ARG* arg) { + DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK; + shader_addline(arg->buffer, "subroutine%lu();\n", snum); +} + +void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) { + + char src1_str[100]; + char src1_reg[50]; + char src1_mask[6]; + + DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK; + shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str); + shader_addline(arg->buffer, "if (%s) subroutine%lu();\n", src1_str, snum); +} + /********************************************* * Pixel Shader Specific Code begins here ********************************************/ diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 977cb4e7e28..498380bf692 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -685,12 +685,12 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {D3DSIO_BREAK, "break", NULL, 0, 0, pshader_break, NULL, shader_glsl_break, D3DPS_VERSION(2,1), -1}, {D3DSIO_BREAKC, "breakc", NULL, 0, 2, pshader_breakc, NULL, shader_glsl_breakc, D3DPS_VERSION(2,1), -1}, {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, pshader_breakp, NULL, NULL, 0, 0}, - {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, pshader_call, NULL, NULL, 0, 0}, - {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, pshader_callnz, NULL, NULL, 0, 0}, + {D3DSIO_CALL, "call", NULL, 0, 1, pshader_call, NULL, shader_glsl_call, D3DPS_VERSION(2,1), -1}, + {D3DSIO_CALLNZ, "callnz", NULL, 0, 2, pshader_callnz, NULL, shader_glsl_callnz, D3DPS_VERSION(2,1), -1}, {D3DSIO_LOOP, "loop", NULL, 0, 2, pshader_loop, NULL, shader_glsl_loop, D3DPS_VERSION(3,0), -1}, - {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, pshader_ret, NULL, NULL, 0, 0}, + {D3DSIO_RET, "ret", NULL, 0, 0, pshader_ret, NULL, NULL, D3DPS_VERSION(2,1), -1}, {D3DSIO_ENDLOOP, "endloop", NULL, 0, 0, pshader_endloop, NULL, shader_glsl_end, D3DPS_VERSION(3,0), -1}, - {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, pshader_label, NULL, NULL, 0, 0}, + {D3DSIO_LABEL, "label", NULL, 0, 1, pshader_label, NULL, shader_glsl_label, D3DPS_VERSION(2,1), -1}, /* Constant definitions */ {D3DSIO_DEF, "def", "undefined", 1, 5, pshader_def, NULL, NULL, 0, 0}, @@ -751,6 +751,7 @@ static void pshader_set_limits( This->baseShader.limits.texcoord = 4; This->baseShader.limits.sampler = 4; This->baseShader.limits.packed_input = 0; + This->baseShader.limits.label = 0; break; case D3DPS_VERSION(1,4): @@ -761,10 +762,20 @@ static void pshader_set_limits( This->baseShader.limits.texcoord = 6; This->baseShader.limits.sampler = 6; This->baseShader.limits.packed_input = 0; + This->baseShader.limits.label = 0; break; /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */ case D3DPS_VERSION(2,0): + This->baseShader.limits.temporary = 32; + This->baseShader.limits.constant_float = 32; + This->baseShader.limits.constant_int = 16; + This->baseShader.limits.constant_bool = 16; + This->baseShader.limits.texcoord = 8; + This->baseShader.limits.sampler = 16; + This->baseShader.limits.packed_input = 0; + break; + case D3DPS_VERSION(2,1): This->baseShader.limits.temporary = 32; This->baseShader.limits.constant_float = 32; @@ -773,6 +784,7 @@ static void pshader_set_limits( This->baseShader.limits.texcoord = 8; This->baseShader.limits.sampler = 16; This->baseShader.limits.packed_input = 0; + This->baseShader.limits.label = 16; break; case D3DPS_VERSION(3,0): @@ -783,6 +795,7 @@ static void pshader_set_limits( This->baseShader.limits.texcoord = 0; This->baseShader.limits.sampler = 16; This->baseShader.limits.packed_input = 12; + This->baseShader.limits.label = 16; /* FIXME: 2048 */ break; default: This->baseShader.limits.temporary = 32; @@ -792,6 +805,7 @@ static void pshader_set_limits( This->baseShader.limits.texcoord = 8; This->baseShader.limits.sampler = 16; This->baseShader.limits.packed_input = 0; + This->baseShader.limits.label = 0; FIXME("Unrecognized pixel shader version %#lx\n", This->baseShader.hex_version); } diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 20d1d4097ea..026207997de 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -545,12 +545,12 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = { {D3DSIO_BREAK, "break", NULL, 0, 0, vshader_break, NULL, shader_glsl_break, D3DVS_VERSION(2,1), -1}, {D3DSIO_BREAKC, "breakc", NULL, 0, 2, vshader_breakc, NULL, shader_glsl_breakc, D3DVS_VERSION(2,1), -1}, {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp, NULL, NULL, 0, 0}, - {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, vshader_call, NULL, NULL, 0, 0}, - {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, vshader_callnz, NULL, NULL, 0, 0}, + {D3DSIO_CALL, "call", NULL, 0, 1, vshader_call, NULL, shader_glsl_call, D3DVS_VERSION(2,0), -1}, + {D3DSIO_CALLNZ, "callnz", NULL, 0, 2, vshader_callnz, NULL, shader_glsl_callnz, D3DVS_VERSION(2,0), -1}, {D3DSIO_LOOP, "loop", NULL, 0, 2, vshader_loop, NULL, shader_glsl_loop, D3DVS_VERSION(2,0), -1}, - {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, vshader_ret, NULL, NULL, 0, 0}, + {D3DSIO_RET, "ret", NULL, 0, 0, vshader_ret, NULL, NULL, D3DVS_VERSION(2,0), -1}, {D3DSIO_ENDLOOP, "endloop", NULL, 0, 0, vshader_endloop, NULL, shader_glsl_end, D3DVS_VERSION(2,0), -1}, - {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, vshader_label, NULL, NULL, 0, 0}, + {D3DSIO_LABEL, "label", NULL, 0, 1, vshader_label, NULL, shader_glsl_label, D3DVS_VERSION(2,0), -1}, {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova, NULL, shader_glsl_mov, 0, 0}, {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 1, 3, vshader_setp, NULL, NULL, 0, 0}, @@ -577,6 +577,7 @@ static void vshader_set_limits( This->baseShader.limits.address = 1; This->baseShader.limits.packed_output = 0; This->baseShader.limits.sampler = 0; + This->baseShader.limits.label = 0; break; case D3DVS_VERSION(2,0): @@ -587,6 +588,7 @@ static void vshader_set_limits( This->baseShader.limits.address = 1; This->baseShader.limits.packed_output = 0; This->baseShader.limits.sampler = 0; + This->baseShader.limits.label = 16; break; case D3DVS_VERSION(3,0): @@ -596,6 +598,7 @@ static void vshader_set_limits( This->baseShader.limits.address = 1; This->baseShader.limits.packed_output = 12; This->baseShader.limits.sampler = 4; + This->baseShader.limits.label = 16; /* FIXME: 2048 */ break; default: This->baseShader.limits.temporary = 12; @@ -604,6 +607,7 @@ static void vshader_set_limits( This->baseShader.limits.address = 1; This->baseShader.limits.packed_output = 0; This->baseShader.limits.sampler = 0; + This->baseShader.limits.label = 16; FIXME("Unrecognized vertex shader version %#lx\n", This->baseShader.hex_version); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5102e7caa2a..c1ce7634bb5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1282,6 +1282,10 @@ struct glsl_shader_prog_link { #define MAX_CONST_I 16 #define MAX_CONST_B 16 +/* FIXME: This needs to go up to 2048 for + * Shader model 3 according to msdn (and for software shaders) */ +#define MAX_LABELS 16 + typedef struct semantic { DWORD usage; DWORD reg; @@ -1301,6 +1305,7 @@ typedef struct shader_reg_maps { char packed_input[MAX_REG_INPUT]; /* pshader >= 3.0 */ char packed_output[MAX_REG_OUTPUT]; /* vertex >= 3.0 */ char attributes[MAX_ATTRIBS]; /* vertex */ + char labels[MAX_LABELS]; /* pixel, vertex */ /* Sampler usage tokens * Use 0 as default (bit 31 is always 1 on a valid token) */ @@ -1368,6 +1373,7 @@ typedef struct SHADER_LIMITS { unsigned int packed_output; unsigned int packed_input; unsigned int attributes; + unsigned int label; } SHADER_LIMITS; /** Keeps track of details for TEX_M#x# shader opcodes which need to @@ -1463,6 +1469,9 @@ extern void shader_glsl_else(SHADER_OPCODE_ARG* arg); extern void shader_glsl_break(SHADER_OPCODE_ARG* arg); extern void shader_glsl_breakc(SHADER_OPCODE_ARG* arg); extern void shader_glsl_rep(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_call(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_callnz(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_label(SHADER_OPCODE_ARG* arg); /** GLSL Pixel Shader Prototypes */ extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg); -- GitLab