Skip to content

Commit 8cedbea

Browse files
HLSL2GLSL Converter: added writeonly qualifier to image variables on GLES; fixed empty return statement from HS constant function
1 parent e4c8897 commit 8cedbea

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

Graphics/HLSL2GLSLConverterLib/include/GLSLDefinitions.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626

2727
#define GLSL
2828

29+
#ifdef GL_ES
30+
// From GLES 3.1 spec:
31+
// Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui,
32+
// image variables must specify either memory qualifier readonly or the memory qualifier writeonly.
33+
# define IMAGE_WRITEONLY writeonly
34+
#else
35+
# define IMAGE_WRITEONLY
36+
#endif
37+
2938
#define float4 vec4
3039
#define float3 vec3
3140
#define float2 vec2

Graphics/HLSL2GLSLConverterLib/include/GLSLDefinitions_inc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
"\n"
2727
"#define GLSL\n"
2828
"\n"
29+
"#ifdef GL_ES\n"
30+
"// From GLES 3.1 spec:\n"
31+
"// Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui,\n"
32+
"// image variables must specify either memory qualifier readonly or the memory qualifier writeonly.\n"
33+
"# define IMAGE_WRITEONLY writeonly\n"
34+
"#else\n"
35+
"# define IMAGE_WRITEONLY\n"
36+
"#endif \n"
37+
"\n"
2938
"#define float4 vec4\n"
3039
"#define float3 vec3\n"
3140
"#define float2 vec2\n"

Graphics/HLSL2GLSLConverterLib/src/HLSL2GLSLConverterImpl.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,7 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessTextureDeclaration( TokenL
17401740
TextureDim == TokenType::kw_RWTexture2D ||
17411741
TextureDim == TokenType::kw_RWTexture2DArray ||
17421742
TextureDim == TokenType::kw_RWTexture3D;
1743+
String ImgFormat;
17431744

17441745
++Token;
17451746
// Texture2D < float > ... ;
@@ -1822,7 +1823,6 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessTextureDeclaration( TokenL
18221823

18231824
if( IsRWTexture )
18241825
{
1825-
String ImgFormat;
18261826
// RWTexture2D<float /* format = r32f */ >
18271827
// ^
18281828
ParseImageFormat( Token->Delimiter, ImgFormat );
@@ -1928,12 +1928,19 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessTextureDeclaration( TokenL
19281928
// Texture2D TexName ;
19291929
// ^
19301930
TexDeclToken->Literal = "";
1931-
TexDeclToken->Literal.append( LayoutQualifier );
19321931
if( IsGlobalScope )
19331932
{
1933+
// Use layout qualifier for global variables only, not for function arguments
1934+
TexDeclToken->Literal.append( LayoutQualifier );
19341935
// Samplers and images in global scope must be declared uniform.
19351936
// Function arguments must not be declared uniform
19361937
TexDeclToken->Literal.append( "uniform " );
1938+
// From GLES 3.1 spec:
1939+
// Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui,
1940+
// image variables must specify either memory qualifier readonly or the memory qualifier writeonly.
1941+
// So on GLES we have to assume that an image is a writeonly variable
1942+
if(IsRWTexture && ImgFormat != "r32f" && ImgFormat != "r32i" && ImgFormat != "r32ui")
1943+
TexDeclToken->Literal.append( "IMAGE_WRITEONLY " ); // defined as 'writeonly' on GLES and as '' on desktop in GLSLDefinitions.h
19371944
}
19381945
TexDeclToken->Literal.append( CompleteGLSLSampler );
19391946
Objects.m.insert( std::make_pair( HashMapStringKey(TextureName), HLSLObjectInfo(CompleteGLSLSampler, NumComponents) ) );
@@ -2379,14 +2386,17 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessAtomics(const TokenListTyp
23792386
// ^
23802387
VERIFY_PARSER_STATE( Token, Token != ScopeEnd, "Unexpected EOF" );
23812388
VERIFY_PARSER_STATE( Token, Token->Type == TokenType::OpenBracket, "Open bracket is expected" );
2382-
2389+
23832390
auto ArgsListEndToken = Token;
23842391
auto NumArguments = CountFunctionArguments( ArgsListEndToken, ScopeEnd );
23852392
// InterlockedAdd(Tex2D[GTid.xy], 1, iOldVal);
23862393
// ^
23872394
// ArgsListEndToken
23882395
VERIFY_PARSER_STATE( ArgsListEndToken, ArgsListEndToken != ScopeEnd, "Unexpected EOF" );
23892396

2397+
++Token;
2398+
VERIFY_PARSER_STATE( Token, Token != ScopeEnd, "Unexpected EOF" );
2399+
23902400
const auto *pObjectInfo = FindHLSLObject(Token->Literal);
23912401
if( pObjectInfo != nullptr )
23922402
{
@@ -3367,7 +3377,8 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessHullShaderConstantFunction
33673377

33683378
std::stringstream PrologueSS, ReturnHandlerSS;
33693379
const Char *ReturnMacroName = "_CONST_FUNC_RETURN_";
3370-
ReturnHandlerSS << "#define " << ReturnMacroName << "(" << (bIsVoid ? "" : "_RET_VAL_") << "){\\\n";
3380+
// Some GLES compilers cannot properly handle macros with empty argument lists, such as _CONST_FUNC_RETURN_()
3381+
ReturnHandlerSS << "#define " << ReturnMacroName << (bIsVoid ? "" : "(_RET_VAL_)") << "{\\\n";
33713382

33723383
bTakesInputPatch = false;
33733384
for( const auto &TopLevelParam : Params )
@@ -3951,13 +3962,13 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessReturnStatements( TokenLis
39513962
//if( x < 0.5 ) _RETURN_( float4(0.0, 0.0, 0.0, 1.0);
39523963
// ^
39533964

3954-
while( Token->Type != TokenType::Semicolon )
3965+
while( Token != m_Tokens.end() && Token->Type != TokenType::Semicolon )
39553966
++Token;
39563967
VERIFY_PARSER_STATE( Token, Token != m_Tokens.end(), "Unexpected end of file while looking for the \';\'" );
39573968
//if( x < 0.5 ) _RETURN_( float4(0.0, 0.0, 0.0, 1.0);
39583969
// ^
39593970

3960-
// Replace semicolon with ):
3971+
// Replace semicolon with ')'
39613972
Token->Type = TokenType::ClosingBracket;
39623973
Token->Literal = ")";
39633974
//if( x < 0.5 ) _RETURN_( float4(0.0, 0.0, 0.0, 1.0))
@@ -3970,11 +3981,11 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessReturnStatements( TokenLis
39703981
auto SemicolonToken = Token;
39713982
++Token;
39723983
//if( x < 0.5 ) _RETURN_ ;
3973-
//int a;
3984+
//else
39743985
//^
39753986
m_Tokens.erase(SemicolonToken);
39763987
//if( x < 0.5 ) _RETURN_
3977-
//int a;
3988+
//else
39783989
//^
39793990
}
39803991

@@ -3997,6 +4008,12 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessReturnStatements( TokenLis
39974008
// Insert return handler before the closing brace
39984009
m_Tokens.insert(Token, TokenInfo(TokenType::TextBlock, MacroName, Token->Delimiter.c_str()));
39994010
Token->Delimiter = "\n";
4011+
// void main ()
4012+
// {
4013+
// ...
4014+
// _RETURN_
4015+
// }
4016+
// ^
40004017
}
40014018
}
40024019

@@ -4063,6 +4080,7 @@ void HLSL2GLSLConverterImpl::ConversionStream::ProcessShaderDeclaration( TokenLi
40634080

40644081
std::stringstream ReturnHandlerSS;
40654082
const Char *ReturnMacroName = "_RETURN_";
4083+
// Some GLES compilers cannot properly handle macros with empty argument lists, such as _RETURN_()
40664084
ReturnHandlerSS << "#define " << ReturnMacroName << (bIsVoid ? "" : "(_RET_VAL_)") << "{\\\n";
40674085

40684086
String GlobalVariables, Prologue;

0 commit comments

Comments
 (0)