Graphics 从HLSL计算着色器写入YUY2纹理

Graphics 从HLSL计算着色器写入YUY2纹理,graphics,directx-11,hlsl,Graphics,Directx 11,Hlsl,我想写一个着色器来分析和转换YUY2格式的视频数据。因为着色器不支持YUY2格式的纹理,所以我对着色器使用不同的视图。输入纹理是DXGI\u格式\u R8G8\u B8G8\u UNORM着色器资源视图,输出纹理是DXGI\u格式\u R32\u UINT无序访问视图,以允许写入 我遇到的问题是,写入输出纹理不会做任何事情。我已经将我的计算着色器简化为只向输出纹理写入一个常量值,但无论写入什么值,输出纹理都是纯绿色 这是我的设置代码: CComPtr<ID3D11DeviceContext

我想写一个着色器来分析和转换YUY2格式的视频数据。因为着色器不支持YUY2格式的纹理,所以我对着色器使用不同的视图。输入纹理是
DXGI\u格式\u R8G8\u B8G8\u UNORM
着色器资源视图,输出纹理是
DXGI\u格式\u R32\u UINT
无序访问视图,以允许写入

我遇到的问题是,写入输出纹理不会做任何事情。我已经将我的计算着色器简化为只向输出纹理写入一个常量值,但无论写入什么值,输出纹理都是纯绿色

这是我的设置代码:

CComPtr<ID3D11DeviceContext4> context;
{
    CComPtr<ID3D11DeviceContext> c;
    m_Device->GetImmediateContext(&c);
    ThrowHR(c.QueryInterface(&context));
}


// Create texture & view for input frame

CComPtr<ID3D11Texture2D> frameTexture;
CComPtr<ID3D11ShaderResourceView> frameView;
{
    D3D11_TEXTURE2D_DESC frameDesc = {};
    frameDesc.ArraySize = 1;
    frameDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    frameDesc.CPUAccessFlags = 0;
    frameDesc.Height = frame.Height;
    frameDesc.Width = frame.Width;
    frameDesc.MipLevels = 1;
    frameDesc.MiscFlags = 0;
    frameDesc.SampleDesc.Count = 1;
    frameDesc.SampleDesc.Quality = 0;
    frameDesc.Usage = D3D11_USAGE_IMMUTABLE;
    frameDesc.Format = DXGI_FORMAT_YUY2;

    D3D11_SUBRESOURCE_DATA frameInit = {};
    frameInit.pSysMem = frame.Data;
    frameInit.SysMemPitch = UINT(frame.Width * 2);
    frameInit.SysMemSlicePitch = (UINT)frame.Size;

    ThrowHR(m_Device->CreateTexture2D(&frameDesc, &frameInit, &frameTexture));

    D3D11_SHADER_RESOURCE_VIEW_DESC frameViewDesc = {};
    frameViewDesc.Format = DXGI_FORMAT_R8G8_B8G8_UNORM; // Analog to YUY2 which is supported by SRVs
    frameViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    frameViewDesc.Texture2D = { 0, 1 };

    ThrowHR(m_Device->CreateShaderResourceView(frameTexture, &frameViewDesc, &frameView));
}

// Create texture & view for output frame

CComPtr<ID3D11Texture2D> outputTexture;
CComPtr<ID3D11UnorderedAccessView> outputView;
{
    D3D11_TEXTURE2D_DESC outputDesc = {};
    outputDesc.ArraySize = 1;
    outputDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
    outputDesc.CPUAccessFlags = 0;
    outputDesc.Height = frame.Height;
    outputDesc.Width = frame.Width;
    outputDesc.MipLevels = 1;
    outputDesc.MiscFlags = 0;
    outputDesc.SampleDesc.Count = 1;
    outputDesc.SampleDesc.Quality = 0;
    outputDesc.Usage = D3D11_USAGE_DEFAULT;
    outputDesc.Format = DXGI_FORMAT_YUY2;

    ThrowHR(m_Device->CreateTexture2D(&outputDesc, nullptr, &outputTexture));

    D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
    uavDesc.Format = DXGI_FORMAT_R32_UINT; // Supported Read/Write format for UAV 
    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
    uavDesc.Texture2D = { 0 };

    ThrowHR(m_Device->CreateUnorderedAccessView(outputTexture, &uavDesc, &outputView));
}

// Bind shader resources
context->CSSetShader(m_ComputeShader, nullptr, 0);
ID3D11Buffer *const cbufs[] = { m_ParamsCBuffer };
context->CSSetConstantBuffers(0, ARRAYSIZE(cbufs), cbufs);
ID3D11UnorderedAccessView *const uavs[] = { m_StatsView, outputView };
context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr);
ID3D11ShaderResourceView *const srvs[] = { frameView };
context->CSSetShaderResources(0, ARRAYSIZE(srvs), srvs);

// Execute shader
context->Dispatch(frame.Width / 2, frame.Height, 1);

// Unbind shader
ZeroMemory((void*)cbufs, sizeof(cbufs));
context->CSSetConstantBuffers(0, ARRAYSIZE(cbufs), cbufs);
ZeroMemory((void*)uavs, sizeof(uavs));
context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr);
ZeroMemory((void*)srvs, sizeof(srvs));
context->CSSetShaderResources(0, ARRAYSIZE(srvs), srvs);
context->CSSetShader(nullptr, nullptr, 0);
CComPtr上下文;
{
c区;
m_设备->GetImmediateContext(&c);
ThrowHR(c.QueryInterface和context));
}
//为输入帧创建纹理和视图
CComPtr框架结构;
CComPtr框架视图;
{
D3D11_TEXTURE2D_DESC frameDesc={};
frameDesc.ArraySize=1;
frameDesc.BindFlags=D3D11\u BIND\u SHADER\u资源;
frameDesc.CPUAccessFlags=0;
frameDesc.Height=框架高度;
frameDesc.Width=frame.Width;
frameDesc.MipLevels=1;
frameDesc.miscsflags=0;
frameDesc.SampleDesc.Count=1;
frameDesc.SampleDesc.Quality=0;
frameDesc.Usage=D3D11\u Usage\u不可变;
frameDesc.Format=DXGI\u Format\u YUY2;
D3D11_子资源_数据帧init={};
frameInit.psysem=frame.Data;
frameInit.SysMemPitch=UINT(frame.Width*2);
frameInit.SysMemSlicePitch=(UINT)frame.Size;
ThrowHR(m_设备->CreateTexture2D(&frameDesc,&frameInit,&frameTexture));
D3D11_着色器_资源_视图_描述frameViewDesc={};
frameViewDesc.Format=DXGI\u Format\u R8G8\u B8G8\u UNORM;//模拟SRV支持的YUY2
frameViewDesc.ViewDimension=D3D11\u SRV\u DIMENSION\u TEXTURE2D;
frameViewDesc.Texture2D={0,1};
通过(m_设备->CreateShaderResourceView(frameTexture,&frameViewDesc,&frameView));
}
//为输出帧创建纹理和视图
CComPtr输出;
CComPtr outputView;
{
D3D11_TEXTURE2D_DESC outputDesc={};
outputDesc.ArraySize=1;
outputDesc.BindFlags=D3D11_BIND_UNORDERED_ACCESS|D3D11_BIND_SHADER_RESOURCE;
outputDesc.CPUAccessFlags=0;
outputDesc.Height=帧高度;
outputDesc.Width=帧宽度;
outputDesc.MipLevels=1;
outputDesc.MiscFlags=0;
outputDesc.SampleDesc.Count=1;
outputDesc.SampleDesc.Quality=0;
outputDesc.Usage=D3D11\u Usage\u默认值;
outputDesc.Format=DXGI\u Format\u YUY2;
ThrowHR(m_设备->CreateTexture2D(&outputDesc、nullptr和outputTexture));
D3D11_无序_访问_视图_描述uavDesc={};
uavDesc.Format=DXGI_Format_R32_UINT;//支持的UAV读/写格式
uavDesc.ViewDimension=D3D11\u UAV\u维度\u纹理2D;
uavDesc.Texture2D={0};
通过(m_设备->CreateUnorderedAccessView(outputTexture,&uavDesc,&outputView));
}
//绑定着色器资源
context->CSSetShader(m_ComputeShader,nullptr,0);
ID3D11Buffer*常量cbufs[]={m_ParamsCBuffer};
上下文->CSSetConstantBuffers(0,数组化(cbufs),cbufs);
ID3D11UnorderedAccessView*常量无人机[]={m_StatsView,outputView};
上下文->CSSetUnorderedAccessView(0,阵列化(UAV),无人机,空PTR);
ID3D11ShaderResourceView*常量srvs[]={frameView};
上下文->CSSetShaderResources(0,数组化(srvs),srvs);
//执行着色器
上下文->分派(frame.Width/2,frame.Height,1);
//取消绑定着色器
零内存((void*)cbufs,sizeof(cbufs));
上下文->CSSetConstantBuffers(0,数组化(cbufs),cbufs);
零内存((void*)无人机,sizeof(无人机));
上下文->CSSetUnorderedAccessView(0,阵列化(UAV),无人机,空PTR);
零内存((void*)srvs,sizeof(srvs));
上下文->CSSetShaderResources(0,数组化(srvs),srvs);
context->CSSetShader(nullptr,nullptr,0);
这是着色器:

// R8G8_B8G8_UNORM view into YUY2
Texture2D<unorm float4> Input : register(t0);

// R32_UINT view into YUY2
RWTexture2D<uint> Output : register(u1);

// Packs an X8Y8Z8W8_UNORM float4 into a uint
uint packFloat4(float4 unpacked)
{
    uint output;
    uint x = (uint)(clamp(unpacked.x, 0, 1) * 255) << 0;
    uint y = (uint)(clamp(unpacked.y, 0, 1) * 255) << 8;
    uint z = (uint)(clamp(unpacked.z, 0, 1) * 255) << 16;
    uint w = (uint)(clamp(unpacked.w, 0, 1) * 255) << 24;
    return x + y + z + w;
}

// Processes two adjacent pixels at a time due to YUY2 packing
[numthreads(1, 1, 1)]
void main(uint3 gid : SV_GroupID)
{
    unorm float4 outPixel = float4(0.5, 0.7, 0.3, 1.0);
    uint outPacked = packFloat4(outPixel);
    Output[gid.xy] = outPacked;
}
//R8G8\u B8G8\u将视图卸载到YUY2中
纹理2D输入:寄存器(t0);
//R32_u u进入YUY2的视图
RWD输出:寄存器(u1);
//将X8Y8Z8W8_UNORM浮动4打包到uint中
uint packFloat4(浮动4未包装)
{
单元输出;

uint x=(uint)(clamp(unpacket.x,0,1)*255)您是否尝试创建调试DX设备以查看是否存在任何错误?此外,您可能需要x | y | z | w而不是x+y+z+w。@VuVirt是的,我使用调试设备。您可能希望尝试使用Visual Studio中的图形调试工具。一旦捕获“帧”,您将能够运行着色器调试器,查看着色器是否实际执行写入操作,以及写入操作发生在何处。这可能是因为线程调度参数出错,因此着色器会不断更新同一像素而不是所有像素。您可能还想检查输出图像的二进制值s像素-如果它们恰好是一致的重复模式,则可以提供更多线索来正确诊断问题。