Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-fonts
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Aleksandr Isakov
wine-fonts
Commits
d567a030
Commit
d567a030
authored
Jul 21, 2010
by
Matteo Bruni
Committed by
Alexandre Julliard
Jul 22, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
d3dx9: Shader assembler <= ps_1_3 support.
parent
8ce3ecea
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
713 additions
and
50 deletions
+713
-50
asmparser.c
dlls/d3dx9_36/asmparser.c
+346
-35
asmshader.y
dlls/d3dx9_36/asmshader.y
+4
-8
bytecodewriter.c
dlls/d3dx9_36/bytecodewriter.c
+309
-5
d3dx9_36_private.h
dlls/d3dx9_36/d3dx9_36_private.h
+10
-0
asm.c
dlls/d3dx9_36/tests/asm.c
+44
-2
No files found.
dlls/d3dx9_36/asmparser.c
View file @
d567a030
...
...
@@ -226,6 +226,86 @@ static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
}
}
static
struct
shader_reg
map_oldps_register
(
const
struct
shader_reg
*
reg
,
BOOL
tex_varying
)
{
struct
shader_reg
ret
;
switch
(
reg
->
type
)
{
case
BWRITERSPR_TEXTURE
:
if
(
tex_varying
)
{
ret
=
*
reg
;
ret
.
type
=
BWRITERSPR_INPUT
;
switch
(
reg
->
regnum
)
{
case
0
:
ret
.
regnum
=
T0_VARYING
;
break
;
case
1
:
ret
.
regnum
=
T1_VARYING
;
break
;
case
2
:
ret
.
regnum
=
T2_VARYING
;
break
;
case
3
:
ret
.
regnum
=
T3_VARYING
;
break
;
case
4
:
ret
.
regnum
=
T4_VARYING
;
break
;
case
5
:
ret
.
regnum
=
T5_VARYING
;
break
;
case
6
:
ret
.
regnum
=
T6_VARYING
;
break
;
case
7
:
ret
.
regnum
=
T7_VARYING
;
break
;
default:
FIXME
(
"Unexpected TEXTURE register t%u
\n
"
,
reg
->
regnum
);
return
*
reg
;
}
return
ret
;
}
else
{
ret
=
*
reg
;
ret
.
type
=
BWRITERSPR_TEMP
;
switch
(
reg
->
regnum
)
{
case
0
:
ret
.
regnum
=
T0_REG
;
break
;
case
1
:
ret
.
regnum
=
T1_REG
;
break
;
case
2
:
ret
.
regnum
=
T2_REG
;
break
;
case
3
:
ret
.
regnum
=
T3_REG
;
break
;
default:
FIXME
(
"Unexpected TEXTURE register t%u
\n
"
,
reg
->
regnum
);
return
*
reg
;
}
return
ret
;
}
/* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
to 3.0 ones */
default:
return
*
reg
;
}
}
static
void
asmparser_texcoord
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
src_regs
*
srcs
)
{
struct
instruction
*
instr
;
if
(
srcs
)
{
asmparser_message
(
This
,
"Line %u: Source registers in texcoord instruction
\n
"
,
This
->
line_no
);
set_parse_status
(
This
,
PARSE_ERR
);
return
;
}
instr
=
alloc_instr
(
1
);
if
(
!
instr
)
{
ERR
(
"Error allocating memory for the instruction
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
return
;
}
/* texcoord copies the texture coord data into a temporary register-like
* readable form. In newer shader models this equals a MOV from v0 to r0,
* record it as this.
*/
instr
->
opcode
=
BWRITERSIO_MOV
;
instr
->
dstmod
=
mod
|
BWRITERSPDM_SATURATE
;
/* texcoord clamps to [0;1] */
instr
->
shift
=
shift
;
instr
->
comptype
=
0
;
This
->
funcs
->
dstreg
(
This
,
instr
,
dst
);
/* The src reg needs special care */
instr
->
src
[
0
]
=
map_oldps_register
(
dst
,
TRUE
);
if
(
!
add_instruction
(
This
->
shader
,
instr
))
{
ERR
(
"Out of memory
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
}
}
static
void
asmparser_texcrd
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
src_regs
*
srcs
)
{
...
...
@@ -259,6 +339,82 @@ static void asmparser_texcrd(struct asm_parser *This, DWORD mod, DWORD shift,
}
}
static
void
asmparser_texkill
(
struct
asm_parser
*
This
,
const
struct
shader_reg
*
dst
)
{
struct
instruction
*
instr
=
alloc_instr
(
0
);
if
(
!
instr
)
{
ERR
(
"Error allocating memory for the instruction
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
return
;
}
instr
->
opcode
=
BWRITERSIO_TEXKILL
;
instr
->
dstmod
=
0
;
instr
->
shift
=
0
;
instr
->
comptype
=
0
;
/* Do not run the dst register through the normal
* register conversion. If used with ps_1_0 to ps_1_3
* the texture coordinate from that register is used,
* not the temporary register value. In ps_1_4 and
* ps_2_0 t0 is always a varying and temporaries can
* be used with texkill.
*/
instr
->
dst
=
map_oldps_register
(
dst
,
TRUE
);
instr
->
has_dst
=
TRUE
;
if
(
!
add_instruction
(
This
->
shader
,
instr
))
{
ERR
(
"Out of memory
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
}
}
static
void
asmparser_texhelper
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
shader_reg
*
src0
)
{
struct
instruction
*
instr
=
alloc_instr
(
2
);
if
(
!
instr
)
{
ERR
(
"Error allocating memory for the instruction
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
return
;
}
instr
->
opcode
=
BWRITERSIO_TEX
;
instr
->
dstmod
=
mod
;
instr
->
shift
=
shift
;
instr
->
comptype
=
0
;
/* The dest register can be mapped normally to a temporary register */
This
->
funcs
->
dstreg
(
This
,
instr
,
dst
);
/* Use the src passed as parameter by the specific instruction handler */
instr
->
src
[
0
]
=
*
src0
;
/* The 2nd source register is the sampler register with the
* destination's regnum
*/
ZeroMemory
(
&
instr
->
src
[
1
],
sizeof
(
instr
->
src
[
1
]));
instr
->
src
[
1
].
type
=
BWRITERSPR_SAMPLER
;
instr
->
src
[
1
].
regnum
=
dst
->
regnum
;
instr
->
src
[
1
].
swizzle
=
BWRITERVS_NOSWIZZLE
;
instr
->
src
[
1
].
srcmod
=
BWRITERSPSM_NONE
;
instr
->
src
[
1
].
rel_reg
=
NULL
;
if
(
!
add_instruction
(
This
->
shader
,
instr
))
{
ERR
(
"Out of memory
\n
"
);
set_parse_status
(
This
,
PARSE_ERR
);
}
}
static
void
asmparser_tex
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
)
{
struct
shader_reg
src
;
/* The first source register is the varying containing the coordinate */
src
=
map_oldps_register
(
dst
,
TRUE
);
asmparser_texhelper
(
This
,
mod
,
shift
,
dst
,
&
src
);
}
static
void
asmparser_texld14
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
src_regs
*
srcs
)
{
...
...
@@ -304,6 +460,46 @@ static void asmparser_texld14(struct asm_parser *This, DWORD mod, DWORD shift,
}
}
static
void
asmparser_texreg2ar
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
shader_reg
*
src0
)
{
struct
shader_reg
src
;
src
=
map_oldps_register
(
src0
,
FALSE
);
/* Supply the correct swizzle */
src
.
swizzle
=
BWRITERVS_X_W
|
BWRITERVS_Y_X
|
BWRITERVS_Z_X
|
BWRITERVS_W_X
;
asmparser_texhelper
(
This
,
mod
,
shift
,
dst
,
&
src
);
}
static
void
asmparser_texreg2gb
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
shader_reg
*
src0
)
{
struct
shader_reg
src
;
src
=
map_oldps_register
(
src0
,
FALSE
);
/* Supply the correct swizzle */
src
.
swizzle
=
BWRITERVS_X_Y
|
BWRITERVS_Y_Z
|
BWRITERVS_Z_Z
|
BWRITERVS_W_Z
;
asmparser_texhelper
(
This
,
mod
,
shift
,
dst
,
&
src
);
}
static
void
asmparser_texreg2rgb
(
struct
asm_parser
*
This
,
DWORD
mod
,
DWORD
shift
,
const
struct
shader_reg
*
dst
,
const
struct
shader_reg
*
src0
)
{
struct
shader_reg
src
;
src
=
map_oldps_register
(
src0
,
FALSE
);
/* Supply the correct swizzle */
src
.
swizzle
=
BWRITERVS_X_X
|
BWRITERVS_Y_Y
|
BWRITERVS_Z_Z
|
BWRITERVS_W_Z
;
asmparser_texhelper
(
This
,
mod
,
shift
,
dst
,
&
src
);
}
/* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
* bytecode writer works instruction by instruction, so we can't properly
* convert these from/to equivalent ps_3_0 instructions. Then simply keep using
* the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
* go through asmparser_instr).
*/
static
void
asmparser_instr
(
struct
asm_parser
*
This
,
DWORD
opcode
,
DWORD
mod
,
DWORD
shift
,
BWRITER_COMPARISON_TYPE
comp
,
...
...
@@ -345,12 +541,20 @@ ns */
break
;
case
BWRITERSIO_TEXCOORD
:
/* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
asmparser_texcrd
(
This
,
mod
,
shift
,
dst
,
srcs
);
if
(
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
4
))
asmparser_texcrd
(
This
,
mod
,
shift
,
dst
,
srcs
);
else
asmparser_texcoord
(
This
,
mod
,
shift
,
dst
,
srcs
);
return
;
case
BWRITERSIO_TEX
:
/* this encodes both the tex PS 1.x instruction and the
texld 1.4/2.0+ instruction */
if
(
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
4
))
{
if
(
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
1
)
||
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
2
)
||
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
3
))
{
asmparser_tex
(
This
,
mod
,
shift
,
dst
);
return
;
}
else
if
(
This
->
shader
->
version
==
BWRITERPS_VERSION
(
1
,
4
))
{
asmparser_texld14
(
This
,
mod
,
shift
,
dst
,
srcs
);
return
;
}
...
...
@@ -364,6 +568,22 @@ ns */
return
;
}
/* Handle PS 1.x instructions, "regularizing" them */
switch
(
opcode
)
{
case
BWRITERSIO_TEXKILL
:
asmparser_texkill
(
This
,
dst
);
return
;
case
BWRITERSIO_TEXREG2AR
:
asmparser_texreg2ar
(
This
,
mod
,
shift
,
dst
,
&
srcs
->
reg
[
0
]);
return
;
case
BWRITERSIO_TEXREG2GB
:
asmparser_texreg2gb
(
This
,
mod
,
shift
,
dst
,
&
srcs
->
reg
[
0
]);
return
;
case
BWRITERSIO_TEXREG2RGB
:
asmparser_texreg2rgb
(
This
,
mod
,
shift
,
dst
,
&
srcs
->
reg
[
0
]);
return
;
}
instr
=
alloc_instr
(
src_count
);
if
(
!
instr
)
{
ERR
(
"Error allocating memory for the instruction
\n
"
);
...
...
@@ -444,39 +664,6 @@ static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
}
}
static
struct
shader_reg
map_oldps_register
(
const
struct
shader_reg
*
reg
,
BOOL
tex_varying
)
{
struct
shader_reg
ret
;
switch
(
reg
->
type
)
{
case
BWRITERSPR_TEXTURE
:
if
(
tex_varying
)
{
ret
=
*
reg
;
ret
.
type
=
BWRITERSPR_INPUT
;
switch
(
reg
->
regnum
)
{
case
0
:
ret
.
regnum
=
T0_VARYING
;
break
;
case
1
:
ret
.
regnum
=
T1_VARYING
;
break
;
case
2
:
ret
.
regnum
=
T2_VARYING
;
break
;
case
3
:
ret
.
regnum
=
T3_VARYING
;
break
;
case
4
:
ret
.
regnum
=
T4_VARYING
;
break
;
case
5
:
ret
.
regnum
=
T5_VARYING
;
break
;
case
6
:
ret
.
regnum
=
T6_VARYING
;
break
;
case
7
:
ret
.
regnum
=
T7_VARYING
;
break
;
default:
FIXME
(
"Unexpected TEXTURE register t%u
\n
"
,
reg
->
regnum
);
return
*
reg
;
}
return
ret
;
}
else
{
FIXME
(
"TODO: ps_1_x texture register mapping
\n
"
);
return
*
reg
;
}
/* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
to 3.0 ones */
default:
return
*
reg
;
}
}
/* Checks for unsupported source modifiers in VS (all versions) or
PS 2.0 and newer */
static
void
check_legacy_srcmod
(
struct
asm_parser
*
This
,
DWORD
srcmod
)
{
...
...
@@ -660,6 +847,30 @@ static void asmparser_srcreg_vs_3(struct asm_parser *This,
memcpy
(
&
instr
->
src
[
num
],
src
,
sizeof
(
*
src
));
}
static
const
struct
allowed_reg_type
ps_1_0123_reg_allowed
[]
=
{
{
BWRITERSPR_CONST
,
8
,
FALSE
},
{
BWRITERSPR_TEMP
,
2
,
FALSE
},
{
BWRITERSPR_TEXTURE
,
4
,
FALSE
},
{
BWRITERSPR_INPUT
,
2
,
FALSE
},
{
~
0U
,
0
}
/* End tag */
};
static
void
asmparser_srcreg_ps_1_0123
(
struct
asm_parser
*
This
,
struct
instruction
*
instr
,
int
num
,
const
struct
shader_reg
*
src
)
{
struct
shader_reg
reg
;
if
(
!
check_reg_type
(
src
,
ps_1_0123_reg_allowed
))
{
asmparser_message
(
This
,
"Line %u: Source register %s not supported in <== PS 1.3
\n
"
,
This
->
line_no
,
debug_print_srcreg
(
src
));
set_parse_status
(
This
,
PARSE_ERR
);
}
check_abs_srcmod
(
This
,
src
->
srcmod
);
reg
=
map_oldps_register
(
src
,
FALSE
);
memcpy
(
&
instr
->
src
[
num
],
&
reg
,
sizeof
(
reg
));
}
static
const
struct
allowed_reg_type
ps_1_4_reg_allowed
[]
=
{
{
BWRITERSPR_CONST
,
8
,
FALSE
},
{
BWRITERSPR_TEMP
,
6
,
FALSE
},
...
...
@@ -827,6 +1038,22 @@ static void asmparser_dstreg_vs_3(struct asm_parser *This,
instr
->
has_dst
=
TRUE
;
}
static
void
asmparser_dstreg_ps_1_0123
(
struct
asm_parser
*
This
,
struct
instruction
*
instr
,
const
struct
shader_reg
*
dst
)
{
struct
shader_reg
reg
;
if
(
!
check_reg_type
(
dst
,
ps_1_0123_reg_allowed
))
{
asmparser_message
(
This
,
"Line %u: Destination register %s not supported in PS 1
\n
"
,
This
->
line_no
,
debug_print_dstreg
(
dst
));
set_parse_status
(
This
,
PARSE_ERR
);
}
reg
=
map_oldps_register
(
dst
,
FALSE
);
memcpy
(
&
instr
->
dst
,
&
reg
,
sizeof
(
reg
));
instr
->
has_dst
=
TRUE
;
}
static
void
asmparser_dstreg_ps_1_4
(
struct
asm_parser
*
This
,
struct
instruction
*
instr
,
const
struct
shader_reg
*
dst
)
{
...
...
@@ -981,6 +1208,26 @@ static const struct asmparser_backend parser_vs_3 = {
asmparser_instr
,
};
static
const
struct
asmparser_backend
parser_ps_1_0123
=
{
asmparser_constF
,
asmparser_constI
,
asmparser_constB
,
asmparser_dstreg_ps_1_0123
,
asmparser_srcreg_ps_1_0123
,
asmparser_predicate_unsupported
,
asmparser_coissue_supported
,
asmparser_dcl_output_unsupported
,
asmparser_dcl_input_unsupported
,
asmparser_dcl_sampler_unsupported
,
asmparser_end
,
asmparser_instr
,
};
static
const
struct
asmparser_backend
parser_ps_1_4
=
{
asmparser_constF
,
asmparser_constI
,
...
...
@@ -1171,6 +1418,70 @@ void create_vs30_parser(struct asm_parser *ret) {
ret
->
funcs
=
&
parser_vs_3
;
}
void
create_ps10_parser
(
struct
asm_parser
*
ret
)
{
TRACE_
(
parsed_shader
)(
"ps_1_0
\n
"
);
ret
->
shader
=
asm_alloc
(
sizeof
(
*
ret
->
shader
));
if
(
!
ret
->
shader
)
{
ERR
(
"Failed to allocate memory for the shader
\n
"
);
set_parse_status
(
ret
,
PARSE_ERR
);
return
;
}
ret
->
shader
->
type
=
ST_PIXEL
;
ret
->
shader
->
version
=
BWRITERPS_VERSION
(
1
,
0
);
ret
->
funcs
=
&
parser_ps_1_0123
;
gen_oldps_input
(
ret
->
shader
,
4
);
}
void
create_ps11_parser
(
struct
asm_parser
*
ret
)
{
TRACE_
(
parsed_shader
)(
"ps_1_1
\n
"
);
ret
->
shader
=
asm_alloc
(
sizeof
(
*
ret
->
shader
));
if
(
!
ret
->
shader
)
{
ERR
(
"Failed to allocate memory for the shader
\n
"
);
set_parse_status
(
ret
,
PARSE_ERR
);
return
;
}
ret
->
shader
->
type
=
ST_PIXEL
;
ret
->
shader
->
version
=
BWRITERPS_VERSION
(
1
,
1
);
ret
->
funcs
=
&
parser_ps_1_0123
;
gen_oldps_input
(
ret
->
shader
,
4
);
}
void
create_ps12_parser
(
struct
asm_parser
*
ret
)
{
TRACE_
(
parsed_shader
)(
"ps_1_2
\n
"
);
ret
->
shader
=
asm_alloc
(
sizeof
(
*
ret
->
shader
));
if
(
!
ret
->
shader
)
{
ERR
(
"Failed to allocate memory for the shader
\n
"
);
set_parse_status
(
ret
,
PARSE_ERR
);
return
;
}
ret
->
shader
->
type
=
ST_PIXEL
;
ret
->
shader
->
version
=
BWRITERPS_VERSION
(
1
,
2
);
ret
->
funcs
=
&
parser_ps_1_0123
;
gen_oldps_input
(
ret
->
shader
,
4
);
}
void
create_ps13_parser
(
struct
asm_parser
*
ret
)
{
TRACE_
(
parsed_shader
)(
"ps_1_3
\n
"
);
ret
->
shader
=
asm_alloc
(
sizeof
(
*
ret
->
shader
));
if
(
!
ret
->
shader
)
{
ERR
(
"Failed to allocate memory for the shader
\n
"
);
set_parse_status
(
ret
,
PARSE_ERR
);
return
;
}
ret
->
shader
->
type
=
ST_PIXEL
;
ret
->
shader
->
version
=
BWRITERPS_VERSION
(
1
,
3
);
ret
->
funcs
=
&
parser_ps_1_0123
;
gen_oldps_input
(
ret
->
shader
,
4
);
}
void
create_ps14_parser
(
struct
asm_parser
*
ret
)
{
TRACE_
(
parsed_shader
)(
"ps_1_4
\n
"
);
...
...
dlls/d3dx9_36/asmshader.y
View file @
d567a030
...
...
@@ -329,26 +329,22 @@ version_marker: VER_VS10
| VER_PS10
{
TRACE("Pixel shader 1.0\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps10_parser(&asm_ctx);
}
| VER_PS11
{
TRACE("Pixel shader 1.1\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps11_parser(&asm_ctx);
}
| VER_PS12
{
TRACE("Pixel shader 1.2\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps12_parser(&asm_ctx);
}
| VER_PS13
{
TRACE("Pixel shader 1.3\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps13_parser(&asm_ctx);
}
| VER_PS14
{
...
...
dlls/d3dx9_36/bytecodewriter.c
View file @
d567a030
...
...
@@ -578,7 +578,7 @@ static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
return
S_OK
;
}
static
void
ps_1_
4
_header
(
struct
bc_writer
*
This
,
const
struct
bwriter_shader
*
shader
,
struct
bytecode_buffer
*
buffer
)
{
static
void
ps_1_
x
_header
(
struct
bc_writer
*
This
,
const
struct
bwriter_shader
*
shader
,
struct
bytecode_buffer
*
buffer
)
{
HRESULT
hr
;
/* First check the constants and varyings, and complain if unsupported things are used */
...
...
@@ -589,6 +589,27 @@ static void ps_1_4_header(struct bc_writer *This, const struct bwriter_shader *s
return
;
}
hr
=
find_ps_builtin_semantics
(
This
,
shader
,
4
);
if
(
FAILED
(
hr
))
{
This
->
state
=
hr
;
return
;
}
/* Declare the shader type and version */
put_dword
(
buffer
,
This
->
version
);
write_constF
(
shader
,
buffer
,
TRUE
);
}
static
void
ps_1_4_header
(
struct
bc_writer
*
This
,
const
struct
bwriter_shader
*
shader
,
struct
bytecode_buffer
*
buffer
)
{
HRESULT
hr
;
/* First check the constants and varyings, and complain if unsupported things are used */
if
(
shader
->
num_ci
||
shader
->
num_cb
)
{
WARN
(
"Int and bool constants are not supported in shader model 1 shaders
\n
"
);
WARN
(
"Got %u int and %u boolean constants
\n
"
,
shader
->
num_ci
,
shader
->
num_cb
);
This
->
state
=
E_INVALIDARG
;
return
;
}
hr
=
find_ps_builtin_semantics
(
This
,
shader
,
6
);
if
(
FAILED
(
hr
))
{
This
->
state
=
hr
;
...
...
@@ -808,6 +829,27 @@ static void write_srcregs(struct bc_writer *This, const struct instruction *inst
}
}
static
DWORD
map_ps13_temp
(
struct
bc_writer
*
This
,
const
struct
shader_reg
*
reg
)
{
DWORD
token
=
0
;
if
(
reg
->
regnum
==
T0_REG
)
{
token
|=
(
D3DSPR_TEXTURE
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
0
&
D3DSP_REGNUM_MASK
;
/* No shift */
}
else
if
(
reg
->
regnum
==
T1_REG
)
{
token
|=
(
D3DSPR_TEXTURE
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
1
&
D3DSP_REGNUM_MASK
;
/* No shift */
}
else
if
(
reg
->
regnum
==
T2_REG
)
{
token
|=
(
D3DSPR_TEXTURE
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
2
&
D3DSP_REGNUM_MASK
;
/* No shift */
}
else
if
(
reg
->
regnum
==
T3_REG
)
{
token
|=
(
D3DSPR_TEXTURE
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
3
&
D3DSP_REGNUM_MASK
;
/* No shift */
}
else
{
token
|=
(
D3DSPR_TEMP
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
reg
->
regnum
&
D3DSP_REGNUM_MASK
;
/* No shift */
}
return
token
;
}
static
DWORD
map_ps_input
(
struct
bc_writer
*
This
,
const
struct
shader_reg
*
reg
)
{
DWORD
i
,
token
=
0
;
...
...
@@ -832,6 +874,86 @@ static DWORD map_ps_input(struct bc_writer *This,
return
token
;
}
static
void
ps_1_0123_srcreg
(
struct
bc_writer
*
This
,
const
struct
shader_reg
*
reg
,
struct
bytecode_buffer
*
buffer
)
{
DWORD
token
=
(
1
<<
31
);
/* Bit 31 of registers is 1 */
if
(
reg
->
rel_reg
)
{
WARN
(
"Relative addressing not supported in <= ps_3_0
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
switch
(
reg
->
type
)
{
case
BWRITERSPR_INPUT
:
token
|=
map_ps_input
(
This
,
reg
);
break
;
/* Take care about the texture temporaries. There's a problem: They aren't
* declared anywhere, so we can only hardcode the values that are used
* to map ps_1_3 shaders to the common shader structure
*/
case
BWRITERSPR_TEMP
:
token
|=
map_ps13_temp
(
This
,
reg
);
break
;
case
BWRITERSPR_CONST
:
/* Can be mapped 1:1 */
token
|=
(
reg
->
type
<<
D3DSP_REGTYPE_SHIFT
)
&
D3DSP_REGTYPE_MASK
;
token
|=
reg
->
regnum
&
D3DSP_REGNUM_MASK
;
/* No shift */
break
;
default
:
WARN
(
"Invalid register type for <= ps_1_3 shader
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
token
|=
d3d9_swizzle
(
reg
->
swizzle
)
&
D3DVS_SWIZZLE_MASK
;
/* already shifted */
if
(
reg
->
srcmod
==
BWRITERSPSM_DZ
||
reg
->
srcmod
==
BWRITERSPSM_DW
||
reg
->
srcmod
==
BWRITERSPSM_ABS
||
reg
->
srcmod
==
BWRITERSPSM_ABSNEG
||
reg
->
srcmod
==
BWRITERSPSM_NOT
)
{
WARN
(
"Invalid source modifier %u for <= ps_1_3
\n
"
,
reg
->
srcmod
);
This
->
state
=
E_INVALIDARG
;
return
;
}
token
|=
d3d9_srcmod
(
reg
->
srcmod
);
put_dword
(
buffer
,
token
);
}
static
void
ps_1_0123_dstreg
(
struct
bc_writer
*
This
,
const
struct
shader_reg
*
reg
,
struct
bytecode_buffer
*
buffer
,
DWORD
shift
,
DWORD
mod
)
{
DWORD
token
=
(
1
<<
31
);
/* Bit 31 of registers is 1 */
if
(
reg
->
rel_reg
)
{
WARN
(
"Relative addressing not supported for destination registers
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
switch
(
reg
->
type
)
{
case
BWRITERSPR_TEMP
:
token
|=
map_ps13_temp
(
This
,
reg
);
break
;
/* texkill uses the input register as a destination parameter */
case
BWRITERSPR_INPUT
:
token
|=
map_ps_input
(
This
,
reg
);
break
;
default
:
WARN
(
"Invalid dest register type for 1.x pshader
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
token
|=
(
shift
<<
D3DSP_DSTSHIFT_SHIFT
)
&
D3DSP_DSTSHIFT_MASK
;
token
|=
d3d9_dstmod
(
mod
);
token
|=
d3d9_writemask
(
reg
->
writemask
);
put_dword
(
buffer
,
token
);
}
/* The length of an instruction consists of the destination register (if any),
* the number of source registers, the number of address registers used for
* indirect addressing, and optionally the predicate register
...
...
@@ -910,6 +1032,168 @@ static const struct bytecode_backend vs_1_x_backend = {
vs_1_x_handlers
};
static
void
instr_ps_1_0123_texld
(
struct
bc_writer
*
This
,
const
struct
instruction
*
instr
,
struct
bytecode_buffer
*
buffer
)
{
DWORD
idx
,
srcidx
;
struct
shader_reg
reg
;
DWORD
swizzlemask
;
if
(
instr
->
src
[
1
].
type
!=
BWRITERSPR_SAMPLER
||
instr
->
src
[
1
].
regnum
>
3
)
{
WARN
(
"Unsupported sampler type %u regnum %u
\n
"
,
instr
->
src
[
1
].
type
,
instr
->
src
[
1
].
regnum
);
This
->
state
=
E_INVALIDARG
;
return
;
}
else
if
(
instr
->
dst
.
type
!=
BWRITERSPR_TEMP
)
{
WARN
(
"Can only sample into a temp register
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
idx
=
instr
->
src
[
1
].
regnum
;
if
((
idx
==
0
&&
instr
->
dst
.
regnum
!=
T0_REG
)
||
(
idx
==
1
&&
instr
->
dst
.
regnum
!=
T1_REG
)
||
(
idx
==
2
&&
instr
->
dst
.
regnum
!=
T2_REG
)
||
(
idx
==
3
&&
instr
->
dst
.
regnum
!=
T3_REG
))
{
WARN
(
"Sampling from sampler s%u to register r%u is not possible in ps_1_x
\n
"
,
idx
,
instr
->
dst
.
regnum
);
This
->
state
=
E_INVALIDARG
;
return
;
}
if
(
instr
->
src
[
0
].
type
==
BWRITERSPR_INPUT
)
{
/* A simple non-dependent read tex instruction */
if
(
instr
->
src
[
0
].
regnum
!=
This
->
t_regnum
[
idx
])
{
WARN
(
"Cannot sample from s%u with texture address data from interpolator %u
\n
"
,
idx
,
instr
->
src
[
0
].
regnum
);
This
->
state
=
E_INVALIDARG
;
return
;
}
This
->
funcs
->
opcode
(
This
,
instr
,
D3DSIO_TEX
&
D3DSI_OPCODE_MASK
,
buffer
);
/* map the temp dstreg to the ps_1_3 texture temporary register */
This
->
funcs
->
dstreg
(
This
,
&
instr
->
dst
,
buffer
,
instr
->
shift
,
instr
->
dstmod
);
}
else
if
(
instr
->
src
[
0
].
type
==
BWRITERSPR_TEMP
)
{
if
(
instr
->
src
[
0
].
regnum
==
T0_REG
)
{
srcidx
=
0
;
}
else
if
(
instr
->
src
[
0
].
regnum
==
T1_REG
)
{
srcidx
=
1
;
}
else
if
(
instr
->
src
[
0
].
regnum
==
T2_REG
)
{
srcidx
=
2
;
}
else
if
(
instr
->
src
[
0
].
regnum
==
T3_REG
)
{
srcidx
=
3
;
}
else
{
WARN
(
"Invalid address data source register r%u
\n
"
,
instr
->
src
[
0
].
regnum
);
}
swizzlemask
=
(
3
<<
BWRITERVS_SWIZZLE_SHIFT
)
|
(
3
<<
(
BWRITERVS_SWIZZLE_SHIFT
+
2
))
|
(
3
<<
(
BWRITERVS_SWIZZLE_SHIFT
+
4
));
if
((
instr
->
src
[
0
].
swizzle
&
swizzlemask
)
==
(
BWRITERVS_X_X
|
BWRITERVS_Y_Y
|
BWRITERVS_Z_Z
))
{
TRACE
(
"writing texreg2rgb
\n
"
);
This
->
funcs
->
opcode
(
This
,
instr
,
D3DSIO_TEXREG2RGB
&
D3DSI_OPCODE_MASK
,
buffer
);
}
else
if
(
instr
->
src
[
0
].
swizzle
==
(
BWRITERVS_X_W
|
BWRITERVS_Y_X
|
BWRITERVS_Z_X
|
BWRITERVS_W_X
))
{
TRACE
(
"writing texreg2ar
\n
"
);
This
->
funcs
->
opcode
(
This
,
instr
,
D3DSIO_TEXREG2AR
&
D3DSI_OPCODE_MASK
,
buffer
);
}
else
if
(
instr
->
src
[
0
].
swizzle
==
(
BWRITERVS_X_Y
|
BWRITERVS_Y_Z
|
BWRITERVS_Z_Z
|
BWRITERVS_W_Z
))
{
TRACE
(
"writing texreg2gb
\n
"
);
This
->
funcs
->
opcode
(
This
,
instr
,
D3DSIO_TEXREG2GB
&
D3DSI_OPCODE_MASK
,
buffer
);
}
else
{
WARN
(
"Unsupported src addr swizzle in dependent texld: 0x%08x
\n
"
,
instr
->
src
[
0
].
swizzle
);
This
->
state
=
E_INVALIDARG
;
return
;
}
/* Dst and src reg can be mapped normally. Both registers are temporary registers in the
* source shader and have to be mapped to the temporary form of the texture registers. However,
* the src reg doesn't have a swizzle
*/
This
->
funcs
->
dstreg
(
This
,
&
instr
->
dst
,
buffer
,
instr
->
shift
,
instr
->
dstmod
);
reg
=
instr
->
src
[
0
];
reg
.
swizzle
=
BWRITERVS_NOSWIZZLE
;
This
->
funcs
->
srcreg
(
This
,
&
reg
,
buffer
);
}
else
{
WARN
(
"Invalid address data source register
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
}
static
void
instr_ps_1_0123_mov
(
struct
bc_writer
*
This
,
const
struct
instruction
*
instr
,
struct
bytecode_buffer
*
buffer
)
{
DWORD
token
=
D3DSIO_MOV
&
D3DSI_OPCODE_MASK
;
if
(
instr
->
dst
.
type
==
BWRITERSPR_TEMP
&&
instr
->
src
[
0
].
type
==
BWRITERSPR_INPUT
)
{
if
((
instr
->
dst
.
regnum
==
T0_REG
&&
instr
->
src
[
0
].
regnum
==
This
->
t_regnum
[
0
])
||
(
instr
->
dst
.
regnum
==
T1_REG
&&
instr
->
src
[
0
].
regnum
==
This
->
t_regnum
[
1
])
||
(
instr
->
dst
.
regnum
==
T2_REG
&&
instr
->
src
[
0
].
regnum
==
This
->
t_regnum
[
2
])
||
(
instr
->
dst
.
regnum
==
T3_REG
&&
instr
->
src
[
0
].
regnum
==
This
->
t_regnum
[
3
]))
{
if
(
instr
->
dstmod
&
BWRITERSPDM_SATURATE
)
{
This
->
funcs
->
opcode
(
This
,
instr
,
D3DSIO_TEXCOORD
&
D3DSI_OPCODE_MASK
,
buffer
);
/* Remove the SATURATE flag, it's implicit to the instruction */
This
->
funcs
->
dstreg
(
This
,
&
instr
->
dst
,
buffer
,
instr
->
shift
,
instr
->
dstmod
&
(
~
BWRITERSPDM_SATURATE
));
return
;
}
else
{
WARN
(
"A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
}
else
if
(
instr
->
src
[
0
].
regnum
==
This
->
v_regnum
[
0
]
||
instr
->
src
[
0
].
regnum
==
This
->
v_regnum
[
1
])
{
/* Handled by the normal mov below. Just drop out of the if condition */
}
else
{
WARN
(
"Unsupported varying -> temp mov in <= ps_1_3
\n
"
);
This
->
state
=
E_INVALIDARG
;
return
;
}
}
This
->
funcs
->
opcode
(
This
,
instr
,
token
,
buffer
);
This
->
funcs
->
dstreg
(
This
,
&
instr
->
dst
,
buffer
,
instr
->
shift
,
instr
->
dstmod
);
This
->
funcs
->
srcreg
(
This
,
&
instr
->
src
[
0
],
buffer
);
}
static
const
struct
instr_handler_table
ps_1_0123_handlers
[]
=
{
{
BWRITERSIO_ADD
,
instr_handler
},
{
BWRITERSIO_NOP
,
instr_handler
},
{
BWRITERSIO_MOV
,
instr_ps_1_0123_mov
},
{
BWRITERSIO_SUB
,
instr_handler
},
{
BWRITERSIO_MAD
,
instr_handler
},
{
BWRITERSIO_MUL
,
instr_handler
},
{
BWRITERSIO_DP3
,
instr_handler
},
{
BWRITERSIO_DP4
,
instr_handler
},
{
BWRITERSIO_LRP
,
instr_handler
},
/* pshader instructions */
{
BWRITERSIO_CND
,
instr_handler
},
{
BWRITERSIO_CMP
,
instr_handler
},
{
BWRITERSIO_TEXKILL
,
instr_handler
},
{
BWRITERSIO_TEX
,
instr_ps_1_0123_texld
},
{
BWRITERSIO_TEXBEM
,
instr_handler
},
{
BWRITERSIO_TEXBEML
,
instr_handler
},
{
BWRITERSIO_TEXM3x2PAD
,
instr_handler
},
{
BWRITERSIO_TEXM3x3PAD
,
instr_handler
},
{
BWRITERSIO_TEXM3x3SPEC
,
instr_handler
},
{
BWRITERSIO_TEXM3x3VSPEC
,
instr_handler
},
{
BWRITERSIO_TEXM3x3TEX
,
instr_handler
},
{
BWRITERSIO_TEXM3x3
,
instr_handler
},
{
BWRITERSIO_TEXM3x2DEPTH
,
instr_handler
},
{
BWRITERSIO_TEXM3x2TEX
,
instr_handler
},
{
BWRITERSIO_TEXDP3
,
instr_handler
},
{
BWRITERSIO_TEXDP3TEX
,
instr_handler
},
{
BWRITERSIO_END
,
NULL
},
};
static
const
struct
bytecode_backend
ps_1_0123_backend
=
{
ps_1_x_header
,
end
,
ps_1_0123_srcreg
,
ps_1_0123_dstreg
,
sm_1_x_opcode
,
ps_1_0123_handlers
};
static
void
ps_1_4_srcreg
(
struct
bc_writer
*
This
,
const
struct
shader_reg
*
reg
,
struct
bytecode_buffer
*
buffer
)
{
DWORD
token
=
(
1
<<
31
);
/* Bit 31 of registers is 1 */
...
...
@@ -1860,6 +2144,26 @@ static void init_vs30_dx9_writer(struct bc_writer *writer) {
writer
->
funcs
=
&
vs_3_backend
;
}
static
void
init_ps10_dx9_writer
(
struct
bc_writer
*
writer
)
{
TRACE
(
"Creating DirectX9 pixel shader 1.0 writer
\n
"
);
writer
->
funcs
=
&
ps_1_0123_backend
;
}
static
void
init_ps11_dx9_writer
(
struct
bc_writer
*
writer
)
{
TRACE
(
"Creating DirectX9 pixel shader 1.1 writer
\n
"
);
writer
->
funcs
=
&
ps_1_0123_backend
;
}
static
void
init_ps12_dx9_writer
(
struct
bc_writer
*
writer
)
{
TRACE
(
"Creating DirectX9 pixel shader 1.2 writer
\n
"
);
writer
->
funcs
=
&
ps_1_0123_backend
;
}
static
void
init_ps13_dx9_writer
(
struct
bc_writer
*
writer
)
{
TRACE
(
"Creating DirectX9 pixel shader 1.3 writer
\n
"
);
writer
->
funcs
=
&
ps_1_0123_backend
;
}
static
void
init_ps14_dx9_writer
(
struct
bc_writer
*
writer
)
{
TRACE
(
"Creating DirectX9 pixel shader 1.4 writer
\n
"
);
writer
->
funcs
=
&
ps_1_4_backend
;
...
...
@@ -1930,28 +2234,28 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
WARN
(
"Unsupported dxversion for pixel shader 1.0 requested: %u
\n
"
,
dxversion
);
goto
fail
;
}
/* TODO: Set the appropriate writer backend */
init_ps10_dx9_writer
(
ret
);
break
;
case
BWRITERPS_VERSION
(
1
,
1
):
if
(
dxversion
!=
9
)
{
WARN
(
"Unsupported dxversion for pixel shader 1.1 requested: %u
\n
"
,
dxversion
);
goto
fail
;
}
/* TODO: Set the appropriate writer backend */
init_ps11_dx9_writer
(
ret
);
break
;
case
BWRITERPS_VERSION
(
1
,
2
):
if
(
dxversion
!=
9
)
{
WARN
(
"Unsupported dxversion for pixel shader 1.2 requested: %u
\n
"
,
dxversion
);
goto
fail
;
}
/* TODO: Set the appropriate writer backend */
init_ps12_dx9_writer
(
ret
);
break
;
case
BWRITERPS_VERSION
(
1
,
3
):
if
(
dxversion
!=
9
)
{
WARN
(
"Unsupported dxversion for pixel shader 1.3 requested: %u
\n
"
,
dxversion
);
goto
fail
;
}
/* TODO: Set the appropriate writer backend */
init_ps13_dx9_writer
(
ret
);
break
;
case
BWRITERPS_VERSION
(
1
,
4
):
if
(
dxversion
!=
9
)
{
...
...
dlls/d3dx9_36/d3dx9_36_private.h
View file @
d567a030
...
...
@@ -323,6 +323,10 @@ void create_vs11_parser(struct asm_parser *ret);
void
create_vs20_parser
(
struct
asm_parser
*
ret
);
void
create_vs2x_parser
(
struct
asm_parser
*
ret
);
void
create_vs30_parser
(
struct
asm_parser
*
ret
);
void
create_ps10_parser
(
struct
asm_parser
*
ret
);
void
create_ps11_parser
(
struct
asm_parser
*
ret
);
void
create_ps12_parser
(
struct
asm_parser
*
ret
);
void
create_ps13_parser
(
struct
asm_parser
*
ret
);
void
create_ps14_parser
(
struct
asm_parser
*
ret
);
void
create_ps20_parser
(
struct
asm_parser
*
ret
);
void
create_ps2x_parser
(
struct
asm_parser
*
ret
);
...
...
@@ -639,6 +643,12 @@ typedef enum _BWRITERDECLUSAGE {
BWRITERDECLUSAGE_SAMPLE
}
BWRITERDECLUSAGE
;
/* ps 1.x texture registers mappings */
#define T0_REG 2
#define T1_REG 3
#define T2_REG 4
#define T3_REG 5
struct
bwriter_shader
*
SlAssembleShader
(
const
char
*
text
,
char
**
messages
);
DWORD
SlWriteBytecode
(
const
struct
bwriter_shader
*
shader
,
int
dxversion
,
DWORD
**
result
);
void
SlDeleteShader
(
struct
bwriter_shader
*
shader
);
...
...
dlls/d3dx9_36/tests/asm.c
View file @
d567a030
...
...
@@ -132,6 +132,11 @@ static void ps_1_1_test(void) {
{
0xffff0101
,
0x00000042
,
0xb00f0000
,
0x00000002
,
0x80070000
,
0x80e40000
,
0x80e40001
,
0x40000001
,
0x80080000
,
0xb0e40000
,
0x0000ffff
}
},
{
/* shader 1 */
"ps.1.1
\n
"
"mov_d4 r0, r1
\n
"
,
{
0xffff0101
,
0x00000001
,
0x8e0f0000
,
0x80e40001
,
0x0000ffff
}
},
};
exec_tests
(
"ps_1_1"
,
tests
,
sizeof
(
tests
)
/
sizeof
(
tests
[
0
]));
...
...
@@ -478,6 +483,43 @@ static void ps_1_3_test(void) {
"mov_x4_sat r0.a, -r1_bx2.a
\n
"
,
{
0xffff0103
,
0x00000001
,
0x82180000
,
0x85ff0001
,
0x0000ffff
}
},
{
/* shader 30 */
"ps_1_3
\n
"
"texcoord_x2 t0
\n
"
,
{
0xffff0103
,
0x00000040
,
0xb10f0000
,
0x0000ffff
}
},
{
/* shader 31 */
"ps_1_3
\n
"
"tex_x2 t0
\n
"
,
{
0xffff0103
,
0x00000042
,
0xb10f0000
,
0x0000ffff
}
},
{
/* shader 32 */
"ps_1_3
\n
"
"texreg2ar_x4 t0, t1
\n
"
,
{
0xffff0103
,
0x00000045
,
0xb20f0000
,
0xb0e40001
,
0x0000ffff
}
},
{
/* shader 33 */
"ps_1_3
\n
"
"texbem_d4 t1, t0
\n
"
,
{
0xffff0103
,
0x00000043
,
0xbe0f0001
,
0xb0e40000
,
0x0000ffff
}
},
{
/* shader 34 */
"ps_1_3
\n
"
"tex t0
\n
"
"texm3x3pad_x2 t1, t0
\n
"
"texm3x3pad_x2 t2, t0
\n
"
"texm3x3tex_x2 t3, t0
\n
"
,
{
0xffff0103
,
0x00000042
,
0xb00f0000
,
0x00000049
,
0xb10f0001
,
0xb0e40000
,
0x00000049
,
0xb10f0002
,
0xb0e40000
,
0x0000004a
,
0xb10f0003
,
0xb0e40000
,
0x0000ffff
}
},
{
/* shader 35 */
"ps_1_3
\n
"
"tex t0
\n
"
"texdp3tex_x8 t1, t0
\n
"
,
{
0xffff0103
,
0x00000042
,
0xb00f0000
,
0x00000053
,
0xb30f0001
,
0xb0e40000
,
0x0000ffff
}
},
};
exec_tests
(
"ps_1_3"
,
tests
,
sizeof
(
tests
)
/
sizeof
(
tests
[
0
]));
...
...
@@ -1661,9 +1703,9 @@ static void assembleshader_test(void) {
START_TEST
(
asm
)
{
preproc_test
();
todo_wine
ps_1_1_test
();
ps_1_1_test
();
vs_1_1_test
();
todo_wine
ps_1_3_test
();
ps_1_3_test
();
ps_1_4_test
();
vs_2_0_test
();
vs_2_x_test
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment