Reduce allocations for Spir-v serialization

Passes BinaryWriter instead of the stream to Write and WriteOperand

- Removes creation of BinaryWriter for each instruction
- Removes allocations for literal string
This commit is contained in:
riperiperi 2022-02-15 19:17:33 +00:00
parent 301ddec36f
commit 12dec18f39
5 changed files with 25 additions and 27 deletions

View file

@ -111,15 +111,13 @@ namespace Spv.Generator
AddOperand(LiteralInteger.CreateForEnum(value)); AddOperand(LiteralInteger.CreateForEnum(value));
} }
public void Write(Stream stream) public void Write(BinaryWriter writer)
{ {
BinaryWriter writer = new BinaryWriter(stream);
// Word 0 // Word 0
writer.Write((ushort)Opcode); writer.Write((ushort)Opcode);
writer.Write(GetTotalWordCount()); writer.Write(GetTotalWordCount());
_resultType?.WriteOperand(stream); _resultType?.WriteOperand(writer);
if (Id != InvalidId) if (Id != InvalidId)
{ {
@ -128,11 +126,11 @@ namespace Spv.Generator
foreach (Operand operand in _operands) foreach (Operand operand in _operands)
{ {
operand.WriteOperand(stream); operand.WriteOperand(writer);
} }
} }
public void WriteOperand(Stream stream) public void WriteOperand(BinaryWriter writer)
{ {
Debug.Assert(Id != InvalidId); Debug.Assert(Id != InvalidId);
@ -156,7 +154,7 @@ namespace Spv.Generator
throw new InvalidOperationException($"Id wasn't bound to the module, please make sure to call {methodToCall}"); throw new InvalidOperationException($"Id wasn't bound to the module, please make sure to call {methodToCall}");
} }
stream.Write(BitConverter.GetBytes(Id)); writer.Write(Id);
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View file

@ -53,9 +53,9 @@ namespace Spv.Generator
public ushort WordCount => (ushort)(_data.Length / 4); public ushort WordCount => (ushort)(_data.Length / 4);
public void WriteOperand(Stream stream) public void WriteOperand(BinaryWriter writer)
{ {
stream.Write(_data); writer.Write(_data);
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View file

@ -17,15 +17,15 @@ namespace Spv.Generator
public ushort WordCount => (ushort)(_value.Length / 4 + 1); public ushort WordCount => (ushort)(_value.Length / 4 + 1);
public void WriteOperand(Stream stream) public void WriteOperand(BinaryWriter writer)
{ {
byte[] rawValue = Encoding.ASCII.GetBytes(_value); writer.Write(_value.AsSpan());
stream.Write(rawValue); int paddingSize = 4 - (Encoding.ASCII.GetByteCount(_value) % 4);
int paddingSize = 4 - (rawValue.Length % 4); Span<byte> padding = stackalloc byte[paddingSize];
stream.Write(new byte[paddingSize]); writer.Write(padding);
} }
public override bool Equals(object obj) public override bool Equals(object obj)

View file

@ -247,7 +247,7 @@ namespace Spv.Generator
{ {
using (MemoryStream stream = new MemoryStream()) using (MemoryStream stream = new MemoryStream())
{ {
BinaryWriter writer = new BinaryWriter(stream); BinaryWriter writer = new BinaryWriter(stream, System.Text.Encoding.ASCII);
// Header // Header
writer.Write(MagicNumber); writer.Write(MagicNumber);
@ -262,7 +262,7 @@ namespace Spv.Generator
Instruction capabilityInstruction = new Instruction(Op.OpCapability); Instruction capabilityInstruction = new Instruction(Op.OpCapability);
capabilityInstruction.AddOperand(capability); capabilityInstruction.AddOperand(capability);
capabilityInstruction.Write(stream); capabilityInstruction.Write(writer);
} }
// 2. // 2.
@ -271,44 +271,44 @@ namespace Spv.Generator
Instruction extensionInstruction = new Instruction(Op.OpExtension); Instruction extensionInstruction = new Instruction(Op.OpExtension);
extensionInstruction.AddOperand(extension); extensionInstruction.AddOperand(extension);
extensionInstruction.Write(stream); extensionInstruction.Write(writer);
} }
// 3. // 3.
foreach (Instruction extInstImport in _extInstImports) foreach (Instruction extInstImport in _extInstImports)
{ {
extInstImport.Write(stream); extInstImport.Write(writer);
} }
// 4. // 4.
Instruction memoryModelInstruction = new Instruction(Op.OpMemoryModel); Instruction memoryModelInstruction = new Instruction(Op.OpMemoryModel);
memoryModelInstruction.AddOperand(_addressingModel); memoryModelInstruction.AddOperand(_addressingModel);
memoryModelInstruction.AddOperand(_memoryModel); memoryModelInstruction.AddOperand(_memoryModel);
memoryModelInstruction.Write(stream); memoryModelInstruction.Write(writer);
// 5. // 5.
foreach (Instruction entrypoint in _entrypoints) foreach (Instruction entrypoint in _entrypoints)
{ {
entrypoint.Write(stream); entrypoint.Write(writer);
} }
// 6. // 6.
foreach (Instruction executionMode in _executionModes) foreach (Instruction executionMode in _executionModes)
{ {
executionMode.Write(stream); executionMode.Write(writer);
} }
// 7. // 7.
// TODO: order debug information correclty. // TODO: order debug information correclty.
foreach (Instruction debug in _debug) foreach (Instruction debug in _debug)
{ {
debug.Write(stream); debug.Write(writer);
} }
// 8. // 8.
foreach (Instruction annotation in _annotations) foreach (Instruction annotation in _annotations)
{ {
annotation.Write(stream); annotation.Write(writer);
} }
// Ensure that everything is in the right order in the declarations section // Ensure that everything is in the right order in the declarations section
@ -320,19 +320,19 @@ namespace Spv.Generator
// 9. // 9.
foreach (Instruction declaration in declarations) foreach (Instruction declaration in declarations)
{ {
declaration.Write(stream); declaration.Write(writer);
} }
// 10. // 10.
foreach (Instruction functionDeclaration in _functionsDeclarations) foreach (Instruction functionDeclaration in _functionsDeclarations)
{ {
functionDeclaration.Write(stream); functionDeclaration.Write(writer);
} }
// 11. // 11.
foreach (Instruction functionDefinition in _functionsDefinitions) foreach (Instruction functionDefinition in _functionsDefinitions)
{ {
functionDefinition.Write(stream); functionDefinition.Write(writer);
} }
return stream.ToArray(); return stream.ToArray();

View file

@ -9,6 +9,6 @@ namespace Spv.Generator
ushort WordCount { get; } ushort WordCount { get; }
void WriteOperand(Stream stream); void WriteOperand(BinaryWriter writer);
} }
} }