void FGPUBaseSkinVertexFactory::ShaderDataType::UpdateBoneData() { uint32 NumBones = BoneMatrices.Num(); check(NumBones <= MaxGPUSkinBones); if (GRHIFeatureLevel_DEPRECATED >= ERHIFeatureLevel::SM4) { static FSharedPoolPolicyData PoolPolicy; uint32 NumVectors = NumBones*3; check(NumVectors <= (MaxGPUSkinBones*3)); uint32 VectorArraySize = NumVectors * sizeof(FVector4); uint32 PooledArraySize = BoneBufferPool.PooledSizeForCreationArguments(VectorArraySize); if(!IsValidRef(BoneBuffer) || PooledArraySize != BoneBuffer.VertexBufferRHI->GetSize()) { if(IsValidRef(BoneBuffer)) { BoneBufferPool.ReleasePooledResource(BoneBuffer); } BoneBuffer = BoneBufferPool.CreatePooledResource(VectorArraySize); check(IsValidRef(BoneBuffer)); } if(NumBones) { #if PLATFORM_SUPPORTS_RHI_THREAD check(VectorArraySize == NumBones * sizeof(BoneMatrices[0])); if (GRHIThread) { GRHICommandList.GetImmediateCommandList().UpdateVertexBuffer(BoneBuffer.VertexBufferRHI, BoneMatrices.GetData(), NumBones * sizeof(BoneMatrices[0])); } else #endif { float* Data = (float*)RHILockVertexBuffer(BoneBuffer.VertexBufferRHI, 0, VectorArraySize, RLM_WriteOnly); checkSlow(Data); FMemory::Memcpy(Data, BoneMatrices.GetData(), NumBones * sizeof(BoneMatrices[0])); RHIUnlockVertexBuffer(BoneBuffer.VertexBufferRHI); } } } else { check(NumBones * BoneMatrices.GetTypeSize() <= sizeof(GBoneUniformStruct)); FMemory::Memcpy(&GBoneUniformStruct, BoneMatrices.GetData(), NumBones * sizeof(BoneMatrices[0])); UniformBuffer = RHICreateUniformBuffer(&GBoneUniformStruct, FBoneMatricesUniformShaderParameters::StaticStruct.GetLayout(), UniformBuffer_MultiFrame); } }
FUniformBufferRHIRef FUniformExpressionSet::CreateUniformBuffer(const FMaterialRenderContext& MaterialRenderContext, FRHICommandList* CommandListIfLocalMode, struct FLocalUniformBuffer* OutLocalUniformBuffer) const { check(UniformBufferStruct); check(IsInParallelRenderingThread()); FUniformBufferRHIRef UniformBuffer; if (UniformBufferStruct->GetSize() > 0) { FMemMark Mark(FMemStack::Get()); void* const TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct->GetSize(),UNIFORM_BUFFER_STRUCT_ALIGNMENT); FLinearColor* TempVectorBuffer = (FLinearColor*)TempBuffer; for(int32 VectorIndex = 0;VectorIndex < UniformVectorExpressions.Num();++VectorIndex) { TempVectorBuffer[VectorIndex] = FLinearColor(0,0,0,0); UniformVectorExpressions[VectorIndex]->GetNumberValue(MaterialRenderContext,TempVectorBuffer[VectorIndex]); } float* TempScalarBuffer = (float*)(TempVectorBuffer + UniformVectorExpressions.Num()); for(int32 ScalarIndex = 0;ScalarIndex < UniformScalarExpressions.Num();++ScalarIndex) { FLinearColor VectorValue(0,0,0,0); UniformScalarExpressions[ScalarIndex]->GetNumberValue(MaterialRenderContext,VectorValue); TempScalarBuffer[ScalarIndex] = VectorValue.R; } void** ResourceTable = (void**)((uint8*)TempBuffer + UniformBufferStruct->GetLayout().ResourceOffset); check(((UPTRINT)ResourceTable & 0x7) == 0); check(UniformBufferStruct->GetLayout().Resources.Num() == Uniform2DTextureExpressions.Num() * 2 + UniformCubeTextureExpressions.Num() * 2 + 2); // Cache 2D texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < Uniform2DTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; Uniform2DTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if (Value && Value->Resource) { //@todo-rco: Help track down a invalid values checkf(Value->IsA(UTexture::StaticClass()), TEXT("Expecting a UTexture! Value='%s' class='%s'"), *Value->GetName(), *Value->GetClass()->GetName()); // UMaterial / UMaterialInstance should have caused all dependent textures to be PostLoaded, which initializes their rendering resource checkf(Value->TextureReference.TextureReferenceRHI, TEXT("Texture %s of class %s had invalid texture reference"), *Value->GetName(), *Value->GetClass()->GetName()); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } // Cache cube texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < UniformCubeTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; UniformCubeTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if(Value && Value->Resource) { check(Value->TextureReference.TextureReferenceRHI); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } *ResourceTable++ = Wrap_WorldGroupSettings->SamplerStateRHI; *ResourceTable++ = Clamp_WorldGroupSettings->SamplerStateRHI; if (CommandListIfLocalMode) { check(OutLocalUniformBuffer); *OutLocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct->GetSize(), UniformBufferStruct->GetLayout()); check(OutLocalUniformBuffer->IsValid()); } else { UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct->GetLayout(), UniformBuffer_MultiFrame); check(!OutLocalUniformBuffer->IsValid()); } } return UniformBuffer; }
FUniformBufferRHIRef FUniformExpressionSet::CreateUniformBuffer(const FMaterialRenderContext& MaterialRenderContext, FRHICommandList* CommandListIfLocalMode, struct FLocalUniformBuffer* OutLocalUniformBuffer) const { check(UniformBufferStruct); check(IsInParallelRenderingThread()); FUniformBufferRHIRef UniformBuffer; if (UniformBufferStruct->GetSize() > 0) { FMemMark Mark(FMemStack::Get()); void* const TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct->GetSize(),UNIFORM_BUFFER_STRUCT_ALIGNMENT); FLinearColor* TempVectorBuffer = (FLinearColor*)TempBuffer; for(int32 VectorIndex = 0;VectorIndex < UniformVectorExpressions.Num();++VectorIndex) { TempVectorBuffer[VectorIndex] = FLinearColor(0,0,0,0); UniformVectorExpressions[VectorIndex]->GetNumberValue(MaterialRenderContext,TempVectorBuffer[VectorIndex]); } float* TempScalarBuffer = (float*)(TempVectorBuffer + UniformVectorExpressions.Num()); for(int32 ScalarIndex = 0;ScalarIndex < UniformScalarExpressions.Num();++ScalarIndex) { FLinearColor VectorValue(0,0,0,0); UniformScalarExpressions[ScalarIndex]->GetNumberValue(MaterialRenderContext,VectorValue); TempScalarBuffer[ScalarIndex] = VectorValue.R; } void** ResourceTable = (void**)((uint8*)TempBuffer + UniformBufferStruct->GetLayout().ResourceOffset); check(((UPTRINT)ResourceTable & 0x7) == 0); // Cache 2D texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < Uniform2DTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; Uniform2DTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value); if(Value && Value->Resource) { *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; *ResourceTable++ = Value->Resource->SamplerStateRHI; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } // Cache cube texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < UniformCubeTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; UniformCubeTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value); if(Value && Value->Resource) { *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; *ResourceTable++ = Value->Resource->SamplerStateRHI; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } if (CommandListIfLocalMode) { check(OutLocalUniformBuffer); *OutLocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct->GetSize(), UniformBufferStruct->GetLayout()); check(OutLocalUniformBuffer->IsValid()); } else { UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct->GetLayout(), UniformBuffer_MultiFrame); check(!OutLocalUniformBuffer->IsValid()); } } return UniformBuffer; }