C++ C++;简单图像处理示例中的AMP异常

C++ C++;简单图像处理示例中的AMP异常,c++,image-processing,visual-studio-2013,gpgpu,c++-amp,C++,Image Processing,Visual Studio 2013,Gpgpu,C++ Amp,我试图自学C++AMP,并想从我所在领域的一个非常简单的任务开始,那就是图像处理。我想将每像素24位的RGB图像(位图)转换为每像素8位的灰度图像。图像数据在无符号字符数组中可用(从位图::LockBits(…)等获取) 我知道C++AMP由于某些原因无法通过array或array\u view处理char或unsigned char数据,因此我尝试根据需要使用纹理。虽然VisualStudio 2013告诉我writeonly_texture_view已被弃用,但它解释了8bpp纹理是如何写入

我试图自学C++AMP,并想从我所在领域的一个非常简单的任务开始,那就是图像处理。我想将每像素24位的RGB图像(位图)转换为每像素8位的灰度图像。图像数据在
无符号字符
数组中可用(从
位图::LockBits(…)
等获取)

我知道C++AMP由于某些原因无法通过
array
array\u view
处理
char
unsigned char
数据,因此我尝试根据需要使用
纹理。虽然VisualStudio 2013告诉我
writeonly_texture_view
已被弃用,但它解释了8bpp纹理是如何写入的

我的代码引发运行时异常,表示“未能分派内核”。异常的完整文本很长:

ID3D11DeviceContext::Dispatch:计算着色器单元插槽0中的无序访问视图(UAV)的格式为(R8_UINT)。此格式不支持像UAV一样从着色器读取。如果着色器实际使用视图(例如,由于着色器代码分支而未跳过该视图),则此不匹配无效。不幸的是,不可能让所有硬件实现都支持将该格式作为UAV读取,尽管该格式可以作为UAV写入。如果着色器只需要执行读取,但不写入此资源,请考虑使用着色资源视图而不是UAV。 我目前使用的代码如下:

namespace gpu = concurrency;

gpu::extent<3> inputExtent(height, width, 3);
gpu::graphics::texture<unsigned int, 3> inputTexture(inputExtent, eight);
gpu::graphics::copy((void*)inputData24bpp, dataLength, inputTexture);
gpu::graphics::texture_view<unsigned int, 3> inputTexView(inputTexture);
gpu::graphics::texture<unsigned int, 2> outputTexture(width, height, eight);
gpu::graphics::writeonly_texture_view<unsigned int, 2> outputTexView(outputTexture);

gpu::parallel_for_each(outputTexture.extent,
    [inputTexView, outputTexView](gpu::index<2> pix) restrict(amp) {
    gpu::index<3> indR(pix[0], pix[1], 0);
    gpu::index<3> indG(pix[0], pix[1], 1);
    gpu::index<3> indB(pix[0], pix[1], 2);
    unsigned int sum = inputTexView[indR] + inputTexView[indG] + inputTexView[indB];
    outputTexView.set(pix, sum / 3);
});

gpu::graphics::copy(outputTexture, outputData8bpp);
namespace gpu=并发性;
gpu::区段输入区段(高度、宽度、3);
gpu::graphics::texture输入纹理(inputExtent,8);
gpu::graphics::copy((void*)inputData24bpp,dataLength,inputTexture);
gpu::graphics::texture\U视图InputExView(InputExture);
图形:纹理输出纹理(宽度、高度、八);
gpu::graphics::writeonly_纹理_视图OutputExView(outputTexture);
gpu::每个(outputTexture.extent)的并行_,
[InputExView,OutputExView](gpu::index pix)限制(amp){
gpu::索引indR(pix[0],pix[1],0);
gpu::索引indG(pix[0],pix[1],1);
gpu::索引indB(pix[0],pix[1],2);
无符号整数和=INPUTEXVIEW[indR]+INPUTEXVIEW[indG]+INPUTEXVIEW[indB];
OutputExView.set(像素,总和/3);
});
gpu::graphics::copy(outputTexture,outputData8bpp);

出现这种异常的原因是什么?我能做些什么来解决这个问题?

我自己也在学习C++Amp,遇到了一个与您非常相似的问题,但在我的情况下,我需要处理16位图像

很可能,这个问题可以通过使用纹理来解决,尽管由于缺乏经验,我无法在这方面帮助您

所以,我所做的基本上是基于位掩蔽

首先,欺骗编译器以便编译:

unsigned int* sourceData = reinterpret_cast<unsigned int*>(source);
unsigned int* destData   = reinterpret_cast<unsigned int*>(dest);
unsigned int*sourceData=reinterpret\u cast(源代码);
无符号int*destData=重新解释强制转换(dest);
接下来,阵列查看器必须查看所有数据。请注意,viwer真正需要的是您的数据是32位大小的。因此,您必须进行转换(因为16位被划分为2,使用4表示8位)

concurrency::array_view source((size+7)/2,sourceData));
并发性::数组_view dest((大小+7)/2,sourceData));
现在,您可以为每个块编写一个典型的

typedef concurrency::array_view<const unsigned int> OriginalImage;
typedef concurrency::array_view<unsigned int> ResultImage;

bool Filters::Filter_Invert()
{
    const int size = k_width*k_height;
    const int maxVal = GetMaxSize();

    OriginalImage& im_original = GetOriginal();
    ResultImage& im_result = GetResult();
    im_result.discard_data();

    parallel_for_each(
        concurrency::extent<2>(k_width, k_height), 
        [=](concurrency::index<2> idx) restrict(amp)
    {
        const int pos = GetPos(idx);
        const int val = read_int16(im_original, pos);

        write_int16(im_result, pos, maxVal - val);
    });

    return true;
}

int Filters::GetPos( const concurrency::index<2>& idx )  restrict(amp, cpu)
{
    return idx[0] * Filters::k_height + idx[1];
}
typedef并发::数组\视图原始图像;
typedef并发::数组_视图结果图像;
bool Filters::Filter_Invert()
{
常数int size=k_宽度*k_高度;
const int maxVal=GetMaxSize();
OriginalImage&im_original=GetOriginal();
ResultImage&im_result=GetResult();
im_结果。放弃_数据();
每个单元的平行单元(
并发::范围(k_宽度,k_高度),
[=](并发::索引idx)限制(amp)
{
const int pos=GetPos(idx);
const int val=读取int16(原件,位置);
写入int16(im结果、pos、maxVal-val);
});
返回true;
}
int Filters::GetPos(const并发::index和idx)restrict(amp,cpu)
{
返回idx[0]*过滤器::k_高度+idx[1];
}
这就是魔法:

template <typename T>
unsigned int read_int16(T& arr, int idx) restrict(amp, cpu)
{
    return (arr[idx >> 1] & (0xFFFF << ((idx & 0x7) << 4))) >> ((idx & 0x7) << 4);
}

template<typename T>
void write_int16(T& arr, int idx, unsigned int val) restrict(amp, cpu)
{
    atomic_fetch_xor(&arr[idx >> 1], arr[idx >> 1] & (0xFFFF << ((idx & 0x7) << 4)));
    atomic_fetch_xor(&arr[idx >> 1], (val & 0xFFFF) << ((idx & 0x7) << 4));
}
模板
无符号整数读取\整数16(T&arr,整数idx)限制(放大器,cpu)
{

返回(arr[idx>>1]&(0xFFFF((idx&0x7)>1),arr[idx>>1]&(0xFFFF 1],(val&0xFFFF)
unsigned int-eight=8
;与
one
相同。Glag听到这个问题实际上有一个答案。我想您提到的8bit版本在这里有描述:。我一直在阅读该文档,但有点泄气,因为所有这些技巧都是让它工作所必需的。不过,我也了解到,即使是OpenCL也有它与32bpp以外的图像存在问题,因此我仍然可以尝试一下。您好。我想您可能会喜欢此链接。我可以使它与纹理(使用visual 2013)一起工作。这将对您有更大的帮助:)
template <typename T>
unsigned int read_int16(T& arr, int idx) restrict(amp, cpu)
{
    return (arr[idx >> 1] & (0xFFFF << ((idx & 0x7) << 4))) >> ((idx & 0x7) << 4);
}

template<typename T>
void write_int16(T& arr, int idx, unsigned int val) restrict(amp, cpu)
{
    atomic_fetch_xor(&arr[idx >> 1], arr[idx >> 1] & (0xFFFF << ((idx & 0x7) << 4)));
    atomic_fetch_xor(&arr[idx >> 1], (val & 0xFFFF) << ((idx & 0x7) << 4));
}