locked
Is there a restriction for Texture2D's width in D3D?

    Question

  • Hi,

      I have three Texture2D objects which represent Y/U/V plane of video(which U, V plane is 1/4 of the Y). In pixel shader, the RGB value is calculated and displayed. It works fine in resolution of 768*768, 896*768, 1024*768, 128n*768, where n is >= 6. However, when the width of Texture2D is not the multiple of 128, there is a jagged display. Following is my code snippet and two screen capture in 1024*768 and 960*768.

            m_tex_data[0] = y;
            m_tex_data_linelen[0] = width;
            m_tex_data_width[0]= width;
            m_tex_data_height[0]=height;
            m_tex_data[1] = u; m_tex_data[2] = v;
            m_tex_data_linelen[1] = m_tex_data_linelen[2] = width/2;
            m_tex_data_width[1]= m_tex_data_width[2]= width/2;
            m_tex_data_height[1]= m_tex_data_height[2]=height/2;    
            for (int i = 0; i < 3; i++)
    		{
    			D3D11_SUBRESOURCE_DATA textureSubresourceData = { 0 };
    			textureSubresourceData.pSysMem = m_tex_data[i];
    			textureSubresourceData.SysMemPitch = m_tex_data_linelen[i];
    			textureSubresourceData.SysMemSlicePitch = 0;
    			
    			D3D11_TEXTURE2D_DESC textureDesc = { 0 };
    			textureDesc.Width = m_tex_width[i];
    			textureDesc.Height = m_tex_height[i];
    			//textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    			//textureDesc.Usage = D3D11_USAGE_DEFAULT;
    			//textureDesc.CPUAccessFlags = 0;
    			textureDesc.Format = DXGI_FORMAT_R8_UNORM;
    			textureDesc.Usage = D3D11_USAGE_DYNAMIC;
    			textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    			textureDesc.MiscFlags = 0;
    			textureDesc.MipLevels = 1;
    			textureDesc.ArraySize = 1;
    			// Don't use multi-sampling.
    			textureDesc.SampleDesc.Count = 1;
    			textureDesc.SampleDesc.Quality = 0;
    			textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    			DX::ThrowIfFailed(
    				m_d3dDevice->CreateTexture2D(
    				&textureDesc,
    				&textureSubresourceData,
    				&m_texture[i]
    				)
    				);
    			
    			D3D11_SHADER_RESOURCE_VIEW_DESC textureViewDesc;
    			ZeroMemory(&textureViewDesc, sizeof(textureViewDesc));
    			textureViewDesc.Format = textureDesc.Format;
    			textureViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    			textureViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
    			textureViewDesc.Texture2D.MostDetailedMip = 0;
    			DX::ThrowIfFailed(
    				m_d3dDevice->CreateShaderResourceView(
    				m_texture[i].Get(),
    				&textureViewDesc,
    				&m_textureView[i]
    				)
    				);
    		}
    
    		D3D11_SAMPLER_DESC samplerDesc;
    		ZeroMemory(&samplerDesc, sizeof(samplerDesc));
    		samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;//D3D11_FILTER_MIN_MAG_MIP_POINT;
    		samplerDesc.MaxAnisotropy = 0;	
    		samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    		samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    		samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    		samplerDesc.MipLODBias = 0.0f;
    		samplerDesc.MinLOD = 0;
    		samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
    		// Don't use a comparison function.
    		samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    		samplerDesc.BorderColor[0] = 0.0f;
    		samplerDesc.BorderColor[1] = 0.0f;
    		samplerDesc.BorderColor[2] = 0.0f;
    		samplerDesc.BorderColor[3] = 0.0f;
    		DX::ThrowIfFailed(
    			m_d3dDevice->CreateSamplerState(
    			&samplerDesc,
    			&m_sampler
    			)
    			);
    Thursday, August 21, 2014 10:14 AM

Answers

  • The root cause is the row pitch of D3D11_MAPPED_SUBRESOURCE as shown in the following code:

    D3D11_MAPPED_SUBRESOURCE mappedResource; ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE)); // Disable GPU access to the vertex buffer data. m_d3dContext->Map(m_texture[i].Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);

    //Old code: memcpy(mappedResource.pData, m_tex_data[i], m_tex_data_len[i]); for (uint32 j = 0; j < m_tex_height[i]; j++) { memcpy((unsigned char*)(mappedResource.pData) + j*mappedResource.RowPitch, m_tex_data[i] + j*m_tex_data_linelen[i], m_tex_data_linelen[i]); } // Reenable GPU access to the vertex buffer data. m_d3dContext->Unmap(m_texture[i].Get(), 0);

    In some device, the row pitch is larger than the texture's width. That's why the bottom is out of the data. 

    • Marked as answer by Fallson Monday, November 17, 2014 6:48 AM
    Monday, November 17, 2014 6:47 AM

All replies

  • There's no particular restrictions for the code you've posted, so I suspect the issue is with however your YUV conversion is implemented.

    DirectXTex has code for computing pitches for all DXGI formats including video formats in the module DirectXTexUtil.cpp

    Thursday, August 21, 2014 5:54 PM
  • Hi Chuck,

      To verify whether the YUV stream is correct or not, I wrote a simple tool (a windows store universal app). It reads one frame of the yuv420p data, convert to RGBA and display in Windows.UI.Xaml.Controls.Image. At the same time, the yuv420p data is copied to the Texture2D, and display in Windows::UI::Xaml::Controls::SwapChainPanel as the code list above. The result in Surface RT is: The display is fine in Image control, and jagged in SwapChainPanel in 960*768 or 480*768; Both display are fine in 1024*768.

      I run the tool in the phone(Lumia 1020), and found the behavior is different to Surface RT: The display is fine in Image control, and jagged in SwapChainPanel in 480*768; Both display are fine in 1024*768 or 960*768.

      The screen capture of Surface RT and Phone are as the following, the whole source code of the simple tool will be uploaded later for your reference, thanks.

    Tuesday, August 26, 2014 3:26 AM
  • The project of the tool is put in the skydrive: http://1drv.ms/1ssNaXp

    There are some other phenomenons FYI:

    • All size yuv420p data (1024*768, 960*768, 480*768) are displayed fine in my desktop PC(x64).
    • All size yuv420p data are displayed fine when I start the app with Graphics Diagnostic Tool and capture the frame in SurfaceRT. 
    • Edited by Fallson Wednesday, August 27, 2014 5:25 AM
    Tuesday, August 26, 2014 3:34 AM
  • Hi,

      Any update about it? Thanks.

    Monday, September 1, 2014 6:03 AM
  •   we want to know whether it is a bug of MS. If yes, please tell us why and when to fix; if no, please tell us why the behavior happens in different machines.

      The windows phone and surface platform are the poorest mobile system in our developing experience. If the tech support to developers is poor too, the system will not go too far. 

    Thursday, September 4, 2014 7:06 AM
  • Hi,

      The original problem is list in: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/495fc034-010c-4187-b936-5e067854987a/is-there-a-restriction-for-texture2ds-width-in-d3d?forum=wingameswithdirectx#4ba62942-e548-4b17-9515-cf0a66ccf16e

      While there is no body to answer my question, so I open a new post for the problem and hope someone can help.

    Tuesday, September 9, 2014 2:52 AM
  • This isn't the appropriate place for this question. I'll ask my DirectX guy to check out your previous post.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, September 11, 2014 7:53 PM
    Moderator
  • Hi Matt,

      Thanks for your information. Because the case impacts our product's release, so we are eager for the answer. While the post is not replied for about half month. BTW, I have one question: is there any other official technique support of MS except asking the question in this forum?


    • Edited by Fallson Friday, September 12, 2014 2:33 AM
    Friday, September 12, 2014 2:31 AM
  • The official way to request support with Windows Store app development is at http://aka.ms/storesupport . The forums are for community based support and not the right place for in-depth individual support.

    The major difference between DX on phone and on Windows RT is the feature level (9_3 on phone vs. 9_1 on Surface RT), but as Chuck said the differences won't obviously affect your scenario.  I can't look at your code at the moment, but from the symptom check out your stride calculations.

    Given your theory on dividing by 128, the obvious workaround is to round up our internal texture sizes to that ratio.

    Friday, September 12, 2014 7:18 AM
    Owner
  • Hi Rob,

      Thanks for your reply. Currently, only thing we can do is just work-around as you said. However, the case is so strange:

    • The behavior is different in Windows PC, Windows RT, and Windows Phone.
    • The behavior is different when the app is started with Graphics Diagnostic Tool  in Windows RT.

      I attached a simple project with all resources and codes which will reproduce the behavior in Surface 2 and lumia 1020. 

    Monday, September 15, 2014 2:32 AM
  • This appears to be a driver issue. I see the problem you describe in the 960*768 and 480*768 modes on my desktop system. It has an NVidia GPU supporting feature level 10, and the Surface RT also uses an NVidia chipset.

    The problem did not occur when I forced WARP mode.

    --Rob

    Tuesday, September 16, 2014 1:45 AM
    Owner
  • Hi Fallson,

    We looked at this again and reproduced it with an ATI system as well, so this doesn't look likely to be an NVidia driver issue. It does appear to be a sizing issue of some sort with the texture: the way the image wraps suggests that the width is off, and the green at the bottom suggests that we're running out of data. Unfortunately this will be more complicated than we can debug in the forums so if you need help with it please open a support case.

    If we can determine that this is a bug in Microsoft's product then you won't be charged for the incident, but at the moment I don't see anything which suggests that this is an OS bug rather than an app bug.

    --Rob

    Tuesday, September 16, 2014 10:50 PM
    Owner
  • Hi Rob,

      Thanks for your support. We will submit a case in: http://aka.ms/storesupport later, and will post the result if we get the solution.

    Friday, September 19, 2014 3:37 AM
  • The root cause is the row pitch of D3D11_MAPPED_SUBRESOURCE as shown in the following code:

    D3D11_MAPPED_SUBRESOURCE mappedResource; ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE)); // Disable GPU access to the vertex buffer data. m_d3dContext->Map(m_texture[i].Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);

    //Old code: memcpy(mappedResource.pData, m_tex_data[i], m_tex_data_len[i]); for (uint32 j = 0; j < m_tex_height[i]; j++) { memcpy((unsigned char*)(mappedResource.pData) + j*mappedResource.RowPitch, m_tex_data[i] + j*m_tex_data_linelen[i], m_tex_data_linelen[i]); } // Reenable GPU access to the vertex buffer data. m_d3dContext->Unmap(m_texture[i].Get(), 0);

    In some device, the row pitch is larger than the texture's width. That's why the bottom is out of the data. 

    • Marked as answer by Fallson Monday, November 17, 2014 6:48 AM
    Monday, November 17, 2014 6:47 AM