在DirectX 11计算着色器中加载纹理2D数据
我正在尝试从DirectX11计算着色器中的texture2d读取一些数据,但是,texture2d对象的“加载”函数始终返回0,即使该纹理对象填充了相同的浮点数 这是一个160*120的纹理2D,带有DXGI_格式_r32g32b32a2a32_浮点。以下代码是我如何创建此资源的:在DirectX 11计算着色器中加载纹理2D数据,directx,directx-11,texture2d,compute-shader,Directx,Directx 11,Texture2d,Compute Shader,我正在尝试从DirectX11计算着色器中的texture2d读取一些数据,但是,texture2d对象的“加载”函数始终返回0,即使该纹理对象填充了相同的浮点数 这是一个160*120的纹理2D,带有DXGI_格式_r32g32b32a2a32_浮点。以下代码是我如何创建此资源的: HRESULT TestResources(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pImmediateContext) { float *test =
HRESULT TestResources(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pImmediateContext) {
float *test = new float[4 * 80 * 60 * 4]; // 80 * 60, 4 channels, 1 big texture contains 4 80 * 60 subimage
for (int i = 0; i < 4 * 80 * 60 * 4; i++) test[i] = 0.7f;
HRESULT hr = S_OK;
D3D11_TEXTURE2D_DESC RTtextureDesc;
ZeroMemory(&RTtextureDesc, sizeof(D3D11_TEXTURE2D_DESC));
RTtextureDesc.Width = 160;
RTtextureDesc.Height = 120;
RTtextureDesc.MipLevels = 1;
RTtextureDesc.ArraySize = 1;
RTtextureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
RTtextureDesc.SampleDesc.Count = 1;
RTtextureDesc.SampleDesc.Quality = 0;
RTtextureDesc.Usage = D3D11_USAGE_DYNAMIC;
RTtextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
RTtextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
RTtextureDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = test;
InitData.SysMemPitch = sizeof(float) * 4;
V_RETURN(pd3dDevice->CreateTexture2D(&RTtextureDesc, &InitData, &m_pInputTex2Ds));
//V_RETURN(pd3dDevice->CreateTexture2D(&RTtextureDesc, NULL, &m_pInputTex2Ds));
D3D11_SHADER_RESOURCE_VIEW_DESC SRViewDesc;
ZeroMemory(&SRViewDesc, sizeof(SRViewDesc));
SRViewDesc.Format = RTtextureDesc.Format;
SRViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRViewDesc.Texture2D.MostDetailedMip = 0;
SRViewDesc.Texture2D.MipLevels = 1;
V_RETURN(pd3dDevice->CreateShaderResourceView(m_pInputTex2Ds, &SRViewDesc, &m_pInputTexSRV));
delete[] test;
return hr;
}
我编写了一个非常简单的CS着色器,尝试获取纹理2D中的数据并将其输出。因此,计算着色器如下所示:
#define subimg_dim_x 80
#define subimg_dim_y 60
Texture2D<float4> BufferIn : register(t0);
StructuredBuffer<float> Test: register(t1);
RWStructuredBuffer<float> BufferOut : register(u0);
groupshared float sdata[subimg_dim_x];
[numthreads(subimg_dim_x, 1, 1)]
void CSMain(uint3 DTid : SV_DispatchThreadID,
uint3 threadIdx : SV_GroupThreadID,
uint3 groupIdx : SV_GroupID) {
sdata[threadIdx.x] = 0.0;
GroupMemoryBarrierWithGroupSync();
if (threadIdx.x == 0) {
float4 num = BufferIn.Load(uint3(groupIdx.x, groupIdx.y, 1));
//BufferOut[groupIdx.y * 2 + groupIdx.x] = 2.0; //This one gives me 2.0 as output in the console
BufferOut[groupIdx.y * 2 + groupIdx.x] = num.x; //This one keeps giving me 0.0 and in the texture, r = g = b = a = 0.7 or x = y = z = w = 0.7, so it suppose to print 0.7 in the console.
}
GroupMemoryBarrierWithGroupSync();
}
#定义子项尺寸×80
#定义子项尺寸y 60
纹理2d缓冲区:寄存器(t0);
StructuredBuffer测试:寄存器(t1);
RWStructuredBuffer缓冲输出:寄存器(u0);
组共享浮点数据[subimg_dim_x];
[numthreads(subimg_dim_x,1,1)]
无效CSMain(uint3 DTid:SV_DispatchThreadID,
uint3 threadIdx:SV_GroupThreadID,
uint3 groupIdx:SV_GroupID){
sdata[threadIdx.x]=0.0;
GroupMemoryBarrierWithGroupSync();
if(threadIdx.x==0){
float4 num=BufferIn.Load(uint3(groupIdx.x,groupIdx.y,1));
//BufferOut[groupIdx.y*2+groupIdx.x]=2.0;//这一个给我2.0作为控制台中的输出
BufferOut[groupIdx.y*2+groupIdx.x]=num.x;//这个一直给我0.0,在纹理中,r=g=b=a=0.7或x=y=z=w=0.7,所以它假设在控制台中打印0.7。
}
GroupMemoryBarrierWithGroupSync();
}
我认为我在CPU端打印CS着色器结果的方式是正确的
void ComputeShaderReduction::CopyToCPUBuffer(ID3D11Device* pdevice, ID3D11DeviceContext* pd3dImmediateContext, ID3D11Buffer* pGPUOutBufs) {
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
pGPUOutBufs->GetDesc(&desc);
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.MiscFlags = 0;
if (!m_pCPUOutBufs && SUCCEEDED(pdevice->CreateBuffer(&desc, nullptr, &m_pCPUOutBufs))) {
pd3dImmediateContext->CopyResource(m_pCPUOutBufs, pGPUOutBufs);
}
else pd3dImmediateContext->CopyResource(m_pCPUOutBufs, pGPUOutBufs);
D3D11_MAPPED_SUBRESOURCE MappedResource;
float *p;
pd3dImmediateContext->Map(m_pCPUOutBufs, 0, D3D11_MAP_READ, 0, &MappedResource);
p = (float*)MappedResource.pData;
for (int i = 0; i < 4; i++) printf("%d %f\n", i, p[i]);
pd3dImmediateContext->Unmap(m_pCPUOutBufs, 0);
printf("\n");
}
void ComputeShaderReduction::CopyToCPUBuffer(ID3D11Device*pdevice,ID3D11DeviceContext*pd3dimediatecontext,ID3D11Buffer*pgpufs){
D3D11_BUFFER_DESC DESC;
零内存(&desc,sizeof(desc));
pgpufs->GetDesc(&desc);
desc.CPUAccessFlags=D3D11\u CPU\u访问\u读取;
描述用途=D3D11_用途_分期;
desc.BindFlags=0;
desc.miscsflags=0;
如果(!m_pcpuexputfs&&successed(pdevice->CreateBuffer(&desc,nullptr,&m_pcpuexputfs))){
pd3dImmediateContext->copyrource(m_pcpuburafs,pgpuburafs);
}
else pd3dImmediateContext->CopyResource(m_pcpuburafs,pgpuburafs);
D3D11_映射_子资源MappedResource;
浮动*p;
pd3dImmediateContext->Map(m_pcpuexputfs,0,D3D11_Map_READ,0,&MappedResource);
p=(float*)MappedResource.pData;
对于(inti=0;i<4;i++)printf(“%d%f\n”,i,p[i]);
pd3dImmediateContext->取消映射(m_pcpuf,0);
printf(“\n”);
}
绑定到UAV的缓冲区只有4个元素。因此,如果我的texture2d中的所有浮点数都是0.7,我应该在CopyToCPUBuffer函数中打印4个0.7,而不是0.0
有人知道我的代码中可能有什么错误吗?或者有人能给我提供一个完整的示例或教程,说明如何在计算着色器中正确读取DirectX 11 texture2d的数据
提前感谢。以下是错误的开始。输入数据的间距是纹理每行的字节数,而不是每像素
InitData.SysMemPitch = sizeof(float) * 4;
第二:
float4 num = BufferIn.Load(uint3(groupIdx.x, groupIdx.y, 1));
您正在尝试从纹理的第二个mip加载数据,它只有一个mip级别。非常感谢。我认为UINT3中的第三个1表示第一个mip级别。这个问题现在已经解决了。
float4 num = BufferIn.Load(uint3(groupIdx.x, groupIdx.y, 1));