• Advertisement
Sign in to follow this  

Scale Texture2D DirectX11

Recommended Posts

I'm using Desktop Duplication API. After I call AcquireNextFrame I get a Texture2D from the API in Full HD resolution. I would like to resize it and make it smaller (like 1280x720 for example) before drawing it. Here is my code :

if (texture2D != NULL)
{
    D3D11_TEXTURE2D_DESC description;
    texture2D->GetDesc(&description);
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    description.Usage = D3D11_USAGE_STAGING;
    description.MiscFlags = 0;
    description.Width = 1280;
    description.Height = 720;

    ID3D11Texture2D *texTemp = NULL;
    HRESULT hr = m_Device->CreateTexture2D(&description, NULL, &texTemp);
    if (FAILED(hr))
    {
        if (texTemp)
        {
            texTemp->Release();
            texTemp = NULL;
        }
        return NULL;
    }
    m_DeviceContext->CopyResource(texTemp, texture2D);

    D3D11_MAPPED_SUBRESOURCE mapped;
    hr = m_DeviceContext->Map(texTemp, 0, D3D11_MAP_READ, 0, &mapped);
    if (FAILED(hr))
    {
        texTemp->Release();
        texTemp = NULL;
        return NULL;
    }
    unsigned char *source = static_cast<unsigned char*>(mapped.pData);
    //here the source has no values. If I remove description.Width = 1280;
    //description.Height = 720; I get values
}

Can someone help ? Thanks

I'm using Desktop Duplication API. After I call AcquireNextFrame I get a Texture2D from the API in Full HD resolution. I would like to resize it and make it smaller (like 1280x720 for example) before drawing it. Here is my code :

if (texture2D != NULL)
{
    D3D11_TEXTURE2D_DESC description;
    texture2D->GetDesc(&description);
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    description.Usage = D3D11_USAGE_STAGING;
    description.MiscFlags = 0;
    description.Width = 1280;
    description.Height = 720;

    ID3D11Texture2D *texTemp = NULL;
    HRESULT hr = m_Device->CreateTexture2D(&description, NULL, &texTemp);
    if (FAILED(hr))
    {
        if (texTemp)
        {
            texTemp->Release();
            texTemp = NULL;
        }
        return NULL;
    }
    m_DeviceContext->CopyResource(texTemp, texture2D);

    D3D11_MAPPED_SUBRESOURCE mapped;
    hr = m_DeviceContext->Map(texTemp, 0, D3D11_MAP_READ, 0, &mapped);
    if (FAILED(hr))
    {
        texTemp->Release();
        texTemp = NULL;
        return NULL;
    }
    unsigned char *source = static_cast<unsigned char*>(mapped.pData);
    //here the source has no values. If I remove description.Width = 1280;
    //description.Height = 720; I get values
}

Can someone help ? Thanks

Share this post


Link to post
Share on other sites
Advertisement

You can create a SRV for the source image from your Desktop API to bind the texture for a shader.

Then use your smaller target texture as rendertarget and draw a fullscreen quad on it. You don't even need a index or vertexbuffer when using this vertexshader

struct Output
{
	float4 position_cs : SV_POSITION;
	float2 texcoord : TEXCOORD;
};

Output main(uint id: SV_VertexID)
{
	Output output;

	output.texcoord = float2((id << 1) & 2, id & 2);
	output.position_cs = float4(output.texcoord * float2(2, -2) + float2(-1, 1), 0, 1);

	return output;
}

You only have to use Draw(3,0);

The pixelshader is also a no brainer, just sample the sourcetexture and you are done.

Share this post


Link to post
Share on other sites

Hello Auskennfuchs

I was mistaken in what I wanted to do.

​I don't want to draw it on a DirectX Surface. I would like to get the buffer of pixels smaller directly from DirectX.

As you can see in my code I'm copying the Texture2D obtained from AcquireNextFrame to a staging temporary texture to get the pixel buffer data.

I would like to scale the pixel buffer data because I need to send a frame over network and I would like to decrease the resolution.

Thank you very much

Share this post


Link to post
Share on other sites

I'm not sure if you can achieve it by just copying the data to a texture with a smaller dimension. I guess your current result looks something like this:

original image
aaaaaa
bbbbbb
cccccc

smaller image
aaaa
aabb
bbbb

last line is completely missing

So with my solution the scaling is done in the pixelshader, like if you look on a quad from a further distance in 3D. After drawing on the smaller destination texture you can use the Map function to read the smaller image.

As an alternative you can use GDI+ functions to scale a bitmap and don't have to deal with DirectX.

Share this post


Link to post
Share on other sites

If you need it in say, half size it's quite easy:

1) Map your source, and memcpy the data to a buffer you've allocated, and unmap

2) loop through the buffer with a xy stepsize of 2, copying data into a half-sized buffer

 

Edit: Will have to say I would definitely go for the shader approach, much faster ^^

Edited by vinterberg

Share this post


Link to post
Share on other sites

Hello Auskennfuchs

Sorry for the late response...

Thank you for your help. But I think I need more explanation how to use correctly the pixel shader you gave me from my code I show at top.

How to pass the texture2D acquired to the shader with a custom resolution and then grab it again and get the buffer ?

I created a PixelShader.hlsl where I put this code :

struct Output
{
	float4 position_cs : SV_POSITION;
	float2 texcoord : TEXCOORD;
};

[numthreads(1, 1, 1)]
Output main(uint id: SV_VertexID)
{
	Output output;

	output.texcoord = float2((id << 1) & 2, id & 2);
	output.position_cs = float4(output.texcoord * float2(2, -2) + float2(-1, 1), 0, 1);

	return output;
}

I got an error on compilation : Error X3507 'main': Compute shaders can't return values, outputs must be written in writable resources (UAVs)

Thank you!

Edited by DevAndroid

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement