Sorry, the Forum is closed :(

Unfortunately, the forum is now closed.

Please read the following post for further details.

We apologize for the inconvenience.
The SharpDX team.
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC: [D3D9] Texture.Fill() method

[D3D9] Texture.Fill() method 1 year 10 months ago #260


  • Posts:16
  • Yorgl's Avatar
  • Yorgl
  • Fresh Boarder
  • OFFLINE
Hello,

I want to fill a texture I created from scratch with an array of Color4. :woohoo:

The Lock-Unlock method is not because of the Pool.Default, so I wanted to try the .Fill() method with a TextureShader. How can I create a TextureShader ? Or perhaps it is easier to use the Fill2DCallback ?

Thanks
Yann
Last Edit: 1 year 9 months ago by xoofx.
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method 1 year 9 months ago #292


  • Posts:843 Thank you received: 1
  • xoofx's Avatar
  • xoofx
  • Administrator
  • OFFLINE
You can use Lock/Unlock on a managed resource, and copy from that managed resource to the final texture using Device.UpdateTexture.

Never tried Fill2DCallback, It is a d3dx function, so they are probably using internally Device.UpdateTexture and a temporary lockable texture.

Texture.Fill method is expecting a TextureShader, which is a special HLSL shader compiled with the profile tx_1_0, used rarely.
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method => GetData & SetData 1 year 9 months ago #296


  • Posts:16
  • Yorgl's Avatar
  • Yorgl
  • Fresh Boarder
  • OFFLINE
OK thanks for the UpdateTexture tip

Here's some two basics extensions GetData and SetData, I don't know if it is the best way to do this, but it works.
public static void GetData(this Texture texture, out Color4[] colors)
{
    DataStream stream;
    SurfaceDescription s = texture.GetLevelDescription(0);
    if (s.Pool == Pool.Default)
    {
        throw new Exception("Impossible to retrieve data form a Pool.Default Texture ?");
    }
    else
    {
        texture.LockRectangle(0, LockFlags.None, out stream);
        colors = new Color4[stream.Length / 4];
        for (int i = 0; i < colors.Length; i++)
        {
            colors[i] = stream.ReadColor4();
        }
        texture.UnlockRectangle(0);
    }
}

public static void SetData(this Texture texture, Color4[] colors)
{
    DataStream stream;
    SurfaceDescription s = texture.GetLevelDescription(0);
    if (s.Pool == Pool.Default)
    {
        Texture tmpTexture = new Texture(texture.Device, s.Width, s.Height, 0, s.Usage, s.Format, Pool.SystemMemory);
        tmpTexture.SetData(colors);
        texture.Device.UpdateTexture(tmpTexture, texture);
        tmpTexture.Dispose();
    }
    else
    {
        texture.LockRectangle(0, LockFlags.None, out stream);
        for (int i = 0; i < stream.Length / 4; i++)
        {
            //write Color4 doesn't work for this
            stream.Write(colors[i].ToArgb());
        }
        texture.UnlockRectangle(0);
    }
}
Last Edit: 1 year 9 months ago by Yorgl.
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method => GetData & SetData 1 year 4 months ago #1298


  • Posts:2
  • Boemer's Avatar
  • Boemer
  • Fresh Boarder
  • OFFLINE
the following part is very slow in C#
for (int i = 0; i < stream.Length / 4; i++)
{
            //write Color4 doesn't work for this
            stream.Write(colors[i].ToArgb());
}

I had a project where I did this part in an managed c++ dll, it was very very fast.

an other idea:
{
texture.LockRectangle(0, LockFlags.None, out stream); // fixed
var bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, stream.DataPointer);
var graphics = Graphics.FromImage(bitmap);

graphics.Clear(color);

graphics.Dispose();
texture.UnlockRectangle(0);
graphicsbitmap.Dispose();
}
Something like this, has extra costs because of the bitmap creating and graphics. But the graphics.Clear ist much much faster than the for (int i = 0; i < stream.Length / 4; i++).

Anyone a better solution?
Last Edit: 1 year 4 months ago by Boemer. Reason: fixed out stream
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method => GetData & SetData 1 year 4 months ago #1299


  • Posts:843 Thank you received: 1
  • xoofx's Avatar
  • xoofx
  • Administrator
  • OFFLINE
DataStream is not really efficient, as it is using a current position and needs to update it. Graphics.Clear on the other hand is using probably behind the scene a memset.

Also, texture.LockRectangle() is returning a DataRectangle and not a DataStream. If you want to clear it, just use Utilities.ClearMemory(stream.DataPointer, 0, size); (which is a memset).

Basically, if you need to achieve almost the same speed than in C++, you need to do it the same way (using unsafe...etc.) and not going through some "high level" classes that could add some unnecessary overhead for your usecase.
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method => GetData & SetData 1 year 4 months ago #1313


  • Posts:2
  • Boemer's Avatar
  • Boemer
  • Fresh Boarder
  • OFFLINE
Hi xoofx,

thanks for the stream fix, (fixed it in the example).

When using Utilities.Clear, you can only write a byte, not an 32 bits integer (for a color). (I didn't know about the utilities class before... thanks..)

I build an example with IntPtr:

var datarectangle = texture.LockRectangle(0, LockFlags.None);
int fillcolor = System.Drawing.Color.Red.ToArgb();
unsafe
{
int *iptr = (int*)datarectangle.DataPointer.ToPointer();
for (int i = 0, j = width * height; i < j; i++)
{
*iptr = fillcolor;
iptr++;
}
}
texture.UnlockRectangle(0);


I made a benchmark by filling a texture of around 1000x120 px 100 times.

- stream.write method => 260 ms
- unsafe ptr method => 33 ms
- gdi graphics.clear method (internal GDI polygon) => 6.6 ms
- memset (Utilities.ClearMemory), but only 1 byte => 2.2 ms

Any better alternative? memset isn't usable with a 32 bits integer; And I don't like using gdi in directX...
Last Edit: 1 year 4 months ago by Boemer.
The administrator has disabled public write access.

Re: [D3D9] Texture.Fill() method => GetData & SetData 1 year 4 months ago #1319


  • Posts:843 Thank you received: 1
  • xoofx's Avatar
  • xoofx
  • Administrator
  • OFFLINE
Unfortunately, there is nothing directly accessible in .NET to do this efficiently (apart from using Graphics GDI as you found, but this seems to be a bit laborious). For the unsafe loop, I would try to clear the value using a struct with 4 colors values, thought that won't probably change much.

The best method would be to use a DLL function using some SSE2 instructions that would loop and set 128 bits values in one shot, This would be the fastest option.
The administrator has disabled public write access.
  • Page:
  • 1
Time to create page: 0.265 seconds