Vulkan: Workaround for 24bit depth component #108698
|
@ -428,13 +428,11 @@ static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5()
|
|||
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5);
|
||||
#endif
|
||||
|
||||
#if RUN_UNSUPPORTED
|
||||
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F()
|
||||
{
|
||||
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT32F, GPU_DATA_FLOAT>(0.0f);
|
||||
}
|
||||
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F);
|
||||
#endif
|
||||
|
||||
#if RUN_COMPONENT_UNIMPLEMENTED
|
||||
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24()
|
||||
|
@ -622,7 +620,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_R32UI()
|
|||
}
|
||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R32UI);
|
||||
|
||||
#if RUN_UNSUPPORTED
|
||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH32F_STENCIL8()
|
||||
{
|
||||
texture_create_upload_read<GPU_DEPTH32F_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
||||
|
@ -634,7 +631,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8()
|
|||
texture_create_upload_read<GPU_DEPTH24_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
||||
}
|
||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8);
|
||||
#endif
|
||||
|
||||
#if RUN_UNSUPPORTED
|
||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB8UI()
|
||||
|
@ -656,7 +652,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI()
|
|||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI);
|
||||
#endif
|
||||
|
||||
#if RUN_COMPONENT_UNIMPLEMENTED
|
||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT32F()
|
||||
{
|
||||
texture_create_upload_read<GPU_DEPTH_COMPONENT32F, GPU_DATA_UINT, uint32_t>();
|
||||
|
@ -669,6 +664,7 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24()
|
|||
}
|
||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24);
|
||||
|
||||
#if RUN_COMPONENT_UNIMPLEMENTED
|
||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16()
|
||||
{
|
||||
texture_create_upload_read<GPU_DEPTH_COMPONENT16, GPU_DATA_UINT, uint32_t>();
|
||||
|
|
|
@ -73,6 +73,18 @@ void VKBackend::platform_init(const VKDevice &device)
|
|||
driver_version.c_str());
|
||||
}
|
||||
|
||||
void VKBackend::detect_workarounds(VKDevice &device)
|
||||
{
|
||||
VKWorkarounds workarounds;
|
||||
|
||||
/* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
|
||||
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
||||
workarounds.not_aligned_pixel_formats = true;
|
||||
}
|
||||
|
||||
device.workarounds_ = workarounds;
|
||||
}
|
||||
|
||||
void VKBackend::platform_exit()
|
||||
{
|
||||
GPG.clear();
|
||||
|
@ -174,7 +186,7 @@ shaderc::Compiler &VKBackend::get_shaderc_compiler()
|
|||
return shaderc_compiler_;
|
||||
}
|
||||
|
||||
void VKBackend::capabilities_init(const VKDevice &device)
|
||||
void VKBackend::capabilities_init(VKDevice &device)
|
||||
{
|
||||
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
|
||||
const VkPhysicalDeviceLimits &limits = properties.limits;
|
||||
|
@ -205,6 +217,8 @@ void VKBackend::capabilities_init(const VKDevice &device)
|
|||
GCaps.max_varying_floats = limits.maxVertexOutputComponents;
|
||||
GCaps.max_shader_storage_buffer_bindings = limits.maxPerStageDescriptorStorageBuffers;
|
||||
GCaps.max_compute_shader_storage_blocks = limits.maxPerStageDescriptorStorageBuffers;
|
||||
|
||||
detect_workarounds(device);
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -88,9 +88,10 @@ class VKBackend : public GPUBackend {
|
|||
}
|
||||
|
||||
static void platform_init(const VKDevice &device);
|
||||
static void capabilities_init(const VKDevice &device);
|
||||
static void capabilities_init(VKDevice &device);
|
||||
|
||||
private:
|
||||
static void detect_workarounds(VKDevice &device);
|
||||
static void platform_init();
|
||||
static void platform_exit();
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ enum class ConversionType {
|
|||
FLOAT_TO_SNORM16,
|
||||
SNORM16_TO_FLOAT,
|
||||
|
||||
FLOAT_TO_UNORM32,
|
||||
UNORM32_TO_FLOAT,
|
||||
|
||||
UI32_TO_UI16,
|
||||
UI16_TO_UI32,
|
||||
|
||||
|
@ -239,6 +242,7 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
|||
case GPU_RGBA32UI:
|
||||
case GPU_RG32UI:
|
||||
case GPU_R32UI:
|
||||
case GPU_DEPTH_COMPONENT24:
|
||||
return ConversionType::PASS_THROUGH;
|
||||
|
||||
case GPU_RGBA16UI:
|
||||
|
@ -252,6 +256,10 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
|||
case GPU_R8UI:
|
||||
return ConversionType::UI32_TO_UI8;
|
||||
|
||||
case GPU_DEPTH_COMPONENT32F:
|
||||
case GPU_DEPTH32F_STENCIL8:
|
||||
return ConversionType::UNORM32_TO_FLOAT;
|
||||
|
||||
case GPU_RGBA8I:
|
||||
case GPU_RGBA8:
|
||||
case GPU_RGBA16I:
|
||||
|
@ -276,7 +284,6 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
|||
case GPU_RGB10_A2:
|
||||
case GPU_RGB10_A2UI:
|
||||
case GPU_R11F_G11F_B10F:
|
||||
case GPU_DEPTH32F_STENCIL8:
|
||||
case GPU_DEPTH24_STENCIL8:
|
||||
case GPU_SRGB8_A8:
|
||||
case GPU_RGBA8_SNORM:
|
||||
|
@ -304,8 +311,6 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
|||
case GPU_RGBA8_DXT5:
|
||||
case GPU_SRGB8:
|
||||
case GPU_RGB9_E5:
|
||||
case GPU_DEPTH_COMPONENT32F:
|
||||
case GPU_DEPTH_COMPONENT24:
|
||||
case GPU_DEPTH_COMPONENT16:
|
||||
return ConversionType::UNSUPPORTED;
|
||||
}
|
||||
|
@ -523,6 +528,7 @@ static ConversionType reversed(ConversionType type)
|
|||
CASE_PAIR(FLOAT, SNORM8)
|
||||
CASE_PAIR(FLOAT, UNORM16)
|
||||
CASE_PAIR(FLOAT, SNORM16)
|
||||
CASE_PAIR(FLOAT, UNORM32)
|
||||
CASE_PAIR(UI32, UI16)
|
||||
CASE_PAIR(I32, I16)
|
||||
CASE_PAIR(UI32, UI8)
|
||||
|
@ -632,6 +638,7 @@ template<typename InnerType> struct SignedNormalized {
|
|||
|
||||
template<typename InnerType> struct UnsignedNormalized {
|
||||
static_assert(std::is_same<InnerType, uint8_t>() || std::is_same<InnerType, uint16_t>() ||
|
||||
std::is_same<InnerType, uint32_t>() ||
|
||||
std::is_same<InnerType, DepthComponent24>());
|
||||
InnerType value;
|
||||
|
||||
|
@ -645,15 +652,24 @@ template<typename InnerType> struct UnsignedNormalized {
|
|||
}
|
||||
}
|
||||
|
||||
static constexpr int32_t scalar()
|
||||
static constexpr uint32_t scalar()
|
||||
{
|
||||
|
||||
return (1 << (used_byte_size() * 8)) - 1;
|
||||
if constexpr (std::is_same<InnerType, DepthComponent24>()) {
|
||||
return (1 << (used_byte_size() * 8)) - 1;
|
||||
}
|
||||
else {
|
||||
return std::numeric_limits<InnerType>::max();
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr int32_t max()
|
||||
static constexpr uint32_t max()
|
||||
{
|
||||
return ((1 << (used_byte_size() * 8)) - 1);
|
||||
if constexpr (std::is_same<InnerType, DepthComponent24>()) {
|
||||
return (1 << (used_byte_size() * 8)) - 1;
|
||||
}
|
||||
else {
|
||||
return std::numeric_limits<InnerType>::max();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -674,15 +690,15 @@ template<typename StorageType> void convert(F32 &dst, const SignedNormalized<Sto
|
|||
|
||||
template<typename StorageType> void convert(UnsignedNormalized<StorageType> &dst, const F32 &src)
|
||||
{
|
||||
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||
static constexpr int32_t max = scalar;
|
||||
dst.value = (clamp_i((src.value * scalar), 0, max));
|
||||
static constexpr uint32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||
static constexpr uint32_t max = scalar;
|
||||
dst.value = (clamp_f((src.value * scalar), 0, max));
|
||||
}
|
||||
|
||||
template<typename StorageType> void convert(F32 &dst, const UnsignedNormalized<StorageType> &src)
|
||||
{
|
||||
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||
dst.value = float(int32_t(src.value)) / scalar;
|
||||
static constexpr uint32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||
dst.value = float(uint32_t(src.value)) / scalar;
|
||||
}
|
||||
|
||||
/* Copy the contents of src to dst with out performing any actual conversion. */
|
||||
|
@ -860,6 +876,15 @@ static void convert_buffer(void *dst_memory,
|
|||
dst_memory, src_memory, buffer_size, device_format);
|
||||
break;
|
||||
|
||||
case ConversionType::FLOAT_TO_UNORM32:
|
||||
convert_per_component<UnsignedNormalized<uint32_t>, F32>(
|
||||
dst_memory, src_memory, buffer_size, device_format);
|
||||
break;
|
||||
case ConversionType::UNORM32_TO_FLOAT:
|
||||
convert_per_component<F32, UnsignedNormalized<uint32_t>>(
|
||||
dst_memory, src_memory, buffer_size, device_format);
|
||||
break;
|
||||
|
||||
case ConversionType::FLOAT_TO_HALF:
|
||||
convert_per_component<F16, F32>(dst_memory, src_memory, buffer_size, device_format);
|
||||
break;
|
||||
|
|
|
@ -15,6 +15,17 @@
|
|||
#include "vk_descriptor_pools.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
class VKBackend;
|
||||
|
||||
struct VKWorkarounds {
|
||||
/**
|
||||
* Some devices don't support pixel formats that are aligned to 24 and 48 bits.
|
||||
* In this case we need to use a different texture format.
|
||||
*
|
||||
* If set to true we should work around this issue by using a different texture format.
|
||||
*/
|
||||
bool not_aligned_pixel_formats = false;
|
||||
};
|
||||
|
||||
class VKDevice : public NonCopyable {
|
||||
private:
|
||||
|
@ -35,6 +46,9 @@ class VKDevice : public NonCopyable {
|
|||
/** Functions of vk_ext_debugutils for this device/instance. */
|
||||
debug::VKDebuggingTools debugging_tools_;
|
||||
|
||||
/* Workarounds */
|
||||
VKWorkarounds workarounds_;
|
||||
|
||||
public:
|
||||
VkPhysicalDevice physical_device_get() const
|
||||
{
|
||||
|
@ -95,11 +109,19 @@ class VKDevice : public NonCopyable {
|
|||
std::string vendor_name() const;
|
||||
std::string driver_version() const;
|
||||
|
||||
const VKWorkarounds &workarounds_get() const
|
||||
{
|
||||
return workarounds_;
|
||||
}
|
||||
|
||||
private:
|
||||
void init_physical_device_properties();
|
||||
void init_debug_callbacks();
|
||||
void init_memory_allocator();
|
||||
void init_descriptor_pools();
|
||||
|
||||
/* During initialization the backend requires access to update the workarounds. */
|
||||
friend VKBackend;
|
||||
};
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -220,6 +220,15 @@ bool VKTexture::init_internal()
|
|||
* at this moment, so we cannot initialize here. The initialization is postponed until the
|
||||
* allocation of the texture on the device. */
|
||||
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
const VKWorkarounds &workarounds = device.workarounds_get();
|
||||
if (format_ == GPU_DEPTH_COMPONENT24 && workarounds.not_aligned_pixel_formats) {
|
||||
format_ = GPU_DEPTH_COMPONENT32F;
|
||||
}
|
||||
if (format_ == GPU_DEPTH24_STENCIL8 && workarounds.not_aligned_pixel_formats) {
|
||||
format_ = GPU_DEPTH32F_STENCIL8;
|
||||
}
|
||||
|
||||
/* TODO: return false when texture format isn't supported. */
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue