who Understand this C# opencl.net code? - c#

L want to learn the C# opencl.net to accelerate the code by gpu, this code is in the website https://habrahabr.ru/post/124873/, l cannot understand the meaning, anyone can explain it, and anywhere can l learn about the opencl.net, thank u very much.
private void button4_Click(object sender, EventArgs e)
{
//Установка параметров, инициализирующих видеокарты при работе. В Platforms[1] должен стоять индекс
//указывающий на используемую платформу
ComputeContextPropertyList Properties = new ComputeContextPropertyList(ComputePlatform.Platforms[1]);
ComputeContext Context = new ComputeContext(ComputeDeviceTypes.All, Properties, null, IntPtr.Zero);
//Текст програмы, исполняющейся на устройстве (GPU или CPU). Именно эта программа будет выполнять паралельные
//вычисления и будет складывать вектора. Программа написанна на языке, основанном на C99 специально под OpenCL.
string vecSum = #"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] + v2[i];
}
";
//Список устройств, для которых мы будем компилировать написанную в vecSum программу
List<ComputeDevice> Devs = new List<ComputeDevice>();
Devs.Add(ComputePlatform.Platforms[1].Devices[0]);
Devs.Add(ComputePlatform.Platforms[1].Devices[1]);
Devs.Add(ComputePlatform.Platforms[1].Devices[2]);
//Компиляция программы из vecSum
ComputeProgram prog = null;
try
{
prog = new ComputeProgram(Context, vecSum); prog.Build(Devs, "", null, IntPtr.Zero);
}
catch
{ }
//Инициализация новой программы
ComputeKernel kernelVecSum = prog.CreateKernel("floatVectorSum");
//Инициализация и присвоение векторов, которые мы будем складывать.
float[] v1 = new float[100], v2 = new float[100];
for (int i = 0; i < v1.Length; i++)
{
v1[i] = i;
v2[i] = 2 * i;
}
//Загрузка данных в указатели для дальнейшего использования.
ComputeBuffer<float> bufV1 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v1);
ComputeBuffer<float> bufV2 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v2);
//Объявляем какие данные будут использоваться в программе vecSum
kernelVecSum.SetMemoryArgument(0, bufV1);
kernelVecSum.SetMemoryArgument(1, bufV2);
//Создание програмной очереди. Не забудте указать устройство, на котором будет исполняться программа!
ComputeCommandQueue Queue = new ComputeCommandQueue(Context, Cloo.ComputePlatform.Platforms[1].Devices[0], Cloo.ComputeCommandQueueFlags.None);
//Старт. Execute запускает программу-ядро vecSum указанное колличество раз (v1.Length)
Queue.Execute(kernelVecSum, null, new long[] { v1.Length }, null, null);
//Считывание данных из памяти устройства.
float[] arrC = new float[100];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
Queue.Read<float>(bufV1, true, 0, 100, arrCHandle.AddrOfPinnedObject(), null);
}

private void button4_Click(object sender, EventArgs e)
{
ComputeContextPropertyList Properties = new ComputeContextPropertyList(ComputePlatform.Platforms[1]);
ComputeContext Context = new ComputeContext(ComputeDeviceTypes.All, Properties, null, IntPtr.Zero);
//define a function template that sum two vectors
string vecSum = #"
__kernel void
floatVectorSum(__global float * v1,
__global float * v2)
{
int i = get_global_id(0);
v1[i] = v1[i] + v2[i];
}
";
//add gpu devices into list for executing the vecSum function defined at last step
List<ComputeDevice> Devs = new List<ComputeDevice>();
Devs.Add(ComputePlatform.Platforms[1].Devices[0]);
Devs.Add(ComputePlatform.Platforms[1].Devices[1]);
Devs.Add(ComputePlatform.Platforms[1].Devices[2]);
//define a compute programe with function define and gpu devices specified.
ComputeProgram prog = null;
try
{
prog = new ComputeProgram(Context, vecSum); prog.Build(Devs, "", null, IntPtr.Zero);
}
catch
{ }
ComputeKernel kernelVecSum = prog.CreateKernel("floatVectorSum");
//init the vectors need by the vecSum.
float[] v1 = new float[100], v2 = new float[100];
for (int i = 0; i < v1.Length; i++)
{
v1[i] = i;
v2[i] = 2 * i;
}
//create parametes needed as pass in parameter for vecSum.
ComputeBuffer<float> bufV1 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v1);
ComputeBuffer<float> bufV2 = new ComputeBuffer<float>(Context, ComputeMemoryFlags.ReadWrite | ComputeMemoryFlags.UseHostPointer, v2);
//pass the parameters in.
kernelVecSum.SetMemoryArgument(0, bufV1);
kernelVecSum.SetMemoryArgument(1, bufV2);
//queue your compute request.
ComputeCommandQueue Queue = new ComputeCommandQueue(Context, Cloo.ComputePlatform.Platforms[1].Devices[0], Cloo.ComputeCommandQueueFlags.None);
//execute your compute request
Queue.Execute(kernelVecSum, null, new long[] { v1.Length }, null, null);
//clean the resource and read the result from the queue
float[] arrC = new float[100];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
Queue.Read<float>(bufV1, true, 0, 100, arrCHandle.AddrOfPinnedObject(), null);
}

Related

c# socket - received file works on Firefox but doesn't work on Chrome

When the file is sent to c# server through firefox, it works but it doesn't work on chrome.
In firefox, every files size can be received well.
in chrome, only small files are received. however, received bytes of Files larger than 50kb are not equal to the file size.
public class Client
{
private static readonly string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public Socket Socket { set; get; }
private byte[] Buffer { get; set; }
private int BufferSize { get; set; } = 1024 * 1024;
private List<byte> Buffers = new List<byte>();
private BytesDecoder decoder = new BytesDecoder();
public void Listen()
{
SendHandshake();
BeginReceive();
}
private void SendHandshake()
{
try
{
byte[] buffer = new byte[1024];
Socket.Receive(buffer);
var key = new Regex(#"Sec-WebSocket-Key:\s(.*?)\r\n").Match(Encoding.UTF8.GetString(buffer)).Groups[1].Value.Trim();
byte[] keyBytes = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + guid));
key = Convert.ToBase64String(keyBytes);
var response = string.Format(string.Join("\r\n", new string[]{
"HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
"Sec-WebSocket-Accept: {0}",
"",
""
}), key);
Socket.Send(Encoding.UTF8.GetBytes(response));
}
catch (SocketException ex)
{
Console.WriteLine("{0}: {1}", "SendHandshake", ex.Message);
Close();
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", "SendHandshake", ex.Message);
}
}
private void BeginReceive()
{
try
{
Buffer = new byte[BufferSize];
Socket.BeginReceive(Buffer, 0, BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), this);
}
catch (SocketException ex)
{
Console.WriteLine("{0}: {1}", "BeginReceive1", ex.Message);
Close();
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", "BeginReceive2", ex.Message);
}
}
public static byte[] TrimEnd(byte[] array)
{
int lastIndex = Array.FindLastIndex(array, b => b != 0);
Array.Resize(ref array, lastIndex + 1);
return array;
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
var bytes = new byte[0];
if (decoder.indexFirstMask==0)
{
bytes = decoder.DecodeMessage(TrimEnd(Buffer));
}
else
{
bytes = decoder.DecodeRemainingMessage(TrimEnd(Buffer));
}
Buffers = Buffers.Concat(bytes).ToList();
if (Buffers.ToArray().Length == Convert.ToInt32(fileInfo["size"]))
{
File.WriteAllBytes(#"C:\" + fileInfo["name"], Buffers.ToArray());
}
BeginReceive();
}
catch (SocketException ex)
{
Close();
Console.WriteLine("{0}: {1}", "ReceiveCallback", ex.Message);
}
catch (Exception ex)
{
BeginReceive();
Console.WriteLine("{0}: {1}", "ReceiveCallback", ex.Message);
}
}
public void Close()
{
Socket.Shutdown(SocketShutdown.Both);
Socket.Close();
Socket.Dispose();
}
}
when file size less than 50kb, byte 0 is 130 (opcode=2) and file size larger than 50 kb, byte 0 is 2;
It is clear that there is a problem with frame decoding or handshake response....
public class BytesDecoder
{
public int dataLength, indexFirstMask=0;
public IEnumerable<byte> keys;
public byte[] DecodeMessage(byte[] bytes)
{
Console.WriteLine("+DecodeMessage+");
byte secondByte = bytes[1];
bool masked = (bytes[1] & 128) != 0;
dataLength = secondByte & 127;
indexFirstMask = 2;
if (masked)
{
Console.WriteLine("Masked bit SET");
}
if (dataLength == 126)
{
indexFirstMask = 4;
dataLength = bytes[3] | bytes[2] << 8;
}
else if (dataLength == 127)
{
indexFirstMask = 10;
dataLength = bytes[9] | bytes[8] << 8 | bytes[7] << 16 | bytes[6] << 24 | bytes[5] << 32 |
bytes[4] << 40 | bytes[3] << 48 | bytes[2] << 56;
}
keys = bytes.Skip(indexFirstMask).Take(4);
int indexFirstDataByte = indexFirstMask + 4;
byte[] decoded = new byte[bytes.Length - indexFirstDataByte];
Console.WriteLine("dataLength : " + dataLength + " ; bytes.Length : " + bytes.Length);
int j = 0;
for (int i = indexFirstDataByte; i < bytes.Length; i++)
{
decoded[j] = (byte)(bytes[i] ^ keys.ElementAt(j % 4));
j++;
}
Console.WriteLine("-DecodeMessage-");
return decoded;
}
public byte[] DecodeRemainingMessage(byte[] bytes)
{
Console.WriteLine("+DecodeRemainingMessage+");
int indexFirstDataByte = 0;
byte[] decoded = new byte[bytes.Length - indexFirstDataByte];
int j = 0;
for (int i = indexFirstDataByte; i < bytes.Length; i++)
{
decoded[j] = (byte)(bytes[i] ^ keys.ElementAt(j % 4));
j++;
}
Console.WriteLine("-DecodeRemainingMessage-");
return decoded;
}
}
js code:
connect:function(){
var root = this;
root.websocket = new WebSocket(root.url);
root.websocket.binaryType = "arraybuffer";
root.websocket.onopen = () => root.fireEvent('connect');
root.websocket.onmessage = (e) => {
root.fireEvent('receive',JSON.parse(e.data));
}
window.addEventListener("beforeunload", function() {
root.websocket.onclose = function () {};
root.websocket.close();
});
},
sendMessage:function(msg){
var root = this;
root.controller.websocket.send(message);
},
sendFile:function(){
var root = this;
var file = document.getElementById('filename').files[0];
var root = this;
var loader = new FileReader();
loader.onload = (e) => {
var byteArray = new Uint8Array(e.target.result);
root.buffer = byteArray.buffer;
root.byteLength = root.buffer.byteLength;
root.server.websocket.send(root.buffer);
}
loader.readAsArrayBuffer(file);
}
Edit 1:
problem found large messages dataLength not currect
dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2] }, 0);
for example file size is 169174 received data length
received data length in firefox= 169174
received data length in chrome= 131000
Edit 2:
FIN bit in chrome is 2 and in firefox is 1

Xamarin.Android wav to m4a

I have found the answer for Java: https://stackoverflow.com/a/36357819/202179 and tried to port it to Xamarin.
Here is the code that I've made:
const string COMPRESSED_AUDIO_FILE_MIME_TYPE = "audio/mp4a-latm";
const int COMPRESSED_AUDIO_FILE_BIT_RATE = 64000; // 64kbps
const int SAMPLING_RATE = 48000;
const int BUFFER_SIZE = 48000;
const int CODEC_TIMEOUT_IN_MS = 5000;
void Compress()
{
var inputFile = new Java.IO.File(tempFileWavPath);
var fis = new Java.IO.FileInputStream(inputFile);
var outputFile = new Java.IO.File(fileM4APath);
if (outputFile.Exists())
outputFile.Delete();
var mux = new MediaMuxer(outputFile.AbsolutePath, MuxerOutputType.Mpeg4);
MediaFormat outputFormat = MediaFormat.CreateAudioFormat(COMPRESSED_AUDIO_FILE_MIME_TYPE, SAMPLING_RATE, 1);
outputFormat.SetInteger(MediaFormat.KeyAacProfile, (int)MediaCodecProfileType.Aacobjectlc);
outputFormat.SetInteger(MediaFormat.KeyBitRate, COMPRESSED_AUDIO_FILE_BIT_RATE);
outputFormat.SetInteger(MediaFormat.KeyMaxInputSize, 16384);
MediaCodec codec = MediaCodec.CreateEncoderByType(COMPRESSED_AUDIO_FILE_MIME_TYPE);
codec.Configure(outputFormat, null, null, MediaCodecConfigFlags.Encode);
codec.Start();
MediaCodec.BufferInfo outBuffInfo = new MediaCodec.BufferInfo();
byte[] tempBuffer = new byte[BUFFER_SIZE];
var hasMoreData = true;
double presentationTimeUs = 0;
int audioTrackIdx = 0;
int totalBytesRead = 0;
int percentComplete = 0;
do
{
int inputBufIndex = 0;
while (inputBufIndex != -1 && hasMoreData)
{
inputBufIndex = codec.DequeueInputBuffer(CODEC_TIMEOUT_IN_MS);
if (inputBufIndex >= 0)
{
var dstBuf = codec.GetInputBuffer(inputBufIndex);
dstBuf.Clear();
int bytesRead = fis.Read(tempBuffer, 0, dstBuf.Limit());
if (bytesRead == -1)
{ // -1 implies EOS
hasMoreData = false;
codec.QueueInputBuffer(inputBufIndex, 0, 0, (long)presentationTimeUs, MediaCodecBufferFlags.EndOfStream);
}
else
{
totalBytesRead += bytesRead;
dstBuf.Put(tempBuffer, 0, bytesRead);
codec.QueueInputBuffer(inputBufIndex, 0, bytesRead, (long)presentationTimeUs, 0);
presentationTimeUs = 1000000l * (totalBytesRead / 2) / SAMPLING_RATE;
}
}
}
// Drain audio
int outputBufIndex = 0;
while (outputBufIndex != (int)MediaCodecInfoState.TryAgainLater)
{
outputBufIndex = codec.DequeueOutputBuffer(outBuffInfo, CODEC_TIMEOUT_IN_MS);
if (outputBufIndex >= 0)
{
var encodedData = codec.GetOutputBuffer(outputBufIndex);
encodedData.Position(outBuffInfo.Offset);
encodedData.Limit(outBuffInfo.Offset + outBuffInfo.Size);
if ((outBuffInfo.Flags & MediaCodecBufferFlags.CodecConfig) != 0 && outBuffInfo.Size != 0)
{
codec.ReleaseOutputBuffer(outputBufIndex, false);
}
else
{
mux.WriteSampleData(audioTrackIdx, encodedData, outBuffInfo);
codec.ReleaseOutputBuffer(outputBufIndex, false);
}
}
else if (outputBufIndex == (int)MediaCodecInfoState.OutputFormatChanged)
{
outputFormat = codec.OutputFormat;
audioTrackIdx = mux.AddTrack(outputFormat);
mux.Start();
}
}
percentComplete = (int)Math.Round(((float)totalBytesRead / (float)inputFile.Length()) * 100.0);
} while (outBuffInfo.Flags != MediaCodecBufferFlags.EndOfStream);
fis.Close();
mux.Stop();
mux.Release();
}
This almost works as it converts the file, but the resulting file appears to be encoded too fast - the pitch is too high and speed is too high and the reproduction lasts shorter than expected.
It is likely that just some slight change is needed, but I am not sure what. Can anyone suggest?
I could reproduce the resulting file appears to be encoded too fast when i use the different size of SAMPLING_RATE.
For example, i download a wav file online. The Sampline Rate is 11025. If i use the original rate 48000 in the code, it would play too fast. When i use 11025, it would work.
So we need to know the Sampling Rate of the wav fille and then set it in the code.
const int SAMPLING_RATE = 11025;//44100, 48000

Capture screenshot of fullscreen DX11 program using SharpDX and EasyHook

Before anybody mentions it, I refered to this link to find out how I needed to copy the backbuffer to a bitmap.
Current situation
I am injected to the target process
Target process' FeatureLevel = Level_11_0
Target SwapChain is being made with DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH flag.
SwapChain::Present function is hooked.
Screenshot turns out black and target process crashes. without screenshot process runs fine.
Desired situation
Make the screenshot properly and let the target process continue with its normal execution.
Code
NOTE Hook class is the same as in the link. I only added an UnmodifiableHook version of it which does what its name says. I left out all unimportant bits.
TestSwapChainHook.cs
using System;
using System.Runtime.InteropServices;
namespace Test
{
public sealed class TestSwapChainHook : IDisposable
{
private enum IDXGISwapChainVirtualTable
{
QueryInterface = 0,
AddRef = 1,
Release = 2,
SetPrivateData = 3,
SetPrivateDataInterface = 4,
GetPrivateData = 5,
GetParent = 6,
GetDevice = 7,
Present = 8,
GetBuffer = 9,
SetFullscreenState = 10,
GetFullscreenState = 11,
GetDesc = 12,
ResizeBuffers = 13,
ResizeTarget = 14,
GetContainingOutput = 15,
GetFrameStatistics = 16,
GetLastPresentCount = 17,
}
public static readonly int VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT = 18;
private static IntPtr[] SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES;
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
public delegate int DXGISwapChainPresentDelegate(IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags);
public delegate int DXGISwapChainPresentHookDelegate(UnmodifiableHook<DXGISwapChainPresentDelegate> hook, IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags);
private DXGISwapChainPresentHookDelegate _present;
private Hook<DXGISwapChainPresentDelegate> presentHook;
static TestSwapChainHook()
{
SharpDX.DXGI.Rational rational = new SharpDX.DXGI.Rational(60, 1);
SharpDX.DXGI.ModeDescription modeDescription = new SharpDX.DXGI.ModeDescription(100, 100, rational, SharpDX.DXGI.Format.R8G8B8A8_UNorm);
SharpDX.DXGI.SampleDescription sampleDescription = new SharpDX.DXGI.SampleDescription(1, 0);
using (SharpDX.Windows.RenderForm renderForm = new SharpDX.Windows.RenderForm())
{
SharpDX.DXGI.SwapChainDescription swapChainDescription = new SharpDX.DXGI.SwapChainDescription();
swapChainDescription.BufferCount = 1;
swapChainDescription.Flags = SharpDX.DXGI.SwapChainFlags.None;
swapChainDescription.IsWindowed = true;
swapChainDescription.ModeDescription = modeDescription;
swapChainDescription.OutputHandle = renderForm.Handle;
swapChainDescription.SampleDescription = sampleDescription;
swapChainDescription.SwapEffect = SharpDX.DXGI.SwapEffect.Discard;
swapChainDescription.Usage = SharpDX.DXGI.Usage.RenderTargetOutput;
SharpDX.Direct3D11.Device device = null;
SharpDX.DXGI.SwapChain swapChain = null;
SharpDX.Direct3D11.Device.CreateWithSwapChain(SharpDX.Direct3D.DriverType.Hardware, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport, swapChainDescription, out device, out swapChain);
try
{
IntPtr swapChainVirtualTable = Marshal.ReadIntPtr(swapChain.NativePointer);
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES = new IntPtr[VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT];
for (int x = 0; x < VIRTUAL_METHOD_COUNT_LEVEL_DEFAULT; x++)
{
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES[x] = Marshal.ReadIntPtr(swapChainVirtualTable, x * IntPtr.Size);
}
device.Dispose();
swapChain.Dispose();
}
catch (Exception)
{
if (device != null)
{
device.Dispose();
}
if (swapChain != null)
{
swapChain.Dispose();
}
throw;
}
}
}
public TestSwapChainHook()
{
this._present = null;
this.presentHook = new Hook<DXGISwapChainPresentDelegate>(
SWAP_CHAIN_VIRTUAL_TABLE_ADDRESSES[(int)IDXGISwapChainVirtualTable.Present],
new DXGISwapChainPresentDelegate(hookPresent),
this);
}
public void activate()
{
this.presentHook.activate();
}
public void deactivate()
{
this.presentHook.deactivate();
}
private int hookPresent(IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags)
{
lock (this.presentHook)
{
if (this._present == null)
{
return this.presentHook.original(thisPtr, syncInterval, flags);
}
else
{
return this._present(new UnmodifiableHook<DXGISwapChainPresentDelegate>(this.presentHook), thisPtr, syncInterval, flags);
}
}
}
public DXGISwapChainPresentHookDelegate present
{
get
{
lock (this.presentHook)
{
return this._present;
}
}
set
{
lock (this.presentHook)
{
this._present = value;
}
}
}
}
}
Using code
initialization
private TestSwapChain swapChainHook;
private bool capture = false;
private object captureLock = new object();
this.swapChainHook = new TestSwapChainHook();
this.swapChainHook.present = presentHook;
this.swapChainHook.activate();
EDIT
I used a different method to capture a screenshot described in this link. However my screenshot turns out like this:
Now this seems to be a problem with my conversion settings or whatever but I'm unable to find out what exactly I need to do to fix it. I know that the surface I'm converting to a bitmap uses the DXGI_FORMAT_R10G10B10A2_UNORM format (32-bits, 10 bits per color and 2 for alpha I think?). But I'm not sure how this even works in the for loops (skipping bytes and stuff). I just plain copy pasted it.
new hook function
private int presentHook(UnmodifiableHook<IDXGISwapChainHook.DXGISwapChainPresentDelegate> hook, IntPtr thisPtr, uint syncInterval, SharpDX.DXGI.PresentFlags flags)
{
try
{
lock (this.captureLock)
{
if (this.capture)
{
SharpDX.DXGI.SwapChain swapChain = (SharpDX.DXGI.SwapChain)thisPtr;
using (SharpDX.Direct3D11.Texture2D backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
{
SharpDX.Direct3D11.Texture2DDescription texture2DDescription = backBuffer.Description;
texture2DDescription.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read;
texture2DDescription.Usage = SharpDX.Direct3D11.ResourceUsage.Staging;
texture2DDescription.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None;
texture2DDescription.BindFlags = SharpDX.Direct3D11.BindFlags.None;
using (SharpDX.Direct3D11.Texture2D texture = new SharpDX.Direct3D11.Texture2D(backBuffer.Device, texture2DDescription))
{
//DXGI_FORMAT_R10G10B10A2_UNORM
backBuffer.Device.ImmediateContext.CopyResource(backBuffer, texture);
using (SharpDX.DXGI.Surface surface = texture.QueryInterface<SharpDX.DXGI.Surface>())
{
SharpDX.DataStream dataStream;
SharpDX.DataRectangle map = surface.Map(SharpDX.DXGI.MapFlags.Read, out dataStream);
try
{
byte[] pixelData = new byte[surface.Description.Width * surface.Description.Height * 4];
int lines = (int)(dataStream.Length / map.Pitch);
int dataCounter = 0;
int actualWidth = surface.Description.Width * 4;
for (int y = 0; y < lines; y++)
{
for (int x = 0; x < map.Pitch; x++)
{
if (x < actualWidth)
{
pixelData[dataCounter++] = dataStream.Read<byte>();
}
else
{
dataStream.Read<byte>();
}
}
}
GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
try
{
using (Bitmap bitmap = new Bitmap(surface.Description.Width, surface.Description.Height, map.Pitch, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()))
{
bitmap.Save(#"C:\Users\SOMEUSERNAME\Desktop\test.bmp");
}
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
}
finally
{
surface.Unmap();
dataStream.Dispose();
}
}
}
}
this.capture = false;
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
return hook.original(thisPtr, syncInterval, flags);
}
Answer
Turns out the DXGI_FORMAT_R10G10B10A2_UNORM format is in this bit format:
A=alpha
B=blue
G=green
R=red
AABBBBBB BBBBGGGG GGGGGGRR RRRRRRRR
And Format32bppArgb is in this byte order:
BGRA
So the final loop code would be:
while (pixelIndex < pixelData.Length)
{
uint currentPixel = dataStream.Read<uint>();
uint r = (currentPixel & 0x3FF);
uint g = (currentPixel & 0xFFC00) >> 10;
uint b = (currentPixel & 0x3FF00000) >> 20;
uint a = (currentPixel & 0xC0000000) >> 30;
pixelData[pixelIndex++] = (byte)(b >> 2);
pixelData[pixelIndex++] = (byte)(g >> 2);
pixelData[pixelIndex++] = (byte)(r >> 2);
pixelData[pixelIndex++] = (byte)(a << 6);
while ((pixelIndex % map.Pitch) >= actualWidth)
{
dataStream.Read<byte>();
pixelIndex++;
}
}
That screenshot does look like R10G10B10A2 is getting stuffed into R8G8B8A8. I haven't tested your code but we should have this bit layout
xxxxxxxx yyyyyyyy zzzzzzzz wwwwwwww
RRRRRRRR RRGGGGGG GGGGBBBB BBBBBBAA
and you can extract them as follows
byte x = data[ptr++];
byte y = data[ptr++];
byte z = data[ptr++];
byte w = data[ptr++];
int r = x << 2 | y >> 6;
int g = (y & 0x3F) << 4 | z >> 4;
int b = (z & 0xF) << 6 | w >> 2;
int a = w & 0x3;
where r, g, b now have 10 bit resolution. If you want to scale them back to bytes you can do that with (byte)(r >> 2).
Update
This would replace your double for loop. I have no way of testing this so I don't want to push it further, but I believe the idea is correct. The last check should skip the padding bytes in each row.
while(dataCounter < pixelData.Length)
{
byte x = dataStream.Read<byte>();
byte y = dataStream.Read<byte>();
byte z = dataStream.Read<byte>();
byte w = dataStream.Read<byte>();
int r = x << 2 | y >> 6;
int g = (y & 0x3F) << 4 | z >> 4;
int b = (z & 0xF) << 6 | w >> 2;
int a = w & 0x3;
pixelData[dataCounter++] = (byte)(r >> 2);
pixelData[dataCounter++] = (byte)(g >> 2);
pixelData[dataCounter++] = (byte)(b >> 2);
pixelData[dataCounter++] = (byte)(a << 6);
while((dataCounter % map.Pitch) >= actualWidth)
{
dataStream.Read<byte>();
dataCounter++;
}
}

Why Cursor retrieval from My BerkerleyDB HashDatabase is not in ascennding order

I am using BerkerlyDB with c# on windows. I have a HashDatabase routine which adds 1 byte key and 1 byte data pairs using db.Put. The problem is when i use cursor.movenext() they dont come out in ascending order.
env = OpenEnv();
db = OpenDB(env, dBName);
byte[] rec1 = new byte[1];
rec1[0] = (byte)'D';
byte[] data = new byte[1] { 0 };
BDB.DatabaseEntry dbek1 = new BDB.DatabaseEntry(rec1);
db.Put(dbek1, new BDB.DatabaseEntry(data));
byte[] rec2 = new byte[1];
rec2[0] = (byte)'C';
BDB.DatabaseEntry dbek2 = new BDB.DatabaseEntry(rec2);
db.Put(dbek2, new BDB.DatabaseEntry(data));
cursor = db.Cursor();
while (cursor.MoveNext())
{
sb.Clear();
byte[] key = cursor.Current.Key.Data;
byte[] d = cursor.Current.Value.Data;
foreach (char c in key)
sb.Append(c);
sb.Append(' ');
foreach (int c in d)
sb.Append(c.ToString() + " ");
Console.WriteLine(sb.ToString());
}
private static BDB.HashDatabase OpenDB(BDB.DatabaseEnvironment env, string dbFileName)
{
BDB.HashDatabaseConfig hashConfig = new BDB.HashDatabaseConfig();
hashConfig.Env = env;
hashConfig.Duplicates = BDB.DuplicatesPolicy.SORTED;
hashConfig.Creation = BDB.CreatePolicy.IF_NEEDED;
hashConfig.PageSize = 4 * 4096;
hashConfig.FillFactor = (hashConfig.PageSize - 26) / (1 + 1 + 6);
// hashConfig.TableSize = 2000000;
return BDB.HashDatabase.Open(dbFileName, hashConfig);
}
private static BDB.DatabaseEnvironment OpenEnv()
{
BDB.MPoolConfig mpoolConfig = new BDB.MPoolConfig();
uint cacheSize = 2;
mpoolConfig.MaxCacheSize = new BDB.CacheInfo(cacheSize, 8192 * 4096, 1);
mpoolConfig.CacheSize = new BDB.CacheInfo(cacheSize, 4096 * 4096, 1);
BDB.MutexConfig mutexConfig = new BDB.MutexConfig();
mutexConfig.InitMutexes = 0;
mutexConfig.MaxMutexes = 0;
mutexConfig.Increment = 0;
BDB.DatabaseEnvironmentConfig envConfig = new BDB.DatabaseEnvironmentConfig();
envConfig.MPoolSystemCfg = mpoolConfig;
// envConfig.NoMMap = true;
envConfig.Private = true;
envConfig.Create = true;
envConfig.UseMPool = true;
envConfig.ForceFlush = true;
envConfig.MutexSystemCfg = mutexConfig;
return BDB.DatabaseEnvironment.Open(".", envConfig);
}
Any ideas would be appreciated.
Yes records will be returned as found through a cursor using DB_HASH.
If you wish sorted order through cursors, the simplest fix is to switch from DB_HASH to DB_BTREE, where leaves are always sorted. (But note that if you are using integer keys, you should use network/bigendian order for keys).
Otherwise, sort after retrieval from hash isn't impossibly hard.

Cloo OpenCL c# Problem

I am trying to get a simple Cloo program to run but it is not working, can anyone tell me why?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Cloo;
using System.Runtime.InteropServices;
namespace HelloWorld
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ComputeContextPropertyList cpl = new ComputeContextPropertyList(ComputePlatform.Platforms[0]);
ComputeContext context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero);
string kernelSource = #"
kernel void VectorAdd(
global read_only float* a,
global read_only float* b,
global write_only float* c )
{
int index = get_global_id(0);
c[index] = a[index] + b[index];
}
";
long count = 20;
float[] arrA = new float[count];
float[] arrB = new float[count];
float[] arrC = new float[count];
Random rand = new Random();
for (int i = 0; i < count; i++)
{
arrA[i] = (float)(rand.NextDouble() * 100);
arrB[i] = (float)(rand.NextDouble() * 100);
}
ComputeBuffer<float> a = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrA);
ComputeBuffer<float> b = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrB);
ComputeBuffer<float> c = new ComputeBuffer<float>(context, ComputeMemoryFlags.WriteOnly, arrC.Length);
ComputeProgram program = new ComputeProgram(context, new string[] { kernelSource });
program.Build(null, null, null, IntPtr.Zero);
ComputeKernel kernel = program.CreateKernel("VectorAdd");
kernel.SetMemoryArgument(0, a);
kernel.SetMemoryArgument(1, b);
kernel.SetMemoryArgument(2, c);
ComputeCommandQueue commands = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None);
ComputeEventList events = new ComputeEventList();
commands.Execute(kernel, null, new long[] { count }, null, events);
arrC = new float[count];
GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);
commands.Read(c, false, 0, count, arrCHandle.AddrOfPinnedObject(), events);
commands.Finish();
arrCHandle.Free();
for (int i = 0; i < count; i++)
richTextBox1.Text += "{" + arrA[i] + "} + {" + arrB[i] + "} = {" + arrC[i] + "} \n";
}
}
}
This is the error the program gives me
an unhandled exception of type
'Cloo.InvalidBinaryComputeException'
occurred in Cloo.dll
Additional information: OpenCL error
code detected: InvalidBinary.
This looks identical to the VectorAddTest that is distributed with Cloo.
Are you using ATI Stream? If yes, this may be a problem related to this: http://sourceforge.net/tracker/?func=detail&aid=2946105&group_id=290412&atid=1229014
Clootils works around this problem by allocating a console. Check Clootils/Program.cs for implementation details.
Change the kernel name - I think the name VectorAdd conflicts with something.

Categories