Skip to content

Instantly share code, notes, and snippets.

@BeRo1985
Created February 28, 2018 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BeRo1985/f3d348353edeaadc45393c9a15cd1908 to your computer and use it in GitHub Desktop.
Save BeRo1985/f3d348353edeaadc45393c9a15cd1908 to your computer and use it in GitHub Desktop.
spirv_variable_extractor.pas
function TpvVulkanShaderModule.GetVariables:TpvVulkanShaderModuleVariables;
// https://www.khronos.org/registry/spir-v/specs/1.1/SPIRV.html
type PUInt32Array=^TUInt32Array;
TUInt32Array=array[0..65535] of TpvUInt32;
var Position,Size:TpvInt32;
Opcode,Index,NameIndex,Count,CountIDs,CountNames:TpvUInt32;
Opcodes:PUInt32Array;
Endian:boolean;
Variable:PpvVulkanShaderModuleVariable;
Bindings,Locations,DescriptorSets:array of TpvUInt32;
DebugNames:array of TVkCharString;
function SwapEndian(const Value:TpvUInt32):TpvUInt32;
begin
if Endian then begin
result:=(((Value shr 0) and $ff) shl 24) or
(((Value shr 8) and $ff) shl 16) or
(((Value shr 16) and $ff) shl 8) or
(((Value shr 24) and $ff) shl 0);
end else begin
result:=Value;
end;
end;
begin
result:=nil;
Bindings:=nil;
Locations:=nil;
DescriptorSets:=nil;
DebugNames:=nil;
Count:=0;
try
Opcodes:=fData;
if assigned(Opcodes) and (fDataSize>=(6*SizeOf(TpvUInt32))) and ((Opcodes^[0]=$07230203) or (Opcodes^[0]=$03022307)) then begin
Endian:=Opcodes[0]=$03022307;
Opcodes:=TpvPointer(@Opcodes[5]);
Size:=(fDataSize shr 2)-5;
CountIDs:=0;
CountNames:=0;
Position:=0;
while Position<Size do begin
Opcode:=SwapEndian(Opcodes^[Position]);
case Opcode and $ffff of
$0005{OpName}:begin
CountNames:=Max(CountNames,SwapEndian(Opcodes^[Position+1])+1);
end;
$003b{OpVariable}:begin
inc(Count);
end;
$0047{OpOpDecorate}:begin
CountIDs:=Max(CountIDs,SwapEndian(Opcodes^[Position+1])+1);
end;
end;
inc(Position,Opcode shr 16);
end;
SetLength(result,Count);
try
SetLength(Bindings,CountIDs);
SetLength(Locations,CountIDs);
SetLength(DescriptorSets,CountIDs);
SetLength(DebugNames,CountNames);
Position:=0;
while Position<Size do begin
Opcode:=SwapEndian(Opcodes^[Position]);
case Opcode and $ffff of
$0005{OpName}:begin
Index:=SwapEndian(Opcodes^[Position+1]);
if Index<CountNames then begin
DebugNames[Index]:=PVkChar(TpvPointer(@Opcodes^[Position+2]));
end;
end;
$0047{OpDecorate}:begin
Index:=SwapEndian(Opcodes^[Position+1]);
if Index<CountIDs then begin
case Opcodes^[Position+2] of
$0000001e{Location}:begin
Locations[Index]:=SwapEndian(Opcodes^[Position+3]);
end;
$00000021{Binding}:begin
Bindings[Index]:=SwapEndian(Opcodes^[Position+3]);
end;
$00000022{DescriptorSet}:begin
DescriptorSets[Index]:=SwapEndian(Opcodes^[Position+3]);
end;
end;
end;
end;
end;
inc(Position,Opcode shr 16);
end;
Count:=0;
Position:=0;
while Position<Size do begin
Opcode:=SwapEndian(Opcodes^[Position]);
case Opcode and $ffff of
$003b{OpVariable}:begin
Variable:=@result[Count];
inc(Count);
Index:=SwapEndian(Opcodes^[Position+1]);
if Index<CountIDs then begin
Variable^.fLocation:=Locations[Index];
Variable^.fBinding:=Bindings[Index];
Variable^.fDescriptorSet:=DescriptorSets[Index];
end else begin
Variable^.fLocation:=0;
Variable^.fBinding:=0;
Variable^.fDescriptorSet:=0;
end;
NameIndex:=SwapEndian(Opcodes^[Position+2]);
if NameIndex<CountNames then begin
Variable^.fDebugName:=DebugNames[NameIndex];
end else begin
Variable^.fDebugName:='';
end;
Variable^.fName:=NameIndex;
Variable^.fInstruction:=Position;
Variable^.fStorageClass:=TpvVulkanShaderModuleVariableStorageClass(SwapEndian(Opcodes^[Position+3]));
end;
end;
inc(Position,Opcode shr 16);
end;
finally
Bindings:=nil;
Locations:=nil;
DescriptorSets:=nil;
DebugNames:=nil;
end;
end;
finally
SetLength(result,Count);
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment