private WorldData AllocateWorldData(MgStorageBlockAllocationRequest dynamiceRequest, uint maxUniformBufferRange) { const uint LOW_RES = 16384; const uint HIGH_RES = 65536; if (maxUniformBufferRange < LOW_RES) { throw new InvalidOperationException("not enough space"); } var noOfCameras = 32U; var noOfLights = 256U; if (maxUniformBufferRange >= HIGH_RES) { noOfCameras = 128U; noOfLights = 1024U; } var upperLimit = (maxUniformBufferRange >= HIGH_RES) ? HIGH_RES : LOW_RES; var cameraStride = Marshal.SizeOf(typeof(CameraUBO)); var lightStride = Marshal.SizeOf(typeof(LightUBO)); var cameraLength = cameraStride * noOfCameras; var lightLength = lightStride * noOfLights; var totalSize = (ulong)(cameraLength + lightLength); if (totalSize > upperLimit) { throw new InvalidOperationException("not enough space for uniform block"); } var location = dynamiceRequest.Insert( new MgStorageBlockAllocationInfo { Usage = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT, MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT, Size = totalSize, } ); return(new WorldData { StorageIndex = location, MaxNoOfCameras = noOfCameras, MaxNoOfLights = noOfLights, }); }
private static int ExtractVertices(uint vertexCount, MgStorageBlockAllocationRequest request, MgtfAccessor[] accessors, MgtfBufferView[] bufferViews, IMgtfPerVertexDataLocator locator, out GltfInterleavedOperation[] vertexCopies) { var totalSize = 0UL; var vertexFields = new int?[] { locator.Position, locator.Normal, locator.Tangent, locator.TexCoords0, locator.TexCoords1, locator.Color0, locator.Color1, locator.Joints0, locator.Joints1, locator.Weights0, locator.Weights1, }; var DEFAULT_PADDING_BYTE_STRIDE = new uint[] { 12U, 12U, 16U, 8U, 8U, 16U, 16U, 4U, 4U, 16U, 16U, }; var copyOps = new List <GltfInterleavedOperation>(); var vertexBufferStride = 0U; for (var i = 0; i < vertexFields.Length; i += 1) { var field = vertexFields[i]; if (field.HasValue) { var selected = accessors[field.Value]; var op = GenerateCopyOperation(selected, bufferViews); copyOps.Add(op); vertexBufferStride += op.ByteStride; totalSize += selected.TotalByteSize; } else { vertexBufferStride += DEFAULT_PADDING_BYTE_STRIDE[i]; totalSize += vertexCount * DEFAULT_PADDING_BYTE_STRIDE[i]; } } foreach (var op in copyOps) { op.DstStride = vertexBufferStride; } var vertexInfo = new MgStorageBlockAllocationInfo { MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_COHERENT_BIT, Usage = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT, ElementByteSize = vertexBufferStride, Size = totalSize, }; vertexCopies = copyOps.ToArray(); return(request.Insert(vertexInfo)); }
private GltfPrimitiveStorageLocation[] AllocateMeshes( MgStorageBlockAllocationRequest request, MgtfMesh[] meshes, MgtfAccessor[] accessors, MgtfBufferView[] bufferViews) { var noOfMeshes = meshes != null ? meshes.Length : 0; var locations = new List <GltfPrimitiveStorageLocation>(); for (var i = 0; i < noOfMeshes; i += 1) { var mesh = meshes[i]; var noOfPrimitives = mesh.Primitives != null ? mesh.Primitives.Length : 0; for (var j = 0; j < noOfPrimitives; j += 1) { var primitive = mesh.Primitives[j]; var locator = primitive.VertexLocations; int?indexLocation = null; GltfInterleavedOperation indexCopy = null; if (locator.Indices.HasValue) { var accessor = accessors[locator.Indices.Value]; indexCopy = GenerateCopyOperation(accessor, bufferViews); indexCopy.DstStride = accessor.ElementByteSize; indexLocation = request.Insert(GetIndexAllocation(accessor)); } var vertexLocation = ExtractVertices( primitive.VertexCount, request, accessors, bufferViews, locator, out GltfInterleavedOperation[] vertexCopies); var copyOperations = new List <GltfInterleavedOperation>(); if (indexCopy != null) { copyOperations.Add(indexCopy); } copyOperations.AddRange(vertexCopies); var location = new GltfPrimitiveStorageLocation { Mesh = i, MeshPrimitive = j, FinalDefinition = PadVertexDefinition(primitive.InitialDefinition), Index = indexLocation, Vertex = vertexLocation, CopyOperations = copyOperations.ToArray(), }; locations.Add(location); } } return(locations.ToArray()); }
private static int[] AllocateMaterials(MgtfMaterial[] materials, MgStorageBlockAllocationRequest dynamicRequest, MgPhysicalDeviceLimits limits) { // materials var query = new PerMaterialTextureStorageQuery(limits); var noOfSamplers = query.GetMaxNoOfCombinedImageSamplers(); const uint PBR_TEXTURES_PER_MATERIALS = 5U; var blockSize = (uint)Marshal.SizeOf(typeof(MaterialUBO)); const uint HI_RES = 32U; const uint LOW_RES = 16U; // GONNA RESERVE 5 BINDINGS SLOTS // IN VK, a global binding range is used by all descriptors // IN OPENGL/WEBGL, buffer and textures have the own binding range // THEREFORE, Mg standard is not to overlap binding values between descriptors // OTHERWISE, separate sets implementation (TODO) could be used to handle separate ranges const uint NO_OF_RESERVED_BINDINGS = 5U; var range = noOfSamplers - NO_OF_RESERVED_BINDINGS; if (noOfSamplers < LOW_RES) { throw new InvalidOperationException("not enough combined samplers for pbr"); } // pick between hi res and low res bool isHighRes = (noOfSamplers >= HI_RES); uint bindableImages = isHighRes ? 32U : 16U; var elementRange = query.GetElementRange( MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT, PBR_TEXTURES_PER_MATERIALS, blockSize); if (isHighRes) { // floor(no_of_samplers - reserved_slots / textures_per_mat) = floor((32 - 5)/5) = 5 if (elementRange < 5U) { throw new InvalidOperationException("hi res not applicable"); } elementRange = 5U; } else { // floor(no_of_samplers - reserved_slots / textures_per_mat) = floor((16 - 5)/5) = 2 if (elementRange < 2U) { throw new InvalidOperationException("low res not applicable"); } elementRange = 2U; } var noOfAllocations = (materials.Length / elementRange); noOfAllocations += (materials.Length % elementRange == 0) ? 0 : 1; var info = new MgStorageBlockAllocationInfo { Usage = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT, MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT, Size = elementRange * blockSize, }; var materialIndices = new int[noOfAllocations]; for (var i = 0; i < noOfAllocations; i += 1) { materialIndices[i] = dynamicRequest.Insert(info); } return(materialIndices); }