vulkan glsl 中的非统一纹理访问
Non uniform texture access in vulkan glsl
我正在尝试编写一个计算着色器,它对图像进行光线跟踪,图像 A 的 yz 平面样本右侧的像素,图像 B 左侧的像素。
我不想对两个图像都进行采样,所以我尝试通过以下方式使用非统一访问:
texture(textures[nonuniformEXT(sampler_id)], vec2(0.5));
并在着色器中启用相关扩展。这会触发以下验证层错误:
Message: Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01091 ] Object 0: handle = 0x55a1c21315d0, name = Logical device: AMD RADV RAVEN2, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xa7bb8db6 | vkCreateShaderModule(): The SPIR-V Capability (SampledImageArrayNonUniformIndexing) was declared, but none of the requirements were met to use it. The Vulkan spec states: If pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.2.182.0/linux/1.2-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01091)
如果我阅读 docs,这似乎是一项硬件功能,但有人说如果创建正确的扩展对象,我仍然可以进行非统一访问。但我不完全确定该怎么做。
您必须在创建设备时启用该功能。
您可以通过调用 vkGetPhysicalDeviceFeatures2 and following the pNext
chain through to a VkPhysicalDeviceVulkan12Features 来检查是否支持该功能,并检查 shaderSampledImageArrayNonUniformIndexing
成员是否为 VK_TRUE
。
之后,当使用 vkCreateDevice, inside the pCreateInfo
structure, in the pNext
chain you have to have a VkPhysicalDeviceVulkan12Features 创建设备时 shaderSampledImageArrayNonUniformIndexing
设置为 VK_TRUE
。
bool checkForNonUniformIndexing(VkPhysicalDevice physicalDevice)
{
VkPhysicalDeviceFeatures2 features;
vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
if(features.sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2)
{
return false;
}
const VkPhysicalDeviceFeatures2* next = &features;
do
{
// We know the type of the struct based on the `sType` member, but the first
// two fields are the same in all of these structs. There may be a more appropriate
// generic structure to use, but as long as we don't access any further members
// we should be mostly fine.
next = reinterpret_cast<const VkPhysicalDeviceFeatures*>(next->pNext);
if(next.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES)
{
const VkPhysicalDeviceVulkan12Features* pVk12Features = reinterpret_cast<const VkPhysicalDeviceVulkan12Features*>(next);
return next.shaderSampledImageArrayNonUniformIndexing == VK_TRUE;
}
} while(next);
return false;
}
VkDevice* createDevice(VkPhysicalDevice physicalDevice, const VkAllocationCallbacks* pAllocator)
{
VkPhysicalDeviceVulkan12Features features;
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE;
VkDeviceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pNext = &features;
// Setting other create data
VkDevice device;
vkCreateDevice(physicalDevice, &createInfo, pAllocator, &device);
// Error checking
return device;
}
我正在尝试编写一个计算着色器,它对图像进行光线跟踪,图像 A 的 yz 平面样本右侧的像素,图像 B 左侧的像素。
我不想对两个图像都进行采样,所以我尝试通过以下方式使用非统一访问:
texture(textures[nonuniformEXT(sampler_id)], vec2(0.5));
并在着色器中启用相关扩展。这会触发以下验证层错误:
Message: Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01091 ] Object 0: handle = 0x55a1c21315d0, name = Logical device: AMD RADV RAVEN2, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xa7bb8db6 | vkCreateShaderModule(): The SPIR-V Capability (SampledImageArrayNonUniformIndexing) was declared, but none of the requirements were met to use it. The Vulkan spec states: If pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.2.182.0/linux/1.2-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01091)
如果我阅读 docs,这似乎是一项硬件功能,但有人说如果创建正确的扩展对象,我仍然可以进行非统一访问。但我不完全确定该怎么做。
您必须在创建设备时启用该功能。
您可以通过调用 vkGetPhysicalDeviceFeatures2 and following the pNext
chain through to a VkPhysicalDeviceVulkan12Features 来检查是否支持该功能,并检查 shaderSampledImageArrayNonUniformIndexing
成员是否为 VK_TRUE
。
之后,当使用 vkCreateDevice, inside the pCreateInfo
structure, in the pNext
chain you have to have a VkPhysicalDeviceVulkan12Features 创建设备时 shaderSampledImageArrayNonUniformIndexing
设置为 VK_TRUE
。
bool checkForNonUniformIndexing(VkPhysicalDevice physicalDevice)
{
VkPhysicalDeviceFeatures2 features;
vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
if(features.sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2)
{
return false;
}
const VkPhysicalDeviceFeatures2* next = &features;
do
{
// We know the type of the struct based on the `sType` member, but the first
// two fields are the same in all of these structs. There may be a more appropriate
// generic structure to use, but as long as we don't access any further members
// we should be mostly fine.
next = reinterpret_cast<const VkPhysicalDeviceFeatures*>(next->pNext);
if(next.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES)
{
const VkPhysicalDeviceVulkan12Features* pVk12Features = reinterpret_cast<const VkPhysicalDeviceVulkan12Features*>(next);
return next.shaderSampledImageArrayNonUniformIndexing == VK_TRUE;
}
} while(next);
return false;
}
VkDevice* createDevice(VkPhysicalDevice physicalDevice, const VkAllocationCallbacks* pAllocator)
{
VkPhysicalDeviceVulkan12Features features;
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE;
VkDeviceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pNext = &features;
// Setting other create data
VkDevice device;
vkCreateDevice(physicalDevice, &createInfo, pAllocator, &device);
// Error checking
return device;
}