shader.c revision 058c0c53c37f5cb271aeb3c385c10766f84f4aef
/*
* Copyright 2002-2003 Jason Edmeades
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2006 Ivan Gyurdiev
* Copyright 2007-2008, 2013 Stefan Dösinger for CodeWeavers
* Copyright 2009-2011 Henri Verbeet for CodeWeavers
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "wined3d_private.h"
#ifdef VBOX_WINE_WITH_SHADER_CACHE
#endif
static const char * const shader_opcode_names[] =
{
/* WINED3DSIH_ABS */ "abs",
/* WINED3DSIH_ADD */ "add",
/* WINED3DSIH_AND */ "and",
/* WINED3DSIH_BEM */ "bem",
/* WINED3DSIH_BREAK */ "break",
/* WINED3DSIH_BREAKC */ "breakc",
/* WINED3DSIH_BREAKP */ "breakp",
/* WINED3DSIH_CALL */ "call",
/* WINED3DSIH_CALLNZ */ "callnz",
/* WINED3DSIH_CMP */ "cmp",
/* WINED3DSIH_CND */ "cnd",
/* WINED3DSIH_CRS */ "crs",
/* WINED3DSIH_CUT */ "cut",
/* WINED3DSIH_DCL */ "dcl",
/* WINED3DSIH_DCL_CONSTANT_BUFFER */ "dcl_constantBuffer",
/* WINED3DSIH_DCL_INPUT_PRIMITIVE */ "dcl_inputPrimitive",
/* WINED3DSIH_DCL_OUTPUT_TOPOLOGY */ "dcl_outputTopology",
/* WINED3DSIH_DCL_VERTICES_OUT */ "dcl_maxOutputVertexCount",
/* WINED3DSIH_DEF */ "def",
/* WINED3DSIH_DEFB */ "defb",
/* WINED3DSIH_DEFI */ "defi",
/* WINED3DSIH_DIV */ "div",
/* WINED3DSIH_DP2ADD */ "dp2add",
/* WINED3DSIH_DP3 */ "dp3",
/* WINED3DSIH_DP4 */ "dp4",
/* WINED3DSIH_DST */ "dst",
/* WINED3DSIH_DSX */ "dsx",
/* WINED3DSIH_DSY */ "dsy",
/* WINED3DSIH_ELSE */ "else",
/* WINED3DSIH_EMIT */ "emit",
/* WINED3DSIH_ENDIF */ "endif",
/* WINED3DSIH_ENDLOOP */ "endloop",
/* WINED3DSIH_ENDREP */ "endrep",
/* WINED3DSIH_EQ */ "eq",
/* WINED3DSIH_EXP */ "exp",
/* WINED3DSIH_EXPP */ "expp",
/* WINED3DSIH_FRC */ "frc",
/* WINED3DSIH_FTOI */ "ftoi",
/* WINED3DSIH_GE */ "ge",
/* WINED3DSIH_IADD */ "iadd",
/* WINED3DSIH_IEQ */ "ieq",
/* WINED3DSIH_IF */ "if",
/* WINED3DSIH_IFC */ "ifc",
/* WINED3DSIH_IGE */ "ige",
/* WINED3DSIH_IMUL */ "imul",
/* WINED3DSIH_ITOF */ "itof",
/* WINED3DSIH_LABEL */ "label",
/* WINED3DSIH_LD */ "ld",
/* WINED3DSIH_LIT */ "lit",
/* WINED3DSIH_LOG */ "log",
/* WINED3DSIH_LOGP */ "logp",
/* WINED3DSIH_LOOP */ "loop",
/* WINED3DSIH_LRP */ "lrp",
/* WINED3DSIH_LT */ "lt",
/* WINED3DSIH_M3x2 */ "m3x2",
/* WINED3DSIH_M3x3 */ "m3x3",
/* WINED3DSIH_M3x4 */ "m3x4",
/* WINED3DSIH_M4x3 */ "m4x3",
/* WINED3DSIH_M4x4 */ "m4x4",
/* WINED3DSIH_MAD */ "mad",
/* WINED3DSIH_MAX */ "max",
/* WINED3DSIH_MIN */ "min",
/* WINED3DSIH_MOV */ "mov",
/* WINED3DSIH_MOVA */ "mova",
/* WINED3DSIH_MOVC */ "movc",
/* WINED3DSIH_MUL */ "mul",
/* WINED3DSIH_NOP */ "nop",
/* WINED3DSIH_NRM */ "nrm",
/* WINED3DSIH_PHASE */ "phase",
/* WINED3DSIH_POW */ "pow",
/* WINED3DSIH_RCP */ "rcp",
/* WINED3DSIH_REP */ "rep",
/* WINED3DSIH_RET */ "ret",
/* WINED3DSIH_ROUND_NI */ "round_ni",
/* WINED3DSIH_RSQ */ "rsq",
/* WINED3DSIH_SAMPLE */ "sample",
/* WINED3DSIH_SAMPLE_GRAD */ "sample_d",
/* WINED3DSIH_SAMPLE_LOD */ "sample_l",
/* WINED3DSIH_SETP */ "setp",
/* WINED3DSIH_SGE */ "sge",
/* WINED3DSIH_SGN */ "sgn",
/* WINED3DSIH_SINCOS */ "sincos",
/* WINED3DSIH_SLT */ "slt",
/* WINED3DSIH_SQRT */ "sqrt",
/* WINED3DSIH_SUB */ "sub",
/* WINED3DSIH_TEX */ "texld",
/* WINED3DSIH_TEXBEM */ "texbem",
/* WINED3DSIH_TEXBEML */ "texbeml",
/* WINED3DSIH_TEXCOORD */ "texcrd",
/* WINED3DSIH_TEXDEPTH */ "texdepth",
/* WINED3DSIH_TEXDP3 */ "texdp3",
/* WINED3DSIH_TEXDP3TEX */ "texdp3tex",
/* WINED3DSIH_TEXKILL */ "texkill",
/* WINED3DSIH_TEXLDD */ "texldd",
/* WINED3DSIH_TEXLDL */ "texldl",
/* WINED3DSIH_TEXM3x2DEPTH */ "texm3x2depth",
/* WINED3DSIH_TEXM3x2PAD */ "texm3x2pad",
/* WINED3DSIH_TEXM3x2TEX */ "texm3x2tex",
/* WINED3DSIH_TEXM3x3 */ "texm3x3",
/* WINED3DSIH_TEXM3x3DIFF */ "texm3x3diff",
/* WINED3DSIH_TEXM3x3PAD */ "texm3x3pad",
/* WINED3DSIH_TEXM3x3SPEC */ "texm3x3spec",
/* WINED3DSIH_TEXM3x3TEX */ "texm3x3tex",
/* WINED3DSIH_TEXM3x3VSPEC */ "texm3x3vspec",
/* WINED3DSIH_TEXREG2AR */ "texreg2ar",
/* WINED3DSIH_TEXREG2GB */ "texreg2gb",
/* WINED3DSIH_TEXREG2RGB */ "texreg2rgb",
/* WINED3DSIH_UDIV */ "udiv",
/* WINED3DSIH_USHR */ "ushr",
/* WINED3DSIH_UTOF */ "utof",
/* WINED3DSIH_XOR */ "xor",
};
static const char * const semantic_names[] =
{
/* WINED3D_DECL_USAGE_POSITION */ "SV_POSITION",
/* WINED3D_DECL_USAGE_BLEND_WEIGHT */ "BLENDWEIGHT",
/* WINED3D_DECL_USAGE_BLEND_INDICES */ "BLENDINDICES",
/* WINED3D_DECL_USAGE_NORMAL */ "NORMAL",
/* WINED3D_DECL_USAGE_PSIZE */ "PSIZE",
/* WINED3D_DECL_USAGE_TEXCOORD */ "TEXCOORD",
/* WINED3D_DECL_USAGE_TANGENT */ "TANGENT",
/* WINED3D_DECL_USAGE_BINORMAL */ "BINORMAL",
/* WINED3D_DECL_USAGE_TESS_FACTOR */ "TESSFACTOR",
/* WINED3D_DECL_USAGE_POSITIONT */ "POSITIONT",
/* WINED3D_DECL_USAGE_COLOR */ "COLOR",
/* WINED3D_DECL_USAGE_FOG */ "FOG",
/* WINED3D_DECL_USAGE_DEPTH */ "DEPTH",
/* WINED3D_DECL_USAGE_SAMPLE */ "SAMPLE",
};
{
{
return "UNRECOGNIZED";
}
return semantic_names[usage];
}
{
unsigned int i;
for (i = 0; i < sizeof(semantic_names) / sizeof(*semantic_names); ++i)
{
}
return ~0U;
}
{
}
static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e,
const struct wined3d_shader_semantic *s)
{
e->semantic_idx = s->usage_idx;
e->sysval_semantic = 0;
e->component_type = 0;
}
static void shader_signature_from_usage(struct wined3d_shader_signature_element *e,
{
e->semantic_idx = usage_idx;
e->sysval_semantic = 0;
e->component_type = 0;
e->register_idx = reg_idx;
e->mask = write_mask;
}
{
switch (version_token >> 16)
{
case WINED3D_SM1_VS:
case WINED3D_SM1_PS:
return &sm1_shader_frontend;
case WINED3D_SM4_PS:
case WINED3D_SM4_VS:
case WINED3D_SM4_GS:
return &sm4_shader_frontend;
default:
return NULL;
}
}
{
buffer->content_size = 0;
}
{
{
ERR("Failed to allocate shader buffer memory.\n");
return FALSE;
}
return TRUE;
}
{
}
{
int rc;
char *new_buffer;
while(1)
{
{
if (!new_buffer)
{
ERR("The buffer allocated for the shader program string is too small at %d bytes.\n", buffer->buffer_size);
return -1;
}
}
else
{
break;
}
}
{
}
else
{
}
{
}
return 0;
}
{
int ret;
return ret;
}
{
}
/* Convert floating point offset relative to a register file to an absolute
* offset for float constants. */
static unsigned int shader_get_float_offset(enum wined3d_shader_register_type register_type, UINT register_idx)
{
switch (register_type)
{
case WINED3DSPR_CONST: return register_idx;
default:
return register_idx;
}
}
{
struct wined3d_shader_lconst *constant;
while (ptr)
{
}
}
{
}
static void shader_record_register_usage(struct wined3d_shader *shader, struct wined3d_shader_reg_maps *reg_maps,
{
{
case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
else
break;
case WINED3DSPR_TEMP:
break;
case WINED3DSPR_INPUT:
if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
{
{
/* If relative addressing is used, we must assume that all registers
* are used. Even if it is a construct like v3[aL], we can't assume
* that v0, v1 and v2 aren't read because aL can be negative */
unsigned int i;
for (i = 0; i < MAX_REG_INPUT; ++i)
{
}
}
else
{
}
}
else
break;
case WINED3DSPR_RASTOUT:
break;
case WINED3DSPR_MISCTYPE:
if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
{
}
break;
case WINED3DSPR_CONST:
{
}
else
{
}
break;
case WINED3DSPR_CONSTINT:
break;
case WINED3DSPR_CONSTBOOL:
break;
case WINED3DSPR_COLOROUT:
break;
default:
TRACE("Not recording register of type %#x and [%#x][%#x].\n",
break;
}
}
static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param)
{
switch (instr)
{
case WINED3DSIH_M4x4:
case WINED3DSIH_M3x4:
case WINED3DSIH_M4x3:
case WINED3DSIH_M3x3:
case WINED3DSIH_M3x2:
default:
return 0;
}
}
/* Note that this does not count the loop register as an address register. */
static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe,
struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size)
{
unsigned int cur_loop_depth = 0, max_loop_depth = 0;
struct wined3d_shader_version shader_version;
reg_maps->min_rel_offset = ~0U;
{
ERR("Failed to allocate constant map memory.\n");
return E_OUTOFMEMORY;
}
{
struct wined3d_shader_instruction ins;
/* Fetch opcode. */
/* Unhandled opcode, and its parameters. */
{
TRACE("Skipping unrecognized instruction.\n");
continue;
}
/* Handle declarations. */
{
{
/* Mark input registers used. */
case WINED3DSPR_INPUT:
break;
/* Vertex shader: mark 3.0 output registers used, save token. */
case WINED3DSPR_OUTPUT:
break;
/* Save sampler usage token. */
case WINED3DSPR_SAMPLER:
break;
default:
break;
}
}
{
else
}
{
else
FIXME("Invalid instruction %#x for shader type %#x.\n",
}
{
else
FIXME("Invalid instruction %#x for shader type %#x.\n",
}
{
else
FIXME("Invalid instruction %#x for shader type %#x.\n",
}
{
float *value;
if (!lconst) return E_OUTOFMEMORY;
/* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
{
}
{
}
}
{
if (!lconst) return E_OUTOFMEMORY;
}
{
if (!lconst) return E_OUTOFMEMORY;
}
/* For subroutine prototypes. */
{
}
/* Set texture, address, temporary registers. */
else
{
unsigned int i;
/* This will loop over all the registers and try to
* make a bitmask of the ones we're interested in.
*
* Relative addressing tokens are ignored, but that's
* okay, since we'll catch any address registers when
* they are initialized (required by spec). */
{
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
* is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
* shaders because TECRDOUT isn't used in them, but future register types might cause issues */
{
{
case WINED3DSPR_RASTOUT:
switch (idx)
{
case 0: /* oPos */
break;
case 1: /* oFog */
break;
case 2: /* oPts */
break;
}
break;
case WINED3DSPR_ATTROUT:
if (idx < 2)
{
idx += 8;
{
}
else
{
}
}
break;
case WINED3DSPR_TEXCRDOUT:
{
}
else
{
}
break;
default:
break;
}
}
{
{
/* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
* COLOROUT 0. If we know this in advance, the ARB shader backend can skip
* the mov and perform the sRGB write correction from the source register.
*
* However, if the mov is only partial, we can't do this, and if the write
* comes from an instruction other than MOV it is hard to do as well. If
* COLOROUT 0 is overwritten partially later, the marker is dropped again. */
{
/* Used later when the source register is read. */
color0_mov = TRUE;
}
}
/* Also drop the MOV marker if the source register is overwritten prior to the shader
* end
*/
{
}
}
/* Declare 1.x samplers implicitly, based on the destination reg. number. */
{
/* Fake sampler usage, only set reserved bit and type. */
TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
/* texbem is only valid with < 1.4 pixel shaders */
{
{
}
}
}
{
}
}
{
if (cur_loop_depth > max_loop_depth)
}
{
while (count)
{
--count;
}
if (color0_mov)
{
{
}
}
}
}
}
/* PS before 2.0 don't have explicit color outputs. Instead the value of
* R0 is written to the render target. */
return WINED3D_OK;
}
unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, unsigned int max)
{
return wined3d_log2i(map);
}
const struct wined3d_shader_version *shader_version)
{
TRACE("dcl");
{
switch (semantic->sampler_type)
{
}
}
else
{
/* Pixel shaders 3.0 don't have usage semantics. */
else TRACE("_");
{
break;
TRACE("blend");
break;
TRACE("weight");
break;
break;
case WINED3D_DECL_USAGE_PSIZE:
TRACE("psize");
break;
case WINED3D_DECL_USAGE_COLOR:
break;
break;
TRACE("tangent");
break;
TRACE("binormal");
break;
TRACE("tessfactor");
break;
break;
case WINED3D_DECL_USAGE_FOG:
TRACE("fog");
break;
case WINED3D_DECL_USAGE_DEPTH:
TRACE("depth");
break;
TRACE("sample");
break;
default:
}
}
}
const struct wined3d_shader_version *shader_version)
{
{
case WINED3DSPR_TEMP:
TRACE("r");
break;
case WINED3DSPR_INPUT:
TRACE("v");
break;
case WINED3DSPR_CONST:
case WINED3DSPR_CONST2:
case WINED3DSPR_CONST3:
case WINED3DSPR_CONST4:
TRACE("c");
break;
case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */
break;
case WINED3DSPR_RASTOUT:
break;
case WINED3DSPR_COLOROUT:
TRACE("oC");
break;
case WINED3DSPR_DEPTHOUT:
TRACE("oDepth");
break;
case WINED3DSPR_ATTROUT:
TRACE("oD");
break;
case WINED3DSPR_TEXCRDOUT:
/* Vertex shaders >= 3.0 use general purpose output registers
* (WINED3DSPR_OUTPUT), which can include an address token. */
else TRACE("oT");
break;
case WINED3DSPR_CONSTINT:
TRACE("i");
break;
case WINED3DSPR_CONSTBOOL:
TRACE("b");
break;
case WINED3DSPR_LABEL:
TRACE("l");
break;
case WINED3DSPR_LOOP:
TRACE("aL");
break;
case WINED3DSPR_SAMPLER:
TRACE("s");
break;
case WINED3DSPR_MISCTYPE:
if (offset > 1)
else
break;
case WINED3DSPR_PREDICATE:
TRACE("p");
break;
case WINED3DSPR_IMMCONST:
TRACE("l");
break;
case WINED3DSPR_CONSTBUFFER:
TRACE("cb");
break;
case WINED3DSPR_PRIMID:
TRACE("primID");
break;
case WINED3DSPR_NULL:
TRACE("null");
break;
case WINED3DSPR_RESOURCE:
TRACE("t");
break;
default:
break;
}
{
TRACE("(");
switch (reg->immconst_type)
{
case WINED3D_IMMCONST_SCALAR:
{
case WINED3D_DATA_FLOAT:
break;
case WINED3D_DATA_INT:
break;
case WINED3D_DATA_RESOURCE:
case WINED3D_DATA_SAMPLER:
case WINED3D_DATA_UINT:
break;
default:
break;
}
break;
case WINED3D_IMMCONST_VEC4:
{
case WINED3D_DATA_FLOAT:
TRACE("%.8e, %.8e, %.8e, %.8e",
break;
case WINED3D_DATA_INT:
TRACE("%d, %d, %d, %d",
break;
case WINED3D_DATA_RESOURCE:
case WINED3D_DATA_SAMPLER:
case WINED3D_DATA_UINT:
TRACE("%u, %u, %u, %u",
break;
default:
break;
}
break;
default:
break;
}
TRACE(")");
}
{
if (offset != ~0U)
{
TRACE("[");
{
TRACE(" + ");
}
{
TRACE("[");
{
TRACE(" + ");
}
}
}
}
}
const struct wined3d_shader_version *shader_version)
{
{
static const char *write_mask_chars = "xyzw";
TRACE(".");
}
}
const struct wined3d_shader_version *shader_version)
{
if (src_modifier == WINED3DSPSM_NEG
|| src_modifier == WINED3DSPSM_ABSNEG)
TRACE("-");
else if (src_modifier == WINED3DSPSM_COMP)
TRACE("1-");
else if (src_modifier == WINED3DSPSM_NOT)
TRACE("!");
TRACE("abs(");
if (src_modifier)
{
switch (src_modifier)
{
case WINED3DSPSM_NONE: break;
case WINED3DSPSM_NEG: break;
case WINED3DSPSM_NOT: break;
case WINED3DSPSM_COMP: break;
}
}
if (swizzle != WINED3DSP_NOSWIZZLE)
{
static const char *swizzle_chars = "xyzw";
{
}
else
{
}
}
}
/* Shared code in order to generate the bulk of the shader string.
* NOTE: A description of how to parse tokens can be found on MSDN. */
void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer,
{
struct wined3d_shader_version shader_version;
struct wined3d_shader_loop_state loop_state;
struct wined3d_shader_instruction ins;
struct wined3d_shader_tex_mx tex_mx;
struct wined3d_shader_context ctx;
/* Initialize current parsing state. */
tex_mx.current_row = 0;
loop_state.current_depth = 0;
loop_state.current_reg = 0;
{
/* Read opcode. */
/* Unknown opcode and its parameters. */
{
TRACE("Skipping unrecognized instruction.\n");
continue;
}
FIXME("Predicates not implemented.\n");
/* Call appropriate function for output target */
}
}
{
{
case 0: break;
}
}
{
switch (primitive_type)
{
case WINED3D_PT_UNDEFINED:
TRACE("undefined");
break;
case WINED3D_PT_POINTLIST:
TRACE("pointlist");
break;
case WINED3D_PT_LINELIST:
TRACE("linelist");
break;
case WINED3D_PT_LINESTRIP:
TRACE("linestrip");
break;
case WINED3D_PT_TRIANGLELIST:
TRACE("trianglelist");
break;
case WINED3D_PT_TRIANGLESTRIP:
TRACE("trianglestrip");
break;
case WINED3D_PT_TRIANGLEFAN:
TRACE("trianglefan");
break;
case WINED3D_PT_LINELIST_ADJ:
TRACE("linelist_adj");
break;
case WINED3D_PT_LINESTRIP_ADJ:
TRACE("linestrip_adj");
break;
TRACE("trianglelist_adj");
break;
TRACE("trianglestrip_adj");
break;
default:
break;
}
}
static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *byte_code)
{
struct wined3d_shader_version shader_version;
const char *type_prefix;
DWORD i;
switch (shader_version.type)
{
type_prefix = "vs";
break;
type_prefix = "gs";
break;
type_prefix = "ps";
break;
default:
type_prefix = "unknown";
break;
}
{
struct wined3d_shader_instruction ins;
{
TRACE("Skipping unrecognized instruction.\n");
continue;
}
{
TRACE(" ");
}
{
}
{
}
{
}
{
}
{
}
{
TRACE("defb b%u = %s", ins.dst[0].reg.idx[0].offset, ins.src[0].reg.immconst_data[0] ? "true" : "false");
}
else
{
{
TRACE("(");
TRACE(") ");
}
/* PixWin marks instructions with the coissue flag with a '+' */
{
{
}
}
{
TRACE("p");
}
{
}
/* Other source tokens */
{
}
}
TRACE("\n");
}
}
{
}
struct shader_none_priv
{
const struct wined3d_vertex_pipe_ops *vertex_pipe;
const struct fragment_pipeline *fragment_pipe;
};
static void shader_none_deselect_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info) {}
static void shader_none_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) {}
static void shader_none_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) {}
const struct wined3d_state *state) {}
static void shader_none_load_np2fixup_constants(void *shader_priv,
static void shader_none_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
/* Context activation is done by the caller. */
const struct wined3d_state *state)
{
}
/* Context activation is done by the caller. */
{
}
static HRESULT shader_none_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
const struct fragment_pipeline *fragment_pipe)
{
struct fragment_caps fragment_caps;
void *vertex_priv, *fragment_priv;
struct shader_none_priv *priv;
return E_OUTOFMEMORY;
{
ERR("Failed to initialize vertex pipe.\n");
return E_FAIL;
}
{
ERR("Failed to initialize fragment pipe.\n");
return E_FAIL;
}
return WINED3D_OK;
}
{
}
{
/* Set the shader caps to 0 for the none shader backend */
caps->vs_version = 0;
caps->gs_version = 0;
caps->ps_version = 0;
caps->vs_uniform_count = 0;
caps->ps_uniform_count = 0;
caps->wined3d_caps = 0;
}
{
/* We "support" every possible fixup, since we don't support any shader
* model, and will never have to actually sample a texture. */
return TRUE;
}
{
return priv->ffp_proj_control;
}
const struct wined3d_shader_backend_ops none_shader_backend =
{
};
{
const struct wined3d_shader_frontend *fe;
unsigned int backend_version;
TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
if (!fe)
{
FIXME("Unable to find frontend for shader.\n");
return WINED3DERR_INVALIDCALL;
}
if (!shader->frontend_data)
{
FIXME("Failed to initialize frontend.\n");
return WINED3DERR_INVALIDCALL;
}
/* First pass: trace shader. */
if (TRACE_ON(d3d_shader))
/* Initialize immediate constant lists. */
/* Second pass: figure out which registers are used, what the semantics are, etc. */
{
return WINED3DERR_INVALIDCALL;
}
{
return WINED3DERR_INVALIDCALL;
}
switch (type)
{
break;
break;
break;
default:
FIXME("No backend version-checking for this shader type\n");
backend_version = 0;
}
{
WARN("Shader version %d.%d not supported by your GPU with the current shader backend.\n",
return WINED3DERR_INVALIDCALL;
}
return E_OUTOFMEMORY;
return WINED3D_OK;
}
{
return refcount;
}
/* Do not call while under the GL lock. */
{
if (!refcount)
{
#ifdef VBOX_WINE_WITH_SHADER_CACHE
#else
#endif
}
return refcount;
}
{
}
{
if (!byte_code)
{
return WINED3D_OK;
}
{
/* MSDN claims (for d3d8 at least) that if *byte_code_size is smaller
* than the required size we should write the required size and
* return D3DERR_MOREDATA. That's not actually true. */
return WINED3DERR_INVALIDCALL;
}
return WINED3D_OK;
}
/* Set local constants for d3d8 shaders. */
{
UINT i;
{
WARN("end_idx %u > float constants limit %u.\n",
}
{
float *value;
if (!lconst)
return E_OUTOFMEMORY;
{
}
}
return WINED3D_OK;
}
{
}
{
if (usage_idx1 != usage_idx2)
return FALSE;
return TRUE;
return TRUE;
return TRUE;
return FALSE;
}
{
unsigned int i;
{
if (!(map & 1)) continue;
{
*regnum = i;
return TRUE;
}
}
return FALSE;
}
{
switch (shader_version)
{
case WINED3D_SHADER_VERSION(1, 0):
/* TODO: vs_1_1 has a minimum of 96 constants. What happens when
* a vs_1_1 shader is used on a vs_3_0 capable card that has 256
* constants? */
break;
case WINED3D_SHADER_VERSION(2, 0):
break;
case WINED3D_SHADER_VERSION(3, 0):
/* DX10 cards on Windows advertise a d3d9 constant limit of 256
* even though they are capable of supporting much more (GL
* drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
* wined3d-advertised maximum. Clamp the constant limit for <= 3.0
* shaders to 256. */
break;
case WINED3D_SHADER_VERSION(4, 0):
break;
default:
FIXME("Unrecognized vertex shader version \"%u.%u\".\n",
}
}
{
unsigned int i;
if (!byte_code) return WINED3DERR_INVALIDCALL;
{
return hr;
}
{
continue;
}
if (output_signature)
{
for (i = 0; i < output_signature->element_count; ++i)
{
}
}
return WINED3D_OK;
}
{
switch (shader_version)
{
case WINED3D_SHADER_VERSION(4, 0):
break;
default:
FIXME("Unhandled geometry shader version \"%u.%u\".\n",
}
}
{
{
return hr;
}
return WINED3D_OK;
}
{
const struct wined3d_texture *texture;
UINT i;
{
{
static unsigned int warned = 0;
WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB "
"support, expect rendering artifacts.\n");
}
}
{
{
if (flags & WINED3D_TTFF_PROJECTED)
{
if (!state->vertex_shader)
{
unsigned int j;
{
struct wined3d_vertex_declaration_element *element =
{
break;
}
}
{
WARN("Fixing up projected texture transform flags from %#x to %#x.\n",
}
else
{
WARN("Application requested projected texture with unsuitable texture coordinates.\n");
WARN("(texture unit %u, transform flags %#x, sampler type %u).\n",
i, tex_transform, sampler_type);
}
}
else
}
}
}
{
{
continue;
/* Treat unbound textures as 2D. The dummy texture will provide
* the proper sample value. The tex_types bitmap defaults to
* 2D because of the memset. */
if (!texture)
continue;
{
/* RECT textures are distinguished from 2D textures via np2_fixup */
case GL_TEXTURE_RECTANGLE_ARB:
case GL_TEXTURE_2D:
break;
case GL_TEXTURE_3D:
break;
case GL_TEXTURE_CUBE_MAP_ARB:
break;
}
}
}
for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
{
continue;
if (!texture)
{
continue;
}
/* Flag samplers that need NP2 texcoord fixup. */
}
{
else
}
else
{
{
{
case WINED3D_FOG_NONE:
{
break;
}
{
case WINED3D_FOG_NONE: /* Fall through. */
}
break;
}
}
else
{
}
}
}
{
switch (shader_version)
{
case WINED3D_SHADER_VERSION(1, 0):
break;
break;
/* FIXME: Temporaries must match D3DPSHADERCAPS2_0.NumTemps. */
case WINED3D_SHADER_VERSION(2, 0):
break;
break;
case WINED3D_SHADER_VERSION(3, 0):
break;
case WINED3D_SHADER_VERSION(4, 0):
break;
default:
FIXME("Unrecognized pixel shader version %u.%u\n",
}
}
{
unsigned int i, highest_reg_used = 0, num_regs_used = 0;
if (!byte_code) return WINED3DERR_INVALIDCALL;
{
return hr;
}
for (i = 0; i < MAX_REG_INPUT; ++i)
{
{
highest_reg_used = i;
}
}
/* Don't do any register mapping magic if it is not needed, or if we can't
* achieve anything anyway */
{
{
/* This happens with relative addressing. The input mapper function
* warns about this if the higher registers are declared too, so
* don't write a FIXME here */
WARN("More varying registers used than supported\n");
}
for (i = 0; i < MAX_REG_INPUT; ++i)
{
}
}
else
{
for (i = 0; i < MAX_REG_INPUT; ++i)
{
}
}
return WINED3D_OK;
}
{
unsigned int i;
{
/* We don't sample from this sampler. */
if (!sampler_type[i]) continue;
{
case WINED3D_SHADER_TEX_2D:
sampler_type[i] = WINED3DSTT_2D;
break;
case WINED3D_SHADER_TEX_3D:
break;
case WINED3D_SHADER_TEX_CUBE:
sampler_type[i] = WINED3DSTT_CUBE;
break;
}
}
}
const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
{
struct wined3d_shader *object;
TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
if (!object)
return E_OUTOFMEMORY;
hr = geometryshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
{
return hr;
}
return WINED3D_OK;
}
const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
{
struct wined3d_shader *object;
TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
if (!object)
return E_OUTOFMEMORY;
hr = pixelshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
{
return hr;
}
#ifdef VBOX_WINE_WITH_SHADER_CACHE
#endif
return WINED3D_OK;
}
const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version)
{
struct wined3d_shader *object;
TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n",
if (!object)
return E_OUTOFMEMORY;
hr = vertexshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version);
{
return hr;
}
#ifdef VBOX_WINE_WITH_SHADER_CACHE
#endif
return WINED3D_OK;
}
#ifdef VBOX_WINE_WITH_SHADER_CACHE
{
#ifdef DEBUG
{
struct wined3d_shader *tst_shader;
if (tst_shader == shader)
return;
}
ERR("shader not in list!");
}
#endif
}
{
if (shader->u32CacheDataInited)
{
}
{
}
}
{
return TRUE;
return FALSE;
{
#ifdef DEBUG_misha
#endif
return FALSE;
}
}
#define VBOX_SHADER_FROM_CACHE_ENTRY(_pEntry) RT_FROM_MEMBER((_pEntry), struct wined3d_shader, CacheEntry)
static DECLCALLBACK(void) shader_cache_cleanup_entry(void *pvKey, struct VBOXEXT_HASHCACHE_ENTRY *pEntry)
{
}
{
}
{
}
{
{
}
}
static struct wined3d_shader* shader_chache_get(PVBOXEXT_HASHCACHE pCache, struct wined3d_shader *shader)
{
struct wined3d_shader *cached_shader;
if (!pEntry)
return shader;
/* we can not do a IWineD3DBaseShader_Release here since this would result in putting a shader to the cache */
return cached_shader;
}
struct wined3d_shader * vertexshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object)
{
}
struct wined3d_shader * pixelshader_check_cached(struct wined3d_device *device, struct wined3d_shader *object)
{
}
{
}
{
}
#endif