2015-04-12 9 views
0

Я пытаюсь прочитать некоторые данные из текстуры2d в вычислительном шейдере DirectX11, однако функция «Загрузить» объекта texture2D сохраняет значение 0, даже если объект текстуры заполнен тем же самым плавающий номер.Загрузка данных Texture2D в DirectX 11 Compute Shader

Это 160 * 120 texture2d с DXGI_FORMAT_R32G32B32A32_FLOAT. Следующий код, как я создал этот ресурс:

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; 
} 

И затем я пытаюсь запустить отправку с X = Y = 2 и Z = 1 вроде следующего:

void ComputeShaderReduction::ExecuteComputeShader(ID3D11DeviceContext* pd3dImmediateContext, UINT uInputNum, ID3D11UnorderedAccessView** ppUAVInputs, UINT X, UINT Y, UINT Z) { 
    pd3dImmediateContext->CSSetShader(m_pComputeShader, nullptr, 0); 

    pd3dImmediateContext->CSSetShaderResources(0, 1, &m_pInputTexSRV); // test code 

    pd3dImmediateContext->CSSetUnorderedAccessViews(0, uInputNum, ppUAVInputs, nullptr); 
    //pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, &m_pGPUOutUAVs, nullptr); 

    pd3dImmediateContext->UpdateSubresource(m_pConstBuf, 0, nullptr, &m_ConstBuf, 0, 0); 
    pd3dImmediateContext->CSSetConstantBuffers(0, 1, &m_pConstBuf); 
    pd3dImmediateContext->Dispatch(X, Y, Z); 

    pd3dImmediateContext->CSSetShader(nullptr, nullptr, 0); 

    ID3D11UnorderedAccessView* ppUAViewnullptr[1] = { nullptr }; 
    pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, ppUAViewnullptr, nullptr); 

    ID3D11ShaderResourceView* ppSRVnullptr[1] = { nullptr }; 
    pd3dImmediateContext->CSSetShaderResources(0, 1, ppSRVnullptr); 

    ID3D11Buffer* ppCBnullptr[1] = { nullptr }; 
    pd3dImmediateContext->CSSetConstantBuffers(0, 1, ppCBnullptr); 
} 

И я написал очень простой CS-шейдер, чтобы попытаться получить данные в texture2d и выйти из него. Таким образом, Compute Shader выглядит следующим образом:

#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(); 
} 

Я думаю, как я распечатать результат шейдера 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"); 
} 

Буфер, который связывается с БПЛА, имеет только 4 элемента. Итак, если все числа с плавающей запятой в моей текстуре2d равны 0.7, я должен иметь 4 0.7s, которые будут напечатаны в функции CopyToCPUBuffer вместо 0.0.

Кто-нибудь знает, что может быть неправильным в моем коде, или кто-нибудь может предоставить мне целый пример или учебник, в котором показано, как правильно читать данные DirectX 11 texture2d в вычислительных шейдерах?

Заранее спасибо.

ответ

0

Для начала необходимо следующее. Шаг ваших входных данных - это количество байтов на строку текстуры, а не на пиксель.

InitData.SysMemPitch = sizeof(float) * 4; 

Во-вторых:

float4 num = BufferIn.Load(uint3(groupIdx.x, groupIdx.y, 1)); 

Вы пытаетесь загрузить данные из 2-го MIP текстуры, он имеет только 1 уровень мип.

+0

спасибо. Я, хотя третий 1 в uintt3 означает уровень 1-го уровня. Эта проблема исправлена. – NULLPTR