/**
	* Initialize the RHI for this rendering resource
	*/
	void InitRHI() override
	{
		const int32 NumVerts = 8;
		TResourceArray<FVector4, VERTEXBUFFER_ALIGNMENT> Verts;
		Verts.SetNumUninitialized(NumVerts);

		for (uint32 Z = 0; Z < 2; Z++)
		{
			for (uint32 Y = 0; Y < 2; Y++)
			{
				for (uint32 X = 0; X < 2; X++)
				{
					const FVector4 Vertex = FVector4(
					  (X ? -1 : 1),
					  (Y ? -1 : 1),
					  (Z ? -1 : 1),
					  1.0f
					);

					Verts[GetCubeVertexIndex(X, Y, Z)] = Vertex;
				}
			}
		}

		uint32 Size = Verts.GetResourceDataSize();

		// Create vertex buffer. Fill buffer with initial data upon creation
		FRHIResourceCreateInfo CreateInfo(&Verts);
		VertexBufferRHI = RHICreateVertexBuffer(Size, BUF_Static, CreateInfo);
	}
static void IssueProjectedShadowOcclusionQuery(FRHICommandListImmediate& RHICmdList, FViewInfo& View, const FProjectedShadowInfo& ProjectedShadowInfo, FOcclusionQueryVS* VertexShader, int32 NumBufferedFrames)
{	
	FSceneViewState* ViewState = (FSceneViewState*)View.State;

	const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryIssueIndex(ViewState->PendingPrevFrameNumber, NumBufferedFrames);
	FSceneViewState::ShadowKeyOcclusionQueryMap& ShadowOcclusionQueryMap = ViewState->ShadowOcclusionQueryMaps[QueryIndex];

	// The shadow transforms and view transforms are relative to different origins, so the world coordinates need to
	// be translated.
	const FVector4 PreShadowToPreViewTranslation(View.ViewMatrices.PreViewTranslation - ProjectedShadowInfo.PreShadowTranslation,0);

	// If the shadow frustum is farther from the view origin than the near clipping plane,
	// it can't intersect the near clipping plane.
	const bool bIntersectsNearClippingPlane = ProjectedShadowInfo.ReceiverFrustum.IntersectSphere(
		View.ViewMatrices.ViewOrigin + ProjectedShadowInfo.PreShadowTranslation,
		View.NearClippingDistance * FMath::Sqrt(3.0f)
		);
	if( !bIntersectsNearClippingPlane )
	{

		// Allocate an occlusion query for the primitive from the occlusion query pool.
		const FRenderQueryRHIRef ShadowOcclusionQuery = ViewState->OcclusionQueryPool.AllocateQuery();
		
		VertexShader->SetParameters(RHICmdList, View);

		// Draw the primitive's bounding box, using the occlusion query.
		RHICmdList.BeginRenderQuery(ShadowOcclusionQuery);

		void* VerticesPtr;
		void* IndicesPtr;
		// preallocate memory to fill out with vertices and indices
		RHICmdList.BeginDrawIndexedPrimitiveUP(PT_TriangleList, 12, 8, sizeof(FVector), VerticesPtr, 0, NUM_CUBE_VERTICES, sizeof(uint16), IndicesPtr);
		FVector* Vertices = (FVector*)VerticesPtr;
		uint16* Indices = (uint16*)IndicesPtr;

		// Generate vertices for the shadow's frustum.
		for(uint32 Z = 0;Z < 2;Z++)
		{
			for(uint32 Y = 0;Y < 2;Y++)
			{
				for(uint32 X = 0;X < 2;X++)
				{
					const FVector4 UnprojectedVertex = ProjectedShadowInfo.InvReceiverMatrix.TransformFVector4(
						FVector4(
						(X ? -1.0f : 1.0f),
						(Y ? -1.0f : 1.0f),
						(Z ?  1.0f : 0.0f),
						1.0f
						)
						);
					const FVector ProjectedVertex = UnprojectedVertex / UnprojectedVertex.W + PreShadowToPreViewTranslation;
					Vertices[GetCubeVertexIndex(X,Y,Z)] = ProjectedVertex;
				}
			}
		}

		// we just copy the indices right in
		FMemory::Memcpy(Indices, GCubeIndices, sizeof(GCubeIndices));

		FSceneViewState::FProjectedShadowKey Key(ProjectedShadowInfo);

		checkSlow(ShadowOcclusionQueryMap.Find(Key) == NULL);
		ShadowOcclusionQueryMap.Add(Key, ShadowOcclusionQuery);

		RHICmdList.EndDrawIndexedPrimitiveUP();
		RHICmdList.EndRenderQuery(ShadowOcclusionQuery);
	}
}