Exemple #1
0
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);
}
Exemple #3
0
//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;
}
Exemple #4
0
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();
}
Exemple #5
0
    PropGroup* PropGroup::Group(const std::wstring& name)
    {
      PropGroup *group=new PropGroup(this,Desc(name));

      groups.push_back(group);

      return group;
    }
Exemple #6
0
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));
}
Exemple #7
0
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;
}
Exemple #8
0
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);
}
Exemple #11
0
__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;
	}
}
Exemple #12
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());
	}
}
Exemple #14
0
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);
}
Exemple #15
0
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;
}
Exemple #16
0
/********************************************************************************************
>	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(); 
}			
Exemple #17
0
//=============================================================================
//	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"));
	}
}
Exemple #21
0
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
		}
	}
}
Exemple #27
0
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);
					}
				}
			}
		}
	}
Exemple #30
0
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;
}