@@ -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