我刚开始学习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) 我想在计算着色器中将纹理数据用作一维数组.我读到最好的方法是将其作为缓冲区而不是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: ¤tVertPtr, length: kernelSourceTexture!.buffer!.length, options: []) …Run Code Online (Sandbox Code Playgroud) 我在 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
假设我有一个带有local_size = 8*8*8的OpenGL计算着色器.调用如何映射到nVidia GPU warp?同样的调用是否gl_LocalInvocationID.x会在同一个warp中?还是?还是z?我并不是指所有的调用,我只是指一般的聚合.
我问这个是因为在一个时刻进行了优化,并非所有的调用都有工作要做,所以我希望它们处于相同的变形中.
作为一个测试项目,我使用计算着色器(Vulkan)编写了Consway基本的生活游戏。基本上:
#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]达到类似的效果吗?
我想使用两个浮点数进行双重划分(看起来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++ 结构
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)
在计算过程中,我发现数组的所有元素(除了第一个元素)都有不正确的数据(很可能是移位的),我会犯什么错误?