1 module ppc.shader; 2 import ppc; 3 import ppc.exceptions; 4 5 import std.conv; 6 import std.bitmanip; 7 8 public class ShaderFactory : ContentFactory { 9 public this() { 10 super(TypeId.Shader); 11 } 12 13 public override Content Construct(ubyte[] data) { 14 return new Shader(data); 15 } 16 } 17 18 public enum ShaderType : ubyte { 19 SPIRV, 20 GLSL, 21 PPSL 22 } 23 24 public enum CodeType : ubyte { 25 SPIRVFullShader, 26 PPSLFullShader, 27 Vertex, 28 Geometry, 29 Fragment 30 } 31 32 public class ShaderCode { 33 public CodeType Type; 34 public ubyte[] Code; 35 public @property string CodeString() { return cast(string)Code; } 36 public @property void CodeString(string value) { Code = cast(ubyte[])value; } 37 38 public this(CodeType type) { 39 this.Type = type; 40 this.Code = []; 41 } 42 43 public this(CodeType type, ubyte[] code) { 44 this.Type = type; 45 this.Code = code; 46 } 47 } 48 49 public class Shader : Content { 50 51 public ShaderType Type; 52 public ShaderCode[] Code; 53 54 public this(string name) { 55 super(TypeId.Shader, name); 56 } 57 58 public this(ubyte[] data) { 59 super(data); 60 this.Type = cast(ShaderType)this.data[0]; 61 bool done = false; 62 int i = 1; 63 while (!done) { 64 // Set Code Type Header. 65 CodeType t = cast(CodeType)this.data[i]; 66 i++; 67 68 // Set Length Header. 69 ubyte[4] len_i = this.data[i..i+4]; 70 int length = bigEndianToNative!int(len_i); 71 i += 4; 72 73 if (length == 0) throw new InvalidHeaderSizeException("Shader [Infinite loading loop!]"); 74 75 // Set Shader Code. 76 ubyte[] d = this.data[i..i+length]; 77 i += length; 78 Code.length++; 79 Code[Code.length-1] = new ShaderCode(t, d); 80 81 //Finish off loading the shader code, if no more data is left. 82 if (i+1 >= this.data.length) done = true; 83 } 84 } 85 86 public override void Convert(ubyte[] data) { 87 // Do Nothing, nonconvertible type for now 88 } 89 90 public void Add(ShaderCode code) { 91 this.Code.length++; 92 this.Code[this.Code.length-1] = code; 93 } 94 95 public override ubyte[] Compile() { 96 ubyte[] data = [cast(ubyte)Type]; 97 foreach(ShaderCode c; Code) { 98 99 //Add Type header for shader code. 100 data.length += 1; 101 ulong s = data.length-1; 102 data[s] = cast(ubyte)c.Type; 103 s++; 104 105 //Add Size header for shader code. 106 data.length += 4; 107 int len_i = cast(int)c.Code.length; 108 ubyte[] len = nativeToBigEndian(len_i); 109 s += 4; 110 111 //Add shader code. 112 data.length += c.Code.length; 113 for (int i = 0; i < c.Code.length; i++) { 114 data[s+i] = c.Code[i]; 115 } 116 } 117 return data; 118 } 119 }