2013-11-14 3 views
2

============ РЕДАКТИРОВАНИЕ: решение =====================Pixel Shader может получить доступ к Structured Buffer, а Vertex Shader не может - это спецификация DirectX?

Я, наконец, нашел проблему, и поскольку ответ может быть важен для новичков, которые изучают DirectX, я размещаю его здесь. (Я использую F # и SharpDX в качестве оболочки .NET для DirectX)

В моей программе ресурсы (буферы, представления и т. Д.) Изменяются только тогда, когда изменяется цепочка подкачки. Поэтому я включил все распределения ресурсов (IA, OM, VS, PS) в функцию switchTo2DLayout. switchTo2DLayout немедленно возвращается (без каких-либо действий), если цепочка подкачки была не изменено. Это контролируется флагом.

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

let renderPixels() = 
    switchTo2DLayout() 

    // this line was missing: 
    context.PixelShader.SetShaderResource(COUNT_COLOR_SLOT, countColorSRV_2D) 

    context.ClearRenderTargetView (renderTargetView2D, Color.White.ToColor4()) 
    context.Draw(4,0)             
    swapChain.Present(1, PresentFlags.None) 

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

Для рендеринга сетки я использую подобную установку (здесь без ошибки я уже упоминал), и снова эквивалентная линия отсутствует:

let draw3D() = 
    switchTo3DLayout() 

    // this line was missing: 
    context.VertexShader.SetShaderResource(TRIANGLE_SLOT, triangleSRV ) 

    context.ClearDepthStencilView(depthView3D, DepthStencilClearFlags.Depth, 1.0f, 0uy 
    context.ClearRenderTargetView(renderTargetView2D, Color4.Black)                
    context.Draw(triangleCount, 0) 
    swapChain.Present(1, PresentFlags.None)  

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

Несколько дней назад я разместил проблему [link:] How can I feed compute shader results into vertex shader w/o using a vertex buffer?, которая была, вероятно, слишком сложной для ответа. В то же время я урезанная установку в гораздо более простом случае:

struct PS_IN 
{ 
float4 pos : SV_POSITION; 
float4 col : COLOR; 
}; 

RWStructuredBuffer<float4> colorOutputTable : register (u5); 
StructuredBuffer<float4> output2 :    register (t5); 

Случай A: пиксельные шейдеры устанавливает цвет (работ)

// vertex shader A 

PS_IN VS_A (uint vid : SV_VertexID) 
{ 
    PS_IN output = (PS_IN)0; 
    if (vid == 0) output.pos = float4(-1, -1, 0, 1); 
    if (vid == 1) output.pos = float4(1, -1, 0, 1); 
    if (vid == 2) output.pos = float4(-1, 1, 0, 1);  
    if (vid == 3) output.pos = float4(1, 1, 0, 1);  

    return output; 
} 

// pixel shader A 

float4 PS_A (float4 input : SV_Position) : SV_Target 
{   
    uint2 pixel = uint2(input.x, input.y);  
    return output2[ pixel.y * width + pixel.x]; // PS accesses buffer (works) 

} 

Случай B: вершинные шейдеры устанавливает цвет (не работает)

// vertex shader B 

PS_IN VS_B (uint vid : SV_VertexID) 
{ 
    PS_IN output = (PS_IN)0; 
    if (vid == 0) output.pos = float4(-1, -1, 0, 1); 
    if (vid == 1) output.pos = float4(1, -1, 0, 1); 
    if (vid == 2) output.pos = float4(-1, 1, 0, 1);  
    if (vid == 3) output.pos = float4(1, 1, 0, 1);  
    output.col = output2[vid]; // VS accesses buffer (does not work) 
    return output; 
} 

// pixel shader B 

float4 PS_B (PS_IN input) : SV_Target 
{ 
    return input.col; 
} 

Очевидно пиксельного шейдера может доступ к «output2» буфер, а вершинные шейдеры не может (чтение всегда нулей).

Поиск в Интернете Я не мог найти объяснения этого поведения. В моем «реальном» приложении вычислительный шейдер вычисляет список треугольников и сохраняет его в RWStructuredBuffer, поэтому мне нужен доступ к этой таблице из вершинного шейдера (через слот с отображением).

Я думаю, что многие люди, которые работают с вычислительными шейдерами, могут наткнуться на эту проблему. Любая идея, как это решить? (В настоящее время я не могу использовать Level 11.1 или 11.2, мне нужно найти решение на основе 11.0)

ответ

1

Только что попробовал, ваш шейдер, похоже, работает (никогда не было проблем с StructuredBuffer, недоступным на любом этапе, уровень 11).

Образец только из мини-трубки SharpDX (только что заменил шейдерный код внутри и добавил буфер).

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

Поскольку я знаю, что у вас есть проблема с отладочным конвейером, еще один полезный способ увидеть, что что-то не так, это использовать запросы (в основном, PipelineStatistics и Occlusion в вашем случае).

Некоторое неправильное состояние может легко создать проблему, поэтому вы можете сразу увидеть, что-то не так, если посмотреть на количество пикселов, написанных/обработанных примитивов).

Shader код здесь:

struct PS_IN 
{ 
    float4 pos : SV_POSITION; 
    float4 col : COLOR; 
}; 

RWStructuredBuffer<float4> colorOutputTable : register (u5); 
StructuredBuffer<float4> output2 :    register (t5); 

PS_IN VS_B(uint vid : SV_VertexID) 
{ 
    PS_IN output = (PS_IN)0; 
    if (vid == 1) output.pos = float4(-1, -1, 0, 1); 
    if (vid == 0) output.pos = float4(1, -1, 0, 1); 
    if (vid == 3) output.pos = float4(-1, 1, 0, 1); 
    if (vid == 2) output.pos = float4(1, 1, 0, 1); 
    output.col = output2[vid]; // VS accesses buffer (does not work) 
    return output; 
} 

// pixel shader B 

float4 PS_B(PS_IN input) : SV_Target 
{ 
    return input.col; 
} 

Кодекс here (это довольно громоздкая, так что я положил его на Pastebin)

+0

Можете ли вы объяснить, почему реверсирования обмотка делает разницу в этом случае? Мои исходные данные - это TriangleList, в то время как четыре верта здесь образуют TriangleStrip - нужно ли мне также менять треугольники? –

+0

Поскольку мы не указываем состояние растеризатора, эквалайзер на лицевой панели включен по умолчанию (см. Http://msdn.microsoft.com/en-us/library/windows/desktop/ff476198(v=vs.85). aspx). Ваша обмотка будет отменена, так что ваши лица треугольника будут отбракованы и не попадут в пиксельный шейдер. – catflier

+0

Моя обмотка DID показывает синий прямоугольник, когда он заменил 'output.col = output2 [vid];' с 'output.col = float4 (0.5, 0.6, 0.8, 1);' Рядом - я всегда использовал по часовой стрелке обмотку, и это работал с моим списком треугольников, пока я использовал Vertex Buffer (копирование с процессора на графический процессор) ... –

Смежные вопросы