Created
February 28, 2018 17:31
-
-
Save BeRo1985/f3d348353edeaadc45393c9a15cd1908 to your computer and use it in GitHub Desktop.
spirv_variable_extractor.pas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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