DirectX 11 Compute Shader — запись не всех значений

Я пытаюсь провести некоторые эксперименты с фрактальным рендерингом с помощью вычислительных шейдеров DirectX11. Предоставленный пример работает на устройстве FeatureLevel_10.

Мой выходной буфер RwStructured имеет формат данных R32G32B32A32_FLOAT.

Проблема в том, что при записи в буфер кажется, что записывается только значение АЛЬФА ( w ), больше ничего.... Вот код шейдера:

struct BufType
{
    float4 value;
};

cbuffer ScreenConstants : register(b0)
{
  float2 ScreenDimensions;
  float2 Padding;
};

RWStructuredBuffer<BufType> BufferOut : register(u0);

[numthreads(1, 1, 1)]
void Main( uint3 DTid : SV_DispatchThreadID )
{
    uint index = DTid.y * ScreenDimensions.x + DTid.x;
    
    float minRe = -2.0f;
    float maxRe = 1.0f;
    float minIm = -1.2;
    float maxIm = minIm + ( maxRe - minRe ) * ScreenDimensions.y / ScreenDimensions.x;
    float reFactor = (maxRe - minRe ) / (ScreenDimensions.x - 1.0f);
    float imFactor = (maxIm - minIm ) / (ScreenDimensions.y - 1.0f);
    float cim = maxIm - DTid.y * imFactor;
    
    uint maxIterations = 30;
    
    float cre = minRe + DTid.x * reFactor;
    float zre = cre;
    float zim = cim;
    
    bool isInside = true;
    uint iterationsRun = 0;
    
    for( uint n = 0; n < maxIterations; ++n )
    {
        float zre2 = zre * zre;
        float zim2 = zim * zim;
        
        if ( zre2 + zim2 > 4.0f )
        {
            isInside = false;
            iterationsRun = n;
        }
        
        zim = 2 * zre * zim + cim;
        zre = zre2 - zim2 + cre;
    }
    
    if ( isInside )
    { 
        BufferOut[index].value = float4(1.0f,0.0f,0.0f,1.0f);
    }
}

Код на самом деле выдает в каком-то смысле правильный результат (2D-множество Мандельброта), но кажется, что каким-то образом затрагивается только альфа-значение и больше ничего не пишется, хотя пиксели внутри набора должны быть окрашены в красный цвет... (изображение черное и белый )

Кто-нибудь знает, что здесь происходит?


person Gluber    schedule 20.11.2009    source источник
comment
вы показываете только код HLSL, генерирующий буфер. А как насчет кода c, фактически отображающего буфер? Как узнать, что в вашем буфере нет красного компонента?   -  person Bahbar    schedule 21.11.2009
comment
Проверяли ли вы сгенерированный Asm Shader на возможные ошибки компилятора?   -  person Stringer    schedule 21.11.2009


Ответы (5)


После некоторого возни я нашел проблему. Я не нашел никакой документации от MS, в которой упоминается об этом, так что это также может быть проблема с конкретным драйвером Nvidia.

Очевидно, вам разрешено писать только ОДИН РАЗ за каждый вызов вычислительного шейдера в один и тот же элемент в RWSructuredBuffer. И вы также ДОЛЖНЫ написать ОДИН РАЗ.

Я изменил код, чтобы аккумулировать правильный цвет в локальную переменную, и теперь записываю его только один раз в конце шейдера.

Теперь все отлично работает таким образом.

person Gluber    schedule 21.11.2009
comment
В любом случае имеет смысл написать в BufferOut один раз (по соображениям производительности), так как RWStructuredBuffer должен находиться в видеопамяти. Локальные переменные находятся на чипе GPU, а также в TGSM. - person Stringer; 21.11.2009

Я не уверен, но разве это не должно быть для BufferOut decl:

RWStructuredBuffer<BufType> BufferOut : register(u0);

вместо :

RWStructuredBuffer BufferOut : register(u0);

Если вы используете только цель записи float4, почему бы не использовать просто:

RWBuffer<float4> BufferOut : register (u0);

Может быть, это может помочь.

person Stringer    schedule 21.11.2009
comment
Вы абсолютно правы, к сожалению, это была просто ошибка копирования с моей стороны.. исходное объявление, конечно, было RWStructedBuffer‹BufType› BufferOut : register(u0) - person Gluber; 22.11.2009

Поиграв сегодня снова, я снова столкнулся с той же проблемой. Следующий код выдал весь белый вывод:

[numthreads(1, 1, 1)]
void Main( uint3 dispatchId : SV_DispatchThreadID )
{
    float4 color = float4(1.0f,0.0f,0.0f,1.0f);
    WriteResult(dispatchId,color);
}

Метод WriteResult — это служебный метод из моей стандартной библиотеки hlsl.

Короче говоря. После того, как я обновил версию драйвера 192 до 195 (бета), проблема исчезла. Похоже, у драйверов остались определенные проблемы с поддержкой вычислительных шейдеров, так что будьте осторожны.

person Gluber    schedule 22.11.2009
comment
Я также написал свою собственную функцию WriteResult несколько недель назад. Он работал с рефрастом (уровень функций 5_0), не тестировался на HW, так как у меня нет доступа к графическому процессору класса DX11. Рефраст определенно стоит использовать для устранения подобных проблем. - person Stringer; 25.11.2009

Из того, что я видел, компьютерные шейдеры полезны только в том случае, если вам нужна более общая вычислительная модель, чем традиционный пиксельный шейдер, или если вы можете загрузить данные, а затем разделить их между потоками в быстрой общей памяти. Я почти уверен, что вы получите лучшую производительность с пиксельным шейдером для шейдера Мандельброта.

на моей установке (win7, 10 февраля dx sdk, gtx480) у моих вычислительных шейдеров время настройки составляет более 0,2–0,3 мс (связывание SRV и БПЛА, а затем вызов диспетчера()).

если вы выполняете реализацию PS, пожалуйста, напишите о своем опыте.

person hdb    schedule 15.06.2010

У меня нет прямого опыта работы с вычислительными шейдерами DX, но...

Почему вы устанавливаете альфа = 1.0?

IIRC, который делает пиксель прозрачным на 100%, поэтому ваши внутренние пиксели прозрачно-красные и отображаются в виде любого цвета, который был нарисован за ними. Когда альфа = 1,0, компоненты RGB никогда не используются.

person Die in Sente    schedule 20.11.2009