public static void CompareVariable(EffectVariable reflectionVariable, object variable) { EffectTypeDescription typeDesc = reflectionVariable.TypeInfo.Description; Assert.AreEqual(typeDesc.TypeName, typeDesc.TypeName); Assert.AreEqual(typeDesc.Class, typeDesc.Class); Assert.AreEqual(typeDesc.Type, typeDesc.Type); Assert.AreEqual(typeDesc.Elements, typeDesc.Elements); Assert.AreEqual(typeDesc.Members, typeDesc.Members); Assert.AreEqual(typeDesc.Rows, typeDesc.Rows); Assert.AreEqual(typeDesc.Columns, typeDesc.Columns); Assert.AreEqual(typeDesc.PackedSize, typeDesc.PackedSize); Assert.AreEqual(typeDesc.UnpackedSize, typeDesc.UnpackedSize); Assert.AreEqual(typeDesc.Stride, typeDesc.Stride); EffectVariableDescription variableDesc = reflectionVariable.Description; Assert.AreEqual(variableDesc.Name, variableDesc.Name); Assert.AreEqual(variableDesc.Semantic, variableDesc.Semantic); Assert.AreEqual(variableDesc.Flags, variableDesc.Flags); Assert.AreEqual(variableDesc.AnnotationCount, variableDesc.AnnotationCount); Assert.AreEqual(variableDesc.BufferOffset, variableDesc.BufferOffset); Assert.AreEqual(variableDesc.ExplicitBindPoint, variableDesc.ExplicitBindPoint); if (variable is EffectNumericVariable v1) { Assert.AreEqual(variableDesc.Name, v1.Name); Assert.AreEqual(0, v1.ExplicitBindPoint); } if (variable is EffectObjectVariable v2) { Assert.AreEqual(variableDesc.Name, v2.Name); } for (int i = 0; i < variableDesc.AnnotationCount; i++) { var annotation = reflectionVariable.GetAnnotationByIndex(i); } if (typeDesc.Type == ShaderVariableType.Sampler) { EffectSamplerVariable sampVariable = reflectionVariable.AsSampler(); SamplerState samplerState = sampVariable.GetSampler(); var sampDesc = samplerState.Description; } }
private static void HashType(ObjectIdBuilder hashBuilder, EffectTypeDescription type) { hashBuilder.Write(type.RowCount); hashBuilder.Write(type.ColumnCount); hashBuilder.Write(type.Elements); if (type.Name != null) { hashBuilder.Write(type.Name); } if (type.Members != null) { foreach (var member in type.Members) { hashBuilder.Write(member.Name); hashBuilder.Write(member.Offset); HashType(hashBuilder, member.Type); } } }
private static int ComputeMemberSize(ref EffectTypeDescription memberType, ref int constantBufferOffset) { var elementSize = ComputeTypeSize(memberType.Type); int size; int alignment = 4; switch (memberType.Class) { case EffectParameterClass.Struct: { // Fill members size = 0; for (int index = 0; index < memberType.Members.Length; index++) { // Properly compute size and offset according to DX rules var memberSize = ComputeMemberSize(ref memberType.Members[index].Type, ref size); // Align offset and store it as member offset memberType.Members[index].Offset = size; // Adjust offset for next item size += memberSize; } alignment = size; break; } case EffectParameterClass.Scalar: { size = elementSize; break; } case EffectParameterClass.Color: case EffectParameterClass.Vector: { size = elementSize * memberType.ColumnCount; break; } case EffectParameterClass.MatrixColumns: { size = elementSize * (4 * (memberType.ColumnCount - 1) + memberType.RowCount); break; } case EffectParameterClass.MatrixRows: { size = elementSize * (4 * (memberType.RowCount - 1) + memberType.ColumnCount); break; } default: throw new NotImplementedException(); } // Update element size memberType.ElementSize = size; // Array if (memberType.Elements > 0) { var roundedSize = (size + 15) / 16 * 16; // Round up to vec4 size += roundedSize * (memberType.Elements - 1); alignment = 16; } // Align to float4 if it is bigger than leftover space in current float4 if (constantBufferOffset / 16 != (constantBufferOffset + size - 1) / 16) { alignment = 16; } // Align offset and store it as member offset constantBufferOffset = (constantBufferOffset + alignment - 1) / alignment * alignment; return(size); }
private static EffectTypeDescription CreateTypeInfo(TypeBase variableType, List <AttributeBase> attributes, out EffectTypeDescription elementType) { elementType = default; var parameterTypeInfo = new EffectTypeDescription(); if (variableType.TypeInference.TargetType != null) { variableType = variableType.TypeInference.TargetType; } if (variableType is ArrayType) { var arrayType = (ArrayType)variableType; variableType = arrayType.Type; parameterTypeInfo.Elements = (int)((LiteralExpression)arrayType.Dimensions[0]).Literal.Value; if (variableType.TypeInference.TargetType != null) { variableType = variableType.TypeInference.TargetType; } } if (variableType is ScalarType) { if (variableType == ScalarType.Int) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Int; } else if (variableType == ScalarType.UInt) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.UInt; } else if (variableType == ScalarType.Float) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Float; } else if (variableType == ScalarType.Double) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Double; } else if (variableType == ScalarType.Bool) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Bool; } parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = 1; } else if (variableType is VectorType vectorType) { if (vectorType.Type == ScalarType.Float) { bool isColor = attributes.OfType <AttributeDeclaration>().Any(x => x.Name == "Color"); parameterTypeInfo.Class = isColor ? EffectParameterClass.Color : EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.Float; } else if (vectorType.Type == ScalarType.Double) { parameterTypeInfo.Class = EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.Double; } else if (vectorType.Type == ScalarType.Int) { parameterTypeInfo.Class = EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.Int; } else if (vectorType.Type == ScalarType.UInt) { parameterTypeInfo.Class = EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.UInt; } parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = ((VectorType)variableType).Dimension; } else if (variableType is MatrixType) { parameterTypeInfo.Class = EffectParameterClass.MatrixColumns; parameterTypeInfo.Type = EffectParameterType.Float; parameterTypeInfo.RowCount = ((MatrixType)variableType).RowCount; parameterTypeInfo.ColumnCount = ((MatrixType)variableType).ColumnCount; } else if (variableType is StructType) { var structType = (StructType)variableType; parameterTypeInfo.Class = EffectParameterClass.Struct; parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = 1; parameterTypeInfo.Name = structType.Name.Text; var members = new List <EffectTypeMemberDescription>(); foreach (var field in structType.Fields) { var memberInfo = new EffectTypeMemberDescription { Name = field.Name.Text, Type = CreateTypeInfo(field.Type, field.Attributes, out var _), }; members.Add(memberInfo); } parameterTypeInfo.Members = members.ToArray(); } else { var variableTypeName = variableType.Name.Text.ToLowerInvariant(); if (variableType is ClassType classType && classType.GenericArguments.Count == 1) { elementType = CreateTypeInfo(classType.GenericArguments[0], new List <AttributeBase>(), out var _); } switch (variableTypeName) { case "cbuffer": parameterTypeInfo.Class = EffectParameterClass.ConstantBuffer; parameterTypeInfo.Type = EffectParameterType.ConstantBuffer; break; case "tbuffer": parameterTypeInfo.Class = EffectParameterClass.TextureBuffer; parameterTypeInfo.Type = EffectParameterType.TextureBuffer; break; case "structuredbuffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.StructuredBuffer; break; case "rwstructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWStructuredBuffer; break; case "consumestructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.ConsumeStructuredBuffer; break; case "appendstructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.AppendStructuredBuffer; break; case "buffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Buffer; break; case "rwbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWBuffer; break; case "byteaddressbuffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.ByteAddressBuffer; break; case "rwbyteaddressbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWByteAddressBuffer; break; case "texture1d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture1D; break; case "texturecube": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.TextureCube; break; case "texture2d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2D; break; case "texture2dms": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2DMultisampled; break; case "texture3d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture3D; break; case "texture1darray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture1DArray; break; case "texturecubearray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.TextureCubeArray; break; case "texture2darray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2DArray; break; case "texture2dmsarray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2DMultisampledArray; break; case "rwtexture1d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture1D; break; case "rwtexture2d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture2D; break; case "rwtexture3d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture3D; break; case "rwtexture1darray": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture1DArray; break; case "rwtexture2darray": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture2DArray; break; case "samplerstate": case "samplercomparisonstate": parameterTypeInfo.Class = EffectParameterClass.Sampler; parameterTypeInfo.Type = EffectParameterType.Sampler; break; } } return(parameterTypeInfo); }
public static void CompareVariable(EffectVariable reflectionVariable, Fx10.IEffectVariable variable) { EffectTypeDescription typeDesc = reflectionVariable.TypeInfo.Description; var type = variable.Type; Assert.AreEqual(typeDesc.TypeName, type.TypeName); Assert.AreEqual(typeDesc.Class, (ShaderVariableClass)type.VariableClass); Assert.AreEqual(typeDesc.Type, (ShaderVariableType)type.VariableType); Assert.AreEqual(typeDesc.Elements, type.ElementCount); Assert.AreEqual(typeDesc.Members, type.MemberCount); Assert.AreEqual(typeDesc.Rows, type.Rows); Assert.AreEqual(typeDesc.Columns, type.Columns); Assert.AreEqual(typeDesc.PackedSize, type.PackedSize); Assert.AreEqual(typeDesc.UnpackedSize, type.UnpackedSize); Assert.AreEqual(typeDesc.Stride, type.Stride); EffectVariableDescription variableDesc = reflectionVariable.Description; Assert.AreEqual(variableDesc.Name, variable.Name); Assert.AreEqual(variableDesc.Semantic ?? "", variable.Semantic); Assert.AreEqual(variableDesc.Flags, (EffectVariableFlags)variable.Flags); Assert.AreEqual(variableDesc.AnnotationCount, variable.AnnotationCount); //TODO: SharpDX seems defines BufferOffset relative to buffer, but variable is just relative to struct //Assert.AreEqual(variableDesc.BufferOffset, variable.BufferOffset == uint.MaxValue ? 0 : variable.BufferOffset); Assert.AreEqual(variableDesc.ExplicitBindPoint, variable.ExplicitBindPoint); var annotations = GetAnnotations(reflectionVariable); if (typeDesc.Class == ShaderVariableClass.Struct) { //TODO: SharpDx has GetMemberValues on the EffectType. for (int i = 0; i < typeDesc.Members; i++) { var reflectionMember = reflectionVariable.GetMemberByIndex(i); var member = variable.Type.Members[i]; CompareVariable(reflectionMember, member); } } for (int i = 0; i < annotations.Count; i++) { var reflectionAnnotation = annotations[i]; var annotation = variable.Annotations[i]; CompareVariable(reflectionAnnotation, annotation); } if (typeDesc.Type == ShaderVariableType.Blend) { var specDesc = reflectionVariable .AsBlend() .GetBlendState() .Description; } if (typeDesc.Type == ShaderVariableType.ConstantBuffer) { var specDesc = reflectionVariable .AsConstantBuffer() .GetConstantBuffer() .Description; } if (typeDesc.Type == ShaderVariableType.DepthStencil) { var specDesc = reflectionVariable .AsDepthStencil() .GetDepthStencilState() .Description; } if (typeDesc.Type == ShaderVariableType.DepthStencilView) { var specDesc = reflectionVariable .AsDepthStencilView() .GetDepthStencil() .Description; } if (typeDesc.Type == ShaderVariableType.Rasterizer) { var specDesc = reflectionVariable .AsRasterizer() .GetRasterizerState() .Description; } if (typeDesc.Type == ShaderVariableType.Rasterizer) { var specDesc = reflectionVariable .AsRasterizer() .GetRasterizerState() .Description; } if (typeDesc.Type == ShaderVariableType.RenderTargetView) { var specDesc = reflectionVariable .AsRenderTargetView() .GetRenderTarget() .Description; } if (typeDesc.Type == ShaderVariableType.Sampler) { var specDesc = reflectionVariable .AsSampler() .GetSampler() .Description; var stateAnnotations = (variable as Fx10.EffectObjectVariable).Assignments; } if (typeDesc.Type == ShaderVariableType.PixelShader || typeDesc.Type == ShaderVariableType.VertexShader || typeDesc.Type == ShaderVariableType.GeometryShader) { var shader = reflectionVariable .AsShader(); } if (false) { var shader = reflectionVariable .AsShaderResource(); } }
private static EffectTypeDescription CreateTypeInfo(TypeBase variableType, List<AttributeBase> attributes) { var parameterTypeInfo = new EffectTypeDescription(); if (variableType.TypeInference.TargetType != null) variableType = variableType.TypeInference.TargetType; if (variableType is ArrayType) { var arrayType = (ArrayType)variableType; variableType = arrayType.Type; parameterTypeInfo.Elements = (int)((LiteralExpression)arrayType.Dimensions[0]).Literal.Value; if (variableType.TypeInference.TargetType != null) variableType = variableType.TypeInference.TargetType; } if (variableType is ScalarType) { // Uint and int are collapsed to int if (variableType == ScalarType.Int || variableType == ScalarType.UInt) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = variableType == ScalarType.Int ? EffectParameterType.Int : EffectParameterType.UInt; } else if (variableType == ScalarType.Float) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Float; } else if (variableType == ScalarType.Bool) { parameterTypeInfo.Class = EffectParameterClass.Scalar; parameterTypeInfo.Type = EffectParameterType.Bool; } parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = 1; } else if (variableType is VectorType) { if (variableType == VectorType.Float2 || variableType == VectorType.Float3 || variableType == VectorType.Float4) { bool isColor = attributes.OfType<AttributeDeclaration>().Any(x => x.Name == "Color"); parameterTypeInfo.Class = isColor ? EffectParameterClass.Color : EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.Float; } else if (variableType == VectorType.Int2 || variableType == VectorType.Int3 || variableType == VectorType.Int4) { parameterTypeInfo.Class = EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.Int; } else if (variableType == VectorType.UInt2 || variableType == VectorType.UInt3 || variableType == VectorType.UInt4) { parameterTypeInfo.Class = EffectParameterClass.Vector; parameterTypeInfo.Type = EffectParameterType.UInt; } parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = ((VectorType)variableType).Dimension; } else if (variableType is MatrixType) { parameterTypeInfo.Class = EffectParameterClass.MatrixColumns; parameterTypeInfo.Type = EffectParameterType.Float; parameterTypeInfo.RowCount = ((MatrixType)variableType).RowCount; parameterTypeInfo.ColumnCount = ((MatrixType)variableType).ColumnCount; } else if (variableType is StructType) { var structType = (StructType)variableType; parameterTypeInfo.Class = EffectParameterClass.Struct; parameterTypeInfo.RowCount = 1; parameterTypeInfo.ColumnCount = 1; parameterTypeInfo.Name = structType.Name.Text; var members = new List<EffectTypeMemberDescription>(); foreach (var field in structType.Fields) { var memberInfo = new EffectTypeMemberDescription { Name = field.Name.Text, Type = CreateTypeInfo(field.Type, field.Attributes), }; members.Add(memberInfo); } parameterTypeInfo.Members = members.ToArray(); } else { var variableTypeName = variableType.Name.Text.ToLower(); switch (variableTypeName) { case "cbuffer": parameterTypeInfo.Class = EffectParameterClass.ConstantBuffer; parameterTypeInfo.Type = EffectParameterType.ConstantBuffer; break; case "tbuffer": parameterTypeInfo.Class = EffectParameterClass.TextureBuffer; parameterTypeInfo.Type = EffectParameterType.TextureBuffer; break; case "structuredbuffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.StructuredBuffer; break; case "rwstructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWStructuredBuffer; break; case "consumestructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.ConsumeStructuredBuffer; break; case "appendstructuredbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.AppendStructuredBuffer; break; case "buffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Buffer; break; case "rwbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWBuffer; break; case "byteaddressbuffer": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.ByteAddressBuffer; break; case "rwbyteaddressbuffer": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWByteAddressBuffer; break; case "texture1d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture1D; break; case "texturecube": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.TextureCube; break; case "texture2d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2D; break; case "texture3d": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture3D; break; case "texture1darray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture1DArray; break; case "texturecubearray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.TextureCubeArray; break; case "texture2darray": parameterTypeInfo.Class = EffectParameterClass.ShaderResourceView; parameterTypeInfo.Type = EffectParameterType.Texture2DArray; break; case "rwtexture1d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture1D; break; case "rwtexture2d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture2D; break; case "rwtexture3d": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture3D; break; case "rwtexture1darray": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture1DArray; break; case "rwtexture2darray": parameterTypeInfo.Class = EffectParameterClass.UnorderedAccessView; parameterTypeInfo.Type = EffectParameterType.RWTexture2DArray; break; case "samplerstate": case "samplercomparisonstate": parameterTypeInfo.Class = EffectParameterClass.Sampler; parameterTypeInfo.Type = EffectParameterType.Sampler; break; } } return parameterTypeInfo; }
private static int ComputeMemberSize(ref EffectTypeDescription memberType, ref int constantBufferOffset) { var elementSize = ComputeTypeSize(memberType.Type); int size; int alignment = 4; switch (memberType.Class) { case EffectParameterClass.Struct: { // Fill members size = 0; for (int index = 0; index < memberType.Members.Length; index++) { // Properly compute size and offset according to DX rules var memberSize = ComputeMemberSize(ref memberType.Members[index].Type, ref size); // Align offset and store it as member offset memberType.Members[index].Offset = size; // Adjust offset for next item size += memberSize; } alignment = size; break; } case EffectParameterClass.Scalar: { size = elementSize; break; } case EffectParameterClass.Color: case EffectParameterClass.Vector: { size = elementSize * memberType.ColumnCount; break; } case EffectParameterClass.MatrixColumns: { size = elementSize * (4 * (memberType.ColumnCount - 1) + memberType.RowCount); break; } case EffectParameterClass.MatrixRows: { size = elementSize * (4 * (memberType.RowCount - 1) + memberType.ColumnCount); break; } default: throw new NotImplementedException(); } // Update element size memberType.ElementSize = size; // Array if (memberType.Elements > 0) { var roundedSize = (size + 15) / 16 * 16; // Round up to vec4 size += roundedSize * (memberType.Elements - 1); alignment = 16; } // Align to float4 if it is bigger than leftover space in current float4 if (constantBufferOffset / 16 != (constantBufferOffset + size - 1) / 16) alignment = 16; // Align offset and store it as member offset constantBufferOffset = (constantBufferOffset + alignment - 1) / alignment * alignment; return size; }