diff --git a/source/blender/gpu/tests/texture_test.cc b/source/blender/gpu/tests/texture_test.cc index 6a5028b16ec..785f37fbcac 100644 --- a/source/blender/gpu/tests/texture_test.cc +++ b/source/blender/gpu/tests/texture_test.cc @@ -262,13 +262,11 @@ static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R11F_G11F_B10F() GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R11F_G11F_B10F); #endif -#if RUN_SRGB_UNIMPLEMENTED static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8() { - texture_create_upload_read_with_bias(0.0f); + texture_create_upload_read_with_bias(0.003f); } GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8); -#endif static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_SNORM() { @@ -405,13 +403,13 @@ static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F() 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() { - texture_create_upload_read_with_bias(0.0f); + texture_create_upload_read_with_bias(0.0000001f); } GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24); +#if RUN_COMPONENT_UNIMPLEMENTED static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT16() { texture_create_upload_read_with_bias(0.0f); diff --git a/source/blender/gpu/vulkan/vk_data_conversion.cc b/source/blender/gpu/vulkan/vk_data_conversion.cc index c44e6b6f2d2..5851189c5d3 100644 --- a/source/blender/gpu/vulkan/vk_data_conversion.cc +++ b/source/blender/gpu/vulkan/vk_data_conversion.cc @@ -7,6 +7,8 @@ #include "vk_data_conversion.hh" +#include "BLI_color.hh" + #include "Imath/half.h" namespace blender::gpu { @@ -47,6 +49,12 @@ enum class ConversionType { HALF_TO_FLOAT, FLOAT_TO_HALF, + FLOAT_TO_SRGBA8, + SRGBA8_TO_FLOAT, + + FLOAT_TO_DEPTH_COMPONENT24, + DEPTH_COMPONENT24_TO_FLOAT, + /** * The requested conversion isn't supported. */ @@ -90,6 +98,12 @@ static ConversionType type_of_conversion_float(eGPUTextureFormat device_format) case GPU_R16_SNORM: return ConversionType::FLOAT_TO_SNORM16; + case GPU_SRGB8_A8: + return ConversionType::FLOAT_TO_SRGBA8; + + case GPU_DEPTH_COMPONENT24: + return ConversionType::FLOAT_TO_DEPTH_COMPONENT24; + case GPU_RGB32F: /* GPU_RGB32F Not supported by vendors. */ case GPU_RGBA8UI: case GPU_RGBA8I: @@ -114,7 +128,6 @@ static ConversionType type_of_conversion_float(eGPUTextureFormat device_format) case GPU_R11F_G11F_B10F: case GPU_DEPTH32F_STENCIL8: case GPU_DEPTH24_STENCIL8: - case GPU_SRGB8_A8: case GPU_RGB8UI: case GPU_RGB8I: case GPU_RGB8: @@ -131,7 +144,6 @@ static ConversionType type_of_conversion_float(eGPUTextureFormat device_format) case GPU_RGBA8_DXT5: case GPU_SRGB8: case GPU_RGB9_E5: - case GPU_DEPTH_COMPONENT24: case GPU_DEPTH_COMPONENT16: return ConversionType::UNSUPPORTED; } @@ -512,6 +524,8 @@ static ConversionType reversed(ConversionType type) CASE_PAIR(UI32, UI8) CASE_PAIR(I32, I8) CASE_PAIR(FLOAT, HALF) + CASE_PAIR(FLOAT, SRGBA8) + CASE_PAIR(FLOAT, DEPTH_COMPONENT24) case ConversionType::UNSUPPORTED: return ConversionType::UNSUPPORTED; @@ -529,6 +543,44 @@ static ConversionType reversed(ConversionType type) /** \name Data Conversion * \{ */ +template struct ComponentValue { + InnerType value; +}; +template struct PixelValue { + InnerType value; +}; + +using UI8 = ComponentValue; +using UI16 = ComponentValue; +using UI32 = ComponentValue; +using I8 = ComponentValue; +using I16 = ComponentValue; +using I32 = ComponentValue; +using F32 = ComponentValue; +using F16 = ComponentValue; +using SRGBA8 = PixelValue>; +using FLOAT4 = PixelValue>; + +class DepthComponent24 : public ComponentValue { + public: + operator uint32_t() const + { + return value; + } + + DepthComponent24 &operator=(uint32_t new_value) + { + value = new_value; + return *this; + } + + /* Depth component24 are 4 bytes, but 1 isn't used. */ + static constexpr size_t used_byte_size() + { + return 3; + } +}; + template struct SignedNormalized { static_assert(std::is_same() || std::is_same()); InnerType value; @@ -550,35 +602,33 @@ template struct SignedNormalized { }; template struct UnsignedNormalized { - static_assert(std::is_same() || std::is_same()); + static_assert(std::is_same() || std::is_same() || + std::is_same()); InnerType value; + static constexpr size_t used_byte_size() + { + if constexpr (std::is_same()) { + return InnerType::used_byte_size(); + } + else { + return sizeof(InnerType); + } + } + static constexpr int32_t scalar() { - return (1 << (sizeof(InnerType) * 8)) - 1; + + return (1 << (used_byte_size() * 8)) - 1; } static constexpr int32_t max() { - return ((1 << (sizeof(InnerType) * 8)) - 1); + return ((1 << (used_byte_size() * 8)) - 1); } }; -template struct ComponentValue { - InnerType value; -}; - -using UI8 = ComponentValue; -using UI16 = ComponentValue; -using UI32 = ComponentValue; -using I8 = ComponentValue; -using I16 = ComponentValue; -using I32 = ComponentValue; -using F32 = ComponentValue; -using F16 = ComponentValue; - -template -void convert_component(SignedNormalized &dst, const F32 &src) +template void convert(SignedNormalized &dst, const F32 &src) { static constexpr int32_t scalar = SignedNormalized::scalar(); static constexpr int32_t delta = SignedNormalized::delta(); @@ -586,32 +636,29 @@ void convert_component(SignedNormalized &dst, const F32 &src) dst.value = (clamp_i((src.value * scalar + delta), 0, max)); } -template -void convert_component(F32 &dst, const SignedNormalized &src) +template void convert(F32 &dst, const SignedNormalized &src) { static constexpr int32_t scalar = SignedNormalized::scalar(); static constexpr int32_t delta = SignedNormalized::delta(); dst.value = float(int32_t(src.value) - delta) / scalar; } -template -void convert_component(UnsignedNormalized &dst, const F32 &src) +template void convert(UnsignedNormalized &dst, const F32 &src) { static constexpr int32_t scalar = UnsignedNormalized::scalar(); static constexpr int32_t max = scalar; dst.value = (clamp_i((src.value * scalar), 0, max)); } -template -void convert_component(F32 &dst, const UnsignedNormalized &src) +template void convert(F32 &dst, const UnsignedNormalized &src) { static constexpr int32_t scalar = UnsignedNormalized::scalar(); - dst.value = float(src.value) / scalar; + dst.value = float(int32_t(src.value)) / scalar; } /* Copy the contents of src to dst with out performing any actual conversion. */ template -void convert_component(DestinationType &dst, const SourceType &src) +void convert(DestinationType &dst, const SourceType &src) { static_assert(std::is_same() || std::is_same() || std::is_same() || std::is_same() || @@ -623,24 +670,34 @@ void convert_component(DestinationType &dst, const SourceType &src) dst.value = src.value; } -static void convert_component(F16 &dst, const F32 &src) +static void convert(F16 &dst, const F32 &src) { dst.value = imath_float_to_half(src.value); } -static void convert_component(F32 &dst, const F16 &src) +static void convert(F32 &dst, const F16 &src) { dst.value = imath_half_to_float(src.value); } +static void convert(SRGBA8 &dst, const FLOAT4 &src) +{ + dst.value = src.value.encode(); +} + +static void convert(FLOAT4 &dst, const SRGBA8 &src) +{ + dst.value = src.value.decode(); +} + /* \} */ template -void convert_per_component(MutableSpan dst, Span src) +void convert(MutableSpan dst, Span src) { BLI_assert(src.size() == dst.size()); for (int64_t index : IndexRange(src.size())) { - convert_component(dst[index], src[index]); + convert(dst[index], src[index]); } } @@ -655,7 +712,17 @@ void convert_per_component(void *dst_memory, total_components); MutableSpan dst = MutableSpan( static_cast(dst_memory), total_components); - convert_per_component(dst, src); + convert(dst, src); +} + +template +void convert_per_pixel(void *dst_memory, const void *src_memory, size_t buffer_size) +{ + Span src = Span(static_cast(src_memory), + buffer_size); + MutableSpan dst = MutableSpan( + static_cast(dst_memory), buffer_size); + convert(dst, src); } static void convert_buffer(void *dst_memory, @@ -746,6 +813,22 @@ static void convert_buffer(void *dst_memory, case ConversionType::HALF_TO_FLOAT: convert_per_component(dst_memory, src_memory, buffer_size, device_format); break; + + case ConversionType::FLOAT_TO_SRGBA8: + convert_per_pixel(dst_memory, src_memory, buffer_size); + break; + case ConversionType::SRGBA8_TO_FLOAT: + convert_per_pixel(dst_memory, src_memory, buffer_size); + break; + + case ConversionType::FLOAT_TO_DEPTH_COMPONENT24: + convert_per_component, F32>( + dst_memory, src_memory, buffer_size, device_format); + break; + case ConversionType::DEPTH_COMPONENT24_TO_FLOAT: + convert_per_component>( + dst_memory, src_memory, buffer_size, device_format); + break; } }