Exemplo n.º 1
0
FD3D11UniformBuffer::~FD3D11UniformBuffer()
{
	// Do not return the allocation to the pool if it is in the dynamic constant buffer!
	if (!RingAllocation.IsValid() && Resource != nullptr)
	{
		check(IsInRenderingThread());
		D3D11_BUFFER_DESC Desc;
		Resource->GetDesc(&Desc);

		// Return this uniform buffer to the free pool
		if (Desc.CPUAccessFlags == D3D11_CPU_ACCESS_WRITE && Desc.Usage == D3D11_USAGE_DYNAMIC)
		{
			check(IsValidRef(Resource));
			FPooledUniformBuffer NewEntry;
			NewEntry.Buffer = Resource;
			NewEntry.FrameFreed = GFrameNumberRenderThread;
			NewEntry.CreatedSize = Desc.ByteWidth;

			// Add to this frame's array of free uniform buffers
			const int32 SafeFrameIndex = (GFrameNumberRenderThread - 1) % NumSafeFrames;
			const uint32 BucketIndex = GetPoolBucketIndex(Desc.ByteWidth);
			int32 LastNum = SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Num();
			check(Desc.ByteWidth <= GetPoolBucketSize(Desc.ByteWidth));
			SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Add(NewEntry);
			INC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers);
			INC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, Desc.ByteWidth);

			FPlatformMisc::MemoryBarrier(); // check for unwanted concurrency
			check(SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Num() == LastNum + 1);
		}
	}
}
/*-----------------------------------------------------------------------------
 FBoneBufferPoolPolicy
 -----------------------------------------------------------------------------*/
FBoneBufferTypeRef FBoneBufferPoolPolicy::CreateResource(CreationArguments Args)
{
	uint32 BufferSize = GetPoolBucketSize(GetPoolBucketIndex(Args));
	FBoneBuffer Buffer;
	FRHIResourceCreateInfo CreateInfo;
	Buffer.VertexBufferRHI = RHICreateVertexBuffer( BufferSize, (BUF_Dynamic | BUF_ShaderResource), CreateInfo );
	Buffer.VertexBufferSRV = RHICreateShaderResourceView( Buffer.VertexBufferRHI, sizeof(FVector4), PF_A32B32G32R32F );
	return Buffer;
}
Exemplo n.º 3
0
FUniformBufferRHIRef FD3D11DynamicRHI::RHICreateUniformBuffer(const void* Contents,const FRHIUniformBufferLayout& Layout,EUniformBufferUsage Usage)
{
	check(IsInRenderingThread());

	FD3D11UniformBuffer* NewUniformBuffer = nullptr;
	const uint32 NumBytes = Layout.ConstantBufferSize;
	if (NumBytes > 0)
	{
		// Constant buffers must also be 16-byte aligned.
		check(Align(NumBytes,16) == NumBytes);
		check(Align(Contents,16) == Contents);
		check(NumBytes <= D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16);
		check(NumBytes < (1 << NumPoolBuckets));

		SCOPE_CYCLE_COUNTER(STAT_D3D11UpdateUniformBufferTime);
		if (IsPoolingEnabled())
		{
			TRefCountPtr<ID3D11Buffer> UniformBufferResource;
			FRingAllocation RingAllocation;

			if (!RingAllocation.IsValid())
			{
				// Find the appropriate bucket based on size
				const uint32 BucketIndex = GetPoolBucketIndex(NumBytes);
				TArray<FPooledUniformBuffer>& PoolBucket = UniformBufferPool[BucketIndex];

				if (PoolBucket.Num() > 0)
				{
					// Reuse the last entry in this size bucket
					FPooledUniformBuffer FreeBufferEntry = PoolBucket.Pop();
					check(IsValidRef(FreeBufferEntry.Buffer));
					UniformBufferResource = FreeBufferEntry.Buffer;
					checkf(FreeBufferEntry.CreatedSize >= NumBytes, TEXT("%u %u %u %u"), NumBytes, BucketIndex, FreeBufferEntry.CreatedSize, GetPoolBucketSize(NumBytes));
					DEC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers);
					DEC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, FreeBufferEntry.CreatedSize);
				}

				// Nothing usable was found in the free pool, create a new uniform buffer
				if (!IsValidRef(UniformBufferResource))
				{
					D3D11_BUFFER_DESC Desc;
					// Allocate based on the bucket size, since this uniform buffer will be reused later
					Desc.ByteWidth = GetPoolBucketSize(NumBytes);
					// Use D3D11_USAGE_DYNAMIC, which allows multiple CPU writes for pool reuses
					// This is method of updating is vastly superior to creating a new constant buffer each time with D3D11_USAGE_IMMUTABLE, 
					// Since that inserts the data into the command buffer which causes GPU flushes
					Desc.Usage = D3D11_USAGE_DYNAMIC;
					Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
					Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
					Desc.MiscFlags = 0;
					Desc.StructureByteStride = 0;

					VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc, NULL, UniformBufferResource.GetInitReference()));

					UpdateBufferStats(UniformBufferResource, true);
				}

				check(IsValidRef(UniformBufferResource));

				D3D11_MAPPED_SUBRESOURCE MappedSubresource;
				// Discard previous results since we always do a full update
				VERIFYD3D11RESULT(Direct3DDeviceIMContext->Map(UniformBufferResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedSubresource));
				check(MappedSubresource.RowPitch >= NumBytes);
				FMemory::Memcpy(MappedSubresource.pData, Contents, NumBytes);
				Direct3DDeviceIMContext->Unmap(UniformBufferResource, 0);
			}

			NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, RingAllocation);
		}
		else
		{
			// No pooling
			D3D11_BUFFER_DESC Desc;
			Desc.ByteWidth = NumBytes;
			Desc.Usage = D3D11_USAGE_IMMUTABLE;
			Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
			Desc.CPUAccessFlags = 0;
			Desc.MiscFlags = 0;
			Desc.StructureByteStride = 0;

			D3D11_SUBRESOURCE_DATA ImmutableData;
			ImmutableData.pSysMem = Contents;
			ImmutableData.SysMemPitch = ImmutableData.SysMemSlicePitch = 0;

			TRefCountPtr<ID3D11Buffer> UniformBufferResource;
			VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc,&ImmutableData,UniformBufferResource.GetInitReference()));

			NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, FRingAllocation());
		}
	}
	else
	{
		// This uniform buffer contains no constants, only a resource table.
		NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, nullptr, FRingAllocation());
	}

	if (Layout.Resources.Num())
	{
		int32 NumResources = Layout.Resources.Num();
		FRHIResource** InResources = (FRHIResource**)((uint8*)Contents + Layout.ResourceOffset);
		NewUniformBuffer->ResourceTable.Empty(NumResources);
		NewUniformBuffer->ResourceTable.AddZeroed(NumResources);
		for (int32 i = 0; i < NumResources; ++i)
		{
			check(InResources[i]);
			NewUniformBuffer->ResourceTable[i] = InResources[i];
		}
		NewUniformBuffer->RawResourceTable.Empty(NumResources);
		NewUniformBuffer->RawResourceTable.AddZeroed(NumResources);
	}

	return NewUniformBuffer;
}