2016-01-07 08:17:16 -05:00
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2014-09-29 14:31:38 -04:00
// .
2014-06-05 16:38:54 -04:00
# include "ShaderCompilerCommon.h"
# include "ModuleManager.h"
2015-07-02 11:52:03 -04:00
# include "CrossCompilerCommon.h"
# include "TypeHash.h"
2014-09-29 18:57:21 -04:00
2014-09-21 20:35:48 -04:00
2014-06-05 16:38:54 -04:00
IMPLEMENT_MODULE ( FDefaultModuleImpl , ShaderCompilerCommon ) ;
2015-07-30 13:31:13 -04:00
/**
* The shader frequency .
*/
enum EHlslShaderFrequency
{
HSF_VertexShader ,
HSF_PixelShader ,
HSF_GeometryShader ,
HSF_HullShader ,
HSF_DomainShader ,
HSF_ComputeShader ,
HSF_FrequencyCount ,
HSF_InvalidFrequency = - 1
} ;
/**
* Compilation flags . See PackUniformBuffers . h for details on Grouping / Packing uniforms .
*/
enum EHlslCompileFlag
{
/** Disables validation of the IR. */
HLSLCC_NoValidation = 0x1 ,
/** Disabled preprocessing. */
HLSLCC_NoPreprocess = 0x2 ,
/** Pack uniforms into typed arrays. */
HLSLCC_PackUniforms = 0x4 ,
/** Assume that input shaders output into DX11 clip space,
* and adjust them for OpenGL clip space . */
HLSLCC_DX11ClipSpace = 0x8 ,
/** Print AST for debug purposes. */
HLSLCC_PrintAST = 0x10 ,
// Removed any structures embedded on uniform buffers flattens them into elements of the uniform buffer (Mostly for ES 2: this implies PackUniforms).
HLSLCC_FlattenUniformBufferStructures = 0x20 | HLSLCC_PackUniforms ,
// Removes uniform buffers and flattens them into globals (Mostly for ES 2: this implies PackUniforms & Flatten Structures).
HLSLCC_FlattenUniformBuffers = 0x40 | HLSLCC_PackUniforms | HLSLCC_FlattenUniformBufferStructures ,
// Groups flattened uniform buffers per uniform buffer source/precision (Implies Flatten UBs)
HLSLCC_GroupFlattenedUniformBuffers = 0x80 | HLSLCC_FlattenUniformBuffers ,
// Remove redundant subexpressions [including texture fetches] (to workaround certain drivers who can't optimize redundant texture fetches)
HLSLCC_ApplyCommonSubexpressionElimination = 0x100 ,
// Expand subexpressions/obfuscate (to workaround certain drivers who can't deal with long nested expressions)
HLSLCC_ExpandSubexpressions = 0x200 ,
// Generate shaders compatible with the separate_shader_objects extension
HLSLCC_SeparateShaderObjects = 0x400 ,
// Finds variables being used as atomics and changes all references to use atomic reads/writes
HLSLCC_FixAtomicReferences = 0x800 ,
// Packs global uniforms & flattens structures, and makes each packed array its own uniform buffer
HLSLCC_PackUniformsIntoUniformBuffers = 0x1000 | HLSLCC_PackUniforms ,
} ;
2014-09-21 20:35:48 -04:00
2015-10-06 15:59:09 -04:00
int16 GetNumUniformBuffersUsed ( const FShaderCompilerResourceTable & InSRT )
2014-08-25 14:41:54 -04:00
{
auto CountLambda = [ & ] ( const TArray < uint32 > & In )
{
int16 LastIndex = - 1 ;
for ( int32 i = 0 ; i < In . Num ( ) ; + + i )
{
auto BufferIndex = FRHIResourceTableEntry : : GetUniformBufferIndex ( In [ i ] ) ;
2015-04-09 17:01:04 -04:00
if ( BufferIndex ! = static_cast < uint16 > ( FRHIResourceTableEntry : : GetEndOfStreamToken ( ) ) )
2014-08-25 14:41:54 -04:00
{
LastIndex = FMath : : Max ( LastIndex , ( int16 ) BufferIndex ) ;
}
}
return LastIndex + 1 ;
} ;
int16 Num = CountLambda ( InSRT . SamplerMap ) ;
Num = FMath : : Max ( Num , ( int16 ) CountLambda ( InSRT . ShaderResourceViewMap ) ) ;
Num = FMath : : Max ( Num , ( int16 ) CountLambda ( InSRT . TextureMap ) ) ;
Num = FMath : : Max ( Num , ( int16 ) CountLambda ( InSRT . UnorderedAccessViewMap ) ) ;
return Num ;
}
2014-06-05 16:38:54 -04:00
void BuildResourceTableTokenStream ( const TArray < uint32 > & InResourceMap , int32 MaxBoundResourceTable , TArray < uint32 > & OutTokenStream )
{
// First we sort the resource map.
TArray < uint32 > SortedResourceMap = InResourceMap ;
SortedResourceMap . Sort ( ) ;
// The token stream begins with a table that contains offsets per bound uniform buffer.
// This offset provides the start of the token stream.
OutTokenStream . AddZeroed ( MaxBoundResourceTable + 1 ) ;
auto LastBufferIndex = FRHIResourceTableEntry : : GetEndOfStreamToken ( ) ;
for ( int32 i = 0 ; i < SortedResourceMap . Num ( ) ; + + i )
{
auto BufferIndex = FRHIResourceTableEntry : : GetUniformBufferIndex ( SortedResourceMap [ i ] ) ;
if ( BufferIndex ! = LastBufferIndex )
{
// Store the offset for resources from this buffer.
OutTokenStream [ BufferIndex ] = OutTokenStream . Num ( ) ;
LastBufferIndex = BufferIndex ;
}
OutTokenStream . Add ( SortedResourceMap [ i ] ) ;
}
// Add a token to mark the end of the stream. Not needed if there are no bound resources.
if ( OutTokenStream . Num ( ) )
{
OutTokenStream . Add ( FRHIResourceTableEntry : : GetEndOfStreamToken ( ) ) ;
}
}
2014-09-21 20:35:48 -04:00
2014-06-05 16:38:54 -04:00
void BuildResourceTableMapping (
const TMap < FString , FResourceTableEntry > & ResourceTableMap ,
const TMap < FString , uint32 > & ResourceTableLayoutHashes ,
TBitArray < > & UsedUniformBufferSlots ,
FShaderParameterMap & ParameterMap ,
2015-10-06 15:59:09 -04:00
FShaderCompilerResourceTable & OutSRT )
2014-06-05 16:38:54 -04:00
{
check ( OutSRT . ResourceTableBits = = 0 ) ;
check ( OutSRT . ResourceTableLayoutHashes . Num ( ) = = 0 ) ;
// Build resource table mapping
int32 MaxBoundResourceTable = - 1 ;
TArray < uint32 > ResourceTableSRVs ;
TArray < uint32 > ResourceTableSamplerStates ;
TArray < uint32 > ResourceTableUAVs ;
for ( auto MapIt = ResourceTableMap . CreateConstIterator ( ) ; MapIt ; + + MapIt )
{
const FString & Name = MapIt - > Key ;
const FResourceTableEntry & Entry = MapIt - > Value ;
uint16 BufferIndex , BaseIndex , Size ;
if ( ParameterMap . FindParameterAllocation ( * Name , BufferIndex , BaseIndex , Size ) )
{
ParameterMap . RemoveParameterAllocation ( * Name ) ;
uint16 UniformBufferIndex = INDEX_NONE , UBBaseIndex , UBSize ;
if ( ParameterMap . FindParameterAllocation ( * Entry . UniformBufferName , UniformBufferIndex , UBBaseIndex , UBSize ) = = false )
{
UniformBufferIndex = UsedUniformBufferSlots . FindAndSetFirstZeroBit ( ) ;
ParameterMap . AddParameterAllocation ( * Entry . UniformBufferName , UniformBufferIndex , 0 , 0 ) ;
}
OutSRT . ResourceTableBits | = ( 1 < < UniformBufferIndex ) ;
MaxBoundResourceTable = FMath : : Max < int32 > ( MaxBoundResourceTable , ( int32 ) UniformBufferIndex ) ;
while ( OutSRT . ResourceTableLayoutHashes . Num ( ) < = MaxBoundResourceTable )
{
OutSRT . ResourceTableLayoutHashes . Add ( 0 ) ;
}
OutSRT . ResourceTableLayoutHashes [ UniformBufferIndex ] = ResourceTableLayoutHashes . FindChecked ( Entry . UniformBufferName ) ;
auto ResourceMap = FRHIResourceTableEntry : : Create ( UniformBufferIndex , Entry . ResourceIndex , BaseIndex ) ;
switch ( Entry . Type )
{
case UBMT_TEXTURE :
OutSRT . TextureMap . Add ( ResourceMap ) ;
break ;
case UBMT_SAMPLER :
OutSRT . SamplerMap . Add ( ResourceMap ) ;
break ;
case UBMT_SRV :
OutSRT . ShaderResourceViewMap . Add ( ResourceMap ) ;
break ;
case UBMT_UAV :
OutSRT . UnorderedAccessViewMap . Add ( ResourceMap ) ;
break ;
default :
check ( 0 ) ;
}
}
}
OutSRT . MaxBoundResourceTable = MaxBoundResourceTable ;
}
2015-05-28 16:46:01 -04:00
// Specialized version of FString::ReplaceInline that checks that the search word is not inside a #line directive
2015-01-12 18:28:54 -05:00
static void WholeWordReplaceInline ( FString & String , TCHAR * StartPtr , const TCHAR * SearchText , const TCHAR * ReplacementText )
{
if ( String . Len ( ) > 0
& & SearchText ! = nullptr & & * SearchText ! = 0
& & ReplacementText ! = nullptr & & FCString : : Strcmp ( SearchText , ReplacementText ) ! = 0 )
{
const int32 NumCharsToReplace = FCString : : Strlen ( SearchText ) ;
const int32 NumCharsToInsert = FCString : : Strlen ( ReplacementText ) ;
check ( NumCharsToInsert = = NumCharsToReplace ) ;
check ( * StartPtr ) ;
TCHAR * Pos = FCString : : Strstr ( StartPtr , SearchText ) ;
while ( Pos ! = nullptr )
{
// Find a " character, indicating we might be inside a #line directive
TCHAR * FoundQuote = nullptr ;
auto * ValidatePos = Pos ;
do
{
- - ValidatePos ;
if ( * ValidatePos = = ' \" ' )
{
FoundQuote = ValidatePos ;
break ;
}
}
while ( ValidatePos > = StartPtr & & * ValidatePos ! = ' \n ' ) ;
bool bReplace = true ;
if ( FoundQuote )
{
// Validate that we're indeed inside a #line directive by first finding the last \n character
TCHAR * FoundEOL = nullptr ;
do
{
- - ValidatePos ;
if ( * ValidatePos = = ' \n ' )
{
FoundEOL = ValidatePos ;
break ;
}
}
while ( ValidatePos > StartPtr ) ;
// Finally make sure the directive is between the \n and the and the quote
if ( FoundEOL )
{
auto * FoundInclude = FCString : : Strstr ( FoundEOL + 1 , TEXT ( " #line " ) ) ;
if ( FoundInclude & & FoundInclude < FoundQuote )
{
bReplace = false ;
}
}
}
2015-05-28 16:46:01 -04:00
// Make sure this is not part of an identifier
if ( bReplace & & Pos > StartPtr )
{
const auto Char = Pos [ - 1 ] ;
if ( ( Char > = ' a ' & & Char < = ' z ' ) | |
( Char > = ' A ' & & Char < = ' Z ' ) | |
( Char > = ' 0 ' & & Char < = ' 9 ' ) | |
Char = = ' _ ' )
{
bReplace = false ;
}
}
2015-01-12 18:28:54 -05:00
if ( bReplace )
{
// FCString::Strcpy inserts a terminating zero so can't use that
for ( int32 i = 0 ; i < NumCharsToInsert ; i + + )
{
Pos [ i ] = ReplacementText [ i ] ;
}
}
if ( Pos + NumCharsToReplace - * String < String . Len ( ) )
{
Pos = FCString : : Strstr ( Pos + NumCharsToReplace , SearchText ) ;
}
else
{
break ;
}
}
}
}
2014-09-21 20:35:48 -04:00
2016-01-07 11:21:22 -05:00
bool RemoveUniformBuffersFromSource ( FString & SourceCode )
2014-06-05 16:38:54 -04:00
{
static const FString StaticStructToken ( TEXT ( " static const struct " ) ) ;
int32 StaticStructTokenPos = SourceCode . Find ( StaticStructToken , ESearchCase : : CaseSensitive , ESearchDir : : FromStart ) ;
while ( StaticStructTokenPos ! = INDEX_NONE )
{
static const FString CloseBraceSpaceToken ( TEXT ( " } " ) ) ;
int32 CloseBraceSpaceTokenPos = SourceCode . Find ( CloseBraceSpaceToken , ESearchCase : : CaseSensitive , ESearchDir : : FromStart , StaticStructTokenPos + StaticStructToken . Len ( ) ) ;
if ( CloseBraceSpaceTokenPos = = INDEX_NONE )
{
check ( 0 ) ; //@todo-rco: ERROR
return false ;
}
int32 NamePos = CloseBraceSpaceTokenPos + CloseBraceSpaceToken . Len ( ) ;
static const FString SpaceEqualsToken ( TEXT ( " = " ) ) ;
int32 SpaceEqualsTokenPos = SourceCode . Find ( SpaceEqualsToken , ESearchCase : : CaseSensitive , ESearchDir : : FromStart , NamePos ) ;
if ( SpaceEqualsTokenPos = = INDEX_NONE )
{
check ( 0 ) ; //@todo-rco: ERROR
return false ;
}
FString UniformBufferName = SourceCode . Mid ( NamePos , SpaceEqualsTokenPos - NamePos ) ;
check ( UniformBufferName . Len ( ) > 0 ) ;
static const FString CloseBraceSemicolorToken ( TEXT ( " }; " ) ) ;
int32 CloseBraceSemicolonTokenPos = SourceCode . Find ( CloseBraceSemicolorToken , ESearchCase : : CaseSensitive , ESearchDir : : FromStart , SpaceEqualsTokenPos + SpaceEqualsToken . Len ( ) ) ;
if ( CloseBraceSemicolonTokenPos = = INDEX_NONE )
{
check ( 0 ) ; //@todo-rco: ERROR
return false ;
}
// Comment out this UB
auto & SourceCharArray = SourceCode . GetCharArray ( ) ;
SourceCharArray [ StaticStructTokenPos ] = TCHAR ( ' / ' ) ;
SourceCharArray [ StaticStructTokenPos + 1 ] = TCHAR ( ' * ' ) ;
SourceCharArray [ CloseBraceSemicolonTokenPos ] = TCHAR ( ' * ' ) ;
SourceCharArray [ CloseBraceSemicolonTokenPos + 1 ] = TCHAR ( ' / ' ) ;
// Find & Replace this UB
FString UBSource = UniformBufferName + FString ( TEXT ( " . " ) ) ;
FString UBDest = UniformBufferName + FString ( TEXT ( " _ " ) ) ;
2015-01-12 18:28:54 -05:00
WholeWordReplaceInline ( SourceCode , & SourceCharArray [ CloseBraceSemicolonTokenPos + 2 ] , * UBSource , * UBDest ) ;
2014-06-05 16:38:54 -04:00
// Find next UB
StaticStructTokenPos = SourceCode . Find ( StaticStructToken , ESearchCase : : CaseSensitive , ESearchDir : : FromStart , CloseBraceSemicolonTokenPos + 2 ) ;
}
return true ;
}
2014-06-30 18:32:57 -04:00
2014-09-21 20:35:48 -04:00
2016-06-08 16:02:23 -04:00
FString CreateShaderCompilerWorkerDirectCommandLine ( const FShaderCompilerInput & Input )
{
FString Text ( TEXT ( " -directcompile -format= " ) ) ;
Text + = Input . ShaderFormat . GetPlainNameString ( ) ;
Text + = TEXT ( " -entry= " ) ;
Text + = Input . EntryPointName ;
switch ( Input . Target . Frequency )
{
case SF_Vertex : Text + = TEXT ( " -vs " ) ; break ;
case SF_Hull : Text + = TEXT ( " -hs " ) ; break ;
case SF_Domain : Text + = TEXT ( " -ds " ) ; break ;
case SF_Geometry : Text + = TEXT ( " -gs " ) ; break ;
case SF_Pixel : Text + = TEXT ( " -ps " ) ; break ;
case SF_Compute : Text + = TEXT ( " -cs " ) ; break ;
default : ensure ( 0 ) ; break ;
}
if ( Input . bCompilingForShaderPipeline )
{
Text + = TEXT ( " -pipeline " ) ;
}
if ( Input . bIncludeUsedOutputs )
{
Text + = TEXT ( " -usedoutputs= " ) ;
for ( int32 Index = 0 ; Index < Input . UsedOutputs . Num ( ) ; + + Index )
{
if ( Index ! = 0 )
{
Text + = TEXT ( " + " ) ;
}
Text + = Input . UsedOutputs [ Index ] ;
}
}
Text + = TEXT ( " " ) ;
Text + = Input . DumpDebugInfoPath / Input . SourceFilename + TEXT ( " .usf " ) ;
uint64 CFlags = 0 ;
for ( int32 Index = 0 ; Index < Input . Environment . CompilerFlags . Num ( ) ; + + Index )
{
CFlags = CFlags | ( ( uint64 ) 1 < < ( uint64 ) Input . Environment . CompilerFlags [ Index ] ) ;
}
if ( CFlags )
{
Text + = TEXT ( " -cflags= " ) ;
Text + = FString : : Printf ( TEXT ( " %llu " ) , CFlags ) ;
}
return Text ;
}
2015-07-02 11:52:03 -04:00
namespace CrossCompiler
2014-06-30 18:32:57 -04:00
{
2015-07-30 13:31:13 -04:00
FString CreateBatchFileContents ( const FString & ShaderFile , const FString & OutputFile , uint32 Frequency , const FString & EntryPoint , const FString & VersionSwitch , uint32 CCFlags , const FString & ExtraArguments )
2015-02-22 19:58:52 -05:00
{
2015-07-30 13:31:13 -04:00
const TCHAR * FrequencySwitch = TEXT ( " " ) ;
switch ( Frequency )
{
case HSF_PixelShader : FrequencySwitch = TEXT ( " -ps " ) ; break ;
case HSF_VertexShader : FrequencySwitch = TEXT ( " -vs " ) ; break ;
case HSF_HullShader : FrequencySwitch = TEXT ( " -hs " ) ; break ;
case HSF_DomainShader : FrequencySwitch = TEXT ( " -ds " ) ; break ;
case HSF_ComputeShader : FrequencySwitch = TEXT ( " -cs " ) ; break ;
case HSF_GeometryShader : FrequencySwitch = TEXT ( " -gs " ) ; break ;
default : check ( 0 ) ; break ;
}
FString CCTCmdLine = ExtraArguments ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_NoValidation ) = = HLSLCC_NoValidation ) ? TEXT ( " -novalidate " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_DX11ClipSpace ) = = HLSLCC_DX11ClipSpace ) ? TEXT ( " -dx11clip " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_NoPreprocess ) = = HLSLCC_NoPreprocess ) ? TEXT ( " -nopp " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_FlattenUniformBuffers ) = = HLSLCC_FlattenUniformBuffers ) ? TEXT ( " -flattenub " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_FlattenUniformBufferStructures ) = = HLSLCC_FlattenUniformBufferStructures ) ? TEXT ( " -flattenubstruct " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_GroupFlattenedUniformBuffers ) = = HLSLCC_GroupFlattenedUniformBuffers ) ? TEXT ( " -groupflatub " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_ApplyCommonSubexpressionElimination ) = = HLSLCC_ApplyCommonSubexpressionElimination ) ? TEXT ( " -cse " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_ExpandSubexpressions ) = = HLSLCC_ExpandSubexpressions ) ? TEXT ( " -xpxpr " ) : TEXT ( " " ) ;
CCTCmdLine + = ( ( CCFlags & HLSLCC_SeparateShaderObjects ) = = HLSLCC_SeparateShaderObjects ) ? TEXT ( " -separateshaders " ) : TEXT ( " " ) ;
2015-09-28 16:09:22 -04:00
CCTCmdLine + = ( ( CCFlags & HLSLCC_PackUniformsIntoUniformBuffers ) = = HLSLCC_PackUniformsIntoUniformBuffers ) ? TEXT ( " -packintoubs " ) : TEXT ( " " ) ;
Copying //UE4/Dev-Rendering to //UE4/Dev-Main (Source: //UE4/Dev-Rendering @ 2998063)
#lockdown nick.penwarden
==========================
MAJOR FEATURES + CHANGES
==========================
Change 2981877 on 2016/05/18 by Rolando.Caloca
DR - Fix some PVS warnings
- Removed 'uniform' as a keyword on hlslcc as it's ignored/causes issues/doesn't really optimize
#jira UE-30996
Change 2981966 on 2016/05/18 by Rolando.Caloca
DR - Fix OpenGL crash quitting editor
#jira UE-25549
Change 2982072 on 2016/05/18 by Uriel.Doyon
Fixed a "Build Texture Streaming" crash related to custom outputs.
Fixed issue with debug view mode and translucent primitives
Fix bug with visibility that made some texture low res.
Enabled per instance visibility in the texture streaming order (in game only).
Improved InvestigateTexture Logs.
Tweaked the mip computations from screen size.
Change 2982077 on 2016/05/18 by Uriel.Doyon
Removed debug options!
Change 2982108 on 2016/05/18 by Olaf.Piesche
#jira UE-30772
moving AMD hacks to console variables
Change 2982422 on 2016/05/18 by Gil.Gribb
UE4 - Potential crash fix on foliage occlusion queries and reflection captures.
Change 2982547 on 2016/05/18 by Martin.Mittring
UE-26409 Crash when Light Propagation Volume Plugin is disabled on a Project
Change 2982548 on 2016/05/18 by Martin.Mittring
Refactored MRT and outer Pixel Shader output to a struct
to allow it passed in/out of functions allowing for a more readable code (less #ifdefs, reducing the boolean hell)
Needed for upcoming MeshDecals
Change 2982601 on 2016/05/18 by Daniel.Wright
Movable skylight now matches stationary for subsurface shading models
* Two sided was broken in 4.11, Subsurface had never been handled
Change 2982603 on 2016/05/18 by Daniel.Wright
DrawMaterialToRenderTarget / BeginDrawCanvasToRenderTarget now work correctly with material parameter collections and Time
* FCanvas stores an optional scene to render to, UWorld caches the UCanvas needed for implementing these functions
Change 2982618 on 2016/05/18 by Daniel.Wright
Better categories for some Rendering project settings
Change 2982619 on 2016/05/18 by Daniel.Wright
Scene capture 2d improvements
* Orthographic projection supported
* Opacity is now captured in alpha, allows partial rendering in a scene capture and compositing into another scene later
* Various GBuffer attributes are now available to be captured, including depth
* Changed Blueprint capture function to CaptureScene, which happens immediately (was previously deferred), allowing multiple captures with different parameters
Change 2982664 on 2016/05/18 by Daniel.Wright
Fading out planar reflections based on roughness since they don't have support for variable roughness (fade starts at .2 roughness, ends at .3)
Change 2982684 on 2016/05/18 by Martin.Mittring
polish ImageValidator
Change 2982685 on 2016/05/18 by Martin.Mittring
show testimage on sm4 as well
Change 2982736 on 2016/05/18 by Uriel.Doyon
Improved overbudget retention logic.
Updated ListStreamingTextures stats.
Change 2982854 on 2016/05/18 by Martin.Mittring
ImageValidator can now save/load IVxml file
Change 2982863 on 2016/05/18 by Daniel.Wright
Fixed shader compile error
Change 2982864 on 2016/05/18 by Daniel.Wright
Removed deprecation message
Change 2982927 on 2016/05/18 by Martin.Mittring
ImageValidator is now sorting by time
Change 2983743 on 2016/05/19 by Chris.Bunner
Saturated tri-planar UV function outputs to prevent negative blending
#jira UE-30964
Change 2983747 on 2016/05/19 by Martin.Wilson
Fix for morph curves not getting applied to meshes in cooked builds (smart names were not being corrected).
Change 2984008 on 2016/05/19 by Brian.Karis
New contact shadows feature.
Hair uses ray cast for nonshadow lights
Change 2984009 on 2016/05/19 by Brian.Karis
changed to ShadowedBits
Change 2984054 on 2016/05/19 by Brian.Karis
Deleted old motion blur
Change 2984420 on 2016/05/19 by Daniel.Wright
Shorter display name for WorldPosition material node
Change 2984423 on 2016/05/19 by Daniel.Wright
Fixed WorldPosition and ScreenPosition for downsampled separate translucency by scaling SvPosition before those computations. The View uniform buffer still contains incorrect buffer sizes for this pass.
Change 2984432 on 2016/05/19 by Rolando.Caloca
DR - Disable PPCombineLUT for Vulkan to work around glslang issue (will need to be reenabled when adding SM4/5 path)
Change 2985415 on 2016/05/20 by Daniel.Wright
Added a Texture2D exporter for .hdr
Texture2D exporters now implement SupportsObject properly, so you only see extensions that are valid based on the format
Change 2985439 on 2016/05/20 by Daniel.Wright
Scene color alpha clear value validation
Change 2987173 on 2016/05/23 by Martin.Mittring
ImageValidator Report with Thumbnail (cannot be copied and pasted into email), non Thumbnail version could be.
Change 2987248 on 2016/05/23 by Martin.Mittring
ImageValidator: added Summary, removed timer hack
Change 2987369 on 2016/05/23 by Martin.Mittring
ImageValidator polish
Change 2987390 on 2016/05/23 by Brian.Karis
Improvement to temporal aa sharpness and speed.
Change 2988038 on 2016/05/24 by Gil.Gribb
Merging //UE4/Dev-Main@2987977 to Dev-Rendering (//UE4/Dev-Rendering)
Change 2988304 on 2016/05/24 by Martin.Mittring
added const to prevent coding errors
Change 2988332 on 2016/05/24 by Brian.Karis
Fixed motion blur crash on SM4
Change 2988446 on 2016/05/24 by Martin.Mittring
nicer UI
Change 2988990 on 2016/05/24 by Martin.Mittring
fixed UE-31227 Building lighting produces bad results
#jira:UE-31227
Change 2989729 on 2016/05/25 by Uriel.Doyon
Fixed lightmaps and shadowmaps having low resolutions after building the lighting.
#jira UE-31254
Change 2989752 on 2016/05/25 by Olaf.Piesche
CVar to disable/freeze GPU particle simulation
Change 2989811 on 2016/05/25 by Daniel.Wright
Making use of MATERIALBLENDING_ANY_TRANSLUCENT
Change 2989812 on 2016/05/25 by Daniel.Wright
Hide DFGI show flags from UI
Change 2989901 on 2016/05/25 by Daniel.Wright
Height fog now works properly in planar reflections
* The ray used for computing fog is first clipped by the reflection plane
Change 2989904 on 2016/05/25 by Daniel.Wright
Always use PF_FloatRGBA for LightAccumulation to guarantee alpha channel and negative range
Change 2989991 on 2016/05/25 by Daniel.Wright
Improved usability for DBuffer Decals
* 'Show Decals' works correctly, previously would fetch from uninitialized textures
* DBuffer being enabled forces a full prepass, previously decals would render incorrectly unless correct settings of r.EarlyZPass were used
* Improved the PrePass draw event to indicate whether it's full or partial
* Materials using DBuffer blend modes will fail to compile when the DBuffer project setting is disabled, instead of just being invisible
* r.EarlyZPass can now be changed at runtime, which is useful for profiling
Change 2990008 on 2016/05/25 by Daniel.Wright
Fixed capsule shadows on skeletal meshes with scaling
Change 2990274 on 2016/05/25 by Daniel.Wright
Fixed DFAO (from cl 2961310)
Change 2990304 on 2016/05/25 by Martin.Mittring
OR-22233 GPU Sprites invisible unless solo'd
#jira:OR-22233
Change 2990309 on 2016/05/25 by Martin.Mittring
Added SubDSurface actor (using CPU code of OpenSubDiv), component, asset as starting point for more work in that direction,
(Early work in progress)
Change 2990363 on 2016/05/25 by Daniel.Wright
Spreading precomputed visibility to neighbors now uses a 2d grid to find neighbors, speeds up the process for 800k cells from 40 mins to 20s
Change 2990392 on 2016/05/25 by Daniel.Wright
Added r.AOSpecularOcclusionMode, which determines how specular should be occluded by DFAO
0: Apply non-directional AO to specular.
1: (default) Intersect the reflection cone with the unoccluded cone produced by DFAO. This gives more accurate occlusion than 0, but can bring out DFAO sampling artifacts.
2: (experimental) Cone trace through distance fields along the reflection vector. Costs about the same as DFAO again because more cone tracing is done, but produces more accurate occlusion.
Change 2990454 on 2016/05/25 by Martin.Mittring
polish readme
Change 2990610 on 2016/05/25 by Martin.Mittring
fixed building with VS2015, the right OpenSubDiv .lib files are missing, temporarily disabled the relevant code
#code_review:Shane.Caudle
Change 2990754 on 2016/05/25 by Zabir.Hoque
Fix compiler warning: C4456: declaration of 'NewStaticMesh' hides previous local declaration.
#CodeReview: Martin.Mittring
Change 2990801 on 2016/05/25 by Zabir.Hoque
Only allocate reflection capture cubemaps if we are actually doing a reflection capture. The old approach always allocated based on CVar and worked with a warning on D3D since if SRC was larger than the DST, the extra SRC area was dropped. New approach only allocates when necessary and is correctly sized everytime. Also hardened access to CVar and what users are allowed to set.
#CodeReview Marcus.Wassmer, Rolando.Caloca, Daniel.Wright, Martin.Mittring
Change 2991169 on 2016/05/26 by Martin.Mittring
fixed compiler warning
WARNING: Non-editor build cannot depend on non-redistributable modules. Details:
#lockdown: gil.gribb
Change 2991238 on 2016/05/26 by Martin.Mittring
fixed build
fatal error C1083: Cannot open include file: 'RawMesh.h': No such file or directory (when RawMesh is not part of PrivateDependencyModuleNames in Engine.Build.cs)
#lockdown:Gil.Gribb
Change 2991726 on 2016/05/26 by Daniel.Wright
Subsurface materials are now handled with simple forward shading
#jira OR-22237
#lockdown gil.gribb
Change 2991727 on 2016/05/26 by Daniel.Wright
Emissive decals are now supported with simple forward shading
#jira OR-22282
#lockdown Gil.Gribb
Change 2994849 on 2016/05/31 by Daniel.Wright
Disabled fix for WorldPosition and ScreenPosition in downsampled separate translucency, since it breaks GetScreenAlignedUV (used in DepthFade), since the uniform buffer still contains full res buffer sizes
#lockdown Gil.Gribb
Change 2997243 on 2016/06/01 by Gil.Gribb
Merging //UE4/Dev-Main@2996565 to Dev-Rendering (//UE4/Dev-Rendering)
#lockdown nick.penwarden
[CL 2998067 by Gil Gribb in Main branch]
2016-06-02 13:13:43 -04:00
CCTCmdLine + = ( ( CCFlags & HLSLCC_FixAtomicReferences ) = = HLSLCC_FixAtomicReferences ) ? TEXT ( " -fixatomics " ) : TEXT ( " " ) ;
2015-07-02 11:52:03 -04:00
FString BatchFile ;
if ( PLATFORM_MAC )
{
2015-07-30 13:31:13 -04:00
BatchFile = FPaths : : RootDir ( ) / FString : : Printf ( TEXT ( " Engine/Source/ThirdParty/hlslcc/hlslcc/bin/Mac/hlslcc_64 %s -o=%s %s -entry=%s %s %s " ) , * ShaderFile , * OutputFile , FrequencySwitch , * EntryPoint , * VersionSwitch , * CCTCmdLine ) ;
2015-07-02 11:52:03 -04:00
}
else if ( PLATFORM_LINUX )
{
2015-08-03 16:07:57 -04:00
BatchFile = TEXT ( " #!/bin/sh \n " ) ;
2016-03-17 11:10:14 -04:00
// add an extra '/' to the file name (which is absolute at this point) because CrossCompilerTool will strip out first '/' considering it a legacy DOS-style switch marker.
BatchFile + = FPaths : : RootDir ( ) / FString : : Printf ( TEXT ( " Engine/Binaries/Linux/CrossCompilerTool /%s -o=%s %s -entry=%s %s %s " ) , * ShaderFile , * OutputFile , FrequencySwitch , * EntryPoint , * VersionSwitch , * CCTCmdLine ) ;
2015-07-02 11:52:03 -04:00
}
else if ( PLATFORM_WINDOWS )
{
BatchFile = TEXT ( " @echo off " ) ;
BatchFile + = TEXT ( " \n if defined ue.hlslcc GOTO DONE \n set ue.hlslcc= " ) ;
BatchFile + = FPaths : : RootDir ( ) / TEXT ( " Engine \\ Binaries \\ Win64 \\ CrossCompilerTool.exe " ) ;
BatchFile + = TEXT ( " \n \n :DONE \n %ue.hlslcc% " ) ;
2015-07-30 13:31:13 -04:00
BatchFile + = FString : : Printf ( TEXT ( " \" %s \" -o= \" %s \" %s -entry=%s %s %s " ) , * ShaderFile , * OutputFile , FrequencySwitch , * EntryPoint , * VersionSwitch , * CCTCmdLine ) ;
2015-07-02 11:52:03 -04:00
BatchFile + = TEXT ( " \n pause \n " ) ;
}
else
{
checkf ( false , TEXT ( " CreateCrossCompilerBatchFileContents: unsupported platform! " ) ) ;
}
return BatchFile ;
2015-02-22 19:58:52 -05:00
}
2015-07-02 11:52:03 -04:00
/**
* Parse an error emitted by the HLSL cross - compiler .
* @ param OutErrors - Array into which compiler errors may be added .
* @ param InLine - A line from the compile log .
*/
void ParseHlslccError ( TArray < FShaderCompilerError > & OutErrors , const FString & InLine )
{
const TCHAR * p = * InLine ;
FShaderCompilerError * Error = new ( OutErrors ) FShaderCompilerError ( ) ;
// Copy the filename.
while ( * p & & * p ! = TEXT ( ' ( ' ) ) { Error - > ErrorFile + = ( * p + + ) ; }
Error - > ErrorFile = GetRelativeShaderFilename ( Error - > ErrorFile ) ;
p + + ;
// Parse the line number.
int32 LineNumber = 0 ;
while ( * p & & * p > = TEXT ( ' 0 ' ) & & * p < = TEXT ( ' 9 ' ) )
{
LineNumber = 10 * LineNumber + ( * p + + - TEXT ( ' 0 ' ) ) ;
}
Error - > ErrorLineString = * FString : : Printf ( TEXT ( " %d " ) , LineNumber ) ;
// Skip to the warning message.
while ( * p & & ( * p = = TEXT ( ' ) ' ) | | * p = = TEXT ( ' : ' ) | | * p = = TEXT ( ' ' ) | | * p = = TEXT ( ' \t ' ) ) ) { p + + ; }
Error - > StrippedErrorMessage = p ;
}
static inline bool ParseIdentifier ( const ANSICHAR * & Str , FString & OutStr )
{
OutStr = TEXT ( " " ) ;
FString Result ;
while ( ( * Str > = ' A ' & & * Str < = ' Z ' )
| | ( * Str > = ' a ' & & * Str < = ' z ' )
| | ( * Str > = ' 0 ' & & * Str < = ' 9 ' )
| | * Str = = ' _ ' )
{
OutStr + = ( TCHAR ) * Str ;
+ + Str ;
}
return OutStr . Len ( ) > 0 ;
}
static FORCEINLINE bool Match ( const ANSICHAR * & Str , ANSICHAR Char )
{
if ( * Str = = Char )
{
+ + Str ;
return true ;
}
return false ;
}
template < typename T >
static bool ParseIntegerNumber ( const ANSICHAR * & Str , T & OutNum )
{
auto * OriginalStr = Str ;
OutNum = 0 ;
while ( * Str > = ' 0 ' & & * Str < = ' 9 ' )
{
OutNum = OutNum * 10 + * Str + + - ' 0 ' ;
}
return Str ! = OriginalStr ;
}
static bool ParseSignedNumber ( const ANSICHAR * & Str , int32 & OutNum )
{
int32 Sign = Match ( Str , ' - ' ) ? - 1 : 1 ;
uint32 Num = 0 ;
if ( ParseIntegerNumber ( Str , Num ) )
{
OutNum = Sign * ( int32 ) Num ;
return true ;
}
return false ;
}
/** Map shader frequency -> string for messages. */
static const TCHAR * FrequencyStringTable [ ] =
{
TEXT ( " Vertex " ) ,
TEXT ( " Hull " ) ,
TEXT ( " Domain " ) ,
TEXT ( " Pixel " ) ,
TEXT ( " Geometry " ) ,
TEXT ( " Compute " )
} ;
/** Compile time check to verify that the GL mapping tables are up-to-date. */
static_assert ( SF_NumFrequencies = = ARRAY_COUNT ( FrequencyStringTable ) , " NumFrequencies changed. Please update tables. " ) ;
const TCHAR * GetFrequencyName ( EShaderFrequency Frequency )
{
check ( ( int32 ) Frequency > = 0 & & Frequency < SF_NumFrequencies ) ;
return FrequencyStringTable [ Frequency ] ;
}
FHlslccHeader : : FHlslccHeader ( ) :
Name ( TEXT ( " " ) )
{
NumThreads [ 0 ] = NumThreads [ 1 ] = NumThreads [ 2 ] = 0 ;
}
bool FHlslccHeader : : Read ( const ANSICHAR * & ShaderSource , int32 SourceLen )
{
# define DEF_PREFIX_STR(Str) \
static const ANSICHAR * Str # # Prefix = " // @ " # Str " : " ; \
static const int32 Str # # PrefixLen = FCStringAnsi : : Strlen ( Str # # Prefix )
DEF_PREFIX_STR ( Inputs ) ;
DEF_PREFIX_STR ( Outputs ) ;
DEF_PREFIX_STR ( UniformBlocks ) ;
DEF_PREFIX_STR ( Uniforms ) ;
DEF_PREFIX_STR ( PackedGlobals ) ;
DEF_PREFIX_STR ( PackedUB ) ;
DEF_PREFIX_STR ( PackedUBCopies ) ;
DEF_PREFIX_STR ( PackedUBGlobalCopies ) ;
DEF_PREFIX_STR ( Samplers ) ;
DEF_PREFIX_STR ( UAVs ) ;
DEF_PREFIX_STR ( SamplerStates ) ;
DEF_PREFIX_STR ( NumThreads ) ;
# undef DEF_PREFIX_STR
// Skip any comments that come before the signature.
while ( FCStringAnsi : : Strncmp ( ShaderSource , " // " , 2 ) = = 0 & &
FCStringAnsi : : Strncmp ( ShaderSource + 2 , " ! " , 2 ) ! = 0 & &
FCStringAnsi : : Strncmp ( ShaderSource + 2 , " @ " , 2 ) ! = 0 )
{
ShaderSource + = 2 ;
while ( * ShaderSource & & * ShaderSource + + ! = ' \n ' )
{
// Do nothing
}
}
// Read shader name if any
2015-07-02 15:19:30 -04:00
if ( FCStringAnsi : : Strncmp ( ShaderSource , " // ! " , 4 ) = = 0 )
2015-07-02 11:52:03 -04:00
{
2015-07-02 15:19:30 -04:00
ShaderSource + = 4 ;
2015-07-02 11:52:03 -04:00
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
Name + = ( TCHAR ) * ShaderSource ;
+ + ShaderSource ;
}
2015-07-02 15:19:30 -04:00
if ( * ShaderSource = = ' \n ' )
{
+ + ShaderSource ;
}
}
// Skip any comments that come before the signature.
while ( FCStringAnsi : : Strncmp ( ShaderSource , " // " , 2 ) = = 0 & &
FCStringAnsi : : Strncmp ( ShaderSource + 2 , " @ " , 2 ) ! = 0 )
{
ShaderSource + = 2 ;
while ( * ShaderSource & & * ShaderSource + + ! = ' \n ' )
{
// Do nothing
}
2015-07-02 11:52:03 -04:00
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , InputsPrefix , InputsPrefixLen ) = = 0 )
{
ShaderSource + = InputsPrefixLen ;
if ( ! ReadInOut ( ShaderSource , Inputs ) )
{
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , OutputsPrefix , OutputsPrefixLen ) = = 0 )
{
ShaderSource + = OutputsPrefixLen ;
if ( ! ReadInOut ( ShaderSource , Outputs ) )
{
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , UniformBlocksPrefix , UniformBlocksPrefixLen ) = = 0 )
{
ShaderSource + = UniformBlocksPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FAttribute UniformBlock ;
if ( ! ParseIdentifier ( ShaderSource , UniformBlock . Name ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , UniformBlock . Index ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
UniformBlocks . Add ( UniformBlock ) ;
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , UniformsPrefix , UniformsPrefixLen ) = = 0 )
{
// @todo-mobile: Will we ever need to support this code path?
check ( 0 ) ;
return false ;
/*
ShaderSource + = UniformsPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
uint16 ArrayIndex = 0 ;
uint16 Offset = 0 ;
uint16 NumComponents = 0 ;
FString ParameterName = ParseIdentifier ( ShaderSource ) ;
verify ( ParameterName . Len ( ) > 0 ) ;
verify ( Match ( ShaderSource , ' ( ' ) ) ;
ArrayIndex = ParseNumber ( ShaderSource ) ;
verify ( Match ( ShaderSource , ' : ' ) ) ;
Offset = ParseNumber ( ShaderSource ) ;
verify ( Match ( ShaderSource , ' : ' ) ) ;
NumComponents = ParseNumber ( ShaderSource ) ;
verify ( Match ( ShaderSource , ' ) ' ) ) ;
ParameterMap . AddParameterAllocation (
* ParameterName ,
ArrayIndex ,
Offset * BytesPerComponent ,
NumComponents * BytesPerComponent
) ;
if ( ArrayIndex < OGL_NUM_PACKED_UNIFORM_ARRAYS )
{
PackedUniformSize [ ArrayIndex ] = FMath : : Max < uint16 > (
PackedUniformSize [ ArrayIndex ] ,
BytesPerComponent * ( Offset + NumComponents )
) ;
}
// Skip the comma.
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
verify ( Match ( ShaderSource , ' , ' ) ) ;
}
Match ( ShaderSource , ' \n ' ) ;
*/
}
// @PackedGlobals: Global0(h:0,1),Global1(h:4,1),Global2(h:8,1)
if ( FCStringAnsi : : Strncmp ( ShaderSource , PackedGlobalsPrefix , PackedGlobalsPrefixLen ) = = 0 )
{
ShaderSource + = PackedGlobalsPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FPackedGlobal PackedGlobal ;
if ( ! ParseIdentifier ( ShaderSource , PackedGlobal . Name ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
PackedGlobal . PackedType = * ShaderSource + + ;
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedGlobal . Offset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' , ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedGlobal . Count ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
PackedGlobals . Add ( PackedGlobal ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
}
// Packed Uniform Buffers (Multiple lines)
// @PackedUB: CBuffer(0): CBMember0(0,1),CBMember1(1,1)
while ( FCStringAnsi : : Strncmp ( ShaderSource , PackedUBPrefix , PackedUBPrefixLen ) = = 0 )
{
ShaderSource + = PackedUBPrefixLen ;
FPackedUB PackedUB ;
if ( ! ParseIdentifier ( ShaderSource , PackedUB . Attribute . Name ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedUB . Attribute . Index ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ' ) )
{
return false ;
}
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FPackedUB : : FMember Member ;
ParseIdentifier ( ShaderSource , Member . Name ) ;
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , Member . Offset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' , ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , Member . Count ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
PackedUB . Members . Add ( Member ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
PackedUBs . Add ( PackedUB ) ;
}
// @PackedUBCopies: 0:0-0:h:0:1,0:1-0:h:4:1,1:0-1:h:0:1
if ( FCStringAnsi : : Strncmp ( ShaderSource , PackedUBCopiesPrefix , PackedUBCopiesPrefixLen ) = = 0 )
{
ShaderSource + = PackedUBCopiesPrefixLen ;
if ( ! ReadCopies ( ShaderSource , false , PackedUBCopies ) )
{
return false ;
}
}
// @PackedUBGlobalCopies: 0:0-h:12:1,0:1-h:16:1,1:0-h:20:1
if ( FCStringAnsi : : Strncmp ( ShaderSource , PackedUBGlobalCopiesPrefix , PackedUBGlobalCopiesPrefixLen ) = = 0 )
{
ShaderSource + = PackedUBGlobalCopiesPrefixLen ;
if ( ! ReadCopies ( ShaderSource , true , PackedUBGlobalCopies ) )
{
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , SamplersPrefix , SamplersPrefixLen ) = = 0 )
{
ShaderSource + = SamplersPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FSampler Sampler ;
if ( ! ParseIdentifier ( ShaderSource , Sampler . Name ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , Sampler . Offset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , Sampler . Count ) )
{
return false ;
}
if ( Match ( ShaderSource , ' [ ' ) )
{
// Sampler States
do
{
FString SamplerState ;
if ( ! ParseIdentifier ( ShaderSource , SamplerState ) )
{
return false ;
}
Sampler . SamplerStates . Add ( SamplerState ) ;
}
while ( Match ( ShaderSource , ' , ' ) ) ;
if ( ! Match ( ShaderSource , ' ] ' ) )
{
return false ;
}
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
Samplers . Add ( Sampler ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , UAVsPrefix , UAVsPrefixLen ) = = 0 )
{
ShaderSource + = UAVsPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FUAV UAV ;
if ( ! ParseIdentifier ( ShaderSource , UAV . Name ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ( ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , UAV . Offset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , UAV . Count ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ) ' ) )
{
return false ;
}
UAVs . Add ( UAV ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , SamplerStatesPrefix , SamplerStatesPrefixLen ) = = 0 )
{
ShaderSource + = SamplerStatesPrefixLen ;
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FAttribute SamplerState ;
if ( ! ParseIntegerNumber ( ShaderSource , SamplerState . Index ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIdentifier ( ShaderSource , SamplerState . Name ) )
{
return false ;
}
SamplerStates . Add ( SamplerState ) ;
2015-07-02 15:19:30 -04:00
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
2015-07-02 11:52:03 -04:00
}
}
if ( FCStringAnsi : : Strncmp ( ShaderSource , NumThreadsPrefix , NumThreadsPrefixLen ) = = 0 )
{
ShaderSource + = NumThreadsPrefixLen ;
if ( ! ParseIntegerNumber ( ShaderSource , NumThreads [ 0 ] ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' , ' ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , NumThreads [ 1 ] ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' , ' ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , NumThreads [ 2 ] ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' \n ' ) )
{
return false ;
}
}
return true ;
}
bool FHlslccHeader : : ReadCopies ( const ANSICHAR * & ShaderSource , bool bGlobals , TArray < FPackedUBCopy > & OutCopies )
{
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FPackedUBCopy PackedUBCopy ;
PackedUBCopy . DestUB = 0 ;
if ( ! ParseIntegerNumber ( ShaderSource , PackedUBCopy . SourceUB ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedUBCopy . SourceOffset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' - ' ) )
{
return false ;
}
if ( ! bGlobals )
{
if ( ! ParseIntegerNumber ( ShaderSource , PackedUBCopy . DestUB ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
}
PackedUBCopy . DestPackedType = * ShaderSource + + ;
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedUBCopy . DestOffset ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIntegerNumber ( ShaderSource , PackedUBCopy . Count ) )
{
return false ;
}
OutCopies . Add ( PackedUBCopy ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
return true ;
}
bool FHlslccHeader : : ReadInOut ( const ANSICHAR * & ShaderSource , TArray < FInOut > & OutAttributes )
{
while ( * ShaderSource & & * ShaderSource ! = ' \n ' )
{
FInOut Attribute ;
if ( ! ParseIdentifier ( ShaderSource , Attribute . Type ) )
{
return false ;
}
if ( Match ( ShaderSource , ' [ ' ) )
{
if ( ! ParseIntegerNumber ( ShaderSource , Attribute . ArrayCount ) )
{
return false ;
}
if ( ! Match ( ShaderSource , ' ] ' ) )
{
return false ;
}
}
else
{
Attribute . ArrayCount = 0 ;
}
2015-07-02 14:43:11 -04:00
if ( Match ( ShaderSource , ' ; ' ) )
2015-07-02 11:52:03 -04:00
{
2015-07-02 14:43:11 -04:00
if ( ! ParseSignedNumber ( ShaderSource , Attribute . Index ) )
{
return false ;
}
2015-07-02 11:52:03 -04:00
}
if ( ! Match ( ShaderSource , ' : ' ) )
{
return false ;
}
if ( ! ParseIdentifier ( ShaderSource , Attribute . Name ) )
{
return false ;
}
2015-07-10 14:14:44 -04:00
// Optional array suffix
if ( Match ( ShaderSource , ' [ ' ) )
{
Attribute . Name + = ' [ ' ;
while ( * ShaderSource )
{
Attribute . Name + = * ShaderSource ;
if ( Match ( ShaderSource , ' ] ' ) )
{
break ;
}
+ + ShaderSource ;
}
}
2015-07-02 11:52:03 -04:00
OutAttributes . Add ( Attribute ) ;
// Break if EOL
if ( Match ( ShaderSource , ' \n ' ) )
{
break ;
}
// Has to be a comma!
if ( Match ( ShaderSource , ' , ' ) )
{
continue ;
}
//#todo-rco: Need a log here
//UE_LOG(ShaderCompilerCommon, Warning, TEXT("Invalid char '%c'"), *ShaderSource);
return false ;
}
return true ;
}
2014-06-30 18:32:57 -04:00
}