/// <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); }
public void IsOwner() { var inputData1 = Symbol.Variable("data"); var ptr1 = new UniquePtr <Symbol>(inputData1); Assert.IsTrue(ptr1.IsOwner); }
public void Constructor() { var inputData = Symbol.Variable("data"); var ptr = new UniquePtr <Symbol>(inputData); ptr.Dispose(); Assert.IsTrue(ptr.IsDisposed); }
public void IsDisposed() { var inputData1 = Symbol.Variable("data"); var ptr1 = new UniquePtr <Symbol>(inputData1); Assert.IsFalse(ptr1.IsDisposed); ptr1.Dispose(); Assert.IsTrue(ptr1.IsDisposed); }
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); }
/// <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); }
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); } } }
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); }
/// <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); }
/// <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(); }
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); }
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); }
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}"); } }