Fix handling of 64-bit integer vertex attributes in mesh output fetch

This commit is contained in:
baldurk
2022-06-20 16:47:50 +01:00
parent 183f50bfb7
commit 687c11ba68
6 changed files with 153 additions and 54 deletions
+39 -23
View File
@@ -589,10 +589,13 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
io.variable = patchData.inputs[i].ID;
rdcspv::Scalar scalarType = rdcspv::scalar(refl.inputSignature[i].varType);
VarType vType = refl.inputSignature[i].varType;
// doubles are loaded as uvec4 and then packed in pairs, so we need to declare vec4ID as uvec4
if(refl.inputSignature[i].varType == VarType::Double)
rdcspv::Scalar scalarType = rdcspv::scalar(vType);
// 64-bit values are loaded as uvec4 and then packed in pairs, so we need to declare vec4ID as
// uvec4
if(vType == VarType::Double || vType == VarType::ULong || vType == VarType::SLong)
{
io.fetchVec4Type = io.vec4Type =
editor.DeclareType(rdcspv::Vector(rdcspv::scalar<uint32_t>(), 4));
@@ -602,7 +605,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
io.vec4Type = editor.DeclareType(rdcspv::Vector(scalarType, 4));
// if the underlying scalar is actually
switch(refl.inputSignature[i].varType)
switch(vType)
{
case VarType::Half:
io.fetchVec4Type = editor.DeclareType(rdcspv::Vector(rdcspv::scalar<float>(), 4));
@@ -1100,6 +1103,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
for(size_t i = 0; i < refl.inputSignature.size(); i++)
{
VarType vType = refl.inputSignature[i].varType;
ShaderBuiltin builtin = refl.inputSignature[i].systemValue;
if(builtin != ShaderBuiltin::Undefined)
{
@@ -1159,7 +1164,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
if(valueID)
{
if(VarTypeCompType(refl.inputSignature[i].varType) == compType)
if(VarTypeCompType(vType) == compType)
{
ops.add(rdcspv::OpStore(ins[i].variable, valueID));
}
@@ -1218,9 +1223,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
}
}
if(refl.inputSignature[i].varType == VarType::Double)
if(vType == VarType::Double || vType == VarType::ULong || vType == VarType::SLong)
{
// since doubles are packed into two uints, we need to multiply the index by two
// since 64-bit vlaues are packed into two uints, we need to multiply the index by two
idx = ops.add(rdcspv::OpIMul(u32Type, editor.MakeId(), idx,
editor.AddConstantImmediate<uint32_t>(2)));
}
@@ -1255,9 +1260,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
// size (typically ushort or half) then convert here
if(ins[i].fetchVec4Type != ins[i].vec4Type)
{
if(VarTypeCompType(refl.inputSignature[i].varType) == CompType::Float)
if(VarTypeCompType(vType) == CompType::Float)
result = ops.add(rdcspv::OpFConvert(ins[i].vec4Type, editor.MakeId(), result));
else if(VarTypeCompType(refl.inputSignature[i].varType) == CompType::UInt)
else if(VarTypeCompType(vType) == CompType::UInt)
result = ops.add(rdcspv::OpUConvert(ins[i].vec4Type, editor.MakeId(), result));
else
result = ops.add(rdcspv::OpSConvert(ins[i].vec4Type, editor.MakeId(), result));
@@ -1265,9 +1270,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
uint32_t comp = Bits::CountTrailingZeroes(uint32_t(refl.inputSignature[i].regChannelMask));
if(refl.inputSignature[i].varType == VarType::Double)
if(vType == VarType::Double || vType == VarType::ULong || vType == VarType::SLong)
{
// since doubles are packed into two uints, we now need to fetch more data and do
// since 64-bit values are packed into two uints, we now need to fetch more data and do
// packing. We can fetch the data unconditionally since it's harmless to read out of the
// bounds of the buffer
@@ -1304,10 +1309,21 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl,
editor.SetName(packed, StringFormat::Fmt("packed_%c", swizzle[c]));
// double comp = PackDouble2x32(packed);
comps[c] = ops.add(rdcspv::OpGLSL450(editor.DeclareType(rdcspv::scalar<double>()),
editor.MakeId(), glsl450,
rdcspv::GLSLstd450::PackDouble2x32, {packed}));
if(vType == VarType::Double)
{
// double comp = PackDouble2x32(packed);
comps[c] = ops.add(rdcspv::OpGLSL450(editor.DeclareType(rdcspv::scalar<double>()),
editor.MakeId(), glsl450,
rdcspv::GLSLstd450::PackDouble2x32, {packed}));
}
else
{
rdcspv::Scalar s = (vType == VarType::ULong) ? rdcspv::scalar<uint64_t>()
: rdcspv::scalar<int64_t>();
// [u]int64 comp = Bitcast(packed);
comps[c] = ops.add(rdcspv::OpBitcast(editor.DeclareType(s), editor.MakeId(), packed));
}
}
// if there's only one component it's ready, otherwise construct a vector
@@ -2133,7 +2149,7 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
VkFormat origFormat = attrDesc.format;
VkFormat expandedFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
if(IsDoubleFormat(origFormat))
if(Is64BitFormat(origFormat))
expandedFormat = VK_FORMAT_R32G32B32A32_UINT;
else if(IsUIntFormat(origFormat))
expandedFormat = VK_FORMAT_R32G32B32A32_UINT;
@@ -2143,8 +2159,8 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
uint32_t origElemSize = GetByteSize(1, 1, 1, origFormat, 0);
uint32_t elemSize = GetByteSize(1, 1, 1, expandedFormat, 0);
// doubles are packed as uvec2
if(IsDoubleFormat(origFormat))
// 64-bit values are packed as uvec2
if(Is64BitFormat(origFormat))
elemSize *= 2;
// used for interpreting the original data, if we're upcasting
@@ -2253,14 +2269,14 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
uint32_t zero = 0;
// upcasting path
if(IsDoubleFormat(origFormat))
if(Is64BitFormat(origFormat))
{
while(src < origVBEnd && dst < dstEnd)
{
// the double is already in "packed uvec2" order, with least significant 32-bits
// first, so we can copy directly
memcpy(dst, src, sizeof(double) * fmt.compCount);
dst += sizeof(double) * fmt.compCount;
// the 64-bit value (especially for doubles) is already in "packed uvec2" order,
// with least significant 32-bits first, so we can copy directly
memcpy(dst, src, sizeof(uint64_t) * fmt.compCount);
dst += sizeof(uint64_t) * fmt.compCount;
// fill up to *8* zeros not 4, since we're filling two for every component
for(uint8_t c = fmt.compCount * 2; c < 8; c++)
+1 -1
View File
@@ -344,7 +344,7 @@ bool IsSRGBFormat(VkFormat f)
return false;
}
bool IsDoubleFormat(VkFormat f)
bool Is64BitFormat(VkFormat f)
{
switch(f)
{
+1 -1
View File
@@ -2378,7 +2378,7 @@ bool IsStencilFormat(VkFormat f);
bool IsStencilOnlyFormat(VkFormat f);
bool IsSRGBFormat(VkFormat f);
bool IsUIntFormat(VkFormat f);
bool IsDoubleFormat(VkFormat f);
bool Is64BitFormat(VkFormat f);
bool IsSIntFormat(VkFormat f);
bool IsYUVFormat(VkFormat f);
VkImageAspectFlags FormatImageAspects(VkFormat f);
+97 -25
View File
@@ -35,11 +35,13 @@ RD_TEST(VK_Vertex_Attr_Zoo, VulkanGraphicsTest)
{
int16_t i16[4];
uint16_t u16[4];
double df[2];
double df[3];
float arr0[2];
float arr1[2];
float mat0[2];
float mat1[2];
uint64_t lf[3];
int64_t slf[3];
};
std::string vertex = R"EOSHADER(
@@ -50,10 +52,14 @@ layout(location = 3) in uvec2 InUInt;
layout(location = 3, component = 2) in uint InUInt1;
layout(location = 3, component = 3) in uint InUInt2;
#if DOUBLES
layout(location = 4) in dvec2 InDouble;
layout(location = 4) in dvec3 InDouble;
#endif
layout(location = 6) in vec2 InArray[2];
layout(location = 8) in mat2x2 InMatrix;
#if LONGS
layout(location = 10) in u64vec3 InULong;
layout(location = 12) in i64vec3 InSLong;
#endif
layout(location = 5) in vec2 InArray[2];
layout(location = 7) in mat2x2 InMatrix;
layout(location = 0) out vec4 OutSNorm;
layout(location = 1) out vec4 OutUNorm;
@@ -62,10 +68,14 @@ layout(location = 3) flat out uvec2 OutUInt;
layout(location = 3, component = 2) flat out uint OutUInt1;
layout(location = 3, component = 3) flat out uint OutUInt2;
#if DOUBLES
layout(location = 4) out dvec2 OutDouble;
layout(location = 4) out dvec3 OutDouble;
#endif
layout(location = 6) out vec2 OutArray[2];
layout(location = 8) out mat2x2 OutMatrix;
#if LONGS
layout(location = 10) out u64vec3 OutULong;
layout(location = 12) out i64vec3 OutSLong;
#endif
layout(location = 5) out vec2 OutArray[2];
layout(location = 7) out mat2x2 OutMatrix;
void main()
{
@@ -85,6 +95,10 @@ void main()
OutUNorm = InUNorm;
OutArray = InArray;
OutMatrix = InMatrix;
#if LONGS
OutULong = InULong;
OutSLong = InSLong;
#endif
}
)EOSHADER";
@@ -97,10 +111,14 @@ layout(location = 3) flat in uvec2 InUInt;
layout(location = 3, component = 2) flat in uint InUInt1;
layout(location = 3, component = 3) flat in uint InUInt2;
#if DOUBLES
layout(location = 4) flat in dvec2 InDouble;
layout(location = 4) flat in dvec3 InDouble;
#endif
layout(location = 6) in vec2 InArray[2];
layout(location = 8) in mat2x2 InMatrix;
#if LONGS
layout(location = 10) flat in u64vec3 InULong;
layout(location = 12) flat in i64vec3 InSLong;
#endif
layout(location = 5) in vec2 InArray[2];
layout(location = 7) in mat2x2 InMatrix;
layout(location = 0, index = 0) out vec4 Color;
@@ -131,6 +149,13 @@ void main()
if(clamp(InDouble, -10.0, 10.0) != InDouble)
Color = vec4(0.5f, 0, 0, 1);
#endif
#if LONGS
if(InULong.x < 10000000000UL || InULong.y < 10000000000UL || InULong.z < 10000000000UL)
Color = vec4(0.6f, 0, 0, 1);
if(InSLong.x > -10000000000UL || InSLong.y > -10000000000UL || InSLong.z > -10000000000UL)
Color = vec4(0.7f, 0, 0, 1);
#endif
}
)EOSHADER";
@@ -146,10 +171,14 @@ layout(location = 3) flat in uvec2 InUInt[3];
layout(location = 3, component = 2) flat in uint InUInt1[3];
layout(location = 3, component = 3) flat in uint InUInt2[3];
#if DOUBLES
layout(location = 4) in dvec2 InDouble[3];
layout(location = 4) in dvec3 InDouble[3];
#endif
layout(location = 6) in vec2 InArray[3][2];
layout(location = 8) in mat2x2 InMatrix[3];
#if LONGS
layout(location = 10) in u64vec3 InULong[3];
layout(location = 12) in i64vec3 InSLong[3];
#endif
layout(location = 5) in vec2 InArray[3][2];
layout(location = 7) in mat2x2 InMatrix[3];
layout(location = 0) out vec4 OutSNorm;
layout(location = 1) out vec4 OutUNorm;
@@ -158,10 +187,14 @@ layout(location = 3) flat out uvec2 OutUInt;
layout(location = 3, component = 2) flat out uint OutUInt1;
layout(location = 3, component = 3) flat out uint OutUInt2;
#if DOUBLES
layout(location = 4) out dvec2 OutDouble;
layout(location = 4) out dvec3 OutDouble;
#endif
layout(location = 6) out vec2 OutArray[2];
layout(location = 8) out mat2x2 OutMatrix;
#if LONGS
layout(location = 10) out u64vec3 OutULong;
layout(location = 12) out i64vec3 OutSLong;
#endif
layout(location = 5) out vec2 OutArray[2];
layout(location = 7) out mat2x2 OutMatrix;
void main()
{
@@ -180,6 +213,10 @@ void main()
OutUNorm = InUNorm[i];
OutArray = InArray[i];
OutMatrix = InMatrix[i];
#if LONGS
OutULong = InULong[i];
OutSLong = InSLong[i];
#endif
EmitVertex();
}
@@ -297,6 +334,8 @@ void main()
// radv doesn't support doubles :(
optFeatures.shaderFloat64 = VK_TRUE;
optFeatures.shaderInt64 = VK_TRUE;
VulkanGraphicsTest::Prepare(argc, argv);
if(!Avail.empty())
@@ -322,10 +361,20 @@ void main()
return 3;
VkFormatProperties props = {};
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_R64G64_SFLOAT, &props);
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_R64G64B64_SFLOAT, &props);
const bool doubles = (props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0;
props = {};
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_R64G64B64_SINT, &props);
const bool slongs = (props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0;
props = {};
vkGetPhysicalDeviceFormatProperties(phys, VK_FORMAT_R64G64B64_UINT, &props);
const bool ulongs = (props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0;
const bool longs = slongs && ulongs;
VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo());
vkh::GraphicsPipelineCreateInfo pipeCreateInfo;
@@ -340,18 +389,32 @@ void main()
vkh::vertexAttrFormatted(1, 0, vertin, u16, VK_FORMAT_R16G16B16A16_UNORM),
vkh::vertexAttrFormatted(2, 0, vertin, u16, VK_FORMAT_R16G16B16A16_USCALED),
vkh::vertexAttrFormatted(3, 0, vertin, u16, VK_FORMAT_R16G16B16A16_UINT),
vkh::vertexAttrFormatted(5, 0, vertin, arr0, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(6, 0, vertin, arr1, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(7, 0, vertin, mat0, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(8, 0, vertin, mat1, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(6, 0, vertin, arr0, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(7, 0, vertin, arr1, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(8, 0, vertin, mat0, VK_FORMAT_R32G32_SFLOAT),
vkh::vertexAttrFormatted(9, 0, vertin, mat1, VK_FORMAT_R32G32_SFLOAT),
};
std::string common = "#version 450 core\n\n";
if(longs)
{
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions.push_back(
vkh::vertexAttrFormatted(10, 0, vertin, lf, VK_FORMAT_R64G64B64_UINT));
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions.push_back(
vkh::vertexAttrFormatted(12, 0, vertin, slf, VK_FORMAT_R64G64B64_SINT));
common += "#extension GL_ARB_gpu_shader_int64 : require\n\n#define LONGS 1\n\n";
}
else
{
common += "#define LONGS 0\n\n";
}
if(doubles)
{
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions.push_back(
vkh::vertexAttrFormatted(4, 0, vertin, df, VK_FORMAT_R64G64_SFLOAT));
vkh::vertexAttrFormatted(4, 0, vertin, df, VK_FORMAT_R64G64B64_SFLOAT));
common += "#define DOUBLES 1\n\n";
}
@@ -381,29 +444,35 @@ void main()
{
{32767, -32768, 32767, -32767},
{12345, 6789, 1234, 567},
{9.8765432109, -5.6789012345},
{9.8765432109, -5.6789012345, 1.2345},
{1.0f, 2.0f},
{3.0f, 4.0f},
{7.0f, 8.0f},
{9.0f, 10.0f},
{10000012345, 10000006789, 10000001234},
{-10000012345, -10000006789, -10000001234},
},
{
{32766, -32766, 16000, -16000},
{56, 7890, 123, 4567},
{-7.89012345678, 6.54321098765},
{-7.89012345678, 6.54321098765, 1.2345},
{11.0f, 12.0f},
{13.0f, 14.0f},
{17.0f, 18.0f},
{19.0f, 20.0f},
{10000000056, 10000007890, 10000000123},
{-10000000056, -10000007890, -10000000123},
},
{
{5, -5, 0, 0},
{8765, 43210, 987, 65432},
{0.1234567890123, 4.5678901234},
{0.1234567890123, 4.5678901234, 1.2345},
{21.0f, 22.0f},
{23.0f, 24.0f},
{27.0f, 28.0f},
{29.0f, 30.0f},
{10000008765, 10000043210, 10000000987},
{-10000008765, -10000043210, -10000000987},
},
};
@@ -430,6 +499,9 @@ void main()
if(doubles)
setMarker(cmd, "DoublesEnabled");
if(longs)
setMarker(cmd, "LongsEnabled");
vkCmdBeginRenderPass(
cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
VK_SUBPASS_CONTENTS_INLINE);
+1 -1
View File
@@ -163,7 +163,7 @@ def get_postvs_attrs(controller: rd.ReplayController, mesh: rd.MeshFormat, data_
# Construct a resource format for this element
attr.mesh.format = rd.ResourceFormat()
attr.mesh.format.compByteWidth = 8 if sig.varType == rd.VarType.Double else 4
attr.mesh.format.compByteWidth = rd.VarTypeByteSize(sig.varType)
attr.mesh.format.compCount = sig.compCount
attr.mesh.format.compType = rd.VarTypeCompType(sig.varType)
attr.mesh.format.type = rd.ResourceFormatType.Regular
+14 -3
View File
@@ -21,11 +21,13 @@ class VK_Vertex_Attr_Zoo(rdtest.TestCase):
'UInt': [12345, 6789],
'UInt1': [1234],
'UInt2': [567],
'Double': [9.8765432109, -5.6789012345],
'Double': [9.8765432109, -5.6789012345, 1.2345],
'Array[0]': [1.0, 2.0],
'Array[1]': [3.0, 4.0],
'Matrix:col0': [7.0, 8.0],
'Matrix:col1': [9.0, 10.0],
'ULong': [10000012345, 10000006789, 10000001234],
'SLong': [-10000012345, -10000006789, -10000001234],
},
1: {
'SNorm': [32766.0/32767.0, -32766.0/32767.0, 16000.0/32767.0, -16000.0/32767.0],
@@ -34,11 +36,13 @@ class VK_Vertex_Attr_Zoo(rdtest.TestCase):
'UInt': [56, 7890],
'UInt1': [123],
'UInt2': [4567],
'Double': [-7.89012345678, 6.54321098765],
'Double': [-7.89012345678, 6.54321098765, 1.2345],
'Array[0]': [11.0, 12.0],
'Array[1]': [13.0, 14.0],
'Matrix:col0': [17.0, 18.0],
'Matrix:col1': [19.0, 20.0],
'ULong': [10000000056, 10000007890, 10000000123],
'SLong': [-10000000056, -10000007890, -10000000123],
},
2: {
'SNorm': [5.0/32767.0, -5.0/32767.0, 0.0, 0.0],
@@ -47,15 +51,18 @@ class VK_Vertex_Attr_Zoo(rdtest.TestCase):
'UInt': [8765, 43210],
'UInt1': [987],
'UInt2': [65432],
'Double': [0.1234567890123, 4.5678901234],
'Double': [0.1234567890123, 4.5678901234, 1.2345],
'Array[0]': [21.0, 22.0],
'Array[1]': [23.0, 24.0],
'Matrix:col0': [27.0, 28.0],
'Matrix:col1': [29.0, 30.0],
'ULong': [10000008765, 10000043210, 10000000987],
'SLong': [-10000008765, -10000043210, -10000000987],
},
}
doubles = self.find_action('DoublesEnabled') is not None
longs = self.find_action('LongsEnabled') is not None
# Copy the ref values and prepend 'In'
in_ref = {}
@@ -66,6 +73,8 @@ class VK_Vertex_Attr_Zoo(rdtest.TestCase):
continue
if not doubles and 'Double' in key:
continue
if not longs and 'Long' in key:
continue
in_ref[idx]['In' + key] = ref[idx][key]
in_ref[idx]['InUInt2'] = ref[idx]['UInt'] + ref[idx]['UInt1'] + ref[idx]['UInt2']
@@ -77,6 +86,8 @@ class VK_Vertex_Attr_Zoo(rdtest.TestCase):
for key in ref[idx]:
if not doubles and 'Double' in key:
continue
if not longs and 'Long' in key:
continue
out_ref[idx]['Out' + key] = ref[idx][key]
vsout_ref = copy.deepcopy(out_ref)