This is C# WPF using SharpDX 4.0.
I'm trying to update a dynamic texture on each render loop using a color buffer generated from a library. I'm seeing an issue where the resulting texture doesn't match the expected bitmap. The texture appears to be wider than expect or the format is larger than expected.
var surfaceWidth = 200; var surfaceHeight = 200;
var pixelBytes = surfaceWidth * surfaceHeight * 4;
//Set up the color buffer and byte array to stream to the texture
_colorBuffer = new int[surfaceWidth * surfaceHeight];
_textureStreamBytes = new byte[pixelBytes]; //16000 length
//Create the texture to update
_scanTexture = new Texture2D(Device, new Texture2DDescription()
{
Format = Format.B8G8R8A8_UNorm,
ArraySize = 1,
MipLevels = 1,
Width = SurfaceWidth,
Height = SurfaceHeight,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Dynamic,
BindFlags = BindFlags.ShaderResource,
CpuAccessFlags = CpuAccessFlags.Write,
OptionFlags = ResourceOptionFlags.None,
});
_scanResourceView= new ShaderResourceView(Device, _scanTexture);
context.PixelShader.SetShaderResource(0, _scanResourceView);
And on render I populate the color buffer and write to the texture.
protected void Render()
{
Device.ImmediateContext.ClearRenderTargetView(
RenderTargetView, new SharpDX.Mathematics.Interop.RawColor4(0.8f,0.8f,0,1));
Library.GenerateColorBuffer(ref _colorBuffer);
System.Buffer.BlockCopy(_colorBuffer, 0, depthPixels, 0, depthPixels.Length);
_parent.DrawBitmap(ref _colorBuffer);
DataBox databox = context.MapSubresource(_scanTexture, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out DataStream stream);
if (!databox.IsEmpty)
stream.Write(_textureStreamBytes, 0, _textureStreamBytes.Length);
context.UnmapSubresource(_scanTexture, 0);
context.Draw(4, 0);
}
Sampler creation and setting before the above happens:
var sampler = new SamplerState(_device, new SamplerStateDescription()
{
Filter = SharpDX.Direct3D11.Filter.MinMagMipLinear,
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = SharpDX.Color.Blue,
ComparisonFunction = Comparison.Never,
MaximumAnisotropy = 1,
MipLodBias = 0,
MinimumLod = 0,
MaximumLod = 0,
});
context = _device.ImmediateContext;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
context.VertexShader.Set(vertexShader);
context.Rasterizer.SetViewport(new Viewport(0, 0, SurfaceWidth, SurfaceHeight, 0.0f, 1.0f));
context.PixelShader.Set(pixelShader);
context.PixelShader.SetSampler(0, sampler);
context.OutputMerger.SetTargets(depthView, _renderTargetView);
And shader (using a full screen triangle with no vertices):
SamplerState pictureSampler;
Texture2D picture;
struct PS_IN
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD;
};
PS_IN VS(uint vI : SV_VERTEXID)
{
float2 texcoord = float2(vI & 1,vI >> 1); //you can use these for texture coordinates later
PS_IN output = (PS_IN)0;
output.pos = float4((texcoord.x - 0.5f) * 2, -(texcoord.y - 0.5f) * 2, 0, 1);
output.tex = texcoord;
return output;
}
float4 PS(PS_IN input) : SV_Target
{
return picture.Sample(pictureSampler, input.tex);
}
What I'm seeing is:
_colorBuffer length 40000 (200 width *200 height)
_textureStreamBytes length 160000 (200 * 200 * 4bytes)
Stream from databox Length = 179200 difference of 19200 bytes / 4800 pixels. This translates to 24 rows of 200 pixel width. In other words the texture is 24 pixels wider than expected. But debugging shows width/height as 200.
Image showing the issue. Left is rendered view, right is bitmap
Does anyone know what I'm doing wrong here? Or things that should/could be done differently?
Thank you.
P.S. I've got this working correctly in OpenGL by using a similar process but need to get it working for directx:
gl.TexSubImage2D(OpenGL.GL_TEXTURE_2D, 0, 0, 0, (int)width, (int)height, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, colorBuffer);