void FMeshParticleVertexFactory::InitRHI() { FVertexDeclarationElementList Elements; const bool bInstanced = GetFeatureLevel() >= ERHIFeatureLevel::SM4; if (Data.bInitialized) { if(bInstanced) { // Stream 0 - Instance data { checkf(DynamicVertexStride != -1, TEXT("FMeshParticleVertexFactory does not have a valid DynamicVertexStride - likely an empty one was made, but SetStrides was not called")); FVertexStream VertexStream; VertexStream.VertexBuffer = NULL; VertexStream.Stride = 0; VertexStream.Offset = 0; Streams.Add(VertexStream); // @todo metal: this will need a valid stride when we get to instanced meshes! Elements.Add(FVertexElement(0, Data.TransformComponent[0].Offset, Data.TransformComponent[0].Type, 8, DynamicVertexStride, Data.TransformComponent[0].bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.TransformComponent[1].Offset, Data.TransformComponent[1].Type, 9, DynamicVertexStride, Data.TransformComponent[1].bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.TransformComponent[2].Offset, Data.TransformComponent[2].Type, 10, DynamicVertexStride, Data.TransformComponent[2].bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.SubUVs.Offset, Data.SubUVs.Type, 11, DynamicVertexStride, Data.SubUVs.bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.SubUVLerpAndRelTime.Offset, Data.SubUVLerpAndRelTime.Type, 12, DynamicVertexStride, Data.SubUVLerpAndRelTime.bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.ParticleColorComponent.Offset, Data.ParticleColorComponent.Type, 14, DynamicVertexStride, Data.ParticleColorComponent.bUseInstanceIndex)); Elements.Add(FVertexElement(0, Data.VelocityComponent.Offset, Data.VelocityComponent.Type, 15, DynamicVertexStride, Data.VelocityComponent.bUseInstanceIndex)); } // Stream 1 - Dynamic parameter { checkf(DynamicParameterVertexStride != -1, TEXT("FMeshParticleVertexFactory does not have a valid DynamicParameterVertexStride - likely an empty one was made, but SetStrides was not called")); FVertexStream VertexStream; VertexStream.VertexBuffer = NULL; VertexStream.Stride = 0; VertexStream.Offset = 0; Streams.Add(VertexStream); Elements.Add(FVertexElement(1, 0, VET_Float4, 13, DynamicParameterVertexStride, true)); } } if(Data.PositionComponent.VertexBuffer != NULL) { Elements.Add(AccessStreamComponent(Data.PositionComponent,0)); } // only tangent,normal are used by the stream. the binormal is derived in the shader uint8 TangentBasisAttributes[2] = { 1, 2 }; for(int32 AxisIndex = 0;AxisIndex < 2;AxisIndex++) { if(Data.TangentBasisComponents[AxisIndex].VertexBuffer != NULL) { Elements.Add(AccessStreamComponent(Data.TangentBasisComponents[AxisIndex],TangentBasisAttributes[AxisIndex])); } } // Vertex color if(Data.VertexColorComponent.VertexBuffer != NULL) { Elements.Add(AccessStreamComponent(Data.VertexColorComponent,3)); } else { //If the mesh has no color component, set the null color buffer on a new stream with a stride of 0. //This wastes 4 bytes of bandwidth per vertex, but prevents having to compile out twice the number of vertex factories. FVertexStreamComponent NullColorComponent(&GNullColorVertexBuffer, 0, 0, VET_Color); Elements.Add(AccessStreamComponent(NullColorComponent,3)); } if(Data.TextureCoordinates.Num()) { const int32 BaseTexCoordAttribute = 4; for(int32 CoordinateIndex = 0;CoordinateIndex < Data.TextureCoordinates.Num();CoordinateIndex++) { Elements.Add(AccessStreamComponent( Data.TextureCoordinates[CoordinateIndex], BaseTexCoordAttribute + CoordinateIndex )); } for(int32 CoordinateIndex = Data.TextureCoordinates.Num();CoordinateIndex < MAX_TEXCOORDS;CoordinateIndex++) { Elements.Add(AccessStreamComponent( Data.TextureCoordinates[Data.TextureCoordinates.Num() - 1], BaseTexCoordAttribute + CoordinateIndex )); } } if(Streams.Num() > 0) { InitDeclaration(Elements,Data); check(IsValidRef(GetDeclaration())); } } }
bool CompileShaderPipeline(const IShaderFormat* Compiler, FName Format, FShaderPipelineCompileJob* PipelineJob, const FString& Dir) { check(PipelineJob && PipelineJob->StageJobs.Num() > 0); FShaderCompileJob* CurrentJob = PipelineJob->StageJobs[0]->GetSingleShaderJob(); CurrentJob->Input.bCompilingForShaderPipeline = true; // First job doesn't have to trim outputs CurrentJob->Input.bIncludeUsedOutputs = false; if (IsValidRef(CurrentJob->Input.SharedEnvironment)) { // Merge the shared environment into the per-shader environment before calling into the compile function // Normally this happens in the worker CurrentJob->Input.Environment.Merge(*CurrentJob->Input.SharedEnvironment); } // Compile the shader directly through the platform dll (directly from the shader dir as the working directory) Compiler->CompileShader(Format, CurrentJob->Input, CurrentJob->Output, Dir); CurrentJob->bSucceeded = CurrentJob->Output.bSucceeded; if (!CurrentJob->Output.bSucceeded) { // Can't carry on compiling the pipeline return false; } // Generate a hash of the output and cache it // The shader processing this output will use it to search for existing FShaderResources CurrentJob->Output.GenerateOutputHash(); // This tells the shader compiler we do want to remove unused outputs bool bEnableRemovingUnused = true; // This tells us the hlsl parser failed at removing unused outputs bool bJobFailedRemovingUnused = false; //#todo-rco: Currently only removes for pure VS & PS stages for (int32 Index = 0; Index < PipelineJob->StageJobs.Num(); ++Index) { auto Stage = PipelineJob->StageJobs[Index]->GetSingleShaderJob()->Input.Target.Frequency; if (Stage != SF_Vertex && Stage != SF_Pixel) { bEnableRemovingUnused = false; break; } } for (int32 Index = 1; Index < PipelineJob->StageJobs.Num(); ++Index) { auto* PreviousJob = CurrentJob; CurrentJob = PipelineJob->StageJobs[Index]->GetSingleShaderJob(); bEnableRemovingUnused = bEnableRemovingUnused && PreviousJob->Output.bSupportsQueryingUsedAttributes; if (bEnableRemovingUnused) { CurrentJob->Input.bIncludeUsedOutputs = true; CurrentJob->Input.bCompilingForShaderPipeline = true; CurrentJob->Input.UsedOutputs = PreviousJob->Output.UsedAttributes; } if (IsValidRef(CurrentJob->Input.SharedEnvironment)) { // Merge the shared environment into the per-shader environment before calling into the compile function // Normally this happens in the worker CurrentJob->Input.Environment.Merge(*CurrentJob->Input.SharedEnvironment); } // Compile the shader directly through the platform dll (directly from the shader dir as the working directory) Compiler->CompileShader(Format, CurrentJob->Input, CurrentJob->Output, Dir); CurrentJob->bSucceeded = CurrentJob->Output.bSucceeded; if (!CurrentJob->Output.bSucceeded) { // Can't carry on compiling the pipeline return false; } bJobFailedRemovingUnused = CurrentJob->Output.bFailedRemovingUnused || bJobFailedRemovingUnused; // Generate a hash of the output and cache it // The shader processing this output will use it to search for existing FShaderResources CurrentJob->Output.GenerateOutputHash(); } PipelineJob->bSucceeded = true; PipelineJob->bFailedRemovingUnused = bJobFailedRemovingUnused; return true; }
void FVisualizeTexture::GenerateContent(const FSceneRenderTargetItem& RenderTargetItem, const FPooledRenderTargetDesc& Desc) { // otherwise StartFrame() wasn't called check(ViewRect != FIntRect(0, 0, 0, 0)) FTexture2DRHIRef VisTexture = (FTexture2DRHIRef&)RenderTargetItem.ShaderResourceTexture; if(!IsValidRef(VisTexture) || !Desc.IsValid()) { // todo: improve return; } FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent); FIntPoint Size = VisualizeTextureRect.Size(); // clamp to reasonable value to prevent crash Size.X = FMath::Max(Size.X, 1); Size.Y = FMath::Max(Size.Y, 1); FPooledRenderTargetDesc OutputDesc(FPooledRenderTargetDesc::Create2DDesc(Size, PF_B8G8R8A8, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource, false)); GRenderTargetPool.FindFreeElement(OutputDesc, VisualizeTextureContent, TEXT("VisualizeTexture")); if(!VisualizeTextureContent) { return; } const FSceneRenderTargetItem& DestRenderTarget = VisualizeTextureContent->GetRenderTargetItem(); RHISetRenderTarget(DestRenderTarget.TargetableTexture, FTextureRHIRef()); RHIClear(true, FLinearColor(1,1,0,1), false, 0.0f, false, 0, FIntRect()); RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); FIntPoint RTExtent = GSceneRenderTargets.GetBufferSizeXY(); FVector2D Tex00 = FVector2D(0, 0); FVector2D Tex11 = FVector2D(1, 1); uint32 LocalVisualizeTextureInputMapping = UVInputMapping; if(!Desc.Is2DTexture()) { LocalVisualizeTextureInputMapping = 1; } // set UV switch(LocalVisualizeTextureInputMapping) { // UV in left top case 0: Tex11 = FVector2D((float)ViewRect.Width() / RTExtent.X, (float)ViewRect.Height() / RTExtent.Y); break; // whole texture default: break; } bool bIsDefault = StencilSRVSrc == GBlackTexture->TextureRHI; bool bDepthStencil = Desc.Is2DTexture() && Desc.Format == PF_DepthStencil; //clear if this is a new different Stencil buffer, or it's not a stencil buffer and we haven't switched to the default yet. bool bNeedsClear = bDepthStencil && (StencilSRVSrc != RenderTargetItem.TargetableTexture); bNeedsClear |= !bDepthStencil && !bIsDefault; if (bNeedsClear) { StencilSRVSrc = nullptr; StencilSRV.SafeRelease(); } //always set something into the StencilSRV slot for platforms that require a full resource binding, even if //dynamic branching will cause them not to be used. if(bDepthStencil && !StencilSRVSrc) { StencilSRVSrc = RenderTargetItem.TargetableTexture; StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) RenderTargetItem.TargetableTexture, 0, 1, PF_X24_G8); } else if(!StencilSRVSrc) { StencilSRVSrc = GBlackTexture->TextureRHI; StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) GBlackTexture->TextureRHI, 0, 1, PF_B8G8R8A8); } FVisualizeTextureData VisualizeTextureData(RenderTargetItem, Desc); bool bDepthTexture = (Desc.TargetableFlags & TexCreate_DepthStencilTargetable) != 0; VisualizeTextureData.RGBMul = RGBMul; VisualizeTextureData.AMul = AMul; VisualizeTextureData.Tex00 = Tex00; VisualizeTextureData.Tex11 = Tex11; VisualizeTextureData.bSaturateInsteadOfFrac = (Flags & 1) != 0; VisualizeTextureData.InputValueMapping = bDepthTexture ? 1 : 0; VisualizeTextureData.ArrayIndex = ArrayIndex; VisualizeTextureData.CustomMip = CustomMip; VisualizeTextureData.StencilSRV = StencilSRV; { SCOPED_DRAW_EVENT(VisualizeTexture, DEC_SCENE_ITEMS); // continue rendering to HDR if necessary RenderVisualizeTexture(VisualizeTextureData); } RHICopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); VisualizeTextureDesc = Desc; // save to disk if(bSaveBitmap) { bSaveBitmap = false; uint32 MipAdjustedExtentX = FMath::Clamp(Desc.Extent.X >> CustomMip, 0, Desc.Extent.X); uint32 MipAdjustedExtentY = FMath::Clamp(Desc.Extent.Y >> CustomMip, 0, Desc.Extent.Y); FIntPoint Extent(MipAdjustedExtentX, MipAdjustedExtentY); FReadSurfaceDataFlags ReadDataFlags; ReadDataFlags.SetLinearToGamma(false); ReadDataFlags.SetOutputStencil(bOutputStencil); ReadDataFlags.SetMip(CustomMip); FTextureRHIRef Texture = RenderTargetItem.TargetableTexture ? RenderTargetItem.TargetableTexture : RenderTargetItem.ShaderResourceTexture; check(Texture); TArray<FColor> Bitmap; RHIReadSurfaceData(Texture, FIntRect(0, 0, Extent.X, Extent.Y), Bitmap, ReadDataFlags); // if the format and texture type is supported if(Bitmap.Num()) { // Create screenshot folder if not already present. IFileManager::Get().MakeDirectory(*FPaths::ScreenShotDir(), true); const FString ScreenFileName(FPaths::ScreenShotDir() / TEXT("VisualizeTexture")); uint32 ExtendXWithMSAA = Bitmap.Num() / Extent.Y; // Save the contents of the array to a bitmap file. (24bit only so alpha channel is dropped) FFileHelper::CreateBitmap(*ScreenFileName, ExtendXWithMSAA, Extent.Y, Bitmap.GetTypedData()); UE_LOG(LogConsoleResponse, Display, TEXT("Content was saved to \"%s\""), *FPaths::ScreenShotDir()); } else { UE_LOG(LogConsoleResponse, Error, TEXT("Failed to save BMP for VisualizeTexture, format or texture type is not supported")); } } }
void FVisualizeTexture::PresentContent(const FSceneView& View) { if(Mode != 0) { // old mode is used, lets copy the specified texture to do it similar to the new system FPooledRenderTarget* Element = GRenderTargetPool.GetElementById(Mode - 1); if(Element) { GenerateContent(Element->GetRenderTargetItem(), Element->GetDesc()); } } const FTexture2DRHIRef& RenderTargetTexture = View.Family->RenderTarget->GetRenderTargetTexture(); if(!VisualizeTextureContent || !IsValidRef(RenderTargetTexture) || GRHIFeatureLevel < ERHIFeatureLevel::SM3) { // visualize feature is deactivated return; } FPooledRenderTargetDesc Desc = VisualizeTextureDesc; RHISetRenderTarget(View.Family->RenderTarget->GetRenderTargetTexture(),FTextureRHIRef()); RHISetViewport(0, 0, 0.0f, GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y, 1.0f ); RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FVisualizeTexturePresentPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetParameters(View); PixelShader->SetParameters(View, *VisualizeTextureContent); FIntRect DestRect = View.ViewRect; FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent); // Draw a quad mapping scene color to the view's render target DrawRectangle( VisualizeTextureRect.Min.X, VisualizeTextureRect.Min.Y, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), 0, 0, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), GSceneRenderTargets.GetBufferSizeXY(), VisualizeTextureRect.Size(), EDRF_Default); // this is a helper class for FCanvas to be able to get screen size class FRenderTargetTemp : public FRenderTarget { public: const FSceneView& View; FRenderTargetTemp(const FSceneView& InView) : View(InView) { } virtual FIntPoint GetSizeXY() const { return View.UnscaledViewRect.Size(); }; virtual const FTexture2DRHIRef& GetRenderTargetTexture() const { return View.Family->RenderTarget->GetRenderTargetTexture(); } } TempRenderTarget(View); FCanvas Canvas(&TempRenderTarget, NULL, View.Family->CurrentRealTime, View.Family->CurrentWorldTime, View.Family->DeltaWorldTime); float X = 100 + View.ViewRect.Min.X; float Y = 160 + View.ViewRect.Min.Y; float YStep = 14; { uint32 ReuseCount = ObservedDebugNameReusedCurrent; FString ExtendedName; if(ReuseCount) { uint32 ReuseGoal = FMath::Min(ReuseCount - 1, ObservedDebugNameReusedGoal); // was reused this frame ExtendedName = FString::Printf(TEXT("%s@%d @0..%d"), Desc.DebugName, ReuseGoal, ReuseCount - 1); } else { // was not reused this frame but can be referenced ExtendedName = FString::Printf(TEXT("%s"), Desc.DebugName); } FString Line = FString::Printf(TEXT("VisualizeTexture: %d \"%s\" RGB*%g+A*%g UV%d"), Mode, *ExtendedName, RGBMul, AMul, UVInputMapping); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" TextureInfoString(): %s"), *(Desc.GenerateInfoString())); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" BufferSize:(%d,%d)"), GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } const FSceneViewFamily& ViewFamily = *View.Family; for(int32 ViewId = 0; ViewId < ViewFamily.Views.Num(); ++ViewId) { const FSceneView& ViewIt = *ViewFamily.Views[ViewId]; FString Line = FString::Printf(TEXT(" View #%d: (%d,%d)-(%d,%d)"), ViewId + 1, ViewIt.ViewRect.Min.X, ViewIt.ViewRect.Min.Y, ViewIt.ViewRect.Max.X, ViewIt.ViewRect.Max.Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } X += 40; Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Red: <0"), GetStatsFont(), FLinearColor(1,0,0)); Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Blue: NAN or Inf"), GetStatsFont(), FLinearColor(0,0,1)); Canvas.Flush(); }
void FMaterialShader::SetParameters( FRHICommandList& RHICmdList, const ShaderRHIParamRef ShaderRHI, const FMaterialRenderProxy* MaterialRenderProxy, const FMaterial& Material, const FSceneView& View, bool bDeferredPass, ESceneRenderTargetsMode::Type TextureMode) { ERHIFeatureLevel::Type FeatureLevel = View.GetFeatureLevel(); FUniformExpressionCache TempUniformExpressionCache; const FUniformExpressionCache* UniformExpressionCache = &MaterialRenderProxy->UniformExpressionCache[FeatureLevel]; SetParameters(RHICmdList, ShaderRHI, View); // If the material has cached uniform expressions for selection or hover // and that is being overridden by show flags in the editor, recache // expressions for this draw call. const bool bOverrideSelection = GIsEditor && !View.Family->EngineShowFlags.Selection && (MaterialRenderProxy->IsSelected() || MaterialRenderProxy->IsHovered()); if (!bAllowCachedUniformExpressions || !UniformExpressionCache->bUpToDate || bOverrideSelection) { FMaterialRenderContext MaterialRenderContext(MaterialRenderProxy, Material, &View); MaterialRenderProxy->EvaluateUniformExpressions(TempUniformExpressionCache, MaterialRenderContext, &RHICmdList); UniformExpressionCache = &TempUniformExpressionCache; } check(Material.GetRenderingThreadShaderMap()); check(Material.GetRenderingThreadShaderMap()->IsValidForRendering()); check(Material.GetFeatureLevel() == FeatureLevel); // Validate that the shader is being used for a material that matches the uniform expression set the shader was compiled for. const FUniformExpressionSet& MaterialUniformExpressionSet = Material.GetRenderingThreadShaderMap()->GetUniformExpressionSet(); #if NO_LOGGING == 0 const bool bUniformExpressionSetMismatch = !DebugUniformExpressionSet.Matches(MaterialUniformExpressionSet) || UniformExpressionCache->CachedUniformExpressionShaderMap != Material.GetRenderingThreadShaderMap(); if (bUniformExpressionSetMismatch) { UE_LOG( LogShaders, Fatal, TEXT("%s shader uniform expression set mismatch for material %s/%s.\n") TEXT("Shader compilation info: %s\n") TEXT("Material render proxy compilation info: %s\n") TEXT("Shader uniform expression set: %u vectors, %u scalars, %u 2D textures, %u cube textures, %u scalars/frame, %u vectors/frame, shader map %p\n") TEXT("Material uniform expression set: %u vectors, %u scalars, %u 2D textures, %u cube textures, %u scalars/frame, %u vectors/frame, shader map %p\n"), GetType()->GetName(), *MaterialRenderProxy->GetFriendlyName(), *Material.GetFriendlyName(), *DebugDescription, *Material.GetRenderingThreadShaderMap()->GetDebugDescription(), DebugUniformExpressionSet.NumVectorExpressions, DebugUniformExpressionSet.NumScalarExpressions, DebugUniformExpressionSet.Num2DTextureExpressions, DebugUniformExpressionSet.NumCubeTextureExpressions, DebugUniformExpressionSet.NumPerFrameScalarExpressions, DebugUniformExpressionSet.NumPerFrameVectorExpressions, UniformExpressionCache->CachedUniformExpressionShaderMap, MaterialUniformExpressionSet.UniformVectorExpressions.Num(), MaterialUniformExpressionSet.UniformScalarExpressions.Num(), MaterialUniformExpressionSet.Uniform2DTextureExpressions.Num(), MaterialUniformExpressionSet.UniformCubeTextureExpressions.Num(), MaterialUniformExpressionSet.PerFrameUniformScalarExpressions.Num(), MaterialUniformExpressionSet.PerFrameUniformVectorExpressions.Num(), Material.GetRenderingThreadShaderMap() ); } #endif if (UniformExpressionCache->LocalUniformBuffer.IsValid()) { // Set the material uniform buffer. SetLocalUniformBufferParameter(RHICmdList, ShaderRHI, MaterialUniformBuffer, UniformExpressionCache->LocalUniformBuffer); } else { // Set the material uniform buffer. SetUniformBufferParameter(RHICmdList, ShaderRHI, MaterialUniformBuffer, UniformExpressionCache->UniformBuffer); } { const TArray<FGuid>& ParameterCollections = UniformExpressionCache->ParameterCollections; const int32 ParameterCollectionsNum = ParameterCollections.Num(); check(ParameterCollectionUniformBuffers.Num() >= ParameterCollectionsNum); // Find each referenced parameter collection's uniform buffer in the scene and set the parameter for (int32 CollectionIndex = 0; CollectionIndex < ParameterCollectionsNum; CollectionIndex++) { FUniformBufferRHIParamRef UniformBuffer = GetParameterCollectionBuffer(ParameterCollections[CollectionIndex], View.Family->Scene); SetUniformBufferParameter(RHICmdList, ShaderRHI,ParameterCollectionUniformBuffers[CollectionIndex],UniformBuffer); } } { // Per frame material expressions const int32 NumScalarExpressions = PerFrameScalarExpressions.Num(); const int32 NumVectorExpressions = PerFrameVectorExpressions.Num(); if (NumScalarExpressions > 0 || NumVectorExpressions > 0) { FMaterialRenderContext MaterialRenderContext(MaterialRenderProxy, Material, &View); MaterialRenderContext.Time = View.Family->CurrentWorldTime; MaterialRenderContext.RealTime = View.Family->CurrentRealTime; for (int32 Index = 0; Index < NumScalarExpressions; ++Index) { auto& Parameter = PerFrameScalarExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFrameUniformScalarExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue.R); } } for (int32 Index = 0; Index < NumVectorExpressions; ++Index) { auto& Parameter = PerFrameVectorExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFrameUniformVectorExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue); } } // Now previous frame's expressions const int32 NumPrevScalarExpressions = PerFramePrevScalarExpressions.Num(); const int32 NumPrevVectorExpressions = PerFramePrevVectorExpressions.Num(); if (NumPrevScalarExpressions > 0 || NumPrevVectorExpressions > 0) { MaterialRenderContext.Time = View.Family->CurrentWorldTime - View.Family->DeltaWorldTime; MaterialRenderContext.RealTime = View.Family->CurrentRealTime - View.Family->DeltaWorldTime; for (int32 Index = 0; Index < NumPrevScalarExpressions; ++Index) { auto& Parameter = PerFramePrevScalarExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFramePrevUniformScalarExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue.R); } } for (int32 Index = 0; Index < NumPrevVectorExpressions; ++Index) { auto& Parameter = PerFramePrevVectorExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFramePrevUniformVectorExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue); } } } } } DeferredParameters.Set(RHICmdList, ShaderRHI, View, TextureMode); AtmosphericFogTextureParameters.Set(RHICmdList, ShaderRHI, View); if (FeatureLevel >= ERHIFeatureLevel::SM4) { // for copied scene color if(LightAttenuation.IsBound()) { SetTextureParameter( RHICmdList, ShaderRHI, LightAttenuation, LightAttenuationSampler, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), GSceneRenderTargets.GetLightAttenuationTexture()); } } //Use of the eye adaptation texture here is experimental and potentially dangerous as it can introduce a feedback loop. May be removed. if(EyeAdaptation.IsBound()) { FTextureRHIRef& EyeAdaptationTex = GetEyeAdaptation(View); SetTextureParameter(RHICmdList, ShaderRHI, EyeAdaptation, EyeAdaptationTex); } if (PerlinNoiseGradientTexture.IsBound() && IsValidRef(GSystemTextures.PerlinNoiseGradient)) { const FTexture2DRHIRef& Texture = (FTexture2DRHIRef&)GSystemTextures.PerlinNoiseGradient->GetRenderTargetItem().ShaderResourceTexture; // Bind the PerlinNoiseGradientTexture as a texture SetTextureParameter( RHICmdList, ShaderRHI, PerlinNoiseGradientTexture, PerlinNoiseGradientTextureSampler, TStaticSamplerState<SF_Point,AM_Wrap,AM_Wrap,AM_Wrap>::GetRHI(), Texture ); } if (PerlinNoise3DTexture.IsBound() && IsValidRef(GSystemTextures.PerlinNoise3D)) { const FTexture3DRHIRef& Texture = (FTexture3DRHIRef&)GSystemTextures.PerlinNoise3D->GetRenderTargetItem().ShaderResourceTexture; // Bind the PerlinNoise3DTexture as a texture SetTextureParameter( RHICmdList, ShaderRHI, PerlinNoise3DTexture, PerlinNoise3DTextureSampler, TStaticSamplerState<SF_Bilinear,AM_Wrap,AM_Wrap,AM_Wrap>::GetRHI(), Texture ); } GlobalDistanceFieldParameters.Set(RHICmdList, ShaderRHI, static_cast<const FViewInfo&>(View).GlobalDistanceFieldInfo.ParameterData); }
void FSlateRHIRenderingPolicy::DrawElements(FRHICommandListImmediate& RHICmdList, FSlateBackBuffer& BackBuffer, const FMatrix& ViewProjectionMatrix, const TArray<FSlateRenderBatch>& RenderBatches) { SCOPE_CYCLE_COUNTER( STAT_SlateDrawTime ); // Should only be called by the rendering thread check(IsInRenderingThread()); TSlateElementVertexBuffer<FSlateVertex>& VertexBuffer = VertexBuffers[CurrentBufferIndex]; FSlateElementIndexBuffer& IndexBuffer = IndexBuffers[CurrentBufferIndex]; float TimeSeconds = FPlatformTime::Seconds() - GStartTime; float RealTimeSeconds = FPlatformTime::Seconds() - GStartTime; float DeltaTimeSeconds = FApp::GetDeltaTime(); static const FEngineShowFlags DefaultShowFlags(ESFIM_Game); const float DisplayGamma = bGammaCorrect ? GEngine ? GEngine->GetDisplayGamma() : 2.2f : 1.0f; FSceneViewFamilyContext SceneViewContext ( FSceneViewFamily::ConstructionValues ( &BackBuffer, NULL, DefaultShowFlags ) .SetWorldTimes( TimeSeconds, RealTimeSeconds, DeltaTimeSeconds ) .SetGammaCorrection( DisplayGamma ) ); FSceneView* SceneView = NULL; TShaderMapRef<FSlateElementVS> VertexShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); // Disabled stencil test state FDepthStencilStateRHIRef DSOff = TStaticDepthStencilState<false,CF_Always>::GetRHI(); FSamplerStateRHIRef BilinearClamp = TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(); if (GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), 0); } // Draw each element for( int32 BatchIndex = 0; BatchIndex < RenderBatches.Num(); ++BatchIndex ) { const FSlateRenderBatch& RenderBatch = RenderBatches[BatchIndex]; const FSlateShaderResource* ShaderResource = RenderBatch.Texture; const ESlateBatchDrawFlag::Type DrawFlags = RenderBatch.DrawFlags; const ESlateDrawEffect::Type DrawEffects = RenderBatch.DrawEffects; const ESlateShader::Type ShaderType = RenderBatch.ShaderType; const FShaderParams& ShaderParams = RenderBatch.ShaderParams; if( !RenderBatch.CustomDrawer.IsValid() ) { if( !ShaderResource || ShaderResource->GetType() != ESlateShaderResource::Material ) { FSlateElementPS* PixelShader = GetTexturePixelShader(ShaderType, DrawEffects); RHICmdList.SetLocalBoundShaderState(RHICmdList.BuildLocalBoundShaderState( GSlateVertexDeclaration.VertexDeclarationRHI, VertexShader->GetVertexShader(), nullptr, nullptr, PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); VertexShader->SetViewProjection(RHICmdList, ViewProjectionMatrix); #if !DEBUG_OVERDRAW RHICmdList.SetBlendState( (RenderBatch.DrawFlags & ESlateBatchDrawFlag::NoBlending) ? TStaticBlendState<>::GetRHI() : TStaticBlendState<CW_RGBA, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_InverseDestAlpha, BF_One>::GetRHI() ); #else RHICmdList.SetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI()); #endif // Disable stencil testing by default RHICmdList.SetDepthStencilState(DSOff); if (DrawFlags & ESlateBatchDrawFlag::Wireframe) { RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Wireframe, CM_None, true>::GetRHI()); } else { RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None, true>::GetRHI()); } if (RenderBatch.ScissorRect.IsSet()) { RHICmdList.SetScissorRect(true, RenderBatch.ScissorRect.GetValue().Left, RenderBatch.ScissorRect.GetValue().Top, RenderBatch.ScissorRect.GetValue().Right, RenderBatch.ScissorRect.GetValue().Bottom); } else { RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } FTexture2DRHIRef TextureRHI; if(ShaderResource) { TextureRHI = ((TSlateTexture<FTexture2DRHIRef>*)ShaderResource)->GetTypedResource(); } if (ShaderType == ESlateShader::LineSegment) { // The lookup table used for splines should clamp when sampling otherwise the results are wrong PixelShader->SetTexture(RHICmdList, TextureRHI, BilinearClamp ); } else if( ShaderResource && IsValidRef( TextureRHI ) ) { FSamplerStateRHIRef SamplerState; if( DrawFlags == (ESlateBatchDrawFlag::TileU | ESlateBatchDrawFlag::TileV) ) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Wrap, AM_Wrap, AM_Wrap>::GetRHI(); } else if (DrawFlags & ESlateBatchDrawFlag::TileU) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Wrap, AM_Clamp, AM_Wrap>::GetRHI(); } else if (DrawFlags & ESlateBatchDrawFlag::TileV) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Wrap, AM_Wrap>::GetRHI(); } else { SamplerState = BilinearClamp; } PixelShader->SetTexture(RHICmdList, TextureRHI, SamplerState); } else { PixelShader->SetTexture(RHICmdList, GWhiteTexture->TextureRHI, BilinearClamp); } PixelShader->SetShaderParams(RHICmdList, ShaderParams.PixelParams); PixelShader->SetDisplayGamma(RHICmdList, (DrawFlags & ESlateBatchDrawFlag::NoGamma) ? 1.0f : 1.0f/DisplayGamma); check(RenderBatch.NumIndices > 0); uint32 PrimitiveCount = RenderBatch.DrawPrimitiveType == ESlateDrawPrimitive::LineList ? RenderBatch.NumIndices / 2 : RenderBatch.NumIndices / 3; // for RHIs that can't handle VertexOffset, we need to offset the stream source each time if (!GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), RenderBatch.VertexOffset * sizeof(FSlateVertex)); RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), 0, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } else { RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), RenderBatch.VertexOffset, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } } else if (ShaderResource && ShaderResource->GetType() == ESlateShaderResource::Material) { if (!SceneView) { SceneView = &CreateSceneView(SceneViewContext, BackBuffer, ViewProjectionMatrix); } FMaterialRenderProxy* MaterialRenderProxy = ((FSlateMaterialResource*)ShaderResource)->GetRenderProxy(); const FMaterial* Material = MaterialRenderProxy->GetMaterial(SceneView->GetFeatureLevel()); FSlateMaterialShaderPS* PixelShader = GetMaterialPixelShader( Material, ShaderType, DrawEffects ); if( PixelShader ) { RHICmdList.SetLocalBoundShaderState(RHICmdList.BuildLocalBoundShaderState( GSlateVertexDeclaration.VertexDeclarationRHI, VertexShader->GetVertexShader(), nullptr, nullptr, PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); PixelShader->SetParameters(RHICmdList, *SceneView, MaterialRenderProxy, Material, 1.0f / DisplayGamma, ShaderParams.PixelParams); VertexShader->SetViewProjection( RHICmdList, ViewProjectionMatrix ); check(RenderBatch.NumIndices > 0); uint32 PrimitiveCount = RenderBatch.DrawPrimitiveType == ESlateDrawPrimitive::LineList ? RenderBatch.NumIndices / 2 : RenderBatch.NumIndices / 3; // for RHIs that can't handle VertexOffset, we need to offset the stream source each time if (!GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), RenderBatch.VertexOffset * sizeof(FSlateVertex)); RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), 0, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } else { RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), RenderBatch.VertexOffset, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } } } } else { TSharedPtr<ICustomSlateElement, ESPMode::ThreadSafe> CustomDrawer = RenderBatch.CustomDrawer.Pin(); if (CustomDrawer.IsValid()) { // This element is custom and has no Slate geometry. Tell it to render itself now CustomDrawer->DrawRenderThread(RHICmdList, &BackBuffer.GetRenderTargetTexture()); // Something may have messed with the viewport size so set it back to the full target. RHICmdList.SetViewport( 0,0,0,BackBuffer.GetSizeXY().X, BackBuffer.GetSizeXY().Y, 0.0f ); RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), 0); } } } CurrentBufferIndex = (CurrentBufferIndex + 1) % 2; }
static void UpdatePlanarReflectionContents_RenderThread( FRHICommandListImmediate& RHICmdList, FSceneRenderer* MainSceneRenderer, FSceneRenderer* SceneRenderer, const FPlanarReflectionSceneProxy* SceneProxy, FRenderTarget* RenderTarget, FTexture* RenderTargetTexture, const FPlane& MirrorPlane, const FName OwnerName, const FResolveParams& ResolveParams, bool bUseSceneColorTexture) { QUICK_SCOPE_CYCLE_COUNTER(STAT_RenderPlanarReflection); FBox PlanarReflectionBounds = SceneProxy->WorldBounds; bool bIsInAnyFrustum = false; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (View.ViewFrustum.IntersectBox(PlanarReflectionBounds.GetCenter(), PlanarReflectionBounds.GetExtent())) { bIsInAnyFrustum = true; break; } } if (bIsInAnyFrustum) { bool bIsVisibleInAnyView = true; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; FSceneViewState* ViewState = View.ViewState; if (ViewState) { FIndividualOcclusionHistory& OcclusionHistory = ViewState->PlanarReflectionOcclusionHistories.FindOrAdd(SceneProxy->PlanarReflectionId); // +1 to buffered frames because the query is submitted late into the main frame, but read at the beginning of a reflection capture frame const int32 NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames() + 1; // +1 to frame counter because we are operating before the main view's InitViews, which is where OcclusionFrameCounter is incremented uint32 OcclusionFrameCounter = ViewState->OcclusionFrameCounter + 1; FRenderQueryRHIRef& PastQuery = OcclusionHistory.GetPastQuery(OcclusionFrameCounter, NumBufferedFrames); if (IsValidRef(PastQuery)) { uint64 NumSamples = 0; QUICK_SCOPE_CYCLE_COUNTER(STAT_PlanarReflectionOcclusionQueryResults); if (RHIGetRenderQueryResult(PastQuery.GetReference(), NumSamples, true)) { bIsVisibleInAnyView = NumSamples > 0; if (bIsVisibleInAnyView) { break; } } } } } if (bIsVisibleInAnyView) { FMemMark MemStackMark(FMemStack::Get()); // update any resources that needed a deferred update FDeferredUpdateResource::UpdateResources(RHICmdList); { #if WANTS_DRAW_MESH_EVENTS FString EventName; OwnerName.ToString(EventName); SCOPED_DRAW_EVENTF(RHICmdList, SceneCapture, TEXT("PlanarReflection %s"), *EventName); #else SCOPED_DRAW_EVENT(RHICmdList, UpdatePlanarReflectionContent_RenderThread); #endif const FRenderTarget* Target = SceneRenderer->ViewFamily.RenderTarget; SetRenderTarget(RHICmdList, Target->GetRenderTargetTexture(), NULL, true); // Note: relying on GBuffer SceneColor alpha being cleared to 1 in the main scene rendering check(GetSceneColorClearAlpha() == 1.0f); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); // Reflection view late update if (SceneRenderer->Views.Num() > 1) { const FMirrorMatrix MirrorMatrix(MirrorPlane); for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& ReflectionViewToUpdate = SceneRenderer->Views[ViewIndex]; const FViewInfo& UpdatedParentView = MainSceneRenderer->Views[ViewIndex]; ReflectionViewToUpdate.UpdatePlanarReflectionViewMatrix(UpdatedParentView, MirrorMatrix); } } // Render the scene normally { SCOPED_DRAW_EVENT(RHICmdList, RenderScene); SceneRenderer->Render(RHICmdList); } for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (MainSceneRenderer->Scene->GetShadingPath() == EShadingPath::Deferred) { PrefilterPlanarReflection<true>(RHICmdList, View, SceneProxy, Target); } else { PrefilterPlanarReflection<false>(RHICmdList, View, SceneProxy, Target); } } RHICmdList.CopyToResolveTarget(RenderTarget->GetRenderTargetTexture(), RenderTargetTexture->TextureRHI, false, ResolveParams); } FSceneRenderer::WaitForTasksClearSnapshotsAndDeleteSceneRenderer(RHICmdList, SceneRenderer); } } }
FUniformBufferRHIRef FD3D11DynamicRHI::RHICreateUniformBuffer(const void* Contents,const FRHIUniformBufferLayout& Layout,EUniformBufferUsage Usage) { check(IsInRenderingThread()); FD3D11UniformBuffer* NewUniformBuffer = nullptr; const uint32 NumBytes = Layout.ConstantBufferSize; if (NumBytes > 0) { // Constant buffers must also be 16-byte aligned. check(Align(NumBytes,16) == NumBytes); check(Align(Contents,16) == Contents); check(NumBytes <= D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16); check(NumBytes < (1 << NumPoolBuckets)); SCOPE_CYCLE_COUNTER(STAT_D3D11UpdateUniformBufferTime); if (IsPoolingEnabled()) { TRefCountPtr<ID3D11Buffer> UniformBufferResource; FRingAllocation RingAllocation; if (!RingAllocation.IsValid()) { // Find the appropriate bucket based on size const uint32 BucketIndex = GetPoolBucketIndex(NumBytes); TArray<FPooledUniformBuffer>& PoolBucket = UniformBufferPool[BucketIndex]; if (PoolBucket.Num() > 0) { // Reuse the last entry in this size bucket FPooledUniformBuffer FreeBufferEntry = PoolBucket.Pop(); check(IsValidRef(FreeBufferEntry.Buffer)); UniformBufferResource = FreeBufferEntry.Buffer; checkf(FreeBufferEntry.CreatedSize >= NumBytes, TEXT("%u %u %u %u"), NumBytes, BucketIndex, FreeBufferEntry.CreatedSize, GetPoolBucketSize(NumBytes)); DEC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers); DEC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, FreeBufferEntry.CreatedSize); } // Nothing usable was found in the free pool, create a new uniform buffer if (!IsValidRef(UniformBufferResource)) { D3D11_BUFFER_DESC Desc; // Allocate based on the bucket size, since this uniform buffer will be reused later Desc.ByteWidth = GetPoolBucketSize(NumBytes); // Use D3D11_USAGE_DYNAMIC, which allows multiple CPU writes for pool reuses // This is method of updating is vastly superior to creating a new constant buffer each time with D3D11_USAGE_IMMUTABLE, // Since that inserts the data into the command buffer which causes GPU flushes Desc.Usage = D3D11_USAGE_DYNAMIC; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; Desc.MiscFlags = 0; Desc.StructureByteStride = 0; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc, NULL, UniformBufferResource.GetInitReference())); UpdateBufferStats(UniformBufferResource, true); } check(IsValidRef(UniformBufferResource)); D3D11_MAPPED_SUBRESOURCE MappedSubresource; // Discard previous results since we always do a full update VERIFYD3D11RESULT(Direct3DDeviceIMContext->Map(UniformBufferResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedSubresource)); check(MappedSubresource.RowPitch >= NumBytes); FMemory::Memcpy(MappedSubresource.pData, Contents, NumBytes); Direct3DDeviceIMContext->Unmap(UniformBufferResource, 0); } NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, RingAllocation); } else { // No pooling D3D11_BUFFER_DESC Desc; Desc.ByteWidth = NumBytes; Desc.Usage = D3D11_USAGE_IMMUTABLE; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = 0; Desc.MiscFlags = 0; Desc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA ImmutableData; ImmutableData.pSysMem = Contents; ImmutableData.SysMemPitch = ImmutableData.SysMemSlicePitch = 0; TRefCountPtr<ID3D11Buffer> UniformBufferResource; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc,&ImmutableData,UniformBufferResource.GetInitReference())); NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, FRingAllocation()); } } else { // This uniform buffer contains no constants, only a resource table. NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, nullptr, FRingAllocation()); } if (Layout.Resources.Num()) { int32 NumResources = Layout.Resources.Num(); FRHIResource** InResources = (FRHIResource**)((uint8*)Contents + Layout.ResourceOffset); NewUniformBuffer->ResourceTable.Empty(NumResources); NewUniformBuffer->ResourceTable.AddZeroed(NumResources); for (int32 i = 0; i < NumResources; ++i) { check(InResources[i]); NewUniformBuffer->ResourceTable[i] = InResources[i]; } NewUniformBuffer->RawResourceTable.Empty(NumResources); NewUniformBuffer->RawResourceTable.AddZeroed(NumResources); } return NewUniformBuffer; }
static FD3D11Texture2D* D3D11CreateTexture2DAlias( FD3D11DynamicRHI* InD3D11RHI, ID3D11Texture2D* InResource, ID3D11ShaderResourceView* InShaderResourceView, uint32 InSizeX, uint32 InSizeY, uint32 InSizeZ, uint32 InNumMips, uint32 InNumSamples, EPixelFormat InFormat, uint32 InFlags) { const bool bSRGB = (InFlags & TexCreate_SRGB) != 0; const DXGI_FORMAT PlatformResourceFormat = (DXGI_FORMAT)GPixelFormats[InFormat].PlatformFormat; const DXGI_FORMAT PlatformShaderResourceFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); const DXGI_FORMAT PlatformRenderTargetFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); D3D11_RTV_DIMENSION RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; if (InNumSamples > 1) { RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; } TArray<TRefCountPtr<ID3D11RenderTargetView> > RenderTargetViews; if (InFlags & TexCreate_RenderTargetable) { // Create a render target view for each mip for (uint32 MipIndex = 0; MipIndex < InNumMips; MipIndex++) { check(!(InFlags & TexCreate_TargetArraySlicesIndependently)); // not supported D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; FMemory::Memzero(&RTVDesc, sizeof(RTVDesc)); RTVDesc.Format = PlatformRenderTargetFormat; RTVDesc.ViewDimension = RenderTargetViewDimension; RTVDesc.Texture2D.MipSlice = MipIndex; TRefCountPtr<ID3D11RenderTargetView> RenderTargetView; VERIFYD3D11RESULT(InD3D11RHI->GetDevice()->CreateRenderTargetView(InResource, &RTVDesc, RenderTargetView.GetInitReference())); RenderTargetViews.Add(RenderTargetView); } } TRefCountPtr<ID3D11ShaderResourceView> ShaderResourceView; // Create a shader resource view for the texture. if (!InShaderResourceView && (InFlags & TexCreate_ShaderResource)) { D3D11_SRV_DIMENSION ShaderResourceViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; SRVDesc.Format = PlatformShaderResourceFormat; SRVDesc.ViewDimension = ShaderResourceViewDimension; SRVDesc.Texture2D.MostDetailedMip = 0; SRVDesc.Texture2D.MipLevels = InNumMips; VERIFYD3D11RESULT(InD3D11RHI->GetDevice()->CreateShaderResourceView(InResource, &SRVDesc, ShaderResourceView.GetInitReference())); check(IsValidRef(ShaderResourceView)); } else { ShaderResourceView = InShaderResourceView; } FD3D11Texture2D* NewTexture = new FD3D11Texture2D( InD3D11RHI, InResource, ShaderResourceView, false, 1, RenderTargetViews, /*DepthStencilViews=*/ NULL, InSizeX, InSizeY, InSizeZ, InNumMips, InNumSamples, InFormat, /*bInCubemap=*/ false, InFlags, /*bPooledTexture=*/ false ); return NewTexture; }
FD3D11Texture2DSet* FD3D11Texture2DSet::D3D11CreateTexture2DSet( FD3D11DynamicRHI* InD3D11RHI, ovrSwapTextureSet* InTextureSet, const D3D11_TEXTURE2D_DESC& InDsDesc, EPixelFormat InFormat, uint32 InFlags ) { check(InTextureSet); TArray<TRefCountPtr<ID3D11RenderTargetView> > RenderTargetViews; FD3D11Texture2DSet* NewTextureSet = new FD3D11Texture2DSet( InD3D11RHI, nullptr, nullptr, false, 1, RenderTargetViews, /*DepthStencilViews=*/ NULL, InDsDesc.Width, InDsDesc.Height, 0, InDsDesc.MipLevels, InDsDesc.SampleDesc.Count, InFormat, /*bInCubemap=*/ false, InFlags, /*bPooledTexture=*/ false ); const uint32 TexCount = InTextureSet->TextureCount; const bool bSRGB = (InFlags & TexCreate_SRGB) != 0; const DXGI_FORMAT PlatformResourceFormat = (DXGI_FORMAT)GPixelFormats[InFormat].PlatformFormat; const DXGI_FORMAT PlatformShaderResourceFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); const DXGI_FORMAT PlatformRenderTargetFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); D3D11_RTV_DIMENSION RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; if (InDsDesc.SampleDesc.Count > 1) { RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; } for (uint32 i = 0; i < TexCount; ++i) { ovrD3D11Texture D3DTex; D3DTex.Texture = InTextureSet->Textures[i]; TArray<TRefCountPtr<ID3D11RenderTargetView> > RenderTargetViews; if (InFlags & TexCreate_RenderTargetable) { // Create a render target view for each mip for (uint32 MipIndex = 0; MipIndex < InDsDesc.MipLevels; MipIndex++) { check(!(InFlags & TexCreate_TargetArraySlicesIndependently)); // not supported D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; FMemory::Memzero(&RTVDesc, sizeof(RTVDesc)); RTVDesc.Format = PlatformRenderTargetFormat; RTVDesc.ViewDimension = RenderTargetViewDimension; RTVDesc.Texture2D.MipSlice = MipIndex; TRefCountPtr<ID3D11RenderTargetView> RenderTargetView; VERIFYD3D11RESULT(InD3D11RHI->GetDevice()->CreateRenderTargetView(D3DTex.D3D11.pTexture, &RTVDesc, RenderTargetView.GetInitReference())); RenderTargetViews.Add(RenderTargetView); } } TRefCountPtr<ID3D11ShaderResourceView> ShaderResourceView = D3DTex.D3D11.pSRView; // Create a shader resource view for the texture. if (!ShaderResourceView && (InFlags & TexCreate_ShaderResource)) { D3D11_SRV_DIMENSION ShaderResourceViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; SRVDesc.Format = PlatformShaderResourceFormat; SRVDesc.ViewDimension = ShaderResourceViewDimension; SRVDesc.Texture2D.MostDetailedMip = 0; SRVDesc.Texture2D.MipLevels = InDsDesc.MipLevels; VERIFYD3D11RESULT(InD3D11RHI->GetDevice()->CreateShaderResourceView(D3DTex.D3D11.pTexture, &SRVDesc, ShaderResourceView.GetInitReference())); check(IsValidRef(ShaderResourceView)); } NewTextureSet->AddTexture(D3DTex.D3D11.pTexture, ShaderResourceView, &RenderTargetViews); } NewTextureSet->TextureSet = InTextureSet; NewTextureSet->InitWithCurrentElement(); return NewTextureSet; }
void FDeferredShadingSceneRenderer::BeginOcclusionTests(FRHICommandListImmediate& RHICmdList, bool bRenderQueries) { SCOPE_CYCLE_COUNTER(STAT_BeginOcclusionTestsTime); int32 NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames(); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const bool bUseDownsampledDepth = SceneContext.UseDownsizedOcclusionQueries() && IsValidRef(SceneContext.SmallDepthZ) && IsValidRef(SceneContext.GetSmallDepthSurface()); if (bUseDownsampledDepth) { SetRenderTarget(RHICmdList, NULL, SceneContext.GetSmallDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } else { SetRenderTarget(RHICmdList, NULL, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } if (bRenderQueries) { RHICmdList.BeginOcclusionQueryBatch(); // Perform occlusion queries for each view for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { SCOPED_DRAW_EVENT(RHICmdList, BeginOcclusionTests); FViewInfo& View = Views[ViewIndex]; if (bUseDownsampledDepth) { const uint32 DownsampledX = FMath::TruncToInt(View.ViewRect.Min.X / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledY = FMath::TruncToInt(View.ViewRect.Min.Y / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledSizeX = FMath::TruncToInt(View.ViewRect.Width() / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledSizeY = FMath::TruncToInt(View.ViewRect.Height() / SceneContext.GetSmallColorDepthDownsampleFactor()); // Setup the viewport for rendering to the downsampled depth buffer RHICmdList.SetViewport(DownsampledX, DownsampledY, 0.0f, DownsampledX + DownsampledSizeX, DownsampledY + DownsampledSizeY, 1.0f); } else { RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f); } FSceneViewState* ViewState = (FSceneViewState*)View.State; if (ViewState && !View.bDisableQuerySubmissions) { // Depth tests, no depth writes, no color writes, opaque, solid rasterization wo/ backface culling. RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI()); // We only need to render the front-faces of the culling geometry (this halves the amount of pixels we touch) RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<CW_NONE>::GetRHI()); // Lookup the vertex shader. TShaderMapRef<FOcclusionQueryVS> VertexShader(View.ShaderMap); SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), OcclusionTestBoundShaderState, GetVertexDeclarationFVector3(), *VertexShader, NULL); VertexShader->SetParameters(RHICmdList, View); // Issue this frame's occlusion queries (occlusion queries from last frame may still be in flight) const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryIssueIndex(ViewState->PendingPrevFrameNumber, NumBufferedFrames); FSceneViewState::ShadowKeyOcclusionQueryMap& ShadowOcclusionQueryMap = ViewState->ShadowOcclusionQueryMaps[QueryIndex]; // Clear primitives which haven't been visible recently out of the occlusion history, and reset old pending occlusion queries. ViewState->TrimOcclusionHistory(RHICmdList, ViewFamily.CurrentRealTime, ViewFamily.CurrentRealTime - GEngine->PrimitiveProbablyVisibleTime, ViewFamily.CurrentRealTime, ViewState->OcclusionFrameCounter); // Give back all these occlusion queries to the pool. for (TMap<FSceneViewState::FProjectedShadowKey, FRenderQueryRHIRef>::TIterator QueryIt(ShadowOcclusionQueryMap); QueryIt; ++QueryIt) { //FRenderQueryRHIParamRef Query = QueryIt.Value(); //check( Query.GetRefCount() == 1 ); ViewState->OcclusionQueryPool.ReleaseQuery(QueryIt.Value()); } ShadowOcclusionQueryMap.Reset(); { SCOPED_DRAW_EVENT(RHICmdList, ShadowFrustumQueries); for (TSparseArray<FLightSceneInfoCompact>::TConstIterator LightIt(Scene->Lights); LightIt; ++LightIt) { const FVisibleLightInfo& VisibleLightInfo = VisibleLightInfos[LightIt.GetIndex()]; for (int32 ShadowIndex = 0; ShadowIndex < VisibleLightInfo.AllProjectedShadows.Num(); ShadowIndex++) { const FProjectedShadowInfo& ProjectedShadowInfo = *VisibleLightInfo.AllProjectedShadows[ShadowIndex]; if (ProjectedShadowInfo.DependentView && ProjectedShadowInfo.DependentView != &View) { continue; } if (ProjectedShadowInfo.CascadeSettings.bOnePassPointLightShadow) { FLightSceneProxy& LightProxy = *(ProjectedShadowInfo.GetLightSceneInfo().Proxy); // Query one pass point light shadows separately because they don't have a shadow frustum, they have a bounding sphere instead. FSphere LightBounds = LightProxy.GetBoundingSphere(); const bool bCameraInsideLightGeometry = ((FVector)View.ViewMatrices.ViewOrigin - LightBounds.Center).SizeSquared() < FMath::Square(LightBounds.W * 1.05f + View.NearClippingDistance * 2.0f); if (!bCameraInsideLightGeometry) { const FRenderQueryRHIRef ShadowOcclusionQuery = ViewState->OcclusionQueryPool.AllocateQuery(); RHICmdList.BeginRenderQuery(ShadowOcclusionQuery); FSceneViewState::FProjectedShadowKey Key(ProjectedShadowInfo); checkSlow(ShadowOcclusionQueryMap.Find(Key) == NULL); ShadowOcclusionQueryMap.Add(Key, ShadowOcclusionQuery); // Draw bounding sphere VertexShader->SetParametersWithBoundingSphere(RHICmdList, View, LightBounds); StencilingGeometry::DrawVectorSphere(RHICmdList); RHICmdList.EndRenderQuery(ShadowOcclusionQuery); } } // Don't query preshadows, since they are culled if their subject is occluded. // Don't query if any subjects are visible because the shadow frustum will be definitely unoccluded else if (!ProjectedShadowInfo.IsWholeSceneDirectionalShadow() && !ProjectedShadowInfo.bPreShadow && !ProjectedShadowInfo.SubjectsVisible(View)) { IssueProjectedShadowOcclusionQuery(RHICmdList, View, ProjectedShadowInfo, *VertexShader, NumBufferedFrames); } } // Issue occlusion queries for all per-object projected shadows that we would have rendered but were occluded last frame. for (int32 ShadowIndex = 0; ShadowIndex < VisibleLightInfo.OccludedPerObjectShadows.Num(); ShadowIndex++) { const FProjectedShadowInfo& ProjectedShadowInfo = *VisibleLightInfo.OccludedPerObjectShadows[ShadowIndex]; IssueProjectedShadowOcclusionQuery(RHICmdList, View, ProjectedShadowInfo, *VertexShader, NumBufferedFrames); } } } // Don't do primitive occlusion if we have a view parent or are frozen. #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (!ViewState->HasViewParent() && !ViewState->bIsFrozen) #endif { VertexShader->SetParameters(RHICmdList, View); { SCOPED_DRAW_EVENT(RHICmdList, IndividualQueries); View.IndividualOcclusionQueries.Flush(RHICmdList); } { SCOPED_DRAW_EVENT(RHICmdList, GroupedQueries); View.GroupedOcclusionQueries.Flush(RHICmdList); } } } } RHICmdList.EndOcclusionQueryBatch(); } if (bUseDownsampledDepth) { // Restore default render target SceneContext.BeginRenderingSceneColor(RHICmdList, ESimpleRenderTargetMode::EUninitializedColorExistingDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } }
int32 FUniformMeshConverter::Convert( FRHICommandListImmediate& RHICmdList, FSceneRenderer& Renderer, FViewInfo& View, const FPrimitiveSceneInfo* PrimitiveSceneInfo, int32 LODIndex, FUniformMeshBuffers*& OutUniformMeshBuffers, const FMaterialRenderProxy*& OutMaterialRenderProxy, FUniformBufferRHIParamRef& OutPrimitiveUniformBuffer) { const FPrimitiveSceneProxy* PrimitiveSceneProxy = PrimitiveSceneInfo->Proxy; const auto FeatureLevel = View.GetFeatureLevel(); TArray<FMeshBatch> MeshElements; PrimitiveSceneInfo->Proxy->GetMeshDescription(LODIndex, MeshElements); int32 NumTriangles = 0; for (int32 MeshIndex = 0; MeshIndex < MeshElements.Num(); MeshIndex++) { if (ShouldConvertMesh(MeshElements[MeshIndex])) { NumTriangles += MeshElements[MeshIndex].GetNumPrimitives(); } } if (NumTriangles > 0) { if (GUniformMeshTemporaryBuffers.MaxElements < NumTriangles * 3) { GUniformMeshTemporaryBuffers.MaxElements = NumTriangles * 3; GUniformMeshTemporaryBuffers.Release(); GUniformMeshTemporaryBuffers.Initialize(); } RHICmdList.SetRenderTargets(0, (const FRHIRenderTargetView*)NULL, NULL, 0, (const FUnorderedAccessViewRHIParamRef*)NULL); uint32 Offsets[1] = {0}; const FVertexBufferRHIParamRef StreamOutTargets[1] = {GUniformMeshTemporaryBuffers.TriangleData.GetReference()}; RHICmdList.SetStreamOutTargets(1, StreamOutTargets, Offsets); for (int32 MeshIndex = 0; MeshIndex < MeshElements.Num(); MeshIndex++) { const FMeshBatch& Mesh = MeshElements[MeshIndex]; if (ShouldConvertMesh(Mesh)) { FConvertToUniformMeshDrawingPolicy DrawingPolicy( Mesh.VertexFactory, Mesh.MaterialRenderProxy, *Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel), FeatureLevel); //@todo - fix OutMaterialRenderProxy = Mesh.MaterialRenderProxy; RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(FeatureLevel)); DrawingPolicy.SetSharedState(RHICmdList, &View, FConvertToUniformMeshDrawingPolicy::ContextDataType()); for (int32 BatchElementIndex = 0; BatchElementIndex < Mesh.Elements.Num(); BatchElementIndex++) { //@todo - fix OutPrimitiveUniformBuffer = IsValidRef(Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer) ? Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer : *Mesh.Elements[BatchElementIndex].PrimitiveUniformBufferResource; DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,Mesh,BatchElementIndex,false,FMeshDrawingRenderState(),FConvertToUniformMeshDrawingPolicy::ElementDataType(), FConvertToUniformMeshDrawingPolicy::ContextDataType()); DrawingPolicy.DrawMesh(RHICmdList, Mesh, BatchElementIndex); } } } RHICmdList.SetStreamOutTargets(1, (const FVertexBufferRHIParamRef*)NULL, Offsets); } OutUniformMeshBuffers = &GUniformMeshTemporaryBuffers; return NumTriangles; }
FD3D11Texture2DSet* FD3D11Texture2DSet::D3D11CreateTexture2DSet( FD3D11DynamicRHI* InD3D11RHI, const FOvrSessionSharedPtr& InOvrSession, ovrTextureSwapChain InTextureSet, const D3D11_TEXTURE2D_DESC& InDsDesc, EPixelFormat InFormat, uint32 InFlags ) { FOvrSessionShared::AutoSession OvrSession(InOvrSession); check(InTextureSet); TArray<TRefCountPtr<ID3D11RenderTargetView> > TextureSetRenderTargetViews; FD3D11Texture2DSet* NewTextureSet = new FD3D11Texture2DSet( InD3D11RHI, nullptr, nullptr, false, 1, TextureSetRenderTargetViews, /*DepthStencilViews=*/ NULL, InDsDesc.Width, InDsDesc.Height, 0, InDsDesc.MipLevels, InDsDesc.SampleDesc.Count, InFormat, /*bInCubemap=*/ false, InFlags, /*bPooledTexture=*/ false ); int TexCount; ovr_GetTextureSwapChainLength(OvrSession, InTextureSet, &TexCount); const bool bSRGB = (InFlags & TexCreate_SRGB) != 0; const DXGI_FORMAT PlatformResourceFormat = (DXGI_FORMAT)GPixelFormats[InFormat].PlatformFormat; const DXGI_FORMAT PlatformShaderResourceFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); const DXGI_FORMAT PlatformRenderTargetFormat = FindShaderResourceDXGIFormat(PlatformResourceFormat, bSRGB); D3D11_RTV_DIMENSION RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; if (InDsDesc.SampleDesc.Count > 1) { RenderTargetViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; } for (int32 i = 0; i < TexCount; ++i) { TRefCountPtr<ID3D11Texture2D> pD3DTexture; ovrResult res = ovr_GetTextureSwapChainBufferDX(OvrSession, InTextureSet, i, IID_PPV_ARGS(pD3DTexture.GetInitReference())); if (!OVR_SUCCESS(res)) { UE_LOG(LogHMD, Error, TEXT("ovr_GetTextureSwapChainBufferDX failed, error = %d"), int(res)); return nullptr; } TArray<TRefCountPtr<ID3D11RenderTargetView> > RenderTargetViews; if (InFlags & TexCreate_RenderTargetable) { // Create a render target view for each mip for (uint32 MipIndex = 0; MipIndex < InDsDesc.MipLevels; MipIndex++) { check(!(InFlags & TexCreate_TargetArraySlicesIndependently)); // not supported D3D11_RENDER_TARGET_VIEW_DESC RTVDesc; FMemory::Memzero(&RTVDesc, sizeof(RTVDesc)); RTVDesc.Format = PlatformRenderTargetFormat; RTVDesc.ViewDimension = RenderTargetViewDimension; RTVDesc.Texture2D.MipSlice = MipIndex; TRefCountPtr<ID3D11RenderTargetView> RenderTargetView; VERIFYD3D11RESULT_EX(InD3D11RHI->GetDevice()->CreateRenderTargetView(pD3DTexture, &RTVDesc, RenderTargetView.GetInitReference()), InD3D11RHI->GetDevice()); RenderTargetViews.Add(RenderTargetView); } } TRefCountPtr<ID3D11ShaderResourceView> ShaderResourceView; // Create a shader resource view for the texture. if (InFlags & TexCreate_ShaderResource) { D3D11_SRV_DIMENSION ShaderResourceViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; SRVDesc.Format = PlatformShaderResourceFormat; SRVDesc.ViewDimension = ShaderResourceViewDimension; SRVDesc.Texture2D.MostDetailedMip = 0; SRVDesc.Texture2D.MipLevels = InDsDesc.MipLevels; VERIFYD3D11RESULT_EX(InD3D11RHI->GetDevice()->CreateShaderResourceView(pD3DTexture, &SRVDesc, ShaderResourceView.GetInitReference()), InD3D11RHI->GetDevice()); check(IsValidRef(ShaderResourceView)); } NewTextureSet->AddTexture(pD3DTexture, ShaderResourceView, &RenderTargetViews); } if (InFlags & TexCreate_RenderTargetable) { NewTextureSet->SetCurrentGPUAccess(EResourceTransitionAccess::EWritable); } NewTextureSet->TextureSet = InTextureSet; NewTextureSet->InitWithCurrentElement(0); return NewTextureSet; }