Merge pull request #1309 from aws-lumberyard-dev/MetalAsyncBufferFixes
Metal async buffer fixes related to meshes
This commit is contained in:
@@ -400,15 +400,13 @@ namespace AZ
|
||||
id<MTLResource> mtlconstantBufferResource = m_constantBuffer.GetGpuAddress<id<MTLResource>>();
|
||||
if(RHI::CheckBitsAny(srgResourcesVisInfo.m_constantDataStageMask, RHI::ShaderStageMask::Compute))
|
||||
{
|
||||
uint16_t arrayIndex = resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArrayLen++;
|
||||
resourcesToMakeResidentCompute[MTLResourceUsageRead].m_resourceArray[arrayIndex] = mtlconstantBufferResource;
|
||||
resourcesToMakeResidentCompute[MTLResourceUsageRead].emplace(mtlconstantBufferResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
MTLRenderStages mtlRenderStages = GetRenderStages(srgResourcesVisInfo.m_constantDataStageMask);
|
||||
AZStd::pair <MTLResourceUsage,MTLRenderStages> key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages);
|
||||
uint16_t arrayIndex = resourcesToMakeResidentGraphics[key].m_resourceArrayLen++;
|
||||
resourcesToMakeResidentGraphics[key].m_resourceArray[arrayIndex] = mtlconstantBufferResource;
|
||||
AZStd::pair <MTLResourceUsage,MTLRenderStages> key = AZStd::make_pair(MTLResourceUsageRead, mtlRenderStages);
|
||||
resourcesToMakeResidentGraphics[key].emplace(mtlconstantBufferResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -440,16 +438,18 @@ namespace AZ
|
||||
//Call UseResource on all resources for Compute stage
|
||||
for (const auto& key : resourcesToMakeResidentCompute)
|
||||
{
|
||||
[static_cast<id<MTLComputeCommandEncoder>>(commandEncoder) useResources: key.second.m_resourceArray.data()
|
||||
count: key.second.m_resourceArrayLen
|
||||
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
|
||||
[static_cast<id<MTLComputeCommandEncoder>>(commandEncoder) useResources: &resourcesToProcessVec[0]
|
||||
count: resourcesToProcessVec.size()
|
||||
usage: key.first];
|
||||
}
|
||||
|
||||
//Call UseResource on all resources for Vertex and Fragment stages
|
||||
for (const auto& key : resourcesToMakeResidentGraphics)
|
||||
{
|
||||
[static_cast<id<MTLRenderCommandEncoder>>(commandEncoder) useResources: key.second.m_resourceArray.data()
|
||||
count: key.second.m_resourceArrayLen
|
||||
AZStd::vector<id <MTLResource>> resourcesToProcessVec(key.second.begin(), key.second.end());
|
||||
[static_cast<id<MTLRenderCommandEncoder>>(commandEncoder) useResources: &resourcesToProcessVec[0]
|
||||
count: resourcesToProcessVec.size()
|
||||
usage: key.first.first
|
||||
stages: key.first.second];
|
||||
}
|
||||
@@ -480,9 +480,9 @@ namespace AZ
|
||||
AZ_Assert(false, "Undefined Resource type");
|
||||
}
|
||||
}
|
||||
uint16_t arrayIndex = resourcesToMakeResidentMap[resourceUsage].m_resourceArrayLen++;
|
||||
|
||||
id<MTLResource> mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress<id<MTLResource>>();
|
||||
resourcesToMakeResidentMap[resourceUsage].m_resourceArray[arrayIndex] = mtlResourceToBind;
|
||||
resourcesToMakeResidentMap[resourceUsage].emplace(mtlResourceToBind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,9 +516,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZStd::pair <MTLResourceUsage, MTLRenderStages> key = AZStd::make_pair(resourceUsage, mtlRenderStages);
|
||||
uint16_t arrayIndex = resourcesToMakeResidentMap[key].m_resourceArrayLen++;
|
||||
id<MTLResource> mtlResourceToBind = resourceBindingData.m_resourcPtr->GetGpuAddress<id<MTLResource>>();
|
||||
resourcesToMakeResidentMap[key].m_resourceArray[arrayIndex] = mtlResourceToBind;
|
||||
resourcesToMakeResidentMap[key].emplace(mtlResourceToBind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,15 +120,10 @@ namespace AZ
|
||||
ResourceBindingsMap m_resourceBindings;
|
||||
|
||||
static const int MaxEntriesInArgTable = 31;
|
||||
struct MetalResourceArray
|
||||
{
|
||||
AZStd::array<id <MTLResource>, MaxEntriesInArgTable> m_resourceArray;
|
||||
uint16_t m_resourceArrayLen = 0;
|
||||
};
|
||||
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage
|
||||
using ComputeResourcesToMakeResidentMap = AZStd::unordered_map<MTLResourceUsage, MetalResourceArray>;
|
||||
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage
|
||||
using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map<AZStd::pair<MTLResourceUsage,MTLRenderStages>, MetalResourceArray>;
|
||||
//Map to cache all the resources based on the usage as we can batch all the resources for a given usage.
|
||||
using ComputeResourcesToMakeResidentMap = AZStd::unordered_map<MTLResourceUsage, AZStd::unordered_set<id <MTLResource>>>;
|
||||
//Map to cache all the resources based on the usage and shader stage as we can batch all the resources for a given usage/shader usage.
|
||||
using GraphicsResourcesToMakeResidentMap = AZStd::unordered_map<AZStd::pair<MTLResourceUsage,MTLRenderStages>, AZStd::unordered_set<id <MTLResource>>>;
|
||||
|
||||
void CollectResourcesForCompute(id<MTLCommandEncoder> encoder,
|
||||
const ResourceBindingsSet& resourceBindingData,
|
||||
|
||||
@@ -85,16 +85,36 @@ namespace AZ
|
||||
|
||||
uint64_t AsyncUploadQueue::QueueUpload(const RHI::BufferStreamRequest& uploadRequest)
|
||||
{
|
||||
uint64_t queueValue = m_uploadFence.Increment();
|
||||
Buffer& destBuffer = static_cast<Buffer&>(*uploadRequest.m_buffer);
|
||||
const MemoryView& destMemoryView = destBuffer.GetMemoryView();
|
||||
MTLStorageMode mtlStorageMode = destBuffer.GetMemoryView().GetStorageMode();
|
||||
RHI::BufferPool& bufferPool = static_cast<RHI::BufferPool&>(*destBuffer.GetPool());
|
||||
|
||||
// No need to use staging buffers since it's host memory.
|
||||
// We just map, copy and then unmap.
|
||||
if(mtlStorageMode == MTLStorageModeShared || mtlStorageMode == GetCPUGPUMemoryMode())
|
||||
{
|
||||
RHI::BufferMapRequest mapRequest;
|
||||
mapRequest.m_buffer = uploadRequest.m_buffer;
|
||||
mapRequest.m_byteCount = uploadRequest.m_byteCount;
|
||||
mapRequest.m_byteOffset = uploadRequest.m_byteOffset;
|
||||
RHI::BufferMapResponse mapResponse;
|
||||
bufferPool.MapBuffer(mapRequest, mapResponse);
|
||||
::memcpy(mapResponse.m_data, uploadRequest.m_sourceData, uploadRequest.m_byteCount);
|
||||
bufferPool.UnmapBuffer(*uploadRequest.m_buffer);
|
||||
if (uploadRequest.m_fenceToSignal)
|
||||
{
|
||||
uploadRequest.m_fenceToSignal->SignalOnCpu();
|
||||
}
|
||||
return m_uploadFence.GetPendingValue();
|
||||
}
|
||||
|
||||
const MemoryView& memoryView = static_cast<Buffer&>(*uploadRequest.m_buffer).GetMemoryView();
|
||||
RHI::Ptr<Memory> buffer = memoryView.GetMemory();
|
||||
|
||||
Fence* fenceToSignal = nullptr;
|
||||
uint64_t fenceToSignalValue = 0;
|
||||
|
||||
size_t byteCount = uploadRequest.m_byteCount;
|
||||
size_t byteOffset = memoryView.GetOffset() + uploadRequest.m_byteOffset;
|
||||
size_t byteOffset = destMemoryView.GetOffset() + uploadRequest.m_byteOffset;
|
||||
uint64_t queueValue = m_uploadFence.Increment();
|
||||
|
||||
const uint8_t* sourceData = reinterpret_cast<const uint8_t*>(uploadRequest.m_sourceData);
|
||||
|
||||
if (uploadRequest.m_fenceToSignal)
|
||||
@@ -125,11 +145,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [framePacket->m_mtlCommandBuffer blitCommandEncoder];
|
||||
[blitEncoder copyFromBuffer:framePacket->m_stagingResource
|
||||
sourceOffset:0
|
||||
toBuffer:buffer->GetGpuAddress<id<MTLBuffer>>()
|
||||
destinationOffset:byteOffset + pendingByteOffset
|
||||
size:bytesToCopy];
|
||||
[blitEncoder copyFromBuffer: framePacket->m_stagingResource
|
||||
sourceOffset: 0
|
||||
toBuffer: destMemoryView.GetGpuAddress<id<MTLBuffer>>()
|
||||
destinationOffset: byteOffset + pendingByteOffset
|
||||
size: bytesToCopy];
|
||||
[blitEncoder endEncoding];
|
||||
blitEncoder = nil;
|
||||
|
||||
|
||||
@@ -40,9 +40,8 @@ namespace AZ
|
||||
buffer->m_pendingResolves++;
|
||||
|
||||
uploadRequest.m_attachmentBuffer = buffer;
|
||||
uploadRequest.m_byteOffset = request.m_byteOffset;
|
||||
uploadRequest.m_byteOffset = buffer->GetMemoryView().GetOffset() + request.m_byteOffset;
|
||||
uploadRequest.m_stagingBuffer = stagingBuffer;
|
||||
uploadRequest.m_byteSize = request.m_byteCount;
|
||||
|
||||
return stagingBuffer->GetMemoryView().GetCpuAddress();
|
||||
}
|
||||
@@ -64,12 +63,15 @@ namespace AZ
|
||||
AZ_Assert(stagingBuffer, "Staging Buffer is null.");
|
||||
AZ_Assert(destBuffer, "Attachment Buffer is null.");
|
||||
|
||||
//Inform the GPU that the CPU has modified the staging buffer.
|
||||
Platform::SynchronizeBufferOnCPU(stagingBuffer->GetMemoryView().GetGpuAddress<id<MTLBuffer>>(), stagingBuffer->GetMemoryView().GetOffset(), stagingBuffer->GetMemoryView().GetSize());
|
||||
|
||||
RHI::CopyBufferDescriptor copyDescriptor;
|
||||
copyDescriptor.m_sourceBuffer = stagingBuffer;
|
||||
copyDescriptor.m_sourceOffset = 0;
|
||||
copyDescriptor.m_sourceOffset = stagingBuffer->GetMemoryView().GetOffset();
|
||||
copyDescriptor.m_destinationBuffer = destBuffer;
|
||||
copyDescriptor.m_destinationOffset = static_cast<uint32_t>(packet.m_byteOffset);
|
||||
copyDescriptor.m_size = static_cast<uint32_t>(packet.m_byteSize);
|
||||
copyDescriptor.m_size = stagingBuffer->GetMemoryView().GetSize();
|
||||
|
||||
commandList.Submit(RHI::CopyItem(copyDescriptor));
|
||||
device.QueueForRelease(stagingBuffer->GetMemoryView());
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace AZ
|
||||
Buffer* m_attachmentBuffer = nullptr;
|
||||
RHI::Ptr<Buffer> m_stagingBuffer;
|
||||
size_t m_byteOffset = 0;
|
||||
size_t m_byteSize = 0;
|
||||
};
|
||||
|
||||
AZStd::mutex m_uploadPacketsLock;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace AZ
|
||||
if (memoryView.IsValid())
|
||||
{
|
||||
heapMemoryUsage.m_residentInBytes += m_descriptor.m_pageSizeInBytes;
|
||||
memoryView.SetName("BufferPage");
|
||||
memoryView.SetName(AZStd::string::format("BufferPage_%s", AZ::Uuid::CreateRandom().ToString<AZStd::string>().c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user