void FShaderResource::Serialize(FArchive& Ar) { Ar << SpecificType; Ar << Target; Ar << Code; Ar << OutputHash; Ar << NumInstructions; Ar << NumTextureSamplers; if (Ar.IsLoading()) { INC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), (int64)Code.Num()); INC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); FShaderCache::LogShader((EShaderPlatform)Target.Platform, (EShaderFrequency)Target.Frequency, OutputHash, Code); // The shader resource has been serialized in, so this shader resource is now initialized. check(Canary != FShader::ShaderMagic_CleaningUp); Canary = FShader::ShaderMagic_Initialized; } #if WITH_EDITORONLY_DATA else if(Ar.IsCooking()) { FShaderCache::CookShader((EShaderPlatform)Target.Platform, (EShaderFrequency)Target.Frequency, OutputHash, Code); } #endif }
FShaderResource::FShaderResource(const FShaderCompilerOutput& Output, FShaderType* InSpecificType) : SpecificType(InSpecificType) , NumInstructions(Output.NumInstructions) , NumTextureSamplers(Output.NumTextureSamplers) , NumRefs(0) , Canary(FShader::ShaderMagic_Initialized) { Target = Output.Target; // todo: can we avoid the memcpy? Code = Output.ShaderCode.GetReadAccess(); check(Code.Num() > 0); OutputHash = Output.OutputHash; checkSlow(OutputHash != FSHAHash()); { FScopeLock ShaderResourceIdMapLock(&ShaderResourceIdMapCritical); ShaderResourceIdMap.Add(GetId(), this); } INC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); INC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); INC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }
FShaderResource::~FShaderResource() { check(Canary == FShader::ShaderMagic_Uninitialized || Canary == FShader::ShaderMagic_CleaningUp || Canary == FShader::ShaderMagic_Initialized); check(NumRefs == 0); Canary = 0; DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }
void FShaderResource::InitRHI() { checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data.")); // we can't have this called on the wrong platform's shaders if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform)) { if (FPlatformProperties::RequiresCookedData()) { UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), *LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString()); } return; } INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1); SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime); if(Target.Frequency == SF_Vertex) { VertexShader = RHICreateVertexShader(Code); } else if(Target.Frequency == SF_Pixel) { PixelShader = RHICreatePixelShader(Code); } else if(Target.Frequency == SF_Hull) { HullShader = RHICreateHullShader(Code); } else if(Target.Frequency == SF_Domain) { DomainShader = RHICreateDomainShader(Code); } else if(Target.Frequency == SF_Geometry) { GeometryShader = RHICreateGeometryShader(Code); } else if(Target.Frequency == SF_Compute) { ComputeShader = RHICreateComputeShader(Code); } if (!FPlatformProperties::HasEditorOnlyData()) { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize()); Code.Empty(); } }
void FShaderResource::Serialize(FArchive& Ar) { Ar << Target; Ar << Code; Ar << OutputHash; Ar << NumInstructions; Ar << NumTextureSamplers; if (Ar.IsLoading()) { INC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), (int64)Code.Num()); INC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); } }
FShaderResource::FShaderResource(const FShaderCompilerOutput& Output) : NumInstructions(Output.NumInstructions) , NumTextureSamplers(Output.NumTextureSamplers) , NumRefs(0) { Target = Output.Target; Code = Output.Code; check(Code.Num() > 0); OutputHash = Output.OutputHash; checkSlow(OutputHash != FSHAHash()); ShaderResourceIdMap.Add(GetId(), this); INC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); INC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); INC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }
void FShaderResource::InitRHI() { checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data.")); // we can't have this called on the wrong platform's shaders if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform)) { if (FPlatformProperties::RequiresCookedData()) { UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), *LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString()); } return; } INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1); SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime); FShaderCache* ShaderCache = FShaderCache::GetShaderCache(); if(Target.Frequency == SF_Vertex) { VertexShader = ShaderCache ? ShaderCache->GetVertexShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateVertexShader(Code); } else if(Target.Frequency == SF_Pixel) { PixelShader = ShaderCache ? ShaderCache->GetPixelShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreatePixelShader(Code); } else if(Target.Frequency == SF_Hull) { HullShader = ShaderCache ? ShaderCache->GetHullShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateHullShader(Code); } else if(Target.Frequency == SF_Domain) { DomainShader = ShaderCache ? ShaderCache->GetDomainShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateDomainShader(Code); } else if(Target.Frequency == SF_Geometry) { if (SpecificType) { FStreamOutElementList ElementList; TArray<uint32> StreamStrides; int32 RasterizedStream = -1; SpecificType->GetStreamOutElements(ElementList, StreamStrides, RasterizedStream); checkf(ElementList.Num(), *FString::Printf(TEXT("Shader type %s was given GetStreamOutElements implementation that had no elements!"), SpecificType->GetName())); //@todo - not using the cache GeometryShader = RHICreateGeometryShaderWithStreamOutput(Code, ElementList, StreamStrides.Num(), StreamStrides.GetData(), RasterizedStream); } else { GeometryShader = ShaderCache ? ShaderCache->GetGeometryShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateGeometryShader(Code); } } else if(Target.Frequency == SF_Compute) { ComputeShader = ShaderCache ? ShaderCache->GetComputeShader((EShaderPlatform)Target.Platform, Code) : RHICreateComputeShader(Code); } if (Target.Frequency != SF_Geometry) { checkf(!SpecificType, *FString::Printf(TEXT("Only geometry shaders can use GetStreamOutElements, shader type %s"), SpecificType->GetName())); } if (!FPlatformProperties::HasEditorOnlyData()) { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize()); Code.Empty(); } }
FShaderResource::~FShaderResource() { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }