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..e75ee4d4bf 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_blockElementWidth = 1; + + /// The number of blocks in height based on the texture fomat + uint32_t m_blockElementHeight = 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..c76af7d5bb 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_blockElementWidth", &ImageSubresourceLayout::m_blockElementWidth) + ->Field("m_blockElementHeight", &ImageSubresourceLayout::m_blockElementHeight) ; } } @@ -115,11 +117,15 @@ namespace AZ Size size, uint32_t rowCount, uint32_t bytesPerRow, - uint32_t bytesPerImage) + uint32_t bytesPerImage, + uint32_t blockElementWidth, + uint32_t blockElementHeight) : m_size{size} , m_rowCount{rowCount} , m_bytesPerRow{bytesPerRow} , m_bytesPerImage{bytesPerImage} + , m_blockElementWidth{blockElementWidth} + , m_blockElementHeight{blockElementHeight} {} ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset) @@ -296,8 +302,22 @@ namespace AZ numBlocks = 4; break; + case RHI::Format::EAC_R11_UNORM: + case RHI::Format::EAC_R11_SNORM: + isBlockCompressed = true; + bytesPerElement = 8; + numBlocks = 4; + break; + + case RHI::Format::EAC_RG11_UNORM: + case RHI::Format::EAC_RG11_SNORM: + isBlockCompressed = true; + bytesPerElement = 16; + numBlocks = 4; + break; + default: - AZ_Assert(false, "Unimplemented esoteric format."); + AZ_Assert(false, "Unimplemented esoteric format %i.", static_cast(imageFormat)); } if (isBlockCompressed) @@ -316,6 +336,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_blockElementWidth = numBlocks; + subresourceLayout.m_blockElementHeight = numBlocks; } else if (isPacked) { diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp index 22849f7236..951a405d40 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp @@ -271,7 +271,7 @@ namespace AZ // Staging sizes uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, DX12_TEXTURE_DATA_PITCH_ALIGNMENT); uint32_t stagingSlicePitch = RHI::AlignUp(subresourceLayout.m_rowCount*stagingRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); - const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount; + const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_blockElementHeight; // 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. @@ -386,7 +386,7 @@ namespace AZ const uint32_t numRowsToCopy = endRow - startRow; // 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 { @@ -402,6 +402,14 @@ namespace AZ } } + //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; + } + // Add copy command to copy image subresource from staging memory to image gpu resource // Source location diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h index c7a2a5dd64..a6fe57f6d8 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.h @@ -415,7 +415,7 @@ namespace AZ // this assert typically happens when a shader needs a particular Srg (e.g., the ViewSrg) but the code did not bind it, // check the pass code in this callstack to determine why it was not bound - AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that is not currently bound in the pipeline. Current bindings: %s", + AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that isF not currently bound in the pipeline. Current bindings: %s", srgSlot, slotSrgString.c_str()); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/AsyncUploadQueue.cpp index 891f9ea2f3..594a4931b9 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_blockElementHeight; + // 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/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp index a6e7ff082f..ed578f18c5 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/AsyncUploadQueue.cpp @@ -214,7 +214,7 @@ namespace AZ const uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, bufferOffsetAlign); const uint32_t stagingSlicePitch = subresourceLayout.m_rowCount * stagingRowPitch; 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_blockElementHeight; // 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. @@ -333,7 +333,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. { @@ -348,6 +348,14 @@ namespace AZ framePacket->m_stagingBuffer->GetBufferMemoryView()->Unmap(RHI::HostMemoryAccess::Write); } + //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; + } + // Add copy command to copy image subresource from staging memory to image GPU resource. copyDescriptor.m_destinationOrigin.m_top = destHeight; copyDescriptor.m_sourceSize.m_height = heightToCopy; 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); }