mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-08 08:40:55 +00:00
Don't flush mapped memory in driver for detected coherent memory writes
This commit is contained in:
@@ -617,6 +617,7 @@ enum class VulkanChunk : uint32_t
|
||||
vkCmdSetDepthBoundsTestEnableEXT,
|
||||
vkCmdSetStencilTestEnableEXT,
|
||||
vkCmdSetStencilOpEXT,
|
||||
CoherentMapWrite,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user