@ -23,6 +23,7 @@
# include "video_core/shader/ast.h"
# include "video_core/shader/ast.h"
# include "video_core/shader/node.h"
# include "video_core/shader/node.h"
# include "video_core/shader/shader_ir.h"
# include "video_core/shader/shader_ir.h"
# include "video_core/shader/transform_feedback.h"
namespace OpenGL {
namespace OpenGL {
@ -36,6 +37,7 @@ using Tegra::Shader::IpaInterpMode;
using Tegra : : Shader : : IpaMode ;
using Tegra : : Shader : : IpaMode ;
using Tegra : : Shader : : IpaSampleMode ;
using Tegra : : Shader : : IpaSampleMode ;
using Tegra : : Shader : : Register ;
using Tegra : : Shader : : Register ;
using VideoCommon : : Shader : : BuildTransformFeedback ;
using VideoCommon : : Shader : : Registry ;
using VideoCommon : : Shader : : Registry ;
using namespace std : : string_literals ;
using namespace std : : string_literals ;
@ -49,6 +51,11 @@ class ExprDecompiler;
enum class Type { Void , Bool , Bool2 , Float , Int , Uint , HalfFloat } ;
enum class Type { Void , Bool , Bool2 , Float , Int , Uint , HalfFloat } ;
constexpr std : : array FLOAT_TYPES { " float " , " vec2 " , " vec3 " , " vec4 " } ;
constexpr std : : string_view INPUT_ATTRIBUTE_NAME = " in_attr " ;
constexpr std : : string_view OUTPUT_ATTRIBUTE_NAME = " out_attr " ;
struct TextureOffset { } ;
struct TextureOffset { } ;
struct TextureDerivates { } ;
struct TextureDerivates { } ;
using TextureArgument = std : : pair < Type , Node > ;
using TextureArgument = std : : pair < Type , Node > ;
@ -390,12 +397,19 @@ std::string FlowStackTopName(MetaStackClass stack) {
return stage = = ShaderType : : Vertex ;
return stage = = ShaderType : : Vertex ;
}
}
struct GenericVaryingDescription {
std : : string name ;
u8 first_element = 0 ;
bool is_scalar = false ;
} ;
class GLSLDecompiler final {
class GLSLDecompiler final {
public :
public :
explicit GLSLDecompiler ( const Device & device , const ShaderIR & ir , const Registry & registry ,
explicit GLSLDecompiler ( const Device & device , const ShaderIR & ir , const Registry & registry ,
ShaderType stage , std : : string_view identifier , std : : string_view suffix )
ShaderType stage , std : : string_view identifier , std : : string_view suffix )
: device { device } , ir { ir } , registry { registry } , stage { stage } ,
: device { device } , ir { ir } , registry { registry } , stage { stage } ,
identifier { identifier } , suffix { suffix } , header { ir . GetHeader ( ) } { }
identifier { identifier } , suffix { suffix } , header { ir . GetHeader ( ) } ,
transform_feedback { BuildTransformFeedback ( registry . GetGraphicsInfo ( ) ) } { }
void Decompile ( ) {
void Decompile ( ) {
DeclareHeader ( ) ;
DeclareHeader ( ) ;
@ -403,17 +417,17 @@ public:
DeclareGeometry ( ) ;
DeclareGeometry ( ) ;
DeclareFragment ( ) ;
DeclareFragment ( ) ;
DeclareCompute ( ) ;
DeclareCompute ( ) ;
DeclareRegisters ( ) ;
DeclareCustomVariables ( ) ;
DeclarePredicates ( ) ;
DeclareLocalMemory ( ) ;
DeclareInternalFlags ( ) ;
DeclareInputAttributes ( ) ;
DeclareInputAttributes ( ) ;
DeclareOutputAttributes ( ) ;
DeclareOutputAttributes ( ) ;
DeclareConstantBuffers ( ) ;
DeclareGlobalMemory ( ) ;
DeclareSamplers ( ) ;
DeclareImages ( ) ;
DeclareImages ( ) ;
DeclareSamplers ( ) ;
DeclareGlobalMemory ( ) ;
DeclareConstantBuffers ( ) ;
DeclareLocalMemory ( ) ;
DeclareRegisters ( ) ;
DeclarePredicates ( ) ;
DeclareInternalFlags ( ) ;
DeclareCustomVariables ( ) ;
DeclarePhysicalAttributeReader ( ) ;
DeclarePhysicalAttributeReader ( ) ;
code . AddLine ( " void main() {{ " ) ;
code . AddLine ( " void main() {{ " ) ;
@ -485,7 +499,7 @@ private:
if ( ! identifier . empty ( ) ) {
if ( ! identifier . empty ( ) ) {
code . AddLine ( " // {} " , identifier ) ;
code . AddLine ( " // {} " , identifier ) ;
}
}
code . AddLine ( " #version 4 3 0 core" ) ;
code . AddLine ( " #version 4 4 0 core" ) ;
code . AddLine ( " #extension GL_ARB_separate_shader_objects : enable " ) ;
code . AddLine ( " #extension GL_ARB_separate_shader_objects : enable " ) ;
if ( device . HasShaderBallot ( ) ) {
if ( device . HasShaderBallot ( ) ) {
code . AddLine ( " #extension GL_ARB_shader_ballot : require " ) ;
code . AddLine ( " #extension GL_ARB_shader_ballot : require " ) ;
@ -570,7 +584,13 @@ private:
code . AddLine ( " out gl_PerVertex {{ " ) ;
code . AddLine ( " out gl_PerVertex {{ " ) ;
+ + code . scope ;
+ + code . scope ;
code . AddLine ( " vec4 gl_Position; " ) ;
auto pos_xfb = GetTransformFeedbackDecoration ( Attribute : : Index : : Position ) ;
if ( ! pos_xfb . empty ( ) ) {
pos_xfb = fmt : : format ( " layout ({}) " , pos_xfb ) ;
}
const char * pos_type =
FLOAT_TYPES . at ( GetNumComponents ( Attribute : : Index : : Position ) . value_or ( 4 ) - 1 ) ;
code . AddLine ( " {}{} gl_Position; " , pos_xfb , pos_type ) ;
for ( const auto attribute : ir . GetOutputAttributes ( ) ) {
for ( const auto attribute : ir . GetOutputAttributes ( ) ) {
if ( attribute = = Attribute : : Index : : ClipDistances0123 | |
if ( attribute = = Attribute : : Index : : ClipDistances0123 | |
@ -703,7 +723,7 @@ private:
void DeclareInputAttribute ( Attribute : : Index index , bool skip_unused ) {
void DeclareInputAttribute ( Attribute : : Index index , bool skip_unused ) {
const u32 location { GetGenericAttributeIndex ( index ) } ;
const u32 location { GetGenericAttributeIndex ( index ) } ;
std : : string name { Get InputAttribute( index ) } ;
std : : string name { Get Generic InputAttribute( index ) } ;
if ( stage = = ShaderType : : Geometry ) {
if ( stage = = ShaderType : : Geometry ) {
name = " gs_ " + name + " [] " ;
name = " gs_ " + name + " [] " ;
}
}
@ -740,9 +760,58 @@ private:
}
}
}
}
std : : optional < std : : size_t > GetNumComponents ( Attribute : : Index index , u8 element = 0 ) const {
const u8 location = static_cast < u8 > ( index ) * 4 + element ;
const auto it = transform_feedback . find ( location ) ;
if ( it = = transform_feedback . end ( ) ) {
return { } ;
}
return it - > second . components ;
}
std : : string GetTransformFeedbackDecoration ( Attribute : : Index index , u8 element = 0 ) const {
const u8 location = static_cast < u8 > ( index ) * 4 + element ;
const auto it = transform_feedback . find ( location ) ;
if ( it = = transform_feedback . end ( ) ) {
return { } ;
}
const VaryingTFB & tfb = it - > second ;
return fmt : : format ( " xfb_buffer = {}, xfb_offset = {} " , tfb . buffer , tfb . offset ) ;
}
void DeclareOutputAttribute ( Attribute : : Index index ) {
void DeclareOutputAttribute ( Attribute : : Index index ) {
const u32 location { GetGenericAttributeIndex ( index ) } ;
static constexpr std : : string_view swizzle = " xyzw " ;
code . AddLine ( " layout (location = {}) out vec4 {}; " , location , GetOutputAttribute ( index ) ) ;
u8 element = 0 ;
while ( element < 4 ) {
auto xfb = GetTransformFeedbackDecoration ( index , element ) ;
if ( ! xfb . empty ( ) ) {
xfb = fmt : : format ( " , {} " , xfb ) ;
}
const std : : size_t remainder = 4 - element ;
const std : : size_t num_components = GetNumComponents ( index , element ) . value_or ( remainder ) ;
const char * const type = FLOAT_TYPES . at ( num_components - 1 ) ;
const u32 location = GetGenericAttributeIndex ( index ) ;
GenericVaryingDescription description ;
description . first_element = static_cast < u8 > ( element ) ;
description . is_scalar = num_components = = 1 ;
description . name = AppendSuffix ( location , OUTPUT_ATTRIBUTE_NAME ) ;
if ( element ! = 0 | | num_components ! = 4 ) {
const std : : string_view name_swizzle = swizzle . substr ( element , num_components ) ;
description . name = fmt : : format ( " {}_{} " , description . name , name_swizzle ) ;
}
for ( std : : size_t i = 0 ; i < num_components ; + + i ) {
const u8 offset = static_cast < u8 > ( location * 4 + element + i ) ;
varying_description . insert ( { offset , description } ) ;
}
code . AddLine ( " layout (location = {}, component = {}{}) out {} {}; " , location , element ,
xfb , type , description . name ) ;
element + = static_cast < u8 > ( num_components ) ;
}
}
}
void DeclareConstantBuffers ( ) {
void DeclareConstantBuffers ( ) {
@ -1095,7 +1164,7 @@ private:
return { " 0 " , Type : : Int } ;
return { " 0 " , Type : : Int } ;
default :
default :
if ( IsGenericAttribute ( attribute ) ) {
if ( IsGenericAttribute ( attribute ) ) {
return { GeometryPass ( Get InputAttribute( attribute ) ) + GetSwizzle ( element ) ,
return { GeometryPass ( Get Generic InputAttribute( attribute ) ) + GetSwizzle ( element ) ,
Type : : Float } ;
Type : : Float } ;
}
}
break ;
break ;
@ -1164,8 +1233,7 @@ private:
return { { fmt : : format ( " gl_ClipDistance[{}] " , abuf - > GetElement ( ) + 4 ) , Type : : Float } } ;
return { { fmt : : format ( " gl_ClipDistance[{}] " , abuf - > GetElement ( ) + 4 ) , Type : : Float } } ;
default :
default :
if ( IsGenericAttribute ( attribute ) ) {
if ( IsGenericAttribute ( attribute ) ) {
return {
return { { GetGenericOutputAttribute ( attribute , abuf - > GetElement ( ) ) , Type : : Float } } ;
{ GetOutputAttribute ( attribute ) + GetSwizzle ( abuf - > GetElement ( ) ) , Type : : Float } } ;
}
}
UNIMPLEMENTED_MSG ( " Unhandled output attribute: {} " , static_cast < u32 > ( attribute ) ) ;
UNIMPLEMENTED_MSG ( " Unhandled output attribute: {} " , static_cast < u32 > ( attribute ) ) ;
return { } ;
return { } ;
@ -2376,27 +2444,34 @@ private:
static_assert ( operation_decompilers . size ( ) = = static_cast < std : : size_t > ( OperationCode : : Amount ) ) ;
static_assert ( operation_decompilers . size ( ) = = static_cast < std : : size_t > ( OperationCode : : Amount ) ) ;
std : : string GetRegister ( u32 index ) const {
std : : string GetRegister ( u32 index ) const {
return GetDeclarationWith Suffix( index , " gpr " ) ;
return Append Suffix( index , " gpr " ) ;
}
}
std : : string GetCustomVariable ( u32 index ) const {
std : : string GetCustomVariable ( u32 index ) const {
return GetDeclarationWith Suffix( index , " custom_var " ) ;
return Append Suffix( index , " custom_var " ) ;
}
}
std : : string GetPredicate ( Tegra : : Shader : : Pred pred ) const {
std : : string GetPredicate ( Tegra : : Shader : : Pred pred ) const {
return GetDeclarationWith Suffix( static_cast < u32 > ( pred ) , " pred " ) ;
return Append Suffix( static_cast < u32 > ( pred ) , " pred " ) ;
}
}
std : : string Get InputAttribute( Attribute : : Index attribute ) const {
std : : string Get Generic InputAttribute( Attribute : : Index attribute ) const {
return GetDeclarationWithSuffix( GetGenericAttributeIndex ( attribute ) , " input_attr " ) ;
return AppendSuffix( GetGenericAttributeIndex ( attribute ) , INPUT_ATTRIBUTE_NAME ) ;
}
}
std : : string GetOutputAttribute ( Attribute : : Index attribute ) const {
std : : unordered_map < u8 , GenericVaryingDescription > varying_description ;
return GetDeclarationWithSuffix ( GetGenericAttributeIndex ( attribute ) , " output_attr " ) ;
std : : string GetGenericOutputAttribute ( Attribute : : Index attribute , std : : size_t element ) const {
const u8 offset = static_cast < u8 > ( GetGenericAttributeIndex ( attribute ) * 4 + element ) ;
const auto & description = varying_description . at ( offset ) ;
if ( description . is_scalar ) {
return description . name ;
}
return fmt : : format ( " {}[{}] " , description . name , element - description . first_element ) ;
}
}
std : : string GetConstBuffer ( u32 index ) const {
std : : string GetConstBuffer ( u32 index ) const {
return GetDeclarationWithSuffix ( index , " cbuf " ) ;
return Append Suffix( index , " cbuf " ) ;
}
}
std : : string GetGlobalMemory ( const GlobalMemoryBase & descriptor ) const {
std : : string GetGlobalMemory ( const GlobalMemoryBase & descriptor ) const {
@ -2409,7 +2484,7 @@ private:
}
}
std : : string GetConstBufferBlock ( u32 index ) const {
std : : string GetConstBufferBlock ( u32 index ) const {
return GetDeclarationWith Suffix( index , " cbuf_block " ) ;
return Append Suffix( index , " cbuf_block " ) ;
}
}
std : : string GetLocalMemory ( ) const {
std : : string GetLocalMemory ( ) const {
@ -2434,14 +2509,14 @@ private:
}
}
std : : string GetSampler ( const Sampler & sampler ) const {
std : : string GetSampler ( const Sampler & sampler ) const {
return GetDeclarationWith Suffix( static_cast < u32 > ( sampler . GetIndex ( ) ) , " sampler " ) ;
return Append Suffix( static_cast < u32 > ( sampler . GetIndex ( ) ) , " sampler " ) ;
}
}
std : : string GetImage ( const Image & image ) const {
std : : string GetImage ( const Image & image ) const {
return GetDeclarationWith Suffix( static_cast < u32 > ( image . GetIndex ( ) ) , " image " ) ;
return Append Suffix( static_cast < u32 > ( image . GetIndex ( ) ) , " image " ) ;
}
}
std : : string GetDeclarationWith Suffix( u32 index , std : : string_view name ) const {
std : : string Append Suffix( u32 index , std : : string_view name ) const {
if ( suffix . empty ( ) ) {
if ( suffix . empty ( ) ) {
return fmt : : format ( " {}{} " , name , index ) ;
return fmt : : format ( " {}{} " , name , index ) ;
} else {
} else {
@ -2477,6 +2552,7 @@ private:
const std : : string_view identifier ;
const std : : string_view identifier ;
const std : : string_view suffix ;
const std : : string_view suffix ;
const Header header ;
const Header header ;
const std : : unordered_map < u8 , VaryingTFB > transform_feedback ;
ShaderWriter code ;
ShaderWriter code ;