From 8c2fdb9097e21b1ed0cd6516ed7ddbce99ad11cb Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sun, 7 Dec 2014 20:46:46 +0000 Subject: [PATCH] Add CopyToArray method for IPalette. By allowing a palette to be copied to an array, a speedup can be gained in HardwarePalette since palettes can be block copied using native magic rather than having to copy them item by item. We transpose the buffer in HardwarePalette in order to allow a contiguous block copy into this buffer, transposing again in the shader to keep everything correct. --- OpenRA.Game/Graphics/HardwarePalette.cs | 8 +++---- OpenRA.Game/Graphics/Palette.cs | 32 +++++++++++++++++++++---- glsl/shp.frag | 2 +- glsl/vxl.frag | 4 ++-- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/OpenRA.Game/Graphics/HardwarePalette.cs b/OpenRA.Game/Graphics/HardwarePalette.cs index 00b48749db..4695d62d04 100644 --- a/OpenRA.Game/Graphics/HardwarePalette.cs +++ b/OpenRA.Game/Graphics/HardwarePalette.cs @@ -23,7 +23,7 @@ namespace OpenRA.Graphics readonly Dictionary modifiablePalettes = new Dictionary(); readonly IReadOnlyDictionary readOnlyModifiablePalettes; readonly Dictionary indices = new Dictionary(); - readonly uint[,] buffer = new uint[Palette.Size, MaxPalettes]; + readonly uint[,] buffer = new uint[MaxPalettes, Palette.Size]; public HardwarePalette() { @@ -85,8 +85,7 @@ namespace OpenRA.Graphics void CopyPaletteToBuffer(int index, IPalette p) { - for (var i = 0; i < Palette.Size; i++) - buffer[i, index] = p[i]; + p.CopyToArray(buffer, index * Palette.Size); } void CopyModifiablePalettesToBuffer() @@ -109,8 +108,7 @@ namespace OpenRA.Graphics { var originalPalette = palettes[kvp.Key]; var modifiedPalette = kvp.Value; - for (var i = 0; i < Palette.Size; i++) - modifiedPalette[i] = originalPalette[i]; + modifiedPalette.SetFromPalette(originalPalette); } } } diff --git a/OpenRA.Game/Graphics/Palette.cs b/OpenRA.Game/Graphics/Palette.cs index 8f0689d89f..61bf3c0257 100644 --- a/OpenRA.Game/Graphics/Palette.cs +++ b/OpenRA.Game/Graphics/Palette.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; @@ -17,7 +18,11 @@ using System.Runtime.InteropServices; namespace OpenRA.Graphics { - public interface IPalette { uint this[int index] { get; } } + public interface IPalette + { + uint this[int index] { get; } + void CopyToArray(Array destination, int destinationOffset); + } public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); } public static class Palette @@ -52,8 +57,7 @@ namespace OpenRA.Graphics var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); var temp = new uint[Palette.Size]; - for (int i = 0; i < temp.Length; i++) - temp[i] = palette[i]; + palette.CopyToArray(temp, 0); Marshal.Copy((int[])(object)temp, 0, data.Scan0, Size); b.UnlockBits(data); return b; @@ -71,6 +75,10 @@ namespace OpenRA.Graphics IPalette palette; public ReadOnlyPalette(IPalette palette) { this.palette = palette; } public uint this[int index] { get { return palette[index]; } } + public void CopyToArray(Array destination, int destinationOffset) + { + palette.CopyToArray(destination, destinationOffset); + } } } @@ -83,6 +91,11 @@ namespace OpenRA.Graphics get { return colors[index]; } } + public void CopyToArray(Array destination, int destinationOffset) + { + Buffer.BlockCopy(colors, 0, destination, destinationOffset * 4, Palette.Size * 4); + } + public ImmutablePalette(string filename, int[] remap) { using (var s = File.OpenRead(filename)) @@ -141,10 +154,14 @@ namespace OpenRA.Graphics set { colors[index] = value; } } + public void CopyToArray(Array destination, int destinationOffset) + { + Buffer.BlockCopy(colors, 0, destination, destinationOffset * 4, Palette.Size * 4); + } + public MutablePalette(IPalette p) { - for (int i = 0; i < Palette.Size; i++) - this[i] = p[i]; + SetFromPalette(p); } public void SetColor(int index, Color color) @@ -152,6 +169,11 @@ namespace OpenRA.Graphics colors[index] = (uint)color.ToArgb(); } + public void SetFromPalette(IPalette p) + { + p.CopyToArray(colors, 0); + } + public void ApplyRemap(IPaletteRemap r) { for (var i = 0; i < Palette.Size; i++) diff --git a/glsl/shp.frag b/glsl/shp.frag index bd4915121d..45a3ebe467 100644 --- a/glsl/shp.frag +++ b/glsl/shp.frag @@ -3,6 +3,6 @@ uniform sampler2D DiffuseTexture, Palette; void main() { vec4 x = texture2D(DiffuseTexture, gl_TexCoord[0].st); - vec2 p = vec2(gl_TexCoord[0].p, dot(x, gl_TexCoord[1])); + vec2 p = vec2(dot(x, gl_TexCoord[1]), gl_TexCoord[0].p); gl_FragColor = texture2D(Palette, p); } diff --git a/glsl/vxl.frag b/glsl/vxl.frag index c5baaeb919..492ae02fe2 100644 --- a/glsl/vxl.frag +++ b/glsl/vxl.frag @@ -7,11 +7,11 @@ uniform vec3 AmbientLight, DiffuseLight; void main() { vec4 x = texture2D(DiffuseTexture, gl_TexCoord[0].st); - vec4 color = texture2D(Palette, vec2(PaletteRows.x, dot(x, gl_TexCoord[1]))); + vec4 color = texture2D(Palette, vec2(dot(x, gl_TexCoord[1]), PaletteRows.x)); if (color.a < 0.01) discard; - vec4 normal = (2.0 * texture2D(Palette, vec2(PaletteRows.y, dot(x, gl_TexCoord[2]))) - 1.0); + vec4 normal = (2.0 * texture2D(Palette, vec2(dot(x, gl_TexCoord[2]), PaletteRows.y)) - 1.0); vec3 intensity = AmbientLight + DiffuseLight * max(dot(normal, LightDirection), 0.0); gl_FragColor = vec4(intensity * color.rgb, color.a); }