Sergio0694 / ComputeSharp

A .NET library to run C# code in parallel on the GPU through DX12, D2D1, and dynamically generated HLSL compute and pixel shaders, with the goal of making GPU computing easy to use for all .NET developers! 🚀
MIT License
2.74k stars 122 forks source link

Please add support of Texture.CopyTexture() #215

Open JohnMasen opened 2 years ago

JohnMasen commented 2 years ago

Description (optional)

I found the library is using texture copy inside AllocateReadOnlyTexture2D<T,TPixel>(), however the texture copy method is not exposed to public. The idea is able to create a texture processing pipleline like this: Upload ->CopyTo Texture -> Process Texture ->Readback result

Rationale

I'm trying to use ComputeSharp to build a fast image resize/resample pipeline for AI Model(ONNX) inference, the stream from video source is RGBA32 format, I wish I could use UploadTexutre2D to upload the stream then copy it to ReadOnlyTexture2D .

Proposed API

Add CopyTexture<TSource,TTarget>(Texture texture) to UploadTexture.

Drawbacks

TBD

Alternatives

Other thoughts

It is also suggested add a customer type mapper to allow map user data structure to DXPixelFormat just like DXGIFormatHelper. User can create UploadTexture/ReadOnlyTexture with the custom mapper to

  1. Map ImageSharp pixel formats directly to DirectX PixelFormats without MemoryMarshal.Cast()
  2. use DXGI_FORMAT_NV12 directly from DXVA GPU decoded video frame

example: device.AllocateUploadTexture2D(ReadonlySpan buffer, int w, int h, DXGITypeMapper mapper );

Thanks

Sergio0694 commented 2 years ago

I'm not sure I understand the proposal (also the actual API proposal isn't really an API either). You can already do this:

using UploadTexture2D<float> upload = GraphicsDevice.Default.AllocateUploadTexture2D<float>(64, 64);
using ReadOnlyTexture2D<float> texture = GraphicsDevice.Default.AllocateReadOnlyTexture2D<float>(64, 64);

upload.CopyTo(texture);

// Run the shader...

using ReadBackTexture2D<float> readback = GraphicsDevice.Default.AllocateReadBackTexture2D<float>(64, 64);

texture.CopyTo(readback);

Am I missing something? Could you clarify what you're trying to do that's not working for you? 🤔 Thanks!

JohnMasen commented 2 years ago

The idea is CopyTexture will automatically convert the pixel format from source to target, it will be a large cost to convert it in CPU. The suggestion in alternatives is allowing user to upload a user mapped pixel format, this allows me to upload pixel memory directly from DXGI_FORMAT_NV12 formatted memory data. My target is I can upload a NV12 frame data to GPU, then CopyTexture to a RGBA32 Texture for later processing.

JohnMasen commented 2 years ago

Another target is I can upload a RGBA image data to GPU, then CopyTexture to a BGRA32 Texture for later processing

rickbrew commented 2 years ago

I've had to do something similar when working with Direct2D so I can render on the GPU at RGBA Float32 precision (128-bits per pixel), and then pull data back to the CPU-side at BGRA U8 precision (32-bits per pixel). I render to a RGBA F32 target, then I copy to a second GPU-side bitmap that is BGRA U8, which means the conversion happens on the GPU. Very useful because otherwise, as you state, the cost to do it on the CPU is much higher. This also lets me do un-premultiplication on the GPU at full Float32, which avoids smashing low-alpha color values.

Sergio0694 commented 2 years ago

@JohnMasen I'm still not sure I understand the proposal, could you clarify exactly what API you're asking for? In the first message, you say:

"I found the library is using texture copy inside AllocateReadOnlyTexture2D<T,TPixel>(), however the texture copy method is not exposed to public."

But... That doesn't seem to be true? That API is this:

https://github.com/Sergio0694/ComputeSharp/blob/1da016a8478f489f954ef976b75e4d380676c5d5/src/ComputeSharp/Graphics/Extensions/GraphicsDeviceExtensions.Resources.cs#L326-L338

But that texture.CopyFrom is a public API as well:

https://github.com/Sergio0694/ComputeSharp/blob/1da016a8478f489f954ef976b75e4d380676c5d5/src/ComputeSharp/Graphics/Extensions/Texture2DExtensions.cs#L357-L366

So I'm not sure what API you're referring to exactly as not being public here? 🤔

"Add CopyTexture<TSource,TTarget>(Texture texture) to UploadTexture."

If the ask is for a new API to copy to a texture with a different pixel format, then I can understand that, I'm just not sure how the two things are related. Like, this just seems like a request for a new API, but not to make an existing one public?

JohnMasen commented 2 years ago

The native api allows user copy texture with a pixel format mapping, this enables user copy and transfer pixelformat with single operation. In my program, I'm looking for a way to upload a RGBA32 format texture and copy it to a BGR texutre without manually transfer the pixels. The best way I can think is expose the CopyTexture() function with pixelmapping parameter.