Implement support for VK_EXT_robustness2

This commit is contained in:
baldurk
2020-05-28 15:54:36 +01:00
parent c41b72edb7
commit 1cd32d3f61
19 changed files with 448 additions and 88 deletions
+6 -3
View File
@@ -976,7 +976,7 @@ FrameRefType GetRefType(VkDescriptorType descType)
return eFrameRef_Read;
}
bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement)
bool IsValid(bool allowNULLDescriptors, const VkWriteDescriptorSet &write, uint32_t arrayElement)
{
if(write.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
return true;
@@ -986,10 +986,10 @@ bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement)
// case they can be garbage and we must ignore them based on the descriptorType
if(write.pTexelBufferView)
return write.pTexelBufferView[arrayElement] != VK_NULL_HANDLE;
return allowNULLDescriptors ? true : write.pTexelBufferView[arrayElement] != VK_NULL_HANDLE;
if(write.pBufferInfo)
return write.pBufferInfo[arrayElement].buffer != VK_NULL_HANDLE;
return allowNULLDescriptors ? true : write.pBufferInfo[arrayElement].buffer != VK_NULL_HANDLE;
if(write.pImageInfo)
{
@@ -1000,6 +1000,9 @@ bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement)
// but all types that aren't just a sampler need an image
bool needImage = (write.descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER);
if(allowNULLDescriptors)
needImage = false;
if(needSampler && write.pImageInfo[arrayElement].sampler == VK_NULL_HANDLE)
return false;
+5 -1
View File
@@ -450,7 +450,7 @@ DECLARE_REFLECTION_STRUCT(DescriptorSetSlotBufferInfo);
DECLARE_REFLECTION_STRUCT(DescriptorSetSlotImageInfo);
DECLARE_REFLECTION_STRUCT(DescriptorSetSlot);
bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement);
bool IsValid(bool allowNULLDescriptors, const VkWriteDescriptorSet &write, uint32_t arrayElement);
#define NUM_VK_IMAGE_ASPECTS 4
#define VK_ACCESS_ALL_READ_BITS \
@@ -835,6 +835,8 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProperties2);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProtectedMemoryFeatures);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProtectedMemoryProperties);
DECLARE_REFLECTION_STRUCT(VkPhysicalDevicePushDescriptorPropertiesKHR);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceRobustness2FeaturesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceRobustness2PropertiesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceSampleLocationsPropertiesEXT);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceSamplerFilterMinmaxProperties);
DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceSamplerYcbcrConversionFeatures);
@@ -1129,6 +1131,8 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceProperties2);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryFeatures);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryProperties);
DECLARE_DESERIALISE_TYPE(VkPhysicalDevicePushDescriptorPropertiesKHR);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceRobustness2FeaturesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceRobustness2PropertiesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceSampleLocationsPropertiesEXT);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceSamplerFilterMinmaxProperties);
DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceSamplerYcbcrConversionFeatures);
+3
View File
@@ -859,6 +859,9 @@ static const VkExtensionProperties supportedExtensions[] = {
{
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, VK_EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION,
},
{
VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, VK_EXT_ROBUSTNESS_2_SPEC_VERSION,
},
{
VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, VK_EXT_SAMPLE_LOCATIONS_SPEC_VERSION,
},
+2
View File
@@ -399,6 +399,7 @@ private:
};
bool m_SeparateDepthStencil = false;
bool m_NULLDescriptorsAllowed = false;
PFN_vkSetDeviceLoaderData m_SetDeviceLoaderData;
@@ -1058,6 +1059,7 @@ public:
VkDeviceCreateInfo &createInfo, uint32_t &queueFamilyIndex);
bool SeparateDepthStencil() const { return m_SeparateDepthStencil; }
bool NULLDescriptorsAllowed() const { return m_NULLDescriptorsAllowed; }
VulkanRenderState &GetRenderState() { return m_RenderState; }
void SetDrawcallCB(VulkanDrawcallCallback *cb) { m_DrawcallCallback = cb; }
void SetSubmitChain(void *submitChain) { m_SubmitChain = submitChain; }
+1 -1
View File
@@ -2212,7 +2212,7 @@ void VulkanReplay::PatchReservedDescriptors(const VulkanStatePipeline &pipe,
for(uint32_t w = 0; w < bind.descriptorCount; w++)
{
// if this write is valid, we increment the descriptor count and continue
if(IsValid(write, w - write.dstArrayElement))
if(IsValid(m_pDriver->NULLDescriptorsAllowed(), write, w - write.dstArrayElement))
{
write.descriptorCount++;
}
+3 -3
View File
@@ -793,8 +793,8 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
dstInline++;
}
// quick check for slots that were completely uninitialised and so don't have valid data
else if(descriptorCount == 1 && src->texelBufferView == ResourceId() &&
src->imageInfo.sampler == ResourceId() &&
else if(!NULLDescriptorsAllowed() && descriptorCount == 1 &&
src->texelBufferView == ResourceId() && src->imageInfo.sampler == ResourceId() &&
src->imageInfo.imageView == ResourceId() && src->bufferInfo.buffer == ResourceId())
{
// do nothing - don't increment bind so that the same write descriptor is used next time.
@@ -900,7 +900,7 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
// is this array element in the write valid? Note that below when we encounter an
// invalid write, the next one starts from a later point in the array, so we need to
// check relative to the dstArrayElement
if(IsValid(writes[bind], d - writes[bind].dstArrayElement))
if(IsValid(NULLDescriptorsAllowed(), writes[bind], d - writes[bind].dstArrayElement))
{
// if this descriptor is valid, just increment the number of descriptors. The data
// and dstArrayElement is pointing to the start of the valid range
+4 -2
View File
@@ -267,6 +267,10 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
VkPhysicalDeviceProtectedMemoryProperties); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR, \
VkPhysicalDevicePushDescriptorPropertiesKHR); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT, \
VkPhysicalDeviceRobustness2FeaturesEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT, \
VkPhysicalDeviceRobustness2PropertiesEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT, \
VkPhysicalDeviceSampleLocationsPropertiesEXT); \
COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, \
@@ -637,8 +641,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: \
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV: \
+3 -4
View File
@@ -1671,11 +1671,9 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
offs += drawcall->vertexOffset * vi->pVertexBindingDescriptions[vb].stride;
}
origVBs.push_back(bytebuf());
if(state.vbuffers[binding].buf != ResourceId())
{
origVBs.push_back(bytebuf());
GetBufferData(state.vbuffers[binding].buf, offs, len, origVBs.back());
}
}
for(uint32_t i = 0; i < vi->vertexAttributeDescriptionCount; i++)
@@ -1712,7 +1710,8 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
}
}
RDCASSERT(origVBEnd);
if(origVBBegin == NULL)
continue;
// in some limited cases, provided we added the UNIFORM_TEXEL_BUFFER usage bit, we could use
// the original buffers here as-is and read out of them. However it is likely that the offset
+43 -4
View File
@@ -615,6 +615,12 @@ SERIALISE_VK_HANDLES();
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT, \
VkPipelineCreationFeedbackCreateInfoEXT) \
\
/* VK_EXT_robustness2 */ \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT, \
VkPhysicalDeviceRobustness2FeaturesEXT) \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT, \
VkPhysicalDeviceRobustness2PropertiesEXT) \
\
/* VK_EXT_sampler_filter_minmax */ \
PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, \
VkPhysicalDeviceSamplerFilterMinmaxProperties) \
@@ -1069,10 +1075,6 @@ SERIALISE_VK_HANDLES();
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT) \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT) \
\
/* VK_EXT_robustness2 */ \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT) \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT) \
\
/* VK_EXT_texture_compression_astc_hdr */ \
PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT) \
\
@@ -5659,6 +5661,41 @@ void Deserialise(const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT &e
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPhysicalDeviceRobustness2FeaturesEXT &el)
{
RDCASSERT(ser.IsReading() ||
el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(robustBufferAccess2);
SERIALISE_MEMBER(robustImageAccess2);
SERIALISE_MEMBER(nullDescriptor);
}
template <>
void Deserialise(const VkPhysicalDeviceRobustness2FeaturesEXT &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPhysicalDeviceRobustness2PropertiesEXT &el)
{
RDCASSERT(ser.IsReading() ||
el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER(robustStorageBufferAccessSizeAlignment);
SERIALISE_MEMBER(robustUniformBufferAccessSizeAlignment);
}
template <>
void Deserialise(const VkPhysicalDeviceRobustness2PropertiesEXT &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPhysicalDeviceTransformFeedbackFeaturesEXT &el)
{
@@ -8458,6 +8495,8 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProperties2);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryFeatures);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryProperties);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDevicePushDescriptorPropertiesKHR);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceRobustness2FeaturesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceRobustness2PropertiesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceSampleLocationsPropertiesEXT);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceSamplerFilterMinmaxProperties);
INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceSamplerYcbcrConversionFeatures);
+71 -62
View File
@@ -1382,8 +1382,11 @@ private:
m_ResourcesDirty = false;
}
m_pDriver->GetDebugManager()->GetBufferData(GetResID(bufData.buffer), bufData.offset,
bufData.range, data);
if(bufData.buffer != VK_NULL_HANDLE)
{
m_pDriver->GetDebugManager()->GetBufferData(GetResID(bufData.buffer), bufData.offset,
bufData.range, data);
}
}
}
}
@@ -1411,54 +1414,57 @@ private:
m_ResourcesDirty = false;
}
const VulkanCreationInfo::ImageView &viewProps =
m_Creation.m_ImageView[GetResID(imgData.imageView)];
const VulkanCreationInfo::Image &imageProps = m_Creation.m_Image[viewProps.image];
uint32_t mip = viewProps.range.baseMipLevel;
data.width = RDCMAX(1U, imageProps.extent.width >> mip);
data.height = RDCMAX(1U, imageProps.extent.height >> mip);
if(imageProps.type == VK_IMAGE_TYPE_3D)
if(imgData.imageView != VK_NULL_HANDLE)
{
data.depth = RDCMAX(1U, imageProps.extent.depth >> mip);
}
else
{
data.depth = viewProps.range.layerCount;
if(data.depth == VK_REMAINING_ARRAY_LAYERS)
data.depth = imageProps.arrayLayers - viewProps.range.baseArrayLayer;
}
const VulkanCreationInfo::ImageView &viewProps =
m_Creation.m_ImageView[GetResID(imgData.imageView)];
const VulkanCreationInfo::Image &imageProps = m_Creation.m_Image[viewProps.image];
data.texelSize = GetByteSize(1, 1, 1, imageProps.format, 0);
data.rowPitch = GetByteSize(data.width, 1, 1, imageProps.format, 0);
data.slicePitch = GetByteSize(data.width, data.height, 1, imageProps.format, 0);
data.samplePitch = GetByteSize(data.width, data.height, data.depth, imageProps.format, 0);
uint32_t mip = viewProps.range.baseMipLevel;
const uint32_t numSlices = imageProps.type == VK_IMAGE_TYPE_3D ? 1 : data.depth;
const uint32_t numSamples = (uint32_t)imageProps.samples;
data.bytes.reserve(data.samplePitch * numSamples);
// defaults are fine - no interpretation. Maybe we could use the view's typecast?
const GetTextureDataParams params = GetTextureDataParams();
for(uint32_t sample = 0; sample < numSamples; sample++)
{
for(uint32_t slice = 0; slice < numSlices; slice++)
data.width = RDCMAX(1U, imageProps.extent.width >> mip);
data.height = RDCMAX(1U, imageProps.extent.height >> mip);
if(imageProps.type == VK_IMAGE_TYPE_3D)
{
bytebuf subBytes;
m_pDriver->GetReplay()->GetTextureData(viewProps.image, Subresource(mip, slice, sample),
params, subBytes);
data.depth = RDCMAX(1U, imageProps.extent.depth >> mip);
}
else
{
data.depth = viewProps.range.layerCount;
if(data.depth == VK_REMAINING_ARRAY_LAYERS)
data.depth = imageProps.arrayLayers - viewProps.range.baseArrayLayer;
}
// fast path, swap into output if there's only one slice and one sample (common case)
if(numSlices == 1 && numSamples == 1)
data.texelSize = GetByteSize(1, 1, 1, imageProps.format, 0);
data.rowPitch = GetByteSize(data.width, 1, 1, imageProps.format, 0);
data.slicePitch = GetByteSize(data.width, data.height, 1, imageProps.format, 0);
data.samplePitch = GetByteSize(data.width, data.height, data.depth, imageProps.format, 0);
const uint32_t numSlices = imageProps.type == VK_IMAGE_TYPE_3D ? 1 : data.depth;
const uint32_t numSamples = (uint32_t)imageProps.samples;
data.bytes.reserve(data.samplePitch * numSamples);
// defaults are fine - no interpretation. Maybe we could use the view's typecast?
const GetTextureDataParams params = GetTextureDataParams();
for(uint32_t sample = 0; sample < numSamples; sample++)
{
for(uint32_t slice = 0; slice < numSlices; slice++)
{
subBytes.swap(data.bytes);
}
else
{
data.bytes.append(subBytes);
bytebuf subBytes;
m_pDriver->GetReplay()->GetTextureData(
viewProps.image, Subresource(mip, slice, sample), params, subBytes);
// fast path, swap into output if there's only one slice and one sample (common case)
if(numSlices == 1 && numSamples == 1)
{
subBytes.swap(data.bytes);
}
else
{
data.bytes.append(subBytes);
}
}
}
}
@@ -3444,28 +3450,31 @@ ShaderDebugTrace *VulkanReplay::DebugVertex(uint32_t eventId, uint32_t vertid, u
{
const VulkanRenderState::VertBuffer &vb = state.vbuffers[bind.vbufferBinding];
uint32_t vertexOffset = 0;
if(bind.perInstance)
if(vb.buf != ResourceId())
{
if(bind.instanceDivisor == 0)
vertexOffset = instOffset * bind.bytestride;
uint32_t vertexOffset = 0;
if(bind.perInstance)
{
if(bind.instanceDivisor == 0)
vertexOffset = instOffset * bind.bytestride;
else
vertexOffset = (instOffset + (instid / bind.instanceDivisor)) * bind.bytestride;
}
else
vertexOffset = (instOffset + (instid / bind.instanceDivisor)) * bind.bytestride;
}
else
{
vertexOffset = (idx + vertOffset) * bind.bytestride;
}
{
vertexOffset = (idx + vertOffset) * bind.bytestride;
}
if(Vulkan_Debug_ShaderDebugLogging())
{
RDCLOG("Fetching from %s at %llu offset %zu bytes", ToStr(vb.buf).c_str(),
vb.offs + attr.byteoffset + vertexOffset, size);
}
if(Vulkan_Debug_ShaderDebugLogging())
{
RDCLOG("Fetching from %s at %llu offset %zu bytes", ToStr(vb.buf).c_str(),
vb.offs + attr.byteoffset + vertexOffset, size);
}
GetDebugManager()->GetBufferData(vb.buf, vb.offs + attr.byteoffset + vertexOffset, size,
data);
GetDebugManager()->GetBufferData(vb.buf, vb.offs + attr.byteoffset + vertexOffset, size,
data);
}
}
else if(Vulkan_Debug_ShaderDebugLogging())
{
+9 -1
View File
@@ -233,7 +233,15 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd,
for(size_t i = 0; i < vbuffers.size(); i++)
{
if(vbuffers[i].buf == ResourceId())
{
if(vk->NULLDescriptorsAllowed())
{
VkBuffer empty = VK_NULL_HANDLE;
ObjDisp(cmd)->CmdBindVertexBuffers(Unwrap(cmd), (uint32_t)i, 1, &empty, &vbuffers[i].offs);
}
continue;
}
ObjDisp(cmd)->CmdBindVertexBuffers(
Unwrap(cmd), (uint32_t)i, 1,
@@ -485,7 +493,7 @@ void VulkanRenderState::BindDescriptorSet(WrappedVulkan *vk, const DescSetLayout
for(uint32_t w = 0; w < bind.descriptorCount; w++)
{
// if this push is valid, we increment the descriptor count and continue
if(IsValid(push, w - push.dstArrayElement))
if(IsValid(vk->NULLDescriptorsAllowed(), push, w - push.dstArrayElement))
{
push.descriptorCount++;
}
@@ -2648,8 +2648,10 @@ void WrappedVulkan::vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32
record->AddChunk(scope.Get());
for(uint32_t i = 0; i < bindingCount; i++)
{
record->MarkBufferFrameReferenced(GetRecord(pBuffers[i]), pOffsets[i], VK_WHOLE_SIZE,
eFrameRef_Read);
// binding NULL is legal with robustness2
if(pBuffers[i])
record->MarkBufferFrameReferenced(GetRecord(pBuffers[i]), pOffsets[i], VK_WHOLE_SIZE,
eFrameRef_Read);
}
}
}
@@ -624,7 +624,9 @@ void WrappedVulkan::ReplayDescriptorSetWrite(VkDevice device, const VkWriteDescr
valid &= (writeDesc.pImageInfo[i].sampler != VK_NULL_HANDLE) ||
(layoutBinding->immutableSampler &&
layoutBinding->immutableSampler[curIdx] != ResourceId());
valid &= (writeDesc.pImageInfo[i].imageView != VK_NULL_HANDLE);
if(!NULLDescriptorsAllowed())
valid &= (writeDesc.pImageInfo[i].imageView != VK_NULL_HANDLE);
}
break;
}
@@ -632,14 +634,14 @@ void WrappedVulkan::ReplayDescriptorSetWrite(VkDevice device, const VkWriteDescr
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
{
for(uint32_t i = 0; i < writeDesc.descriptorCount; i++)
for(uint32_t i = 0; !NULLDescriptorsAllowed() && i < writeDesc.descriptorCount; i++)
valid &= (writeDesc.pImageInfo[i].imageView != VK_NULL_HANDLE);
break;
}
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
{
for(uint32_t i = 0; i < writeDesc.descriptorCount; i++)
for(uint32_t i = 0; !NULLDescriptorsAllowed() && i < writeDesc.descriptorCount; i++)
valid &= (writeDesc.pTexelBufferView[i] != VK_NULL_HANDLE);
break;
}
@@ -648,7 +650,7 @@ void WrappedVulkan::ReplayDescriptorSetWrite(VkDevice device, const VkWriteDescr
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
{
for(uint32_t i = 0; i < writeDesc.descriptorCount; i++)
for(uint32_t i = 0; !NULLDescriptorsAllowed() && i < writeDesc.descriptorCount; i++)
valid &= (writeDesc.pBufferInfo[i].buffer != VK_NULL_HANDLE);
break;
}
@@ -2539,6 +2539,17 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
CHECK_PHYS_EXT_FEATURE(customBorderColorWithoutFormat);
}
END_PHYS_EXT_CHECK();
BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceRobustness2FeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT);
{
CHECK_PHYS_EXT_FEATURE(robustBufferAccess2);
CHECK_PHYS_EXT_FEATURE(robustImageAccess2);
CHECK_PHYS_EXT_FEATURE(nullDescriptor);
m_NULLDescriptorsAllowed |= (ext->nullDescriptor != VK_FALSE);
}
END_PHYS_EXT_CHECK();
}
if(availFeatures.depthClamp)