void GetUniformMeshStreamOutLayout(FStreamOutElementList& Layout)
{
	Layout.Add(FStreamOutElement(0, "SV_Position", 0, 4, 0));
	Layout.Add(FStreamOutElement(0, "Tangent", 0, 3, 0));
	Layout.Add(FStreamOutElement(0, "Tangent", 1, 3, 0));
	Layout.Add(FStreamOutElement(0, "Tangent", 2, 3, 0));
	Layout.Add(FStreamOutElement(0, "UV", 0, 2, 0));
	Layout.Add(FStreamOutElement(0, "UV", 1, 2, 0));
	Layout.Add(FStreamOutElement(0, "VertexColor", 0, 4, 0));
}
/** Returns number of float's in the uniform vertex. */
int32 ComputeUniformVertexStride()
{
	FStreamOutElementList Layout;
	int32 StreamStride = 0;

	GetUniformMeshStreamOutLayout(Layout);

	for (int32 ElementIndex = 0; ElementIndex < Layout.Num(); ElementIndex++)
	{
		StreamStride += Layout[ElementIndex].ComponentCount;
	}

	// D3D11 stream out buffer element stride must be a factor of 4
	return FMath::DivideAndRoundUp(StreamStride, 4) * 4;
}
예제 #3
0
FGeometryShaderRHIRef FD3D11DynamicRHI::RHICreateGeometryShaderWithStreamOutput(const TArray<uint8>& Code, const FStreamOutElementList& ElementList, uint32 NumStrides, const uint32* Strides, int32 RasterizedStream) 
{ 
	check(Code.Num());

	FD3D11GeometryShader* Shader = new FD3D11GeometryShader;

	FMemoryReader Ar( Code, true );
	Ar << Shader->ShaderResourceTable;
	int32 Offset = Ar.Tell();
	const uint8* CodePtr = Code.GetData() + Offset;
	const size_t CodeSize = Code.Num() - Offset - 1;

	uint32 D3DRasterizedStream = RasterizedStream;
	if (RasterizedStream == -1)
	{
		D3DRasterizedStream = D3D11_SO_NO_RASTERIZED_STREAM;
	}

	D3D11_SO_DECLARATION_ENTRY StreamOutEntries[D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT];

	for (int32 EntryIndex = 0; EntryIndex < ElementList.Num(); EntryIndex++)
	{
		StreamOutEntries[EntryIndex].Stream = ElementList[EntryIndex].Stream;
		StreamOutEntries[EntryIndex].SemanticName = ElementList[EntryIndex].SemanticName;
		StreamOutEntries[EntryIndex].SemanticIndex = ElementList[EntryIndex].SemanticIndex;
		StreamOutEntries[EntryIndex].StartComponent = ElementList[EntryIndex].StartComponent;
		StreamOutEntries[EntryIndex].ComponentCount = ElementList[EntryIndex].ComponentCount;
		StreamOutEntries[EntryIndex].OutputSlot = ElementList[EntryIndex].OutputSlot;
	}

	VERIFYD3D11RESULT( Direct3DDevice->CreateGeometryShaderWithStreamOutput(
		(void*)CodePtr,
		CodeSize,
		StreamOutEntries,
		ElementList.Num(),
		Strides,
		NumStrides,
		D3DRasterizedStream,
		NULL,
		Shader->Resource.GetInitReference()
	) );
	
	// bGlobalUniformBufferUsed is in the last byte, see CompileD3D11Shader
	Shader->bShaderNeedsGlobalConstantBuffer = Code[Code.Num() - 1] != 0;

	return Shader;
}
예제 #4
0
FGeometryShaderRHIRef FD3D11DynamicRHI::RHICreateGeometryShaderWithStreamOutput(const TArray<uint8>& Code, const FStreamOutElementList& ElementList, uint32 NumStrides, const uint32* Strides, int32 RasterizedStream) 
{ 
	check(Code.Num());

	uint32 D3DRasterizedStream = RasterizedStream;
	if (RasterizedStream == -1)
	{
		D3DRasterizedStream = D3D11_SO_NO_RASTERIZED_STREAM;
	}

	D3D11_SO_DECLARATION_ENTRY StreamOutEntries[D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT];

	for (int32 EntryIndex = 0; EntryIndex < ElementList.Num(); EntryIndex++)
	{
		StreamOutEntries[EntryIndex].Stream = ElementList[EntryIndex].Stream;
		StreamOutEntries[EntryIndex].SemanticName = ElementList[EntryIndex].SemanticName;
		StreamOutEntries[EntryIndex].SemanticIndex = ElementList[EntryIndex].SemanticIndex;
		StreamOutEntries[EntryIndex].StartComponent = ElementList[EntryIndex].StartComponent;
		StreamOutEntries[EntryIndex].ComponentCount = ElementList[EntryIndex].ComponentCount;
		StreamOutEntries[EntryIndex].OutputSlot = ElementList[EntryIndex].OutputSlot;
	}

	TRefCountPtr<ID3D11GeometryShader> D3DShader;
	VERIFYD3D11RESULT(Direct3DDevice->CreateGeometryShaderWithStreamOutput(
		(const void*)Code.GetTypedData(),
		// bGlobalUniformBufferUsed is in the last byte, see CompileD3D11Shader
		Code.Num() - 1,
		StreamOutEntries,
		ElementList.Num(),
		Strides,
		NumStrides,
		D3DRasterizedStream,
		NULL,
		(ID3D11GeometryShader**)D3DShader.GetInitReference()));

	return new FD3D11GeometryShader(D3DShader, Code);
}
예제 #5
0
void FShaderResource::InitRHI()
{
	checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data."));

	// we can't have this called on the wrong platform's shaders
	if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform))
 	{
 		if (FPlatformProperties::RequiresCookedData())
 		{
 			UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), 
				*LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString());
 		}
 		return;
 	}

	INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1);
	SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime);

	FShaderCache* ShaderCache = FShaderCache::GetShaderCache();

	if(Target.Frequency == SF_Vertex)
	{
		VertexShader = ShaderCache ? ShaderCache->GetVertexShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateVertexShader(Code);
	}
	else if(Target.Frequency == SF_Pixel)
	{
		PixelShader = ShaderCache ? ShaderCache->GetPixelShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreatePixelShader(Code);
	}
	else if(Target.Frequency == SF_Hull)
	{
		HullShader = ShaderCache ? ShaderCache->GetHullShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateHullShader(Code);
	}
	else if(Target.Frequency == SF_Domain)
	{
		DomainShader = ShaderCache ? ShaderCache->GetDomainShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateDomainShader(Code);
	}
	else if(Target.Frequency == SF_Geometry)
	{
		if (SpecificType)
		{
			FStreamOutElementList ElementList;
			TArray<uint32> StreamStrides;
			int32 RasterizedStream = -1;
			SpecificType->GetStreamOutElements(ElementList, StreamStrides, RasterizedStream);
			checkf(ElementList.Num(), *FString::Printf(TEXT("Shader type %s was given GetStreamOutElements implementation that had no elements!"), SpecificType->GetName()));

			//@todo - not using the cache
			GeometryShader = RHICreateGeometryShaderWithStreamOutput(Code, ElementList, StreamStrides.Num(), StreamStrides.GetData(), RasterizedStream);
		}
		else
		{
			GeometryShader = ShaderCache ? ShaderCache->GetGeometryShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateGeometryShader(Code);
		}
	}
	else if(Target.Frequency == SF_Compute)
	{
		ComputeShader = ShaderCache ? ShaderCache->GetComputeShader((EShaderPlatform)Target.Platform, Code) : RHICreateComputeShader(Code);
	}

	if (Target.Frequency != SF_Geometry)
	{
		checkf(!SpecificType, *FString::Printf(TEXT("Only geometry shaders can use GetStreamOutElements, shader type %s"), SpecificType->GetName()));
	}

	if (!FPlatformProperties::HasEditorOnlyData())
	{
		DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num());
		DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize());
		Code.Empty();
	}
}
예제 #6
0
FGeometryShaderRHIRef FD3D12DynamicRHI::RHICreateGeometryShaderWithStreamOutput(const TArray<uint8>& Code, const FStreamOutElementList& ElementList, uint32 NumStrides, const uint32* Strides, int32 RasterizedStream)
{
	check(Code.Num());

	FD3D12GeometryShader* Shader = new FD3D12GeometryShader;

	FMemoryReader Ar(Code, true);
	Ar << Shader->ShaderResourceTable;
	int32 Offset = Ar.Tell();
	const uint8* CodePtr = Code.GetData() + Offset;
	const SIZE_T CodeSize = Code.Num() - Offset - 5;

	Shader->StreamOutput.RasterizedStream = RasterizedStream;
	if (RasterizedStream == -1)
	{
		Shader->StreamOutput.RasterizedStream = D3D12_SO_NO_RASTERIZED_STREAM;
	}

	Shader->StreamOutput.NumEntries = ElementList.Num();
	Shader->pStreamOutEntries = new D3D12_SO_DECLARATION_ENTRY[ElementList.Num()];
	Shader->StreamOutput.pSODeclaration = Shader->pStreamOutEntries;
	if (Shader->pStreamOutEntries == nullptr)
	{
		return nullptr;	// Out of memory
	}
	for (int32 EntryIndex = 0; EntryIndex < ElementList.Num(); EntryIndex++)
	{
		Shader->pStreamOutEntries[EntryIndex].Stream = ElementList[EntryIndex].Stream;
		Shader->pStreamOutEntries[EntryIndex].SemanticName = ElementList[EntryIndex].SemanticName;
		Shader->pStreamOutEntries[EntryIndex].SemanticIndex = ElementList[EntryIndex].SemanticIndex;
		Shader->pStreamOutEntries[EntryIndex].StartComponent = ElementList[EntryIndex].StartComponent;
		Shader->pStreamOutEntries[EntryIndex].ComponentCount = ElementList[EntryIndex].ComponentCount;
		Shader->pStreamOutEntries[EntryIndex].OutputSlot = ElementList[EntryIndex].OutputSlot;
	}


	// bGlobalUniformBufferUsed and resource counts are packed in the last few bytes, see CompileD3D11Shader
	Shader->bShaderNeedsGlobalConstantBuffer = Code[Code.Num() - 5] != 0;
	Shader->SamplerCount                     = Code[Code.Num() - 4];
	Shader->SRVCount                         = Code[Code.Num() - 3];
	Shader->CBCount                          = Code[Code.Num() - 2];
	Shader->UAVCount                         = Code[Code.Num() - 1];

	// Indicate this shader uses stream output
	Shader->bShaderNeedsStreamOutput = true;

	// Copy the strides
	Shader->StreamOutput.NumStrides = NumStrides;
	Shader->pStreamOutStrides = new uint32[NumStrides];
	Shader->StreamOutput.pBufferStrides = Shader->pStreamOutStrides;
	if (Shader->pStreamOutStrides == nullptr)
	{
		return nullptr;	// Out of memory
	}
	FMemory::Memcpy(Shader->pStreamOutStrides, Strides, sizeof(uint32) * NumStrides);

	Shader->Code = Code;

	D3D12_SHADER_BYTECODE ShaderBytecode;
	ShaderBytecode.pShaderBytecode = Shader->Code.GetData() + Offset;
	ShaderBytecode.BytecodeLength = CodeSize;
	Shader->ShaderBytecode.SetShaderBytecode(ShaderBytecode);

	return Shader;
}