Texture Renders Incorrectly in Application but Perfectly fine in VS2013's Graphics Debugger

Started by
4 comments, last by jdub 9 years, 2 months ago

I am building an application that rasterizes (on the CPU) and renders 2D triangles. In order to do this, I create a texture to hold the 2D triangles and then render it on-screen on a textured quad. The issue is that, the triangle renders incorrectly when rendered while the application is running. However, when I capture a frame inside the VS2013's graphics debugger, the resultant frame is rendered with the triangle appearing as I would expect it to be. Here is code for how I create the texture holding the triangle:


struct Pixel
{
char r, g, b, a;
};

....

HRESULT res;
D3D11_TEXTURE2D_DESC texture_desc;
D3D11_SUBRESOURCE_DATA initial_data;
D3D11_SHADER_RESOURCE_VIEW_DESC SRV_desc;
Pixel default_color;

this->raw_data = (char *)malloc(this->image_width*this->image_height*sizeof(Pixel));
default_color.r = 0;
default_color.g = 0;
default_color.b = 0;
default_color.a = 255;

texture_desc.ArraySize = 1;
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texture_desc.Width = this->image_width;
texture_desc.Height = this->image_height;
texture_desc.MipLevels = 1;
texture_desc.MiscFlags = 0;
texture_desc.SampleDesc.Count = 1; 
texture_desc.SampleDesc.Quality = 0;
texture_desc.Usage = D3D11_USAGE_DYNAMIC;

initial_data.pSysMem = this->raw_data;
initial_data.SysMemPitch = this->image_width * sizeof(Pixel);
initial_data.SysMemSlicePitch = 0;
	
SRV_desc.Texture2D.MipLevels = 1;
SRV_desc.Texture2D.MostDetailedMip = 0;
SRV_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SRV_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;

for (int i = 0; i < this->image_height; i++)
{
	for (int j = 0; j < this->image_width; j++)
	{
		memcpy(&this->raw_data[i*this->image_width*sizeof(Pixel) + j*sizeof(Pixel)], &default_color, sizeof(Pixel));
	}
}

if (FAILED(res = this->renderer->GetDevice()->CreateTexture2D(&texture_desc, &initial_data, &this->texture)))
{
	return false;
}

if (FAILED(res = this->renderer->GetDevice()->CreateShaderResourceView(this->texture, &SRV_desc, &this->texture_SRV)))
{
	return false;
}

And here is where the quad is rendered:


D3D11_MAPPED_SUBRESOURCE mapped_subresource;
ID3D11Buffer *vBuffs = {this->quad_v_buffer};
UINT strides[] = {sizeof(TexturedVertex)};
UINT offsets[] = {0};
ID3D11SamplerState *sampler_states = { this->renderer->GetSamplerState() };
ID3D11ShaderResourceView *textureSRVs = { this->texture_SRV };

HRESULT res = this->renderer->GetDeviceContext()->Map(this->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_subresource);
memcpy(mapped_subresource.pData, this->raw_data, this->image_width*this->image_height*sizeof(Pixel));
this->renderer->GetDeviceContext()->Unmap(this->texture, 0);

this->renderer->BindShader(SHADER_TYPE_TEXTURE);
this->renderer->SetTransform(TRANSFORM_WORLD, Matrix::Identity());
this->renderer->SetTransform(TRANSFORM_VIEW, Matrix::Identity());
this->renderer->SetTransform(TRANSFORM_PROJECTION, Matrix::Identity());

this->renderer->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
this->renderer->GetDeviceContext()->IASetVertexBuffers(0, 1, &vBuffs, strides, offsets);
	
this->renderer->GetDeviceContext()->PSSetShaderResources(0, 1, &textureSRVs);

this->renderer->SetCullMode(D3D11_CULL_NONE);

this->renderer->GetDeviceContext()->Draw(6, 0);

I should also add that the previous code works absolutely fine (renders a textured quad) when I provide a texture that I load from disk.

Attached are images of how the quad renders 2 triangles correctly (in the graphics debugger) and incorrectly (on the application window).[attachment=25657:triangle_error.jpg]

[attachment=25656:triangle_correct.jpg]

J.W.
Advertisement
Hi. May be you are not zeroing out the structure like memset on texture description and other structure. Do that and see.
The debug builds validate all members and release don't.

Thanks for the response. Perhaps I didn't clarify but the Application renders incorrectly while running in debug mode. However, when a frame is captured inside the graphics debugger, the frame renders as it should.

J.W.


HRESULT res = this->renderer->GetDeviceContext()->Map(this->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_subresource);
memcpy(mapped_subresource.pData, this->raw_data, this->image_width*this->image_height*sizeof(Pixel));
this->renderer->GetDeviceContext()->Unmap(this->texture, 0);

This is almost certainly where it's going wrong. You're ignoring the pitch value in the mapped_subresource, and it just happens to work correctly when using the debugger.

As Adam_42 mentions, the Map call looks suspicious. In addition, is there a reason you call Map/Unmap after you've already created an SRV from the texture?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

As Adam_42 mentions, the Map call looks suspicious. In addition, is there a reason you call Map/Unmap after you've already created an SRV from the texture?

This is for a school project where the goal is to rasterize triangles. Thus, the contents of the texture "back buffer" could change so I would rather Map/Unmap it than create a new texture every time I need to draw.

It turns out that the Map/Unmap is indeed the culprit. I was creating the texture as a size that isn't memory aligned (1000*1000) so DirectX pads the texture to make it be aligned. I wasn't accounting for the extra padding while writing texture data.

J.W.

This topic is closed to new replies.

Advertisement