/// <summary>
        /// Creates a new <see cref="TransferBuffer{T}"/> instance with the specified parameters.
        /// </summary>
        /// <param name="device">The <see cref="GraphicsDevice"/> associated with the current instance.</param>
        /// <param name="length">The number of items to store in the current buffer.</param>
        /// <param name="resourceType">The resource type for the current buffer.</param>
        /// <param name="allocationMode">The allocation mode to use for the new resource.</param>
        private protected TransferBuffer(GraphicsDevice device, int length, ResourceType resourceType, AllocationMode allocationMode)
        {
            device.ThrowIfDisposed();

            // The maximum length is set such that the aligned buffer size can't exceed uint.MaxValue
            Guard.IsBetweenOrEqualTo(length, 1, (uint.MaxValue / (uint)sizeof(T)) & ~255, nameof(length));

            GraphicsDevice = device;
            Length         = length;

            ulong sizeInBytes = (uint)length * (uint)sizeof(T);

            if (device.IsCacheCoherentUMA)
            {
                this.d3D12Resource = device.D3D12Device->CreateCommittedResource(resourceType, allocationMode, sizeInBytes, true);
            }
            else
            {
                this.allocation    = device.Allocator->CreateResource(resourceType, allocationMode, sizeInBytes);
                this.d3D12Resource = new ComPtr <ID3D12Resource>(this.allocation.Get()->GetResource());
            }

            this.mappedData = (T *)this.d3D12Resource.Get()->Map().Pointer;

            this.d3D12Resource.Get()->SetName(this);
        }
예제 #2
0
        public void IsOwner()
        {
            var inputData1 = Symbol.Variable("data");
            var ptr1       = new UniquePtr <Symbol>(inputData1);

            Assert.IsTrue(ptr1.IsOwner);
        }
예제 #3
0
        public void Constructor()
        {
            var inputData = Symbol.Variable("data");
            var ptr       = new UniquePtr <Symbol>(inputData);

            ptr.Dispose();
            Assert.IsTrue(ptr.IsDisposed);
        }
예제 #4
0
        public void IsDisposed()
        {
            var inputData1 = Symbol.Variable("data");
            var ptr1       = new UniquePtr <Symbol>(inputData1);

            Assert.IsFalse(ptr1.IsDisposed);
            ptr1.Dispose();
            Assert.IsTrue(ptr1.IsDisposed);
        }
예제 #5
0
        public void Move()
        {
            var inputData1 = Symbol.Variable("data");
            var ptr1       = new UniquePtr <Symbol>(inputData1);

            Assert.IsTrue(ptr1.IsOwner);

            UniquePtr <Symbol> .Move(ptr1, out var ptr2);

            Assert.IsFalse(ptr1.IsOwner);
            Assert.IsTrue(ptr2.IsOwner);
        }
예제 #6
0
        /// <summary>
        /// Creates a new <see cref="Buffer{T}"/> instance with the specified parameters.
        /// </summary>
        /// <param name="device">The <see cref="GraphicsDevice"/> associated with the current instance.</param>
        /// <param name="length">The number of items to store in the current buffer.</param>
        /// <param name="elementSizeInBytes">The size in bytes of each buffer item (including padding, if any).</param>
        /// <param name="resourceType">The resource type for the current buffer.</param>
        /// <param name="allocationMode">The allocation mode to use for the new resource.</param>
        private protected Buffer(GraphicsDevice device, int length, uint elementSizeInBytes, ResourceType resourceType, AllocationMode allocationMode)
        {
            device.ThrowIfDisposed();

            if (resourceType == ResourceType.Constant)
            {
                Guard.IsBetweenOrEqualTo(length, 1, FX.D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT, nameof(length));
            }
            else
            {
                // The maximum length is set such that the aligned buffer size can't exceed uint.MaxValue
                Guard.IsBetweenOrEqualTo(length, 1, (uint.MaxValue / elementSizeInBytes) & ~255, nameof(length));
            }

            if (TypeInfo <T> .IsDoubleOrContainsDoubles &&
                device.D3D12Device->CheckFeatureSupport <D3D12_FEATURE_DATA_D3D12_OPTIONS>(D3D12_FEATURE_D3D12_OPTIONS).DoublePrecisionFloatShaderOps == 0)
            {
                UnsupportedDoubleOperationsException.Throw <T>();
            }

            SizeInBytes    = checked ((nint)(length * elementSizeInBytes));
            GraphicsDevice = device;
            Length         = length;

            if (device.IsCacheCoherentUMA)
            {
                this.d3D12Resource = device.D3D12Device->CreateCommittedResource(resourceType, allocationMode, (ulong)SizeInBytes, true);
            }
            else
            {
                this.allocation    = device.Allocator->CreateResource(resourceType, allocationMode, (ulong)SizeInBytes);
                this.d3D12Resource = new ComPtr <ID3D12Resource>(this.allocation.Get()->GetResource());
            }

            device.RentShaderResourceViewDescriptorHandles(out D3D12CpuDescriptorHandle, out D3D12GpuDescriptorHandle);

            switch (resourceType)
            {
            case ResourceType.Constant:
                device.D3D12Device->CreateConstantBufferView(this.d3D12Resource.Get(), SizeInBytes, D3D12CpuDescriptorHandle);
                break;

            case ResourceType.ReadOnly:
                device.D3D12Device->CreateShaderResourceView(this.d3D12Resource.Get(), (uint)length, elementSizeInBytes, D3D12CpuDescriptorHandle);
                break;

            case ResourceType.ReadWrite:
                device.D3D12Device->CreateUnorderedAccessView(this.d3D12Resource.Get(), (uint)length, elementSizeInBytes, D3D12CpuDescriptorHandle);
                break;
            }

            this.d3D12Resource.Get()->SetName(this);
        }
예제 #7
0
        public void Ptr()
        {
            var inputData1 = Symbol.Variable("data");
            var ptr1       = new UniquePtr <Symbol>(inputData1);
            var obj1       = ptr1.Ptr;

            Assert.AreEqual(inputData1, obj1);

            var inputData2 = Symbol.Variable("data");
            var ptr2       = new UniquePtr <Symbol>(inputData2);
            var obj2       = ptr2.Ptr;

            Assert.AreNotEqual(inputData1, obj2);
        }
        /// <inheritdoc/>
        internal override unsafe void CopyTo(ref T destination, int length, int offset)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            Guard.IsInRange(offset, 0, Length, nameof(offset));
            Guard.IsLessThanOrEqualTo(offset + length, Length, nameof(length));

            if (GraphicsDevice.IsCacheCoherentUMA)
            {
                using ID3D12ResourceMap resource = D3D12Resource->Map();

                fixed(void *destinationPointer = &destination)
                {
                    MemoryHelper.Copy(
                        resource.Pointer,
                        (uint)offset,
                        (uint)length,
                        (uint)sizeof(T),
                        destinationPointer);
                }
            }
            else
            {
                nint
                    byteOffset = (nint)offset * sizeof(T),
                    byteLength = length * sizeof(T);

                using UniquePtr <D3D12MA_Allocation> allocation = GraphicsDevice.Allocator->CreateResource(ResourceType.ReadBack, AllocationMode.Default, (ulong)byteLength);

                using (CommandList copyCommandList = new(GraphicsDevice, D3D12_COMMAND_LIST_TYPE_COPY))
                {
                    copyCommandList.D3D12GraphicsCommandList->CopyBufferRegion(allocation.Get()->GetResource(), 0, D3D12Resource, (ulong)byteOffset, (ulong)byteLength);
                    copyCommandList.ExecuteAndWaitForCompletion();
                }

                using ID3D12ResourceMap resource = allocation.Get()->GetResource()->Map();

                fixed(void *destinationPointer = &destination)
                {
                    MemoryHelper.Copy(
                        resource.Pointer,
                        0u,
                        (uint)length,
                        (uint)sizeof(T),
                        destinationPointer);
                }
            }
        }
예제 #9
0
        public void Dispose()
        {
            var inputData1 = Symbol.Variable("data");
            var ptr        = new UniquePtr <Symbol>(inputData1);

            ptr.Dispose();

            try
            {
                ptr.Dispose();
            }
            catch (Exception e)
            {
                Assert.Fail();
            }
        }
        /// <summary>
        /// Creates a new <see cref="TransferTexture3D{T}"/> instance with the specified parameters.
        /// </summary>
        /// <param name="device">The <see cref="ComputeSharp.GraphicsDevice"/> associated with the current instance.</param>
        /// <param name="height">The height of the texture.</param>
        /// <param name="width">The width of the texture.</param>
        /// <param name="depth">The depth of the texture.</param>
        /// <param name="resourceType">The resource type for the current texture.</param>
        /// <param name="allocationMode">The allocation mode to use for the new resource.</param>
        private protected TransferTexture3D(GraphicsDevice device, int width, int height, int depth, ResourceType resourceType, AllocationMode allocationMode)
        {
            device.ThrowIfDisposed();

            Guard.IsBetweenOrEqualTo(width, 1, FX.D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION, nameof(width));
            Guard.IsBetweenOrEqualTo(height, 1, FX.D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION, nameof(height));
            Guard.IsBetweenOrEqualTo(depth, 1, FX.D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION, nameof(depth));

            if (!device.D3D12Device->IsDxgiFormatSupported(DXGIFormatHelper.GetForType <T>(), D3D12_FORMAT_SUPPORT1_TEXTURE3D))
            {
                UnsupportedTextureTypeException.ThrowForTexture2D <T>();
            }

            GraphicsDevice = device;

            device.D3D12Device->GetCopyableFootprint(
                DXGIFormatHelper.GetForType <T>(),
                (uint)width,
                (uint)height,
                (ushort)depth,
                out this.d3D12PlacedSubresourceFootprint,
                out _,
                out ulong totalSizeInBytes);

            if (device.IsCacheCoherentUMA)
            {
                this.d3D12Resource = device.D3D12Device->CreateCommittedResource(resourceType, allocationMode, totalSizeInBytes, true);
            }
            else
            {
                this.allocation    = device.Allocator->CreateResource(resourceType, allocationMode, totalSizeInBytes);
                this.d3D12Resource = new ComPtr <ID3D12Resource>(this.allocation.Get()->GetResource());
            }

            this.mappedData = (T *)this.d3D12Resource.Get()->Map().Pointer;

            this.d3D12Resource.Get()->SetName(this);
        }
예제 #11
0
        /// <summary>
        /// Creates a new <see cref="Texture2D{T}"/> instance with the specified parameters.
        /// </summary>
        /// <param name="device">The <see cref="ComputeSharp.GraphicsDevice"/> associated with the current instance.</param>
        /// <param name="height">The height of the texture.</param>
        /// <param name="width">The width of the texture.</param>
        /// <param name="resourceType">The resource type for the current texture.</param>
        /// <param name="allocationMode">The allocation mode to use for the new resource.</param>
        /// <param name="d3D12FormatSupport">The format support for the current texture type.</param>
        private protected Texture2D(GraphicsDevice device, int width, int height, ResourceType resourceType, AllocationMode allocationMode, D3D12_FORMAT_SUPPORT1 d3D12FormatSupport)
        {
            device.ThrowIfDisposed();

            Guard.IsBetweenOrEqualTo(width, 1, FX.D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, nameof(width));
            Guard.IsBetweenOrEqualTo(height, 1, FX.D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION, nameof(height));

            if (!device.D3D12Device->IsDxgiFormatSupported(DXGIFormatHelper.GetForType <T>(), d3D12FormatSupport))
            {
                UnsupportedTextureTypeException.ThrowForTexture2D <T>();
            }

            GraphicsDevice = device;

            if (device.IsCacheCoherentUMA)
            {
                this.d3D12Resource = device.D3D12Device->CreateCommittedResource(
                    resourceType,
                    allocationMode,
                    DXGIFormatHelper.GetForType <T>(),
                    (uint)width,
                    (uint)height,
                    true,
                    out this.d3D12ResourceState);
            }
            else
            {
                this.allocation = device.Allocator->CreateResource(
                    resourceType,
                    allocationMode,
                    DXGIFormatHelper.GetForType <T>(),
                    (uint)width,
                    (uint)height,
                    out this.d3D12ResourceState);

                this.d3D12Resource = new ComPtr <ID3D12Resource>(this.allocation.Get()->GetResource());
            }

            this.d3D12CommandListType = this.d3D12ResourceState == D3D12_RESOURCE_STATE_COMMON
                ? D3D12_COMMAND_LIST_TYPE_COPY
                : D3D12_COMMAND_LIST_TYPE_COMPUTE;

            device.D3D12Device->GetCopyableFootprint(
                DXGIFormatHelper.GetForType <T>(),
                (uint)width,
                (uint)height,
                out this.d3D12PlacedSubresourceFootprint,
                out _,
                out _);

            device.RentShaderResourceViewDescriptorHandles(out D3D12CpuDescriptorHandle, out D3D12GpuDescriptorHandle);

            switch (resourceType)
            {
            case ResourceType.ReadOnly:
                device.D3D12Device->CreateShaderResourceView(this.d3D12Resource.Get(), DXGIFormatHelper.GetForType <T>(), D3D12_SRV_DIMENSION_TEXTURE2D, D3D12CpuDescriptorHandle);
                break;

            case ResourceType.ReadWrite:
                device.D3D12Device->CreateUnorderedAccessView(this.d3D12Resource.Get(), DXGIFormatHelper.GetForType <T>(), D3D12_UAV_DIMENSION_TEXTURE2D, D3D12CpuDescriptorHandle);
                break;
            }

            this.d3D12Resource.Get()->SetName(this);
        }
예제 #12
0
        /// <summary>
        /// Writes the contents of a given memory area to a specified area of the current <see cref="Texture2D{T}"/> instance.
        /// </summary>
        /// <param name="source">The input memory area to read data from.</param>
        /// <param name="size">The size of the memory area to read data from.</param>
        /// <param name="x">The horizontal offset in the destination texture.</param>
        /// <param name="y">The vertical offset in the destination texture.</param>
        /// <param name="width">The width of the memory area to write to.</param>
        /// <param name="height">The height of the memory area to write to.</param>
        internal void CopyFrom(ref T source, int size, int x, int y, int width, int height)
        {
            GraphicsDevice.ThrowIfDisposed();

            ThrowIfDisposed();

            Guard.IsInRange(x, 0, Width, nameof(x));
            Guard.IsInRange(y, 0, Height, nameof(y));
            Guard.IsBetweenOrEqualTo(width, 1, Width, nameof(width));
            Guard.IsBetweenOrEqualTo(height, 1, Height, nameof(height));
            Guard.IsLessThanOrEqualTo(x + width, Width, nameof(x));
            Guard.IsLessThanOrEqualTo(y + height, Height, nameof(y));
            Guard.IsGreaterThanOrEqualTo(size, (nint)width * height, nameof(size));

            GraphicsDevice.D3D12Device->GetCopyableFootprint(
                DXGIFormatHelper.GetForType <T>(),
                (uint)width,
                (uint)height,
                out D3D12_PLACED_SUBRESOURCE_FOOTPRINT d3D12PlacedSubresourceFootprintSource,
                out ulong rowSizeInBytes,
                out ulong totalSizeInBytes);

            using UniquePtr <D3D12MA_Allocation> allocation = default;
            using ComPtr <ID3D12Resource> d3D12Resource     = default;

            if (GraphicsDevice.IsCacheCoherentUMA)
            {
                *&d3D12Resource = GraphicsDevice.D3D12Device->CreateCommittedResource(ResourceType.Upload, AllocationMode.Default, totalSizeInBytes, true);
            }
            else
            {
                *&allocation    = GraphicsDevice.Allocator->CreateResource(ResourceType.Upload, AllocationMode.Default, totalSizeInBytes);
                *&d3D12Resource = new ComPtr <ID3D12Resource>(allocation.Get()->GetResource());
            }

            using (ID3D12ResourceMap resource = d3D12Resource.Get()->Map())
                fixed(void *sourcePointer = &source)
                {
                    MemoryHelper.Copy(
                        sourcePointer,
                        resource.Pointer,
                        (uint)height,
                        rowSizeInBytes,
                        d3D12PlacedSubresourceFootprintSource.Footprint.RowPitch);
                }

            using CommandList copyCommandList = new(GraphicsDevice, this.d3D12CommandListType);

            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->ResourceBarrier(D3D12Resource, this.d3D12ResourceState, D3D12_RESOURCE_STATE_COPY_DEST);
            }

            copyCommandList.D3D12GraphicsCommandList->CopyTextureRegion(
                d3D12ResourceDestination: D3D12Resource,
                destinationX: (uint)x,
                destinationY: (uint)y,
                destinationZ: 0,
                d3D12ResourceSource: d3D12Resource.Get(),
                &d3D12PlacedSubresourceFootprintSource,
                sourceX: 0,
                sourceY: 0,
                sourceZ: 0,
                (uint)width,
                (uint)height,
                depth: 1);

            if (copyCommandList.D3D12CommandListType == D3D12_COMMAND_LIST_TYPE_COMPUTE)
            {
                copyCommandList.D3D12GraphicsCommandList->ResourceBarrier(D3D12Resource, D3D12_RESOURCE_STATE_COPY_DEST, this.d3D12ResourceState);
            }

            copyCommandList.ExecuteAndWaitForCompletion();
        }
예제 #13
0
        public static unsafe bool TryGetMesh(Renderable renderable, [MaybeNullWhen(false)] out Mesh mesh)
        {
            ArgumentNullException.ThrowIfNull(renderable);

            if (renderable.TryGetScreen(out var screen) == false)
            {
                goto FAILURE;
            }
            if (Engine.CurrentContext != screen)
            {
                goto FAILURE;
            }
            if (renderable.IsLoaded == false)
            {
                goto FAILURE;
            }

            const uint IndexSize = sizeof(int);

            var vertexType = renderable.VertexType;

            Debug.Assert(vertexType != null);
            if (VertexMarshalHelper.TryGetVertexTypeData(vertexType, out var vertexTypeData) == false)
            {
                goto FAILURE;
            }

            var vertexSize = (ulong)vertexTypeData.VertexSize;

            Debug.Assert(vertexType != null);

            var vbo = renderable.VBO;
            var ibo = renderable.IBO;

            var verticesCount    = vbo.Length;
            var indicesCount     = ibo.Length;
            var verticesByteSize = verticesCount * vertexSize;
            var indicesByteSize  = indicesCount * IndexSize;

            var bufLen = verticesByteSize + indicesByteSize;
            var buf    = UniquePtr.Malloc(checked ((nuint)bufLen));
            var vDest  = (void *)buf.Ptr;
            var iDest  = buf.GetPtr <byte>() + verticesByteSize;

            try {
                try {
                    VBO.Bind(vbo);
                    var vSource = (void *)VBO.MapBufferReadOnly();
                    Buffer.MemoryCopy(vSource, vDest, bufLen, verticesByteSize);
                }
                finally {
                    VBO.UnmapBuffer();
                    VBO.Unbind();
                }
                try {
                    IBO.Bind(ibo);
                    var iSource = (void *)IBO.MapBufferReadOnly();
                    Buffer.MemoryCopy(iSource, iDest, bufLen, indicesByteSize);
                }
                finally {
                    IBO.UnmapBuffer();
                    IBO.Unbind();
                }
                mesh = Mesh.Create(vertexTypeData, IndexSize, vDest, verticesByteSize, iDest, indicesByteSize, ref buf, static buf => buf.Dispose());
                return(true);
            }
            finally {
                buf.Dispose();
            }

FAILURE:
            mesh = null;
            return(false);
        }
예제 #14
0
        public static GMFile /* errors: different return type? */ ReadFile(string baseDir, JsonData projFile)
        {
            var f = new GMFile();

            // OBJT: depends on SPRT, obj<->id map
            // ROOM: depends on OBJT, BGND
            // SCPT: depends on CODE

            if (projFile.Has("chunkorder") && projFile["chunkorder"].IsArray)
            {
                f.ChunkOrder = DeserializeArray(projFile["chunkorder"], jd => SectionHeadersExtensions.FromChunkName((string)jd));
            }
            else
            {
                Console.Error.WriteLine("Warning: Project file doesn't have a chunk order. You should export with a newer Altar.NET version.");
                f.ChunkOrder = new SectionHeaders[] {
                    SectionHeaders.General,
                    SectionHeaders.Options,
                    SectionHeaders.Language,
                    SectionHeaders.Extensions,
                    SectionHeaders.Sounds,
                    SectionHeaders.AudioGroup,
                    SectionHeaders.Sprites,
                    SectionHeaders.Backgrounds,
                    SectionHeaders.Paths,
                    SectionHeaders.Scripts,
                    SectionHeaders.Globals,
                    SectionHeaders.Shaders,
                    SectionHeaders.Fonts,
                    SectionHeaders.Timelines,
                    SectionHeaders.Objects,
                    SectionHeaders.Rooms,
                    SectionHeaders.DataFiles,
                    SectionHeaders.TexturePage,
                    SectionHeaders.Code,
                    SectionHeaders.Variables,
                    SectionHeaders.Functions,
                    SectionHeaders.Strings,
                    SectionHeaders.Textures,
                    SectionHeaders.Audio,
                    SectionHeaders.EmbedImage,
                };
            }

            if (projFile.Has("general"))
            {
                Console.WriteLine("Loading general...");
                try
                {
                    f.General = DeserializeGeneral(LoadJson(baseDir, (string)(projFile["general"])));
                    if (f.General.Version >= new Version(2, 0))
                    {
                        Console.Error.WriteLine("Warning: GM:S 2.0 support is incomplete!");
                    }
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading general");
                    throw;
                }
            }
            if (projFile.Has("options"))
            {
                Console.WriteLine("Loading options...");
                try
                {
                    f.Options = DeserializeOptions(LoadJson(baseDir, (string)(projFile["options"])));
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading options");
                    throw;
                }
            }
            if (projFile.Has("strings"))
            {
                Console.WriteLine("Loading strings...");
                try
                {
                    f.Strings = DeserializeArray(LoadJson(baseDir, (string)(projFile["strings"])), jd => (string)jd);
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading strings");
                    throw;
                }
            }

            var variables = new ReferenceDef[0];
            var functions = new ReferenceDef[0];

            if (projFile.Has("variables"))
            {
                Console.WriteLine("Loading variables...");
                try
                {
                    var vardata = LoadJson(baseDir, (string)(projFile["variables"]));
                    variables = DeserializeArray(vardata.IsArray ? vardata : vardata["variables"], DeserializeReferenceDef);
                    if (vardata.Has("extra"))
                    {
                        f.VariableExtra = DeserializeArray(vardata["extra"], jd => (uint)jd);
                    }
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading variables");
                    throw;
                }
            }
            if (projFile.Has("functions"))
            {
                Console.WriteLine("Loading functions...");
                try
                {
                    var funcdata = LoadJson(baseDir, (string)(projFile["functions"]));
                    functions = DeserializeArray(funcdata.IsArray ? funcdata : funcdata["functions"], DeserializeReferenceDef);
                    if (funcdata.Has("locals"))
                    {
                        f.FunctionLocals = DeserializeArray(funcdata["locals"], DeserializeFuncLocals);
                    }
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading functions");
                    throw;
                }
            }
            f.RefData = new RefData {
                Variables = variables, Functions = functions
            };

            if (projFile.Has("textures"))
            {
                Console.WriteLine("Loading textures...");
                var textures = projFile["textures"].ToArray();
                var ts       = new TextureInfo[textures.Length];
                for (int i = 0; i < textures.Length; i++)
                {
                    try
                    {
                        var texinfo = new TextureInfo
                        {
                            PngData = File.ReadAllBytes(Path.Combine(baseDir, (string)(textures[i])))
                        };

                        var bp = new UniquePtr(texinfo.PngData);

                        unsafe
                        {
                            var png = (PngHeader *)bp.BPtr;

                            texinfo.Width  = Utils.SwapEnd32(png->IHDR.Width);
                            texinfo.Height = Utils.SwapEnd32(png->IHDR.Height);
                        }

                        ts[i] = texinfo;
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {textures[i]}");
                        throw;
                    }
                }
                f.Textures = ts;
            }
            if (projFile.Has("tpags"))
            {
                Console.Write("Loading texture pages... ");
                var cl = Console.CursorLeft;
                var ct = Console.CursorTop;

                var tpags = projFile["tpags"].ToArray();
                var tps   = new TexturePageInfo[tpags.Length];
                for (int i = 0; i < tpags.Length; i++)
                {
                    Console.SetCursorPosition(cl, ct);
                    Console.WriteLine(O_PAREN + (i + 1) + SLASH + tpags.Length + C_PAREN);
                    try
                    {
                        tps[i] = DeserializeTPag(LoadJson(baseDir, (string)(tpags[i])));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {tpags[i]}");
                        throw;
                    }
                }
                f.TexturePages = tps;
            }
            if (projFile.Has("audio"))
            {
                Console.WriteLine("Loading audio...");
                var audio = projFile["audio"].ToArray();
                var ais   = new AudioInfo[audio.Length];
                for (int i = 0; i < audio.Length; i++)
                {
                    try
                    {
                        var audioinfo = new AudioInfo
                        {
                            Wave = File.ReadAllBytes(Path.Combine(baseDir, (string)(audio[i])))
                        };
                        ais[i] = audioinfo;
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {audio[i]}");
                        throw;
                    }
                }
                f.Audio = ais;
            }
            if (projFile.Has("sprites"))
            {
                Console.Write("Loading sprites... ");
                var cl = Console.CursorLeft;
                var ct = Console.CursorTop;

                var sprites = projFile["sprites"].ToArray();
                var ss      = new SpriteInfo[sprites.Length];
                for (int i = 0; i < sprites.Length; i++)
                {
                    Console.SetCursorPosition(cl, ct);
                    Console.WriteLine(O_PAREN + (i + 1) + SLASH + sprites.Length + C_PAREN);
                    try
                    {
                        ss[i]      = DeserializeSprite(LoadJson(baseDir, (string)(sprites[i])));
                        ss[i].Name = Path.GetFileNameWithoutExtension((string)(sprites[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {sprites[i]}");
                        throw;
                    }
                }
                f.Sprites = ss;
            }
            if (projFile.Has("objs"))
            {
                Console.Write("Loading objects... ");
                var cl = Console.CursorLeft;
                var ct = Console.CursorTop;

                var objs     = projFile["objs"].ToArray();
                var objNames = objs.Select(o => Path.GetFileNameWithoutExtension((string)o)).ToArray();
                var os       = new ObjectInfo[objs.Length];
                for (int i = 0; i < objs.Length; i++)
                {
                    Console.SetCursorPosition(cl, ct);
                    Console.WriteLine(O_PAREN + (i + 1) + SLASH + objs.Length + C_PAREN);
                    try
                    {
                        os[i] = DeserializeObj(
                            LoadJson(baseDir, (string)(objs[i])),
                            f.Sprites,
                            s => (uint)Array.IndexOf(objNames, s));
                        os[i].Name = objNames[i];
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {objs[i]}");
                        throw;
                    }
                }
                f.Objects = os;
            }
            if (projFile.Has("code"))
            {
                Console.WriteLine("Loading code...");
                var code = projFile["code"].ToArray();
                var cs   = new CodeInfo[code.Length];

                var strings = new StringsListBuilder();
                strings.AddStrings(f.Strings);
                IDictionary <string, uint> objectIndices = new Dictionary <string, uint>(f.Objects.Length);
                for (uint i = 0; i < f.Objects.Length; i++)
                {
                    objectIndices[f.Objects[i].Name] = i;
                }

                for (int i = 0; i < code.Length; i++)
                {
                    Console.WriteLine((string)(code[i]));
                    try
                    {
                        cs[i] = Assembler.DeserializeCodeFromFile(Path.Combine(baseDir, (string)(code[i])), f.General.BytecodeVersion,
                                                                  strings, objectIndices);
                        cs[i].Name          = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension((string)(code[i])));
                        cs[i].ArgumentCount = 1;
                        if (f.FunctionLocals != null)
                        {
                            for (int j = 0; j < f.FunctionLocals.Length; j++)
                            {
                                int fastIndex = (j + i) % f.FunctionLocals.Length;
                                if (f.FunctionLocals[fastIndex].FunctionName == cs[i].Name)
                                {
                                    cs[i].ArgumentCount = f.FunctionLocals[fastIndex].LocalNames.Length;
                                    break;
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {code[i]}");
                        throw;
                    }
                }
                f.Code = cs;

                f.Strings = strings.GetStrings();
            }
            if (projFile.Has("sounds"))
            {
                Console.WriteLine("Loading sounds...");
                var sounds = projFile["sounds"].ToArray();
                var ss     = new SoundInfo[sounds.Length];
                for (int i = 0; i < sounds.Length; i++)
                {
                    try
                    {
                        ss[i]      = DeserializeSound(LoadJson(baseDir, (string)(sounds[i])));
                        ss[i].Name = Path.GetFileNameWithoutExtension((string)(sounds[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {sounds[i]}");
                        throw;
                    }
                }
                f.Sound = ss;
            }
            if (projFile.Has("bg"))
            {
                Console.WriteLine("Loading backgrounds...");
                var bg = projFile["bg"].ToArray();
                var bs = new BackgroundInfo[bg.Length];
                for (int i = 0; i < bg.Length; i++)
                {
                    try
                    {
                        bs[i]      = DeserializeBg(LoadJson(baseDir, (string)(bg[i])));
                        bs[i].Name = Path.GetFileNameWithoutExtension((string)(bg[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {bg[i]}");
                        throw;
                    }
                }
                f.Backgrounds = bs;
            }
            if (projFile.Has("paths"))
            {
                Console.WriteLine("Loading paths...");
                var paths = projFile["paths"].ToArray();
                var ps    = new PathInfo[paths.Length];
                for (int i = 0; i < paths.Length; i++)
                {
                    try
                    {
                        ps[i]      = DeserializePath(LoadJson(baseDir, (string)(paths[i])));
                        ps[i].Name = Path.GetFileNameWithoutExtension((string)(paths[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {paths[i]}");
                        throw;
                    }
                }
                f.Paths = ps;
            }
            if (projFile.Has("scripts"))
            {
                Console.WriteLine("Loading scripts...");
                var scripts = projFile["scripts"].ToArray();
                var ss      = new ScriptInfo[scripts.Length];
                for (int i = 0; i < scripts.Length; i++)
                {
                    try
                    {
                        ss[i]      = DeserializeScript(LoadJson(baseDir, (string)(scripts[i])), f.Code);
                        ss[i].Name = Path.GetFileNameWithoutExtension((string)(scripts[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {scripts[i]}");
                        throw;
                    }
                }
                f.Scripts = ss;
            }
            if (projFile.Has("fonts"))
            {
                Console.WriteLine("Loading fonts...");
                var fonts = projFile["fonts"].ToArray();
                var fs    = new FontInfo[fonts.Length];
                for (int i = 0; i < fonts.Length; i++)
                {
                    try
                    {
                        fs[i]          = DeserializeFont(LoadJson(baseDir, (string)(fonts[i])));
                        fs[i].CodeName = Path.GetFileNameWithoutExtension((string)(fonts[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {fonts[i]}");
                        throw;
                    }
                }
                f.Fonts = fs;
            }
            if (projFile.Has("rooms"))
            {
                Console.Write("Loading rooms... ");
                var cl = Console.CursorLeft;
                var ct = Console.CursorTop;

                var rooms = projFile["rooms"].ToArray();
                var rs    = new RoomInfo[rooms.Length];
                for (int i = 0; i < rooms.Length; i++)
                {
                    Console.SetCursorPosition(cl, ct);
                    Console.WriteLine(O_PAREN + (i + 1) + SLASH + rooms.Length + C_PAREN);
                    try
                    {
                        rs[i]      = DeserializeRoom(LoadJson(baseDir, (string)(rooms[i])), f.Backgrounds, f.Objects);
                        rs[i].Name = Path.GetFileNameWithoutExtension((string)(rooms[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {rooms[i]}");
                        throw;
                    }
                }
                f.Rooms = rs;
            }
            if (projFile.Has("audiogroups"))
            {
                Console.WriteLine("Loading audio groups...");
                try
                {
                    f.AudioGroups = DeserializeArray(LoadJson(baseDir, (string)(projFile["audiogroups"])), jd => (string)jd);
                }
                catch (Exception)
                {
                    Console.Error.WriteLine("Error loading audio groups");
                    throw;
                }
            }
            if (projFile.Has("shaders"))
            {
                Console.WriteLine("Loading shaders...");
                var shaders = projFile["shaders"].ToArray();
                var ss      = new ShaderInfo[shaders.Length];
                for (int i = 0; i < shaders.Length; i++)
                {
                    try
                    {
                        ss[i]      = DeserializeShader(LoadJson(baseDir, (string)(shaders[i])));
                        ss[i].Name = Path.GetFileNameWithoutExtension((string)(shaders[i]));
                    }
                    catch (Exception)
                    {
                        Console.Error.WriteLine($"Error loading {shaders[i]}");
                        throw;
                    }
                }
                f.Shaders = ss;
            }
            return(f);
        }
예제 #15
0
        private static void Main(string[] args)
        {
            //var minScore = float.Parse(args[0], NumberStyles.Float, null);
            var minScore = 0.9f;

            const int   imageSize    = 28;
            var         layers       = new[] { 128, 64, 10 };
            const int   batchSize    = 100;
            const int   maxEpoch     = 10;
            const float learningRate = 0.1f;
            const float weightDecay  = 1e-2f;

            var trainIter = new MXDataIter("MNISTIter")
                            .SetParam("image", "./mnist_data/train-images-idx3-ubyte")
                            .SetParam("label", "./mnist_data/train-labels-idx1-ubyte")
                            .SetParam("batch_size", batchSize)
                            .SetParam("flat", 1)
                            .CreateDataIter();
            var valIter = new MXDataIter("MNISTIter")
                          .SetParam("image", "./mnist_data/t10k-images-idx3-ubyte")
                          .SetParam("label", "./mnist_data/t10k-labels-idx1-ubyte")
                          .SetParam("batch_size", batchSize)
                          .SetParam("flat", 1)
                          .CreateDataIter();

            var net = Mlp(layers);

            var ctx = Context.Cpu();  // Use GPU for training

            var dictionary = new Dictionary <string, NDArray>();

            dictionary["X"]     = new NDArray(new Shape(batchSize, imageSize * imageSize), ctx);
            dictionary["label"] = new NDArray(new Shape(batchSize), ctx);
            // Let MXNet infer shapes of other parameters such as weights
            net.InferArgsMap(ctx, dictionary, dictionary);

            // Initialize all parameters with uniform distribution U(-0.01, 0.01)
            var initializer = new Uniform(0.01f);

            foreach (var arg in dictionary)
            {
                // arg.first is parameter name, and arg.second is the value
                initializer.Operator(arg.Key, arg.Value);
            }

            // Create sgd optimizer
            var opt = OptimizerRegistry.Find("sgd");

            opt.SetParam("rescale_grad", 1.0 / batchSize)
            .SetParam("lr", learningRate)
            .SetParam("wd", weightDecay);
            var lrSch = new UniquePtr <LRScheduler>(new FactorScheduler(5000, 0.1f));

            opt.SetLearningRateScheduler(lrSch);

            // Create executor by binding parameters to the model
            using (var exec = net.SimpleBind(ctx, dictionary))
            {
                var argNames = net.ListArguments();

                float score = 0;
                // Start training

                var sw = new Stopwatch();
                for (var iter = 0; iter < maxEpoch; ++iter)
                {
                    var samples = 0;
                    trainIter.Reset();

                    sw.Restart();
                    while (trainIter.Next())
                    {
                        samples += batchSize;
                        var dataBatch = trainIter.GetDataBatch();
                        // Data provided by DataIter are stored in memory, should be copied to GPU first.
                        dataBatch.Data.CopyTo(dictionary["X"]);
                        dataBatch.Label.CopyTo(dictionary["label"]);
                        // CopyTo is imperative, need to wait for it to complete.
                        NDArray.WaitAll();

                        // Compute gradients
                        exec.Forward(true);
                        exec.Backward();
                        // Update parameters
                        for (var i = 0; i < argNames.Count; ++i)
                        {
                            if (argNames[i] == "X" || argNames[i] == "label")
                            {
                                continue;
                            }

                            var weight = exec.ArgmentArrays[i];
                            var grad   = exec.GradientArrays[i];
                            opt.Update(i, weight, grad);
                        }
                    }

                    sw.Stop();

                    var acc = new Accuracy();
                    valIter.Reset();
                    while (valIter.Next())
                    {
                        var dataBatch = valIter.GetDataBatch();
                        dataBatch.Data.CopyTo(dictionary["X"]);
                        dataBatch.Label.CopyTo(dictionary["label"]);
                        NDArray.WaitAll();
                        // Only forward pass is enough as no gradient is needed when evaluating
                        exec.Forward(false);
                        acc.Update(dataBatch.Label, exec.Outputs[0]);
                    }

                    var duration = sw.ElapsedMilliseconds / 1000.0;
                    var message  = $"Epoch: {iter} {samples / duration} samples/sec Accuracy: {acc.Get()}";
                    Logging.LG(message);
                    score = acc.Get();
                }

                MXNet.MXNotifyShutdown();
                var ret = score >= minScore ? 0 : 1;
                Console.WriteLine($"{ret}");
            }
        }