Unable to Register Vertex Shader (C++)

Overview

I am currently trying to create a vertex shader in Unreal Engine. The project does build, however the Editor crashes while attempting to retrieve my shader file. I acquire the error message in the log Couldn't find source file of virtual shader path '/Engine/Shaders/Private/DemoShader.usf'. Despite constant research, I have yet to fix this issue.

Shader Module

In order to include shaders in my project, I have created a game module named ShadersModule, which is implemented in my ShadersModule CPP file. All code shown, with exception to the DemoShader USF file, is contained within ShadersModule. This module includes RenderCore as a public dependency. Additionally, the primary game module includes ShadersModule as a public dependency. Due to when shaders need to be loaded, ShadersModule’s loading phase is set to PostConfigInit in my uproject file.

Shader Registration (Face Value Problem)

So far, I think it is likely that my implementation of the IMPLEMENT_SHADER_TYPE macro is failing to register my vertex shader. This is due to the crash log stating Couldn't find source file of virtual shader path '/Engine/Shaders/Private/DemoShader.usf'. Various references I have found use different virtual paths to my own, however none of them appear to have worked for me so far. I have been led to believe that the intended virtual path has changed across Unreal Engine versions, which might be my issue. Most references I have found use various Unreal Engine 4 versions. I am using Unreal Engine v5.1.1 with a C++ project. I attempt to register the shader in my DemoShaderVS CPP file with the following line:

IMPLEMENT_SHADER_TYPE(, FDemoShaderVS, TEXT("/Engine/Shaders/Private/DemoShader.usf"), TEXT("MainVS"), SF_Vertex);

Shader Directory Mapping

Project Shader Path

I have created a directory to locate my shader file within my project at /Shaders. Within this, I have created two subdirectories, Private & Public. I have been made aware these distinctions are necessary, however I feel unsure as to whether this is strictly the case. Regardless, my shader is in the Private folder.

Virtual Shader Path

Setup

I have mapped my project’s shader directory to Unreal Engine’s virtual shader directory in my ShadersModule header file. This was done by creating a subclass of IModuleInterface, which in my case is named FShaderModule. I have overriden the StartupModule() function & I execute AddShaderSourceDirectoryMapping() in order to map my path.

Errors

My previous mappings used to throw errors when I started the Editor, however I believe this has ceased with the use of the /Engine/Shaders/Private path. When this used to present an error, the crash log suggested I use the aforementioned path. However, I have found this to be particularly confusing. Despite requiring a virtual path, the aforementioned path is a real path within my Engine directory. I am also wondering if the paths are correct, but if they are not being mapped prior to the Engine attempting to retrieve my shader. If this is the case, I don’t know why this would be. Regardless, I currently map the directories as follows:

FString shaderDirectory = FPaths::Combine(FPaths::ProjectDir(), TEXT("Shaders/Private"));
AddShaderSourceDirectoryMapping("/Engine/Shaders/Private", shaderDirectory);

Conclusion

The rest of my code that I felt is worth sharing is below. I have also included more of the crash log. Any help would be extremely appreciated.^^

Crash Log

[2024.04.01-15.52.08:239][ 0]LogShaderCompilers: Guid format shader working directory is -23 characters bigger than the processId version (…/…/…/…/…/…/Work/UEShadersLecture/Unreal-Engine-Shader-Tutorial/Intermediate/Shaders/WorkingDirectory/5872/).
[2024.04.01-15.52.08:239][ 0]LogShaderCompilers: Cleaned the shader compiler working directory ‘C:/Users/sebas/AppData/Local/Temp/UnrealShaderWorkingDir/D99A674B446DB527F664749B032B2CE2/’.
[2024.04.01-15.52.08:241][ 0]LogXGEController: Cannot use XGE Controller as Incredibuild is not installed on this machine.
[2024.04.01-15.52.08:241][ 0]LogShaderCompilers: Display: Using Local Shader Compiler with 9 workers.
[2024.04.01-15.52.08:251][ 0]LogShaders: InitializeShaderTypes() begin
[2024.04.01-15.52.08:253][ 0]LogShaders: Shader directory mapping /Engine → …/…/…/Engine/Shaders
[2024.04.01-15.52.08:253][ 0]LogShaders: Shader directory mapping /ShaderAutogen → D:/Work/UEShadersLecture/Unreal-Engine-Shader-Tutorial/Intermediate/ShaderAutogen
[2024.04.01-15.52.08:253][ 0]LogShaders: Shader directory mapping /Plugin/GLTFExporter → …/…/…/Engine/Plugins/Enterprise/GLTFExporter/Shaders
[2024.04.01-15.52.08:253][ 0]LogShaders: Shader directory mapping /Plugin/FX/Niagara → …/…/…/Engine/Plugins/FX/Niagara/Shaders
[2024.04.01-15.52.08:253][ 0]LogShaders: Shader directory mapping /Plugin/ExrReaderShaders → …/…/…/Engine/Plugins/Media/ImgMedia/Shaders
[2024.04.01-15.52.08:254][ 0]LogShaders: Shader directory mapping /Plugin/WmfMedia → …/…/…/Engine/Plugins/Media/WmfMedia/Shaders
The thread ‘FIOSDeviceHelper.QueryTask_1’ (31408) has exited with code 0 (0x0).
[2024.04.01-15.52.10:641][ 0]LogTurnkeySupport: Completed SDK detection: ExitCode = 0
The thread ‘FMonitoredProcess 0’ (26900) has exited with code 0 (0x0).
Fatal error: [File:D:\build++UE5\Sync\Engine\Source\Runtime\RenderCore\Private\ShaderCore.cpp] [Line: 999]
Couldn’t find source file of virtual shader path ‘/Engine/Shaders/Private/DemoShader.usf’
A breakpoint instruction (__debugbreak() statement or a similar call) was executed in UnrealEditor.exe.
A breakpoint instruction (__debugbreak() statement or a similar call) was executed in UnrealEditor.exe.
[2024.04.01-15.52.17:712][ 0]LogWindows: Error: appError called: Fatal error: [File:D:\build++UE5\Sync\Engine\Source\Runtime\RenderCore\Private\ShaderCore.cpp] [Line: 999]
Couldn’t find source file of virtual shader path ‘/Engine/Shaders/Private/DemoShader.usf’
[2024.04.01-15.52.17:712][ 0]LogWindows: Windows GetLastError: The operation completed successfully. (0)
[2024.04.01-15.52.17:712][ 0]LogWindows: Error: === Critical error: ===
[2024.04.01-15.52.17:712][ 0]LogWindows: Error:
[2024.04.01-15.52.17:712][ 0]LogWindows: Error: Fatal error: [File:D:\build++UE5\Sync\Engine\Source\Runtime\RenderCore\Private\ShaderCore.cpp] [Line: 999]
[2024.04.01-15.52.17:712][ 0]LogWindows: Error: Couldn’t find source file of virtual shader path ‘/Engine/Shaders/Private/DemoShader.usf’

ShadersModule Header

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"

class SHADERSMODULE_API FShaderModule : public IModuleInterface {
public:
	static inline FShaderModule& Get()
	{
		return FModuleManager::LoadModuleChecked<FShaderModule>("ShadersModule");
	}
	static inline bool IsAvailable()
	{
		return FModuleManager::Get().IsModuleLoaded("ShadersModule");
	}

	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};

ShadersModule CPP

// Copyright Epic Games, Inc. All Rights Reserved.

#include "ShadersModule.h"
#include "Modules/ModuleManager.h"

IMPLEMENT_GAME_MODULE(FDefaultGameModuleImpl, ShadersModule);

void FShaderModule::StartupModule()
{
	FString shaderDirectory = FPaths::Combine(FPaths::ProjectDir(), TEXT("Shaders/Private"));
	AddShaderSourceDirectoryMapping("/Engine/Shaders/Private", shaderDirectory);
}

void FShaderModule::ShutdownModule()
{
	ResetAllShaderSourceDirectoryMappings();
}

DemoShaderVS Header

#pragma once

#include "GlobalShader.h"

class FDemoShaderVS : public FGlobalShader
{
    DECLARE_EXPORTED_SHADER_TYPE(FDemoShaderVS, Global, SHADERSMODULE_API);

    FDemoShaderVS() { }
    FDemoShaderVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
        : FGlobalShader(Initializer)
    {
    }

    static bool ShouldCache(EShaderPlatform Platform)
    {
        return true;
    }
};

DemoShaderVS CPP

#include "DemoShaderVS.h"

IMPLEMENT_SHADER_TYPE(, FDemoShaderVS, TEXT("/Engine/Shaders/Private/DemoShader.usf"), TEXT("MainVS"), SF_Vertex);

DemoShader USF

void MainVS(
    in float4 InPosition : ATTRIBUTE0,
    out float4 Output : SV_POSITION
)
{
    Output = InPosition;
}

// Simple solid color pixel shader
float4 MyColor;
float4 MainPS() : SV_Target0
{
    return MyColor;
}