Don't flush mapped memory in driver for detected coherent memory writes

This commit is contained in:
baldurk
2020-07-31 17:20:25 +01:00
parent 351687eb87
commit 39431bb83f
8 changed files with 69 additions and 10 deletions
+1
View File
@@ -617,6 +617,7 @@ enum class VulkanChunk : uint32_t
vkCmdSetDepthBoundsTestEnableEXT,
vkCmdSetStencilTestEnableEXT,
vkCmdSetStencilOpEXT,
CoherentMapWrite,
Max,
};
+1
View File
@@ -2720,6 +2720,7 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
case VulkanChunk::vkUnmapMemory:
return Serialise_vkUnmapMemory(ser, VK_NULL_HANDLE, VK_NULL_HANDLE);
case VulkanChunk::vkFlushMappedMemoryRanges:
case VulkanChunk::CoherentMapWrite:
return Serialise_vkFlushMappedMemoryRanges(ser, VK_NULL_HANDLE, 0, NULL);
case VulkanChunk::vkCreateCommandPool:
return Serialise_vkCreateCommandPool(ser, VK_NULL_HANDLE, NULL, NULL, NULL);
+4
View File
@@ -680,6 +680,10 @@ private:
// All IDs are original IDs, not live.
VulkanRenderState m_RenderState;
// an internal structure used to differentiate forced vkFlushMappedMemoryRanges due to coherent
// map writes from real calls to vkFlushMappedMemoryRanges
VkBaseInStructure internalMemoryFlushMarker = {};
bool InRerecordRange(ResourceId cmdid);
bool HasRerecordCmdBuf(ResourceId cmdid);
bool ShouldUpdateRenderState(ResourceId cmdid, bool forcePrimary = false);
+2 -1
View File
@@ -28,7 +28,7 @@
template <>
rdcstr DoStringise(const VulkanChunk &el)
{
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1152, "Chunks changed without updating names");
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1153, "Chunks changed without updating names");
BEGIN_ENUM_STRINGISE(VulkanChunk)
{
@@ -184,6 +184,7 @@ rdcstr DoStringise(const VulkanChunk &el)
STRINGISE_ENUM_CLASS(vkCmdSetDepthBoundsTestEnableEXT);
STRINGISE_ENUM_CLASS(vkCmdSetStencilTestEnableEXT);
STRINGISE_ENUM_CLASS(vkCmdSetStencilOpEXT);
STRINGISE_ENUM_CLASS_NAMED(CoherentMapWrite, "Internal: Coherent Mapped Memory Write")
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
}
END_ENUM_STRINGISE()
@@ -1137,9 +1137,13 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
{
RDCLOG("Persistent map flush forced for %s (%llu -> %llu)",
ToStr(record->GetResourceID()).c_str(), (uint64_t)diffStart, (uint64_t)diffEnd);
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, NULL,
(VkDeviceMemory)(uint64_t)record->Resource,
state.mapOffset + diffStart, diffEnd - diffStart};
VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
&internalMemoryFlushMarker,
(VkDeviceMemory)(uint64_t)record->Resource,
state.mapOffset + diffStart,
diffEnd - diffStart,
};
vkFlushMappedMemoryRanges(dev, 1, &range);
state.mapFlushed = false;
}
@@ -840,8 +840,24 @@ VkResult WrappedVulkan::vkFlushMappedMemoryRanges(VkDevice device, uint32_t memR
}
VkResult ret;
SERIALISE_TIME_CALL(
ret = ObjDisp(device)->FlushMappedMemoryRanges(Unwrap(device), memRangeCount, unwrapped));
bool internalFlush = false;
// don't call the driver for a fake coherent map flush
if(memRangeCount == 1 && pMemRanges->pNext == &internalMemoryFlushMarker)
{
ret = VK_SUCCESS;
internalFlush = true;
// for simplicity we set the pNext to NULL after we've seen our internal marker. We can safely
// modify this because it's a temporary variable in the calling stackframe
VkMappedMemoryRange *range = (VkMappedMemoryRange *)pMemRanges;
range->pNext = NULL;
}
else
{
SERIALISE_TIME_CALL(
ret = ObjDisp(device)->FlushMappedMemoryRanges(Unwrap(device), memRangeCount, unwrapped));
}
if(IsCaptureMode(m_State))
{
@@ -857,7 +873,8 @@ VkResult WrappedVulkan::vkFlushMappedMemoryRanges(VkDevice device, uint32_t memR
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkFlushMappedMemoryRanges);
SCOPED_SERIALISE_CHUNK(internalFlush ? VulkanChunk::CoherentMapWrite
: VulkanChunk::vkFlushMappedMemoryRanges);
Serialise_vkFlushMappedMemoryRanges(ser, device, 1, pMemRanges + i);
m_FrameCaptureRecord->AddChunk(scope.Get());
+23 -2
View File
@@ -58,10 +58,11 @@ RD_TEST(VK_Misaligned_Dirty, VulkanGraphicsTest)
const float val = 2.0f / 3.0f;
const DefaultA2V tri[3] = {
const DefaultA2V tri[4] = {
{Vec3f(-val, -val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
{Vec3f(0.0f, val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
{Vec3f(val, -val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
{},
};
AllocatedBuffer vb(this, vkh::BufferCreateInfo(sizeof(tri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
@@ -77,10 +78,28 @@ RD_TEST(VK_Misaligned_Dirty, VulkanGraphicsTest)
copy_src.upload(tri);
float *mapped = (float *)(copy_src.map() + sizeof(DefaultA2V) * 3);
float counter = 0;
while(Running())
{
mapped[2] = counter;
counter += 1.0f;
VkCommandBuffer cmd = GetCommandBuffer();
// create a dummy submit which uses the memory. This will serialise the whole memory contents
// (we don't create reference data until after this)
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
vkCmdUpdateBuffer(cmd, copy_src.buffer, sizeof(Vec3f), sizeof(Vec4f), &tri[0].col);
vkEndCommandBuffer(cmd);
Submit(0, 2, {cmd});
mapped[2] = counter;
counter += 1.0f;
cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
VkImage swapimg =
@@ -112,11 +131,13 @@ RD_TEST(VK_Misaligned_Dirty, VulkanGraphicsTest)
vkEndCommandBuffer(cmd);
Submit(0, 1, {cmd});
Submit(1, 2, {cmd});
Present();
}
copy_src.unmap();
return 0;
}
};
+11 -1
View File
@@ -5,8 +5,13 @@ import rdtest
class VK_Misaligned_Dirty(rdtest.TestCase):
demos_test_name = 'VK_Misaligned_Dirty'
def get_capture_options(self):
opts = rdtest.TestCase.get_capture_options(self)
opts.apiValidation = True
return opts
def get_replay_options(self):
opts = rd.ReplayOptions()
opts = rdtest.TestCase.get_replay_options(self)
# Set a balanced optimisation level to ensure that written ranges are cleared instead of being either restored
# or ignored
opts.optimisation = rd.ReplayOptimisationLevel.Balanced
@@ -19,6 +24,11 @@ class VK_Misaligned_Dirty(rdtest.TestCase):
self.controller.SetFrameEvent(draw.eventId, False)
self.check(len(self.controller.GetFrameInfo().debugMessages) == 0)
self.check(len(self.controller.GetDebugMessages()) == 0)
rdtest.log.success("No debug messages found")
pipe: rd.PipeState = self.controller.GetPipelineState()
postvs_data = self.get_postvs(draw, rd.MeshDataStage.VSOut, 0, draw.numIndices)