Пример #1
0
 internal static void AddAttributeDescriptions(
     int binding,
     ResizeArray <VertexInputAttributeDescription> attributes)
 {
     //Float4x4 matrix takes 4 'locations' and needs to be bound as 4 separate float4's
     attributes.Add(new VertexInputAttributeDescription(
                        location: attributes.Count,
                        binding: binding,
                        format: Format.R32G32B32A32SFloat, //float4
                        offset: 0));                       //In bytes from the beginning of the struct
     attributes.Add(new VertexInputAttributeDescription(
                        location: attributes.Count,
                        binding: binding,
                        format: Format.R32G32B32A32SFloat, //float4
                        offset: Float4.SIZE));             //In bytes from the beginning of the struct
     attributes.Add(new VertexInputAttributeDescription(
                        location: attributes.Count,
                        binding: binding,
                        format: Format.R32G32B32A32SFloat, //float4
                        offset: Float4.SIZE * 2));         //In bytes from the beginning of the struct
     attributes.Add(new VertexInputAttributeDescription(
                        location: attributes.Count,
                        binding: binding,
                        format: Format.R32G32B32A32SFloat, //float4
                        offset: Float4.SIZE * 3));         //In bytes from the beginning of the struct
     //Age
     attributes.Add(new VertexInputAttributeDescription(
                        location: attributes.Count,
                        binding: binding,
                        format: Format.R32SFloat, //float
                        offset: Float4x4.SIZE));
 }
Пример #2
0
        internal Chunk(
            Device logicalDevice,
            HostDevice hostDevice,
            Location location,
            int supportedMemoryTypesFilter,
            long size = 128 *ByteUtils.MEGABYTE_TO_BYTE)
        {
            if (logicalDevice == null)
            {
                throw new ArgumentNullException(nameof(logicalDevice));
            }
            if (hostDevice == null)
            {
                throw new ArgumentNullException(nameof(hostDevice));
            }
            this.logicalDevice = logicalDevice;
            this.location      = location;
            totalSize          = size;

            //Add a block the size of the entire chunk to the free set
            freeBlocks.Add(new Block(container: this, offset: 0, size: size));

            //Find the memory type on the gpu to place this pool in
            memoryTypeIndex = hostDevice.GetMemoryType(
                properties: location == Location.Device ?
                MemoryProperties.DeviceLocal :
                MemoryProperties.HostVisible,
                supportedTypesFilter: supportedMemoryTypesFilter);
            //Allocate the memory
            memory = logicalDevice.AllocateMemory(new MemoryAllocateInfo(
                                                      allocationSize: size,
                                                      memoryTypeIndex: memoryTypeIndex));
        }
        internal static void AddAttributeDescriptions(
            int binding,
            ResizeArray <VertexInputAttributeDescription> attributes)
        {
            int offset = 0;

            for (int i = 0; i < 5; i++)
            {
                switch (i)
                {
                case 0: //Position
                    attributes.Add(new VertexInputAttributeDescription(
                                       location: attributes.Count,
                                       binding: binding,
                                       format: Format.R32G32B32SFloat, //float3
                                       offset: offset));               //In bytes from the beginning of the struct
                    offset += Float3.SIZE;
                    break;

                case 1: //Color
                    attributes.Add(new VertexInputAttributeDescription(
                                       location: attributes.Count,
                                       binding: binding,
                                       format: Format.R32G32B32A32SFloat, //float4
                                       offset: offset));                  //In bytes from the beginning of the struct
                    offset += Float4.SIZE;
                    break;

                case 2: //Normal
                    attributes.Add(new VertexInputAttributeDescription(
                                       location: attributes.Count,
                                       binding: binding,
                                       format: Format.R32G32B32SFloat, //float3
                                       offset: offset));               //In bytes from the beginning of the struct
                    offset += Float3.SIZE;
                    break;

                case 3: //Uv1
                    attributes.Add(new VertexInputAttributeDescription(
                                       location: attributes.Count,
                                       binding: binding,
                                       format: Format.R32G32SFloat, //float2
                                       offset: offset));            //In bytes from the beginning of the struct
                    offset += Float2.SIZE;
                    break;

                case 4: //Uv2
                    attributes.Add(new VertexInputAttributeDescription(
                                       location: attributes.Count,
                                       binding: binding,
                                       format: Format.R32G32SFloat, //float2
                                       offset: offset));            //In bytes from the beginning of the struct
                    offset += Float2.SIZE;
                    break;
                }
            }
        }
        private void ParseFloatSetArray <T>(XmlElement element, ResizeArray <T> output)
            where T : struct, IFloatSet
        {
            output.Clear();

            //Get meta data
            XmlElement accessorElement = element.GetChild("technique_common")?.GetChild("accessor");

            if (accessorElement == null)
            {
                throw new Exception($"[{nameof(ColladaParser)}] 'accessor' element");
            }
            int count  = int.Parse(accessorElement.Tag.GetAttributeValue("count"));
            int stride = int.Parse(accessorElement.Tag.GetAttributeValue("stride"));

            //Get raw data
            XmlElement arrayElement = element.GetChild("float_array");

            if (arrayElement == null)
            {
                throw new Exception($"[{nameof(ColladaParser)}] 'float_array' missing");
            }

            XmlDataEntry?dataEntry = arrayElement.FirstData;

            if (dataEntry == null)
            {
                throw new Exception($"[{nameof(ColladaParser)}] Data is missing");
            }

            int componentCount = FloatSetUtils.GetComponentCount <T>();

            if (componentCount > stride)
            {
                throw new Exception(
                          $"[{nameof(ColladaParser)}] Data has too little component for given type, expected: {componentCount}, got: {stride}");
            }
            int dataToSkip = stride - componentCount;

            par.Seek(dataEntry.Value.StartBytePosition);
            for (int i = 0; i < count; i++)
            {
                output.Add(par.ConsumeFloatSet <T>());
                //If there is extra data we don't want to load then we skip over that
                for (int j = 0; j < dataToSkip; j++)
                {
                    par.ExpectConsume(' ');
                    par.ConsumeFloat();
                }
                par.ConsumeWhitespace(includeNewline: true);
            }
            if (par.CurrentBytePosition > dataEntry.Value.EndBytePosition)
            {
                throw new Exception($"[{nameof(ColladaParser)}] Data was bigger then expected");
            }
        }
Пример #5
0
            internal Chunk(Device logicalDevice, ReadOnlySpan <IShaderInput> inputs, int size = 5)
            {
                types = new DescriptorType[inputs.Length];
                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = inputs[i].DescriptorType;
                }

                //Gather how many inputs of each type we have
                var poolSizes = new ResizeArray <DescriptorPoolSize>();

                for (int i = 0; i < types.Length; i++)
                {
                    for (int j = 0; j < poolSizes.Count; j++)
                    {
                        if (poolSizes.Data[j].Type == types[i])
                        {
                            poolSizes.Data[j].DescriptorCount += size;
                            continue;
                        }
                    }
                    poolSizes.Add(new DescriptorPoolSize(types[i], size));
                }

                //Create a pool for 'size' types the amount of resources of one set
                pool = logicalDevice.CreateDescriptorPool(new DescriptorPoolCreateInfo(
                                                              maxSets: size,
                                                              poolSizes: poolSizes.ToArray(),
                                                              flags: DescriptorPoolCreateFlags.None));

                //Create a layout that matches the inputs
                layout = CreateLayout(logicalDevice, inputs);

                //Even tho we use the same layout for the entire pool the 'VkDescriptorSetAllocateInfo'
                //expects a layout per allocation so we create a array of layouts all pointing to the
                //same layout
                var layouts = new DescriptorSetLayout[size];

                for (int i = 0; i < layouts.Length; i++)
                {
                    layouts[i] = layout;
                }

                //Pre-allocate all the sets from the pool
                sets = pool.AllocateSets(new DescriptorSetAllocateInfo(
                                             descriptorSetCount: size,
                                             setLayouts: layouts));

                //Mark all the sets as being free
                isFree = new bool[size];
                for (int i = 0; i < isFree.Length; i++)
                {
                    isFree[i] = true;
                }
            }
Пример #6
0
        public int Add <T>() where T : struct
        {
            ThrowIfDisposed();

            int size    = Unsafe.SizeOf <T>();
            int binding = entries.Count;

            entries.Add(new Entry(currentSize, size));
            currentSize += size;
            return(binding);
        }
        public static Mesh CreatePlane(int segments, float size)
        {
            //Create the vertices
            Vertex[] vertices = new Vertex[segments * segments];
            Float3   offset   = (x : size * .5f, y : 0f, z : size * .5f);

            for (int z = 0; z < segments; z++)
            {
                for (int x = 0; x < segments; x++)
                {
                    float xProg = (float)x / (segments - 1);
                    float zProg = (float)z / (segments - 1);
                    vertices[x + z * segments] = new Vertex(
                        position: (xProg * size, 0f, zProg * size) - offset,
                        color: Float4.One,
                        normal: Float3.Up,
                        uv1: new Float2(xProg, zProg),
                        uv2: new Float2(xProg, zProg));
                }
            }

            //Create the indices
            ResizeArray <UInt16> indices = new ResizeArray <UInt16>();

            for (int z = 1; z < segments; z++) //Start at 1 because we handle 2 'rows' in one iteration
            {
                //Strip row
                for (int x = 0; x < segments; x++)
                {
                    indices.Add((UInt16)(x + segments * z));
                    indices.Add((UInt16)(x + segments * (z - 1)));
                }
                //Restart strip
                indices.Add(Mesh.RESTART_INDEX);
            }

            return(new Mesh(vertices, indices.ToArray(), Mesh.TopologyType.TriangleStrip));
        }
        public void Add <T>(T data) where T : struct
        {
            ThrowIfDisposed();

            int dataSize = Unsafe.SizeOf <T>();

            memory.Write(data, currentSize);

            entries.Add(new SpecializationMapEntry(
                            constantId: entries.Count,
                            offset: (int)currentSize,
                            size: new Size(dataSize)));

            currentSize += dataSize;
        }
        public Mesh Parse()
        {
            if (par.Current.IsEndOfFile)
            {
                throw new Exception($"[{nameof(WavefrontObjParser)}] Stream allready at the end");
            }

            while (!par.Current.IsEndOfFile)
            {
                par.ConsumeWhitespace(); //Ignore whitespace before the id
                string id = par.ConsumeWord();
                par.ConsumeWhitespace(); //Ignore whitespace after the id
                switch (id)
                {
                case "v": positions.Add(par.ConsumeFloatSet <Float3>()); break;

                case "vn": normals.Add(par.ConsumeFloatSet <Float3>()); break;

                case "vt": texcoords.Add(par.ConsumeFloatSet <Float2>()); break;

                case "f":
                {
                    elementCache.Clear();
                    while (!par.Current.IsEndOfLine)
                    {
                        elementCache.Add(ConsumeFaceElement());
                        par.ConsumeWhitespace();
                    }
                    if (elementCache.Count < 3)
                    {
                        throw par.CreateError("At least 3 vertices are required to create a face");
                    }
                    faces.Add(new Face(elementCache.ToArray()));
                }
                break;
                }
                //Ignore everything we don't know about
                par.ConsumeRestOfLine();

                //End the token with a newline
                if (!par.Current.IsEndOfFile)
                {
                    par.ConsumeNewline();
                }
            }
            return(CreateMesh());
        }
Пример #10
0
        public void PushVertex(Vertex vertex)
        {
            //Filter out similar vertices to reduce vertex count
            int index = FindSimilar(vertex);

            if (index < 0)
            {
                if (vertices.Count >= UInt16.MaxValue)
                {
                    throw new Exception(
                              $"[{nameof(MeshBuilder)}] Only '{UInt16.MaxValue}' vertices are supported");
                }
                index = vertices.Count;
                vertices.Add(vertex);
            }
            indices.Add((UInt16)index);
        }
Пример #11
0
    public void Update()
    {
        if (!assigned && enter && Application.isEditor && !Application.isPlaying)
        {
            LightmapData data = new LightmapData();
            // copy to folder and import the copied and assign them
            if (far != null)
            {
                data.lightmapColor = far;
            }
            if (near != null)
            {
                data.lightmapDir = near;
            }


            int  i      = 0;
            bool exists = false;
            foreach (LightmapData dt in LightmapSettings.lightmaps)
            {
                if (dt.lightmapColor == far && dt.lightmapDir == near)
                {
                    this.GetComponent <Renderer>().lightmapIndex = i;
                    exists = true;
                    break;
                }

                i++;
            }
            if (!exists)
            {
                ResizeArray.Add(LightmapSettings.lightmaps.Length, data);
                this.GetComponent <Renderer>().lightmapIndex = LightmapSettings.lightmaps.Length - 1;
            }

            assigned = true;
            DestroyImmediate(this);
        }
    }
        internal static Pipeline CreatePipeline(
            Device logicalDevice,
            RenderPass renderpass,
            PipelineLayout layout,
            ShaderModule vertModule,
            ShaderModule fragModule,
            SpecializationContainer specializationContainer,
            bool depthClamp,
            bool depthBias,
            ReadOnlySpan <DeviceTexture> targets,
            IInternalRenderObject renderObject)
        {
            if (logicalDevice == null)
            {
                throw new ArgumentNullException(nameof(logicalDevice));
            }
            if (renderpass == null)
            {
                throw new ArgumentNullException(nameof(renderpass));
            }

            var shaderStages = new []
            {
                new PipelineShaderStageCreateInfo(
                    stage: ShaderStages.Vertex, module: vertModule, name: "main",
                    specializationInfo: specializationContainer?.GetInfo()),
                new PipelineShaderStageCreateInfo(
                    stage: ShaderStages.Fragment,
                    module: fragModule, name: "main",
                    specializationInfo: specializationContainer?.GetInfo())
            };
            var depthTest = new PipelineDepthStencilStateCreateInfo {
                DepthTestEnable       = true,
                DepthWriteEnable      = true,
                DepthCompareOp        = CompareOp.LessOrEqual,
                DepthBoundsTestEnable = false,
                StencilTestEnable     = false
            };
            var rasterizer = new PipelineRasterizationStateCreateInfo(
                depthClampEnable: depthClamp,
                rasterizerDiscardEnable: false,
                polygonMode: PolygonMode.Fill,
                cullMode: CullModes.Back,
                frontFace: renderObject.GetFrontFace(),
                depthBiasEnable: depthBias,
                depthBiasConstantFactor: .1f,
                depthBiasSlopeFactor: 1.75f,
                lineWidth: 1f
                );

            //Gather all the color targets and setup a blend-state for them
            ResizeArray <PipelineColorBlendAttachmentState> blendAttachments =
                new ResizeArray <PipelineColorBlendAttachmentState>();

            for (int i = 0; i < targets.Length; i++)
            {
                if (!targets[i].DepthTexture)
                {
                    blendAttachments.Add(new PipelineColorBlendAttachmentState(
                                             colorWriteMask: ColorComponents.All, blendEnable: false));
                }
            }

            var blending = new PipelineColorBlendStateCreateInfo(
                attachments: blendAttachments.ToArray(),
                logicOpEnable: false
                );
            var multisampleState = new PipelineMultisampleStateCreateInfo(
                rasterizationSamples: SampleCounts.Count1,
                sampleShadingEnable: false
                );
            //Pass the viewport and scissor-rect as dynamic so we are not tied to swapchain size
            //the advantage is this is that we don't need to recreate the pipeline on swapchain
            //resize
            var dynamicState = new PipelineDynamicStateCreateInfo(
                DynamicState.Viewport,
                DynamicState.Scissor
                );

            return(logicalDevice.CreateGraphicsPipeline(new GraphicsPipelineCreateInfo(
                                                            layout: layout,
                                                            renderPass: renderpass,
                                                            subpass: 0,
                                                            stages: shaderStages,
                                                            inputAssemblyState: renderObject.GetInputAssemblyStateInfo(),
                                                            vertexInputState: renderObject.GetVertexInputState(),
                                                            rasterizationState: rasterizer,
                                                            tessellationState: null,
                                                            //Pass empty viewport and scissor-rect as we set them dynamically
                                                            viewportState: new PipelineViewportStateCreateInfo(new Viewport(), new Rect2D()),
                                                            multisampleState: multisampleState,
                                                            depthStencilState: depthTest,
                                                            colorBlendState: blending,
                                                            dynamicState: dynamicState,
                                                            flags: PipelineCreateFlags.None
                                                            )));
        }
        private void ParseTriangles(XmlElement meshElement)
        {
            XmlElement trianglesElement = meshElement.GetChild("triangles");
            XmlElement polygonsElement  = trianglesElement ?? meshElement.GetChild("polygons");

            if (polygonsElement == null || !polygonsElement.HasChildren)
            {
                throw new Exception($"[{nameof(ColladaParser)}] Triangles / Polygons element missing");
            }

            //Parse all the triangles data
            triangleCount = int.Parse(polygonsElement.Tag.GetAttributeValue("count"));
            for (int i = 0; i < polygonsElement.Children.Count; i++)
            {
                ParseTriangleElement(polygonsElement.Children[i]);
            }
            if (indices.Count != triangleCount * 3 * inputStride)
            {
                throw new Exception($"[{nameof(ColladaParser)}] Incorrect indices count found");
            }

            //The triangle input can contain a VERTEX element with more data, we want to resolve
            //that here so we end of with just a flat list of attributes
            for (int i = 0; i < inputs.Count; i++)
            {
                Input input = inputs.Data[i];
                if (input.Semantic == "VERTEX")
                {
                    XmlElement vertexElement = meshElement.GetChildWithAttribute(
                        name: "vertices",
                        attributeName: "id",
                        attributeValue: input.Source);
                    for (int j = 0; j < vertexElement.Children.Count; j++)
                    {
                        XmlElement vertexInput = vertexElement.Children[j];
                        if (vertexInput.HasName("input"))
                        {
                            string semantic        = vertexInput.Tag.GetAttributeValue("semantic");
                            string sourceReference = GetSourceReference(vertexInput);
                            inputs.Add(new Input(semantic, input.Offset, set: -1, sourceReference));
                        }
                    }
                }
            }

            void ParseTriangleElement(XmlElement triangleElement)
            {
                //The input elements contain info about what is in the indices
                if (triangleElement.HasName("input"))
                {
                    string semantic        = triangleElement.Tag.GetAttributeValue("semantic");
                    int    offset          = int.Parse(triangleElement.Tag.GetAttributeValue("offset"));
                    int    set             = int.Parse(triangleElement.Tag.GetAttributeValue("set", "-1"));
                    string sourceReference = GetSourceReference(triangleElement);
                    inputStride = Max(inputStride, offset + 1);
                    inputs.Add(new Input(semantic, offset, set, sourceReference));
                }

                // The 'p' (primitive) element contains the actual indices
                if (triangleElement.HasName("p"))
                {
                    XmlDataEntry?dataEntry = triangleElement.FirstData;
                    if (dataEntry == null)
                    {
                        throw new Exception($"[{nameof(ColladaParser)}] Data is missing");
                    }

                    //Read the indices
                    par.Seek(dataEntry.Value.StartBytePosition);
                    while (par.CurrentBytePosition < dataEntry.Value.EndBytePosition)
                    {
                        par.ConsumeWhitespace(includeNewline: true);
                        indices.Add(par.ConsumeInt());
                    }
                }
            }
        }
        private static RenderPass CreateRenderPass(
            Device logicalDevice,
            ReadOnlySpan <DeviceTexture> targets)
        {
            ResizeArray <AttachmentReference> colorReferences = new ResizeArray <AttachmentReference>();
            AttachmentReference?depthReference = null;

            var attachmentDescriptions = new AttachmentDescription[targets.Length];

            for (int i = 0; i < targets.Length; i++)
            {
                //Create the description
                attachmentDescriptions[i] = new AttachmentDescription(
                    flags: AttachmentDescriptions.MayAlias,
                    format: targets[i].Format,
                    samples: SampleCounts.Count1,
                    loadOp: AttachmentLoadOp.Clear,
                    storeOp: AttachmentStoreOp.Store,
                    stencilLoadOp: AttachmentLoadOp.DontCare,
                    stencilStoreOp: AttachmentStoreOp.DontCare,
                    initialLayout: ImageLayout.Undefined,
                    finalLayout: targets[i].DesiredLayout);
                //Add the reference (either color or depth)
                if (targets[i].DepthTexture)
                {
                    if (depthReference != null)
                    {
                        throw new Exception(
                                  $"[{nameof(Renderer)}] Only 1 depth target can be used at a time");
                    }
                    else
                    {
                        depthReference = new AttachmentReference(i, ImageLayout.DepthStencilAttachmentOptimal);
                    }
                }
                else
                {
                    colorReferences.Add(new AttachmentReference(i, ImageLayout.ColorAttachmentOptimal));
                }
            }
            //Dependency at the beginning to transition the attachments to the proper layout
            var beginTransitionDependency = new SubpassDependency(
                srcSubpass: Constant.SubpassExternal,
                dstSubpass: 0, //Our subpass
                srcStageMask: PipelineStages.BottomOfPipe,
                srcAccessMask: Accesses.MemoryRead,
                dstStageMask: PipelineStages.ColorAttachmentOutput,
                dstAccessMask: Accesses.ColorAttachmentWrite,
                dependencyFlags: Dependencies.None
                );
            //Dependency at the end to transition the attachments to the final layout
            var endTransitionDependency = new SubpassDependency(
                srcSubpass: 0, //Our subpass
                dstSubpass: Constant.SubpassExternal,
                srcStageMask: PipelineStages.ColorAttachmentOutput,
                srcAccessMask: Accesses.ColorAttachmentWrite,
                dstStageMask: PipelineStages.BottomOfPipe,
                dstAccessMask: Accesses.MemoryRead,
                dependencyFlags: Dependencies.None
                );

            return(logicalDevice.CreateRenderPass(new RenderPassCreateInfo(
                                                      subpasses: new []
            {
                new SubpassDescription
                (
                    flags: SubpassDescriptionFlags.None,
                    colorAttachments: colorReferences.ToArray(),
                    depthStencilAttachment: depthReference
                )
            },
                                                      attachments: attachmentDescriptions,
                                                      dependencies: new [] { beginTransitionDependency, endTransitionDependency }
                                                      )));
        }