Refactor vulkan PostVS fetch to use compute instead of vertex stores

* Mobile chips are lacking in features, particularly
  vertexPipelineStoresAndAtomics which is needed to manually emulate
  stream-out with shader patching.
* Instead we change to transform the vertex shader into a compute shader
  and dispatch it to manually fetch the vertex inputs, run the original
  shader, and store the resulting outputs.
This commit is contained in:
baldurk
2018-01-16 20:12:07 +00:00
parent 6f38462761
commit 654fa1bb6c
6 changed files with 1012 additions and 394 deletions
+15 -2
View File
@@ -1337,8 +1337,20 @@ void VulkanReplay::CreateResources()
WrappedVulkan *driver = m_pDriver;
CREATE_OBJECT(m_MeshFetchDescSetLayout,
{{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL}});
CREATE_OBJECT(
m_MeshFetchDescSetLayout,
{
// output buffer
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, NULL},
// index buffer (if needed)
{1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, NULL},
// vertex buffers (float type)
{2, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16, VK_SHADER_STAGE_COMPUTE_BIT, NULL},
// vertex buffers (uint32_t type)
{3, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16, VK_SHADER_STAGE_COMPUTE_BIT, NULL},
// vertex buffers (int32_t type)
{4, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16, VK_SHADER_STAGE_COMPUTE_BIT, NULL},
});
CREATE_OBJECT(m_MeshFetchDescSet, m_General.DescriptorPool, m_MeshFetchDescSetLayout);
}
@@ -1367,6 +1379,7 @@ void VulkanReplay::GeneralMisc::Init(WrappedVulkan *driver, VkDescriptorPool des
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 32},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 128},
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 64},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 32},
};
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -132,13 +132,15 @@ struct VulkanPostVSData
VkDeviceMemory bufmem;
VkPrimitiveTopology topo;
int32_t baseVertex;
uint32_t numVerts;
uint32_t vertStride;
uint32_t instStride;
bool useIndices;
VkBuffer idxBuf;
VkDeviceMemory idxBufMem;
ResourceId idxBuf;
VkDeviceSize idxOffset;
VkIndexType idxFmt;
bool hasPosOut;
+1 -1
View File
@@ -276,7 +276,7 @@ void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding bindin
// only set push constant ranges that the layout uses
for(size_t i = 0; i < pushRanges.size(); i++)
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags,
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), VK_SHADER_STAGE_COMPUTE_BIT,
pushRanges[i].offset, pushRanges[i].size,
pushconsts + pushRanges[i].offset);
@@ -244,6 +244,17 @@ bool WrappedVulkan::Serialise_vkCreateDescriptorSetLayout(
{
VkDescriptorSetLayout layout = VK_NULL_HANDLE;
VkDescriptorSetLayoutBinding *bindings = (VkDescriptorSetLayoutBinding *)CreateInfo.pBindings;
// ensure any bindings available to the vertex shader are also available to compute. This is
// valid and changes nothing, but means we don't have to create a duplicate parallel 'computer
// friendly' descriptor set layout and pipeline layout.
for(uint32_t i = 0; i < CreateInfo.bindingCount; i++)
{
if(bindings[i].stageFlags & VK_SHADER_STAGE_VERTEX_BIT)
bindings[i].stageFlags |= VK_SHADER_STAGE_COMPUTE_BIT;
}
VkDescriptorSetLayoutCreateInfo unwrapped = UnwrapInfo(&CreateInfo);
VkResult ret =
ObjDisp(device)->CreateDescriptorSetLayout(Unwrap(device), &unwrapped, NULL, &layout);
@@ -1096,11 +1096,6 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
"robustBufferAccess = false, out of bounds access due to bugs in application or "
"RenderDoc may cause crashes");
if(availFeatures.vertexPipelineStoresAndAtomics)
enabledFeatures.vertexPipelineStoresAndAtomics = true;
else
RDCWARN("vertexPipelineStoresAndAtomics = false, output mesh data will not be available");
if(availFeatures.shaderStorageImageWriteWithoutFormat)
enabledFeatures.shaderStorageImageWriteWithoutFormat = true;
else