On UE4, a global shader is one that doesn’t operate on a material or a mesh - for example, a full-screen quad, a post-processing feature, a compute shader, etc. There are times when the built-in global shaders do not provide enough functionality and a custom shader pass is required. Doing this is relatively simple, which will be covered in this post.
Untuk mengatasi masalah tersebut, disini akan memberikan 2 cara agar bisa teratasi, cara pertama tanpa menggunakan PC dan cara kedua menggunakan komputer/laptop, kalo ga punya bisa melalui WARNET atau pinjem punya teman. Bootloop biasanya disebabkan kerusakan pada file data ataupun system. On-demand shader compiling can cause freezes during the game play and uses extra memory. To reduce this overhead, all required shader combinations for a game are parsed, compiled, and stored in the shader cache. The shader cache generally refers to the following files.
UE4 reads USF (Unreal Shader Files) off the Engine/Shaders folder, so any new shaders need to supply their source files there. As of 4.17, shaders can also be read from a plugin (Plugin/Shaders).
I’d recommend enabling r.ShaderDevelopmentMode=1 in your ConsoleVariables.ini file for ease of development! Check out https://docs.unrealengine.com/latest/INT/Programming/Rendering/ShaderDevelopment/ for more information!
Let’s start by adding a new USF file in your Engine/Shaders folder; let’s call it MyTest.usf and add a simple pass-through Vertex Shader, and a Pixel Shader that returns a custom color:
// MyTest.usf
// Simple pass-through vertex shader
void MainVS(
in float4 InPosition : ATTRIBUTE0,
outfloat4Output : SV_POSITION
)
{
Output = InPosition;
}
// Simple solid color pixel shader
float4 MyColor;
float4 MainPS() : SV_Target0
{
return MyColor;
}
// Simple pass-through vertex shader
void MainVS(
in float4 InPosition : ATTRIBUTE0,
outfloat4Output : SV_POSITION
)
{
Output = InPosition;
}
// Simple solid color pixel shader
float4 MyColor;
float4 MainPS() : SV_Target0
{
return MyColor;
}
Now, in order to get UE4 to pick up the shader and start compiling it, we need to declare a C++ class; let’s start with the Vertex Shader:
// This can go on a header or cpp file
class FMyTestVS : publicFGlobalShader
{
DECLARE_EXPORTED_SHADER_TYPE(FMyTestVS, Global, /*MYMODULE_API*/);
FMyTestVS() { }
FMyTestVS(constShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
}
staticboolShouldCache(EShaderPlatformPlatform)
{
returntrue;
}
};
class FMyTestVS : publicFGlobalShader
{
DECLARE_EXPORTED_SHADER_TYPE(FMyTestVS, Global, /*MYMODULE_API*/);
FMyTestVS() { }
FMyTestVS(constShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
}
staticboolShouldCache(EShaderPlatformPlatform)
{
returntrue;
}
};
- This is a subclass of FGlobalShader; as such it will end up in the Global Shader Map, (which means we don’t need a Material to find it).
- Usage of the DECLARE_EXPORTED_SHADER_TYPE() macro; this will generate exports required for serialization of the shader type, etc; the third parameter is a type for external linkage for the code module where the shader module will live, if required (eg the C++ code doesn’t live in the Renderer module).
- Two constructors, both the default and the serialization, are required.
- The ShouldCache() function, needed to decide if this shader should be compiled under certain circumstances (eg we might not want to compile a compute shader on a non-compute shader capable RHI).
With the class declared, we can now register the Shader Type to UE4’s list:
IMPLEMENT_SHADER_TYPE(, FMyTestVS, TEXT('MyTest'), TEXT('MainVS'), SF_Vertex);
This macro maps the type (FMyTestVS) to the USF file (MyTest), the shader entry point (MainVS) and the frequency/shader stage (SF_Vertex); it also causes the shader to be added to the compilation list, as long as its ShouldCache() method returns true.
Note: Whatever module you end adding your FGlobalShader has to be loaded before the actual engine starts, or you will get an assert like “'Shader type was loaded after engine init, use ELoadingPhase::PostConfigInit on your module to cause it to load earlier.”; i.e. we current do not allow a dynamic module loaded in the middle of the game or editor to add its own shader type.
Let’s now declare the more interesting Pixel Shader:
class FMyTestPS : publicFGlobalShader
{
DECLARE_EXPORTED_SHADER_TYPE(FMyTestPS, Global, /*MYMODULE_API*/);
FShaderParameter MyColorParameter;
FMyTestPS() { }
FMyTestPS(constShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
MyColorParameter.Bind(Initializer.ParameterMap, TEXT('MyColor'), SPF_Mandatory);
}
staticvoidModifyCompilationEnvironment(EShaderPlatformPlatform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
// Add your own defines for the shader code
OutEnvironment.SetDefine(TEXT('MY_DEFINE'), 1);
}
staticboolShouldCache(EShaderPlatformPlatform)
{
// Could skip compiling for Platform SP_METAL for example
returntrue;
}
// FShader interface.
virtualboolSerialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << MyColorParameter;
return bShaderHasOutdatedParameters;
}
voidSetColor(FRHICommandList& RHICmdList, constFLinearColor& Color)
{
SetShaderValue(RHICmdList, GetPixelShader(), MyColorParameter, Color);
}
};
// Same source file as before, different entry point
IMPLEMENT_SHADER_TYPE(, FMyTestPS, TEXT('MyTest'), TEXT('MainPS'), SF_Pixel);
{
DECLARE_EXPORTED_SHADER_TYPE(FMyTestPS, Global, /*MYMODULE_API*/);
FShaderParameter MyColorParameter;
FMyTestPS() { }
FMyTestPS(constShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
MyColorParameter.Bind(Initializer.ParameterMap, TEXT('MyColor'), SPF_Mandatory);
}
staticvoidModifyCompilationEnvironment(EShaderPlatformPlatform, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
// Add your own defines for the shader code
OutEnvironment.SetDefine(TEXT('MY_DEFINE'), 1);
}
staticboolShouldCache(EShaderPlatformPlatform)
{
// Could skip compiling for Platform SP_METAL for example
returntrue;
}
// FShader interface.
virtualboolSerialize(FArchive& Ar) override
{
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
Ar << MyColorParameter;
return bShaderHasOutdatedParameters;
}
voidSetColor(FRHICommandList& RHICmdList, constFLinearColor& Color)
{
SetShaderValue(RHICmdList, GetPixelShader(), MyColorParameter, Color);
}
};
// Same source file as before, different entry point
IMPLEMENT_SHADER_TYPE(, FMyTestPS, TEXT('MyTest'), TEXT('MainPS'), SF_Pixel);
In this class we are now exposing the shader parameter MyColor from the USF file:
- The first thing to note is the FShaderParameter MyColorParameter member added to the class: this will hold information for the runtime to be able to find the bindings so the value of the parameter can be set at runtime.
- In the serialization constructor we Bind() the parameter to the ParameterMap by name, this has to match the USF name.
- The new ModifyCompilationEnvironment() function, this is used in the cases where we might have the same C++ class define different behaviors and be able to set up #define values in the shader.
- The Serialize() method, required as this is where the compile/cook time information from the shader’s binding (matched during the serialization constructor) gets load and stored at runtime.
- Finally we have a custom SetColor() method, which shows how to set the MyColor parameter at runtime with a specified value.
Let’s now write a simple function to draw a fullscreen quad using these shader types:
void RenderMyTest(FRHICommandList& RHICmdList, ERHIFeatureLevel::TypeFeatureLevel, constFLinearColor& Color)
{
// Get the collection of Global Shaders
autoShaderMap = GetGlobalShaderMap(FeatureLevel);
// Get the actual shader instances off the ShaderMap
TShaderMapRef MyVS( ShaderMap);
TShaderMapRef MyPS( ShaderMap);
// Declare a bound shader state using those shaders and apply it to the command list
staticFGlobalBoundShaderState MyTestBoundShaderState;
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, MyTestBoundShaderState, GetVertexDeclarationFVector4(), *MyVS, *MyPS);
// Call our function to set up parameters
MyPS->SetColor(RHICmdList, Color);
// Setup the GPU in prep for drawing a solid quad
RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI());
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI(), 0);
// Setup the vertices
FVector4Vertices[4];
Vertices[0].Set(-1.0f, 1.0f, 0, 1.0f);
Vertices[1].Set(1.0f, 1.0f, 0, 1.0f);
Vertices[2].Set(-1.0f, -1.0f, 0, 1.0f);
Vertices[3].Set(1.0f, -1.0f, 0, 1.0f);
// Draw the quad
DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, Vertices, sizeof(Vertices[0]));
}
{
// Get the collection of Global Shaders
autoShaderMap = GetGlobalShaderMap(FeatureLevel);
// Get the actual shader instances off the ShaderMap
TShaderMapRef
TShaderMapRef
// Declare a bound shader state using those shaders and apply it to the command list
staticFGlobalBoundShaderState MyTestBoundShaderState;
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, MyTestBoundShaderState, GetVertexDeclarationFVector4(), *MyVS, *MyPS);
// Call our function to set up parameters
MyPS->SetColor(RHICmdList, Color);
// Setup the GPU in prep for drawing a solid quad
RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI());
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI(), 0);
// Setup the vertices
FVector4Vertices[4];
Vertices[0].Set(-1.0f, 1.0f, 0, 1.0f);
Vertices[1].Set(1.0f, 1.0f, 0, 1.0f);
Vertices[2].Set(-1.0f, -1.0f, 0, 1.0f);
Vertices[3].Set(1.0f, -1.0f, 0, 1.0f);
// Draw the quad
DrawPrimitiveUP(RHICmdList, PT_TriangleStrip, 2, Vertices, sizeof(Vertices[0]));
}
If you want to actually test this in your codebase, you can try something like this; I declared a console variable so it can be toggled at runtime:
staticTAutoConsoleVariable<int32> CVarMyTest(
TEXT('r.MyTest'),
0,
TEXT('Test My Global Shader, set it to 0 to disable, or to 1, 2 or 3 for fun!'),
ECVF_RenderThreadSafe
);
voidFDeferredShadingSceneRenderer::RenderFinish(FRHICommandListImmediate& RHICmdList)
{
[...]
// ***
// Inserted code, just before finishing rendering, so we can overwrite the screen’s contents!
int32 MyTestValue = CVarMyTest.GetValueOnAnyThread();
if (MyTestValue != 0)
{
FLinearColorColor(MyTestValue 1, MyTestValue 2, MyTestValue 3, 1);
RenderMyTest(RHICmdList, FeatureLevel, Color);
}
// End Inserted code
// ***
FSceneRenderer::RenderFinish(RHICmdList);
[...]
}
TEXT('r.MyTest'),
0,
TEXT('Test My Global Shader, set it to 0 to disable, or to 1, 2 or 3 for fun!'),
ECVF_RenderThreadSafe
);
voidFDeferredShadingSceneRenderer::RenderFinish(FRHICommandListImmediate& RHICmdList)
{
[...]
// ***
// Inserted code, just before finishing rendering, so we can overwrite the screen’s contents!
int32 MyTestValue = CVarMyTest.GetValueOnAnyThread();
if (MyTestValue != 0)
{
FLinearColorColor(MyTestValue 1, MyTestValue 2, MyTestValue 3, 1);
RenderMyTest(RHICmdList, FeatureLevel, Color);
}
// End Inserted code
// ***
FSceneRenderer::RenderFinish(RHICmdList);
[...]
}
At this point you should be able to run your project, then pull up a console using tilde (~) and typing r.MyTest 1, then r.MyTest 2 and/or r.MyTest 3 to change colors. Use r.MyTest 0 to disable the pass.
Take a look at the blog post https://www.unrealengine.com/blog/debugging-the-shader-compiling-process if you want to be able to debug the compilation of your USF file and/or see the processed file.
You can modify the USF file while an uncooked game/editor is running, and then press Ctrl+Shift+. (or type recompileshaders changed in the console) to pick up and rebuild your shaders, for quick iteration!
Enjoy!
Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upHave a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
commented Feb 15, 2019 • edited
edited
After I started the simulator, I got the following error: LogShaders: Error: The global shader cache file data/carla_093-compiled/Engine/GlobalShaderCache-GLSL_150.bin is missing xxxxxxx Your application is built to load COOKED content No COOKED content was found his usually means you did not cook content for this build. xxxxxxx Exiting abnormally (error code: 1) It seems that the content files is not in the correct directory, but after I put the content files in Content/carla, it can not work yet. My system version is Ubuntu 16.04 in a docker container. The 0.9.1 compiled version can be successfully started in the container. |
commented Feb 15, 2019
Following the installation instructions at Running in a Docker and doing works for me |
commented Mar 12, 2019 • edited
edited
@nsubiron I extracted the CARLA_0.9.4.tar.gz file and ran the sh file directly on a Google Cloud Ubuntu 18.04 machine(no Docker) with Tesla K80 and OpenGL 3, like this: ./CarlaUE4.sh -opengl3 But it gives below error: On checking the files, there indeed is no such file as GlobalShaderCache-GLSL_150.bin anywhere. Here's the full log: log.txt Any help is appreciated! |
commented Mar 12, 2019 • edited
edited
I find that the cache file /Engine/GlobalShaderCache-GLSL_150.bin is missing, but there is a cache file named '/Engine/GlobalShaderCache-GLSL_430.bin'. Is this bug related to the OpenGL version? My OpenGL version is 3.0, does the 0.9.4 version require OpenGL 4.3 ? @nsubiron |
commented Mar 12, 2019
![Cara Mengatasi The Global Shader Cache File Cara Mengatasi The Global Shader Cache File](/uploads/1/2/3/9/123951122/617885394.jpg)
I tried run the carla 0.9.4 compiled version on my local pc with OpenGL version 4.3, it works. So I guess this bug is because the 0.9.4 compiled version is compiled under OpenGL 4.3 ? Maybe you should try compiled the code under OpenGL 3.0? |
commented Mar 12, 2019 • edited
edited
Hey I read the build instructions but don't know where to pass the -opengl3 flag, it is not mentioned in the instructions: How to build on Linux. I don't want to launch the project in Unreal editor, just want the binaries generated by 'make package' command but where do I say its for -opengl3? Edit: Getting error after executing make command for UE4. Will make a new request as an issue to see if someone has compiled with opengl3. |
referenced this issue Mar 12, 2019
ClosedHelp requested: Carla binaries compiled to run with OpenGL 3. #1376
commented Apr 19, 2019
May be it is not related to OpenGL version only. I've build Carla from master-release on Windows 10. The error (with the cache file GlobalShaderCache-PCD3D_SM5.bin) appears with 'Shipping' and 'Development' configurations. Though it runs fine with 'Development editor' or 'Debug-editor configuration. |
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment