diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h index 70754777c7..5b5c642047 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h @@ -16,6 +16,8 @@ #include #include +#include + namespace AZ { namespace RPI @@ -57,7 +59,22 @@ namespace AZ //! Same as above. Provided as a convenience when all arguments of the 'numthreads' attributes should be assigned to RHI::DispatchDirect::m_threadsPerGroup* variables. AZ::Outcome GetComputeShaderNumThreads(const Data::Asset& shaderAsset, RHI::DispatchDirect& dispatchDirect); - + + //! Get single image pixel value for specified mip and slice + template + T GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + + //! Retrieve a region of image pixel values (float) for specified mip and slice + //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + + //! Retrieve a region of image pixel values (uint) for specified mip and slice + //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); + + //! Retrieve a region of image pixel values (int) for specified mip and slice + //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h index 2e01f99cd9..73af8370cb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAsset.h @@ -12,7 +12,6 @@ #include #include #include -#include namespace AZ { @@ -86,22 +85,6 @@ namespace AZ //! Get image data for specified mip and slice. It may return empty array if its mipchain assets are not loaded AZStd::array_view GetSubImageData(uint32_t mip, uint32_t slice); - //! Get single image pixel value for specified mip and slice - template - T GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); - - //! Retrieve a region of image pixel values (float) for specified mip and slice - //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive - void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); - - //! Retrieve a region of image pixel values (uint) for specified mip and slice - //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive - void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); - - //! Retrieve a region of image pixel values (int) for specified mip and slice - //! NOTE: The topLeft coordinate is inclusive, whereas the bottomRight is exclusive - void GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); - //! Returns streaming image pool asset id of the pool that will be used to create the streaming image. const Data::AssetId& GetPoolAssetId() const; @@ -144,9 +127,6 @@ namespace AZ uint32_t m_totalImageDataSize = 0; StreamingImageFlags m_flags = StreamingImageFlags::None; - - template - T GetSubImagePixelValueInternal(uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); }; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp index 7285273c3e..c36472dd8b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp @@ -20,6 +20,203 @@ namespace AZ { namespace RPI { + namespace Internal + { + // The original implementation was from cryhalf's CryConvertFloatToHalf and CryConvertHalfToFloat function + // Will be replaced with centralized half float API + struct SHalf + { + explicit SHalf(float floatValue) + { + AZ::u32 Result; + + AZ::u32 intValue = ((AZ::u32*)(&floatValue))[0]; + AZ::u32 Sign = (intValue & 0x80000000U) >> 16U; + intValue = intValue & 0x7FFFFFFFU; + + if (intValue > 0x47FFEFFFU) + { + // The number is too large to be represented as a half. Saturate to infinity. + Result = 0x7FFFU; + } + else + { + if (intValue < 0x38800000U) + { + // The number is too small to be represented as a normalized half. + // Convert it to a denormalized value. + AZ::u32 Shift = 113U - (intValue >> 23U); + intValue = (0x800000U | (intValue & 0x7FFFFFU)) >> Shift; + } + else + { + // Rebias the exponent to represent the value as a normalized half. + intValue += 0xC8000000U; + } + + Result = ((intValue + 0x0FFFU + ((intValue >> 13U) & 1U)) >> 13U) & 0x7FFFU; + } + h = static_cast(Result | Sign); + } + + operator float() const + { + AZ::u32 Mantissa; + AZ::u32 Exponent; + AZ::u32 Result; + + Mantissa = h & 0x03FF; + + if ((h & 0x7C00) != 0) // The value is normalized + { + Exponent = ((h >> 10) & 0x1F); + } + else if (Mantissa != 0) // The value is denormalized + { + // Normalize the value in the resulting float + Exponent = 1; + + do + { + Exponent--; + Mantissa <<= 1; + } while ((Mantissa & 0x0400) == 0); + + Mantissa &= 0x03FF; + } + else // The value is zero + { + Exponent = static_cast(-112); + } + + Result = ((h & 0x8000) << 16) | // Sign + ((Exponent + 112) << 23) | // Exponent + (Mantissa << 13); // Mantissa + + return *(float*)&Result; + } + + private: + AZ::u16 h; + }; + + float ScaleValue(float value, float origMin, float origMax, float scaledMin, float scaledMax) + { + return ((value - origMin) / (origMax - origMin)) * (scaledMax - scaledMin) + scaledMin; + } + + float RetrieveFloatValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) + { + switch (format) + { + case AZ::RHI::Format::R8_UNORM: + case AZ::RHI::Format::A8_UNORM: + { + return mem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R8_SNORM: + { + // Scale the value from AZ::s8 min/max to -1 to 1 + // We need to treat -128 and -127 the same, so that we get a symmetric + // range of -127 to 127 with complementary scaled values of -1 to 1 + auto actualMem = reinterpret_cast(mem); + AZ::s8 signedMax = std::numeric_limits::max(); + AZ::s8 signedMin = aznumeric_cast(-signedMax); + return ScaleValue(AZStd::max(actualMem[index], signedMin), signedMin, signedMax, -1.0f, 1.0f); + } + case AZ::RHI::Format::D16_UNORM: + case AZ::RHI::Format::R16_UNORM: + { + return mem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R16_SNORM: + { + // Scale the value from AZ::s16 min/max to -1 to 1 + // We need to treat -32768 and -32767 the same, so that we get a symmetric + // range of -32767 to 32767 with complementary scaled values of -1 to 1 + auto actualMem = reinterpret_cast(mem); + AZ::s16 signedMax = std::numeric_limits::max(); + AZ::s16 signedMin = aznumeric_cast(-signedMax); + return ScaleValue(AZStd::max(actualMem[index], signedMin), signedMin, signedMax, -1.0f, 1.0f); + } + case AZ::RHI::Format::R16_FLOAT: + { + auto actualMem = reinterpret_cast(mem); + return SHalf(actualMem[index]); + } + case AZ::RHI::Format::D32_FLOAT: + case AZ::RHI::Format::R32_FLOAT: + { + auto actualMem = reinterpret_cast(mem); + return actualMem[index]; + } + default: + AZ_Assert(false, "Unsupported pixel format"); + return 0.0f; + } + } + + AZ::u32 RetrieveUintValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) + { + switch (format) + { + case AZ::RHI::Format::R8_UINT: + { + return mem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R16_UINT: + { + auto actualMem = reinterpret_cast(mem); + return actualMem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R32_UINT: + { + auto actualMem = reinterpret_cast(mem); + return actualMem[index]; + } + default: + AZ_Assert(false, "Unsupported pixel format"); + return 0; + } + } + + AZ::s32 RetrieveIntValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) + { + switch (format) + { + case AZ::RHI::Format::R8_SINT: + { + return mem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R16_SINT: + { + auto actualMem = reinterpret_cast(mem); + return actualMem[index] / static_cast(std::numeric_limits::max()); + } + case AZ::RHI::Format::R32_SINT: + { + auto actualMem = reinterpret_cast(mem); + return actualMem[index]; + } + default: + AZ_Assert(false, "Unsupported pixel format"); + return 0; + } + } + + template + T GetSubImagePixelValueInternal(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + AZStd::array values = { aznumeric_cast(0) }; + + auto topLeft = AZStd::make_pair(x, y); + auto bottomRight = AZStd::make_pair(x + 1, y + 1); + AZStd::span valueSpan(values.begin(), values.size()); + GetSubImagePixelValues(imageAsset, topLeft, bottomRight, valueSpan, componentIndex, mip, slice); + + return values[0]; + } + } Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical) { @@ -222,5 +419,119 @@ namespace AZ { return GetComputeShaderNumThreads(shaderAsset, &dispatchDirect.m_threadsPerGroupX, &dispatchDirect.m_threadsPerGroupY, &dispatchDirect.m_threadsPerGroupZ); } + + template<> + float GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + } + + template<> + AZ::u32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + } + + template<> + AZ::s32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + } + + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + // TODO: Use the component index + (void)componentIndex; + + if (!imageAsset.IsReady()) + { + return; + } + + auto imageData = imageAsset->GetSubImageData(mip, slice); + + if (!imageData.empty()) + { + const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); + auto width = imageDescriptor.m_size.m_width; + const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); + + size_t outValuesIndex = 0; + for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) + { + for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) + { + size_t imageDataIndex = (y * width + x) * pixelSize; + + auto& outValue = outValues[outValuesIndex++]; + outValue = Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + } + } + } + + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + // TODO: Use the component index + (void)componentIndex; + + if (!imageAsset.IsReady()) + { + return; + } + + auto imageData = imageAsset->GetSubImageData(mip, slice); + + if (!imageData.empty()) + { + const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); + auto width = imageDescriptor.m_size.m_width; + const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); + + size_t outValuesIndex = 0; + for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) + { + for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) + { + size_t imageDataIndex = (y * width + x) * pixelSize; + + auto& outValue = outValues[outValuesIndex++]; + outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + } + } + } + + void GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + // TODO: Use the component index + (void)componentIndex; + + if (!imageAsset.IsReady()) + { + return; + } + + auto imageData = imageAsset->GetSubImageData(mip, slice); + + if (!imageData.empty()) + { + const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); + auto width = imageDescriptor.m_size.m_width; + const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); + + size_t outValuesIndex = 0; + for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) + { + for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) + { + size_t imageDataIndex = (y * width + x) * pixelSize; + + auto& outValue = outValues[outValuesIndex++]; + outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + } + } + } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp index 286b259696..59f359e474 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAsset.cpp @@ -13,191 +13,6 @@ namespace AZ { - namespace Internal - { - // The original implementation was from cryhalf's CryConvertFloatToHalf and CryConvertHalfToFloat function - // Will be replaced with centralized half float API - struct SHalf - { - explicit SHalf(float floatValue) - { - AZ::u32 Result; - - AZ::u32 intValue = ((AZ::u32*)(&floatValue))[0]; - AZ::u32 Sign = (intValue & 0x80000000U) >> 16U; - intValue = intValue & 0x7FFFFFFFU; - - if (intValue > 0x47FFEFFFU) - { - // The number is too large to be represented as a half. Saturate to infinity. - Result = 0x7FFFU; - } - else - { - if (intValue < 0x38800000U) - { - // The number is too small to be represented as a normalized half. - // Convert it to a denormalized value. - AZ::u32 Shift = 113U - (intValue >> 23U); - intValue = (0x800000U | (intValue & 0x7FFFFFU)) >> Shift; - } - else - { - // Rebias the exponent to represent the value as a normalized half. - intValue += 0xC8000000U; - } - - Result = ((intValue + 0x0FFFU + ((intValue >> 13U) & 1U)) >> 13U) & 0x7FFFU; - } - h = static_cast(Result | Sign); - } - - operator float() const - { - AZ::u32 Mantissa; - AZ::u32 Exponent; - AZ::u32 Result; - - Mantissa = h & 0x03FF; - - if ((h & 0x7C00) != 0) // The value is normalized - { - Exponent = ((h >> 10) & 0x1F); - } - else if (Mantissa != 0) // The value is denormalized - { - // Normalize the value in the resulting float - Exponent = 1; - - do - { - Exponent--; - Mantissa <<= 1; - } while ((Mantissa & 0x0400) == 0); - - Mantissa &= 0x03FF; - } - else // The value is zero - { - Exponent = static_cast(-112); - } - - Result = ((h & 0x8000) << 16) | // Sign - ((Exponent + 112) << 23) | // Exponent - (Mantissa << 13); // Mantissa - - return *(float*)&Result; - } - - private: - AZ::u16 h; - }; - - float ScaleValue(float value, float origMin, float origMax, float scaledMin, float scaledMax) - { - return ((value - origMin) / (origMax - origMin)) * (scaledMax - scaledMin) + scaledMin; - } - - float RetrieveFloatValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) - { - switch (format) - { - case AZ::RHI::Format::R8_UNORM: - case AZ::RHI::Format::A8_UNORM: - { - return mem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R8_SNORM: - { - // Scale the value from AZ::s8 min/max to -1 to 1 - // We need to treat -128 and -127 the same, so that we get a symmetric - // range of -127 to 127 with complementary scaled values of -1 to 1 - auto actualMem = reinterpret_cast(mem); - AZ::s8 signedMax = std::numeric_limits::max(); - AZ::s8 signedMin = aznumeric_cast(-signedMax); - return ScaleValue(AZStd::max(actualMem[index], signedMin), signedMin, signedMax, -1.0f, 1.0f); - } - case AZ::RHI::Format::D16_UNORM: - case AZ::RHI::Format::R16_UNORM: - { - return mem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R16_SNORM: - { - // Scale the value from AZ::s16 min/max to -1 to 1 - // We need to treat -32768 and -32767 the same, so that we get a symmetric - // range of -32767 to 32767 with complementary scaled values of -1 to 1 - auto actualMem = reinterpret_cast(mem); - AZ::s16 signedMax = std::numeric_limits::max(); - AZ::s16 signedMin = aznumeric_cast(-signedMax); - return ScaleValue(AZStd::max(actualMem[index], signedMin), signedMin, signedMax, -1.0f, 1.0f); - } - case AZ::RHI::Format::R16_FLOAT: - { - auto actualMem = reinterpret_cast(mem); - return SHalf(actualMem[index]); - } - case AZ::RHI::Format::D32_FLOAT: - case AZ::RHI::Format::R32_FLOAT: - { - auto actualMem = reinterpret_cast(mem); - return actualMem[index]; - } - default: - AZ_Assert(false, "Unsupported pixel format"); - return 0.0f; - } - } - - AZ::u32 RetrieveUintValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) - { - switch (format) - { - case AZ::RHI::Format::R8_UINT: - { - return mem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R16_UINT: - { - auto actualMem = reinterpret_cast(mem); - return actualMem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R32_UINT: - { - auto actualMem = reinterpret_cast(mem); - return actualMem[index]; - } - default: - AZ_Assert(false, "Unsupported pixel format"); - return 0; - } - } - - AZ::s32 RetrieveIntValue(const AZ::u8* mem, size_t index, AZ::RHI::Format format) - { - switch (format) - { - case AZ::RHI::Format::R8_SINT: - { - return mem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R16_SINT: - { - auto actualMem = reinterpret_cast(mem); - return actualMem[index] / static_cast(std::numeric_limits::max()); - } - case AZ::RHI::Format::R32_SINT: - { - auto actualMem = reinterpret_cast(mem); - return actualMem[index]; - } - default: - AZ_Assert(false, "Unsupported pixel format"); - return 0; - } - } - } - namespace RPI { const char* StreamingImageAsset::DisplayName = "StreamingImage"; @@ -309,117 +124,5 @@ namespace AZ return mipChainAsset->GetSubImageData(mip - mipChain.m_mipOffset, slice); } - - template - T StreamingImageAsset::GetSubImagePixelValueInternal(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - AZStd::array values = { aznumeric_cast(0) }; - - auto topLeft = AZStd::make_pair(x, y); - auto bottomRight = AZStd::make_pair(x + 1, y + 1); - AZStd::span valueSpan(values.begin(), values.size()); - GetSubImagePixelValues(topLeft, bottomRight, valueSpan, componentIndex, mip, slice); - - return values[0]; - } - - template<> - float StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); - } - - template<> - AZ::u32 StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); - } - - template<> - AZ::s32 StreamingImageAsset::GetSubImagePixelValue(uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - return GetSubImagePixelValueInternal(x, y, componentIndex, mip, slice); - } - - void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - // TODO: Use the component index - (void)componentIndex; - - auto imageData = GetSubImageData(mip, slice); - - if (!imageData.empty()) - { - const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); - - size_t outValuesIndex = 0; - for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) - { - for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) - { - size_t imageDataIndex = (y * width + x) * pixelSize; - - auto& outValue = outValues[outValuesIndex++]; - outValue = Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); - } - } - } - } - - void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - // TODO: Use the component index - (void)componentIndex; - - auto imageData = GetSubImageData(mip, slice); - - if (!imageData.empty()) - { - const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); - - size_t outValuesIndex = 0; - for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) - { - for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) - { - size_t imageDataIndex = (y * width + x) * pixelSize; - - auto& outValue = outValues[outValuesIndex++]; - outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); - } - } - } - } - - void StreamingImageAsset::GetSubImagePixelValues(AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) - { - // TODO: Use the component index - (void)componentIndex; - - auto imageData = GetSubImageData(mip, slice); - - if (!imageData.empty()) - { - const AZ::RHI::ImageDescriptor imageDescriptor = GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format); - - size_t outValuesIndex = 0; - for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) - { - for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) - { - size_t imageDataIndex = (y * width + x) * pixelSize; - - auto& outValue = outValues[outValuesIndex++]; - outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); - } - } - } - } } } diff --git a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp index 5efab95818..ef4a0a0e08 100644 --- a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -742,7 +743,7 @@ namespace UnitTest { for (uint32_t x = 0; x < size.m_width; ++x) { - auto pixelDataValue = imageAsset->GetSubImagePixelValue(x, y); + auto pixelDataValue = RPI::GetSubImagePixelValue(imageAsset, x, y); auto pixelExpectedValue = static_cast(y * size.m_width + x) / static_cast(std::numeric_limits::max()); EXPECT_NEAR(pixelDataValue, pixelExpectedValue, Constants::Tolerance); @@ -753,7 +754,7 @@ namespace UnitTest AZStd::vector pixelValues(size.m_width * size.m_height); auto topLeft = AZStd::make_pair(0, 0); auto bottomRight = AZStd::make_pair(size.m_width, size.m_height); - streamingImageAsset->GetSubImagePixelValues(topLeft, bottomRight, pixelValues); + RPI::GetSubImagePixelValues(imageAsset, topLeft, bottomRight, pixelValues); for (uint32_t index = 0; index < pixelValues.size(); ++index) { auto pixelDataValue = pixelValues[index];