mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-22 06:26:30 +00:00
Implement CopyTex2DMSToArray on vulkan for MS texture saving
* The reverse isn't implemented yet, so initial states of MS textures still can't be properly restored (although they could be saved).
This commit is contained in:
@@ -2428,8 +2428,8 @@ byte *GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
|
||||
texType = eGL_TEXTURE_2D_ARRAY;
|
||||
texname = tempTex;
|
||||
depth = 1;
|
||||
depth = samples;
|
||||
arraysize = samples;
|
||||
depth = arraysize * samples;
|
||||
arraysize = arraysize * samples;
|
||||
samples = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2552,6 +2552,7 @@ string ToStrHelper<false, VkResult>::Get(const VkResult &el)
|
||||
TOSTR_CASE_STRINGIZE(VK_ERROR_OUT_OF_DATE_KHR)
|
||||
TOSTR_CASE_STRINGIZE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)
|
||||
TOSTR_CASE_STRINGIZE(VK_ERROR_VALIDATION_FAILED_EXT)
|
||||
TOSTR_CASE_STRINGIZE(VK_ERROR_INVALID_SHADER_NV)
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
@@ -271,6 +271,12 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
m_PickPixelFB = VK_NULL_HANDLE;
|
||||
m_PickPixelRP = VK_NULL_HANDLE;
|
||||
|
||||
m_ArrayMSDescSetLayout = VK_NULL_HANDLE;
|
||||
m_ArrayMSPipeLayout = VK_NULL_HANDLE;
|
||||
m_ArrayMSDescSet = VK_NULL_HANDLE;
|
||||
m_Array2MSPipe = VK_NULL_HANDLE;
|
||||
m_MS2ArrayPipe = VK_NULL_HANDLE;
|
||||
|
||||
m_TextDescSetLayout = VK_NULL_HANDLE;
|
||||
m_TextPipeLayout = VK_NULL_HANDLE;
|
||||
m_TextDescSet = VK_NULL_HANDLE;
|
||||
@@ -650,7 +656,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
};
|
||||
|
||||
// declare a few more misc things that are needed on both paths
|
||||
VkDescriptorBufferInfo bufInfo[6];
|
||||
VkDescriptorBufferInfo bufInfo[7];
|
||||
RDCEraseEl(bufInfo);
|
||||
|
||||
vector<string> sources;
|
||||
@@ -1070,6 +1076,32 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
VkDescriptorSetLayoutBinding layoutBinding[] = {
|
||||
{
|
||||
0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL,
|
||||
},
|
||||
{
|
||||
1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, NULL,
|
||||
},
|
||||
{
|
||||
2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL,
|
||||
},
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = {
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
ARRAY_COUNT(layoutBinding),
|
||||
&layoutBinding[0],
|
||||
};
|
||||
|
||||
vkr = m_pDriver->vkCreateDescriptorSetLayout(dev, &descsetLayoutInfo, NULL,
|
||||
&m_ArrayMSDescSetLayout);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
VkDescriptorSetLayoutBinding layoutBinding[] = {
|
||||
{
|
||||
@@ -1229,6 +1261,11 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
vkr = m_pDriver->vkCreatePipelineLayout(dev, &pipeLayoutInfo, NULL, &m_CheckerboardPipeLayout);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
pipeLayoutInfo.pSetLayouts = &m_ArrayMSDescSetLayout;
|
||||
|
||||
vkr = m_pDriver->vkCreatePipelineLayout(dev, &pipeLayoutInfo, NULL, &m_ArrayMSPipeLayout);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
pipeLayoutInfo.pSetLayouts = &m_QuadDescSetLayout;
|
||||
|
||||
vkr = m_pDriver->vkCreatePipelineLayout(dev, &pipeLayoutInfo, NULL, &m_QuadResolvePipeLayout);
|
||||
@@ -1258,6 +1295,10 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
vkr = m_pDriver->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_CheckerboardDescSet);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
descSetAllocInfo.pSetLayouts = &m_ArrayMSDescSetLayout;
|
||||
vkr = m_pDriver->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_ArrayMSDescSet);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
descSetAllocInfo.pSetLayouts = &m_TexDisplayDescSetLayout;
|
||||
for(size_t i = 0; i < ARRAY_COUNT(m_TexDisplayDescSet); i++)
|
||||
{
|
||||
@@ -1315,6 +1356,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
|
||||
RDCCOMPILE_ASSERT(sizeof(TexDisplayUBOData) <= 128, "tex display size");
|
||||
|
||||
m_ArrayMSUBO.Create(driver, dev, 16, 1, 0);
|
||||
|
||||
string shaderSources[] = {
|
||||
GetEmbeddedResource(glsl_blit_vert), GetEmbeddedResource(glsl_checkerboard_frag),
|
||||
GetEmbeddedResource(glsl_texdisplay_frag), GetEmbeddedResource(glsl_mesh_vert),
|
||||
@@ -1322,13 +1365,13 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
GetEmbeddedResource(glsl_minmaxtile_comp), GetEmbeddedResource(glsl_minmaxresult_comp),
|
||||
GetEmbeddedResource(glsl_histogram_comp), GetEmbeddedResource(glsl_outline_frag),
|
||||
GetEmbeddedResource(glsl_quadresolve_frag), GetEmbeddedResource(glsl_quadwrite_frag),
|
||||
GetEmbeddedResource(glsl_mesh_comp),
|
||||
GetEmbeddedResource(glsl_mesh_comp), GetEmbeddedResource(glsl_ms2array_comp),
|
||||
};
|
||||
|
||||
SPIRVShaderStage shaderStages[] = {
|
||||
eSPIRVVertex, eSPIRVFragment, eSPIRVFragment, eSPIRVVertex, eSPIRVGeometry,
|
||||
eSPIRVFragment, eSPIRVCompute, eSPIRVCompute, eSPIRVCompute, eSPIRVFragment,
|
||||
eSPIRVFragment, eSPIRVFragment, eSPIRVCompute,
|
||||
eSPIRVFragment, eSPIRVFragment, eSPIRVCompute, eSPIRVCompute,
|
||||
};
|
||||
|
||||
enum shaderIdx
|
||||
@@ -1346,6 +1389,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
QUADRESOLVEFS,
|
||||
QUADWRITEFS,
|
||||
MESHCS,
|
||||
MS2ARRAYCS,
|
||||
NUM_SHADERS,
|
||||
};
|
||||
|
||||
@@ -1642,8 +1686,6 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheShaders = false;
|
||||
|
||||
{
|
||||
compPipeInfo.stage.module = module[MESHCS];
|
||||
compPipeInfo.layout = m_MeshPickLayout;
|
||||
@@ -1653,6 +1695,17 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
compPipeInfo.stage.module = module[MS2ARRAYCS];
|
||||
compPipeInfo.layout = m_ArrayMSPipeLayout;
|
||||
|
||||
vkr = m_pDriver->vkCreateComputePipelines(dev, VK_NULL_HANDLE, 1, &compPipeInfo, NULL,
|
||||
&m_MS2ArrayPipe);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
m_CacheShaders = false;
|
||||
|
||||
m_pDriver->vkDestroyRenderPass(dev, RGBA16RP, NULL);
|
||||
m_pDriver->vkDestroyRenderPass(dev, RGBA32RP, NULL);
|
||||
m_pDriver->vkDestroyRenderPass(dev, RGBA8RP, NULL);
|
||||
@@ -2062,6 +2115,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
m_OverdrawRampUBO.FillDescriptor(bufInfo[3]);
|
||||
m_MeshPickUBO.FillDescriptor(bufInfo[4]);
|
||||
m_MeshPickResult.FillDescriptor(bufInfo[5]);
|
||||
m_ArrayMSUBO.FillDescriptor(bufInfo[6]);
|
||||
|
||||
VkWriteDescriptorSet analysisSetWrites[] = {
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_CheckerboardDescSet), 0, 0, 1,
|
||||
@@ -2076,6 +2130,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, NULL, &bufInfo[4], NULL},
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_MeshPickDescSet), 3, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, NULL, &bufInfo[5], NULL},
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_ArrayMSDescSet), 2, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, NULL, &bufInfo[6], NULL},
|
||||
};
|
||||
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(analysisSetWrites), analysisSetWrites,
|
||||
@@ -2161,6 +2217,12 @@ VulkanDebugManager::~VulkanDebugManager()
|
||||
m_pDriver->vkDestroyImage(dev, m_PickPixelImage, NULL);
|
||||
m_pDriver->vkFreeMemory(dev, m_PickPixelImageMem, NULL);
|
||||
|
||||
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_ArrayMSDescSetLayout, NULL);
|
||||
m_pDriver->vkDestroyPipelineLayout(dev, m_ArrayMSPipeLayout, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_Array2MSPipe, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_MS2ArrayPipe, NULL);
|
||||
m_ArrayMSUBO.Destroy();
|
||||
|
||||
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_TextDescSetLayout, NULL);
|
||||
m_pDriver->vkDestroyPipelineLayout(dev, m_TextPipeLayout, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_TextPipeline[0], NULL);
|
||||
@@ -2762,6 +2824,127 @@ void VulkanDebugManager::CreateCustomShaderPipeline(ResourceId shader)
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::CopyTex2DMSToArray(VkImage destArray, VkImage srcMS, VkExtent3D extent,
|
||||
uint32_t layers, uint32_t samples, VkFormat fmt)
|
||||
{
|
||||
if(!m_pDriver->GetDeviceFeatures().shaderStorageImageMultisample ||
|
||||
!m_pDriver->GetDeviceFeatures().shaderStorageImageWriteWithoutFormat)
|
||||
return;
|
||||
|
||||
if(m_MS2ArrayPipe == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_Device;
|
||||
|
||||
VkResult vkr = VK_SUCCESS;
|
||||
|
||||
VkImageView srcView, destView;
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
srcMS,
|
||||
VK_IMAGE_VIEW_TYPE_2D,
|
||||
VK_FORMAT_UNDEFINED,
|
||||
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY},
|
||||
{
|
||||
VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
|
||||
uint32_t bs = GetByteSize(1, 1, 1, fmt, 0);
|
||||
|
||||
if(bs == 1)
|
||||
viewInfo.format = VK_FORMAT_R8_UINT;
|
||||
else if(bs == 2)
|
||||
viewInfo.format = VK_FORMAT_R16_UINT;
|
||||
else if(bs == 4)
|
||||
viewInfo.format = VK_FORMAT_R32_UINT;
|
||||
else if(bs == 8)
|
||||
viewInfo.format = VK_FORMAT_R32G32_UINT;
|
||||
else if(bs == 16)
|
||||
viewInfo.format = VK_FORMAT_R32G32B32A32_UINT;
|
||||
|
||||
if(viewInfo.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
RDCERR("Can't copy 2D to Array with format %s", ToStr::Get(fmt).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(IsStencilOnlyFormat(fmt))
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
else if(IsDepthOrStencilFormat(fmt))
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, NULL, &srcView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
viewInfo.image = destArray;
|
||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
|
||||
vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, NULL, &destView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkDescriptorImageInfo srcdesc = {0};
|
||||
srcdesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
srcdesc.imageView = srcView;
|
||||
srcdesc.sampler = Unwrap(m_PointSampler); // not used
|
||||
|
||||
VkDescriptorImageInfo destdesc = {0};
|
||||
destdesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
destdesc.imageView = destView;
|
||||
destdesc.sampler = Unwrap(m_PointSampler); // not used
|
||||
|
||||
VkWriteDescriptorSet writeSet[] = {
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_ArrayMSDescSet), 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc, NULL, NULL},
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_ArrayMSDescSet), 1, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &destdesc, NULL, NULL},
|
||||
};
|
||||
|
||||
ObjDisp(dev)->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL);
|
||||
|
||||
uint32_t *data = (uint32_t *)m_ArrayMSUBO.Map(NULL);
|
||||
*data = samples;
|
||||
m_ArrayMSUBO.Unmap();
|
||||
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
|
||||
|
||||
ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
|
||||
ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(m_MS2ArrayPipe));
|
||||
ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
Unwrap(m_ArrayMSPipeLayout), 0, 1,
|
||||
UnwrapPtr(m_ArrayMSDescSet), 0, NULL);
|
||||
|
||||
ObjDisp(cmd)->CmdDispatch(Unwrap(cmd), extent.width, extent.height, layers * samples);
|
||||
|
||||
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
|
||||
|
||||
// submit cmds and wait for idle so we can readback
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
|
||||
ObjDisp(dev)->DestroyImageView(Unwrap(dev), srcView, NULL);
|
||||
ObjDisp(dev)->DestroyImageView(Unwrap(dev), destView, NULL);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::CopyArrayToTex2DMS(VkImage destMS, VkImage srcArray, VkExtent3D extent,
|
||||
uint32_t layers, uint32_t samples, VkFormat fmt)
|
||||
{
|
||||
if(!m_pDriver->GetDeviceFeatures().shaderStorageImageMultisample ||
|
||||
!m_pDriver->GetDeviceFeatures().shaderStorageImageWriteWithoutFormat)
|
||||
return;
|
||||
|
||||
if(m_Array2MSPipe == VK_NULL_HANDLE)
|
||||
return;
|
||||
}
|
||||
|
||||
FloatVector VulkanDebugManager::InterpretVertex(byte *data, uint32_t vert, const MeshDisplay &cfg,
|
||||
byte *end, bool &valid)
|
||||
{
|
||||
|
||||
@@ -126,6 +126,11 @@ public:
|
||||
uint32_t PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t x, uint32_t y, uint32_t w,
|
||||
uint32_t h);
|
||||
|
||||
void CopyTex2DMSToArray(VkImage destArray, VkImage srcMS, VkExtent3D extent, uint32_t layers,
|
||||
uint32_t samples, VkFormat fmt);
|
||||
void CopyArrayToTex2DMS(VkImage destMS, VkImage srcArray, VkExtent3D extent, uint32_t layers,
|
||||
uint32_t samples, VkFormat fmt);
|
||||
|
||||
void CreateCustomShaderTex(uint32_t width, uint32_t height, uint32_t mip);
|
||||
void CreateCustomShaderPipeline(ResourceId shader);
|
||||
|
||||
@@ -229,6 +234,13 @@ public:
|
||||
VkFramebuffer m_PickPixelFB;
|
||||
VkRenderPass m_PickPixelRP;
|
||||
|
||||
VkDescriptorSetLayout m_ArrayMSDescSetLayout;
|
||||
VkPipelineLayout m_ArrayMSPipeLayout;
|
||||
VkDescriptorSet m_ArrayMSDescSet;
|
||||
VkPipeline m_Array2MSPipe;
|
||||
VkPipeline m_MS2ArrayPipe;
|
||||
GPUBuffer m_ArrayMSUBO;
|
||||
|
||||
VkDescriptorSetLayout m_TextDescSetLayout;
|
||||
VkPipelineLayout m_TextPipeLayout;
|
||||
VkDescriptorSet m_TextDescSet;
|
||||
|
||||
@@ -4928,7 +4928,109 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m
|
||||
else if(wasms)
|
||||
{
|
||||
// copy/expand multisampled live texture to array readback texture
|
||||
RDCUNIMPLEMENTED("Saving multisampled textures directly as arrays");
|
||||
|
||||
// multiply array layers by sample count
|
||||
uint32_t numSamples = (uint32_t)imInfo.samples;
|
||||
imCreateInfo.arrayLayers *= numSamples;
|
||||
imCreateInfo.mipLevels = 1;
|
||||
imCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imCreateInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
imCreateInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
|
||||
// create resolve texture
|
||||
vt->CreateImage(Unwrap(dev), &imCreateInfo, NULL, &tmpImage);
|
||||
|
||||
VkMemoryRequirements mrq = {0};
|
||||
vt->GetImageMemoryRequirements(Unwrap(dev), tmpImage, &mrq);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, mrq.size,
|
||||
m_pDriver->GetGPULocalMemoryIndex(mrq.memoryTypeBits),
|
||||
};
|
||||
|
||||
vkr = vt->AllocateMemory(Unwrap(dev), &allocInfo, NULL, &tmpMemory);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
vkr = vt->BindImageMemory(Unwrap(dev), tmpImage, tmpMemory, 0);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkImageMemoryBarrier srcimBarrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
srcImage,
|
||||
{srcAspectMask, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}};
|
||||
|
||||
VkImageMemoryBarrier dstimBarrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
0,
|
||||
0, // MULTIDEVICE - need to actually pick the right queue family here maybe?
|
||||
tmpImage,
|
||||
{srcAspectMask, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}};
|
||||
|
||||
// ensure all previous writes have completed
|
||||
srcimBarrier.srcAccessMask = VK_ACCESS_ALL_WRITE_BITS;
|
||||
// before we go copying to array
|
||||
srcimBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
for(size_t si = 0; si < layouts.subresourceStates.size(); si++)
|
||||
{
|
||||
srcimBarrier.subresourceRange = layouts.subresourceStates[si].subresourceRange;
|
||||
srcimBarrier.oldLayout = layouts.subresourceStates[si].newLayout;
|
||||
DoPipelineBarrier(cmd, 1, &srcimBarrier);
|
||||
}
|
||||
|
||||
srcimBarrier.oldLayout = srcimBarrier.newLayout;
|
||||
|
||||
srcimBarrier.srcAccessMask = 0;
|
||||
srcimBarrier.dstAccessMask = 0;
|
||||
|
||||
// move tmp image into transfer destination layout
|
||||
DoPipelineBarrier(cmd, 1, &dstimBarrier);
|
||||
|
||||
vkr = vt->EndCommandBuffer(Unwrap(cmd));
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
// expand multisamples out to array
|
||||
GetDebugManager()->CopyTex2DMSToArray(tmpImage, srcImage, imCreateInfo.extent,
|
||||
imCreateInfo.arrayLayers, numSamples, imCreateInfo.format);
|
||||
|
||||
// fetch a new command buffer for copy & readback
|
||||
cmd = m_pDriver->GetNextCmd();
|
||||
|
||||
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
srcimBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
// image layout back to normal
|
||||
for(size_t si = 0; si < layouts.subresourceStates.size(); si++)
|
||||
{
|
||||
srcimBarrier.subresourceRange = layouts.subresourceStates[si].subresourceRange;
|
||||
srcimBarrier.newLayout = layouts.subresourceStates[si].newLayout;
|
||||
srcimBarrier.dstAccessMask = MakeAccessMask(srcimBarrier.newLayout);
|
||||
DoPipelineBarrier(cmd, 1, &srcimBarrier);
|
||||
}
|
||||
|
||||
// wait for copy to finish before copy to buffer
|
||||
dstimBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
dstimBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
dstimBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
dstimBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &dstimBarrier);
|
||||
|
||||
srcImage = tmpImage;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier srcimBarrier = {
|
||||
|
||||
@@ -208,6 +208,19 @@ bool IsDepthOrStencilFormat(VkFormat f)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsDepthAndStencilFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT: return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsStencilFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
@@ -222,19 +235,6 @@ bool IsStencilFormat(VkFormat f)
|
||||
return false;
|
||||
}
|
||||
|
||||
VkFormat GetDepthOnlyFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT: return VK_FORMAT_D16_UNORM;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool IsDepthOnlyFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
@@ -360,6 +360,118 @@ bool IsSIntFormat(VkFormat f)
|
||||
return false;
|
||||
}
|
||||
|
||||
VkFormat GetDepthOnlyFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT: return VK_FORMAT_D16_UNORM;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
VkFormat GetUIntTypedFormat(VkFormat f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
case VK_FORMAT_R8_SNORM:
|
||||
case VK_FORMAT_R8_USCALED:
|
||||
case VK_FORMAT_R8_SSCALED:
|
||||
case VK_FORMAT_R8_SINT:
|
||||
case VK_FORMAT_R8_SRGB: return VK_FORMAT_R8_UINT;
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
case VK_FORMAT_R8G8_SNORM:
|
||||
case VK_FORMAT_R8G8_USCALED:
|
||||
case VK_FORMAT_R8G8_SSCALED:
|
||||
case VK_FORMAT_R8G8_SINT:
|
||||
case VK_FORMAT_R8G8_SRGB: return VK_FORMAT_R8G8_UINT;
|
||||
case VK_FORMAT_R8G8B8_UNORM:
|
||||
case VK_FORMAT_R8G8B8_SNORM:
|
||||
case VK_FORMAT_R8G8B8_USCALED:
|
||||
case VK_FORMAT_R8G8B8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8_SINT:
|
||||
case VK_FORMAT_R8G8B8_SRGB: return VK_FORMAT_R8G8B8_UINT;
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_R8G8B8A8_SNORM:
|
||||
case VK_FORMAT_R8G8B8A8_USCALED:
|
||||
case VK_FORMAT_R8G8B8A8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8A8_SINT:
|
||||
case VK_FORMAT_R8G8B8A8_SRGB: return VK_FORMAT_R8G8B8A8_UINT;
|
||||
case VK_FORMAT_B8G8R8_UNORM:
|
||||
case VK_FORMAT_B8G8R8_SNORM:
|
||||
case VK_FORMAT_B8G8R8_USCALED:
|
||||
case VK_FORMAT_B8G8R8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8_SINT:
|
||||
case VK_FORMAT_B8G8R8_SRGB: return VK_FORMAT_B8G8R8_UINT;
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SNORM:
|
||||
case VK_FORMAT_B8G8R8A8_USCALED:
|
||||
case VK_FORMAT_B8G8R8A8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8A8_SINT:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB: return VK_FORMAT_B8G8R8A8_UINT;
|
||||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32: return VK_FORMAT_A8B8G8R8_UINT_PACK32;
|
||||
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SINT_PACK32: return VK_FORMAT_A2R10G10B10_UINT_PACK32;
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SINT_PACK32: return VK_FORMAT_A2B10G10R10_UINT_PACK32;
|
||||
case VK_FORMAT_R16_UNORM:
|
||||
case VK_FORMAT_R16_SNORM:
|
||||
case VK_FORMAT_R16_USCALED:
|
||||
case VK_FORMAT_R16_SSCALED:
|
||||
case VK_FORMAT_R16_SINT: return VK_FORMAT_R16_UINT;
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
case VK_FORMAT_R16G16_SNORM:
|
||||
case VK_FORMAT_R16G16_USCALED:
|
||||
case VK_FORMAT_R16G16_SSCALED:
|
||||
case VK_FORMAT_R16G16_SINT: return VK_FORMAT_R16G16_UINT;
|
||||
case VK_FORMAT_R16G16B16_UNORM:
|
||||
case VK_FORMAT_R16G16B16_SNORM:
|
||||
case VK_FORMAT_R16G16B16_USCALED:
|
||||
case VK_FORMAT_R16G16B16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16_SINT: return VK_FORMAT_R16G16B16_UINT;
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
case VK_FORMAT_R16G16B16A16_SNORM:
|
||||
case VK_FORMAT_R16G16B16A16_USCALED:
|
||||
case VK_FORMAT_R16G16B16A16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16A16_SINT: return VK_FORMAT_R16G16B16A16_UINT;
|
||||
case VK_FORMAT_R32_SINT:
|
||||
case VK_FORMAT_R32_SFLOAT: return VK_FORMAT_R32_UINT;
|
||||
case VK_FORMAT_R32G32_SINT:
|
||||
case VK_FORMAT_R32G32_SFLOAT: return VK_FORMAT_R32G32_UINT;
|
||||
case VK_FORMAT_R32G32B32_SINT:
|
||||
case VK_FORMAT_R32G32B32_SFLOAT: return VK_FORMAT_R32G32B32_UINT;
|
||||
case VK_FORMAT_R32G32B32A32_SINT:
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT: return VK_FORMAT_R32G32B32A32_UINT;
|
||||
case VK_FORMAT_R64_SINT:
|
||||
case VK_FORMAT_R64_SFLOAT: return VK_FORMAT_R64_UINT;
|
||||
case VK_FORMAT_R64G64_SINT:
|
||||
case VK_FORMAT_R64G64_SFLOAT: return VK_FORMAT_R64G64_UINT;
|
||||
case VK_FORMAT_R64G64B64_SINT:
|
||||
case VK_FORMAT_R64G64B64_SFLOAT: return VK_FORMAT_R64G64B64_UINT;
|
||||
case VK_FORMAT_R64G64B64A64_SINT:
|
||||
case VK_FORMAT_R64G64B64A64_SFLOAT: return VK_FORMAT_R64G64B64A64_UINT;
|
||||
case VK_FORMAT_S8_UINT: return VK_FORMAT_S8_UINT;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip)
|
||||
{
|
||||
uint32_t w = RDCMAX(Width >> mip, 1U);
|
||||
|
||||
@@ -1066,6 +1066,7 @@ struct ImageLayouts
|
||||
|
||||
bool IsBlockFormat(VkFormat f);
|
||||
bool IsDepthOrStencilFormat(VkFormat f);
|
||||
bool IsDepthAndStencilFormat(VkFormat f);
|
||||
bool IsDepthOnlyFormat(VkFormat f);
|
||||
bool IsStencilFormat(VkFormat f);
|
||||
bool IsStencilOnlyFormat(VkFormat f);
|
||||
@@ -1074,5 +1075,6 @@ bool IsUIntFormat(VkFormat f);
|
||||
bool IsSIntFormat(VkFormat f);
|
||||
|
||||
VkFormat GetDepthOnlyFormat(VkFormat f);
|
||||
VkFormat GetUIntTypedFormat(VkFormat f);
|
||||
|
||||
uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip);
|
||||
|
||||
@@ -933,6 +933,13 @@ bool WrappedVulkan::Serialise_vkCreateDevice(Serialiser *localSerialiser,
|
||||
else
|
||||
RDCWARN("vertexPipelineStoresAndAtomics = false, output mesh data will not be available");
|
||||
|
||||
if(availFeatures.shaderStorageImageWriteWithoutFormat)
|
||||
enabledFeatures.shaderStorageImageWriteWithoutFormat = true;
|
||||
else
|
||||
RDCWARN(
|
||||
"shaderStorageImageWriteWithoutFormat = false, save/load from 2DMS textures will not be "
|
||||
"possible");
|
||||
|
||||
uint32_t numExts = 0;
|
||||
|
||||
VkResult vkr =
|
||||
|
||||
@@ -988,6 +988,10 @@ bool WrappedVulkan::Serialise_vkCreateImage(Serialiser *localSerialiser, VkDevic
|
||||
info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
// ensure we can cast multisampled images, for copying to arrays
|
||||
if((int)info.samples > 1)
|
||||
info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
|
||||
VkResult ret = ObjDisp(device)->CreateImage(Unwrap(device), &info, NULL, &img);
|
||||
|
||||
info.usage = origusage;
|
||||
|
||||
Reference in New Issue
Block a user