Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Suyu
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
many-archive
Suyu
Commits
e6242ab5
There was an error fetching the commit references. Please try again later.
Commit
e6242ab5
authored
6 years ago
by
bunnei
Browse files
Options
Downloads
Patches
Plain Diff
gl_shader_decompiler: Add GLSLRegisterManager class to track register state.
parent
acede1f1
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+262
-154
262 additions, 154 deletions
src/video_core/renderer_opengl/gl_shader_decompiler.cpp
with
262 additions
and
154 deletions
src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+
262
−
154
View file @
e6242ab5
...
@@ -41,7 +41,7 @@ enum class ExitMethod {
...
@@ -41,7 +41,7 @@ enum class ExitMethod {
struct
Subroutine
{
struct
Subroutine
{
/// Generates a name suitable for GLSL source code.
/// Generates a name suitable for GLSL source code.
std
::
string
GetName
()
const
{
std
::
string
GetName
()
const
{
return
"sub_"
+
std
::
to_string
(
begin
)
+
"_"
+
std
::
to_string
(
end
);
return
"sub_"
+
std
::
to_string
(
begin
)
+
'_'
+
std
::
to_string
(
end
);
}
}
u32
begin
;
///< Entry point of the subroutine.
u32
begin
;
///< Entry point of the subroutine.
...
@@ -216,6 +216,16 @@ public:
...
@@ -216,6 +216,16 @@ public:
return
declr_type
.
find
(
Type
::
Integer
)
!=
declr_type
.
end
();
return
declr_type
.
find
(
Type
::
Integer
)
!=
declr_type
.
end
();
}
}
/// Returns true if the active type is float
bool
IsFloat
()
const
{
return
active_type
==
Type
::
Float
;
}
/// Returns true if the active type is integer
bool
IsInteger
()
const
{
return
active_type
==
Type
::
Integer
;
}
private
:
private
:
enum
class
Type
{
enum
class
Type
{
Float
,
Float
,
...
@@ -230,41 +240,168 @@ private:
...
@@ -230,41 +240,168 @@ private:
std
::
set
<
Type
>
declr_type
;
std
::
set
<
Type
>
declr_type
;
};
};
class
GLSLGenerator
{
/**
* Used to manage shader registers that are emulated with GLSL. This class keeps track of the state
* of all registers (e.g. whether they are currently being used as Floats or Integers), and
* generates the necessary GLSL code to perform conversions as needed. This class is used for
* bookkeeping within the GLSL program.
*/
class
GLSLRegisterManager
{
public:
public:
GLSLGenerator
(
const
std
::
set
<
Subroutine
>&
subroutines
,
const
ProgramCode
&
program_code
,
GLSLRegisterManager
(
ShaderWriter
&
shader
,
ShaderWriter
&
declarations
,
u32
main_offset
,
Maxwell3D
::
Regs
::
ShaderStage
stage
)
const
Maxwell3D
::
Regs
::
ShaderStage
&
stage
)
:
subroutines
(
subroutines
),
program_code
(
program_code
),
main_offset
(
main_offset
),
:
shader
{
shader
},
declarations
{
declarations
},
stage
{
stage
}
{
stage
(
stage
)
{
BuildRegisterList
();
BuildRegisterList
();
Generate
();
}
}
std
::
string
GetShaderCode
()
{
/// Generates code representing a temporary (GPR) register.
return
declarations
.
GetResult
()
+
shader
.
GetResult
();
std
::
string
GetRegister
(
const
Register
&
reg
,
unsigned
elem
=
0
)
{
if
(
reg
==
Register
::
ZeroIndex
)
{
return
"0"
;
}
return
regs
[
reg
.
GetSwizzledIndex
(
elem
)].
GetActiveString
();
}
}
/// Returns entries in the shader that are useful for external functions
/**
ShaderEntries
GetEntries
()
const
{
* Writes code that does a register assignment to float value operation. Should only be used
return
{
GetConstBuffersDeclarations
()};
* with shader instructions that deal with floats.
* @param reg The destination register to use.
* @param elem The element to use for the operation.
* @param value The code representing the value to assign.
* @param dest_num_components Number of components in the destination.
* @param value_num_components Number of components in the value.
* @param is_abs Optional, when True, applies absolute value to output.
* @param dest_elem Optional, the destination element to use for the operation.
*/
void
SetRegisterToFloat
(
const
Register
&
reg
,
u64
elem
,
const
std
::
string
&
value
,
u64
dest_num_components
,
u64
value_num_components
,
bool
is_abs
=
false
,
u64
dest_elem
=
0
)
{
ASSERT
(
regs
[
reg
].
IsFloat
());
std
::
string
dest
=
GetRegister
(
reg
,
dest_elem
);
if
(
dest_num_components
>
1
)
{
dest
+=
GetSwizzle
(
elem
);
}
std
::
string
src
=
'('
+
value
+
')'
;
if
(
value_num_components
>
1
)
{
src
+=
GetSwizzle
(
elem
);
}
src
=
is_abs
?
"abs("
+
src
+
')'
:
src
;
shader
.
AddLine
(
dest
+
" = "
+
src
+
';'
);
}
/**
* Writes code that does a register assignment to input attribute operation. Input attributes
* are stored as floats, so this may require conversion.
* @param reg The destination register to use.
* @param elem The element to use for the operation.
* @param attribute The input attibute to use as the source value.
*/
void
SetRegisterToInputAttibute
(
const
Register
&
reg
,
u64
elem
,
Attribute
::
Index
attribute
)
{
std
::
string
dest
=
GetRegister
(
reg
);
std
::
string
src
=
GetInputAttribute
(
attribute
)
+
GetSwizzle
(
elem
);
if
(
regs
[
reg
].
IsFloat
())
{
shader
.
AddLine
(
dest
+
" = "
+
src
+
';'
);
}
else
if
(
regs
[
reg
].
IsInteger
())
{
shader
.
AddLine
(
dest
+
" = floatBitsToInt("
+
src
+
");"
);
}
else
{
UNREACHABLE
();
}
}
/**
* Writes code that does a output attribute assignment to register operation. Output attributes
* are stored as floats, so this may require conversion.
* @param attribute The destination output attribute.
* @param elem The element to use for the operation.
* @param reg The register to use as the source value.
*/
void
SetOutputAttributeToRegister
(
Attribute
::
Index
attribute
,
u64
elem
,
const
Register
&
reg
)
{
std
::
string
dest
=
GetOutputAttribute
(
attribute
)
+
GetSwizzle
(
elem
);
std
::
string
src
=
GetRegister
(
reg
);
ASSERT_MSG
(
regs
[
reg
].
IsFloat
(),
"Output attributes must be set to a float"
);
shader
.
AddLine
(
dest
+
" = "
+
src
+
';'
);
}
/// Generates code representing a uniform (C buffer) register.
std
::
string
GetUniform
(
const
Uniform
&
uniform
,
const
Register
&
dest_reg
)
{
declr_const_buffers
[
uniform
.
index
].
MarkAsUsed
(
static_cast
<
unsigned
>
(
uniform
.
index
),
static_cast
<
unsigned
>
(
uniform
.
offset
),
stage
);
std
::
string
value
=
'c'
+
std
::
to_string
(
uniform
.
index
)
+
'['
+
std
::
to_string
(
uniform
.
offset
)
+
']'
;
if
(
regs
[
dest_reg
].
IsFloat
())
{
return
value
;
}
else
if
(
regs
[
dest_reg
].
IsInteger
())
{
return
"floatBitsToInt("
+
value
+
')'
;
}
else
{
UNREACHABLE
();
}
}
/// Add declarations for registers
void
GenerateDeclarations
()
{
for
(
const
auto
&
reg
:
regs
)
{
if
(
reg
.
IsFloatUsed
())
{
declarations
.
AddLine
(
"float "
+
reg
.
GetFloatString
()
+
" = 0.0;"
);
}
if
(
reg
.
IsIntegerUsed
())
{
declarations
.
AddLine
(
"int "
+
reg
.
GetIntegerString
()
+
" = 0;"
);
}
}
declarations
.
AddNewLine
();
for
(
const
auto
&
index
:
declr_input_attribute
)
{
// TODO(bunnei): Use proper number of elements for these
declarations
.
AddLine
(
"layout(location = "
+
std
::
to_string
(
static_cast
<
u32
>
(
index
)
-
static_cast
<
u32
>
(
Attribute
::
Index
::
Attribute_0
))
+
") in vec4 "
+
GetInputAttribute
(
index
)
+
';'
);
}
declarations
.
AddNewLine
();
for
(
const
auto
&
index
:
declr_output_attribute
)
{
// TODO(bunnei): Use proper number of elements for these
declarations
.
AddLine
(
"layout(location = "
+
std
::
to_string
(
static_cast
<
u32
>
(
index
)
-
static_cast
<
u32
>
(
Attribute
::
Index
::
Attribute_0
))
+
") out vec4 "
+
GetOutputAttribute
(
index
)
+
';'
);
}
declarations
.
AddNewLine
();
unsigned
const_buffer_layout
=
0
;
for
(
const
auto
&
entry
:
GetConstBuffersDeclarations
())
{
declarations
.
AddLine
(
"layout(std430) buffer "
+
entry
.
GetName
());
declarations
.
AddLine
(
'{'
);
declarations
.
AddLine
(
" float c"
+
std
::
to_string
(
entry
.
GetIndex
())
+
"[];"
);
declarations
.
AddLine
(
"};"
);
declarations
.
AddNewLine
();
++
const_buffer_layout
;
}
declarations
.
AddNewLine
();
}
/// Returns a list of constant buffer declarations
std
::
vector
<
ConstBufferEntry
>
GetConstBuffersDeclarations
()
const
{
std
::
vector
<
ConstBufferEntry
>
result
;
std
::
copy_if
(
declr_const_buffers
.
begin
(),
declr_const_buffers
.
end
(),
std
::
back_inserter
(
result
),
[](
const
auto
&
entry
)
{
return
entry
.
IsUsed
();
});
return
result
;
}
}
private
:
private
:
/// Build the GLSL register list
/// Build the GLSL register list
.
void
BuildRegisterList
()
{
void
BuildRegisterList
()
{
for
(
size_t
index
=
0
;
index
<
Register
::
NumRegisters
;
++
index
)
{
for
(
size_t
index
=
0
;
index
<
Register
::
NumRegisters
;
++
index
)
{
regs
.
emplace_back
(
index
,
shader
);
regs
.
emplace_back
(
index
,
shader
);
}
}
}
}
/// Gets the Subroutine object corresponding to the specified address.
const
Subroutine
&
GetSubroutine
(
u32
begin
,
u32
end
)
const
{
auto
iter
=
subroutines
.
find
(
Subroutine
{
begin
,
end
});
ASSERT
(
iter
!=
subroutines
.
end
());
return
*
iter
;
}
/// Generates code representing an input attribute register.
/// Generates code representing an input attribute register.
std
::
string
GetInputAttribute
(
Attribute
::
Index
attribute
)
{
std
::
string
GetInputAttribute
(
Attribute
::
Index
attribute
)
{
switch
(
attribute
)
{
switch
(
attribute
)
{
...
@@ -301,6 +438,50 @@ private:
...
@@ -301,6 +438,50 @@ private:
}
}
}
}
/// Generates code to use for a swizzle operation.
static
std
::
string
GetSwizzle
(
u64
elem
)
{
ASSERT
(
elem
<=
3
);
std
::
string
swizzle
=
"."
;
swizzle
+=
"xyzw"
[
elem
];
return
swizzle
;
}
ShaderWriter
&
shader
;
ShaderWriter
&
declarations
;
std
::
vector
<
GLSLRegister
>
regs
;
std
::
set
<
Attribute
::
Index
>
declr_input_attribute
;
std
::
set
<
Attribute
::
Index
>
declr_output_attribute
;
std
::
array
<
ConstBufferEntry
,
Maxwell3D
::
Regs
::
MaxConstBuffers
>
declr_const_buffers
;
const
Maxwell3D
::
Regs
::
ShaderStage
&
stage
;
};
class
GLSLGenerator
{
public:
GLSLGenerator
(
const
std
::
set
<
Subroutine
>&
subroutines
,
const
ProgramCode
&
program_code
,
u32
main_offset
,
Maxwell3D
::
Regs
::
ShaderStage
stage
)
:
subroutines
(
subroutines
),
program_code
(
program_code
),
main_offset
(
main_offset
),
stage
(
stage
)
{
Generate
();
}
std
::
string
GetShaderCode
()
{
return
declarations
.
GetResult
()
+
shader
.
GetResult
();
}
/// Returns entries in the shader that are useful for external functions
ShaderEntries
GetEntries
()
const
{
return
{
regs
.
GetConstBuffersDeclarations
()};
}
private
:
/// Gets the Subroutine object corresponding to the specified address.
const
Subroutine
&
GetSubroutine
(
u32
begin
,
u32
end
)
const
{
auto
iter
=
subroutines
.
find
(
Subroutine
{
begin
,
end
});
ASSERT
(
iter
!=
subroutines
.
end
());
return
*
iter
;
}
/// Generates code representing a 19-bit immediate value
/// Generates code representing a 19-bit immediate value
static
std
::
string
GetImmediate19
(
const
Instruction
&
instr
)
{
static
std
::
string
GetImmediate19
(
const
Instruction
&
instr
)
{
return
std
::
to_string
(
instr
.
alu
.
GetImm20_19
());
return
std
::
to_string
(
instr
.
alu
.
GetImm20_19
());
...
@@ -311,29 +492,13 @@ private:
...
@@ -311,29 +492,13 @@ private:
return
std
::
to_string
(
instr
.
alu
.
GetImm20_32
());
return
std
::
to_string
(
instr
.
alu
.
GetImm20_32
());
}
}
/// Generates code representing a temporary (GPR) register.
std
::
string
GetRegister
(
const
Register
&
reg
,
unsigned
elem
=
0
)
{
if
(
reg
==
Register
::
ZeroIndex
)
{
return
"0"
;
}
return
regs
[
reg
.
GetSwizzledIndex
(
elem
)].
GetActiveString
();
}
/// Generates code representing a uniform (C buffer) register.
std
::
string
GetUniform
(
const
Uniform
&
reg
)
{
declr_const_buffers
[
reg
.
index
].
MarkAsUsed
(
static_cast
<
unsigned
>
(
reg
.
index
),
static_cast
<
unsigned
>
(
reg
.
offset
),
stage
);
return
'c'
+
std
::
to_string
(
reg
.
index
)
+
'['
+
std
::
to_string
(
reg
.
offset
)
+
']'
;
}
/// Generates code representing a texture sampler.
/// Generates code representing a texture sampler.
std
::
string
GetSampler
(
const
Sampler
&
sampler
)
const
{
std
::
string
GetSampler
(
const
Sampler
&
sampler
)
const
{
// TODO(Subv): Support more than just texture sampler 0
// TODO(Subv): Support more than just texture sampler 0
ASSERT_MSG
(
sampler
.
index
==
Sampler
::
Index
::
Sampler_0
,
"unsupported"
);
ASSERT_MSG
(
sampler
.
index
==
Sampler
::
Index
::
Sampler_0
,
"unsupported"
);
const
unsigned
index
{
static_cast
<
unsigned
>
(
sampler
.
index
.
Value
())
-
const
unsigned
index
{
static_cast
<
unsigned
>
(
sampler
.
index
.
Value
())
-
static_cast
<
unsigned
>
(
Sampler
::
Index
::
Sampler_0
)};
static_cast
<
unsigned
>
(
Sampler
::
Index
::
Sampler_0
)};
return
"tex["
+
std
::
to_string
(
index
)
+
"]"
;
return
"tex["
+
std
::
to_string
(
index
)
+
']'
;
}
}
/**
/**
...
@@ -351,23 +516,6 @@ private:
...
@@ -351,23 +516,6 @@ private:
}
}
}
}
/**
* Writes code that does an assignment operation.
* @param reg the destination register code.
* @param value the code representing the value to assign.
*/
void
SetDest
(
u64
elem
,
const
std
::
string
&
reg
,
const
std
::
string
&
value
,
u64
dest_num_components
,
u64
value_num_components
,
bool
is_abs
=
false
)
{
std
::
string
swizzle
=
"."
;
swizzle
+=
"xyzw"
[
elem
];
std
::
string
dest
=
reg
+
(
dest_num_components
!=
1
?
swizzle
:
""
);
std
::
string
src
=
"("
+
value
+
")"
+
(
value_num_components
!=
1
?
swizzle
:
""
);
src
=
is_abs
?
"abs("
+
src
+
")"
:
src
;
shader
.
AddLine
(
dest
+
" = "
+
src
+
";"
);
}
/*
/*
* Writes code that assigns a predicate boolean variable.
* Writes code that assigns a predicate boolean variable.
* @param pred The id of the predicate to write to.
* @param pred The id of the predicate to write to.
...
@@ -449,11 +597,10 @@ private:
...
@@ -449,11 +597,10 @@ private:
switch
(
opcode
->
GetType
())
{
switch
(
opcode
->
GetType
())
{
case
OpCode
::
Type
::
Arithmetic
:
{
case
OpCode
::
Type
::
Arithmetic
:
{
std
::
string
dest
=
GetRegister
(
instr
.
gpr0
);
std
::
string
op_a
=
instr
.
alu
.
negate_a
?
"-"
:
""
;
std
::
string
op_a
=
instr
.
alu
.
negate_a
?
"-"
:
""
;
op_a
+=
GetRegister
(
instr
.
gpr8
);
op_a
+=
regs
.
GetRegister
(
instr
.
gpr8
);
if
(
instr
.
alu
.
abs_a
)
{
if
(
instr
.
alu
.
abs_a
)
{
op_a
=
"abs("
+
op_a
+
")"
;
op_a
=
"abs("
+
op_a
+
')'
;
}
}
std
::
string
op_b
=
instr
.
alu
.
negate_b
?
"-"
:
""
;
std
::
string
op_b
=
instr
.
alu
.
negate_b
?
"-"
:
""
;
...
@@ -462,56 +609,64 @@ private:
...
@@ -462,56 +609,64 @@ private:
op_b
+=
GetImmediate19
(
instr
);
op_b
+=
GetImmediate19
(
instr
);
}
else
{
}
else
{
if
(
instr
.
is_b_gpr
)
{
if
(
instr
.
is_b_gpr
)
{
op_b
+=
GetRegister
(
instr
.
gpr20
);
op_b
+=
regs
.
GetRegister
(
instr
.
gpr20
);
}
else
{
}
else
{
op_b
+=
GetUniform
(
instr
.
uniform
);
op_b
+=
regs
.
GetUniform
(
instr
.
uniform
,
instr
.
gpr0
);
}
}
}
}
if
(
instr
.
alu
.
abs_b
)
{
if
(
instr
.
alu
.
abs_b
)
{
op_b
=
"abs("
+
op_b
+
")"
;
op_b
=
"abs("
+
op_b
+
')'
;
}
}
switch
(
opcode
->
GetId
())
{
switch
(
opcode
->
GetId
())
{
case
OpCode
::
Id
::
FMUL_C
:
case
OpCode
::
Id
::
FMUL_C
:
case
OpCode
::
Id
::
FMUL_R
:
case
OpCode
::
Id
::
FMUL_R
:
case
OpCode
::
Id
::
FMUL_IMM
:
{
case
OpCode
::
Id
::
FMUL_IMM
:
{
SetDest
(
0
,
dest
,
op_a
+
" * "
+
op_b
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
op_a
+
" * "
+
op_b
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
}
}
case
OpCode
::
Id
::
FMUL32_IMM
:
{
case
OpCode
::
Id
::
FMUL32_IMM
:
{
// fmul32i doesn't have abs or neg bits.
// fmul32i doesn't have abs or neg bits.
SetDest
(
0
,
dest
,
GetRegister
(
instr
.
gpr8
)
+
" * "
+
GetImmediate32
(
instr
),
1
,
1
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
regs
.
GetRegister
(
instr
.
gpr8
)
+
" * "
+
GetImmediate32
(
instr
),
1
,
1
);
break
;
break
;
}
}
case
OpCode
::
Id
::
FADD_C
:
case
OpCode
::
Id
::
FADD_C
:
case
OpCode
::
Id
::
FADD_R
:
case
OpCode
::
Id
::
FADD_R
:
case
OpCode
::
Id
::
FADD_IMM
:
{
case
OpCode
::
Id
::
FADD_IMM
:
{
SetDest
(
0
,
dest
,
op_a
+
" + "
+
op_b
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
op_a
+
" + "
+
op_b
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
}
}
case
OpCode
::
Id
::
MUFU
:
{
case
OpCode
::
Id
::
MUFU
:
{
switch
(
instr
.
sub_op
)
{
switch
(
instr
.
sub_op
)
{
case
SubOp
::
Cos
:
case
SubOp
::
Cos
:
SetDest
(
0
,
dest
,
"cos("
+
op_a
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"cos("
+
op_a
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Sin
:
case
SubOp
::
Sin
:
SetDest
(
0
,
dest
,
"sin("
+
op_a
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"sin("
+
op_a
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Ex2
:
case
SubOp
::
Ex2
:
SetDest
(
0
,
dest
,
"exp2("
+
op_a
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"exp2("
+
op_a
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Lg2
:
case
SubOp
::
Lg2
:
SetDest
(
0
,
dest
,
"log2("
+
op_a
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"log2("
+
op_a
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Rcp
:
case
SubOp
::
Rcp
:
SetDest
(
0
,
dest
,
"1.0 / "
+
op_a
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"1.0 / "
+
op_a
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Rsq
:
case
SubOp
::
Rsq
:
SetDest
(
0
,
dest
,
"inversesqrt("
+
op_a
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"inversesqrt("
+
op_a
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
case
SubOp
::
Min
:
case
SubOp
::
Min
:
SetDest
(
0
,
dest
,
"min("
+
op_a
+
","
+
op_b
+
")"
,
1
,
1
,
instr
.
alu
.
abs_d
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"min("
+
op_a
+
","
+
op_b
+
')'
,
1
,
1
,
instr
.
alu
.
abs_d
);
break
;
break
;
default:
default:
NGLOG_CRITICAL
(
HW_GPU
,
"Unhandled MUFU sub op: {0:x}"
,
NGLOG_CRITICAL
(
HW_GPU
,
"Unhandled MUFU sub op: {0:x}"
,
...
@@ -532,30 +687,29 @@ private:
...
@@ -532,30 +687,29 @@ private:
break
;
break
;
}
}
case
OpCode
::
Type
::
Ffma
:
{
case
OpCode
::
Type
::
Ffma
:
{
std
::
string
dest
=
GetRegister
(
instr
.
gpr0
);
std
::
string
op_a
=
regs
.
GetRegister
(
instr
.
gpr8
);
std
::
string
op_a
=
GetRegister
(
instr
.
gpr8
);
std
::
string
op_b
=
instr
.
ffma
.
negate_b
?
"-"
:
""
;
std
::
string
op_b
=
instr
.
ffma
.
negate_b
?
"-"
:
""
;
std
::
string
op_c
=
instr
.
ffma
.
negate_c
?
"-"
:
""
;
std
::
string
op_c
=
instr
.
ffma
.
negate_c
?
"-"
:
""
;
switch
(
opcode
->
GetId
())
{
switch
(
opcode
->
GetId
())
{
case
OpCode
::
Id
::
FFMA_CR
:
{
case
OpCode
::
Id
::
FFMA_CR
:
{
op_b
+=
GetUniform
(
instr
.
uniform
);
op_b
+=
regs
.
GetUniform
(
instr
.
uniform
,
instr
.
gpr0
);
op_c
+=
GetRegister
(
instr
.
gpr39
);
op_c
+=
regs
.
GetRegister
(
instr
.
gpr39
);
break
;
break
;
}
}
case
OpCode
::
Id
::
FFMA_RR
:
{
case
OpCode
::
Id
::
FFMA_RR
:
{
op_b
+=
GetRegister
(
instr
.
gpr20
);
op_b
+=
regs
.
GetRegister
(
instr
.
gpr20
);
op_c
+=
GetRegister
(
instr
.
gpr39
);
op_c
+=
regs
.
GetRegister
(
instr
.
gpr39
);
break
;
break
;
}
}
case
OpCode
::
Id
::
FFMA_RC
:
{
case
OpCode
::
Id
::
FFMA_RC
:
{
op_b
+=
GetRegister
(
instr
.
gpr39
);
op_b
+=
regs
.
GetRegister
(
instr
.
gpr39
);
op_c
+=
GetUniform
(
instr
.
uniform
);
op_c
+=
regs
.
GetUniform
(
instr
.
uniform
,
instr
.
gpr0
);
break
;
break
;
}
}
case
OpCode
::
Id
::
FFMA_IMM
:
{
case
OpCode
::
Id
::
FFMA_IMM
:
{
op_b
+=
GetImmediate19
(
instr
);
op_b
+=
GetImmediate19
(
instr
);
op_c
+=
GetRegister
(
instr
.
gpr39
);
op_c
+=
regs
.
GetRegister
(
instr
.
gpr39
);
break
;
break
;
}
}
default
:
{
default
:
{
...
@@ -564,28 +718,29 @@ private:
...
@@ -564,28 +718,29 @@ private:
}
}
}
}
SetDest
(
0
,
dest
,
op_a
+
" * "
+
op_b
+
" + "
+
op_c
,
1
,
1
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
op_a
+
" * "
+
op_b
+
" + "
+
op_c
,
1
,
1
);
break
;
break
;
}
}
case
OpCode
::
Type
::
Memory
:
{
case
OpCode
::
Type
::
Memory
:
{
std
::
string
gpr0
=
GetRegister
(
instr
.
gpr0
);
const
Attribute
::
Index
attribute
=
instr
.
attribute
.
fmt20
.
index
;
const
Attribute
::
Index
attribute
=
instr
.
attribute
.
fmt20
.
index
;
switch
(
opcode
->
GetId
())
{
switch
(
opcode
->
GetId
())
{
case
OpCode
::
Id
::
LD_A
:
{
case
OpCode
::
Id
::
LD_A
:
{
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
0
,
"untested"
);
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
0
,
"untested"
);
SetDest
(
instr
.
attribute
.
fmt20
.
element
,
gpr0
,
GetInputAttribute
(
attribute
),
1
,
4
);
regs
.
SetRegisterToInputAttibute
(
instr
.
gpr0
,
instr
.
attribute
.
fmt20
.
element
,
attribute
);
break
;
break
;
}
}
case
OpCode
::
Id
::
ST_A
:
{
case
OpCode
::
Id
::
ST_A
:
{
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
0
,
"untested"
);
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
0
,
"untested"
);
SetDest
(
instr
.
attribute
.
fmt20
.
element
,
GetOutputAttribute
(
attribute
),
gpr0
,
4
,
1
);
regs
.
SetOutputAttributeToRegister
(
attribute
,
instr
.
attribute
.
fmt20
.
element
,
instr
.
gpr0
);
break
;
break
;
}
}
case
OpCode
::
Id
::
TEXS
:
{
case
OpCode
::
Id
::
TEXS
:
{
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
4
,
"untested"
);
ASSERT_MSG
(
instr
.
attribute
.
fmt20
.
size
==
4
,
"untested"
);
const
std
::
string
op_a
=
GetRegister
(
instr
.
gpr8
);
const
std
::
string
op_a
=
regs
.
GetRegister
(
instr
.
gpr8
);
const
std
::
string
op_b
=
GetRegister
(
instr
.
gpr20
);
const
std
::
string
op_b
=
regs
.
GetRegister
(
instr
.
gpr20
);
const
std
::
string
sampler
=
GetSampler
(
instr
.
sampler
);
const
std
::
string
sampler
=
GetSampler
(
instr
.
sampler
);
const
std
::
string
coord
=
"vec2 coords = vec2("
+
op_a
+
", "
+
op_b
+
");"
;
const
std
::
string
coord
=
"vec2 coords = vec2("
+
op_a
+
", "
+
op_b
+
");"
;
// Add an extra scope and declare the texture coords inside to prevent overwriting
// Add an extra scope and declare the texture coords inside to prevent overwriting
...
@@ -595,7 +750,7 @@ private:
...
@@ -595,7 +750,7 @@ private:
shader
.
AddLine
(
coord
);
shader
.
AddLine
(
coord
);
const
std
::
string
texture
=
"texture("
+
sampler
+
", coords)"
;
const
std
::
string
texture
=
"texture("
+
sampler
+
", coords)"
;
for
(
unsigned
elem
=
0
;
elem
<
instr
.
attribute
.
fmt20
.
size
;
++
elem
)
{
for
(
unsigned
elem
=
0
;
elem
<
instr
.
attribute
.
fmt20
.
size
;
++
elem
)
{
SetDest
(
elem
,
G
etRegister
(
instr
.
gpr0
,
elem
)
,
texture
,
1
,
4
);
regs
.
S
etRegister
ToFloat
(
instr
.
gpr0
,
elem
,
texture
,
1
,
4
,
false
,
elem
);
}
}
--
shader
.
scope
;
--
shader
.
scope
;
shader
.
AddLine
(
"}"
);
shader
.
AddLine
(
"}"
);
...
@@ -610,7 +765,7 @@ private:
...
@@ -610,7 +765,7 @@ private:
}
}
case
OpCode
::
Type
::
FloatSetPredicate
:
{
case
OpCode
::
Type
::
FloatSetPredicate
:
{
std
::
string
op_a
=
instr
.
fsetp
.
neg_a
?
"-"
:
""
;
std
::
string
op_a
=
instr
.
fsetp
.
neg_a
?
"-"
:
""
;
op_a
+=
GetRegister
(
instr
.
gpr8
);
op_a
+=
regs
.
GetRegister
(
instr
.
gpr8
);
if
(
instr
.
fsetp
.
abs_a
)
{
if
(
instr
.
fsetp
.
abs_a
)
{
op_a
=
"abs("
+
op_a
+
')'
;
op_a
=
"abs("
+
op_a
+
')'
;
...
@@ -626,9 +781,9 @@ private:
...
@@ -626,9 +781,9 @@ private:
op_b
+=
'('
+
GetImmediate19
(
instr
)
+
')'
;
op_b
+=
'('
+
GetImmediate19
(
instr
)
+
')'
;
}
else
{
}
else
{
if
(
instr
.
is_b_gpr
)
{
if
(
instr
.
is_b_gpr
)
{
op_b
+=
GetRegister
(
instr
.
gpr20
);
op_b
+=
regs
.
GetRegister
(
instr
.
gpr20
);
}
else
{
}
else
{
op_b
+=
GetUniform
(
instr
.
uniform
);
op_b
+=
regs
.
GetUniform
(
instr
.
uniform
,
instr
.
gpr0
);
}
}
}
}
...
@@ -660,9 +815,8 @@ private:
...
@@ -660,9 +815,8 @@ private:
break
;
break
;
}
}
case
OpCode
::
Type
::
FloatSet
:
{
case
OpCode
::
Type
::
FloatSet
:
{
std
::
string
dest
=
GetRegister
(
instr
.
gpr0
);
std
::
string
op_a
=
instr
.
fset
.
neg_a
?
"-"
:
""
;
std
::
string
op_a
=
instr
.
fset
.
neg_a
?
"-"
:
""
;
op_a
+=
GetRegister
(
instr
.
gpr8
);
op_a
+=
regs
.
GetRegister
(
instr
.
gpr8
);
if
(
instr
.
fset
.
abs_a
)
{
if
(
instr
.
fset
.
abs_a
)
{
op_a
=
"abs("
+
op_a
+
')'
;
op_a
=
"abs("
+
op_a
+
')'
;
...
@@ -678,14 +832,14 @@ private:
...
@@ -678,14 +832,14 @@ private:
op_b
+=
imm
;
op_b
+=
imm
;
}
else
{
}
else
{
if
(
instr
.
is_b_gpr
)
{
if
(
instr
.
is_b_gpr
)
{
op_b
+=
GetRegister
(
instr
.
gpr20
);
op_b
+=
regs
.
GetRegister
(
instr
.
gpr20
);
}
else
{
}
else
{
op_b
+=
GetUniform
(
instr
.
uniform
);
op_b
+=
regs
.
GetUniform
(
instr
.
uniform
,
instr
.
gpr0
);
}
}
}
}
if
(
instr
.
fset
.
abs_b
)
{
if
(
instr
.
fset
.
abs_b
)
{
op_b
=
"abs("
+
op_b
+
")"
;
op_b
=
"abs("
+
op_b
+
')'
;
}
}
using
Tegra
::
Shader
::
Pred
;
using
Tegra
::
Shader
::
Pred
;
...
@@ -697,13 +851,16 @@ private:
...
@@ -697,13 +851,16 @@ private:
using
Tegra
::
Shader
::
PredCondition
;
using
Tegra
::
Shader
::
PredCondition
;
switch
(
instr
.
fset
.
cond
)
{
switch
(
instr
.
fset
.
cond
)
{
case
PredCondition
::
LessThan
:
case
PredCondition
::
LessThan
:
SetDest
(
0
,
dest
,
"(("
+
op_a
+
") < ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"(("
+
op_a
+
") < ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
break
;
break
;
case
PredCondition
::
Equal
:
case
PredCondition
::
Equal
:
SetDest
(
0
,
dest
,
"(("
+
op_a
+
") == ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"(("
+
op_a
+
") == ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
break
;
break
;
case
PredCondition
::
GreaterThan
:
case
PredCondition
::
GreaterThan
:
SetDest
(
0
,
dest
,
"(("
+
op_a
+
") > ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
regs
.
SetRegisterToFloat
(
instr
.
gpr0
,
0
,
"(("
+
op_a
+
") > ("
+
op_b
+
")) ? 1.0 : 0"
,
1
,
1
);
break
;
break
;
default:
default:
NGLOG_CRITICAL
(
HW_GPU
,
"Unhandled predicate condition: {} (a: {}, b: {})"
,
NGLOG_CRITICAL
(
HW_GPU
,
"Unhandled predicate condition: {} (a: {}, b: {})"
,
...
@@ -720,10 +877,10 @@ private:
...
@@ -720,10 +877,10 @@ private:
// Final color output is currently hardcoded to GPR0-3 for fragment shaders
// Final color output is currently hardcoded to GPR0-3 for fragment shaders
if
(
stage
==
Maxwell3D
::
Regs
::
ShaderStage
::
Fragment
)
{
if
(
stage
==
Maxwell3D
::
Regs
::
ShaderStage
::
Fragment
)
{
shader
.
AddLine
(
"color.r = "
+
GetRegister
(
0
)
+
";"
);
shader
.
AddLine
(
"color.r = "
+
regs
.
GetRegister
(
0
)
+
';'
);
shader
.
AddLine
(
"color.g = "
+
GetRegister
(
1
)
+
";"
);
shader
.
AddLine
(
"color.g = "
+
regs
.
GetRegister
(
1
)
+
';'
);
shader
.
AddLine
(
"color.b = "
+
GetRegister
(
2
)
+
";"
);
shader
.
AddLine
(
"color.b = "
+
regs
.
GetRegister
(
2
)
+
';'
);
shader
.
AddLine
(
"color.a = "
+
GetRegister
(
3
)
+
";"
);
shader
.
AddLine
(
"color.a = "
+
regs
.
GetRegister
(
3
)
+
';'
);
}
}
shader
.
AddLine
(
"return true;"
);
shader
.
AddLine
(
"return true;"
);
...
@@ -736,8 +893,7 @@ private:
...
@@ -736,8 +893,7 @@ private:
}
}
case
OpCode
::
Id
::
IPA
:
{
case
OpCode
::
Id
::
IPA
:
{
const
auto
&
attribute
=
instr
.
attribute
.
fmt28
;
const
auto
&
attribute
=
instr
.
attribute
.
fmt28
;
std
::
string
dest
=
GetRegister
(
instr
.
gpr0
);
regs
.
SetRegisterToInputAttibute
(
instr
.
gpr0
,
attribute
.
element
,
attribute
.
index
);
SetDest
(
attribute
.
element
,
dest
,
GetInputAttribute
(
attribute
.
index
),
1
,
4
);
break
;
break
;
}
}
default
:
{
default
:
{
...
@@ -843,55 +999,10 @@ private:
...
@@ -843,55 +999,10 @@ private:
GenerateDeclarations
();
GenerateDeclarations
();
}
}
/// Returns a list of constant buffer declarations
std
::
vector
<
ConstBufferEntry
>
GetConstBuffersDeclarations
()
const
{
std
::
vector
<
ConstBufferEntry
>
result
;
std
::
copy_if
(
declr_const_buffers
.
begin
(),
declr_const_buffers
.
end
(),
std
::
back_inserter
(
result
),
[](
const
auto
&
entry
)
{
return
entry
.
IsUsed
();
});
return
result
;
}
/// Add declarations for registers
/// Add declarations for registers
void
GenerateDeclarations
()
{
void
GenerateDeclarations
()
{
for
(
const
auto
&
reg
:
regs
)
{
regs
.
GenerateDeclarations
();
if
(
reg
.
IsFloatUsed
())
{
declarations
.
AddLine
(
"float "
+
reg
.
GetFloatString
()
+
" = 0.0;"
);
}
if
(
reg
.
IsIntegerUsed
())
{
declarations
.
AddLine
(
"int "
+
reg
.
GetIntegerString
()
+
" = 0;"
);
}
}
declarations
.
AddNewLine
();
for
(
const
auto
&
index
:
declr_input_attribute
)
{
// TODO(bunnei): Use proper number of elements for these
declarations
.
AddLine
(
"layout(location = "
+
std
::
to_string
(
static_cast
<
u32
>
(
index
)
-
static_cast
<
u32
>
(
Attribute
::
Index
::
Attribute_0
))
+
") in vec4 "
+
GetInputAttribute
(
index
)
+
";"
);
}
declarations
.
AddNewLine
();
for
(
const
auto
&
index
:
declr_output_attribute
)
{
// TODO(bunnei): Use proper number of elements for these
declarations
.
AddLine
(
"layout(location = "
+
std
::
to_string
(
static_cast
<
u32
>
(
index
)
-
static_cast
<
u32
>
(
Attribute
::
Index
::
Attribute_0
))
+
") out vec4 "
+
GetOutputAttribute
(
index
)
+
";"
);
}
declarations
.
AddNewLine
();
unsigned
const_buffer_layout
=
0
;
for
(
const
auto
&
entry
:
GetConstBuffersDeclarations
())
{
declarations
.
AddLine
(
"layout(std430) buffer "
+
entry
.
GetName
());
declarations
.
AddLine
(
'{'
);
declarations
.
AddLine
(
" float c"
+
std
::
to_string
(
entry
.
GetIndex
())
+
"[];"
);
declarations
.
AddLine
(
"};"
);
declarations
.
AddNewLine
();
++
const_buffer_layout
;
}
declarations
.
AddNewLine
();
for
(
const
auto
&
pred
:
declr_predicates
)
{
for
(
const
auto
&
pred
:
declr_predicates
)
{
declarations
.
AddLine
(
"bool "
+
pred
+
" = false;"
);
declarations
.
AddLine
(
"bool "
+
pred
+
" = false;"
);
}
}
...
@@ -906,13 +1017,10 @@ private:
...
@@ -906,13 +1017,10 @@ private:
ShaderWriter
shader
;
ShaderWriter
shader
;
ShaderWriter
declarations
;
ShaderWriter
declarations
;
std
::
vector
<
GLSLRegister
>
regs
;
GLSLRegisterManager
regs
{
shader
,
declarations
,
stage
}
;
// Declarations
// Declarations
std
::
set
<
std
::
string
>
declr_predicates
;
std
::
set
<
std
::
string
>
declr_predicates
;
std
::
set
<
Attribute
::
Index
>
declr_input_attribute
;
std
::
set
<
Attribute
::
Index
>
declr_output_attribute
;
std
::
array
<
ConstBufferEntry
,
Maxwell3D
::
Regs
::
MaxConstBuffers
>
declr_const_buffers
;
};
// namespace Decompiler
};
// namespace Decompiler
std
::
string
GetCommonDeclarations
()
{
std
::
string
GetCommonDeclarations
()
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment