Вычислительный шейдер не пишет в буфер? - PullRequest
0 голосов
/ 05 июня 2018

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

Renderdoc говорит, что у него нет данных, но есть значения в InstancesOut (см. Рисунок внизу)

Это мой вычислительный шейдер:

#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

struct Indirect
{
    uint indexCount;
    uint instanceCount;
    uint firstIndex;
    uint vertexOffset;
    uint firstInstance;
};
struct Instance
{
    vec4 position;
};

layout (binding = 0, std430) buffer IndirectDraws
{
    Indirect indirects[];
};

layout (binding = 1) uniform UBO 
{
    vec4 frustum[6];
} ubo;

layout (binding = 2, std140) readonly buffer Instances
{
    Instance instances[];
};

layout (binding = 3, std140) writeonly buffer InstancesOut
{
    Instance instancesOut[];
};
layout (binding = 4) buffer Counter
{
    uint counter;
};

bool checkFrustrum(vec4 position, float radius)
{
    for(uint i = 0; i < 6; i++)
        if(dot(position, ubo.frustum[i]) + radius < 0.0)
            return false;
    return true;
}
layout (local_size_x = 1) in;
void main()
{
    uint i = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x;

    uint instanceCount = 0;
    if(i == 0)
        atomicExchange(counter, 0);


    for(uint x = 0; x < indirects[i].instanceCount; x++)
    {
        vec4 position = instances[indirects[i].firstInstance + x].position;
        //if(checkFrustrum(position, 1.0))
        //{
            instancesOut[atomicAdd(counter, 1)].position = position;
            instanceCount++; 
        //}
    }
    //indirects[i].instanceCount = instanceCount;
    indirects[i].instanceCount = i; // testing
}

Изображение буферов в RenderDoc

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 25 июля 2018

Похоже, вы неправильно понимаете, как работают синхронизация и рабочие группы.

Внутри вычислительного шейдера атомика позволит вам синхронизироваться между рабочими группами.Тем не менее, нет гарантии для порядка выполнения рабочих групп, поэтому atomicExchange (counter, 0);не гарантируется, что произойдут другие рабочие группы.Ошибка № 1?

Размер рабочей группы 1 - это огромная трата ресурсов, особенно если вы тратите средства на синхронизацию между рабочими группами.Синхронизация внутри рабочей группы всегда будет самой быстрой, и это позволит вам фактически использовать ресурсы GPU (большинство графических процессоров организованы в модули, содержащие процессоры SIMD, которые могут обрабатывать выполнение только в одной рабочей группе за раз. Если вы используете только рабочие группы размера 131/32 или 63/64 из этих процессоров бездействуют. {Предостережение: большинство этих же процессоров могут одновременно хранить несколько рабочих групп в памяти, но выполнение происходит только на одной в любой момент}).Кроме того, внутри рабочей группы вы можете синхронизировать выполнение с барьерами, обеспечивая порядок операций.Ошибка №2?

atomicCounterIncrement, вероятно, является лучшей инструкцией, если вы добавляете только один из них.

В каком конкретном приложении ответ для экземпляров неверный?на самом деле мне кажется правильным, что каждый ввод заканчивался в выводе без гарантированного порядка (потому что вы не гарантированно выполняете рабочие группы в определенном порядке, то есть так работает параллельное выполнение).Если вы хотите, чтобы они были в порядке, рассчитайте их по идентификаторам вызовов?

Что касается того, почему renderDoc не показывает вам значение в счетчике, я не знаю, оно должно иметь значение, если оно сопоставлено правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...