diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp
index c8919dafb3..0bf9889d40 100644
--- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp
+++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp
@@ -432,14 +432,13 @@ void D3D12GSRender::FillVertexShaderConstantsBuffer()
 		memcpy((char*)vertexConstantShadowCopy + offset, vector, 4 * sizeof(float));
 	}
 
-	size_t constantBuffersHeapOffset = m_perFrameStorage.m_constantsBuffersHeapFreeSpace;
-	// 65536 alignment
-	constantBuffersHeapOffset = (constantBuffersHeapOffset + 65536 - 1) & ~65535;
+	assert(m_constantsData.canAlloc(512 * 4 * sizeof(float)));
+	size_t heapOffset = m_constantsData.alloc(512 * 4 * sizeof(float));
 
 	ID3D12Resource *constantsBuffer;
 	check(m_device->CreatePlacedResource(
-		m_perFrameStorage.m_constantsBuffersHeap,
-		constantBuffersHeapOffset,
+		m_constantsData.m_heap,
+		heapOffset,
 		&getBufferResourceDesc(512 * 4 * sizeof(float)),
 		D3D12_RESOURCE_STATE_GENERIC_READ,
 		nullptr,
@@ -457,8 +456,7 @@ void D3D12GSRender::FillVertexShaderConstantsBuffer()
 	D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_perFrameStorage.m_constantsBufferDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
 	Handle.ptr += m_perFrameStorage.m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
 	m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
-	m_perFrameStorage.m_constantsBuffersHeapFreeSpace = constantBuffersHeapOffset + 512 * 4 * sizeof(float);
-	m_perFrameStorage.m_inflightResources.push_back(constantsBuffer);
+	m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, 512 * 4 * sizeof(float), constantsBuffer));
 }
 
 void D3D12GSRender::FillPixelShaderConstantsBuffer()
@@ -469,14 +467,13 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer()
 	// Multiple of 256 never 0
 	bufferSize = (bufferSize + 255) & ~255;
 
-	size_t constantBuffersHeapOffset = m_perFrameStorage.m_constantsBuffersHeapFreeSpace;
-	// 65536 alignment
-	constantBuffersHeapOffset = (constantBuffersHeapOffset + 65536 - 1) & ~65535;
+	assert(m_constantsData.canAlloc(bufferSize));
+	size_t heapOffset = m_constantsData.alloc(bufferSize);
 
 	ID3D12Resource *constantsBuffer;
 	check(m_device->CreatePlacedResource(
-		m_perFrameStorage.m_constantsBuffersHeap,
-		constantBuffersHeapOffset,
+		m_constantsData.m_heap,
+		heapOffset,
 		&getBufferResourceDesc(bufferSize),
 		D3D12_RESOURCE_STATE_GENERIC_READ,
 		nullptr,
@@ -532,8 +529,7 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer()
 	D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_perFrameStorage.m_constantsBufferDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
 	Handle.ptr += m_perFrameStorage.m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
 	m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
-	m_perFrameStorage.m_constantsBuffersHeapFreeSpace = constantBuffersHeapOffset + bufferSize;
-	m_perFrameStorage.m_inflightResources.push_back(constantsBuffer);
+	m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, bufferSize, constantsBuffer));
 }
 
 
diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp
index 84edfde30f..4ecec2a8a3 100644
--- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp
+++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp
@@ -84,7 +84,6 @@ void D3D12GSRender::ResourceStorage::Reset()
 	m_vertexIndexBuffersHeapFreeSpace = 0;
 	m_constantsBufferIndex = 0;
 	m_currentScaleOffsetBufferIndex = 0;
-	m_constantsBuffersHeapFreeSpace = 0;
 	m_currentStorageOffset = 0;
 	m_currentTextureIndex = 0;
 
@@ -113,7 +112,6 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
 	vertexBufferHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
 	vertexBufferHeapDesc.Properties.Type = D3D12_HEAP_TYPE_UPLOAD;
 	check(device->CreateHeap(&vertexBufferHeapDesc, IID_PPV_ARGS(&m_vertexIndexBuffersHeap)));
-	check(device->CreateHeap(&vertexBufferHeapDesc, IID_PPV_ARGS(&m_constantsBuffersHeap)));
 
 	D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
 	descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
@@ -156,7 +154,6 @@ void D3D12GSRender::ResourceStorage::Release()
 
 	m_constantsBufferDescriptorsHeap->Release();
 	m_scaleOffsetDescriptorHeap->Release();
-	m_constantsBuffersHeap->Release();
 	m_vertexIndexBuffersHeap->Release();
 	for (auto tmp : m_inflightResources)
 		tmp->Release();
diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h
index d563eb702a..b6ecd42d1e 100644
--- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h
+++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h
@@ -91,8 +91,6 @@ private:
 		ID3D12Heap *m_vertexIndexBuffersHeap;
 
 		// Constants storage
-		ID3D12Heap *m_constantsBuffersHeap;
-		size_t m_constantsBuffersHeapFreeSpace;
 		ID3D12DescriptorHeap *m_constantsBufferDescriptorsHeap;
 		size_t m_constantsBufferIndex;
 		ID3D12DescriptorHeap *m_scaleOffsetDescriptorHeap;
@@ -113,6 +111,7 @@ private:
 
 	ResourceStorage m_perFrameStorage;
 
+	// Constants storage
 	DataHeap m_constantsData;
 
 	struct UAVHeap