일부 Vulkan 애플리케이션의 특성상 잘못된 메모리 접근을 방지할 수 없는 쉐이더 코드를 실행해야 하는 경우가 있습니다. 이러한 애플리케이션에는 견고성이 필요합니다.
Note
|
중요
견고성을 설정하면 런타임 성능 비용이 발생할 수 있습니다. 애플리케이션 작성자는 견고성 활성화가 미치는 영향을 신중하게 고려해야 합니다. |
모든 Vulkan 구현은 robustBufferAccess
기능을 지원해야 합니다. 사양서는 어떤 것이 범위를 벗어난 것으로 간주되는지 그리고 어떻게 처리해야 하는지를 설명합니다.구현에는 robustBufferAccess
에 대해 어느 정도의 유연성이 부여됩니다. 예를 들어 w
값이 범위를 벗어난 vec4(x,y,z,w)
에 접근하는 경우, x
, y
, z
도 범위를 벗어난 것으로 간주할지 여부를 구현에서 결정할 수 있도록 사양에서 허용하고 있기 때문입니다.
robustBufferAccess
기능은 이미지가 아닌 버퍼만 다루기 때문에 몇 가지 제한이 있습니다. 또한 접근 중인 버퍼의 데이터를 수정하기 위해 범위를 벗어난 쓰기나 아토믹을 허용해버립니다. 더 강력한 형태의 견고성을 원하는 애플리케이션의 경우, VK_EXT_robustness2가 있습니다.
이미지가 범위를 벗어난 경우, 코어 Vulkan에서는 스토어나 아토믹이 접근하려는 메모리에 영향을 주지 않는 것이 보장되어 있습니다.
다음은 `robustBufferAccess`를 사용하는 예제입니다. (온라인 체험)
#version 450
layout(set = 0, binding = 0) buffer SSBO {
// Vk버퍼의 크기는 64바이트에 불과합니다.
// [0:63]부터의 인덱싱이 유효하고 나머지는 OOB입니다.
uint data[128];
};
void main() {
// 런타임에 OOB가 됩니다.
// robustBufferAccess와 함께 버려집니다.
data[96] = 0;
// robustBufferAccess를 사용하면 0을 반환합니다.
uint x = data[127];
}
VK_EXT_image_robustness 의 robustImageAccess 기능은 이미지 뷰 크기에 대한 범위를 넘는 접근을 검사할 수 있습니다. 이미지 범위에 접근이 있는 경우 (0, 0, 0, 0)
또는 (0, 0, 0, 1)
를 반환합니다.
robustImageAccess
기능은 유효하지 않은 LOD에 접근할 때 반환되는 값에 대한 보장을 제공하지 않으며, 아직 정의되지 않은 동작입니다.
D3D12와 같은 다른 API에서 포팅된 애플리케이션과 같은 일부 애플리케이션은 robustBufferAccess
와 robustImageAccess
가 제공하는 것보다 더 엄격한 보장을 필요로 합니다. 다음 섹션에서 설명하는 3 가지 새로운 견고성 기능을 공개하여 VK_EXT_robustness2 확장 기능을 추가합니다. 일부 구현의 경우 이러한 추가 보장은 성능 저하를 초래할 수 있습니다. 추가 견고성이 필요하지 않은 애플리케이션은 가능하면 robustBufferAccess
및/또는 robustImageAccess
를 대신 사용하는 것이 좋습니다.
robustBufferAccess2 기능은 robustBufferAccess
의 상위 집합으로 볼 수 있습니다.
이 기능을 활성화하면, 모든 범위를 벗어난 쓰기나 아토믹이 메모리 백업 버퍼를 수정할 수 없게 됩니다. 또한 robustBufferAccess2
기능은 사양서에 설명된 대로 범위를 벗어난 접근을 할 때 다양한 유형의 버퍼에 대해 반환해야 하는 값을 강제 적용합니다.
버퍼가 바인딩되는 위치의 정렬은 구현마다 다르므로, VkPhysicalDeviceRobustness2PropertiesEXT에서 robustUniformBufferAccessSizeAlignment
및 robustStorageBufferAccessSizeAlignment
를 쿼리하는 것이 중요합니다.
robustImageAccess2 기능은 robustImageAccess
의 상위 집합으로 볼 수 있습니다. 이 기능은 접근하는 이미지 뷰의 차원에 대한 범위를 벗어난 검사를 기반으로 하며, 반환할 수 있는 값에 대해 더 엄격한 요구 사항을 추가합니다.
robustImageAccess2
를 사용하여 R, RG, 또는 RGB 포맷에 대한 범위를 벗어난 접근은 (0, 0, 0, 1)
을 반환합니다. VK_FORMAT_R8G8B8A8_UNORM
과 같은 RGBA 포맷의 경우, (0, 0, 0, 0)
을 반환합니다.
지원되는 범위를 벗어난 이미지 LOD에 접근하려는 경우, robustImageAccess2
를 활성화하면 범위를 벗어난 것으로 간주됩니다.
nullDescriptor 기능이 활성화되지 않은 경우, VkDescriptorSet
을 업데이트할 때, 쉐이더에서 정적으로 사용되지 않은 디스크립터라도 이를 지원하는 모든 리소스는 null이 아니어야 합니다. 이 기능을 사용하면 null 리소스 또는 뷰가 디스크립터를 지원할 수 있습니다. null 디스크립터에서 로드하면 0 값이 반환되고 null 디스크립터에 대한 스토어 및 아토믹이 삭제됩니다.
nullDescriptor
기능을 사용하면 vkCmdBindVertexBuffers::pBuffers
가 null인 정점 입력 바인딩에 접근을 가능하게 합니다.
일부 구현에서는 견고성이 성능에 영향을 미칠 수 있으므로, 개발자가 필요한 경우에만 견고성을 요청할 수 있도록 VK_EXT_pipeline_robustness 확장 기능을 추가했습니다.
VkPipeline
생성 시 파이프라인 전체 또는 파이프라인 스테이지별로 버퍼, 이미지 및 정점 입력 리소스에 접근하려는 견고성 동작을 지정하기 위해 하나 이상의 VkPipelineRobustnessCreateInfoEXT
구조체를 전달할 수 있습니다.
이 확장 기능은 견고성 기능이 활성화되지 않았을 때 어떤 동작을 기본으로 제공하는지 구현에 쿼리하는 VkPhysicalDevicePipelineRobustnessPropertiesEXT
도 제공합니다.
(Vulkan 1.2의 핵심인) VK_EXT_descriptor_indexing
에 있는 바인딩 후 업데이트 기능을 다루는 경우, 구현이 robustBufferAccess
와 바인딩 후 디스크립터를 업데이트하는 기능을 모두 지원할 수 있는지를 나타내는 robustBufferAccessUpdateAfterBind를 알아두는 것이 중요합니다.