internal void Write(EndianWriter writer) { foreach (VariableHeader header in m_variableHeaders) { WriteVariableHeader(writer, header); } foreach (Variable variable in m_variables) { writer.WriteStringZeroTerm(variable.Name); WriteShaderType(writer, variable.ShaderType); foreach (ShaderTypeMember member in variable.ShaderType.Members) { uint nameOffset = m_variableNameLookup[member.Name]; writer.Write(nameOffset); uint memberOffset = m_typeLookup[member.ShaderType]; writer.Write(memberOffset); writer.Write(member.Index); } foreach (ShaderTypeMember member in variable.ShaderType.Members) { writer.WriteStringZeroTerm(member.Name); WriteShaderType(writer, member.ShaderType); } } }
internal void Write(EndianWriter writer) { foreach (var header in variableHeaders) { WriteVariableHeader(writer, header); } foreach (var variable in variables) { writer.WriteStringZeroTerm(variable.Name); WriteShaderType(writer, variable.ShaderType); foreach (var member in variable.ShaderType.members) { var nameOffset = variableNameLookup[member.Name]; writer.Write(nameOffset); var memberOffset = typeLookup[member.ShaderType]; writer.Write(memberOffset); writer.Write(member.Index); } foreach (var member in variable.ShaderType.members) { writer.WriteStringZeroTerm(member.Name); WriteShaderType(writer, member.ShaderType); } } }
public void Write(EndianWriter writer) { writer.Write(Encoding.ASCII.GetBytes("RDEF")); writer.Write(m_chunkSize); writer.Write(m_constantBuffers.Count); writer.Write(m_constantBufferOffset); writer.Write(m_resourceBindings.Count); writer.Write(m_resourceBindingOffset); byte minorVersion = 0; writer.Write(minorVersion); writer.Write(m_majorVersion); writer.Write((ushort)m_programType); var flags = ShaderFlags.NoPreshader; writer.Write((uint)flags); writer.Write(m_creatorStringOffset); if (m_majorVersion >= 5) { //rd11 writer.Write(Encoding.ASCII.GetBytes("RD11")); //unknown1 writer.Write((uint)60); //unknown2 writer.Write((uint)24); //unknown3 writer.Write((uint)32); //unknown4 writer.Write((uint)40); //unknown5 writer.Write((uint)36); //unknown6 writer.Write((uint)12); //InterfaceSlotCount writer.Write((uint)0); } m_resourceBindings.Write(writer); m_constantBuffers.Write(writer); writer.WriteStringZeroTerm(m_creatorString); }
internal void Write(EndianWriter writer) { uint bindPoint = 0; foreach (var bufferParam in shaderSubprogram.BufferParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[bufferParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Structured); //Resource return type writer.Write((uint)ResourceReturnType.Mixed); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Buffer); //Number of samples writer.Write((uint)56); //TODO: Check this //Bind point writer.Write((uint)bufferParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var textureParam in shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Sampler); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)textureParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var textureParam in shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Texture); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)textureParam.Dim); //Number of samples writer.Write(uint.MaxValue); //Bind point writer.Write((uint)textureParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var constantBuffer in shaderSubprogram.ConstantBufferBindings) { //Resource bindings //nameOffset writer.Write(nameLookup[constantBuffer.Name]); //shader input type writer.Write((uint)ShaderInputType.CBuffer); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)constantBuffer.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } foreach (var bufferParam in shaderSubprogram.BufferParameters) { writer.WriteStringZeroTerm(bufferParam.Name); } foreach (var textureParam in shaderSubprogram.TextureParameters) { writer.WriteStringZeroTerm(textureParam.Name); } foreach (var constantBuffer in shaderSubprogram.ConstantBufferBindings) { writer.WriteStringZeroTerm(constantBuffer.Name); } }
internal void Write(EndianWriter writer) { uint bindPoint = 0; foreach (BufferBinding bufferParam in m_shaderSubprogram.BufferParameters) { //Resource bindings //nameOffset writer.Write(m_nameLookup[bufferParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Structured); //Resource return type writer.Write((uint)ResourceReturnType.Mixed); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Buffer); //Number of samples writer.Write((uint)56); //TODO: Check this //Bind point writer.Write((uint)bufferParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } //Unity doesn't give us a good way of reconstructing the sampler header, //this is probably wrong but good enough bindPoint = 0; foreach (TextureParameter textureParam in m_shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(m_nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Sampler); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)textureParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (TextureParameter textureParam in m_shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(m_nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Texture); //Resource return type writer.Write((uint)ResourceReturnType.Float); //Resource view dimension writer.Write((uint)GetTextureDimension(textureParam)); //Number of samples writer.Write(uint.MaxValue); //Bind point writer.Write((uint)textureParam.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.TextureComponents); } bindPoint = 0; foreach (BufferBinding constantBuffer in m_shaderSubprogram.ConstantBufferBindings) { //Resource bindings //nameOffset writer.Write(m_nameLookup[constantBuffer.Name]); //shader input type writer.Write((uint)ShaderInputType.CBuffer); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)constantBuffer.Index); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } foreach (BufferBinding bufferParam in m_shaderSubprogram.BufferParameters) { writer.WriteStringZeroTerm(bufferParam.Name); } foreach (TextureParameter textureParam in m_shaderSubprogram.TextureParameters) { writer.WriteStringZeroTerm(textureParam.Name); } foreach (BufferBinding constantBuffer in m_shaderSubprogram.ConstantBufferBindings) { writer.WriteStringZeroTerm(constantBuffer.Name); } }
internal void Write(EndianWriter writer) { foreach (BufferBinding bufferParam in m_shaderSubprogram.BufferParameters) { //Resource bindings //nameOffset writer.Write(m_nameLookup[bufferParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Structured); //Resource return type writer.Write((uint)ResourceReturnType.Mixed); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Buffer); //Number of samples writer.Write((uint)56); //TODO: Check this //Bind point writer.Write((uint)bufferParam.Index); //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } foreach (Sampler sampler in m_Samplers) { //Resource bindings //nameOffset writer.Write(m_nameLookup[sampler.Name]); //shader input type writer.Write((uint)ShaderInputType.Sampler); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)sampler.BindPoint); //Bind count writer.Write((uint)1); //Shader input flags ShaderInputFlags samplerFlags = sampler.IsComparisonSampler ? ShaderInputFlags.ComparisonSampler : ShaderInputFlags.None; writer.Write((uint)samplerFlags); } foreach (TextureParameter textureParam in m_shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(m_nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Texture); //Resource return type writer.Write((uint)ResourceReturnType.Float); //Resource view dimension writer.Write((uint)GetTextureDimension(textureParam)); //Number of samples writer.Write(uint.MaxValue); //Bind point writer.Write((uint)textureParam.Index); //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.TextureComponents); } foreach (BufferBinding constantBuffer in m_shaderSubprogram.ConstantBufferBindings) { //Resource bindings //nameOffset writer.Write(m_nameLookup[constantBuffer.Name]); //shader input type writer.Write((uint)ShaderInputType.CBuffer); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write((uint)constantBuffer.Index); //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } foreach (BufferBinding bufferParam in m_shaderSubprogram.BufferParameters) { writer.WriteStringZeroTerm(bufferParam.Name); } foreach (TextureParameter textureParam in m_shaderSubprogram.TextureParameters) { writer.WriteStringZeroTerm(textureParam.Name); } foreach (Sampler sampler in m_Samplers) { writer.WriteStringZeroTerm(sampler.Name); } foreach (BufferBinding constantBuffer in m_shaderSubprogram.ConstantBufferBindings) { writer.WriteStringZeroTerm(constantBuffer.Name); } }
/* Chunk Format * byte[4] ? * uint ? * start: * uint constantBufferCount * uint constantBufferOffset from start * uint resourceBindingCount * uint resourceBindingOffset from start * uint target * uint flags * uint creatorOffset * A[n] ResourceBindings size n*8 * A[n] ResourceBindingNames size variable * A[n] ConstantBuffers * strz createrName from start */ static byte[] ResourceChunk(ShaderSubProgram shaderSubprogram, uint chunkoffset) { var memoryStream = new MemoryStream(); using (var writer = new EndianWriter(memoryStream)) { Dictionary<string, uint> NameLookup = new Dictionary<string, uint>(); var majorVersion = GetMajorVersion(shaderSubprogram.ProgramType); uint startOffset = 0; uint headerOffset = majorVersion >= 5 ? (uint)60 : (uint)28; uint resourceBindingOffset = startOffset + headerOffset; byte[] resourceBindingData = ResourceBindings(shaderSubprogram, resourceBindingOffset, NameLookup); uint contantDataOffset = startOffset + headerOffset + (uint)resourceBindingData.Length; byte[] contantBufferData = ConstantBuffers(shaderSubprogram, contantDataOffset, NameLookup); uint createrStringOffset = contantDataOffset + (uint)contantBufferData.Length; string creatorString = "uTinyRipper"; writer.Write(Encoding.ASCII.GetBytes("RDEF")); //Length of chunk uint chunkLength = headerOffset + (uint)resourceBindingData.Length + (uint)contantBufferData.Length + (uint)creatorString.Length + 1; writer.Write(chunkLength); //ConstantBufferCount uint contantBufferCount = (uint)shaderSubprogram.ConstantBuffers.Count; writer.Write(contantBufferCount); //ContantBufferOffset writer.Write(contantDataOffset); //ResourceBindingCount uint resourceBindingCount = GetResourceBindingCount(shaderSubprogram); writer.Write(resourceBindingCount); //ResourceBindingOffset writer.Write(resourceBindingOffset); //MinorVersionNumber writer.Write((byte)0); //MajorVersionNumber writer.Write((byte)majorVersion); //ProgramType writer.Write((ushort)GetDXProgramType(shaderSubprogram.ProgramType)); //Flags writer.Write((uint)ShaderFlags.NoPreshader); //creatorOffset writer.Write(createrStringOffset); if (majorVersion >= 5) { //rd11 writer.Write(Encoding.ASCII.GetBytes("RD11")); //unknown1 writer.Write((uint)60); //unknown2 writer.Write((uint)24); //unknown3 writer.Write((uint)32); //unknown4 writer.Write((uint)40); //unknown5 writer.Write((uint)36); //unknown6 writer.Write((uint)12); //InterfaceSlotCount writer.Write((uint)0); } writer.Write(resourceBindingData); writer.Write(contantBufferData); //Creatorstring writer.WriteStringZeroTerm(creatorString); return memoryStream.ToArray(); } }
/* Variable Format * uint nameOffset location of variable name * uint startOffset offset of variable in memory * uint size size of type in memory * uint flags * uint typeOffset * uint defaultValueOffset * if sm >= 5 * uint StartTexture * uint TextureSize * uint StartSampler * uint SamplerSize * * Type Format * short VariableClass * short VariableType * short Rows * short Columns * short ElementCount * short memberCount * uint memberOffset */ static byte[] BufferVariables(ConstantBuffer constantBuffer, uint contantBufferOffset, List<Variable> variables, int majorVersion) { var memoryStream = new MemoryStream(); using (var writer = new EndianWriter(memoryStream)) { var typeLookup = new Dictionary<ShaderType, uint>(); uint variableSize = majorVersion >= 5 ? (uint)40 : (uint)24; uint variableCount = (uint)variables.Count; uint dataOffset = contantBufferOffset + variableCount * variableSize; uint startOffset = 0; var seenTypes = new HashSet<ShaderType>(); void WriteVariable(Variable variable) { //name offset writer.Write(dataOffset); dataOffset += (uint)variable.Name.Length + 1; //startOffset writer.Write(startOffset); startOffset += variable.ShaderType.Size(); //Size writer.Write(variable.ShaderType.Size()); //flags writer.Write((uint)ShaderVariableFlags.Used); //Unity only packs used variables as far as I can tell var typeOffset = dataOffset; if (typeLookup.ContainsKey(variable.ShaderType)) { typeOffset = typeLookup[variable.ShaderType]; } else { typeLookup[variable.ShaderType] = dataOffset; dataOffset += variable.ShaderType.Length(); } //type offset writer.Write(typeOffset); //default value offset writer.Write((uint)0); //Not used if(majorVersion >= 5) { //TODO //StartTexture writer.Write((uint)0); //TextureSize writer.Write((uint)0); //StartSampler writer.Write((uint)0); //SamplerSize writer.Write((uint)0); } } void WriteVariableData(Variable variable) { writer.WriteStringZeroTerm(variable.Name); if (!seenTypes.Contains(variable.ShaderType)) { seenTypes.Add(variable.ShaderType); writer.Write((ushort)variable.ShaderType.ShaderVariableClass); writer.Write((ushort)variable.ShaderType.ShaderVariableType); writer.Write(variable.ShaderType.Rows); writer.Write(variable.ShaderType.Columns); writer.Write(variable.ShaderType.ElementCount); writer.Write(variable.ShaderType.MemberCount); writer.Write(variable.ShaderType.MemberOffset); if(majorVersion >= 5) { if(variable.ShaderType.parentTypeOffset != 0 || variable.ShaderType.unknown2 != 0 || variable.ShaderType.unknown5 != 0 || variable.ShaderType.parentNameOffset != 0) { throw new Exception("Shader variable type has invalid value"); } writer.Write(variable.ShaderType.parentTypeOffset); writer.Write(variable.ShaderType.unknown2); writer.Write(variable.ShaderType.unknown4); writer.Write(variable.ShaderType.unknown5); writer.Write(variable.ShaderType.parentNameOffset); } } } if (constantBuffer.StructParams != null && constantBuffer.StructParams.Count > 0) { throw new Exception("Unexpected Struct Params"); } foreach (var variable in variables) { WriteVariable(variable); } foreach (var variable in variables) { WriteVariableData(variable); } return memoryStream.ToArray(); } }
/* ResourceBindingFormat * Size n * 8 * uint nameOffset from start * uint Type * uint ReturnType * uint Dimension * uint NumSamples * uint BindPoint * uint BindCount * uint Flags */ static byte[] ResourceBindings(ShaderSubProgram shaderSubprogram, uint resourceOffset, Dictionary<string, uint> nameLookup) { var memoryStream = new MemoryStream(); using (var writer = new EndianWriter(memoryStream)) { var constantBuffers = GetConstantBuffers(shaderSubprogram); var bindingCount = GetResourceBindingCount(shaderSubprogram); const uint bindingHeaderSize = 32; uint nameOffset = resourceOffset + bindingHeaderSize * (uint)bindingCount; //Build Name Lookup. TODO: Use name indices foreach (var bufferParam in shaderSubprogram.BufferParameters) { nameLookup[bufferParam.Name] = nameOffset; nameOffset += (uint)bufferParam.Name.Length + 1; } foreach (var textureParam in shaderSubprogram.TextureParameters) { nameLookup[textureParam.Name] = nameOffset; nameOffset += (uint)textureParam.Name.Length + 1; } foreach (var constantBuffer in constantBuffers) { nameLookup[constantBuffer.Name] = nameOffset; nameOffset += (uint)constantBuffer.Name.Length + 1; } uint bindPoint = 0; foreach (var bufferParam in shaderSubprogram.BufferParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[bufferParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Structured); //Resource return type writer.Write((uint)ResourceReturnType.Mixed); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Buffer); //Number of samples writer.Write((uint)56); //TODO: Check this //Bind point writer.Write(bindPoint); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var textureParam in shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Sampler); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write(bindPoint); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var textureParam in shaderSubprogram.TextureParameters) { //Resource bindings //nameOffset writer.Write(nameLookup[textureParam.Name]); //shader input type writer.Write((uint)ShaderInputType.Texture); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension //TODO: look into this var viewDimension = textureParam.Dim == 5 ? ShaderResourceViewDimension.Texture2DArray : ShaderResourceViewDimension.Unknown; writer.Write((uint)viewDimension); //Number of samples writer.Write(uint.MaxValue); //Bind point writer.Write(bindPoint); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } bindPoint = 0; foreach (var constantBuffer in constantBuffers) { //Resource bindings //nameOffset writer.Write(nameLookup[constantBuffer.Name]); //shader input type writer.Write((uint)ShaderInputType.CBuffer); //Resource return type writer.Write((uint)ResourceReturnType.NotApplicable); //Resource view dimension writer.Write((uint)ShaderResourceViewDimension.Unknown); //Number of samples writer.Write((uint)0); //Bind point writer.Write(bindPoint); bindPoint += 1; //Bind count writer.Write((uint)1); //Shader input flags writer.Write((uint)ShaderInputFlags.None); } foreach (var textureParam in shaderSubprogram.TextureParameters) { writer.WriteStringZeroTerm(textureParam.Name); } foreach (var constantBuffer in constantBuffers) { writer.WriteStringZeroTerm(constantBuffer.Name); } return memoryStream.ToArray(); } }