标签: compute-shader

numthreads(1,1,1)的计算着色器运行速度极慢

我刚开始学习DirectX编程,使用F#和SharpDX作为.NET包装器.作为测试用例,我渲染了Mandelbrot集.使用2个计算着色器完成计算.

第一个着色器计算每个像素的深度(函数"CalcMandel"),结果存储在RWStructuredBuffer中.这种计算需要大量的单次或双次乘法,但它在我的GPU(AMD 7790)上的速度非常快."CalcMandel"具有该属性

[numthreads(16, 16, 1)]
Run Code Online (Sandbox Code Playgroud)

并通过发送

context.Dispatch (imageWidth / 16, imageHeight / 16, 1)
Run Code Online (Sandbox Code Playgroud)

这里没有问题 - "核心"Mandelbrot集的1000 x 800像素图像以超过1000 fps的速度运行(在GPU上使用单精度).


第二个着色器几乎没有做任何事情:它计算先前计算的最小值,最大值和平均值(函数"CalcMinMax")."CalcMinMax"具有该属性

[numthreads(1, 1, 1)]
Run Code Online (Sandbox Code Playgroud)

并被称为通过

context.Dispatch (1,1,1)
Run Code Online (Sandbox Code Playgroud)

对于当时给定的图像大小,单个GPU线程必须遍历超过800.000个整数的缓冲区以计算最小值,最大值和平均值.我使用单个线程,因为我不知道如何以并行方式实现此计算.

问题:"CalcMinMax"非常慢:帧速率从1000 fps下降到5 fps!

我的问题:这里有什么问题?我使用了错误的设置/参数(numthreads)吗?如何加快min-max计算?

我的想法:我的第一个假设是访问RWBuffer可能会很慢 - 事实并非如此.当我用常量替换缓冲区访问时,帧速率没有增加.

我的GPU有appr.900个着色器核心并使用数千个线程来计算Mandelbrot集合,而"CalcMinMax"仅使用一个线程.然而,我仍然不明白为什么事情变得如此缓慢.

我很感激任何建议!

================================================

// HLSL CONTENT(省略Mandelbrot集计算):

cbuffer cbCSMandel : register( b0 )
{

double  a0, b0, da, db;
double  ja0, jb0;   
int max_iterations;
bool julia;     int  cycle;
int width;      int height;
double colorFactor;
int algoIndex;
int step;
};


struct statistics
{
  int   minDepth;
  int …
Run Code Online (Sandbox Code Playgroud)

directx hlsl compute-shader directcompute

2
推荐指数
1
解决办法
5706
查看次数

如何将纹理缓冲区数据传递给Shader with Metal?

我想在计算着色器中将纹理数据用作一维数组.我读到最好的方法是将其作为缓冲区而不是1D纹理传递.

我正在加载纹理:

let textureLoader = MTKTextureLoader(device: device)

do {
    if let image = UIImage(named: "testImage") {
        let options = [ MTKTextureLoaderOptionSRGB : NSNumber(value: false) ]
        try kernelSourceTexture = textureLoader.newTexture(with: image.cgImage!, options: options)
            kernelDestTexture = device.makeTexture(descriptor: kernelSourceTexture!.matchingDescriptor())
    } else {
        print("Failed to load texture image from main bundle")
    }
}
catch let error {
    print("Failed to create texture from image, error \(error)")
}
Run Code Online (Sandbox Code Playgroud)

我正在创建缓冲区(不确定这是否正确):

var textureBuffer: MTLBuffer! = nil
var currentVertPtr = kernelSourceTexture!.buffer!.contents()
textureBuffer = device.makeBuffer(bytes: &currentVertPtr, length: kernelSourceTexture!.buffer!.length, options: []) …
Run Code Online (Sandbox Code Playgroud)

shader compute-shader ios swift metal

2
推荐指数
1
解决办法
1252
查看次数

如何统一从计算着色器修改纹理像素?

我在 vuforia 中偶然发现了一个奇怪的问题。当我使用 CameraDevice.GetCameraImage(mypixelformat) 请求相机图像时,返回的图像既向侧面翻转又旋转了 180 度。因此,要获得正常图像,我必须先旋转图像,然后将其侧向翻转。我使用的方法只是迭代图像的像素并修改它们。这种方法的性能非常差。下面是代码:

    Texture2D image;

    CameraDevice cameraDevice = Vuforia.CameraDevice.Instance;
    Vuforia.Image vufImage = cameraDevice.GetCameraImage(pixelFormat);
    image = new Texture2D(vufImage.Width, vufImage.Height);
    vufImage.CopyToTexture(image);

    Color32[] colors = image.GetPixels32();
    System.Array.Reverse(colors, 0, colors.Length);  //rotate 180deg
    image.SetPixels32(colors);                       //apply rotation
    image = FlipTexture(image);                      //flip sideways






                 //***** THE FLIP TEXTURE METHOD *******//

private Texture2D FlipTexture(Texture2D original, bool upSideDown = false)
{

    Texture2D flipped = new Texture2D(original.width, original.height);

    int width  = original.width;
    int height = original.height;


    for (int col = 0; col < width; col++)
    {
        for …
Run Code Online (Sandbox Code Playgroud)

shader image-processing texture2d unity-game-engine compute-shader

1
推荐指数
1
解决办法
6180
查看次数

OpenGL计算着色器映射到nVidia warp

假设我有一个带有local_size = 8*8*8的OpenGL计算着色器.调用如何映射到nVidia GPU warp?同样的调用是否gl_LocalInvocationID.x会在同一个warp中?还是?还是z?我并不是指所有的调用,我只是指一般的聚合.

我问这个是因为在一个时刻进行了优化,并非所有的调用都有工作要做,所以我希望它们处于相同的变形中.

opengl compute-shader gpu-warp

1
推荐指数
1
解决办法
156
查看次数

存储缓冲区-[y] [x]使用的int数组比[x] [y]快3倍?

作为一个测试项目,我使用计算着色器(Vulkan)编写了Consway基本的生活游戏。基本上:

  • “板”存储在存储缓冲区内部的int数组中。
#define WIDTH 800
#define HEIGHT 600
#define WORKGROUP_SIZE 32

layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;

layout(binding = 0) readonly buffer buf1 {
   int data[WIDTH][HEIGHT];
} previousBoard;

layout(binding = 1) buffer buf2 {
   int data[WIDTH][HEIGHT];
} nextBoard;
Run Code Online (Sandbox Code Playgroud)
  • 然后,计算着色器每帧更新一次(每个像素调用一次)。

我随机进行了一些更改,并且我注意到,如果使用data[y][x](from gl_GlobalInvocationID.xy)访问阵列,我的程序比使用(至少在我的计算机(intel UHD 620)上)进行的普通访问要快3倍。data[x][y] [x] [y]为500 fps,而[y] [x]为1700 fps)。

我花了几个小时来隔离这种行为,以确保这不是副作用。我什至反汇编了Spir-v代码,但发现没有什么有趣的东西可以帮助我理解。这里是着色器的差异(带有[x] [y]和[y] [x]):https : //www.diffchecker.com/vFlkEsQp

我远远不了解这里会发生什么。是否有任何原因可以解释这种性能差异?

我对使用[y] [x]不太满意(或者应该?),那么我还有另一种方法可以使[x] [y]达到类似的效果吗?

compute-shader vulkan

1
推荐指数
1
解决办法
88
查看次数

使用两个花车进行双重划分?

我想使用两个浮点数进行双重划分(看起来Direct Compute不支持双重划分).

那可能吗?

这是我到目前为止所尝试的(c#代码,以后应该是HLSL):

int count = 7;
double value = 0.0073812398871474;
float f1 = (float)value;
float f2 = (float)((value - f1));
float r1 = f1 / count;
float r2 = f2 / count;
double result = (double)r1 + (double)r2;
Run Code Online (Sandbox Code Playgroud)

0,00105446285765182(结果)

0,00105446284102106(正确的结果)

它与f1中的舍入有关.如果值是:

 double value = 0.0073812344471474;
Run Code Online (Sandbox Code Playgroud)

然后结果是正确的.

c# floating-point directx-11 compute-shader

0
推荐指数
1
解决办法
3238
查看次数

计算着色器中的数组值无效?

我使用一个缓冲区来传递我的 C++ 结构

struct Node {
    Node(int size, glm::ivec3 position);

    bool isEmpty();
    int getSubIndex(const glm::ivec3& vec);
    void divide(std::vector<Node> &nodes);
    void setColor(glm::vec4 color);
    int getSubNodeIndex(const glm::ivec3& vec);
    int getSubNodeIndex(int subIndex);

    glm::ivec4 position;
    glm::vec4 color;
    int halfSize;
    int sub;
    int leaf;
};
Run Code Online (Sandbox Code Playgroud)

在着色器中看起来像这样

struct Node {
    vec4 position;
    vec4 color;
    int data[3];
};

layout(std430, binding=4) readonly buffer Octree_data {
    Node nodes[];
};
Run Code Online (Sandbox Code Playgroud)

在计算过程中,我发现数组的所有元素(除了第一个元素)都有不正确的数据(很可能是移位的),我会犯什么错误?

c++ opengl glsl compute-shader glm-math

0
推荐指数
1
解决办法
167
查看次数