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:
baldurk
2016-07-22 14:16:53 +02:00
parent 5b74d2f90a
commit 75bc04fcd0
9 changed files with 444 additions and 21 deletions
+2 -2
View File
@@ -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;
}
+1
View File
@@ -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;
}
+188 -5
View File
@@ -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)
{
+12
View File
@@ -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;
+103 -1
View File
@@ -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 = {
+125 -13
View File
@@ -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);
+2
View File
@@ -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;