diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp index ccba00f15f..59c799a601 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp @@ -79,7 +79,7 @@ namespace ImageProcessingAtom builderDescriptor.m_busId = azrtti_typeid(); builderDescriptor.m_createJobFunction = AZStd::bind(&ImageBuilderWorker::CreateJobs, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); builderDescriptor.m_processJobFunction = AZStd::bind(&ImageBuilderWorker::ProcessJob, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_version = 22; // [ATOM-14765] + builderDescriptor.m_version = 23; // [ATOM-14022] builderDescriptor.m_analysisFingerprint = ImageProcessingAtom::BuilderSettingManager::Instance()->GetAnalysisFingerprint(); m_imageBuilder.BusConnect(builderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp index 9c02894b7c..2448f501af 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageAssetProducer.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -238,14 +239,9 @@ namespace ImageProcessingAtom uint8_t* mipBuffer; uint32_t pitch; m_imageObject->GetImagePointer(mip, mipBuffer, pitch); - uint32_t mipBufferSize = m_imageObject->GetMipBufSize(mip); - - RHI::ImageSubresourceLayout layout; - layout.m_bytesPerImage = mipBufferSize / arraySize; - layout.m_rowCount = layout.m_bytesPerImage / pitch; - layout.m_size = RHI::Size(m_imageObject->GetWidth(mip), m_imageObject->GetHeight(mip) / arraySize, 1); - layout.m_bytesPerRow = pitch; - + RHI::Format format = Utils::PixelFormatToRHIFormat(m_imageObject->GetPixelFormat(), m_imageObject->HasImageFlags(EIF_SRGBRead)); + + RHI::ImageSubresourceLayout layout = RHI::GetImageSubresourceLayout(RHI::Size(m_imageObject->GetWidth(mip), m_imageObject->GetHeight(mip) / arraySize, 1), format); builder.BeginMip(layout); for (uint32_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ImageSubresource.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ImageSubresource.h index b536ed5524..d81ffc006c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ImageSubresource.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/ImageSubresource.h @@ -100,7 +100,9 @@ namespace AZ Size size, uint32_t rowCount, uint32_t bytesPerRow, - uint32_t bytesPerImage); + uint32_t bytesPerImage, + uint32_t numBlocksWidth, + uint32_t numBlocksHeight); /// The size of the image subresource in pixels. Certain formats have alignment requirements. /// Block compressed formats are 4 pixel aligned. Other non-standard formats may be 2 pixel aligned. @@ -114,6 +116,13 @@ namespace AZ /// The number of bytes in a single image slice. 3D textures are comprised of m_size.m_depth image slices. uint32_t m_bytesPerImage = 0; + + /// The number of blocks in width based on the texture fomat + uint32_t m_numBlocksWidth = 1; + + /// The number of blocks in height based on the texture fomat + uint32_t m_numBlocksHeight = 1; + }; struct ImageSubresourceLayoutPlaced : ImageSubresourceLayout diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ImageSubresource.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ImageSubresource.cpp index 4e34fe2b32..a956a13d1b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/ImageSubresource.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/ImageSubresource.cpp @@ -102,11 +102,13 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("m_size", &ImageSubresourceLayout::m_size) ->Field("m_rowCount", &ImageSubresourceLayout::m_rowCount) ->Field("m_bytesPerRow", &ImageSubresourceLayout::m_bytesPerRow) ->Field("m_bytesPerImage", &ImageSubresourceLayout::m_bytesPerImage) + ->Field("m_numBlocksWidth", &ImageSubresourceLayout::m_numBlocksWidth) + ->Field("m_numBlocksHeight", &ImageSubresourceLayout::m_numBlocksHeight) ; } } @@ -115,11 +117,15 @@ namespace AZ Size size, uint32_t rowCount, uint32_t bytesPerRow, - uint32_t bytesPerImage) + uint32_t bytesPerImage, + uint32_t numBlocksWidth, + uint32_t numBlocksHeight) : m_size{size} , m_rowCount{rowCount} , m_bytesPerRow{bytesPerRow} , m_bytesPerImage{bytesPerImage} + , m_numBlocksWidth{numBlocksWidth} + , m_numBlocksHeight{numBlocksHeight} {} ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset) @@ -316,6 +322,8 @@ namespace AZ subresourceLayout.m_rowCount = numBlocksHigh; subresourceLayout.m_size.m_width = imageSize.m_width; subresourceLayout.m_size.m_height = imageSize.m_height; + subresourceLayout.m_numBlocksWidth = numBlocks; + subresourceLayout.m_numBlocksHeight = numBlocks; } else if (isPacked) { diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp index 891f9ea2f3..d9a8f8aa3b 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp @@ -190,8 +190,8 @@ namespace AZ const uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, bufferOffsetAlign); const uint32_t stagingSlicePitch = RHI::AlignUp(subresourceLayout.m_rowCount * stagingRowPitch, bufferOffsetAlign); const uint32_t rowsPerSplit = static_cast(m_descriptor.m_stagingSizeInBytes) / stagingRowPitch; - const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount; - + const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_numBlocksHeight; + // ImageHeight must be bigger than or equal to the Image's row count. Images with a RowCount that is less than the ImageHeight indicates a block compression. // Images with a RowCount which is higher than the ImageHeight indicates a planar image, which is not supported for streaming images. if (subresourceLayout.m_size.m_height < subresourceLayout.m_rowCount) @@ -281,7 +281,7 @@ namespace AZ const uint32_t endRow = AZStd::min(startRow + rowsPerSplit, subresourceLayout.m_rowCount); // Calculate the blocksize for BC formatted images; the copy command works in texels. - const uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight; + uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight; // Copy subresource data to staging memory. uint8_t* stagingDataStart = framePacket->m_stagingResourceData + framePacket->m_dataOffset; @@ -293,6 +293,14 @@ namespace AZ const uint32_t bytesCopied = (endRow - startRow) * stagingRowPitch; Platform::SynchronizeBufferOnCPU(framePacket->m_stagingResource, framePacket->m_dataOffset, bytesCopied); + //Clamp heightToCopy to match subresourceLayout.m_size.m_height as it is possible to go over + //if subresourceLayout.m_size.m_height is not perfectly divisible by compressedTexelBlockSizeHeight + if(destHeight+heightToCopy > subresourceLayout.m_size.m_height) + { + uint32_t HeightDiff = (destHeight + heightToCopy) - subresourceLayout.m_size.m_height; + heightToCopy -= HeightDiff; + } + const RHI::Size sourceSize = RHI::Size(subresourceLayout.m_size.m_width, heightToCopy, 1); const RHI::Origin sourceOrigin = RHI::Origin(0, destHeight, depth); CopyBufferToImage(framePacket, image, stagingRowPitch, bytesCopied, diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantTreeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantTreeAsset.cpp index 25ba5aa837..f550a6f2ca 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantTreeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantTreeAsset.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -40,15 +41,12 @@ namespace AZ Data::AssetId ShaderVariantTreeAsset::GetShaderVariantTreeAssetIdFromShaderAssetId(const Data::AssetId& shaderAssetId) { //From the shaderAssetId We can deduce the path of the shader asset, and from the path of the shader asset we can deduce the path of the ShaderVariantTreeAsset. - AZStd::string shaderAssetPath; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderAssetPath - , &AZ::Data::AssetCatalogRequests::GetAssetPathById - , shaderAssetId); - - AZStd::string shaderAssetPathRoot; - AZStd::string shaderAssetPathName; - AzFramework::StringFunc::Path::Split(shaderAssetPath.c_str(), nullptr /*drive*/, &shaderAssetPathRoot, &shaderAssetPathName, nullptr /*extension*/); - + AZ::IO::FixedMaxPath shaderAssetPath; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderAssetPath.Native(), &AZ::Data::AssetCatalogRequests::GetAssetPathById + , shaderAssetId); + AZ::IO::FixedMaxPath shaderAssetPathRoot = shaderAssetPath.ParentPath(); + AZ::IO::FixedMaxPath shaderAssetPathName = shaderAssetPath.Stem(); + AZStd::string shaderVariantTreeAssetDir; AzFramework::StringFunc::Path::Join(ShaderVariantTreeAsset::CommonSubFolderLowerCase, shaderAssetPathRoot.c_str(), shaderVariantTreeAssetDir); AZStd::string shaderVariantTreeAssetFilename = AZStd::string::format("%s.%s", shaderAssetPathName.c_str(), ShaderVariantTreeAsset::Extension); @@ -63,8 +61,7 @@ namespace AZ { // If the game project did not customize the shadervariantlist, let's see if the original author of the .shader file // provided a shadervariantlist. - shaderVariantTreeAssetDir = shaderAssetPathRoot; - AzFramework::StringFunc::Path::Join(shaderVariantTreeAssetDir.c_str(), shaderVariantTreeAssetFilename.c_str(), shaderVariantTreeAssetPath); + AzFramework::StringFunc::Path::Join(shaderAssetPathRoot.c_str(), shaderVariantTreeAssetFilename.c_str(), shaderVariantTreeAssetPath); AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderVariantTreeAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath , shaderVariantTreeAssetPath.c_str(), AZ::Data::s_invalidAssetType, false); }