LightStage::Index LightStage::addLight(const LightPointer& light) { auto found = _lightMap.find(light); if (found == _lightMap.end()) { auto lightId = _lights.newElement(light); // Avoid failing to allocate a light, just pass if (lightId != INVALID_INDEX) { // Allocate the matching Desc to the light if (lightId >= (Index) _descs.size()) { _descs.emplace_back(Desc()); } else { _descs.emplace(_descs.begin() + lightId, Desc()); } // INsert the light and its index in the reverese map _lightMap.insert(LightMap::value_type(light, lightId)); updateLightArrayBuffer(lightId); } return lightId; } else { return (*found).second; } }
void FDeferredShadingSceneRenderer::RenderVisualizeTexturePool() { TRefCountPtr<IPooledRenderTarget> VisualizeTexturePool; /** Resolution for the texture pool visualizer texture. */ enum { TexturePoolVisualizerSizeX = 280, TexturePoolVisualizerSizeY = 140, }; FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(FIntPoint(TexturePoolVisualizerSizeX, TexturePoolVisualizerSizeY), PF_B8G8R8A8, TexCreate_None, TexCreate_None, false)); GRenderTargetPool.FindFreeElement(Desc, VisualizeTexturePool, TEXT("VisualizeTexturePool")); uint32 Pitch; FColor* TextureData = (FColor*)RHILockTexture2D((FTexture2DRHIRef&)VisualizeTexturePool->GetRenderTargetItem().ShaderResourceTexture, 0, RLM_WriteOnly, Pitch, false ); if(TextureData) { // clear with grey to get reliable background color FMemory::Memset(TextureData, 0x88, TexturePoolVisualizerSizeX * TexturePoolVisualizerSizeY * 4); RHIGetTextureMemoryVisualizeData(TextureData, TexturePoolVisualizerSizeX, TexturePoolVisualizerSizeY, Pitch, 4096); } RHIUnlockTexture2D((FTexture2DRHIRef&)VisualizeTexturePool->GetRenderTargetItem().ShaderResourceTexture, 0, false); FIntPoint RTExtent = GSceneRenderTargets.GetBufferSizeXY(); FVector2D Tex00 = FVector2D(0, 0); FVector2D Tex11 = FVector2D(1, 1); //todo VisualizeTexture(*VisualizeTexturePool, ViewFamily.RenderTarget, FIntRect(0, 0, RTExtent.X, RTExtent.Y), RTExtent, 1.0f, 0.0f, 0.0f, Tex00, Tex11, 1.0f, false); }
//native TSC_SetChannelDescription(channelname[], desc[]); cell AMX_NATIVE_CALL native_TSC_SetChannelDescription(AMX* amx, cell* params) { char *TmpParam = NULL; amx_StrParam(amx, params[1], TmpParam); string ChannelName(TmpParam); TSServer.EscapeString(ChannelName); amx_StrParam(amx, params[2], TmpParam); string Desc(TmpParam); TSServer.EscapeString(Desc); CommandList *cmds = new CommandList; string CmdStr("channelfind pattern="); CmdStr.append(ChannelName); cmds->push(new CCommand(CmdStr, "cid")); CmdStr.assign("channeledit cid=<1> channel_description="); CmdStr.append(Desc); cmds->push(new CCommand(CmdStr)); TSServer.AddCommandListToQueue(cmds); return 1; }
void TopWindow::Open(HWND hwnd) { GuiLock __; if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1)) DistributeAccessKeys(); UsrLogT(3, "OPEN " + Desc(this)); LLOG("TopWindow::Open, owner HWND = " << FormatIntHex((int)hwnd, 8) << ", Active = " << FormatIntHex((int)::GetActiveWindow(), 8)); IgnoreMouseUp(); SyncCaption(); #ifdef PLATFORM_WINCE if(!GetRect().IsEmpty()) #endif if(fullscreen) { SetRect(GetScreenSize()); Create(hwnd, WS_POPUP, 0, false, SW_SHOWMAXIMIZED, false); } else { CenterRect(hwnd, hwnd && hwnd == GetTrayHWND__() ? center ? 2 : 0 : center); Create(hwnd, style, exstyle, false, state == OVERLAPPED ? SW_SHOWNORMAL : state == MINIMIZED ? SW_MINIMIZE : SW_MAXIMIZE, false); } PlaceFocus(); SyncCaption(); FixIcons(); }
PropGroup* PropGroup::Group(const std::wstring& name) { PropGroup *group=new PropGroup(this,Desc(name)); groups.push_back(group); return group; }
void TopWindow::Deactivate() { LLOG("DeActivate current focus " << UPP::Name(GetFocusCtrl())); if(HasFocusDeep()) activefocus = GetFocusCtrl(); USRLOG(" DEACTIVATE " + Desc(this)); LLOG("DeActivate " << Name() << " activefocus = " << UPP::Name(activefocus)); }
int main(int argc, char* argv[]) { if (argc<=1) return ShowHelp(); // run if (GML::Utils::GString::Equals(argv[1],"run",true)) { if (argc!=3) return Error("run command requare a parameter (a template file)"); return Run(argv[2]); } // info if (GML::Utils::GString::Equals(argv[1],"info",true)) { if (argc!=3) return Error("info command requare a parameter (a name for a an Algorithm, Conector, DataBase or Notifier)"); return Info(argv[2]); } // desc if (GML::Utils::GString::Equals(argv[1],"desc",true)) { if (argc!=4) return Error("desc command requare two parameters (a name for a an Algorithm, Conector, DataBase or Notifier and a property)"); return Desc(argv[2],argv[3]); } // template if (GML::Utils::GString::Equals(argv[1],"template",true)) { if ((argc!=4) && (argc!=3)) return Error("template command requares a name for a an Algorithm, Conector, DataBase or Notifier"); if (argc==3) return Template(argv[2],NULL); else return Template(argv[2],argv[3]); } // pytemplate if (GML::Utils::GString::Equals(argv[1],"pytemplate",true)) { if (argc!=3) return Error("pytemplate command requares one parameter (a name for a an Algorithm, Conector, DataBase or Notifier)"); return PyTemplate(argv[2]); } // algorithms if (GML::Utils::GString::Equals(argv[1],"algorithms",true)) return ShowObjects(ALGORITHM_FOLDER,ALGORITHM_EXT); // connectors if (GML::Utils::GString::Equals(argv[1],"connectors",true)) return ShowObjects(CONNECTOR_FOLDER,CONNECTOR_EXT); // notifiers if (GML::Utils::GString::Equals(argv[1],"notifiers",true)) return ShowObjects(NOTIFYER_FOLDER,NOTIFYER_EXT); // databases if (GML::Utils::GString::Equals(argv[1],"databases",true)) return ShowObjects(DATABASE_FOLDER,DATABASE_EXT); printf("[ERROR] Unknwon command : %s \n",argv[1]); return -1; }
LightStage::LightPointer LightStage::removeLight(Index index) { LightPointer removed = _lights.freeElement(index); if (removed) { _lightMap.erase(removed); _descs[index] = Desc(); } return removed; }
void FHZBOcclusionTester::InitDynamicRHI() { if (GetFeatureLevel() >= ERHIFeatureLevel::SM4) { FRHICommandListImmediate& RHICmdList = FRHICommandListExecutor::GetImmediateCommandList(); FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( FIntPoint( SizeX, SizeY ), PF_B8G8R8A8, FClearValueBinding::None, TexCreate_CPUReadback | TexCreate_HideInVisualizeTexture, TexCreate_None, false ) ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, ResultsTextureCPU, TEXT("HZBResultsCPU") ); } }
void CAComponent::Print(FILE* file) const { fprintf (file, "CAComponent: %p", Comp()); if (mManuName) { fprintf (file, ", Manu:"); _ShowCF (file, mManuName); if (mAUName) fprintf (file, ", Name:"); _ShowCF (file, mAUName); } fprintf (file, ", "); Desc ().Print(file); }
__declspec( dllexport ) ClassDesc* LibClassDesc(int i) { switch(i) { case 0: return Get$$CLASS_NAME$$Desc(); $$IF(SPACE_WARP_TYPE) case 1: return Get$$CLASS_NAME$$ObjDesc(); $$ENDIF default: return 0; } }
void TopWindow::Activate() { LLOG("Activate " << Name() << " activefocus = " << UPP::Name(activefocus)); USRLOG(" ACTIVATE " + Desc(this)); if(activefocus && (HasFocus() || !GetFocusChildDeep()) && IsEnabled()) { LLOG("activefocus->SetWantFocus()"); activefocus->SetWantFocus(); } if(urgent) SyncCaption(); LLOG("Activate End"); }
void AllocateOrReuseLightShaftRenderTarget(FRHICommandListImmediate& RHICmdList, TRefCountPtr<IPooledRenderTarget>& Target, const TCHAR* Name) { if (!Target) { EPixelFormat LightShaftFilterBufferFormat = PF_FloatRGB; const FIntPoint BufferSize = FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY(); FIntPoint LightShaftSize(FMath::Max<uint32>(BufferSize.X / GetLightShaftDownsampleFactor(), 1), FMath::Max<uint32>(BufferSize.Y / GetLightShaftDownsampleFactor(), 1)); FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(LightShaftSize, LightShaftFilterBufferFormat, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable, false)); GRenderTargetPool.FindFreeElement(Desc, Target, Name); SetRenderTarget(RHICmdList, Target->GetRenderTargetItem().TargetableTexture, FTextureRHIRef()); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, FIntRect()); } }
void ToolTip::PopUp(Ctrl *owner, Point p, bool effect) { LLOG("ToolTip::PopUp" << Desc(owner) << " @ " << p); Rect r = owner->GetWorkArea(); Size sz = GetMinSize(); p.x = max(p.x + sz.cx > r.right ? r.right - sz.cx : p.x, r.left); p.y = max(p.y + sz.cy > r.bottom ? r.bottom - sz.cy : p.y, r.top); if(GUI_PopUpEffect() == GUIEFFECT_SLIDE && effect) SetRect(p.x, p.y, sz.cx, 1); else SetRect(p.x, p.y, sz.cx, sz.cy); Ctrl::PopUp(owner, true, false, true); if(effect) Animate(*this, p.x, p.y, sz.cx, sz.cy); }
bool Ctrl::SetFocus0(bool activate) { GuiLock __; USRLOG(" SETFOCUS " << Desc(this)); LLOG("Ctrl::SetFocus " << Desc(this)); LLOG("focusCtrlWnd " << UPP::Name(focusCtrlWnd)); LLOG("Ctrl::SetFocus0 -> deferredSetFocus = NULL; was: " << UPP::Name(defferedSetFocus)); defferedSetFocus = NULL; if(focusCtrl == this) return true; if(!IsOpen() || !IsEnabled() || !IsVisible()) return false; Ptr<Ctrl> pfocusCtrl = focusCtrl; Ptr<Ctrl> topwindow = GetTopWindow(); Ptr<Ctrl> topctrl = GetTopCtrl(); Ptr<Ctrl> _this = this; if(!topwindow) topwindow = topctrl; LLOG("SetFocus -> SetWndFocus: topwindow = " << UPP::Name(topwindow) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd)); if(!topwindow->HasWndFocus() && !topwindow->SetWndFocus()) return false;// cxl 31.1.2004 #ifdef PLATFORM_OSX11 // ugly temporary hack - popups not behaving right in MacOS // before 2012-9-2 was #ifdef GUI_X11, but that caused issues in most linux distros (cxl) // as parent window of popup always manages focus/keyboard for popup in X11 if(activate) // Dolik/fudadmin 2011-5-1 topctrl->SetWndForeground(); #else topwindow->SetWndForeground(); // cxl 2007-4-27 #endif LLOG("SetFocus -> focusCtrl = this: " << FormatIntHex(this) << ", _this = " << FormatIntHex(~_this) << ", " << UPP::Name(_this)); focusCtrl = _this; focusCtrlWnd = topwindow; DoKillFocus(pfocusCtrl, _this); LLOG("SetFocus 2"); DoDeactivate(pfocusCtrl, _this); DoSetFocus(pfocusCtrl, _this, activate); if(topwindow) lastActiveWnd = topwindow; return true; }
/******************************************************************************************** > void OpMakeStroke::Do(OpDescriptor*) Author: Richard_Millican (Xara Group Ltd) <*****@*****.**> Created: 04/03/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Performs the MakeShapes operation. ********************************************************************************************/ void OpMakeStroke::Do(OpDescriptor*) { // Obtain the current selections Range Selection = *GetApplication()->FindSelection(); Node* CurrentNode = Selection.FindFirst(); BOOL Success = TRUE; ERROR3IF(CurrentNode == NULL, "Make shapes called with no nodes selected"); if (CurrentNode != NULL) // No nodes selected so End { // Try to record the selection state, don't render the blobs though if (Success) Success = DoStartSelOp(FALSE,FALSE); // First, Make Shapes on everything so they're all simple paths String_256 Desc("Building new stroke brush..."); Progress::Start(FALSE, &Desc); OpDescriptor *pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_MAKE_SHAPES); if (pOp != NULL) pOp->Invoke(); // Second, Group everything pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_GROUP); if (pOp != NULL) pOp->Invoke(); pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_GROUP); if (pOp != NULL) pOp->Invoke(); // Finally, create a new brush PathStrokerVector::BodgeRipSelection(/*(CommandIndex == 0) ? FALSE :*/ TRUE); Progress::Stop(); } if (!Success) { InformError(); FailAndExecute(); } End(); }
//============================================================================= // eTape::ParseTAP //----------------------------------------------------------------------------- bool eTape::ParseTAP(const void* data, size_t data_size) { const byte* ptr = (const byte*)data; CloseTape(); while(ptr < (const byte*)data + data_size) { dword size = Word(ptr); ptr += 2; if(!size) break; AllocInfocell(); Desc(ptr, size, tapeinfo[tape_infosize].desc); tape_infosize++; MakeBlock(ptr, size, 2168, 667, 735, 855, 1710, (*ptr < 4) ? 8064 : 3220, 1000); ptr += size; } FindTapeSizes(); return (ptr == (const byte*)data + data_size); }
void FIndirectLightingCache::InitDynamicRHI() { if (CanIndirectLightingCacheUseVolumeTexture()) { uint32 Flags = TexCreate_ShaderResource | TexCreate_NoTiling; FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::CreateVolumeDesc( CacheSize, CacheSize, CacheSize, PF_FloatRGBA, Flags, TexCreate_None, false, 1)); GRenderTargetPool.FindFreeElement(Desc, Texture0, TEXT("IndirectLightingCache_0")); GRenderTargetPool.FindFreeElement(Desc, Texture1, TEXT("IndirectLightingCache_1")); GRenderTargetPool.FindFreeElement(Desc, Texture2, TEXT("IndirectLightingCache_2")); } }
void FReflectionEnvironmentCubemapArray::InitDynamicRHI() { if (GetFeatureLevel() >= ERHIFeatureLevel::SM5) { const int32 NumReflectionCaptureMips = FMath::CeilLogTwo(GReflectionCaptureSize) + 1; ReleaseCubeArray(); FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::CreateCubemapDesc( GReflectionCaptureSize, //@todo - get rid of the alpha channel (currently stores brightness which is a constant), could use PF_FloatRGB for half memory, would need to implement RHIReadSurface support PF_FloatRGBA, TexCreate_None, TexCreate_None, false, // Cubemap array of 1 produces a regular cubemap, so guarantee it will be allocated as an array FMath::Max<uint32>(MaxCubemaps, 2), NumReflectionCaptureMips)); // Allocate TextureCubeArray for the scene's reflection captures GRenderTargetPool.FindFreeElement(Desc, ReflectionEnvs, TEXT("ReflectionEnvs")); } }
void FIndirectLightingCache::InitDynamicRHI() { if (CanIndirectLightingCacheUseVolumeTexture(GetFeatureLevel())) { FRHICommandListImmediate& RHICmdList = FRHICommandListExecutor::GetImmediateCommandList(); uint32 Flags = TexCreate_ShaderResource | TexCreate_NoTiling; FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::CreateVolumeDesc( CacheSize, CacheSize, CacheSize, PF_FloatRGBA, FClearValueBinding::None, Flags, TexCreate_None, false, 1)); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, Texture0, TEXT("IndirectLightingCache_0")); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, Texture1, TEXT("IndirectLightingCache_1")); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, Texture2, TEXT("IndirectLightingCache_2")); } }
void Button::AddAction( Json::Value& TriggerAction ) { if( !TriggerAction.isArray() ) { return; } size_t const NumActions = TriggerAction.size(); if( !NumActions ) { return; } ActionDesc Desc( this ); if( !Json::GetStr( TriggerAction[0], Desc.mAction ) ) { return; } boost::algorithm::replace_first( Desc.mAction, "#", "ui." ); boost::algorithm::erase_all( Desc.mAction, "%" ); if( NumActions == 2 ) { Json::Value& Arg = TriggerAction[1]; if( Arg.isInt() ) { Desc.mArg = ( int32_t )Arg.asInt(); } else if( Arg.isDouble() ) { Desc.mArg = Arg.asDouble(); } else if( Arg.isString() ) { Desc.mArg = Arg.asString(); } } mActions.push_back( Desc ); }
void BuildHZB( FRHICommandListImmediate& RHICmdList, FViewInfo& View ) { QUICK_SCOPE_CYCLE_COUNTER(STAT_BuildHZB); // View.ViewRect.{Width,Height}() are most likely to be < 2^24, so the float // conversion won't loss any precision (assuming float have 23bits for mantissa) const int32 NumMipsX = FMath::Max(FPlatformMath::CeilToInt(FMath::Log2(float(View.ViewRect.Width()))) - 1, 1); const int32 NumMipsY = FMath::Max(FPlatformMath::CeilToInt(FMath::Log2(float(View.ViewRect.Height()))) - 1, 1); const uint32 NumMips = FMath::Max(NumMipsX, NumMipsY); // Must be power of 2 const FIntPoint HZBSize( 1 << NumMipsX, 1 << NumMipsY ); View.HZBMipmap0Size = HZBSize; FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(HZBSize, PF_R16F, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource | TexCreate_NoFastClear, false, NumMips)); Desc.Flags |= TexCreate_FastVRAM; GRenderTargetPool.FindFreeElement(RHICmdList, Desc, View.HZB, TEXT("HZB") ); FSceneRenderTargetItem& HZBRenderTarget = View.HZB->GetRenderTargetItem(); FTextureRHIParamRef HZBRenderTargetRef = HZBRenderTarget.TargetableTexture.GetReference(); // Mip 0 { SCOPED_DRAW_EVENTF(RHICmdList, BuildHZB, TEXT("HZB SetupMip 0 %dx%d"), HZBSize.X, HZBSize.Y); SetRenderTarget(RHICmdList, HZBRenderTarget.TargetableTexture, 0, NULL); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false, CF_Always >::GetRHI()); TShaderMapRef< FPostProcessVS > VertexShader(View.ShaderMap); TShaderMapRef< THZBBuildPS<0> > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); // Imperfect sampling, doesn't matter too much PixelShader->SetParameters( RHICmdList, View ); RHICmdList.SetViewport(0, 0, 0.0f, HZBSize.X, HZBSize.Y, 1.0f); DrawRectangle( RHICmdList, 0, 0, HZBSize.X, HZBSize.Y, View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), HZBSize, FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY(), *VertexShader, EDRF_UseTriangleOptimization); //Use RWBarrier since we don't transition individual subresources. Basically treat the whole texture as R/W as we walk down the mip chain. RHICmdList.TransitionResources(EResourceTransitionAccess::ERWSubResBarrier, &HZBRenderTargetRef, 1); } FIntPoint SrcSize = HZBSize; FIntPoint DstSize = SrcSize / 2; SCOPED_DRAW_EVENTF(RHICmdList, BuildHZB, TEXT("HZB SetupMips 1..%d %dx%d Mips:%d"), NumMips - 1, DstSize.X, DstSize.Y); // Downsampling... for( uint8 MipIndex = 1; MipIndex < NumMips; MipIndex++ ) { DstSize.X = FMath::Max(DstSize.X, 1); DstSize.Y = FMath::Max(DstSize.Y, 1); SetRenderTarget(RHICmdList, HZBRenderTarget.TargetableTexture, MipIndex, NULL); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false, CF_Always >::GetRHI()); TShaderMapRef< FPostProcessVS > VertexShader(View.ShaderMap); TShaderMapRef< THZBBuildPS<1> > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, SrcSize, HZBRenderTarget.MipSRVs[ MipIndex - 1 ] ); RHICmdList.SetViewport(0, 0, 0.0f, DstSize.X, DstSize.Y, 1.0f); DrawRectangle( RHICmdList, 0, 0, DstSize.X, DstSize.Y, 0, 0, SrcSize.X, SrcSize.Y, DstSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); SrcSize /= 2; DstSize /= 2; //Use ERWSubResBarrier since we don't transition individual subresources. Basically treat the whole texture as R/W as we walk down the mip chain. RHICmdList.TransitionResources(EResourceTransitionAccess::ERWSubResBarrier, &HZBRenderTargetRef, 1); } GRenderTargetPool.VisualizeTexture.SetCheckPoint( RHICmdList, View.HZB ); }
void FRCPassPostProcessVelocityScatter::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PassPostProcessVelocityScatter); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = FIntRect::DivideAndRoundUp(View.ViewRect, ScaleFactor); FIntRect DestRect = SrcRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); TRefCountPtr<IPooledRenderTarget> DepthTarget; FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( DestRect.Size(), PF_ShadowDepth, TexCreate_None, TexCreate_DepthStencilTargetable, false ) ); GRenderTargetPool.FindFreeElement( Desc, DepthTarget, TEXT("VelocityScatterDepth") ); // Set the view family's render target/viewport. SetRenderTarget( Context.RHICmdList, DestRenderTarget.TargetableTexture, DepthTarget->GetRenderTargetItem().TargetableTexture ); Context.RHICmdList.Clear( true, FLinearColor::Black, true, 0.0f, false, 0, FIntRect() ); Context.SetViewportAndCallRHI(SrcRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_Greater>::GetRHI()); TShaderMapRef< FPostProcessVelocityScatterVS > VertexShader(Context.GetShaderMap()); TShaderMapRef< FPostProcessVelocityScatterPS > PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); FIntPoint TileCount = SrcRect.Size(); VertexShader->SetParameters( Context, TileCount ); PixelShader->SetParameters( Context ); // needs to be the same on shader side (faster on NVIDIA and AMD) int32 QuadsPerInstance = 8; Context.RHICmdList.SetStreamSource(0, NULL, 0, 0); Context.RHICmdList.DrawIndexedPrimitive(GScatterQuadIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 32, 0, 2 * QuadsPerInstance, FMath::DivideAndRoundUp(TileCount.X * TileCount.Y, QuadsPerInstance)); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessDeferredDecals::Process(FRenderingCompositePassContext& Context) { FRHICommandListImmediate& RHICmdList = Context.RHICmdList; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const bool bShaderComplexity = Context.View.Family->EngineShowFlags.ShaderComplexity; const bool bDBuffer = IsDBufferEnabled(); const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0; SCOPED_DRAW_EVENTF(RHICmdList, DeferredDecals, TEXT("DeferredDecals %s"), GetStageName(CurrentStage)); if (CurrentStage == DRS_BeforeBasePass) { // before BasePass, only if DBuffer is enabled check(bDBuffer); FPooledRenderTargetDesc GBufferADesc; SceneContext.GetGBufferADesc(GBufferADesc); // DBuffer: Decal buffer FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(GBufferADesc.Extent, PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_ShaderResource | TexCreate_RenderTargetable, false, 1, true, true)); if (!SceneContext.DBufferA) { Desc.ClearValue = FClearValueBinding::Black; GRenderTargetPool.FindFreeElement(RHICmdList, Desc, SceneContext.DBufferA, TEXT("DBufferA")); } if (!SceneContext.DBufferB) { Desc.ClearValue = FClearValueBinding(FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1)); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, SceneContext.DBufferB, TEXT("DBufferB")); } Desc.Format = PF_R8G8; if (!SceneContext.DBufferC) { Desc.ClearValue = FClearValueBinding(FLinearColor(0, 1, 0, 1)); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, SceneContext.DBufferC, TEXT("DBufferC")); } // we assume views are non overlapping, then we need to clear only once in the beginning, otherwise we would need to set scissor rects // and don't get FastClear any more. bool bFirstView = Context.View.Family->Views[0] == &Context.View; if (bFirstView) { SCOPED_DRAW_EVENT(RHICmdList, DBufferClear); FRHIRenderTargetView RenderTargets[3]; RenderTargets[0] = FRHIRenderTargetView(SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[1] = FRHIRenderTargetView(SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[2] = FRHIRenderTargetView(SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); FRHIDepthRenderTargetView DepthView(SceneContext.GetSceneDepthTexture(), ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, FExclusiveDepthStencil(FExclusiveDepthStencil::DepthRead_StencilWrite)); FRHISetRenderTargetsInfo Info(3, RenderTargets, DepthView); RHICmdList.SetRenderTargetsAndClear(Info); } } // this cast is safe as only the dedicated server implements this differently and this pass should not be executed on the dedicated server const FViewInfo& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); bool bHasValidDBufferMask = false; if(ViewFamily.EngineShowFlags.Decals) { if(CurrentStage == DRS_BeforeBasePass || CurrentStage == DRS_BeforeLighting) { RenderMeshDecals(Context, CurrentStage); } FScene& Scene = *(FScene*)ViewFamily.Scene; //don't early return. Resolves must be run for fast clears to work. if (Scene.Decals.Num()) { FDecalRenderTargetManager RenderTargetManager(RHICmdList, Context.GetShaderPlatform(), CurrentStage); // Build a list of decals that need to be rendered for this view FTransientDecalRenderDataList SortedDecals; FDecalRendering::BuildVisibleDecalList(Scene, View, CurrentStage, SortedDecals); if (SortedDecals.Num() > 0) { SCOPED_DRAW_EVENTF(RHICmdList, DeferredDecalsInner, TEXT("DeferredDecalsInner %d/%d"), SortedDecals.Num(), Scene.Decals.Num()); // optimization to have less state changes EDecalRasterizerState LastDecalRasterizerState = DRS_Undefined; FDecalDepthState LastDecalDepthState; int32 LastDecalBlendMode = -1; int32 LastDecalHasNormal = -1; // Decal state can change based on its normal property.(SM5) FDecalRenderingCommon::ERenderTargetMode LastRenderTargetMode = FDecalRenderingCommon::RTM_Unknown; const ERHIFeatureLevel::Type SMFeatureLevel = Context.GetFeatureLevel(); SCOPED_DRAW_EVENT(RHICmdList, Decals); INC_DWORD_STAT_BY(STAT_Decals, SortedDecals.Num()); for (int32 DecalIndex = 0, DecalCount = SortedDecals.Num(); DecalIndex < DecalCount; DecalIndex++) { const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex]; const FDeferredDecalProxy& DecalProxy = *DecalData.DecalProxy; const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale(); const FMatrix FrustumComponentToClip = FDecalRendering::ComputeComponentToClipMatrix(View, ComponentToWorldMatrix); EDecalBlendMode DecalBlendMode = DecalData.DecalBlendMode; EDecalRenderStage LocalDecalStage = FDecalRenderingCommon::ComputeRenderStage(View.GetShaderPlatform(), DecalBlendMode); bool bStencilThisDecal = IsStencilOptimizationAvailable(LocalDecalStage); FDecalRenderingCommon::ERenderTargetMode CurrentRenderTargetMode = FDecalRenderingCommon::ComputeRenderTargetMode(View.GetShaderPlatform(), DecalBlendMode, DecalData.bHasNormal); if (bShaderComplexity) { CurrentRenderTargetMode = FDecalRenderingCommon::RTM_SceneColor; // we want additive blending for the ShaderComplexity mode DecalBlendMode = DBM_Emissive; } // Here we assume that GBuffer can only be WorldNormal since it is the only GBufferTarget handled correctly. if (RenderTargetManager.bGufferADirty && DecalData.MaterialResource->NeedsGBuffer()) { RHICmdList.CopyToResolveTarget(SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture, SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture, true, FResolveParams()); RenderTargetManager.TargetsToResolve[FDecalRenderTargetManager::GBufferAIndex] = nullptr; RenderTargetManager.bGufferADirty = false; } // fewer rendertarget switches if possible if (CurrentRenderTargetMode != LastRenderTargetMode) { LastRenderTargetMode = CurrentRenderTargetMode; RenderTargetManager.SetRenderTargetMode(CurrentRenderTargetMode, DecalData.bHasNormal); Context.SetViewportAndCallRHI(Context.View.ViewRect); } bool bThisDecalUsesStencil = false; if (bStencilThisDecal && bStencilSizeThreshold) { // note this is after a SetStreamSource (in if CurrentRenderTargetMode != LastRenderTargetMode) call as it needs to get the VB input bThisDecalUsesStencil = RenderPreStencil(Context, ComponentToWorldMatrix, FrustumComponentToClip); LastDecalRasterizerState = DRS_Undefined; LastDecalDepthState = FDecalDepthState(); LastDecalBlendMode = -1; } const bool bBlendStateChange = DecalBlendMode != LastDecalBlendMode;// Has decal mode changed. const bool bDecalNormalChanged = GSupportsSeparateRenderTargetBlendState && // has normal changed for SM5 stain/translucent decals? (DecalBlendMode == DBM_Translucent || DecalBlendMode == DBM_Stain) && (int32)DecalData.bHasNormal != LastDecalHasNormal; // fewer blend state changes if possible if (bBlendStateChange || bDecalNormalChanged) { LastDecalBlendMode = DecalBlendMode; LastDecalHasNormal = (int32)DecalData.bHasNormal; SetDecalBlendState(RHICmdList, SMFeatureLevel, CurrentStage, (EDecalBlendMode)LastDecalBlendMode, DecalData.bHasNormal); } // todo const float ConservativeRadius = DecalData.ConservativeRadius; // const int32 IsInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f) + ( bThisDecalUsesStencil ) ? 2 : 0; const bool bInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f); // const bool bInsideDecal = !(IsInsideDecal & 1); // update rasterizer state if needed { bool bReverseHanded = false; { // Account for the reversal of handedness caused by negative scale on the decal const auto& Scale3d = DecalProxy.ComponentTrans.GetScale3D(); bReverseHanded = Scale3d[0] * Scale3d[1] * Scale3d[2] < 0.f; } EDecalRasterizerState DecalRasterizerState = ComputeDecalRasterizerState(bInsideDecal, bReverseHanded, View); if (LastDecalRasterizerState != DecalRasterizerState) { LastDecalRasterizerState = DecalRasterizerState; SetDecalRasterizerState(DecalRasterizerState, RHICmdList); } } // update DepthStencil state if needed { FDecalDepthState DecalDepthState = ComputeDecalDepthState(LocalDecalStage, bInsideDecal, bThisDecalUsesStencil); if (LastDecalDepthState != DecalDepthState) { LastDecalDepthState = DecalDepthState; SetDecalDepthState(DecalDepthState, RHICmdList); } } FDecalRendering::SetShader(RHICmdList, View, DecalData, FrustumComponentToClip); RHICmdList.DrawIndexedPrimitive(GetUnitCubeIndexBuffer(), PT_TriangleList, 0, 0, 8, 0, ARRAY_COUNT(GCubeIndices) / 3, 1); RenderTargetManager.bGufferADirty |= (RenderTargetManager.TargetsToResolve[FDecalRenderTargetManager::GBufferAIndex] != nullptr); } // we don't modify stencil but if out input was having stencil for us (after base pass - we need to clear) // Clear stencil to 0, which is the assumed default by other passes RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); } if (CurrentStage == DRS_BeforeBasePass) { // combine DBuffer RTWriteMasks; will end up in one texture we can load from in the base pass PS and decide whether to do the actual work or not RenderTargetManager.FlushMetaData(); if (GSupportsRenderTargetWriteMask) { DecodeRTWriteMask(Context); bHasValidDBufferMask = true; } } RenderTargetManager.ResolveTargets(); } if (CurrentStage == DRS_BeforeBasePass) { // before BasePass GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferC); } } if (CurrentStage == DRS_BeforeBasePass && !bHasValidDBufferMask) { // Return the DBufferMask to the render target pool. // FDeferredPixelShaderParameters will fall back to setting a white dummy mask texture. // This allows us to ignore the DBufferMask on frames without decals, without having to explicitly clear the texture. SceneContext.DBufferMask = nullptr; } }
void FHZBOcclusionTester::Submit(FRHICommandListImmediate& RHICmdList, const FViewInfo& View) { SCOPED_DRAW_EVENT(RHICmdList, SubmitHZB); FSceneViewState* ViewState = (FSceneViewState*)View.State; if( !ViewState ) { return; } TRefCountPtr< IPooledRenderTarget > BoundsCenterTexture; TRefCountPtr< IPooledRenderTarget > BoundsExtentTexture; { uint32 Flags = TexCreate_ShaderResource | TexCreate_Dynamic; FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( FIntPoint( SizeX, SizeY ), PF_A32B32G32R32F, FClearValueBinding::None, Flags, TexCreate_None, false ) ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, BoundsCenterTexture, TEXT("HZBBoundsCenter") ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, BoundsExtentTexture, TEXT("HZBBoundsExtent") ); } TRefCountPtr< IPooledRenderTarget > ResultsTextureGPU; { FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( FIntPoint( SizeX, SizeY ), PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable, false ) ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, ResultsTextureGPU, TEXT("HZBResultsGPU") ); } { #if 0 static float CenterBuffer[ SizeX * SizeY ][4]; static float ExtentBuffer[ SizeX * SizeY ][4]; FMemory::Memset( CenterBuffer, 0, sizeof( CenterBuffer ) ); FMemory::Memset( ExtentBuffer, 0, sizeof( ExtentBuffer ) ); const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i++ ) { const FOcclusionPrimitive& Primitive = Primitives[i]; CenterBuffer[i][0] = Primitive.Center.X; CenterBuffer[i][1] = Primitive.Center.Y; CenterBuffer[i][2] = Primitive.Center.Z; CenterBuffer[i][3] = 0.0f; ExtentBuffer[i][0] = Primitive.Extent.X; ExtentBuffer[i][1] = Primitive.Extent.Y; ExtentBuffer[i][2] = Primitive.Extent.Z; ExtentBuffer[i][3] = 1.0f; } FUpdateTextureRegion2D Region( 0, 0, 0, 0, SizeX, SizeY ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)ExtentBuffer ); #elif 0 static float CenterBuffer[ SizeX * SizeY ][4]; static float ExtentBuffer[ SizeX * SizeY ][4]; { QUICK_SCOPE_CYCLE_COUNTER(STAT_HZBPackPrimitiveData); FMemory::Memset( CenterBuffer, 0, sizeof( CenterBuffer ) ); FMemory::Memset( ExtentBuffer, 0, sizeof( ExtentBuffer ) ); const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i++ ) { const FOcclusionPrimitive& Primitive = Primitives[i]; uint32 x = FMath::ReverseMortonCode2( i >> 0 ); uint32 y = FMath::ReverseMortonCode2( i >> 1 ); uint32 m = x + y * SizeX; CenterBuffer[m][0] = Primitive.Center.X; CenterBuffer[m][1] = Primitive.Center.Y; CenterBuffer[m][2] = Primitive.Center.Z; CenterBuffer[m][3] = 0.0f; ExtentBuffer[m][0] = Primitive.Extent.X; ExtentBuffer[m][1] = Primitive.Extent.Y; ExtentBuffer[m][2] = Primitive.Extent.Z; ExtentBuffer[m][3] = 1.0f; } } QUICK_SCOPE_CYCLE_COUNTER(STAT_HZBUpdateTextures); FUpdateTextureRegion2D Region( 0, 0, 0, 0, SizeX, SizeY ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)ExtentBuffer ); #else // Update in blocks to avoid large update const uint32 BlockSize = 8; const uint32 SizeInBlocksX = SizeX / BlockSize; const uint32 SizeInBlocksY = SizeY / BlockSize; const uint32 BlockStride = BlockSize * 4 * sizeof( float ); float CenterBuffer[ BlockSize * BlockSize ][4]; float ExtentBuffer[ BlockSize * BlockSize ][4]; const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i += BlockSize * BlockSize ) { const uint32 BlockEnd = FMath::Min( BlockSize * BlockSize, NumPrimitives - i ); for( uint32 b = 0; b < BlockEnd; b++ ) { const FOcclusionPrimitive& Primitive = Primitives[ i + b ]; CenterBuffer[b][0] = Primitive.Center.X; CenterBuffer[b][1] = Primitive.Center.Y; CenterBuffer[b][2] = Primitive.Center.Z; CenterBuffer[b][3] = 0.0f; ExtentBuffer[b][0] = Primitive.Extent.X; ExtentBuffer[b][1] = Primitive.Extent.Y; ExtentBuffer[b][2] = Primitive.Extent.Z; ExtentBuffer[b][3] = 1.0f; } // Clear rest of block if( BlockEnd < BlockSize * BlockSize ) { FMemory::Memset( (float*)CenterBuffer + BlockEnd * 4, 0, sizeof( CenterBuffer ) - BlockEnd * 4 * sizeof(float) ); FMemory::Memset( (float*)ExtentBuffer + BlockEnd * 4, 0, sizeof( ExtentBuffer ) - BlockEnd * 4 * sizeof(float) ); } const int32 BlockIndex = i / (BlockSize * BlockSize); const int32 BlockX = BlockIndex % SizeInBlocksX; const int32 BlockY = BlockIndex / SizeInBlocksY; FUpdateTextureRegion2D Region( BlockX * BlockSize, BlockY * BlockSize, 0, 0, BlockSize, BlockSize ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, BlockStride, (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, BlockStride, (uint8*)ExtentBuffer ); } #endif Primitives.Empty(); } // Draw test { SCOPED_DRAW_EVENT(RHICmdList, TestHZB); SetRenderTarget(RHICmdList, ResultsTextureGPU->GetRenderTargetItem().TargetableTexture, NULL); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false, CF_Always >::GetRHI()); TShaderMapRef< FScreenVS > VertexShader(View.ShaderMap); TShaderMapRef< FHZBTestPS > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture ); RHICmdList.SetViewport(0, 0, 0.0f, SizeX, SizeY, 1.0f); // TODO draw quads covering blocks added above DrawRectangle( RHICmdList, 0, 0, SizeX, SizeY, 0, 0, SizeX, SizeY, FIntPoint( SizeX, SizeY ), FIntPoint( SizeX, SizeY ), *VertexShader, EDRF_UseTriangleOptimization); } GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, ResultsTextureGPU); // Transfer memory GPU -> CPU RHICmdList.CopyToResolveTarget(ResultsTextureGPU->GetRenderTargetItem().TargetableTexture, ResultsTextureCPU->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams()); }
void RendererGPUBenchmark(FSynthBenchmarkResults& InOut, const FSceneView& View, uint32 WorkScale, bool bDebugOut) { check(IsInRenderingThread()); // two RT to ping pong so we force the GPU to flush it's pipeline TRefCountPtr<IPooledRenderTarget> RTItems[3]; { FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(FIntPoint(GBenchmarkResolution, GBenchmarkResolution), PF_B8G8R8A8, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource, false)); GRenderTargetPool.FindFreeElement(Desc, RTItems[0], TEXT("Benchmark0")); GRenderTargetPool.FindFreeElement(Desc, RTItems[1], TEXT("Benchmark1")); Desc.Extent = FIntPoint(1, 1); Desc.Flags = TexCreate_CPUReadback; // needs TexCreate_ResolveTargetable? Desc.TargetableFlags = TexCreate_None; GRenderTargetPool.FindFreeElement(Desc, RTItems[2], TEXT("BenchmarkReadback")); } // set the state RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); { // larger number means more accuracy but slower, some slower GPUs might timeout with a number to large const uint32 IterationCount = 70; const uint32 MethodCount = ARRAY_COUNT(InOut.GPUStats); // 0 / 1 uint32 DestRTIndex = 0; const uint32 TimerSampleCount = IterationCount * MethodCount + 1; static FRenderQueryRHIRef TimerQueries[TimerSampleCount]; static uint32 PassCount[IterationCount]; for(uint32 i = 0; i < TimerSampleCount; ++i) { TimerQueries[i] = GTimerQueryPool.AllocateQuery(); } if(!TimerQueries[0]) { UE_LOG(LogSynthBenchmark, Warning, TEXT("GPU driver does not support timer queries.")); } // TimingValues are in Seconds per GPixel FTimingSeries TimingSeries[MethodCount]; for(uint32 MethodIterator = 0; MethodIterator < MethodCount; ++MethodIterator) { TimingSeries[MethodIterator].Init(IterationCount); } check(MethodCount == 5); InOut.GPUStats[0] = FSynthBenchmarkStat(TEXT("ALUHeavyNoise"), 1.0f / 4.601f, TEXT("s/GigaPix")); InOut.GPUStats[1] = FSynthBenchmarkStat(TEXT("TexHeavy"), 1.0f / 7.447f, TEXT("s/GigaPix")); InOut.GPUStats[2] = FSynthBenchmarkStat(TEXT("DepTexHeavy"), 1.0f / 3.847f, TEXT("s/GigaPix")); InOut.GPUStats[3] = FSynthBenchmarkStat(TEXT("FillOnly"), 1.0f / 25.463f, TEXT("s/GigaPix")); InOut.GPUStats[4] = FSynthBenchmarkStat(TEXT("Bandwidth"), 1.0f / 1.072f, TEXT("s/GigaPix")); // e.g. on NV670: Method3 (mostly fill rate )-> 26GP/s (seems realistic) // reference: http://en.wikipedia.org/wiki/Comparison_of_Nvidia_graphics_processing_units theoretical: 29.3G/s RHIEndRenderQuery(TimerQueries[0]); // multiple iterations to see how trust able the values are for(uint32 Iteration = 0; Iteration < IterationCount; ++Iteration) { for(uint32 MethodIterator = 0; MethodIterator < MethodCount; ++MethodIterator) { // alternate between forward and backward (should give the same number) // uint32 MethodId = (Iteration % 2) ? MethodIterator : (MethodCount - 1 - MethodIterator); uint32 MethodId = MethodIterator; uint32 QueryIndex = 1 + Iteration * MethodCount + MethodId; // 0 / 1 const uint32 SrcRTIndex = 1 - DestRTIndex; GRenderTargetPool.VisualizeTexture.SetCheckPoint(RTItems[DestRTIndex]); RHISetRenderTarget(RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, FTextureRHIRef()); // decide how much work we do in this pass PassCount[Iteration] = (Iteration / 10 + 1) * WorkScale; RunBenchmarkShader(View, MethodId, RTItems[SrcRTIndex], PassCount[Iteration]); RHICopyToResolveTarget(RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, RTItems[DestRTIndex]->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams()); /*if(bGPUCPUSync) { // more consistent timing but strangely much faster to the level that is unrealistic FResolveParams Param; Param.Rect = FResolveRect(0, 0, 1, 1); RHICopyToResolveTarget( RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, RTItems[2]->GetRenderTargetItem().ShaderResourceTexture, false, Param); void* Data = 0; int Width = 0; int Height = 0; RHIMapStagingSurface(RTItems[2]->GetRenderTargetItem().ShaderResourceTexture, Data, Width, Height); RHIUnmapStagingSurface(RTItems[2]->GetRenderTargetItem().ShaderResourceTexture); }*/ RHIEndRenderQuery(TimerQueries[QueryIndex]); // ping pong DestRTIndex = 1 - DestRTIndex; } } { uint64 OldAbsTime = 0; RHIGetRenderQueryResult(TimerQueries[0], OldAbsTime, true); GTimerQueryPool.ReleaseQuery(TimerQueries[0]); #if !UE_BUILD_SHIPPING FBenchmarkGraph BenchmarkGraph(IterationCount, IterationCount, *(FPaths::ScreenShotDir() + TEXT("GPUSynthBenchmarkGraph.bmp"))); #endif for(uint32 Iteration = 0; Iteration < IterationCount; ++Iteration) { uint32 Results[MethodCount]; for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { uint32 QueryIndex = 1 + Iteration * MethodCount + MethodId; uint64 AbsTime; RHIGetRenderQueryResult(TimerQueries[QueryIndex], AbsTime, true); GTimerQueryPool.ReleaseQuery(TimerQueries[QueryIndex]); Results[MethodId] = AbsTime - OldAbsTime; OldAbsTime = AbsTime; } double SamplesInGPix = PassCount[Iteration] * GBenchmarkResolution * GBenchmarkResolution / 1000000000.0; for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { double TimeInSec = Results[MethodId] / 1000000.0; double TimingValue = TimeInSec / SamplesInGPix; // TimingValue in Seconds per GPixel TimingSeries[MethodId].SetEntry(Iteration, (float)TimingValue); } #if !UE_BUILD_SHIPPING { // This is for debugging and we don't want to change the output but we still use "InOut". // That shouldn't hurt, as we override the values after that anyway. for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { InOut.GPUStats[MethodId].SetMeasuredTime(TimingSeries[MethodId].GetEntry(Iteration)); } float LocalGPUIndex = InOut.ComputeGPUPerfIndex(); // * 0.01 to get it in 0..1 range // * 0.5f to have 100 is the middle BenchmarkGraph.DrawBar(Iteration, LocalGPUIndex * 0.01f * 0.5f); } #endif } for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { float Confidence = 0.0f; float TimingValue = TimingSeries[MethodId].ComputeValue(Confidence); if(Confidence > 0) { InOut.GPUStats[MethodId].SetMeasuredTime(TimingValue, Confidence); } UE_LOG(LogSynthBenchmark, Display, TEXT(" ... %.3f GigaPix/s, Confidence=%.0f%% '%s'"), 1.0f / InOut.GPUStats[MethodId].GetMeasuredTime(), Confidence, InOut.GPUStats[MethodId].GetDesc()); } UE_LOG(LogSynthBenchmark, Display, TEXT("")); #if !UE_BUILD_SHIPPING if(bDebugOut) { BenchmarkGraph.Save(); } #endif } } }
void TopWindow::Open(Ctrl *owner) { LLOG("TopWindow::Open"); GuiLock __; if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1)) DistributeAccessKeys(); USRLOG(" OPEN " + Desc(this)); LLOG("OPEN " << Name() << " owner: " << UPP::Name(owner)); IgnoreMouseUp(); bool weplace = owner && center == 1 || center == 2 || !GetRect().IsEmpty(); if(fullscreen) SetRect(0, 0, Xwidth, Xheight); else CenterRect(owner); LLOG("Open NextRequest " << NextRequest(Xdisplay)); Create(owner, false, false); XSetWMProperties (Xdisplay, GetWindow(), NULL, NULL, NULL, 0, NULL, NULL, NULL); xminsize.cx = xmaxsize.cx = Null; title2.Clear(); if(!weplace) { LLOG("SyncCaption"); SyncCaption(); } LLOG("SyncSizeHints"); size_hints->flags = 0; SyncSizeHints(); Rect r = GetRect(); size_hints->x = r.left; size_hints->y = r.top; size_hints->width = r.Width(); size_hints->height = r.Height(); size_hints->win_gravity = StaticGravity; size_hints->flags |= PPosition|PSize|PWinGravity; if(owner) { ASSERT(owner->IsOpen()); LLOG("XSetTransientForHint"); XSetTransientForHint(Xdisplay, GetWindow(), owner->GetWindow()); } LLOG("XSetWMNormalHints"); XSetWMNormalHints(Xdisplay, GetWindow(), size_hints); Atom protocols[3]; protocols[0] = XAtom("WM_DELETE_WINDOW"); protocols[1] = XAtom("WM_TAKE_FOCUS"); protocols[2] = XAtom("_NET_WM_PING"); LLOG("XSetWMProtocols"); XSetWMProtocols(Xdisplay, GetWindow(), protocols, 3); String x = GetExeTitle().ToString(); const char *progname = ~x; class_hint->res_name = (char *)progname; class_hint->res_class = (char *)progname; XSetClassHint(Xdisplay, GetWindow(), class_hint); LLOG("WndShow(" << visible << ")"); WndShow(visible); if(visible) { XEvent e; LLOG("XWindowEvent"); XWindowEvent(Xdisplay, top->window, VisibilityChangeMask, &e); ignoretakefocus = true; SetTimeCallback(500, THISBACK(EndIgnoreTakeFocus)); LLOG("SetWndFocus"); SetWndFocus(); for(int i = 0; i < 50; i++) { // X11 tries to move our window, so ignore the first set of ConfigureNotify // and move the window into position after FocusIn - but not if we want WM to // place the window if(weplace) while(XCheckTypedWindowEvent(Xdisplay, top->window, ConfigureNotify, &e)) { if(e.xconfigure.window != top->window) ProcessEvent(&e); } if(XCheckTypedWindowEvent(Xdisplay, top->window, FocusIn, &e)) { ProcessEvent(&e); if(e.xfocus.window == top->window) break; } Sleep(10); } } if(weplace) { WndSetPos(GetRect()); LLOG("SyncCaption"); SyncCaption(); } LLOG(">Open NextRequest " << NextRequest(Xdisplay)); LLOG(">OPENED " << Name()); PlaceFocus(); StateH(OPEN); Vector<int> fe = GetPropertyInts(top->window, XAtom("_NET_FRAME_EXTENTS")); if(fe.GetCount() >= 4 && fe[0] >= 0 && fe[0] <= 16 && fe[1] >= 0 && fe[1] <= 16 && //fluxbox returns wrong numbers - quick&dirty workaround fe[2] >= 0 && fe[2] <= 64 && fe[3] >= 0 && fe[3] <= 48) { GuiLock __; windowFrameMargin.left = max(windowFrameMargin.left, fe[0]); windowFrameMargin.right = max(windowFrameMargin.right, fe[1]); windowFrameMargin.top = max(windowFrameMargin.top, fe[2]); windowFrameMargin.bottom = max(windowFrameMargin.bottom, fe[3]); } if(IsOpen() && top) top->owner = owner; long curr_pid = getpid(); static Window wm_client_leader; ONCELOCK { wm_client_leader = XCreateSimpleWindow(Xdisplay, Xroot, 0, 0, 1, 1, 0, 0, 0); XChangeProperty(Xdisplay, wm_client_leader, XAtom("WM_CLIENT_LEADER"), XA_WINDOW, 32, PropModeReplace, (byte *)&wm_client_leader, 1); XChangeProperty(Xdisplay, wm_client_leader, XAtom("_NET_WM_PID"), XA_CARDINAL, 32, PropModeReplace, (byte *) &curr_pid, 1); } Window win = GetWindow(); XChangeProperty(Xdisplay, win, XAtom("_NET_WM_PID"), XA_CARDINAL, 32, PropModeReplace, (byte *) &curr_pid, 1); XChangeProperty(Xdisplay, win, XAtom("WM_CLIENT_LEADER"), XA_WINDOW, 32, PropModeReplace, (byte *)&wm_client_leader, 1); int version = 5; XChangeProperty(Xdisplay, win, XAtom("XdndAware"), XA_ATOM, 32, 0, (byte *)&version, 1); SyncState(); FixIcons(); }
void FRCPassPostProcessDeferredDecals::Process(FRenderingCompositePassContext& Context) { FRHICommandListImmediate& RHICmdList = Context.RHICmdList; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const bool bShaderComplexity = Context.View.Family->EngineShowFlags.ShaderComplexity; const bool bDBuffer = IsDBufferEnabled(); const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0; SCOPED_DRAW_EVENT(RHICmdList, PostProcessDeferredDecals); enum EDecalResolveBufferIndex { SceneColorIndex, GBufferAIndex, GBufferBIndex, GBufferCIndex, DBufferAIndex, DBufferBIndex, DBufferCIndex, ResolveBufferMax, }; FTextureRHIParamRef TargetsToResolve[ResolveBufferMax] = { nullptr }; if(DecalRenderStage == DRS_BeforeBasePass) { // before BasePass, only if DBuffer is enabled check(bDBuffer); // DBuffer: Decal buffer FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(SceneContext.GBufferA->GetDesc().Extent, PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_ShaderResource | TexCreate_RenderTargetable, false)); if(!SceneContext.DBufferA) { Desc.ClearValue = FClearValueBinding::Black; GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferA, TEXT("DBufferA")); } if(!SceneContext.DBufferB) { Desc.ClearValue = FClearValueBinding(FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1)); GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferB, TEXT("DBufferB")); } Desc.Format = PF_R8G8; if(!SceneContext.DBufferC) { Desc.ClearValue = FClearValueBinding(FLinearColor(0, 1, 0, 1)); GRenderTargetPool.FindFreeElement(Desc, SceneContext.DBufferC, TEXT("DBufferC")); } // we assume views are non overlapping, then we need to clear only once in the beginning, otherwise we would need to set scissor rects // and don't get FastClear any more. bool bFirstView = Context.View.Family->Views[0] == &Context.View; if(bFirstView) { SCOPED_DRAW_EVENT(RHICmdList, DBufferClear); FRHIRenderTargetView RenderTargets[3]; RenderTargets[0] = FRHIRenderTargetView(SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[1] = FRHIRenderTargetView(SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); RenderTargets[2] = FRHIRenderTargetView(SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture, 0, -1, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore); FRHIDepthRenderTargetView DepthView(SceneContext.GetSceneDepthSurface(), ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::ENoAction, FExclusiveDepthStencil(FExclusiveDepthStencil::DepthRead_StencilWrite)); FRHISetRenderTargetsInfo Info(3, RenderTargets, DepthView); RHICmdList.SetRenderTargetsAndClear(Info); TargetsToResolve[DBufferAIndex] = SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture; } } // this cast is safe as only the dedicated server implements this differently and this pass should not be executed on the dedicated server const FViewInfo& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FScene& Scene = *(FScene*)ViewFamily.Scene; //don't early return. Resolves must be run for fast clears to work. bool bRenderDecal = Scene.Decals.Num() && ViewFamily.EngineShowFlags.Decals; if (bRenderDecal) { // Build a list of decals that need to be rendered for this view FTransientDecalRenderDataList SortedDecals; FDecalRendering::BuildVisibleDecalList(Scene, View, DecalRenderStage, SortedDecals); if (SortedDecals.Num() > 0) { FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; bool bStencilDecalsInThisStage = true; #if DBUFFER_DONT_USE_STENCIL_YET if (DecalRenderStage != DRS_BeforeLighting) { bStencilDecalsInThisStage = false; } #endif // Setup a stencil mask to prevent certain pixels from receiving deferred decals if (bStencilDecalsInThisStage) { StencilDecalMask(RHICmdList, View, Context.HasHmdMesh()); } // optimization to have less state changes EDecalRasterizerState LastDecalRasterizerState = DRS_Undefined; FDecalDepthState LastDecalDepthState; int32 LastDecalBlendMode = -1; int32 LastDecalHasNormal = -1; // Decal state can change based on its normal property.(SM5) FDecalRendering::ERenderTargetMode LastRenderTargetMode = FDecalRendering::RTM_Unknown; const ERHIFeatureLevel::Type SMFeatureLevel = Context.GetFeatureLevel(); SCOPED_DRAW_EVENT(RHICmdList, Decals); INC_DWORD_STAT_BY(STAT_Decals, SortedDecals.Num()); for (int32 DecalIndex = 0, DecalCount = SortedDecals.Num(); DecalIndex < DecalCount; DecalIndex++) { const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex]; const FDeferredDecalProxy& DecalProxy = *DecalData.DecalProxy; const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale(); const FMatrix FrustumComponentToClip = FDecalRendering::ComputeComponentToClipMatrix(View, ComponentToWorldMatrix); EDecalBlendMode DecalBlendMode = DecalData.DecalBlendMode; bool bStencilThisDecal = bStencilDecalsInThisStage; #if DBUFFER_DONT_USE_STENCIL_YET if (FDecalRendering::ComputeRenderStage(View.GetShaderPlatform(), DecalBlendMode) != DRS_BeforeLighting) { bStencilThisDecal = false; } #endif FDecalRendering::ERenderTargetMode CurrentRenderTargetMode = FDecalRendering::ComputeRenderTargetMode(View.GetShaderPlatform(), DecalBlendMode); if (bShaderComplexity) { CurrentRenderTargetMode = FDecalRendering::RTM_SceneColor; // we want additive blending for the ShaderComplexity mode DecalBlendMode = DBM_Emissive; } // fewer rendertarget switches if possible if (CurrentRenderTargetMode != LastRenderTargetMode) { LastRenderTargetMode = CurrentRenderTargetMode; switch (CurrentRenderTargetMode) { case FDecalRendering::RTM_SceneColorAndGBuffer: { TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = SceneContext.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = SceneContext.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; case FDecalRendering::RTM_SceneColorAndGBufferDepthWrite: { TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = SceneContext.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = SceneContext.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthWrite_StencilWrite); } break; case FDecalRendering::RTM_GBufferNormal: TargetsToResolve[GBufferAIndex] = SceneContext.GBufferA->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[GBufferAIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case FDecalRendering::RTM_SceneColor: TargetsToResolve[SceneColorIndex] = SceneContext.GetSceneColor()->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[SceneColorIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case FDecalRendering::RTM_DBuffer: { TargetsToResolve[DBufferAIndex] = SceneContext.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = SceneContext.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = SceneContext.DBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 3, &TargetsToResolve[DBufferAIndex], SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; default: check(0); break; } Context.SetViewportAndCallRHI(DestRect); // we need to reset the stream source after any call to SetRenderTarget (at least for Metal, which doesn't queue up VB assignments) RHICmdList.SetStreamSource(0, GetUnitCubeVertexBuffer(), sizeof(FVector4), 0); } bool bThisDecalUsesStencil = false; if (bStencilThisDecal) { if (bStencilSizeThreshold) { // note this is after a SetStreamSource (in if CurrentRenderTargetMode != LastRenderTargetMode) call as it needs to get the VB input bThisDecalUsesStencil = RenderPreStencil(Context, ComponentToWorldMatrix, FrustumComponentToClip); LastDecalRasterizerState = DRS_Undefined; LastDecalDepthState = FDecalDepthState(); LastDecalBlendMode = -1; } } const bool bBlendStateChange = DecalBlendMode != LastDecalBlendMode;// Has decal mode changed. const bool bDecalNormalChanged = GSupportsSeparateRenderTargetBlendState && // has normal changed for SM5 stain/translucent decals? (DecalBlendMode == DBM_Translucent || DecalBlendMode == DBM_Stain) && (int32)DecalData.bHasNormal != LastDecalHasNormal; // fewer blend state changes if possible if (bBlendStateChange || bDecalNormalChanged) { LastDecalBlendMode = DecalBlendMode; LastDecalHasNormal = (int32)DecalData.bHasNormal; SetDecalBlendState(RHICmdList, SMFeatureLevel, DecalRenderStage, (EDecalBlendMode)LastDecalBlendMode, DecalData.bHasNormal); } // todo const float ConservativeRadius = DecalData.ConservativeRadius; // const int32 IsInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f) + ( bThisDecalUsesStencil ) ? 2 : 0; const bool bInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f); // const bool bInsideDecal = !(IsInsideDecal & 1); // update rasterizer state if needed { EDecalRasterizerState DecalRasterizerState = ComputeDecalRasterizerState(bInsideDecal, View); if (LastDecalRasterizerState != DecalRasterizerState) { LastDecalRasterizerState = DecalRasterizerState; SetDecalRasterizerState(DecalRasterizerState, RHICmdList); } } // update DepthStencil state if needed { FDecalDepthState DecalDepthState = ComputeDecalDepthState(DecalBlendMode, bInsideDecal, bStencilDecalsInThisStage, bThisDecalUsesStencil); if (LastDecalDepthState != DecalDepthState) { LastDecalDepthState = DecalDepthState; SetDecalDepthState(DecalDepthState, RHICmdList); } } FDecalRendering::SetShader(RHICmdList, View, bShaderComplexity, DecalData, FrustumComponentToClip); RHICmdList.DrawIndexedPrimitive(GetUnitCubeIndexBuffer(), PT_TriangleList, 0, 0, 8, 0, ARRAY_COUNT(GCubeIndices) / 3, 1); } // we don't modify stencil but if out input was having stencil for us (after base pass - we need to clear) // Clear stencil to 0, which is the assumed default by other passes RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); if (DecalRenderStage == DRS_BeforeBasePass) { // before BasePass GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.DBufferC); } } } // resolve the targets we wrote to. FResolveParams ResolveParams; for (int32 i = 0; i < ResolveBufferMax; ++i) { if (TargetsToResolve[i]) { RHICmdList.CopyToResolveTarget(TargetsToResolve[i], TargetsToResolve[i], true, ResolveParams); } } }
void RendererGPUBenchmark(FRHICommandListImmediate& RHICmdList, FSynthBenchmarkResults& InOut, const FSceneView& View, float WorkScale, bool bDebugOut) { check(IsInRenderingThread()); // two RT to ping pong so we force the GPU to flush it's pipeline TRefCountPtr<IPooledRenderTarget> RTItems[3]; { FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(FIntPoint(GBenchmarkResolution, GBenchmarkResolution), PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource, false)); GRenderTargetPool.FindFreeElement(Desc, RTItems[0], TEXT("Benchmark0")); GRenderTargetPool.FindFreeElement(Desc, RTItems[1], TEXT("Benchmark1")); Desc.Extent = FIntPoint(1, 1); Desc.Flags = TexCreate_CPUReadback; // needs TexCreate_ResolveTargetable? Desc.TargetableFlags = TexCreate_None; GRenderTargetPool.FindFreeElement(Desc, RTItems[2], TEXT("BenchmarkReadback")); } // set the state RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); { // larger number means more accuracy but slower, some slower GPUs might timeout with a number to large const uint32 IterationCount = 70; const uint32 MethodCount = ARRAY_COUNT(InOut.GPUStats); // 0 / 1 uint32 DestRTIndex = 0; const uint32 TimerSampleCount = IterationCount * MethodCount + 1; static FRenderQueryRHIRef TimerQueries[TimerSampleCount]; static float LocalWorkScale[IterationCount]; for(uint32 i = 0; i < TimerSampleCount; ++i) { TimerQueries[i] = GTimerQueryPool.AllocateQuery(); } const bool bSupportsTimerQueries = (TimerQueries[0] != NULL); if(!bSupportsTimerQueries) { UE_LOG(LogSynthBenchmark, Warning, TEXT("GPU driver does not support timer queries.")); // Temporary workaround for GL_TIMESTAMP being unavailable and GL_TIME_ELAPSED workaround breaking drivers #if PLATFORM_MAC GLint RendererID = 0; float PerfScale = 1.0f; [[NSOpenGLContext currentContext] getValues:&RendererID forParameter:NSOpenGLCPCurrentRendererID]; { switch((RendererID & kCGLRendererIDMatchingMask)) { case kCGLRendererATIRadeonX4000ID: // AMD 7xx0 & Dx00 series - should be pretty beefy PerfScale = 1.2f; break; case kCGLRendererATIRadeonX3000ID: // AMD 5xx0, 6xx0 series - mostly OK case kCGLRendererGeForceID: // Nvidia 6x0 & 7x0 series - mostly OK PerfScale = 2.0f; break; case kCGLRendererIntelHD5000ID: // Intel HD 5000, Iris, Iris Pro - not dreadful PerfScale = 4.2f; break; case kCGLRendererIntelHD4000ID: // Intel HD 4000 - quite slow PerfScale = 7.5f; break; case kCGLRendererATIRadeonX2000ID: // ATi 4xx0, 3xx0, 2xx0 - almost all very slow and drivers are now very buggy case kCGLRendererGeForce8xxxID: // Nvidia 3x0, 2x0, 1x0, 9xx0, 8xx0 - almost all very slow case kCGLRendererIntelHDID: // Intel HD 3000 - very, very slow and very buggy driver default: PerfScale = 10.0f; break; } } InOut.GPUStats[0] = FSynthBenchmarkStat(TEXT("ALUHeavyNoise"), 1.0f / 4.601f, TEXT("s/GigaPix")); InOut.GPUStats[1] = FSynthBenchmarkStat(TEXT("TexHeavy"), 1.0f / 7.447f, TEXT("s/GigaPix")); InOut.GPUStats[2] = FSynthBenchmarkStat(TEXT("DepTexHeavy"), 1.0f / 3.847f, TEXT("s/GigaPix")); InOut.GPUStats[3] = FSynthBenchmarkStat(TEXT("FillOnly"), 1.0f / 25.463f, TEXT("s/GigaPix")); InOut.GPUStats[4] = FSynthBenchmarkStat(TEXT("Bandwidth"), 1.0f / 1.072f, TEXT("s/GigaPix")); InOut.GPUStats[0].SetMeasuredTime( FTimeSample(PerfScale, PerfScale * (1.0f / 4.601f)) ); InOut.GPUStats[1].SetMeasuredTime( FTimeSample(PerfScale, PerfScale * (1.0f / 7.447f)) ); InOut.GPUStats[2].SetMeasuredTime( FTimeSample(PerfScale, PerfScale * (1.0f / 3.847f)) ); InOut.GPUStats[3].SetMeasuredTime( FTimeSample(PerfScale, PerfScale * (1.0f / 25.463f)) ); InOut.GPUStats[4].SetMeasuredTime( FTimeSample(PerfScale, PerfScale * (1.0f / 1.072f)) ); #endif return; } // TimingValues are in Seconds FTimingSeries TimingSeries[MethodCount]; // in 1/1000000 Seconds uint64 TotalTimes[MethodCount]; for(uint32 MethodIterator = 0; MethodIterator < MethodCount; ++MethodIterator) { TotalTimes[MethodIterator] = 0; TimingSeries[MethodIterator].Init(IterationCount); } check(MethodCount == 5); InOut.GPUStats[0] = FSynthBenchmarkStat(TEXT("ALUHeavyNoise"), 1.0f / 4.601f, TEXT("s/GigaPix")); InOut.GPUStats[1] = FSynthBenchmarkStat(TEXT("TexHeavy"), 1.0f / 7.447f, TEXT("s/GigaPix")); InOut.GPUStats[2] = FSynthBenchmarkStat(TEXT("DepTexHeavy"), 1.0f / 3.847f, TEXT("s/GigaPix")); InOut.GPUStats[3] = FSynthBenchmarkStat(TEXT("FillOnly"), 1.0f / 25.463f, TEXT("s/GigaPix")); InOut.GPUStats[4] = FSynthBenchmarkStat(TEXT("Bandwidth"), 1.0f / 1.072f, TEXT("s/GigaPix")); // e.g. on NV670: Method3 (mostly fill rate )-> 26GP/s (seems realistic) // reference: http://en.wikipedia.org/wiki/Comparison_of_Nvidia_graphics_processing_units theoretical: 29.3G/s RHICmdList.EndRenderQuery(TimerQueries[0]); // multiple iterations to see how trust able the values are for(uint32 Iteration = 0; Iteration < IterationCount; ++Iteration) { for(uint32 MethodIterator = 0; MethodIterator < MethodCount; ++MethodIterator) { // alternate between forward and backward (should give the same number) // uint32 MethodId = (Iteration % 2) ? MethodIterator : (MethodCount - 1 - MethodIterator); uint32 MethodId = MethodIterator; uint32 QueryIndex = 1 + Iteration * MethodCount + MethodId; // 0 / 1 const uint32 SrcRTIndex = 1 - DestRTIndex; GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, RTItems[DestRTIndex]); SetRenderTarget(RHICmdList, RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, FTextureRHIRef()); // decide how much work we do in this pass LocalWorkScale[Iteration] = (Iteration / 10.f + 1.f) * WorkScale; RunBenchmarkShader(RHICmdList, View, MethodId, RTItems[SrcRTIndex], LocalWorkScale[Iteration]); RHICmdList.CopyToResolveTarget(RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, RTItems[DestRTIndex]->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams()); /*if(bGPUCPUSync) { // more consistent timing but strangely much faster to the level that is unrealistic FResolveParams Param; Param.Rect = FResolveRect(0, 0, 1, 1); RHICmdList.CopyToResolveTarget( RTItems[DestRTIndex]->GetRenderTargetItem().TargetableTexture, RTItems[2]->GetRenderTargetItem().ShaderResourceTexture, false, Param); void* Data = 0; int Width = 0; int Height = 0; RHIMapStagingSurface(RTItems[2]->GetRenderTargetItem().ShaderResourceTexture, Data, Width, Height); RHIUnmapStagingSurface(RTItems[2]->GetRenderTargetItem().ShaderResourceTexture); }*/ RHICmdList.EndRenderQuery(TimerQueries[QueryIndex]); // ping pong DestRTIndex = 1 - DestRTIndex; } } { uint64 OldAbsTime = 0; // flushes the RHI thread to make sure all RHICmdList.EndRenderQuery() commands got executed. RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); RHICmdList.GetRenderQueryResult(TimerQueries[0], OldAbsTime, true); GTimerQueryPool.ReleaseQuery(RHICmdList, TimerQueries[0]); for(uint32 Iteration = 0; Iteration < IterationCount; ++Iteration) { uint32 Results[MethodCount]; for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { uint32 QueryIndex = 1 + Iteration * MethodCount + MethodId; uint64 AbsTime; RHICmdList.GetRenderQueryResult(TimerQueries[QueryIndex], AbsTime, true); GTimerQueryPool.ReleaseQuery(RHICmdList, TimerQueries[QueryIndex]); uint64 RelTime = AbsTime - OldAbsTime; TotalTimes[MethodId] += RelTime; Results[MethodId] = RelTime; OldAbsTime = AbsTime; } for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { float TimeInSec = Results[MethodId] / 1000000.0f; // to normalize from seconds to seconds per GPixel float SamplesInGPix = LocalWorkScale[Iteration] * GBenchmarkResolution * GBenchmarkResolution / 1000000000.0f; // TimingValue in Seconds per GPixel TimingSeries[MethodId].SetEntry(Iteration, TimeInSec / SamplesInGPix); } } if(bSupportsTimerQueries) { for(uint32 MethodId = 0; MethodId < MethodCount; ++MethodId) { float Confidence = 0.0f; // in seconds per GPixel float NormalizedTime = TimingSeries[MethodId].ComputeValue(Confidence); if(Confidence > 0) { FTimeSample TimeSample(TotalTimes[MethodId] / 1000000.0f, NormalizedTime); InOut.GPUStats[MethodId].SetMeasuredTime(TimeSample, Confidence); } } } } }
bool Ctrl::DispatchKey(dword keycode, int count) { GuiLock __; if(GUI_AltAccessKeys()) { bool alt = GetAlt(); Ctrl *c = GetActiveCtrl(); if(c) c->RefreshAccessKeysDo(alt); } // RLOGBLOCK("Ctrl::DispatchKey"); // RLOG("DispatchKey: focusCtrl = " << FormatIntHex((int)~focusCtrl) << ", wnd = " << FormatIntHex((int)~focusCtrlWnd) << ")"); LLOG("DispatchKey " << keycode << " (0x" << Sprintf("%08x", keycode) << ", " << GetKeyDesc(keycode) << "), count:" << count << " focusCtrl:" << UPP::Name(focusCtrl) << " focusCtrlWnd:" << UPP::Name(focusCtrlWnd)); if((keycode & K_KEYUP) && ignorekeyup) { ignorekeyup = false; return true; } for(int i = 0; i < keyhook().GetCount(); i++) if((*keyhook()[i])(focusCtrl, keycode, count)) return true; dword k = keycode; word l = LOWORD(keycode); if(!(k & K_DELTA) && l >= 32 && l != 127 && GetDefaultCharset() != CHARSET_UNICODE) k = MAKELONG((word)FromUnicode(l, CHARSET_DEFAULT), HIWORD(keycode)); if(!focusCtrl) return false; Ptr<Ctrl> p = focusCtrl; if(Ini::user_log) { String kl; dword k = keycode; const char *l = ""; if(k < 65536) { kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')'; l = " "; } else { kl << "KEY"; if(k & K_KEYUP) { kl << "UP"; k &= ~K_KEYUP; l = " "; } kl << " " << GetKeyDesc(k); } USRLOG(l << kl); } for(;;) { LLOG("Trying to DispatchKey: p = " << Desc(p)); if(p->IsEnabled() && p->Key(p->unicode ? keycode : k, count)) { LLOG("Ctrl::DispatchKey(" << FormatIntHex(keycode) << ", " << GetKeyDesc(keycode) << "): eaten in " << Desc(p)); if(Ini::user_log) USRLOG(" -> " << Desc(p)); eventCtrl = focusCtrl; return true; } s_hotkey = true; if(!p->GetParent()) { if(p->HotKey(keycode)) { eventCtrl = focusCtrl; return true; } return false; } p = p->GetParent(); } USRLOG(" key was ignored"); return false; }