Извлечение вершин из резервного буфера (HLSL) на XNA - PullRequest
3 голосов
/ 15 ноября 2009

Привет и извините за неясное название:} Я постараюсь объяснить, как могу.

Прежде всего, я новичок в HLSL, но я понимаю о конвейере и прочем из сказочного мира. То, что я пытаюсь сделать, это использовать графический процессор для общих вычислений (GPGPU).

Что я не знаю: как я могу прочитать * вершины (которые были преобразованы с помощью вершинных шейдеров) обратно в мое приложение xna? Я читал что-то об использовании памяти текстур GPU, но я не могу найти ничего твердого ...

Заранее спасибо за любую информацию / чаевые! : -)

* не уверен, если это возможно, из-за растеризатора и пиксельного шейдера (если есть), я имею в виду, в конце концов, все дело в пикселях, верно?

Ответы [ 2 ]

2 голосов
/ 16 ноября 2009

Насколько я знаю, это обычно невозможно.

Что именно вы пытаетесь сделать? Возможно, есть другое решение

РЕДАКТИРОВАТЬ :: С учетом комментария. Если все, что вам нужно, это общие векторные вычисления на GPU, попробуйте выполнить их в пиксельном шейдере, а не в вершинном шейдере.

Так, например, скажем, вы хотите скрестить два вектора, сначала нам нужно записать данные в текстуру

//Data must be in the 0-1 range before writing into the texture, so you'll need to scale everything appropriately
Vector4 a = new Vector4(1, 0, 1, 1);
Vector4 b = new Vector4(0, 1, 0, 0);

Texture2D dataTexture = new Texture2D(device, 2, 1);
dataTexture.SetData<Vector4>(new Vector4[] { a, b });

Итак, теперь у нас есть текстура 2 * 1 с данными, визуализируем текстуру, просто используя spritebatch и эффект:

Effect gpgpu;
gpgpu.Begin();
gpgpu.CurrentTechnique = gpgpu.Techniques["DotProduct"];
gpgpu.CurrentTechnique.Begin();
spriteBatch.Begin();
gpgpu.CurrentTechnique.Passes[0].Begin();
spriteBatch.Draw(dataTexture, new Rectangle(0,0,2,1), Color.White);
spriteBatch.end();
gpgpu.CurrentTechnique.Passes[0].End();
gpgpu.CurrentTechnique.End();

Все, что нам сейчас нужно, это эффект gpgpu, который я показал выше. Это просто стандартный шейдер постобработки, который выглядит примерно так:

sampler2D DataSampler = sampler_state
{
    MinFilter = Point;
    MagFilter = Point;
    MipFilter = Point;
    AddressU = Clamp;
    AddressV = Clamp;
};

float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 A = tex2D(s, texCoord);
    float4 B = tex2D(s, texCoord + float2(0.5, 0); //0.5 is the size of 1 pixel, 1 / textureWidth
    float d = dot(a, b)
    return float4(d, 0, 0, 0);
}

technique DotProduct
{
    pass Pass1
    {
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}

Это запишет точечное произведение A и B в первый пиксель и точечное произведение B и B во второй пиксель. Затем вы можете прочитать эти ответы обратно (игнорируя ненужные)

Vector4[] v = new Vector4[2];
dataTexture.GetData(v);
float dotOfAandB = v[0];
float dotOfBandB = v[1];

тада! Существует множество проблем, связанных с попытками сделать это в большем масштабе, прокомментируйте здесь, и я постараюсь помочь вам с любым, с чем вы столкнетесь:

0 голосов
/ 19 апреля 2011

Если вы включите « Stream Output Stage », выходные данные вашего вершинного шейдера будут сохранены в буфере памяти. Позже эти значения могут быть считаны с графического или центрального процессора по желанию.

...