public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var gen      = new WaterGenerator(shaderOptions.Select(x => (byte)x).ToArray());
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #2
0
        public override string GenerateSharedPixelShader(ShaderStage stage, int methodIndex, int optionIndex)
        {
            var gen      = new HalogramGenerator();
            var bytecode = gen.GenerateSharedPixelShader(stage, methodIndex, optionIndex).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #3
0
        public override string GenerateSharedVertexShader(VertexType vertex, ShaderStage stage)
        {
            var gen      = new HalogramGenerator();
            var bytecode = gen.GenerateSharedVertexShader(vertex, stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
    /// <summary>
    /// Compiles a new HLSL shader from the input source code.
    /// </summary>
    /// <param name="hlslSourceAscii">The HLSL source code to compile (in ASCII).</param>
    /// <param name="entryPointAscii">The entry point of the shader being compiled (in ASCII).</param>
    /// <param name="shaderProfile">The shader profile to use to compile the shader.</param>
    /// <param name="options">The compiler options to use to compile the shader.</param>
    /// <returns>The bytecode for the compiled shader.</returns>
    /// <exception cref="FxcCompilationException">Thrown if the compilation fails.</exception>
    public static unsafe ReadOnlyMemory <byte> Compile(
        ReadOnlySpan <byte> hlslSourceAscii,
        ReadOnlySpan <byte> entryPointAscii,
        D2D1ShaderProfile shaderProfile,
        D2D1CompileOptions options)
    {
        // Check linking support
        bool enableLinking = (options & D2D1CompileOptions.EnableLinking) == D2D1CompileOptions.EnableLinking;

        // Remove the linking flag to make the options blittable to flags
        options &= ~D2D1CompileOptions.EnableLinking;

        // Compile the standalone D2D1 full shader
        using ComPtr <ID3DBlob> d3DBlobFullShader = D3DCompiler.CompileShader(
                  source: hlslSourceAscii,
                  macro: D3DCompiler.ASCII.D2D_FULL_SHADER,
                  d2DEntry: entryPointAscii,
                  entryPoint: entryPointAscii,
                  target: D3DCompiler.ASCII.GetPixelShaderProfile(shaderProfile),
                  flags: (uint)options);

        if (!enableLinking)
        {
            void *blobFullShaderPtr  = d3DBlobFullShader.Get()->GetBufferPointer();
            nuint blobFullShaderSize = d3DBlobFullShader.Get()->GetBufferSize();

            return(new Span <byte>(blobFullShaderPtr, (int)blobFullShaderSize).ToArray());
        }

        // Compile the export function
        using ComPtr <ID3DBlob> d3DBlobFunction = D3DCompiler.CompileShader(
                  source: hlslSourceAscii,
                  macro: D3DCompiler.ASCII.D2D_FUNCTION,
                  d2DEntry: entryPointAscii,
                  entryPoint: default,
Beispiel #5
0
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo         = (Albedo)shaderOptions[0];
            var alpha_test     = (Alpha_Test)shaderOptions[1];
            var material_model = (Material_Model)shaderOptions[2];
            var gen            = new FoliageGenerator(albedo, alpha_test, material_model);
            var bytecode       = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
        private static unsafe Span <byte> CreateBlob(out ID3DBlob *ppBlob, UIntPtr size)
        {
            ID3DBlob *p;

            ThrowIfFailed(D3DCompiler.D3DCreateBlob(size, &p));

            ppBlob = p;

            return(new Span <byte>(ppBlob->GetBufferPointer(), (int)ppBlob->GetBufferSize()));
        }
Beispiel #7
0
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo     = (Albedo)shaderOptions[0];
            var blend_mode = (Blend_Mode)shaderOptions[1];
            var fog        = (Fog)shaderOptions[2];

            var gen      = new LightVolumeGenerator(albedo, blend_mode, fog);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #8
0
        static void TestSharedVertexShader(ShaderType shaderType, VertexType vertexType, ShaderStage stage)
        {
            IShaderGenerator generator = GetShaderGenerator(shaderType);

            if (generator.IsEntryPointSupported(stage) && generator.IsVertexShaderShared(stage) && generator.IsVertexFormatSupported(vertexType))
            {
                var bytecode    = generator.GenerateSharedVertexShader(vertexType, stage).Bytecode;
                var disassembly = D3DCompiler.Disassemble(bytecode);
                WriteShaderFile($"generated_{stage.ToString().ToLower()}_{vertexType.ToString().ToLower()}.glvs", disassembly);
            }
        }
Beispiel #9
0
        static void TestPixelShader(string name)
        {
            var bytecode = GenericPixelShaderGenerator.GeneratePixelShader(name, ShaderStage.Default.ToString());
            var str      = D3DCompiler.Disassemble(bytecode.Bytecode);

            using (FileStream test = new FileInfo($"generated_{name}.pixl").Create())
                using (StreamWriter writer = new StreamWriter(test))
                {
                    writer.WriteLine(str);
                }

            Console.WriteLine(str);
        }
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var warp       = (Warp)shaderOptions[0];
            var _base      = (Base)shaderOptions[1];
            var overlay_a  = (Overlay_A)shaderOptions[2];
            var overlay_b  = (Overlay_B)shaderOptions[3];
            var blend_type = (Blend_Mode)shaderOptions[4];

            var gen      = new ScreenGenerator(warp, _base, overlay_a, overlay_b, blend_type);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #11
0
        static void TestSharedPixelShader(ShaderType shaderType, ShaderStage stage, int methodIndex, int optionIndex)
        {
            IShaderGenerator generator = GetShaderGenerator(shaderType);

            byte[] bytecode;
            string disassembly;

            if (generator.IsSharedPixelShaderUsingMethods(stage))
            {
                if (methodIndex == -1 || optionIndex == -1)
                {
                    for (int i = 0; i < generator.GetMethodCount(); i++)
                    {
                        if (generator.IsMethodSharedInEntryPoint(stage, i) && generator.IsPixelShaderShared(stage))
                        {
                            for (int j = 0; j < generator.GetMethodOptionCount(i); j++)
                            {
                                var result = generator.GenerateSharedPixelShader(stage, i, j);
                                if (result != null)
                                {
                                    bytecode    = generator.GenerateSharedPixelShader(stage, i, j).Bytecode;
                                    disassembly = D3DCompiler.Disassemble(bytecode);
                                    WriteShaderFile($"generated_{stage.ToString().ToLower()}_{i}_{j}.glps", disassembly);
                                }
                            }
                        }
                    }
                }
                else
                {
                    var result = generator.GenerateSharedPixelShader(stage, -1, -1);
                    if (result != null)
                    {
                        bytecode    = result.Bytecode;
                        disassembly = D3DCompiler.Disassemble(bytecode);
                        WriteShaderFile($"generated_{stage.ToString().ToLower()}_{methodIndex}_{optionIndex}.glps", disassembly);
                    }
                }
            }
            else
            {
                var result = generator.GenerateSharedPixelShader(stage, -1, -1);
                if (result != null)
                {
                    bytecode    = result.Bytecode;
                    disassembly = D3DCompiler.Disassemble(bytecode);
                    WriteShaderFile($"generated_{stage.ToString().ToLower()}.glps", disassembly);
                }
            }
        }
Beispiel #12
0
        static void TestPixelShader(ShaderType shaderType, ShaderStage stage, List <int> methods)
        {
            IShaderGenerator generator = GetTemplateShaderGenerator(shaderType, methods);

            if (generator.IsEntryPointSupported(stage) && !generator.IsPixelShaderShared(stage))
            {
                var bytecode   = generator.GeneratePixelShader(stage).Bytecode;
                var parameters = generator.GetPixelShaderParameters();

                var    disassembly = D3DCompiler.Disassemble(bytecode);
                string filename    = $"generated_{stage.ToString().ToLower()}_{string.Join("_", methods)}.pixl";
                WriteShaderFile(filename, disassembly);
            }
        }
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo       = (Albedo)shaderOptions[0];
            var blend_mode   = (Blend_Mode)shaderOptions[1];
            var render_pass  = (Render_Pass)shaderOptions[2];
            var specular     = (Specular)shaderOptions[3];
            var bump_mapping = (Bump_Mapping)shaderOptions[4];
            var tinting      = (Tinting)shaderOptions[5];

            var gen      = new DecalGenerator(albedo, blend_mode, render_pass, specular, bump_mapping, tinting);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #14
0
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var blend_type = (Blending)shaderOptions[0];
            var env_map    = (Environment_Mapping)shaderOptions[1];
            var material_0 = (Material)shaderOptions[2];
            var material_1 = (Material)shaderOptions[3];
            var material_2 = (Material)shaderOptions[4];
            var material_3 = (Material_No_Detail_Bump)shaderOptions[5];

            var gen      = new TerrainGenerator(blend_type, env_map, material_0, material_1, material_2, material_3);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #15
0
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo            = (Albedo)shaderOptions[0];
            var self_illumination = (Self_Illumination)shaderOptions[1];
            var blend_mode        = (Blend_Mode)shaderOptions[2];
            var misc      = (Misc)shaderOptions[3];
            var warp      = (Warp)shaderOptions[4];
            var overlay   = (Overlay)shaderOptions[5];
            var edge_fade = (Edge_Fade)shaderOptions[6];

            var gen      = new HalogramGenerator(albedo, self_illumination, blend_mode, misc, warp, overlay, edge_fade);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
        public static byte[] GenerateSource(string template, IEnumerable <D3D.SHADER_MACRO> macros, string entry, string version)
        {
            // Macros should never be duplicated
            for (var i = 0; i < macros.Count(); i++)
            {
                for (var j = 0; j < macros.Count(); j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (macros.ElementAt(i).Name == macros.ElementAt(j).Name)
                    {
                        throw new Exception($"Macro {macros.ElementAt(i).Name} is defined multiple times");
                    }
                }
            }

            string fileName = template.Split('\\').Last();

            IncludeManager include = new IncludeManager(template.Replace(fileName, ""));

            string shader_source = include.ReadResource(fileName);

            D3DCompiler.D3DCOMPILE flags = 0;
#if DEBUG
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_WARNINGS_ARE_ERRORS;
#endif
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_SKIP_VALIDATION;
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_DEBUG;
            flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_OPTIMIZATION_LEVEL2; // if can't get shader to compile 1-1 add or remove this line
            byte[] shader_code = D3DCompiler.Compile(
                shader_source,
                entry,
                version,
                macros.ToArray(),
                flags,
                0,
                template,
                include
                );

            GC.KeepAlive(include?.NativePointer);
            return(shader_code);
        }
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo              = (Albedo)shaderOptions[0];
            var bump_mapping        = (Bump_Mapping)shaderOptions[1];
            var alpha_test          = (Alpha_Test)shaderOptions[2];
            var specular_mask       = (Specular_Mask)shaderOptions[3];
            var material_model      = (Material_Model)shaderOptions[4];
            var environment_mapping = (Environment_Mapping)shaderOptions[5];
            var self_illumination   = (Self_Illumination)shaderOptions[6];
            var blend_mode          = (Blend_Mode)shaderOptions[7];
            var parallax            = (Parallax)shaderOptions[8];
            var misc       = (Misc)shaderOptions[9];
            var distortion = (Shared.Distortion)shaderOptions[10];
            var gen        = new ShaderGenerator(albedo, bump_mapping, alpha_test, specular_mask, material_model, environment_mapping, self_illumination, blend_mode, parallax, misc, distortion);
            var bytecode   = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
Beispiel #18
0
        public override string GeneratePixelShader(ShaderStage stage, List <int> shaderOptions)
        {
            var albedo                = (Albedo)shaderOptions[0];
            var blend_mode            = (Blend_Mode)shaderOptions[1];
            var specialized_rendering = (Specialized_Rendering)shaderOptions[2];
            var lighting              = (Lighting)shaderOptions[3];
            var render_targets        = (Render_Targets)shaderOptions[4];
            var depth_fade            = (Depth_Fade)shaderOptions[5];
            var black_point           = (Black_Point)shaderOptions[6];
            var fog               = (Fog)shaderOptions[7];
            var frame_blend       = (Frame_Blend)shaderOptions[8];
            var self_illumination = (Self_Illumination)shaderOptions[9];

            var gen      = new ParticleGenerator(albedo, blend_mode, specialized_rendering, lighting, render_targets, depth_fade, black_point, fog, frame_blend, self_illumination);
            var bytecode = gen.GeneratePixelShader(stage).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
        public static byte[] GenerateSource(string template, IEnumerable <D3D.SHADER_MACRO> macros, string entry, string version)
        {
            // Macros should never be duplicated
            for (var i = 0; i < macros.Count(); i++)
            {
                for (var j = 0; j < macros.Count(); j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (macros.ElementAt(i).Name == macros.ElementAt(j).Name)
                    {
                        throw new Exception($"Macro {macros.ElementAt(i).Name} is defined multiple times");
                    }
                }
            }

            IncludeManager include = new IncludeManager();

            string shader_source = include.ReadResource(template);

            D3DCompiler.D3DCOMPILE flags = 0;
#if DEBUG
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_WARNINGS_ARE_ERRORS;
#endif
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_SKIP_OPTIMIZATION;
            flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_SKIP_VALIDATION;
            //flags |= D3DCompiler.D3DCOMPILE.D3DCOMPILE_PREFER_FLOW_CONTROL;

            byte[] shader_code = D3DCompiler.Compile(
                shader_source,
                entry,
                version,
                macros.ToArray(),
                flags,
                0,
                template,
                include
                );

            return(shader_code);
        }
Beispiel #20
0
    public static byte[]? Compile(string source, ShaderStage stage, string entryPoint = "", string fileName = "")
    {
        if (string.IsNullOrEmpty(entryPoint))
        {
            entryPoint = GetDefaultEntryPoint(stage);
        }

        uint   flags         = 0;
        string shaderProfile = $"{GetShaderProfile(stage)}_5_0";
        Result hr            = D3DCompiler.D3DCompile(
            source,
            source.Length,
            fileName,
            null,
            0,
            entryPoint,
            shaderProfile,
            flags,
            0,
            out IDxcBlob blob,
            out IDxcBlob? errorMsgs);

        if (hr.Failure)
        {
            if (errorMsgs != null)
            {
                var errorText = GetStringFromBlob(errorMsgs);
            }
        }
        else
        {
            return(GetBytesFromBlob(blob));
        }

        return(null);
    }
Beispiel #21
0
        static void TestPixelBlack()
        {
            var gen      = new ShaderBlackGenerator();
            var bytecode = gen.GeneratePixelShader(ShaderStage.Albedo).Bytecode;

            WriteShaderFile($"generated_shader_black_{ShaderStage.Albedo.ToString().ToLower()}_0.pixl", D3DCompiler.Disassemble(bytecode));
        }
Beispiel #22
0
        /// <summary>
        /// Converts a new (1.235640+) pixel shader to one compatible with the 1.106708 pipeline.
        /// </summary>
        /// <param name="shaderData">The shader bytecode to convert.</param>
        /// <param name="mode">The drawing mode.</param>
        /// <returns>The new bytecode, or <c>null</c> if conversion failed.</returns>
        public static byte[] ConvertNewPixelShaderToOld(byte[] shaderData, int mode)
        {
            if (mode != 0 && mode != 1)
            {
                return(shaderData); // Only default albedo shaders need to be fixed (?)
            }
            // Disassemble the shader
            var disassembly = D3DCompiler.Disassemble(shaderData);

            if (disassembly == null)
            {
                return(null);
            }
            var lines = disassembly.Split('\n').ToList();

            // Default pixel shaders need to have their inputs remapped (see
            // the vertex shader converter for more info).
            //
            // Albedo pixel shaders need to have sRGB color correction added.
            // The code is based off of the shader for the street cone.

            var highestConstant = -1;
            var addedConstants  = false;
            var addedColorFix   = false;
            var highestTexcoord = -1;
            var highestInput    = -1;
            var wIn             = -1;

            for (var i = 0; i < lines.Count; i++)
            {
                if (mode == 0)
                {
                    // Default fixes
                    var match = Regex.Match(lines[i], @"dcl_texcoord(\d*)");
                    if (match.Success)
                    {
                        var texGroup = match.Groups[1];
                        var index    = (texGroup.Length > 0) ? int.Parse(texGroup.Value) : 0;
                        highestTexcoord = Math.Max(highestTexcoord, index);
                        if (index >= 1)
                        {
                            lines[i] = lines[i].Remove(texGroup.Index, texGroup.Length).Insert(texGroup.Index, (index + 1).ToString());
                        }
                    }
                    match = Regex.Match(lines[i], @"dcl_\S+ v(\d+)");
                    if (match.Success)
                    {
                        var inGroup = match.Groups[1];
                        highestInput = Math.Max(highestInput, int.Parse(inGroup.Value));
                    }
                    else if (highestTexcoord >= 1 && highestInput >= 0)
                    {
                        wIn = highestInput + 1;
                        lines.Insert(i, string.Format("    dcl_texcoord1 v{0}.x", wIn));
                        lines.Add(string.Format("    mov oC2, v{0}.x", wIn));
                        break;
                    }
                }
                else if (mode == 1)
                {
                    // Albedo fixes
                    var match = Regex.Match(lines[i], @"dcl_texcoord1 v1\.xyz");
                    if (match.Success)
                    {
                        wIn      = 1;
                        lines[i] = lines[i].Remove(match.Index, match.Length).Insert(match.Index, "dcl_texcoord1 v1");
                        continue;
                    }

                    // Find the number of the highest-used constant register
                    match = Regex.Match(lines[i], @"def c(\d+)");
                    if (match.Success)
                    {
                        highestConstant = Math.Max(highestConstant, int.Parse(match.Groups[1].Value));
                        continue;
                    }

                    if (!addedConstants)
                    {
                        // Add color correction constants before input/output declarations
                        match = Regex.Match(lines[i], @"dcl_");
                        if (match.Success)
                        {
                            lines.Insert(i,
                                         string.Format("    def c{0}, 0.416666657, 1.05499995, -0.0549999997, 0.00313080009\n" +
                                                       "    def c{1}, 12.9200001, 0, 0, 0",
                                                       highestConstant + 1, highestConstant + 2));
                            addedConstants = true;
                            continue;
                        }
                    }

                    if (!addedColorFix)
                    {
                        // Add color correction code before the output color is set
                        match = Regex.Match(lines[i], @"\S+ (oC0)\.xyz");
                        if (match.Success)
                        {
                            // NOTE: This is really hacky and just assumes that
                            // r29-r31 aren't used. It seems to work OK, but if we
                            // run into issues then some sort of register
                            // allocation may need to be done.
                            var group = match.Groups[1];
                            lines[i] = lines[i].Remove(group.Index, group.Length).Insert(group.Index, "r31");
                            lines.Insert(++i,
                                         string.Format("    log r30.x, r31.x\n" +
                                                       "    log r30.y, r31.y\n" +
                                                       "    log r30.z, r31.z\n" +
                                                       "    mul r30.xyz, r30, c{0}.x\n" +
                                                       "    exp r29.x, r30.x\n" +
                                                       "    exp r29.y, r30.y\n" +
                                                       "    exp r29.z, r30.z\n" +
                                                       "    mad r30.xyz, r29, c{0}.y, c{0}.z\n" +
                                                       "    add r29.xyz, -r31, c{0}.w\n" +
                                                       "    mul r31.xyz, r31, c{1}.x\n" +
                                                       "    cmp oC0.xyz, r29, r31, r30",
                                                       highestConstant + 1, highestConstant + 2));
                            if (wIn >= 0)
                            {
                                lines.Insert(++i, string.Format("    mov oC2, v{0}.w", wIn));
                            }
                            addedColorFix = true;
                            continue;
                        }
                    }
                }
            }

            // Reassemble the shader
            var newShader = string.Join("\n", lines);

            return(D3DCompiler.Assemble(newShader));
        }
Beispiel #23
0
        /// <summary>
        /// Converts a new (1.235640+) vertex shader to one compatible with the 1.106708 pipeline.
        /// Note that this requires that models have binormals set so that X = Position.W and Y = Tangent.W.
        /// </summary>
        /// <param name="shaderData">The shader bytecode to convert.</param>
        /// <param name="mode">The drawing mode.</param>
        /// <param name="type">The vertex type.</param>
        /// <returns>The new bytecode, or <c>null</c> if conversion failed.</returns>
        public static byte[] ConvertNewVertexShaderToOld(byte[] shaderData, int mode, VertexType type)
        {
            // Only applies to world, rigid, skinned, and dual quat
            if (type != VertexType.World && type != VertexType.Rigid && type != VertexType.Skinned && type != VertexType.DualQuat)
            {
                return(shaderData);
            }

            // Disassemble the shader
            var disassembly = D3DCompiler.Disassemble(shaderData);

            if (disassembly == null)
            {
                return(null);
            }
            var lines = disassembly.Split('\n').ToList();

            // So, the reason that new vertex shaders don't work in 1.106708
            // is because vertex declarations changed. For world, rigid, and
            // skinned meshes, the normal and binormal components were removed,
            // and the position and tangent vectors were extended to be 4D.
            // (The W components are used for various things.) To convert a new
            // vertex shader to use the old declaration format, we need to do
            // the following:
            //
            // 1. Add an input declaration for the binormal, so we can pull the
            //    position.W and tangent.W values from it (assuming they're
            //    stored that way in the model).
            //
            // 2. Remap the W component of the position to the X component of
            //    the binormal. (The W component will never be used alongside
            //    the other position components because it's technically
            //    completely separate.)
            //
            // 3. The tangent will be unpacked by using a "mad" instruction.
            //    However, in 1.106708, the tangent isn't packed to begin with.
            //    So, we look for an instruction of the form
            //
            //      mad [register], v[tangent], [constant], [constant]
            //
            //    and replace it with instructions to load the components,
            //    with the W component of the tangent in the Y component of the
            //    binormal:
            //
            //      mov [register].xyz, v[tangent]
            //      mov [register].w, v[binormal].y
            //
            // 4. Insert code to handle v_squish_params and v_mesh_squished.
            //    This is mainly needed for first-person models.
            //
            // 5. For albedo shaders only, o2 needs to be made 4D and the W
            //    component must be set to the W component of the position so
            //    that the pixel shader can pass it through to an output. This
            //    appears to be necessary for objects to receive shadows.
            //
            // 6. For default shaders only, a texcoord1 output has to be added
            //    for storing the W component of the position. This means that
            //    the other texcoord outputs need to be remapped.

            var    addedDeclarations = false;
            var    fixedTangent      = false;
            var    lastInput         = -1;
            var    tangentRegister   = -1;
            var    binormalRegister  = -1;
            var    storedZ           = false;
            var    storedW           = false;
            var    addedSquishParams = false;
            string squishConstant1   = null;
            string squishConstant2   = null;
            var    needSquishCheck   = false;
            var    wOut = -1;

            for (var i = 0; i < lines.Count; i++)
            {
                if (lines[i].StartsWith("//"))
                {
                    continue;
                }

                // Find the tangent declaration and keep track of the highest input register
                var match = Regex.Match(lines[i], @"dcl_(\S+) v(\d+)");
                if (match.Success)
                {
                    var name     = match.Groups[1].Value;
                    var register = int.Parse(match.Groups[2].Value);
                    if (name == "tangent")
                    {
                        tangentRegister = register;
                    }
                    lastInput = Math.Max(lastInput, register);
                }

                if (!addedDeclarations)
                {
                    // Once the first output is found, add a definition for the binormal input before it
                    match = Regex.Match(lines[i], @"dcl_(\S+) o\d+");
                    if (match.Success)
                    {
                        binormalRegister = lastInput + 1;
                        lines.Insert(i++, string.Format("    dcl_binormal v{0}", binormalRegister));
                        addedDeclarations = true;
                        continue;
                    }
                }

                if (!fixedTangent && tangentRegister >= 0 && binormalRegister >= 0)
                {
                    // Adjust tangent unpacking
                    match = Regex.Match(lines[i], @"mad r(\d+), v" + tangentRegister);
                    if (match.Success)
                    {
                        var index = int.Parse(match.Groups[1].Value);
                        lines[i++] = string.Format("    mov r{0}.xyz, v{1}", index, tangentRegister);
                        lines.Insert(i, string.Format("    mov r{0}.w, v{1}.y", index, binormalRegister));
                        fixedTangent = true;
                        continue;
                    }
                }

                // When the output Z is set, store it to r31.z instead (for v_squish_params)
                match = Regex.Match(lines[i], @"\S+ (o0)\.z");
                if (match.Success)
                {
                    var group = match.Groups[1];
                    lines[i] = lines[i].Remove(group.Index, group.Length).Insert(group.Index, "r31");
                    storedZ  = true;
                }

                // When the output W is set, store it to r30.w instead (for v_squish_params)
                match = Regex.Match(lines[i], @"\S+ (o0)\.w");
                if (match.Success)
                {
                    var group = match.Groups[1];
                    lines[i] = lines[i].Remove(group.Index, group.Length).Insert(group.Index, "r30");
                    storedW  = true;
                }

                // If b8 (v_mesh_squished) is checked, we need to remove most
                // of it and transform the previous instruction into a store to
                // r31.z (for the v_squish_params fix later on).
                match = Regex.Match(lines[i], @"if b8");
                if (match.Success)
                {
                    // Check that the previous instruction stores to a register
                    match = Regex.Match(lines[i - 1], @"\S+ (r\d+\..),");
                    if (match.Success)
                    {
                        // Get squish constant 1
                        var constMatch = Regex.Match(lines[i + 1], @"mov r\d+\.., (c\d+\..)");
                        if (constMatch.Success)
                        {
                            squishConstant1 = constMatch.Groups[1].Value;
                        }

                        // Get squish constant 2
                        constMatch = Regex.Match(lines[i + 3], @"mov r\d+\.., (c\d+\..)");
                        if (constMatch.Success)
                        {
                            squishConstant2 = constMatch.Groups[1].Value;
                        }

                        if (squishConstant1 != null && squishConstant2 != null)
                        {
                            // Remove the if block
                            lines.RemoveRange(i--, 6);

                            // Transform the previous instruction
                            var group = match.Groups[1];
                            lines[i]        = lines[i].Remove(group.Index, group.Length).Insert(group.Index, "r31.z");
                            needSquishCheck = true;
                            storedZ         = true;
                        }
                    }
                }

                // v_squish_params fix
                if (storedZ && storedW && !addedSquishParams)
                {
                    lines.Insert(++i, "    mad r30.x, c250.x, r30.w, -c250.y\n" +
                                 "    mad r30.x, r30.x, c250.z, -r31.z");
                    if (needSquishCheck)
                    {
                        // Check v_mesh_squished
                        lines.Insert(++i,
                                     string.Format("    mad r31.z, c250.w, r30.x, r31.z\n" +
                                                   "    if b8\n" +
                                                   "      mov r30.x, {0}\n" +
                                                   "    else\n" +
                                                   "      mov r30.x, {1}\n" +
                                                   "    endif\n" +
                                                   "    add o0.z, -r30.x, r31.z",
                                                   squishConstant1, squishConstant2));
                    }
                    else
                    {
                        lines.Insert(++i, "    mad o0.z, c250.w, r30.x, r31.z");
                    }
                    lines.Insert(++i, "    mov o0.w, r30.w");

                    // Needed for shadow receiving
                    if (wOut >= 0)
                    {
                        if (mode == 0)
                        {
                            lines.Insert(++i, string.Format("    mov o{0}.x, r30.w", wOut));
                        }
                        else if (mode == 1)
                        {
                            lines.Insert(++i, string.Format("    mov o{0}.w, r30.w", wOut));
                        }
                    }

                    addedSquishParams = true;
                    continue;
                }

                if (mode == 0)
                {
                    // Default-only: add a texcoord1 output and remap input registers
                    match = Regex.Match(lines[i], @"dcl_texcoord(\d*) o(\d+)");
                    if (match.Success)
                    {
                        var texGroup = match.Groups[1];
                        var outGroup = match.Groups[2];
                        var outIndex = int.Parse(outGroup.Value);
                        if (texGroup.Length == 0)
                        {
                            wOut = outIndex + 1;
                            lines.Insert(++i, string.Format("    dcl_texcoord1 o{0}.x", outIndex + 1));
                            continue;
                        }
                        var texIndex = int.Parse(texGroup.Value);
                        lines[i] = lines[i].Remove(texGroup.Index, texGroup.Length).Insert(texGroup.Index, (texIndex + 1).ToString());
                        lines[i] = lines[i].Remove(outGroup.Index, outGroup.Length).Insert(outGroup.Index, (outIndex + 1).ToString());
                        continue;
                    }

                    if (wOut >= 0)
                    {
                        foreach (Match m in Regex.Matches(lines[i], @" o(\d+)"))
                        {
                            var group = m.Groups[1];
                            var index = int.Parse(group.Value);
                            if (index < wOut)
                            {
                                continue;
                            }
                            index++;
                            lines[i] = lines[i].Remove(group.Index, group.Length).Insert(group.Index, index.ToString());
                        }
                    }
                }

                // Albedo-only: make o2 be 4D
                if (mode == 1)
                {
                    match = Regex.Match(lines[i], @"dcl_texcoord1 o2\.xyz");
                    if (match.Success)
                    {
                        wOut     = 2;
                        lines[i] = lines[i].Remove(match.Index, match.Length).Insert(match.Index, "dcl_texcoord1 o2");
                        continue;
                    }
                }

                if (binormalRegister >= 0)
                {
                    // Change the source of the position W component
                    lines[i] = lines[i].Replace("v0.w", string.Format("v{0}.x", binormalRegister));
                }
            }

            // Reassemble the shader
            var newShader = string.Join("\n", lines);

            return(D3DCompiler.Assemble(newShader));
        }
Beispiel #24
0
        public override string GenerateChudVertexShader(ChudShader chudShader, ShaderStage entry)
        {
            var bytecode = GenericVertexShaderGenerator.GenerateVertexShader(chudShader.ToString(), entry.ToString().ToLower(), true).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }
        private string Disassemble(int shaderIndex)
        {
            string disassembly = null;

            if (typeof(T) == typeof(PixelShader) || typeof(T) == typeof(GlobalPixelShader))
            {
                PixelShaderBlock shader_block = null;
                if (typeof(T) == typeof(PixelShader))
                {
                    var _definition = Definition as PixelShader;
                    if (shaderIndex < _definition.Shaders.Count)
                    {
                        shader_block = _definition.Shaders[shaderIndex];
                    }
                    else
                    {
                        return(null);
                    }
                }

                if (typeof(T) == typeof(GlobalPixelShader))
                {
                    var _definition = Definition as GlobalPixelShader;
                    if (shaderIndex < _definition.Shaders.Count)
                    {
                        shader_block = _definition.Shaders[shaderIndex];
                    }
                    else
                    {
                        return(null);
                    }
                }

                var pc_shader = shader_block.PCShaderBytecode;
                disassembly = D3DCompiler.Disassemble(pc_shader);
                if (pc_shader == null)
                {
                    disassembly = null;
                }
            }

            if (typeof(T) == typeof(VertexShader) || typeof(T) == typeof(GlobalVertexShader))
            {
                VertexShaderBlock shader_block = null;
                if (typeof(T) == typeof(VertexShader))
                {
                    var _definition = Definition as VertexShader;
                    if (shaderIndex < _definition.Shaders.Count)
                    {
                        shader_block = _definition.Shaders[shaderIndex];
                    }
                    else
                    {
                        return(null);
                    }
                }

                if (typeof(T) == typeof(GlobalVertexShader))
                {
                    var _definition = Definition as GlobalVertexShader;
                    if (shaderIndex < _definition.Shaders.Count)
                    {
                        shader_block = _definition.Shaders[shaderIndex];
                    }
                    else
                    {
                        return(null);
                    }
                }

                var pc_shader = shader_block.PCShaderBytecode;
                disassembly = D3DCompiler.Disassemble(pc_shader);
                if (pc_shader == null)
                {
                    disassembly = null;
                }
            }

            return(disassembly);
        }
Beispiel #26
0
        public ShaderGeneratorResult(byte[] bytecode)
        {
            Bytecode = bytecode;
            if (bytecode == null)
            {
                return;
            }
            var result = D3DCompiler.Disassemble(bytecode);

            if (result == null)
            {
                return;
            }

            var registers  = GetRegisters(result);
            var parameters = GetRegisterParameters(result);

            foreach (var parameters_kp in parameters)
            {
                var name     = parameters_kp.Key;
                var typename = parameters_kp.Value;

                ShaderRegister.RegisterType register_type;
                {
                    ShaderRegister.RegisterType?_register_type = null;

                    switch (typename)
                    {
                    case "float4":
                    case "float3":
                    case "float2":
                    case "float":
                        _register_type = ShaderRegister.RegisterType.Vector;
                        break;

                    case "int":
                        _register_type = ShaderRegister.RegisterType.Integer;
                        break;

                    case "bool":
                        _register_type = ShaderRegister.RegisterType.Boolean;
                        break;
                    }
                    if (typename.StartsWith("sampler"))
                    {
                        _register_type = ShaderRegister.RegisterType.Sampler;
                    }

                    register_type = _register_type ?? ShaderRegister.RegisterType.Vector;
                }

                foreach (var register in registers)
                {
                    if (register.Name == name && register.registerType == register_type)
                    {
                        // Integers have an associated Vector, find and add it
                        if (register_type == ShaderRegister.RegisterType.Integer)
                        {
                            foreach (var register2 in registers)
                            {
                                if (register2.Name == name && register2.registerType == ShaderRegister.RegisterType.Vector)
                                {
                                    Registers.Add(register2);
                                    break;
                                }
                            }
                        }

                        Registers.Add(register);
                        break;
                    }

                    // slight hack, for int's that get compiled only as vector
                    else if (register.Name == name && register_type == ShaderRegister.RegisterType.Integer)
                    {
                        foreach (var register2 in registers)
                        {
                            if (register2.Name == name && register2.registerType == ShaderRegister.RegisterType.Vector)
                            {
                                Registers.Add(register2);
                                break;
                            }
                        }
                    }
                }
            }
        }
Beispiel #27
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            if (typeof(T) == typeof(PixelShader) || typeof(T) == typeof(GlobalPixelShader))
            {
                PixelShaderBlock shader_block = null;
                if (typeof(T) == typeof(PixelShader))
                {
                    var _definition = Definition as PixelShader;
                    shader_block = _definition.Shaders[int.Parse(args[0])];
                }

                if (typeof(T) == typeof(GlobalPixelShader))
                {
                    var _definition = Definition as GlobalPixelShader;
                    shader_block = _definition.Shaders[int.Parse(args[0])];
                }

                var pc_shader   = shader_block.PCShaderBytecode;
                var disassembly = D3DCompiler.Disassemble(pc_shader);
                if (pc_shader != null)
                {
                    Console.WriteLine(disassembly);
                }
                else
                {
                    Console.WriteLine("Failed to disassemble shader");
                }
            }

            if (typeof(T) == typeof(VertexShader) || typeof(T) == typeof(GlobalVertexShader))
            {
                VertexShaderBlock shader_block = null;
                if (typeof(T) == typeof(VertexShader))
                {
                    var _definition = Definition as VertexShader;
                    shader_block = _definition.Shaders[int.Parse(args[0])];
                }

                if (typeof(T) == typeof(GlobalVertexShader))
                {
                    var _definition = Definition as GlobalVertexShader;
                    shader_block = _definition.Shaders[int.Parse(args[0])];
                }

                var pc_shader   = shader_block.PCShaderBytecode;
                var disassembly = D3DCompiler.Disassemble(pc_shader);
                if (pc_shader != null)
                {
                    Console.WriteLine(disassembly);
                }
                else
                {
                    Console.WriteLine("Failed to disassemble shader");
                }
            }


            return(true);
        }
Beispiel #28
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 2)
            {
                return(false);
            }



            bool   use_assembly_compiler = args.Count >= 2 && args[0].ToLower() == "asm";
            string file        = args[args.Count - 1];
            string shader_code = File.ReadAllText(file);

            if (use_assembly_compiler && args.Count < 3)
            {
                return(false);
            }

            int index = use_assembly_compiler ? int.Parse(args[1]) : int.Parse(args[0]);

            if (!use_assembly_compiler)
            {
                using (var reader = new StringReader(shader_code))
                {
                    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
                    {
                        var str = line.Trim();
                        if (str == "ps_3_0" || str == "vs_3_0")
                        {
                            use_assembly_compiler = true;
                            break;
                        }
                    }
                }
            }

            byte[] bytecode = null;
            if (use_assembly_compiler)
            {
                bytecode = D3DCompiler.Assemble(shader_code);
            }
            else
            {
                var profile = IsVertexShader ? "vs_3_0" : "ps_3_0";

                try
                {
                    bytecode = D3DCompiler.CompileFromFile(shader_code, "main", profile);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    return(true);
                }
            }

            var disassembly = D3DCompiler.Disassemble(bytecode);

            Console.WriteLine(disassembly);

            if (typeof(T) == typeof(PixelShader) || typeof(T) == typeof(GlobalPixelShader))
            {
                var shader_data_block = new PixelShaderBlock
                {
                    PCShaderBytecode = bytecode
                };

                if (typeof(T) == typeof(PixelShader))
                {
                    var _definition    = Definition as PixelShader;
                    var existing_block = _definition.Shaders[index];
                    shader_data_block.PCParameters = existing_block.PCParameters;

                    _definition.Shaders[index] = shader_data_block;
                }

                if (typeof(T) == typeof(GlobalPixelShader))
                {
                    var _definition    = Definition as GlobalPixelShader;
                    var existing_block = _definition.Shaders[index];
                    shader_data_block.PCParameters = existing_block.PCParameters;

                    _definition.Shaders[index] = shader_data_block;
                }
            }

            if (typeof(T) == typeof(VertexShader) || typeof(T) == typeof(GlobalVertexShader))
            {
                var shader_data_block = new VertexShaderBlock
                {
                    PCShaderBytecode = bytecode
                };

                if (typeof(T) == typeof(VertexShader))
                {
                    var _definition    = Definition as VertexShader;
                    var existing_block = _definition.Shaders[index];
                    shader_data_block.PCParameters = existing_block.PCParameters;

                    _definition.Shaders[index] = shader_data_block;
                }

                if (typeof(T) == typeof(GlobalVertexShader))
                {
                    var _definition    = Definition as GlobalVertexShader;
                    var existing_block = _definition.Shaders[index];
                    shader_data_block.PCParameters = existing_block.PCParameters;


                    _definition.Shaders[index] = shader_data_block;
                }
            }

            return(true);
        }
Beispiel #29
0
        static void TestSharedVertexBlack(VertexType vertexType, ShaderStage stage)
        {
            var gen      = new ShaderBlackGenerator();
            var bytecode = gen.GenerateSharedVertexShader(vertexType, stage).Bytecode;

            WriteShaderFile($"generated_shader_black_{stage.ToString().ToLower()}_{vertexType.ToString().ToLower()}.glvs", D3DCompiler.Disassemble(bytecode));
        }
Beispiel #30
0
        public override string GenerateExplicitVertexShader(ExplicitShader explicitShader, ShaderStage entry)
        {
            var bytecode = GenericVertexShaderGenerator.GenerateVertexShader(explicitShader.ToString(), entry.ToString().ToLower(), false).Bytecode;

            return(D3DCompiler.Disassemble(bytecode));
        }