DirectX Shader Resource View в шейдерах

Я сейчас немного сбит с толку и просто хочу попросить вас всех помочь мне прояснить несколько идей.

В шейдере HLSL (например, вычислить шейдер) я могу объявить sb StructuredBuffer, верно? Должен ли я связать его с регистром, например: register (t0)?

Со стороны приложения я могу вызвать CSSetShaderResources (…). Первый аргумент (StartSlot), имеет ли он какое-либо отношение к маленькому числу за «t» в объявлении регистра?

Если я устанавливаю StartSlot как 0 (например), и я устанавливаю второй аргумент как 2. Говорю ли я API, что я буду связывать два представления ресурса шейдера, одно в регистре (t0) и другое в регистре (t1)?

Если я объявлю Texture2D tex [10]: register (t0), я могу установить его, вызвав CSSetShaderResources (0, 10, …). Означает ли это, что регистры (t0 ~ t9) все израсходованы?

Извините за такой «быстрый огонь» вопросов, но я просто запутался, и некоторые из моих тестов, похоже, дают противоречивые результаты …

Любая помощь будет оценена.

7

Решение

Итак, давайте ответим по порядку:

Да, конечно, вы можете объявить StructuredBuffer в вычислительном шейдере (фактически вы можете объявить его для любого типа шейдера).

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

CSSetShaderResources говорит связывать N ресурсов из начального слота, поэтому ваше описание использования 0,2 правильное.

Для массива текстур мне пришлось запустить PIX, чтобы проверить это, но это действительно так, как вы сказали.

Texture2D tex[10] : register(t0);

Будет означать, что каждому текстурному индексу будет выделен слот, начиная с указанного вами регистра, поэтому вам нужно вызвать CSSetShaderResources (0,10, srvarray), чтобы установить их.

4

Другие решения

Очень классное объяснение! Я тоже запутался, и после ваших вопросов и объяснений мне все ясно!

Но я нашел хороший пример для этого поста, которым хочу поделиться. Кажется, он запускает счетчик слота для каждого типа SetShaderResources. У всех шейдеров (VS, HS, DS, PS) свой счетчик. Вот код из примера NVidia:

Код Shaderclass:

pd3dDeviceContext->HSSetShaderResources( 0, 2, Resources );
pd3dDeviceContext->HSSetShaderResources( 8, 1, &m_pRegularWatertightTexSRV );
pd3dDeviceContext->HSSetShaderResources( 9, 1, &m_pQuadWatertightTexSRV );
pd3dDeviceContext->HSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->DSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 10, 1, &pNormalMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 3, 1, &pTexRenderRV11 );

Первый содержит два ресурса, поэтому следующий слот (строка 4) должен добавить 2 для начального слота (0 + 2 = 2). Каждый SetShaderResources должен начинаться с 0, но вы можете сделать это в разных местах вашего кода, поэтому здесь нет слота 0 для DS и PS. Иногда, если вы удалите строку, она все еще работает, но данные откладываются.
Теперь вы видите первые четыре в HLSL в строках t0, t1, t8 и t9, остальные регистры были связаны где-то еще.

Код HLSL:

Texture2D<float> GregoryStencil               : register( t0 );
Texture2D<uint>  Index                        : register( t1 );
Texture2D<float>  g_txHeight                  : register( t2 );
Texture2D<float> g_depth                      : register( t3 );
Texture2D g_FloorTexture                      : register( t4 );
Texture2D<float3>  regularPatchControlPoints  : register( t5 );
Texture2D<float3>  gregoryPatchControlPoints  : register( t6 );
Texture2D<float4>  g_floorHeight              : register( t7 );
Texture2D<float2>  RegularWatertightUVs       : register( t8 );
Texture2D<float2>  QuadWatertightUVs          : register( t9 );
Texture2D<float3>  g_txNormal                 : register( t10 );
2